util/macros: Import ALIGN_POT from ralloc.c
[mesa.git] / src / util / ralloc.c
index d5cc16766b10b958cf1fb4cb00fc73d457fd8189..5d77f75ee85736857739359bebf547f83a9fe9e8 100644 (file)
 #include <string.h>
 #include <stdint.h>
 
-/* Android defines SIZE_MAX in limits.h, instead of the standard stdint.h */
-#ifdef ANDROID
-#include <limits.h>
-#endif
-
 /* Some versions of MinGW are missing _vscprintf's declaration, although they
  * still provide the symbol in the import library. */
 #ifdef __MINGW32__
@@ -51,7 +46,20 @@ _CRTIMP int _vscprintf(const char *format, va_list argptr);
 
 #define CANARY 0x5A1106
 
-struct ralloc_header
+/* Align the header's size so that ralloc() allocations will return with the
+ * same alignment as a libc malloc would have (8 on 32-bit GLIBC, 16 on
+ * 64-bit), avoiding performance penalities on x86 and alignment faults on
+ * ARM.
+ */
+struct
+#ifdef _MSC_VER
+ __declspec(align(8))
+#elif defined(__LP64__)
+ __attribute__((aligned(16)))
+#else
+ __attribute__((aligned(8)))
+#endif
+   ralloc_header
 {
 #ifdef DEBUG
    /* A canary value used to determine whether a pointer is ralloc'd. */
@@ -277,7 +285,7 @@ ralloc_steal(const void *new_ctx, void *ptr)
       return;
 
    info = get_header(ptr);
-   parent = get_header(new_ctx);
+   parent = new_ctx ? get_header(new_ctx) : NULL;
 
    unlink_block(info);
 
@@ -303,10 +311,12 @@ ralloc_adopt(const void *new_ctx, void *old_ctx)
    for (child = old_info->child; child->next != NULL; child = child->next) {
       child->parent = new_info;
    }
+   child->parent = new_info;
 
    /* Connect the two lists together; parent them to new_ctx; make old_ctx empty. */
    child->next = new_info->child;
-   child->parent = new_info;
+   if (child->next)
+      child->next->prev = child;
    new_info->child = old_info->child;
    old_info->child = NULL;
 }
@@ -392,12 +402,26 @@ ralloc_strcat(char **dest, const char *str)
 bool
 ralloc_strncat(char **dest, const char *str, size_t n)
 {
-   /* Clamp n to the string length */
-   size_t str_length = strlen(str);
-   if (str_length < n)
-      n = str_length;
+   return cat(dest, str, strnlen(str, n));
+}
 
-   return cat(dest, str, n);
+bool
+ralloc_str_append(char **dest, const char *str,
+                  size_t existing_length, size_t str_size)
+{
+   char *both;
+   assert(dest != NULL && *dest != NULL);
+
+   both = resize(*dest, existing_length + str_size + 1);
+   if (unlikely(both == NULL))
+      return false;
+
+   memcpy(both + existing_length, str, str_size);
+   both[existing_length + str_size] = '\0';
+
+   *dest = both;
+
+   return true;
 }
 
 char *
@@ -529,8 +553,6 @@ ralloc_vasprintf_rewrite_tail(char **str, size_t *start, const char *fmt,
  * other buffers.
  */
 
-#define ALIGN_POT(x, y) (((x) + (y) - 1) & ~((y) - 1))
-
 #define MIN_LINEAR_BUFSIZE 2048
 #define SUBALLOC_ALIGNMENT sizeof(uintptr_t)
 #define LMAGIC 0x87b9c7d3
@@ -606,7 +628,9 @@ linear_alloc_child(void *parent, unsigned size)
    linear_size_chunk *ptr;
    unsigned full_size;
 
+#ifdef DEBUG
    assert(first->magic == LMAGIC);
+#endif
    assert(!latest->next);
 
    size = ALIGN_POT(size, SUBALLOC_ALIGNMENT);
@@ -678,7 +702,9 @@ linear_free_parent(void *ptr)
       return;
 
    node = LINEAR_PARENT_TO_HEADER(ptr);
+#ifdef DEBUG
    assert(node->magic == LMAGIC);
+#endif
 
    while (node) {
       void *ptr = node;
@@ -697,7 +723,9 @@ ralloc_steal_linear_parent(void *new_ralloc_ctx, void *ptr)
       return;
 
    node = LINEAR_PARENT_TO_HEADER(ptr);
+#ifdef DEBUG
    assert(node->magic == LMAGIC);
+#endif
 
    while (node) {
       ralloc_steal(new_ralloc_ctx, node);
@@ -710,7 +738,9 @@ void *
 ralloc_parent_of_linear_parent(void *ptr)
 {
    linear_header *node = LINEAR_PARENT_TO_HEADER(ptr);
+#ifdef DEBUG
    assert(node->magic == LMAGIC);
+#endif
    return node->ralloc_parent;
 }