X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=common%2Fdlmalloc.c;h=41c7230424cc52578f64ff8f38cb0ce99d8b5167;hb=448e2b6327d0498d58506d6f4e4b2a325ab7cca0;hp=dade68faf749867dd9f4d3c2fc55383cec625ab5;hpb=a4b7485e2f311b1319b1b9cd59f5666536e24a28;p=platform%2Fkernel%2Fu-boot.git diff --git a/common/dlmalloc.c b/common/dlmalloc.c index dade68f..41c7230 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1,11 +1,24 @@ +// 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 +#include +#include -#if defined(CONFIG_UNIT_TEST) +#if CONFIG_IS_ENABLED(UNIT_TEST) #define DEBUG #endif #include #include +#include #ifdef DEBUG #if __STD_C @@ -280,6 +293,7 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Unused space (may be 0 bytes long) . . . . | + nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ `foot:' | Size of chunk, in bytes | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -574,10 +588,17 @@ static void malloc_bin_reloc(void) static inline void malloc_bin_reloc(void) {} #endif +#ifdef CONFIG_SYS_MALLOC_DEFAULT_TO_INIT +static void malloc_init(void); +#endif + 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; @@ -604,6 +625,10 @@ void mem_malloc_init(ulong start, ulong size) mem_malloc_end = start + size; mem_malloc_brk = start; +#ifdef CONFIG_SYS_MALLOC_DEFAULT_TO_INIT + malloc_init(); +#endif + debug("using memory %#lx-%#lx for malloc()\n", mem_malloc_start, mem_malloc_end); #ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT @@ -708,7 +733,36 @@ static unsigned int max_n_mmaps = 0; static unsigned long max_mmapped_mem = 0; #endif +#ifdef CONFIG_SYS_MALLOC_DEFAULT_TO_INIT +static void malloc_init(void) +{ + int i, j; + + debug("bins (av_ array) are at %p\n", (void *)av_); + + av_[0] = NULL; av_[1] = NULL; + for (i = 2, j = 2; i < NAV * 2 + 2; i += 2, j++) { + av_[i] = bin_at(j - 2); + av_[i + 1] = bin_at(j - 2); + + /* Just print the first few bins so that + * we can see there are alright. + */ + if (i < 10) + debug("av_[%d]=%lx av_[%d]=%lx\n", + i, (ulong)av_[i], + i + 1, (ulong)av_[i + 1]); + } + /* Init the static bookkeeping as well */ + sbrk_base = (char *)(-1); + max_sbrked_mem = 0; + max_total_mem = 0; +#ifdef DEBUG + memset((void *)¤t_mallinfo, 0, sizeof(struct mallinfo)); +#endif +} +#endif /* Debugging support @@ -1051,9 +1105,6 @@ static mchunkptr mremap_chunk(p, new_size) mchunkptr p; size_t new_size; #endif /* HAVE_MMAP */ - - - /* Extend the top-most chunk by obtaining memory from system. Main interface to sbrk (but see also malloc_trim). @@ -1259,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 */ @@ -1292,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); } @@ -1319,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); } } @@ -1342,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); } @@ -1351,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); } @@ -1406,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); } @@ -1414,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); } @@ -1462,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 @@ -1476,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); } @@ -1524,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 */ @@ -1547,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 */ { @@ -1735,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); } } @@ -1744,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; } } @@ -1773,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; } } @@ -1789,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; } @@ -1801,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; } @@ -1827,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); } @@ -1839,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 @@ -1996,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); } @@ -2009,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)); } @@ -2112,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; } } @@ -2394,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: