00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #define HEAP_MIN_SIZE (32*1024)
00026 #ifndef HEAP_MAX_SIZE
00027 #define HEAP_MAX_SIZE (1024*1024)
00028 #endif
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef THREAD_STATS
00039 #define THREAD_STATS 0
00040 #endif
00041
00042
00043
00044
00045
00046
00047 #define top(ar_ptr) ((ar_ptr)->top)
00048
00049
00050
00051
00052
00053
00054 typedef struct _heap_info {
00055 mstate ar_ptr;
00056 struct _heap_info *prev;
00057 size_t size;
00058 size_t pad;
00059 } heap_info;
00060
00061
00062
00063 static tsd_key_t arena_key;
00064 static mutex_t list_lock;
00065
00066 #if THREAD_STATS
00067 static int stat_n_heaps;
00068 #define THREAD_STAT(x) x
00069 #else
00070 #define THREAD_STAT(x) do ; while(0)
00071 #endif
00072
00073
00074 static unsigned long arena_mem;
00075
00076
00077 int __malloc_initialized = -1;
00078
00079
00080
00081 #if USE_ARENAS
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 #define arena_get(ptr, size) do { \
00092 Void_t *vptr = NULL; \
00093 ptr = (mstate)tsd_getspecific(arena_key, vptr); \
00094 if(ptr && !mutex_trylock(&ptr->mutex)) { \
00095 THREAD_STAT(++(ptr->stat_lock_direct)); \
00096 } else \
00097 ptr = arena_get2(ptr, (size)); \
00098 } while(0)
00099
00100
00101
00102 #define heap_for_ptr(ptr) \
00103 ((heap_info *)((unsigned long)(ptr) & ~(HEAP_MAX_SIZE-1)))
00104 #define arena_for_chunk(ptr) \
00105 (chunk_non_main_arena(ptr) ? heap_for_ptr(ptr)->ar_ptr : &main_arena)
00106
00107 #else
00108
00109
00110
00111 #if THREAD_STATS
00112 #define arena_get(ar_ptr, sz) do { \
00113 ar_ptr = &main_arena; \
00114 if(!mutex_trylock(&ar_ptr->mutex)) \
00115 ++(ar_ptr->stat_lock_direct); \
00116 else { \
00117 (void)mutex_lock(&ar_ptr->mutex); \
00118 ++(ar_ptr->stat_lock_wait); \
00119 } \
00120 } while(0)
00121 #else
00122 #define arena_get(ar_ptr, sz) do { \
00123 ar_ptr = &main_arena; \
00124 (void)mutex_lock(&ar_ptr->mutex); \
00125 } while(0)
00126 #endif
00127 #define arena_for_chunk(ptr) (&main_arena)
00128
00129 #endif
00130
00131
00132
00133 #ifndef NO_THREADS
00134
00135
00136
00137 static __malloc_ptr_t (*save_malloc_hook) __MALLOC_P ((size_t __size,
00138 const __malloc_ptr_t));
00139 # if !defined _LIBC || !defined USE_TLS || (defined SHARED && !USE___THREAD)
00140 static __malloc_ptr_t (*save_memalign_hook) __MALLOC_P ((size_t __align,
00141 size_t __size,
00142 const __malloc_ptr_t));
00143 # endif
00144 static void (*save_free_hook) __MALLOC_P ((__malloc_ptr_t __ptr,
00145 const __malloc_ptr_t));
00146 static Void_t* save_arena;
00147
00148
00149
00150
00151 #define ATFORK_ARENA_PTR ((Void_t*)-1)
00152
00153
00154
00155
00156 static Void_t*
00157 malloc_atfork(size_t sz, const Void_t *caller)
00158 {
00159 Void_t *vptr = NULL;
00160 Void_t *victim;
00161
00162 tsd_getspecific(arena_key, vptr);
00163 if(vptr == ATFORK_ARENA_PTR) {
00164
00165 if(save_malloc_hook != malloc_check) {
00166 return _int_malloc(&main_arena, sz);
00167 } else {
00168 if(top_check()<0)
00169 return 0;
00170 victim = _int_malloc(&main_arena, sz+1);
00171 return mem2mem_check(victim, sz);
00172 }
00173 } else {
00174
00175
00176
00177 (void)mutex_lock(&list_lock);
00178 (void)mutex_unlock(&list_lock);
00179 return public_mALLOc(sz);
00180 }
00181 }
00182
00183 static void
00184 free_atfork(Void_t* mem, const Void_t *caller)
00185 {
00186 Void_t *vptr = NULL;
00187 mstate ar_ptr;
00188 mchunkptr p;
00189
00190 if (mem == 0)
00191 return;
00192
00193 p = mem2chunk(mem);
00194
00195 #if HAVE_MMAP
00196 if (chunk_is_mmapped(p))
00197 {
00198 munmap_chunk(p);
00199 return;
00200 }
00201 #endif
00202
00203 ar_ptr = arena_for_chunk(p);
00204 tsd_getspecific(arena_key, vptr);
00205 if(vptr != ATFORK_ARENA_PTR)
00206 (void)mutex_lock(&ar_ptr->mutex);
00207 _int_free(ar_ptr, mem);
00208 if(vptr != ATFORK_ARENA_PTR)
00209 (void)mutex_unlock(&ar_ptr->mutex);
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 static void
00219 ptmalloc_lock_all __MALLOC_P((void))
00220 {
00221 mstate ar_ptr;
00222
00223 if(__malloc_initialized < 1)
00224 return;
00225 (void)mutex_lock(&list_lock);
00226 for(ar_ptr = &main_arena;;) {
00227 (void)mutex_lock(&ar_ptr->mutex);
00228 ar_ptr = ar_ptr->next;
00229 if(ar_ptr == &main_arena) break;
00230 }
00231 save_malloc_hook = __malloc_hook;
00232 save_free_hook = __free_hook;
00233 __malloc_hook = malloc_atfork;
00234 __free_hook = free_atfork;
00235
00236 tsd_getspecific(arena_key, save_arena);
00237 tsd_setspecific(arena_key, ATFORK_ARENA_PTR);
00238 }
00239
00240 static void
00241 ptmalloc_unlock_all __MALLOC_P((void))
00242 {
00243 mstate ar_ptr;
00244
00245 if(__malloc_initialized < 1)
00246 return;
00247 tsd_setspecific(arena_key, save_arena);
00248 __malloc_hook = save_malloc_hook;
00249 __free_hook = save_free_hook;
00250 for(ar_ptr = &main_arena;;) {
00251 (void)mutex_unlock(&ar_ptr->mutex);
00252 ar_ptr = ar_ptr->next;
00253 if(ar_ptr == &main_arena) break;
00254 }
00255 (void)mutex_unlock(&list_lock);
00256 }
00257
00258 #ifdef __linux__
00259
00260
00261
00262
00263
00264
00265 static void
00266 ptmalloc_unlock_all2 __MALLOC_P((void))
00267 {
00268 mstate ar_ptr;
00269
00270 if(__malloc_initialized < 1)
00271 return;
00272 #if defined _LIBC || defined MALLOC_HOOKS
00273 tsd_setspecific(arena_key, save_arena);
00274 __malloc_hook = save_malloc_hook;
00275 __free_hook = save_free_hook;
00276 #endif
00277 for(ar_ptr = &main_arena;;) {
00278 mutex_init(&ar_ptr->mutex);
00279 ar_ptr = ar_ptr->next;
00280 if(ar_ptr == &main_arena) break;
00281 }
00282 mutex_init(&list_lock);
00283 }
00284
00285 #else
00286
00287 #define ptmalloc_unlock_all2 ptmalloc_unlock_all
00288
00289 #endif
00290
00291 #endif
00292
00293
00294 #ifdef _LIBC
00295 #include <string.h>
00296 extern char **_environ;
00297
00298 static char *
00299 internal_function
00300 next_env_entry (char ***position)
00301 {
00302 char **current = *position;
00303 char *result = NULL;
00304
00305 while (*current != NULL)
00306 {
00307 if (__builtin_expect ((*current)[0] == 'M', 0)
00308 && (*current)[1] == 'A'
00309 && (*current)[2] == 'L'
00310 && (*current)[3] == 'L'
00311 && (*current)[4] == 'O'
00312 && (*current)[5] == 'C'
00313 && (*current)[6] == '_')
00314 {
00315 result = &(*current)[7];
00316
00317
00318 *position = ++current;
00319
00320 break;
00321 }
00322
00323 ++current;
00324 }
00325
00326 return result;
00327 }
00328 #endif
00329
00330
00331 static void
00332 ptmalloc_init_minimal __MALLOC_P((void))
00333 {
00334 #if DEFAULT_TOP_PAD != 0
00335 mp_.top_pad = DEFAULT_TOP_PAD;
00336 #endif
00337 mp_.n_mmaps_max = DEFAULT_MMAP_MAX;
00338 mp_.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
00339 mp_.trim_threshold = DEFAULT_TRIM_THRESHOLD;
00340 mp_.pagesize = malloc_getpagesize;
00341 }
00342
00343 #ifdef _LIBC
00344 # if defined SHARED && defined USE_TLS && !USE___THREAD
00345 # include <stdbool.h>
00346
00347
00348
00349
00350
00351
00352 void
00353 __libc_malloc_pthread_startup (bool first_time)
00354 {
00355 if (first_time)
00356 {
00357 ptmalloc_init_minimal ();
00358 save_malloc_hook = __malloc_hook;
00359 save_memalign_hook = __memalign_hook;
00360 save_free_hook = __free_hook;
00361 __malloc_hook = malloc_starter;
00362 __memalign_hook = memalign_starter;
00363 __free_hook = free_starter;
00364 }
00365 else
00366 {
00367 __malloc_hook = save_malloc_hook;
00368 __memalign_hook = save_memalign_hook;
00369 __free_hook = save_free_hook;
00370 }
00371 }
00372 # endif
00373 #endif
00374
00375 static void
00376 ptmalloc_init __MALLOC_P((void))
00377 {
00378 #if __STD_C
00379 const char* s;
00380 #else
00381 char* s;
00382 #endif
00383 int secure = 0;
00384
00385 if(__malloc_initialized >= 0) return;
00386 __malloc_initialized = 0;
00387
00388 #ifdef _LIBC
00389 # if defined SHARED && defined USE_TLS && !USE___THREAD
00390
00391
00392 if (mp_.pagesize == 0)
00393 # endif
00394 #endif
00395 ptmalloc_init_minimal();
00396
00397 #ifndef NO_THREADS
00398 # if defined _LIBC && defined USE_TLS
00399
00400
00401 # define NO_STARTER
00402 # endif
00403 # ifndef NO_STARTER
00404
00405
00406
00407 save_malloc_hook = __malloc_hook;
00408 save_memalign_hook = __memalign_hook;
00409 save_free_hook = __free_hook;
00410 __malloc_hook = malloc_starter;
00411 __memalign_hook = memalign_starter;
00412 __free_hook = free_starter;
00413 # ifdef _LIBC
00414
00415 if (__pthread_initialize != NULL)
00416 __pthread_initialize();
00417 # endif
00418 # endif
00419 #endif
00420 mutex_init(&main_arena.mutex);
00421 main_arena.next = &main_arena;
00422
00423 mutex_init(&list_lock);
00424 tsd_key_create(&arena_key, NULL);
00425 tsd_setspecific(arena_key, (Void_t *)&main_arena);
00426 thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2);
00427 #ifndef NO_THREADS
00428 # ifndef NO_STARTER
00429 __malloc_hook = save_malloc_hook;
00430 __memalign_hook = save_memalign_hook;
00431 __free_hook = save_free_hook;
00432 # else
00433 # undef NO_STARTER
00434 # endif
00435 #endif
00436 #ifdef _LIBC
00437 secure = __libc_enable_secure;
00438 s = NULL;
00439 if (__builtin_expect (_environ != NULL, 1))
00440 {
00441 char **runp = _environ;
00442 char *envline;
00443
00444 while (__builtin_expect ((envline = next_env_entry (&runp)) != NULL,
00445 0))
00446 {
00447 size_t len = strcspn (envline, "=");
00448
00449 if (envline[len] != '=')
00450
00451
00452
00453 continue;
00454
00455 switch (len)
00456 {
00457 case 6:
00458 if (memcmp (envline, "CHECK_", 6) == 0)
00459 s = &envline[7];
00460 break;
00461 case 8:
00462 if (! secure && memcmp (envline, "TOP_PAD_", 8) == 0)
00463 mALLOPt(M_TOP_PAD, atoi(&envline[9]));
00464 break;
00465 case 9:
00466 if (! secure && memcmp (envline, "MMAP_MAX_", 9) == 0)
00467 mALLOPt(M_MMAP_MAX, atoi(&envline[10]));
00468 break;
00469 case 15:
00470 if (! secure)
00471 {
00472 if (memcmp (envline, "TRIM_THRESHOLD_", 15) == 0)
00473 mALLOPt(M_TRIM_THRESHOLD, atoi(&envline[16]));
00474 else if (memcmp (envline, "MMAP_THRESHOLD_", 15) == 0)
00475 mALLOPt(M_MMAP_THRESHOLD, atoi(&envline[16]));
00476 }
00477 break;
00478 default:
00479 break;
00480 }
00481 }
00482 }
00483 #else
00484 if (! secure)
00485 {
00486 if((s = getenv("MALLOC_TRIM_THRESHOLD_")))
00487 mALLOPt(M_TRIM_THRESHOLD, atoi(s));
00488 if((s = getenv("MALLOC_TOP_PAD_")))
00489 mALLOPt(M_TOP_PAD, atoi(s));
00490 if((s = getenv("MALLOC_MMAP_THRESHOLD_")))
00491 mALLOPt(M_MMAP_THRESHOLD, atoi(s));
00492 if((s = getenv("MALLOC_MMAP_MAX_")))
00493 mALLOPt(M_MMAP_MAX, atoi(s));
00494 }
00495 s = getenv("MALLOC_CHECK_");
00496 #endif
00497 if(s) {
00498 if(s[0]) mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0'));
00499 __malloc_check_init();
00500 }
00501 if(__malloc_initialize_hook != NULL)
00502 (*__malloc_initialize_hook)();
00503 __malloc_initialized = 1;
00504 }
00505
00506
00507 #ifdef thread_atfork_static
00508 thread_atfork_static(ptmalloc_lock_all, ptmalloc_unlock_all, \
00509 ptmalloc_unlock_all2)
00510 #endif
00511
00512
00513
00514
00515
00516 #if USE_ARENAS
00517
00518 #if MALLOC_DEBUG > 1
00519
00520
00521
00522 static void
00523 #if __STD_C
00524 dump_heap(heap_info *heap)
00525 #else
00526 dump_heap(heap) heap_info *heap;
00527 #endif
00528 {
00529 char *ptr;
00530 mchunkptr p;
00531
00532 fprintf(stderr, "Heap %p, size %10lx:\n", heap, (long)heap->size);
00533 ptr = (heap->ar_ptr != (mstate)(heap+1)) ?
00534 (char*)(heap + 1) : (char*)(heap + 1) + sizeof(struct malloc_state);
00535 p = (mchunkptr)(((unsigned long)ptr + MALLOC_ALIGN_MASK) &
00536 ~MALLOC_ALIGN_MASK);
00537 for(;;) {
00538 fprintf(stderr, "chunk %p size %10lx", p, (long)p->size);
00539 if(p == top(heap->ar_ptr)) {
00540 fprintf(stderr, " (top)\n");
00541 break;
00542 } else if(p->size == (0|PREV_INUSE)) {
00543 fprintf(stderr, " (fence)\n");
00544 break;
00545 }
00546 fprintf(stderr, "\n");
00547 p = next_chunk(p);
00548 }
00549 }
00550
00551 #endif
00552
00553
00554
00555
00556 static heap_info *
00557 internal_function
00558 #if __STD_C
00559 new_heap(size_t size, size_t top_pad)
00560 #else
00561 new_heap(size, top_pad) size_t size, top_pad;
00562 #endif
00563 {
00564 size_t page_mask = malloc_getpagesize - 1;
00565 char *p1, *p2;
00566 unsigned long ul;
00567 heap_info *h;
00568
00569 if(size+top_pad < HEAP_MIN_SIZE)
00570 size = HEAP_MIN_SIZE;
00571 else if(size+top_pad <= HEAP_MAX_SIZE)
00572 size += top_pad;
00573 else if(size > HEAP_MAX_SIZE)
00574 return 0;
00575 else
00576 size = HEAP_MAX_SIZE;
00577 size = (size + page_mask) & ~page_mask;
00578
00579
00580
00581
00582
00583 p1 = (char *)MMAP(0, HEAP_MAX_SIZE<<1, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE);
00584 if(p1 != MAP_FAILED) {
00585 p2 = (char *)(((unsigned long)p1 + (HEAP_MAX_SIZE-1)) & ~(HEAP_MAX_SIZE-1));
00586 ul = p2 - p1;
00587 munmap(p1, ul);
00588 munmap(p2 + HEAP_MAX_SIZE, HEAP_MAX_SIZE - ul);
00589 } else {
00590
00591
00592 p2 = (char *)MMAP(0, HEAP_MAX_SIZE, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE);
00593 if(p2 == MAP_FAILED)
00594 return 0;
00595 if((unsigned long)p2 & (HEAP_MAX_SIZE-1)) {
00596 munmap(p2, HEAP_MAX_SIZE);
00597 return 0;
00598 }
00599 }
00600 if(mprotect(p2, size, PROT_READ|PROT_WRITE) != 0) {
00601 munmap(p2, HEAP_MAX_SIZE);
00602 return 0;
00603 }
00604 h = (heap_info *)p2;
00605 h->size = size;
00606 THREAD_STAT(stat_n_heaps++);
00607 return h;
00608 }
00609
00610
00611
00612
00613 static int
00614 #if __STD_C
00615 grow_heap(heap_info *h, long diff)
00616 #else
00617 grow_heap(h, diff) heap_info *h; long diff;
00618 #endif
00619 {
00620 size_t page_mask = malloc_getpagesize - 1;
00621 long new_size;
00622
00623 if(diff >= 0) {
00624 diff = (diff + page_mask) & ~page_mask;
00625 new_size = (long)h->size + diff;
00626 if(new_size > HEAP_MAX_SIZE)
00627 return -1;
00628 if(mprotect((char *)h + h->size, diff, PROT_READ|PROT_WRITE) != 0)
00629 return -2;
00630 } else {
00631 new_size = (long)h->size + diff;
00632 if(new_size < (long)sizeof(*h))
00633 return -1;
00634
00635
00636 if((char *)MMAP((char *)h + new_size, -diff, PROT_NONE,
00637 MAP_PRIVATE|MAP_FIXED) == (char *) MAP_FAILED)
00638 return -2;
00639
00640 }
00641 h->size = new_size;
00642 return 0;
00643 }
00644
00645
00646
00647 #define delete_heap(heap) munmap((char*)(heap), HEAP_MAX_SIZE)
00648
00649 static int
00650 internal_function
00651 #if __STD_C
00652 heap_trim(heap_info *heap, size_t pad)
00653 #else
00654 heap_trim(heap, pad) heap_info *heap; size_t pad;
00655 #endif
00656 {
00657 mstate ar_ptr = heap->ar_ptr;
00658 unsigned long pagesz = mp_.pagesize;
00659 mchunkptr top_chunk = top(ar_ptr), p, bck, fwd;
00660 heap_info *prev_heap;
00661 long new_size, top_size, extra;
00662
00663
00664 while(top_chunk == chunk_at_offset(heap, sizeof(*heap))) {
00665 prev_heap = heap->prev;
00666 p = chunk_at_offset(prev_heap, prev_heap->size - (MINSIZE-2*SIZE_SZ));
00667 assert(p->size == (0|PREV_INUSE));
00668 p = prev_chunk(p);
00669 new_size = chunksize(p) + (MINSIZE-2*SIZE_SZ);
00670 assert(new_size>0 && new_size<(long)(2*MINSIZE));
00671 if(!prev_inuse(p))
00672 new_size += p->prev_size;
00673 assert(new_size>0 && new_size<HEAP_MAX_SIZE);
00674 if(new_size + (HEAP_MAX_SIZE - prev_heap->size) < pad + MINSIZE + pagesz)
00675 break;
00676 ar_ptr->system_mem -= heap->size;
00677 arena_mem -= heap->size;
00678 delete_heap(heap);
00679 heap = prev_heap;
00680 if(!prev_inuse(p)) {
00681 p = prev_chunk(p);
00682 unlink(p, bck, fwd);
00683 }
00684 assert(((unsigned long)((char*)p + new_size) & (pagesz-1)) == 0);
00685 assert( ((char*)p + new_size) == ((char*)heap + heap->size) );
00686 top(ar_ptr) = top_chunk = p;
00687 set_head(top_chunk, new_size | PREV_INUSE);
00688
00689 }
00690 top_size = chunksize(top_chunk);
00691 extra = ((top_size - pad - MINSIZE + (pagesz-1))/pagesz - 1) * pagesz;
00692 if(extra < (long)pagesz)
00693 return 0;
00694
00695 if(grow_heap(heap, -extra) != 0)
00696 return 0;
00697 ar_ptr->system_mem -= extra;
00698 arena_mem -= extra;
00699
00700
00701 set_head(top_chunk, (top_size - extra) | PREV_INUSE);
00702
00703 return 1;
00704 }
00705
00706 static mstate
00707 internal_function
00708 #if __STD_C
00709 arena_get2(mstate a_tsd, size_t size)
00710 #else
00711 arena_get2(a_tsd, size) mstate a_tsd; size_t size;
00712 #endif
00713 {
00714 mstate a;
00715
00716 if(!a_tsd)
00717 a = a_tsd = &main_arena;
00718 else {
00719 a = a_tsd->next;
00720 if(!a) {
00721
00722 (void)mutex_lock(&main_arena.mutex);
00723 THREAD_STAT(++(main_arena.stat_lock_wait));
00724 return &main_arena;
00725 }
00726 }
00727
00728
00729 repeat:
00730 do {
00731 if(!mutex_trylock(&a->mutex)) {
00732 THREAD_STAT(++(a->stat_lock_loop));
00733 tsd_setspecific(arena_key, (Void_t *)a);
00734 return a;
00735 }
00736 a = a->next;
00737 } while(a != a_tsd);
00738
00739
00740
00741
00742
00743 if(mutex_trylock(&list_lock)) {
00744 a = a_tsd;
00745 goto repeat;
00746 }
00747 (void)mutex_unlock(&list_lock);
00748
00749
00750 a = _int_new_arena(size);
00751 if(!a)
00752 return 0;
00753
00754 tsd_setspecific(arena_key, (Void_t *)a);
00755 mutex_init(&a->mutex);
00756 mutex_lock(&a->mutex);
00757
00758
00759 (void)mutex_lock(&list_lock);
00760 a->next = main_arena.next;
00761 main_arena.next = a;
00762 (void)mutex_unlock(&list_lock);
00763
00764 THREAD_STAT(++(a->stat_lock_loop));
00765 return a;
00766 }
00767
00768
00769
00770 mstate
00771 _int_new_arena(size_t size)
00772 {
00773 mstate a;
00774 heap_info *h;
00775 char *ptr;
00776 unsigned long misalign;
00777
00778 h = new_heap(size + (sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT),
00779 mp_.top_pad);
00780 if(!h) {
00781
00782
00783
00784 h = new_heap(sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT, mp_.top_pad);
00785 if(!h)
00786 return 0;
00787 }
00788 a = h->ar_ptr = (mstate)(h+1);
00789 malloc_init_state(a);
00790
00791 a->system_mem = a->max_system_mem = h->size;
00792 arena_mem += h->size;
00793 #ifdef NO_THREADS
00794 if((unsigned long)(mp_.mmapped_mem + arena_mem + main_arena.system_mem) >
00795 mp_.max_total_mem)
00796 mp_.max_total_mem = mp_.mmapped_mem + arena_mem + main_arena.system_mem;
00797 #endif
00798
00799
00800 ptr = (char *)(a + 1);
00801 misalign = (unsigned long)chunk2mem(ptr) & MALLOC_ALIGN_MASK;
00802 if (misalign > 0)
00803 ptr += MALLOC_ALIGNMENT - misalign;
00804 top(a) = (mchunkptr)ptr;
00805 set_head(top(a), (((char*)h + h->size) - ptr) | PREV_INUSE);
00806
00807 return a;
00808 }
00809
00810 #endif
00811
00812
00813
00814
00815
00816