event: Correct dependencies on the EVENT framework
[platform/kernel/u-boot.git] / common / dlmalloc.c
index b29a7cf..41c7230 100644 (file)
@@ -1,5 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * This code is based on a version (aka dlmalloc) of malloc/free/realloc written
+ * by Doug Lea and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/-
+ *
+ * The original code is available at http://gee.cs.oswego.edu/pub/misc/
+ * as file malloc-2.6.6.c.
+ */
+
 #include <common.h>
 #include <log.h>
+#include <asm/global_data.h>
 
 #if CONFIG_IS_ENABLED(UNIT_TEST)
 #define DEBUG
@@ -7,6 +18,7 @@
 
 #include <malloc.h>
 #include <asm/io.h>
+#include <valgrind/memcheck.h>
 
 #ifdef DEBUG
 #if __STD_C
@@ -584,6 +596,9 @@ ulong mem_malloc_start = 0;
 ulong mem_malloc_end = 0;
 ulong mem_malloc_brk = 0;
 
+static bool malloc_testing;    /* enable test mode */
+static int malloc_max_allocs;  /* return NULL after this many calls to malloc() */
+
 void *sbrk(ptrdiff_t increment)
 {
        ulong old = mem_malloc_brk;
@@ -1295,6 +1310,11 @@ Void_t* mALLOc(bytes) size_t bytes;
                return malloc_simple(bytes);
 #endif
 
+  if (CONFIG_IS_ENABLED(UNIT_TEST) && malloc_testing) {
+    if (--malloc_max_allocs < 0)
+      return NULL;
+  }
+
   /* check if mem_malloc_init() was run */
   if ((mem_malloc_start == 0) && (mem_malloc_end == 0)) {
     /* not initialized yet */
@@ -1328,6 +1348,7 @@ Void_t* mALLOc(bytes) size_t bytes;
       unlink(victim, bck, fwd);
       set_inuse_bit_at_offset(victim, victim_size);
       check_malloced_chunk(victim, nb);
+      VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false);
       return chunk2mem(victim);
     }
 
@@ -1355,6 +1376,7 @@ Void_t* mALLOc(bytes) size_t bytes;
        unlink(victim, bck, fwd);
        set_inuse_bit_at_offset(victim, victim_size);
        check_malloced_chunk(victim, nb);
+        VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false);
        return chunk2mem(victim);
       }
     }
@@ -1378,6 +1400,7 @@ Void_t* mALLOc(bytes) size_t bytes;
       set_head(remainder, remainder_size | PREV_INUSE);
       set_foot(remainder, remainder_size);
       check_malloced_chunk(victim, nb);
+      VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false);
       return chunk2mem(victim);
     }
 
@@ -1387,6 +1410,7 @@ Void_t* mALLOc(bytes) size_t bytes;
     {
       set_inuse_bit_at_offset(victim, victim_size);
       check_malloced_chunk(victim, nb);
+      VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false);
       return chunk2mem(victim);
     }
 
@@ -1442,6 +1466,7 @@ Void_t* mALLOc(bytes) size_t bytes;
            set_head(remainder, remainder_size | PREV_INUSE);
            set_foot(remainder, remainder_size);
            check_malloced_chunk(victim, nb);
+           VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false);
            return chunk2mem(victim);
          }
 
@@ -1450,6 +1475,7 @@ Void_t* mALLOc(bytes) size_t bytes;
            set_inuse_bit_at_offset(victim, victim_size);
            unlink(victim, bck, fwd);
            check_malloced_chunk(victim, nb);
+           VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false);
            return chunk2mem(victim);
          }
 
@@ -1498,6 +1524,7 @@ Void_t* mALLOc(bytes) size_t bytes;
     /* If big and would otherwise need to extend, try to use mmap instead */
     if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
        (victim = mmap_chunk(nb)))
+      VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false);
       return chunk2mem(victim);
 #endif
 
@@ -1512,6 +1539,7 @@ Void_t* mALLOc(bytes) size_t bytes;
   top = chunk_at_offset(victim, nb);
   set_head(top, remainder_size | PREV_INUSE);
   check_malloced_chunk(victim, nb);
+  VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(victim), bytes, SIZE_SZ, false);
   return chunk2mem(victim);
 
 }
@@ -1560,8 +1588,10 @@ void fREe(mem) Void_t* mem;
 
 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
        /* free() is a no-op - all the memory will be freed on relocation */
