From 8c187839eec1f02b2ffcad2c81399c82c86c5be2 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 10 Dec 2009 13:09:02 +0100 Subject: Re-format the file Re-format the file with 'indent' and some manual corrections. Signed-off-by: Juergen Beisert --- common/dlmalloc.c | 1693 ++++++++++++++++++++++++----------------------------- 1 file changed, 781 insertions(+), 912 deletions(-) (limited to 'common/dlmalloc.c') diff --git a/common/dlmalloc.c b/common/dlmalloc.c index 6f7a9eba44..2f616370aa 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -277,7 +277,6 @@ */ - #ifndef DEFAULT_TOP_PAD #define DEFAULT_TOP_PAD (0) #endif @@ -310,7 +309,6 @@ */ - #ifndef DEFAULT_MMAP_THRESHOLD #define DEFAULT_MMAP_THRESHOLD (128 * 1024) #endif @@ -350,10 +348,8 @@ All together, these considerations should lead you to use mmap only for relatively large requests. - */ - #ifndef DEFAULT_MMAP_MAX #define DEFAULT_MMAP_MAX (0) #endif @@ -397,7 +393,6 @@ returns a unique pointer for malloc(0), so does realloc(p, 0). */ - /* #define REALLOC_ZERO_BYTES_FREES */ /* @@ -446,26 +441,26 @@ /* SVID2/XPG mallinfo structure */ -struct mallinfo { - int arena; /* total space allocated from system */ - int ordblks; /* number of non-inuse chunks */ - int smblks; /* unused -- always zero */ - int hblks; /* number of mmapped regions */ - int hblkhd; /* total space in mmapped regions */ - int usmblks; /* unused -- always zero */ - int fsmblks; /* unused -- always zero */ - int uordblks; /* total allocated space */ - int fordblks; /* total non-inuse space */ - int keepcost; /* top-most, releasable (via malloc_trim) space */ +struct mallinfo +{ + int arena; /* total space allocated from system */ + int ordblks; /* number of non-inuse chunks */ + int smblks; /* unused -- always zero */ + int hblks; /* number of mmapped regions */ + int hblkhd; /* total space in mmapped regions */ + int usmblks; /* unused -- always zero */ + int fsmblks; /* unused -- always zero */ + int uordblks; /* total allocated space */ + int fordblks; /* total non-inuse space */ + int keepcost; /* top-most, releasable (via malloc_trim) space */ }; /* SVID2/XPG mallopt options */ -#define M_MXFAST 1 /* UNUSED in this malloc */ -#define M_NLBLKS 2 /* UNUSED in this malloc */ -#define M_GRAIN 3 /* UNUSED in this malloc */ -#define M_KEEP 4 /* UNUSED in this malloc */ - +#define M_MXFAST 1 /* UNUSED in this malloc */ +#define M_NLBLKS 2 /* UNUSED in this malloc */ +#define M_GRAIN 3 /* UNUSED in this malloc */ +#define M_KEEP 4 /* UNUSED in this malloc */ /* mallopt options that actually do something */ @@ -482,22 +477,21 @@ struct mallinfo { bsd/gnu getpagesize.h */ -#define malloc_getpagesize 4096 +#define malloc_getpagesize 4096 /* Type declarations */ - struct malloc_chunk { - INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ - INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ - struct malloc_chunk* fd; /* double links -- used only if free. */ - struct malloc_chunk* bk; + INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ + INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ + struct malloc_chunk *fd; /* double links -- used only if free. */ + struct malloc_chunk *bk; }; -typedef struct malloc_chunk* mchunkptr; +typedef struct malloc_chunk *mchunkptr; /* @@ -646,14 +640,10 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ #define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0) - - - /* Physical chunk operations */ - /* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */ #define PREV_INUSE 0x1 @@ -666,7 +656,6 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ #define SIZE_BITS (PREV_INUSE|IS_MMAPPED) - /* Ptr to next physical malloc_chunk. */ #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) )) @@ -676,14 +665,10 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ #define prev_chunk(p)\ ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) )) - /* Treat space at ptr + offset as a chunk */ #define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) - - - /* Dealing with use bits */ @@ -720,9 +705,6 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ #define clear_inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE)) - - - /* Dealing with size fields */ @@ -743,10 +725,6 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ #define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s)) - - - - /* Bins @@ -781,9 +759,9 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -#define NAV 128 /* number of bins */ +#define NAV 128 /* number of bins */ -typedef struct malloc_chunk* mbinptr; +typedef struct malloc_chunk *mbinptr; /* access macros */ @@ -797,9 +775,8 @@ typedef struct malloc_chunk* mbinptr; indexing, maintain locality, and avoid some initialization tests. */ -#define top (bin_at(0)->fd) /* The topmost chunk */ -#define last_remainder (bin_at(1)) /* remainder from last split */ - +#define top (bin_at(0)->fd) /* The topmost chunk */ +#define last_remainder (bin_at(1)) /* remainder from last split */ /* Because top initially points to its own bin with initial @@ -815,23 +792,38 @@ typedef struct malloc_chunk* mbinptr; #define IAV(i) bin_at(i), bin_at(i) static mbinptr av_[NAV * 2 + 2] = { - 0, 0, - IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5), IAV(6), IAV(7), - IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13), IAV(14), IAV(15), - IAV(16), IAV(17), IAV(18), IAV(19), IAV(20), IAV(21), IAV(22), IAV(23), - IAV(24), IAV(25), IAV(26), IAV(27), IAV(28), IAV(29), IAV(30), IAV(31), - IAV(32), IAV(33), IAV(34), IAV(35), IAV(36), IAV(37), IAV(38), IAV(39), - IAV(40), IAV(41), IAV(42), IAV(43), IAV(44), IAV(45), IAV(46), IAV(47), - IAV(48), IAV(49), IAV(50), IAV(51), IAV(52), IAV(53), IAV(54), IAV(55), - IAV(56), IAV(57), IAV(58), IAV(59), IAV(60), IAV(61), IAV(62), IAV(63), - IAV(64), IAV(65), IAV(66), IAV(67), IAV(68), IAV(69), IAV(70), IAV(71), - IAV(72), IAV(73), IAV(74), IAV(75), IAV(76), IAV(77), IAV(78), IAV(79), - IAV(80), IAV(81), IAV(82), IAV(83), IAV(84), IAV(85), IAV(86), IAV(87), - IAV(88), IAV(89), IAV(90), IAV(91), IAV(92), IAV(93), IAV(94), IAV(95), - IAV(96), IAV(97), IAV(98), IAV(99), IAV(100), IAV(101), IAV(102), IAV(103), - IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111), - IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119), - IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127) + 0, 0, + IAV (0), IAV (1), IAV (2), IAV (3), IAV (4), IAV (5), IAV (6), IAV (7), + IAV (8), IAV (9), IAV (10), IAV (11), IAV (12), IAV (13), IAV (14), + IAV (15), + IAV (16), IAV (17), IAV (18), IAV (19), IAV (20), IAV (21), IAV (22), + IAV (23), + IAV (24), IAV (25), IAV (26), IAV (27), IAV (28), IAV (29), IAV (30), + IAV (31), + IAV (32), IAV (33), IAV (34), IAV (35), IAV (36), IAV (37), IAV (38), + IAV (39), + IAV (40), IAV (41), IAV (42), IAV (43), IAV (44), IAV (45), IAV (46), + IAV (47), + IAV (48), IAV (49), IAV (50), IAV (51), IAV (52), IAV (53), IAV (54), + IAV (55), + IAV (56), IAV (57), IAV (58), IAV (59), IAV (60), IAV (61), IAV (62), + IAV (63), + IAV (64), IAV (65), IAV (66), IAV (67), IAV (68), IAV (69), IAV (70), + IAV (71), + IAV (72), IAV (73), IAV (74), IAV (75), IAV (76), IAV (77), IAV (78), + IAV (79), + IAV (80), IAV (81), IAV (82), IAV (83), IAV (84), IAV (85), IAV (86), + IAV (87), + IAV (88), IAV (89), IAV (90), IAV (91), IAV (92), IAV (93), IAV (94), + IAV (95), + IAV (96), IAV (97), IAV (98), IAV (99), IAV (100), IAV (101), IAV (102), + IAV (103), + IAV (104), IAV (105), IAV (106), IAV (107), IAV (108), IAV (109), + IAV (110), IAV (111), + IAV (112), IAV (113), IAV (114), IAV (115), IAV (116), IAV (117), + IAV (118), IAV (119), + IAV (120), IAV (121), IAV (122), IAV (123), IAV (124), IAV (125), + IAV (126), IAV (127) }; /* field-extraction macros */ @@ -868,8 +860,6 @@ static mbinptr av_[NAV * 2 + 2] = { #define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH) - - /* To help compensate for the large number of bins, a one-level index structure is used for bin-by-bin searching. `binblocks' is a @@ -880,7 +870,7 @@ static mbinptr av_[NAV * 2 + 2] = { when all are noticed to be empty during traversal in malloc. */ -#define BINBLOCKWIDTH 4 /* bins per block */ +#define BINBLOCKWIDTH 4 /* bins per block */ #define binblocks (bin_at(0)->size) /* bitvector of nonempty blocks */ @@ -909,7 +899,7 @@ ulong mem_malloc_end(void) return malloc_end; } -void mem_malloc_init (void *start, void *end) +void mem_malloc_init(void *start, void *end) { malloc_start = (ulong)start; malloc_end = (ulong)end; @@ -921,21 +911,21 @@ static void *sbrk_no_zero(ptrdiff_t increment) ulong old = malloc_brk; ulong new = old + increment; - if ((new < malloc_start) || (new > malloc_end)) - return NULL; + if ((new < malloc_start) || (new > malloc_end)) + return NULL; malloc_brk = new; return (void *)old; } -static void *sbrk (ptrdiff_t increment) +static void *sbrk(ptrdiff_t increment) { void *old = sbrk_no_zero(increment); /* Only clear increment, if valid address was returned */ if (old != NULL) - memset (old, 0, increment); + memset(old, 0, increment); return old; } @@ -946,14 +936,14 @@ static void *sbrk (ptrdiff_t increment) /* variables holding tunable values */ #ifndef __U_BOOT__ -static unsigned long trim_threshold = DEFAULT_TRIM_THRESHOLD; -static unsigned int n_mmaps_max = DEFAULT_MMAP_MAX; -static unsigned long mmap_threshold = DEFAULT_MMAP_THRESHOLD; +static unsigned long trim_threshold = DEFAULT_TRIM_THRESHOLD; +static unsigned int n_mmaps_max = DEFAULT_MMAP_MAX; +static unsigned long mmap_threshold = DEFAULT_MMAP_THRESHOLD; #endif -static unsigned long top_pad = DEFAULT_TOP_PAD; +static unsigned long top_pad = DEFAULT_TOP_PAD; /* The first value returned from sbrk */ -static char* sbrk_base = (char*)(-1); +static char *sbrk_base = (char*)(-1); /* The maximum memory obtained from system via sbrk */ static unsigned long max_sbrked_mem; @@ -971,10 +961,6 @@ static struct mallinfo current_mallinfo; static unsigned long mmapped_mem; - - - - /* Macro-based internal utilities */ @@ -990,7 +976,6 @@ static unsigned long mmapped_mem; putting it ahead of others of same size. */ - #define frontlink(P, S, IDX, BK, FD) \ { \ if (S < MAX_SMALLBIN_SIZE) \ @@ -1020,7 +1005,6 @@ static unsigned long mmapped_mem; } \ } - /* take a chunk off a list */ #define unlink(P, BK, FD) \ @@ -1044,129 +1028,112 @@ static unsigned long mmapped_mem; #define clear_last_remainder \ (last_remainder->fd = last_remainder->bk = last_remainder) - - - - /* Routines dealing with mmap(). */ - - - - /* Extend the top-most chunk by obtaining memory from system. Main interface to sbrk (but see also malloc_trim). */ - static void malloc_extend_top(INTERNAL_SIZE_T nb) { - char* brk; /* return value from sbrk */ - INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */ - INTERNAL_SIZE_T correction; /* bytes for 2nd sbrk call */ - char* new_brk; /* return of 2nd sbrk call */ - INTERNAL_SIZE_T top_size; /* new size of top chunk */ - - mchunkptr old_top = top; /* Record state of old top */ - INTERNAL_SIZE_T old_top_size = chunksize(old_top); - char* old_end = (char*)(chunk_at_offset(old_top, old_top_size)); - - /* Pad request with top_pad plus minimal overhead */ - - INTERNAL_SIZE_T sbrk_size = nb + top_pad + MINSIZE; - unsigned long pagesz = malloc_getpagesize; - - /* If not the first time through, round to preserve page boundary */ - /* Otherwise, we need to correct to a page size below anyway. */ - /* (We also correct below if an intervening foreign sbrk call.) */ - - if (sbrk_base != (char*)(-1)) - sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1); - - brk = (char*)(sbrk (sbrk_size)); - - /* Fail if sbrk failed or if a foreign sbrk call killed our space */ - if (brk == (char*)(NULL) || - (brk < old_end && old_top != initial_top)) - return; - - sbrked_mem += sbrk_size; - - if (brk == old_end) /* can just add bytes to current top */ - { - top_size = sbrk_size + old_top_size; - set_head(top, top_size | PREV_INUSE); - } - else - { - if (sbrk_base == (char*)(-1)) /* First time through. Record base */ - sbrk_base = brk; - else /* Someone else called sbrk(). Count those bytes as sbrked_mem. */ - sbrked_mem += brk - (char*)old_end; - - /* Guarantee alignment of first new chunk made from this space */ - front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK; - if (front_misalign > 0) - { - correction = (MALLOC_ALIGNMENT) - front_misalign; - brk += correction; - } - else - correction = 0; - - /* Guarantee the next brk will be at a page boundary */ - - correction += ((((unsigned long)(brk + sbrk_size))+(pagesz-1)) & - ~(pagesz - 1)) - ((unsigned long)(brk + sbrk_size)); - - /* Allocate correction */ - new_brk = (char*)(sbrk (correction)); - if (new_brk == (char*)(NULL)) return; - - sbrked_mem += correction; - - top = (mchunkptr)brk; - top_size = new_brk - brk + correction; - set_head(top, top_size | PREV_INUSE); - - if (old_top != initial_top) - { - - /* There must have been an intervening foreign sbrk call. */ - /* A double fencepost is necessary to prevent consolidation */ - - /* If not enough space to do this, then user did something very wrong */ - if (old_top_size < MINSIZE) - { - set_head(top, PREV_INUSE); /* will force null return from malloc */ - return; - } - - /* Also keep size a multiple of MALLOC_ALIGNMENT */ - old_top_size = (old_top_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK; - set_head_size(old_top, old_top_size); - chunk_at_offset(old_top, old_top_size )->size = - SIZE_SZ|PREV_INUSE; - chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size = - SIZE_SZ|PREV_INUSE; - /* If possible, release the rest. */ - if (old_top_size >= MINSIZE) - free(chunk2mem(old_top)); - } - } - - if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem) - max_sbrked_mem = sbrked_mem; - if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem) - max_total_mem = mmapped_mem + sbrked_mem; -} - + char *brk; /* return value from sbrk */ + INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */ + INTERNAL_SIZE_T correction; /* bytes for 2nd sbrk call */ + char *new_brk; /* return of 2nd sbrk call */ + INTERNAL_SIZE_T top_size; /* new size of top chunk */ + + mchunkptr old_top = top; /* Record state of old top */ + INTERNAL_SIZE_T old_top_size = chunksize(old_top); + char *old_end = (char *) (chunk_at_offset(old_top, old_top_size)); + + /* Pad request with top_pad plus minimal overhead */ + + INTERNAL_SIZE_T sbrk_size = nb + top_pad + MINSIZE; + unsigned long pagesz = malloc_getpagesize; + + /* If not the first time through, round to preserve page boundary */ + /* Otherwise, we need to correct to a page size below anyway. */ + /* (We also correct below if an intervening foreign sbrk call.) */ + + if (sbrk_base != (char*)(-1)) + sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1); + + brk = (char*)(sbrk(sbrk_size)); + + /* Fail if sbrk failed or if a foreign sbrk call killed our space */ + if (brk == (char*)(NULL) || (brk < old_end && old_top != initial_top)) + return; + + sbrked_mem += sbrk_size; + + if (brk == old_end) { /* can just add bytes to current top */ + top_size = sbrk_size + old_top_size; + set_head (top, top_size | PREV_INUSE); + } else { + if (sbrk_base == (char*)(-1)) /* First time through. Record base */ + sbrk_base = brk; + else /* Someone else called sbrk(). Count those bytes as sbrked_mem. */ + sbrked_mem += brk - (char*)old_end; + + /* Guarantee alignment of first new chunk made from this space */ + front_misalign = + (unsigned long) chunk2mem(brk) & MALLOC_ALIGN_MASK; + if (front_misalign > 0) { + correction = (MALLOC_ALIGNMENT) - front_misalign; + brk += correction; + } else + correction = 0; + + /* Guarantee the next brk will be at a page boundary */ + + correction += ((((unsigned long) (brk + sbrk_size)) + + (pagesz - 1)) & ~(pagesz - 1)) - + ((unsigned long) (brk + sbrk_size)); + + /* Allocate correction */ + new_brk = (char*) (sbrk(correction)); + if (new_brk == (char*)(NULL)) + return; + + sbrked_mem += correction; + + top = (mchunkptr) brk; + top_size = new_brk - brk + correction; + set_head (top, top_size | PREV_INUSE); + + if (old_top != initial_top) { + + /* There must have been an intervening foreign sbrk call. */ + /* A double fencepost is necessary to prevent consolidation */ + + /* If not enough space to do this, then user did something very wrong */ + if (old_top_size < MINSIZE) { + set_head (top, PREV_INUSE); /* will force null return from malloc */ + return; + } + + /* Also keep size a multiple of MALLOC_ALIGNMENT */ + old_top_size = (old_top_size - + 3 * SIZE_SZ) & ~MALLOC_ALIGN_MASK; + set_head_size (old_top, old_top_size); + chunk_at_offset (old_top, old_top_size)->size = + SIZE_SZ | PREV_INUSE; + chunk_at_offset (old_top, old_top_size + SIZE_SZ)->size = + SIZE_SZ | PREV_INUSE; + /* If possible, release the rest. */ + if (old_top_size >= MINSIZE) + free(chunk2mem (old_top)); + } + } - + if ((unsigned long) sbrked_mem > (unsigned long) max_sbrked_mem) + max_sbrked_mem = sbrked_mem; + if ((unsigned long) (mmapped_mem + sbrked_mem) > (unsigned long) max_total_mem) + max_total_mem = mmapped_mem + sbrked_mem; +} /* Main public routines */ - /* Malloc Algorthim: @@ -1223,233 +1190,191 @@ static void malloc_extend_top(INTERNAL_SIZE_T nb) always true of any allocated chunk; i.e., that each allocated chunk borders either a previously allocated and still in-use chunk, or the base of its memory arena.) - */ - -void* malloc(size_t bytes) +void *malloc(size_t bytes) { - mchunkptr victim; /* inspected/selected chunk */ - INTERNAL_SIZE_T victim_size; /* its size */ - int idx; /* index for bin traversal */ - mbinptr bin; /* associated bin */ - mchunkptr remainder; /* remainder from a split */ - long remainder_size; /* its size */ - int remainder_index; /* its bin index */ - unsigned long block; /* block traverser bit */ - int startidx; /* first bin of a traversed block */ - mchunkptr fwd; /* misc temp for linking */ - mchunkptr bck; /* misc temp for linking */ - mbinptr q; /* misc temp */ - - INTERNAL_SIZE_T nb; - - if ((long)bytes < 0) return 0; - - nb = request2size(bytes); /* padded request size; */ - - /* Check for exact match in a bin */ - - if (is_small_request(nb)) /* Faster version for small requests */ - { - idx = smallbin_index(nb); - - /* No traversal or size check necessary for small bins. */ - - q = bin_at(idx); - victim = last(q); - - /* Also scan the next one, since it would have a remainder < MINSIZE */ - if (victim == q) - { - q = next_bin(q); - victim = last(q); - } - if (victim != q) - { - victim_size = chunksize(victim); - unlink(victim, bck, fwd); - set_inuse_bit_at_offset(victim, victim_size); - return chunk2mem(victim); - } - - idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */ - - } - else - { - idx = bin_index(nb); - bin = bin_at(idx); - - for (victim = last(bin); victim != bin; victim = victim->bk) - { - victim_size = chunksize(victim); - remainder_size = victim_size - nb; - - if (remainder_size >= (long)MINSIZE) /* too big */ - { - --idx; /* adjust to rescan below after checking last remainder */ - break; - } - - else if (remainder_size >= 0) /* exact fit */ - { - unlink(victim, bck, fwd); - set_inuse_bit_at_offset(victim, victim_size); - return chunk2mem(victim); - } - } - - ++idx; - - } - - /* Try to use the last split-off remainder */ - - if ( (victim = last_remainder->fd) != last_remainder) - { - victim_size = chunksize(victim); - remainder_size = victim_size - nb; - - if (remainder_size >= (long)MINSIZE) /* re-split */ - { - remainder = chunk_at_offset(victim, nb); - set_head(victim, nb | PREV_INUSE); - link_last_remainder(remainder); - set_head(remainder, remainder_size | PREV_INUSE); - set_foot(remainder, remainder_size); - return chunk2mem(victim); - } - - clear_last_remainder; - - if (remainder_size >= 0) /* exhaust */ - { - set_inuse_bit_at_offset(victim, victim_size); - return chunk2mem(victim); - } - - /* Else place in bin */ - - frontlink(victim, victim_size, remainder_index, bck, fwd); - } - - /* - If there are any possibly nonempty big-enough blocks, - search for best fitting chunk by scanning bins in blockwidth units. - */ - - if ( (block = idx2binblock(idx)) <= binblocks) - { - - /* Get to the first marked block */ - - if ( (block & binblocks) == 0) - { - /* force to an even block boundary */ - idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH; - block <<= 1; - while ((block & binblocks) == 0) - { - idx += BINBLOCKWIDTH; - block <<= 1; - } - } - - /* For each possibly nonempty block ... */ - for (;;) - { - startidx = idx; /* (track incomplete blocks) */ - q = bin = bin_at(idx); - - /* For each bin in this block ... */ - do - { - /* Find and use first big enough chunk ... */ - - for (victim = last(bin); victim != bin; victim = victim->bk) - { - victim_size = chunksize(victim); - remainder_size = victim_size - nb; - - if (remainder_size >= (long)MINSIZE) /* split */ - { - remainder = chunk_at_offset(victim, nb); - set_head(victim, nb | PREV_INUSE); - unlink(victim, bck, fwd); - link_last_remainder(remainder); - set_head(remainder, remainder_size | PREV_INUSE); - set_foot(remainder, remainder_size); - return chunk2mem(victim); - } - - else if (remainder_size >= 0) /* take */ - { - set_inuse_bit_at_offset(victim, victim_size); - unlink(victim, bck, fwd); - return chunk2mem(victim); - } - + mchunkptr victim; /* inspected/selected chunk */ + INTERNAL_SIZE_T victim_size; /* its size */ + int idx; /* index for bin traversal */ + mbinptr bin; /* associated bin */ + mchunkptr remainder; /* remainder from a split */ + long remainder_size; /* its size */ + int remainder_index; /* its bin index */ + unsigned long block; /* block traverser bit */ + int startidx; /* first bin of a traversed block */ + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + mbinptr q; /* misc temp */ + + INTERNAL_SIZE_T nb; + + if ((long) bytes < 0) + return 0; + + nb = request2size(bytes); /* padded request size; */ + + /* Check for exact match in a bin */ + + if (is_small_request(nb)) { /* Faster version for small requests */ + idx = smallbin_index(nb); + + /* No traversal or size check necessary for small bins. */ + + q = bin_at(idx); + victim = last(q); + + /* Also scan the next one, since it would have a remainder < MINSIZE */ + if (victim == q) { + q = next_bin(q); + victim = last(q); + } + if (victim != q) { + victim_size = chunksize(victim); + unlink(victim, bck, fwd); + set_inuse_bit_at_offset(victim, victim_size); + return chunk2mem(victim); + } + idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */ + } else { + idx = bin_index(nb); + bin = bin_at(idx); + + for (victim = last(bin); victim != bin; victim = victim->bk) { + victim_size = chunksize(victim); + remainder_size = victim_size - nb; + + if (remainder_size >= (long)MINSIZE) { /* too big */ + --idx; /* adjust to rescan below after checking last remainder */ + break; + } + + else if (remainder_size >= 0) { /* exact fit */ + unlink(victim, bck, fwd); + set_inuse_bit_at_offset(victim, victim_size); + return chunk2mem(victim); + } + } + ++idx; } - bin = next_bin(bin); - - } while ((++idx & (BINBLOCKWIDTH - 1)) != 0); - - /* Clear out the block bit. */ - - do /* Possibly backtrack to try to clear a partial block */ - { - if ((startidx & (BINBLOCKWIDTH - 1)) == 0) - { - binblocks &= ~block; - break; - } - --startidx; - q = prev_bin(q); - } while (first(q) == q); - - /* Get to the next possibly nonempty block */ - - if ( (block <<= 1) <= binblocks && (block != 0) ) - { - while ((block & binblocks) == 0) - { - idx += BINBLOCKWIDTH; - block <<= 1; + /* Try to use the last split-off remainder */ + + if ((victim = last_remainder->fd) != last_remainder) { + victim_size = chunksize(victim); + remainder_size = victim_size - nb; + + if (remainder_size >= (long)MINSIZE) { /* re-split */ + remainder = chunk_at_offset(victim, nb); + set_head(victim, nb | PREV_INUSE); + link_last_remainder(remainder); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + return chunk2mem(victim); + } + + clear_last_remainder; + + if (remainder_size >= 0) { /* exhaust */ + set_inuse_bit_at_offset(victim, victim_size); + return chunk2mem(victim); + } + /* Else place in bin */ + frontlink(victim, victim_size, remainder_index, bck, fwd); } - } - else - break; - } - } - - - /* Try to use top chunk */ - - /* Require that there be a remainder, ensuring top always exists */ - if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE) - { + /* + If there are any possibly nonempty big-enough blocks, + search for best fitting chunk by scanning bins in blockwidth units. + */ + if ((block = idx2binblock (idx)) <= binblocks) { + /* Get to the first marked block */ + if ((block & binblocks) == 0) { + /* force to an even block boundary */ + idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH; + block <<= 1; + while ((block & binblocks) == 0) { + idx += BINBLOCKWIDTH; + block <<= 1; + } + } + + /* For each possibly nonempty block ... */ + for (;;) { + startidx = idx; /* (track incomplete blocks) */ + q = bin = bin_at(idx); + + /* For each bin in this block ... */ + do { + /* Find and use first big enough chunk ... */ + for (victim = last(bin); victim != bin; + victim = victim->bk) { + victim_size = chunksize(victim); + remainder_size = victim_size - nb; + + if (remainder_size >= (long)MINSIZE) { /* split */ + remainder = + chunk_at_offset (victim, + nb); + set_head(victim, + nb | PREV_INUSE); + unlink(victim, bck, fwd); + link_last_remainder(remainder); + set_head(remainder, + remainder_size | + PREV_INUSE); + set_foot(remainder, + remainder_size); + return chunk2mem(victim); + } else if (remainder_size >= 0) { /* take */ + set_inuse_bit_at_offset(victim, + victim_size); + unlink(victim, bck, fwd); + return chunk2mem(victim); + } + } + bin = next_bin (bin); + } while ((++idx & (BINBLOCKWIDTH - 1)) != 0); + + /* Clear out the block bit. */ + do { /* Possibly backtrack to try to clear a partial block */ + if ((startidx & (BINBLOCKWIDTH - 1)) == 0) { + binblocks &= ~block; + break; + } + --startidx; + q = prev_bin(q); + } while (first(q) == q); + + /* Get to the next possibly nonempty block */ + + if ((block <<= 1) <= binblocks && (block != 0)) { + while ((block & binblocks) == 0) { + idx += BINBLOCKWIDTH; + block <<= 1; + } + } else + break; + } + } - /* Try to extend */ - malloc_extend_top(nb); - if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE) - return 0; /* propagate failure */ - } + /* Try to use top chunk */ - victim = top; - set_head(victim, nb | PREV_INUSE); - top = chunk_at_offset(victim, nb); - set_head(top, remainder_size | PREV_INUSE); - return chunk2mem(victim); + /* Require that there be a remainder, ensuring top always exists */ + if ((remainder_size = chunksize (top) - nb) < (long) MINSIZE) { + /* Try to extend */ + malloc_extend_top(nb); + if ((remainder_size = chunksize(top) - nb) < (long) MINSIZE) + return 0; /* propagate failure */ + } + victim = top; + set_head(victim, nb | PREV_INUSE); + top = chunk_at_offset(victim, nb); + set_head(top, remainder_size | PREV_INUSE); + return chunk2mem(victim); } - - - /* - free() algorithm : cases: @@ -1466,97 +1391,83 @@ void* malloc(size_t bytes) 4. Other chunks are consolidated as they arrive, and placed in corresponding bins. (This includes the case of consolidating with the current `last_remainder'). - */ - - -void free(void* mem) +void free(void *mem) { - mchunkptr p; /* chunk corresponding to mem */ - INTERNAL_SIZE_T hd; /* its head field */ - INTERNAL_SIZE_T sz; /* its size */ - int idx; /* its bin index */ - mchunkptr next; /* next contiguous chunk */ - INTERNAL_SIZE_T nextsz; /* its size */ - INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */ - mchunkptr bck; /* misc temp for linking */ - mchunkptr fwd; /* misc temp for linking */ - int islr; /* track whether merging with last_remainder */ - - if (mem == 0) /* free(0) has no effect */ - return; - - p = mem2chunk(mem); - hd = p->size; - - - sz = hd & ~PREV_INUSE; - next = chunk_at_offset(p, sz); - nextsz = chunksize(next); - - if (next == top) /* merge with top */ - { - sz += nextsz; - - if (!(hd & PREV_INUSE)) /* consolidate backward */ - { - prevsz = p->prev_size; - p = chunk_at_offset(p, -((long) prevsz)); - sz += prevsz; - unlink(p, bck, fwd); - } - - set_head(p, sz | PREV_INUSE); - top = p; + mchunkptr p; /* chunk corresponding to mem */ + INTERNAL_SIZE_T hd; /* its head field */ + INTERNAL_SIZE_T sz; /* its size */ + int idx; /* its bin index */ + mchunkptr next; /* next contiguous chunk */ + INTERNAL_SIZE_T nextsz; /* its size */ + INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */ + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + int islr; /* track whether merging with last_remainder */ + + if (mem == 0) /* free(0) has no effect */ + return; + + p = mem2chunk(mem); + hd = p->size; + + + sz = hd & ~PREV_INUSE; + next = chunk_at_offset(p, sz); + nextsz = chunksize(next); + + if (next == top) { /* merge with top */ + sz += nextsz; + + if (!(hd & PREV_INUSE)) { /* consolidate backward */ + prevsz = p->prev_size; + p = chunk_at_offset(p, -((long) prevsz)); + sz += prevsz; + unlink (p, bck, fwd); + } + + set_head(p, sz | PREV_INUSE); + top = p; #ifdef USE_MALLOC_TRIM - if ((unsigned long)(sz) >= (unsigned long)trim_threshold) - malloc_trim(top_pad); + if ((unsigned long) (sz) >= (unsigned long)trim_threshold) + malloc_trim(top_pad); #endif - return; - } - - set_head(next, nextsz); /* clear inuse bit */ - - islr = 0; - - if (!(hd & PREV_INUSE)) /* consolidate backward */ - { - prevsz = p->prev_size; - p = chunk_at_offset(p, -((long) prevsz)); - sz += prevsz; - - if (p->fd == last_remainder) /* keep as last_remainder */ - islr = 1; - else - unlink(p, bck, fwd); - } - - if (!(inuse_bit_at_offset(next, nextsz))) /* consolidate forward */ - { - sz += nextsz; - - if (!islr && next->fd == last_remainder) /* re-insert last_remainder */ - { - islr = 1; - link_last_remainder(p); - } - else - unlink(next, bck, fwd); - } - - - set_head(p, sz | PREV_INUSE); - set_foot(p, sz); - if (!islr) - frontlink(p, sz, idx, bck, fwd); -} + return; + } + set_head(next, nextsz); /* clear inuse bit */ - + islr = 0; + if (!(hd & PREV_INUSE)) { /* consolidate backward */ + prevsz = p->prev_size; + p = chunk_at_offset(p, -((long) prevsz)); + sz += prevsz; + + if (p->fd == last_remainder) /* keep as last_remainder */ + islr = 1; + else + unlink(p, bck, fwd); + } + + if (!(inuse_bit_at_offset(next, nextsz))) { /* consolidate forward */ + sz += nextsz; + + if (!islr && next->fd == last_remainder) { /* re-insert last_remainder */ + islr = 1; + link_last_remainder(p); + } else + unlink(next, bck, fwd); + } -/* + set_head(p, sz | PREV_INUSE); + set_foot(p, sz); + if (!islr) + frontlink(p, sz, idx, bck, fwd); +} + +/* Realloc algorithm: Chunks that were obtained via mmap cannot be extended or shrunk @@ -1586,189 +1497,179 @@ void free(void* mem) I don't know of any programs still relying on this feature, and allowing it would also allow too many other incorrect usages of realloc to be sensible. - - */ - - -void* realloc(void* oldmem, size_t bytes) +void *realloc(void *oldmem, size_t bytes) { - INTERNAL_SIZE_T nb; /* padded request size */ + INTERNAL_SIZE_T nb; /* padded request size */ - mchunkptr oldp; /* chunk corresponding to oldmem */ - INTERNAL_SIZE_T oldsize; /* its size */ + mchunkptr oldp; /* chunk corresponding to oldmem */ + INTERNAL_SIZE_T oldsize; /* its size */ - mchunkptr newp; /* chunk to return */ - INTERNAL_SIZE_T newsize; /* its size */ - void* newmem; /* corresponding user mem */ + mchunkptr newp; /* chunk to return */ + INTERNAL_SIZE_T newsize; /* its size */ + void *newmem; /* corresponding user mem */ - mchunkptr next; /* next contiguous chunk after oldp */ - INTERNAL_SIZE_T nextsize; /* its size */ + mchunkptr next; /* next contiguous chunk after oldp */ + INTERNAL_SIZE_T nextsize; /* its size */ - mchunkptr prev; /* previous contiguous chunk before oldp */ - INTERNAL_SIZE_T prevsize; /* its size */ + mchunkptr prev; /* previous contiguous chunk before oldp */ + INTERNAL_SIZE_T prevsize; /* its size */ - mchunkptr remainder; /* holds split off extra space from newp */ - INTERNAL_SIZE_T remainder_size; /* its size */ + mchunkptr remainder; /* holds split off extra space from newp */ + INTERNAL_SIZE_T remainder_size; /* its size */ - mchunkptr bck; /* misc temp for linking */ - mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ #ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { free(oldmem); return 0; } + if (bytes == 0) { + free(oldmem); + return 0; + } #endif - if ((long)bytes < 0) return 0; - - /* realloc of null is supposed to be same as malloc */ - if (oldmem == 0) return malloc(bytes); - - newp = oldp = mem2chunk(oldmem); - newsize = oldsize = chunksize(oldp); - - - nb = request2size(bytes); - - - if ((long)(oldsize) < (long)(nb)) - { + if ((long)bytes < 0) + return 0; + + /* realloc of null is supposed to be same as malloc */ + if (oldmem == 0) + return malloc(bytes); + + newp = oldp = mem2chunk(oldmem); + newsize = oldsize = chunksize(oldp); + + + nb = request2size(bytes); + + + if ((long)(oldsize) < (long)(nb)) { + + /* Try expanding forward */ + + next = chunk_at_offset(oldp, oldsize); + if (next == top || !inuse(next)) { + nextsize = chunksize(next); + + /* Forward into top only if a remainder */ + if (next == top) { + if ((long)(nextsize + newsize) >= + (long)(nb + MINSIZE)) { + newsize += nextsize; + top = chunk_at_offset(oldp, nb); + set_head (top, + (newsize - nb) | PREV_INUSE); + set_head_size(oldp, nb); + return chunk2mem(oldp); + } + } + + /* Forward into next chunk */ + else if (((long) (nextsize + newsize) >= (long) (nb))) { + unlink(next, bck, fwd); + newsize += nextsize; + goto split; + } + } else { + next = 0; + nextsize = 0; + } + + /* Try shifting backwards. */ + + if (!prev_inuse(oldp)) { + prev = prev_chunk(oldp); + prevsize = chunksize(prev); + + /* try forward + backward first to save a later consolidation */ + + if (next != 0) { + /* into top */ + if (next == top) { + if ((long) + (nextsize + prevsize + newsize) >= + (long)(nb + MINSIZE)) { + unlink (prev, bck, fwd); + newp = prev; + newsize += prevsize + nextsize; + newmem = chunk2mem(newp); + memcpy(newmem, oldmem, + oldsize - SIZE_SZ); + top = chunk_at_offset(newp, nb); + set_head(top, + (newsize - + nb) | PREV_INUSE); + set_head_size(newp, nb); + return newmem; + } + } + + /* into next chunk */ + else if (((long)(nextsize + prevsize + newsize) + >= (long)(nb))) { + unlink(next, bck, fwd); + unlink(prev, bck, fwd); + newp = prev; + newsize += nextsize + prevsize; + newmem = chunk2mem(newp); + memcpy(newmem, oldmem, + oldsize - SIZE_SZ); + goto split; + } + } + + /* backward only */ + if (prev != 0 + && (long)(prevsize + newsize) >= (long)nb) { + unlink(prev, bck, fwd); + newp = prev; + newsize += prevsize; + newmem = chunk2mem(newp); + memcpy(newmem, oldmem, oldsize - SIZE_SZ); + goto split; + } + } + + /* Must allocate */ + + newmem = malloc(bytes); + + if (newmem == 0) /* propagate failure */ + return 0; + + /* Avoid copy if newp is next chunk after oldp. */ + /* (This can only happen when new chunk is sbrk'ed.) */ + + if ((newp = mem2chunk(newmem)) == next_chunk(oldp)) { + newsize += chunksize(newp); + newp = oldp; + goto split; + } + + /* Otherwise copy, free, and exit */ + memcpy(newmem, oldmem, oldsize - SIZE_SZ); + free(oldmem); + return newmem; + } - /* Try expanding forward */ - next = chunk_at_offset(oldp, oldsize); - if (next == top || !inuse(next)) - { - nextsize = chunksize(next); +split: /* split off extra room in old or expanded chunk */ - /* Forward into top only if a remainder */ - if (next == top) - { - if ((long)(nextsize + newsize) >= (long)(nb + MINSIZE)) - { - newsize += nextsize; - top = chunk_at_offset(oldp, nb); - set_head(top, (newsize - nb) | PREV_INUSE); - set_head_size(oldp, nb); - return chunk2mem(oldp); - } - } - - /* Forward into next chunk */ - else if (((long)(nextsize + newsize) >= (long)(nb))) - { - unlink(next, bck, fwd); - newsize += nextsize; - goto split; - } - } - else - { - next = 0; - nextsize = 0; - } - - /* Try shifting backwards. */ - - if (!prev_inuse(oldp)) - { - prev = prev_chunk(oldp); - prevsize = chunksize(prev); - - /* try forward + backward first to save a later consolidation */ - - if (next != 0) - { - /* into top */ - if (next == top) - { - if ((long)(nextsize + prevsize + newsize) >= (long)(nb + MINSIZE)) - { - unlink(prev, bck, fwd); - newp = prev; - newsize += prevsize + nextsize; - newmem = chunk2mem(newp); - memcpy(newmem, oldmem, oldsize - SIZE_SZ); - top = chunk_at_offset(newp, nb); - set_head(top, (newsize - nb) | PREV_INUSE); - set_head_size(newp, nb); - return newmem; - } + if (newsize - nb >= MINSIZE) { /* split off remainder */ + remainder = chunk_at_offset(newp, nb); + remainder_size = newsize - nb; + set_head_size(newp, nb); + set_head(remainder, remainder_size | PREV_INUSE); + set_inuse_bit_at_offset(remainder, remainder_size); + free (chunk2mem(remainder)); /* let free() deal with it */ + } else { + set_head_size(newp, newsize); + set_inuse_bit_at_offset(newp, newsize); } - /* into next chunk */ - else if (((long)(nextsize + prevsize + newsize) >= (long)(nb))) - { - unlink(next, bck, fwd); - unlink(prev, bck, fwd); - newp = prev; - newsize += nextsize + prevsize; - newmem = chunk2mem(newp); - memcpy(newmem, oldmem, oldsize - SIZE_SZ); - goto split; - } - } - - /* backward only */ - if (prev != 0 && (long)(prevsize + newsize) >= (long)nb) - { - unlink(prev, bck, fwd); - newp = prev; - newsize += prevsize; - newmem = chunk2mem(newp); - memcpy(newmem, oldmem, oldsize - SIZE_SZ); - goto split; - } - } - - /* Must allocate */ - - newmem = malloc (bytes); - - if (newmem == 0) /* propagate failure */ - return 0; - - /* Avoid copy if newp is next chunk after oldp. */ - /* (This can only happen when new chunk is sbrk'ed.) */ - - if ( (newp = mem2chunk(newmem)) == next_chunk(oldp)) - { - newsize += chunksize(newp); - newp = oldp; - goto split; - } - - /* Otherwise copy, free, and exit */ - memcpy(newmem, oldmem, oldsize - SIZE_SZ); - free(oldmem); - return newmem; - } - - - split: /* split off extra room in old or expanded chunk */ - - if (newsize - nb >= MINSIZE) /* split off remainder */ - { - remainder = chunk_at_offset(newp, nb); - remainder_size = newsize - nb; - set_head_size(newp, nb); - set_head(remainder, remainder_size | PREV_INUSE); - set_inuse_bit_at_offset(remainder, remainder_size); - free(chunk2mem(remainder)); /* let free() deal with it */ - } - else - { - set_head_size(newp, newsize); - set_inuse_bit_at_offset(newp, newsize); - } - - return chunk2mem(newp); + return chunk2mem(newp); } - - - /* - memalign algorithm: memalign requests more than enough space from malloc, finds a spot @@ -1782,177 +1683,158 @@ void* realloc(void* oldmem, size_t bytes) bother calling memalign with an argument of 8 or less. Overreliance on memalign is a sure way to fragment space. - */ - - -void* memalign(size_t alignment, size_t bytes) +void *memalign(size_t alignment, size_t bytes) { - INTERNAL_SIZE_T nb; /* padded request size */ - char* m; /* memory returned by malloc call */ - mchunkptr p; /* corresponding chunk */ - char* brk; /* alignment point within p */ - mchunkptr newp; /* chunk to return */ - INTERNAL_SIZE_T newsize; /* its size */ - INTERNAL_SIZE_T leadsize; /* leading space befor alignment point */ - mchunkptr remainder; /* spare room at end to split off */ - long remainder_size; /* its size */ + INTERNAL_SIZE_T nb; /* padded request size */ + char *m; /* memory returned by malloc call */ + mchunkptr p; /* corresponding chunk */ + char *brk; /* alignment point within p */ + mchunkptr newp; /* chunk to return */ + INTERNAL_SIZE_T newsize; /* its size */ + INTERNAL_SIZE_T leadsize; /* leading space befor alignment point */ + mchunkptr remainder; /* spare room at end to split off */ + long remainder_size; /* its size */ - if ((long)bytes < 0) return 0; + if ((long) bytes < 0) + return 0; - /* If need less alignment than we give anyway, just relay to malloc */ + /* If need less alignment than we give anyway, just relay to malloc */ - if (alignment <= MALLOC_ALIGNMENT) return malloc(bytes); + if (alignment <= MALLOC_ALIGNMENT) + return malloc(bytes); - /* Otherwise, ensure that it is at least a minimum chunk size */ + /* Otherwise, ensure that it is at least a minimum chunk size */ - if (alignment < MINSIZE) alignment = MINSIZE; + if (alignment < MINSIZE) + alignment = MINSIZE; - /* Call malloc with worst case padding to hit alignment. */ + /* Call malloc with worst case padding to hit alignment. */ - nb = request2size(bytes); - m = (char*)(malloc(nb + alignment + MINSIZE)); + nb = request2size(bytes); + m = (char*)(malloc (nb + alignment + MINSIZE)); - if (m == 0) return 0; /* propagate failure */ + if (m == 0) + return 0; /* propagate failure */ - p = mem2chunk(m); + p = mem2chunk(m); - if ((((unsigned long)(m)) % alignment) == 0) /* aligned */ - { - } - else /* misaligned */ - { - /* - Find an aligned spot inside chunk. - Since we need to give back leading space in a chunk of at - least MINSIZE, if the first calculation places us at - a spot with less than MINSIZE leader, we can move to the - next aligned spot -- we've allocated enough total room so that - this is always possible. - */ + if ((((unsigned long)(m)) % alignment) == 0) { /* aligned */ + } else { /* misaligned */ - brk = (char*)mem2chunk(((unsigned long)(m + alignment - 1)) & -((signed) alignment)); - if ((long)(brk - (char*)(p)) < MINSIZE) brk = brk + alignment; + /* + Find an aligned spot inside chunk. + Since we need to give back leading space in a chunk of at + least MINSIZE, if the first calculation places us at + a spot with less than MINSIZE leader, we can move to the + next aligned spot -- we've allocated enough total room so that + this is always possible. + */ - newp = (mchunkptr)brk; - leadsize = brk - (char*)(p); - newsize = chunksize(p) - leadsize; + brk = (char*) mem2chunk(((unsigned long) (m + alignment - 1)) & + -((signed) alignment)); + if ((long)(brk - (char*)(p)) < MINSIZE) + brk = brk + alignment; + newp = (mchunkptr)brk; + leadsize = brk - (char*)(p); + newsize = chunksize(p) - leadsize; - /* give back leader, use the rest */ + /* give back leader, use the rest */ - set_head(newp, newsize | PREV_INUSE); - set_inuse_bit_at_offset(newp, newsize); - set_head_size(p, leadsize); - free(chunk2mem(p)); - p = newp; - } - - /* Also give back spare room at the end */ + set_head(newp, newsize | PREV_INUSE); + set_inuse_bit_at_offset(newp, newsize); + set_head_size(p, leadsize); + free(chunk2mem(p)); + p = newp; + } - remainder_size = chunksize(p) - nb; + /* Also give back spare room at the end */ - if (remainder_size >= (long)MINSIZE) - { - remainder = chunk_at_offset(p, nb); - set_head(remainder, remainder_size | PREV_INUSE); - set_head_size(p, nb); - free(chunk2mem(remainder)); - } + remainder_size = chunksize(p) - nb; - return chunk2mem(p); + if (remainder_size >= (long)MINSIZE) { + remainder = chunk_at_offset(p, nb); + set_head(remainder, remainder_size | PREV_INUSE); + set_head_size(p, nb); + free (chunk2mem(remainder)); + } + return chunk2mem(p); } - - - /* - valloc just invokes memalign with alignment argument equal - to the page size of the system (or as near to this as can - be figured out from all the includes/defines above.) -*/ - -void* valloc(size_t bytes) + * valloc just invokes memalign with alignment argument equal + * to the page size of the system (or as near to this as can + * be figured out from all the includes/defines above.) + */ +void *valloc(size_t bytes) { - return memalign (malloc_getpagesize, bytes); + return memalign(malloc_getpagesize, bytes); } /* - pvalloc just invokes valloc for the nearest pagesize - that will accommodate request -*/ - - -void* pvalloc(size_t bytes) + * pvalloc just invokes valloc for the nearest pagesize + * that will accommodate request + */ +void *pvalloc (size_t bytes) { - size_t pagesize = malloc_getpagesize; - return memalign (pagesize, (bytes + pagesize - 1) & ~(pagesize - 1)); + size_t pagesize = malloc_getpagesize; + + return memalign(pagesize, (bytes + pagesize - 1) & ~(pagesize - 1)); } /* - - calloc calls malloc, then zeroes out the allocated chunk. - -*/ - -void* calloc(size_t n, size_t elem_size) + * + * calloc calls malloc, then zeroes out the allocated chunk. + * + */ +void *calloc(size_t n, size_t elem_size) { - mchunkptr p; - INTERNAL_SIZE_T csz; - - INTERNAL_SIZE_T sz = n * elem_size; - - - /* check if expand_top called, in which case don't need to clear */ - mchunkptr oldtop = top; - INTERNAL_SIZE_T oldtopsize = chunksize(top); + mchunkptr p; + INTERNAL_SIZE_T csz; + INTERNAL_SIZE_T sz = n * elem_size; - void* mem = malloc (sz); + /* check if expand_top called, in which case don't need to clear */ + mchunkptr oldtop = top; + INTERNAL_SIZE_T oldtopsize = chunksize(top); - if ((long)n < 0) return 0; + void *mem = malloc(sz); - if (mem == 0) - return 0; - else - { - p = mem2chunk(mem); + if ((long)n < 0) + return 0; - /* Two optional cases in which clearing not necessary */ + if (mem == 0) + return 0; + else { + p = mem2chunk(mem); + /* Two optional cases in which clearing not necessary */ + csz = chunksize(p); + if (p == oldtop && csz > oldtopsize) { + /* clear only the bytes from non-freshly-sbrked memory */ + csz = oldtopsize; + } - csz = chunksize(p); - - if (p == oldtop && csz > oldtopsize) - { - /* clear only the bytes from non-freshly-sbrked memory */ - csz = oldtopsize; - } - - memset(mem, 0, csz - SIZE_SZ); - return mem; - } + memset(mem, 0, csz - SIZE_SZ); + return mem; + } } /* - - cfree just calls free. It is needed/defined on some systems - that pair it with calloc, presumably for odd historical reasons. - -*/ - + * + * cfree just calls free. It is needed/defined on some systems + * that pair it with calloc, presumably for odd historical reasons. + */ #if !defined(INTERNAL_LINUX_C_LIB) || !defined(__ELF__) void cfree(void *mem) { - free(mem); + free(mem); } #endif - - /* - Malloc_trim gives memory back to the system (via negative arguments to sbrk) if there is unused memory at the `high' end of the malloc pool. You can call this after freeing large blocks of @@ -1971,137 +1853,126 @@ void cfree(void *mem) from the system. Malloc_trim returns 1 if it actually released any memory, else 0. - */ #ifdef USE_MALLOC_TRIM int malloc_trim(size_t pad) { - long top_size; /* Amount of top-most memory */ - long extra; /* Amount to release */ - char* current_brk; /* address returned by pre-check sbrk call */ - char* new_brk; /* address returned by negative sbrk call */ - - unsigned long pagesz = malloc_getpagesize; - - top_size = chunksize(top); - extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz; - - if (extra < (long)pagesz) /* Not enough memory to release */ - return 0; - - else - { - /* Test to make sure no one else called sbrk */ - current_brk = (char*)(sbrk (0)); - if (current_brk != (char*)(top) + top_size) - return 0; /* Apparently we don't own memory; must fail */ - - else - { - new_brk = (char*)(sbrk (-extra)); - - if (new_brk == (char*)(NULL)) /* sbrk failed? */ - { - /* Try to figure out what we have */ - current_brk = (char*)(sbrk (0)); - top_size = current_brk - (char*)top; - if (top_size >= (long)MINSIZE) /* if not, we are very very dead! */ - { - sbrked_mem = current_brk - sbrk_base; - set_head(top, top_size | PREV_INUSE); + long top_size; /* Amount of top-most memory */ + long extra; /* Amount to release */ + char *current_brk; /* address returned by pre-check sbrk call */ + char *new_brk; /* address returned by negative sbrk call */ + + unsigned long pagesz = malloc_getpagesize; + + top_size = chunksize(top); + extra = ((top_size - pad - MINSIZE + (pagesz - 1)) / pagesz - + 1) * pagesz; + + if (extra < (long)pagesz) /* Not enough memory to release */ + return 0; + + else { + /* Test to make sure no one else called sbrk */ + current_brk = (char*)(sbrk(0)); + if (current_brk != (char*)(top) + top_size) + return 0; /* Apparently we don't own memory; must fail */ + + else { + new_brk = (char *) (sbrk(-extra)); + + if (new_brk == (char*)(NULL)) { /* sbrk failed? */ + /* Try to figure out what we have */ + current_brk = (char*)(sbrk (0)); + top_size = current_brk - (char*) top; + if (top_size >= (long)MINSIZE) { /* if not, we are very very dead! */ + sbrked_mem = current_brk - sbrk_base; + set_head(top, top_size | PREV_INUSE); + } + return 0; + } + + else { + /* Success. Adjust top accordingly. */ + set_head(top, (top_size - extra) | PREV_INUSE); + sbrked_mem -= extra; + return 1; + } + } } - return 0; - } - - else - { - /* Success. Adjust top accordingly. */ - set_head(top, (top_size - extra) | PREV_INUSE); - sbrked_mem -= extra; - return 1; - } - } - } } #endif - /* - malloc_usable_size: - - This routine tells you how many bytes you can actually use in an - allocated chunk, which may be more than you requested (although - often not). You can use this many bytes without worrying about - overwriting other allocated objects. Not a particularly great - programming practice, but still sometimes useful. - -*/ - -size_t malloc_usable_size(void* mem) + * malloc_usable_size: + * + * This routine tells you how many bytes you can actually use in an + * allocated chunk, which may be more than you requested (although + * often not). You can use this many bytes without worrying about + * overwriting other allocated objects. Not a particularly great + * programming practice, but still sometimes useful. + */ +size_t malloc_usable_size(void *mem) { - mchunkptr p; - if (mem == 0) - return 0; - else - { - p = mem2chunk(mem); - if(!chunk_is_mmapped(p)) - { - if (!inuse(p)) return 0; - return chunksize(p) - SIZE_SZ; - } - return chunksize(p) - 2*SIZE_SZ; - } + mchunkptr p; + + if (mem == 0) + return 0; + else { + p = mem2chunk(mem); + if (!chunk_is_mmapped(p)) { + if (!inuse(p)) + return 0; + return chunksize(p) - SIZE_SZ; + } + return chunksize(p) - 2 * SIZE_SZ; + } } + - /* Utility to update current_mallinfo for malloc_stats and mallinfo() */ #ifdef CONFIG_CMD_MEMINFO static void malloc_update_mallinfo(void) { - int i; - mbinptr b; - mchunkptr p; + int i; + mbinptr b; + mchunkptr p; + #ifdef DEBUG - mchunkptr q; + mchunkptr q; #endif - INTERNAL_SIZE_T avail = chunksize(top); - int navail = ((long)(avail) >= (long)MINSIZE)? 1 : 0; + INTERNAL_SIZE_T avail = chunksize(top); + int navail = ((long)(avail) >= (long)MINSIZE) ? 1 : 0; - for (i = 1; i < NAV; ++i) - { - b = bin_at(i); - for (p = last(b); p != b; p = p->bk) - { + for (i = 1; i < NAV; ++i) { + b = bin_at (i); + for (p = last(b); p != b; p = p->bk) { #ifdef DEBUG - for (q = next_chunk(p); - q < top && inuse(q) && (long)(chunksize(q)) >= (long)MINSIZE; - q = next_chunk(q)) + for (q = next_chunk(p); + q < top && inuse(q) + && (long) (chunksize(q)) >= (long)MINSIZE; + q = next_chunk(q)) #endif - avail += chunksize(p); - navail++; - } - } - - current_mallinfo.ordblks = navail; - current_mallinfo.uordblks = sbrked_mem - avail; - current_mallinfo.fordblks = avail; + avail += chunksize(p); + navail++; + } + } + + current_mallinfo.ordblks = navail; + current_mallinfo.uordblks = sbrked_mem - avail; + current_mallinfo.fordblks = avail; #if HAVE_MMAP - current_mallinfo.hblks = n_mmaps; + current_mallinfo.hblks = n_mmaps; #endif - current_mallinfo.hblkhd = mmapped_mem; - current_mallinfo.keepcost = chunksize(top); + current_mallinfo.hblkhd = mmapped_mem; + current_mallinfo.keepcost = chunksize(top); } - - /* - malloc_stats: Prints on the amount of space obtain from the system (both @@ -2112,33 +1983,26 @@ static void malloc_update_mallinfo(void) freed. (Note that this is the number of bytes allocated, not the number requested. It will be larger than the number requested because of alignment and bookkeeping overhead.) - -*/ - - + */ /* - mallinfo returns a copy of updated current mallinfo. -*/ - -void malloc_stats() + * mallinfo returns a copy of updated current mallinfo. + */ +void malloc_stats(void) { - malloc_update_mallinfo(); - printf("max system bytes = %10u\n", - (unsigned int)(max_total_mem)); - printf("system bytes = %10u\n", - (unsigned int)(sbrked_mem + mmapped_mem)); - printf("in use bytes = %10u\n", - (unsigned int)(current_mallinfo.uordblks + mmapped_mem)); + malloc_update_mallinfo(); + printf("max system bytes = %10u\n", (unsigned int)(max_total_mem)); + printf("system bytes = %10u\n", + (unsigned int)(sbrked_mem + mmapped_mem)); + printf("in use bytes = %10u\n", + (unsigned int)(current_mallinfo.uordblks + mmapped_mem)); #if HAVE_MMAP - fprintf(stderr, "max mmap regions = %10u\n", - (unsigned int)max_n_mmaps); + fprintf(stderr, "max mmap regions = %10u\n", + (unsigned int) max_n_mmaps); #endif } #endif /* CONFIG_CMD_MEMINFO */ - - /* mallopt: @@ -2149,27 +2013,33 @@ void malloc_stats() and returns 1 if successful else 0. See descriptions of tunable parameters above. - */ #ifndef __U_BOOT__ int mallopt(int param_number, int value) { - switch(param_number) - { - case M_TRIM_THRESHOLD: - trim_threshold = value; return 1; - case M_TOP_PAD: - top_pad = value; return 1; - case M_MMAP_THRESHOLD: - mmap_threshold = value; return 1; - case M_MMAP_MAX: - if (value != 0) return 0; else n_mmaps_max = value; return 1; - - default: - return 0; - } + switch (param_number) { + case M_TRIM_THRESHOLD: + trim_threshold = value; + return 1; + case M_TOP_PAD: + top_pad = value; + return 1; + case M_MMAP_THRESHOLD: + mmap_threshold = value; + return 1; + case M_MMAP_MAX: + if (value != 0) + return 0; + else + n_mmaps_max = value; + return 1; + + default: + return 0; + } } #endif + /* History: @@ -2281,4 +2151,3 @@ EXPORT_SYMBOL(malloc); EXPORT_SYMBOL(calloc); EXPORT_SYMBOL(free); EXPORT_SYMBOL(realloc); - -- cgit v1.2.3