-       if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT))
+       if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
+               VALGRIND_FREELIKE_BLOCK(mem, SIZE_SZ);
                return;
+       }
 #endif
 
   if (mem == NULL)                              /* free(0) has no effect */
@@ -1583,6 +1613,7 @@ void fREe(mem) Void_t* mem;
   sz = hd & ~PREV_INUSE;
   next = chunk_at_offset(p, sz);
   nextsz = chunksize(next);
+  VALGRIND_FREELIKE_BLOCK(mem, SIZE_SZ);
 
   if (next == top)                            /* merge with top */
   {
@@ -1771,6 +1802,8 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
          top = chunk_at_offset(oldp, nb);
          set_head(top, (newsize - nb) | PREV_INUSE);
          set_head_size(oldp, nb);
+         VALGRIND_RESIZEINPLACE_BLOCK(chunk2mem(oldp), 0, bytes, SIZE_SZ);
+         VALGRIND_MAKE_MEM_DEFINED(chunk2mem(oldp), bytes);
          return chunk2mem(oldp);
        }
       }
@@ -1780,6 +1813,8 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
       {
        unlink(next, bck, fwd);
        newsize  += nextsize;
+       VALGRIND_RESIZEINPLACE_BLOCK(chunk2mem(oldp), 0, bytes, SIZE_SZ);
+       VALGRIND_MAKE_MEM_DEFINED(chunk2mem(oldp), bytes);
        goto split;
       }
     }
@@ -1809,10 +1844,12 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
            newp = prev;
            newsize += prevsize + nextsize;
            newmem = chunk2mem(newp);
+           VALGRIND_MALLOCLIKE_BLOCK(newmem, bytes, SIZE_SZ, false);
            MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
            top = chunk_at_offset(newp, nb);
            set_head(top, (newsize - nb) | PREV_INUSE);
            set_head_size(newp, nb);
+           VALGRIND_FREELIKE_BLOCK(oldmem, SIZE_SZ);
            return newmem;
          }
        }
@@ -1825,6 +1862,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
          newp = prev;
          newsize += nextsize + prevsize;
          newmem = chunk2mem(newp);
+         VALGRIND_MALLOCLIKE_BLOCK(newmem, bytes, SIZE_SZ, false);
          MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
          goto split;
        }
@@ -1837,6 +1875,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
        newp = prev;
        newsize += prevsize;
        newmem = chunk2mem(newp);
+       VALGRIND_MALLOCLIKE_BLOCK(newmem, bytes, SIZE_SZ, false);
        MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
        goto split;
       }
@@ -1863,6 +1902,9 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
     MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
     fREe(oldmem);
     return newmem;
+  } else {
+    VALGRIND_RESIZEINPLACE_BLOCK(oldmem, 0, bytes, SIZE_SZ);
+    VALGRIND_MAKE_MEM_DEFINED(oldmem, bytes);
   }
 
 
@@ -1875,6 +1917,8 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
     set_head_size(newp, nb);
     set_head(remainder, remainder_size | PREV_INUSE);
     set_inuse_bit_at_offset(remainder, remainder_size);
+    VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(remainder), remainder_size, SIZE_SZ,
+                             false);
     fREe(chunk2mem(remainder)); /* let free() deal with it */
   }
   else
@@ -2032,6 +2076,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
     set_head_size(p, leadsize);
     fREe(chunk2mem(p));
     p = newp;
+    VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(p), bytes, SIZE_SZ, false);
 
     assert (newsize >= nb && (((unsigned long)(chunk2mem(p))) % alignment) == 0);
   }
@@ -2045,6 +2090,8 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
     remainder = chunk_at_offset(p, nb);
     set_head(remainder, remainder_size | PREV_INUSE);
     set_head_size(p, nb);
+    VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(remainder), remainder_size, SIZE_SZ,
+                             false);
     fREe(chunk2mem(remainder));
   }
 
@@ -2148,6 +2195,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size;
 #endif
 
     MALLOC_ZERO(mem, csz - SIZE_SZ);
+    VALGRIND_MAKE_MEM_DEFINED(mem, sz);
     return mem;
   }
 }
@@ -2430,6 +2478,17 @@ int initf_malloc(void)
        return 0;
 }
 
+void malloc_enable_testing(int max_allocs)
+{
+       malloc_testing = true;
+       malloc_max_allocs = max_allocs;
+}
+
+void malloc_disable_testing(void)
+{
+       malloc_testing = false;
+}
+
 /*
 
 History: