2 This is a version (aka dlmalloc) of malloc/free/realloc written by
3 Doug Lea and released to the public domain, as explained at
4 http://creativecommons.org/publicdomain/zero/1.0/ Send questions,
5 comments, complaints, performance data, etc to dl@cs.oswego.edu
8 #include <vppinfra/dlmalloc.h>
10 /*------------------------------ internal #includes ---------------------- */
13 #pragma warning( disable : 4146 ) /* no "unsigned" warnings */
16 #include <stdio.h> /* for printing in malloc_stats */
17 #endif /* NO_MALLOC_STATS */
19 #include <errno.h> /* for MALLOC_FAILURE_ACTION */
20 #endif /* LACKS_ERRNO_H */
22 #if DLM_ABORT_ON_ASSERT_FAILURE
24 #define assert(x) if(!(x)) DLM_ABORT
25 #else /* DLM_ABORT_ON_ASSERT_FAILURE */
27 #endif /* DLM_ABORT_ON_ASSERT_FAILURE */
34 #if !defined(WIN32) && !defined(LACKS_TIME_H)
35 #include <time.h> /* for magic initialization */
37 #ifndef LACKS_STDLIB_H
38 #include <stdlib.h> /* for abort() */
39 #endif /* LACKS_STDLIB_H */
40 #ifndef LACKS_STRING_H
41 #include <string.h> /* for memset etc */
42 #endif /* LACKS_STRING_H */
44 #ifndef LACKS_STRINGS_H
45 #include <strings.h> /* for ffs */
46 #endif /* LACKS_STRINGS_H */
47 #endif /* USE_BUILTIN_FFS */
49 #ifndef LACKS_SYS_MMAN_H
50 /* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */
51 #if (defined(linux) && !defined(__USE_GNU))
53 #include <sys/mman.h> /* for mmap */
56 #include <sys/mman.h> /* for mmap */
58 #endif /* LACKS_SYS_MMAN_H */
61 #endif /* LACKS_FCNTL_H */
62 #endif /* HAVE_MMAP */
63 #ifndef LACKS_UNISTD_H
64 #include <unistd.h> /* for sbrk, sysconf */
65 #else /* LACKS_UNISTD_H */
66 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
67 extern void* sbrk(ptrdiff_t);
68 #endif /* FreeBSD etc */
69 #endif /* LACKS_UNISTD_H */
71 /* Declarations for locking */
74 #if defined (__SVR4) && defined (__sun) /* solaris */
76 #elif !defined(LACKS_SCHED_H)
78 #endif /* solaris or LACKS_SCHED_H */
79 #if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS
81 #endif /* USE_RECURSIVE_LOCKS ... */
82 #elif defined(_MSC_VER)
84 /* These are already defined on AMD64 builds */
87 #endif /* __cplusplus */
88 LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp);
89 LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value);
92 #endif /* __cplusplus */
94 #pragma intrinsic (_InterlockedCompareExchange)
95 #pragma intrinsic (_InterlockedExchange)
96 #define interlockedcompareexchange _InterlockedCompareExchange
97 #define interlockedexchange _InterlockedExchange
98 #elif defined(WIN32) && defined(__GNUC__)
99 #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
100 #define interlockedexchange __sync_lock_test_and_set
102 #else /* USE_LOCKS */
103 #endif /* USE_LOCKS */
106 #define LOCK_AT_FORK 0
109 /* Declarations for bit scanning on win32 */
110 #if defined(_MSC_VER) && _MSC_VER>=1300
111 #ifndef BitScanForward /* Try to avoid pulling in WinNT.h */
114 #endif /* __cplusplus */
115 unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
116 unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
119 #endif /* __cplusplus */
121 #define BitScanForward _BitScanForward
122 #define BitScanReverse _BitScanReverse
123 #pragma intrinsic(_BitScanForward)
124 #pragma intrinsic(_BitScanReverse)
125 #endif /* BitScanForward */
126 #endif /* defined(_MSC_VER) && _MSC_VER>=1300 */
129 #ifndef malloc_getpagesize
130 # ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
131 # ifndef _SC_PAGE_SIZE
132 # define _SC_PAGE_SIZE _SC_PAGESIZE
135 # ifdef _SC_PAGE_SIZE
136 # define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
138 # if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
139 extern size_t getpagesize();
140 # define malloc_getpagesize getpagesize()
142 # ifdef WIN32 /* use supplied emulation of getpagesize */
143 # define malloc_getpagesize getpagesize()
145 # ifndef LACKS_SYS_PARAM_H
146 # include <sys/param.h>
148 # ifdef EXEC_PAGESIZE
149 # define malloc_getpagesize EXEC_PAGESIZE
153 # define malloc_getpagesize NBPG
155 # define malloc_getpagesize (NBPG * CLSIZE)
159 # define malloc_getpagesize NBPC
162 # define malloc_getpagesize PAGESIZE
163 # else /* just guess */
164 # define malloc_getpagesize ((size_t)4096U)
175 /* ------------------- size_t and alignment properties -------------------- */
177 /* The byte and bit size of a size_t */
178 #define SIZE_T_SIZE (sizeof(size_t))
179 #define SIZE_T_BITSIZE (sizeof(size_t) << 3)
181 /* Some constants coerced to size_t */
182 /* Annoying but necessary to avoid errors on some platforms */
183 #define SIZE_T_ZERO ((size_t)0)
184 #define SIZE_T_ONE ((size_t)1)
185 #define SIZE_T_TWO ((size_t)2)
186 #define SIZE_T_FOUR ((size_t)4)
187 #define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
188 #define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
189 #define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
190 #define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
192 /* The bit mask value corresponding to MALLOC_ALIGNMENT */
193 #define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
195 /* True if address a has acceptable alignment */
196 #define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
198 /* the number of bytes to offset an address to align it */
199 #define align_offset(A)\
200 ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
201 ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
203 /* -------------------------- MMAP preliminaries ------------------------- */
206 If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
207 checks to fail so compiler optimizer can delete code rather than
208 using so many "#if"s.
212 /* MORECORE and MMAP must return MFAIL on failure */
213 #define MFAIL ((void*)(MAX_SIZE_T))
214 #define CMFAIL ((char*)(MFAIL)) /* defined for convenience */
219 #define MUNMAP_DEFAULT(a, s) munmap((a), (s))
220 #define MMAP_PROT (PROT_READ|PROT_WRITE)
221 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
222 #define MAP_ANONYMOUS MAP_ANON
223 #endif /* MAP_ANON */
225 #define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
226 #define MMAP_DEFAULT(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
227 #else /* MAP_ANONYMOUS */
229 Nearly all versions of mmap support MAP_ANONYMOUS, so the following
230 is unlikely to be needed, but is supplied just in case.
232 #define MMAP_FLAGS (MAP_PRIVATE)
233 static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
234 #define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \
235 (dev_zero_fd = open("/dev/zero", O_RDWR), \
236 mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
237 mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
238 #endif /* MAP_ANONYMOUS */
240 #define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s)
244 /* Win32 MMAP via VirtualAlloc */
245 static FORCEINLINE void* win32mmap(size_t size) {
246 void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
247 return (ptr != 0)? ptr: MFAIL;
250 /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
251 static FORCEINLINE void* win32direct_mmap(size_t size) {
252 void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
254 return (ptr != 0)? ptr: MFAIL;
257 /* This function supports releasing coalesed segments */
258 static FORCEINLINE int win32munmap(void* ptr, size_t size) {
259 MEMORY_BASIC_INFORMATION minfo;
260 char* cptr = (char*)ptr;
262 if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
264 if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
265 minfo.State != MEM_COMMIT || minfo.RegionSize > size)
267 if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
269 cptr += minfo.RegionSize;
270 size -= minfo.RegionSize;
275 #define MMAP_DEFAULT(s) win32mmap(s)
276 #define MUNMAP_DEFAULT(a, s) win32munmap((a), (s))
277 #define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s)
279 #endif /* HAVE_MMAP */
283 #define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
285 #endif /* HAVE_MREMAP */
288 * Define CALL_MORECORE
292 #define CALL_MORECORE(S) MORECORE(S)
294 #define CALL_MORECORE(S) MORECORE_DEFAULT(S)
295 #endif /* MORECORE */
296 #else /* HAVE_MORECORE */
297 #define CALL_MORECORE(S) MFAIL
298 #endif /* HAVE_MORECORE */
301 * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP
304 #define USE_MMAP_BIT (SIZE_T_ONE)
307 #define CALL_MMAP(s) MMAP(s)
309 #define CALL_MMAP(s) MMAP_DEFAULT(s)
312 #define CALL_MUNMAP(a, s) MUNMAP((a), (s))
314 #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s))
317 #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s)
318 #else /* DIRECT_MMAP */
319 #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s)
320 #endif /* DIRECT_MMAP */
321 #else /* HAVE_MMAP */
322 #define USE_MMAP_BIT (SIZE_T_ZERO)
324 #define MMAP(s) MFAIL
325 #define MUNMAP(a, s) (-1)
326 #define DIRECT_MMAP(s) MFAIL
327 #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s)
328 #define CALL_MMAP(s) MMAP(s)
329 #define CALL_MUNMAP(a, s) MUNMAP((a), (s))
330 #endif /* HAVE_MMAP */
335 #if HAVE_MMAP && HAVE_MREMAP
337 #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv))
339 #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv))
341 #else /* HAVE_MMAP && HAVE_MREMAP */
342 #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
343 #endif /* HAVE_MMAP && HAVE_MREMAP */
345 /* mstate bit set if continguous morecore disabled or failed */
346 #define USE_NONCONTIGUOUS_BIT (4U)
348 /* mstate bit set if no expansion allowed */
349 #define USE_NOEXPAND_BIT (8U)
351 /* trace allocations if set */
352 #define USE_TRACE_BIT (16U)
354 /* segment bit set in create_mspace_with_base */
355 #define EXTERN_BIT (8U)
358 /* --------------------------- Lock preliminaries ------------------------ */
361 When locks are defined, there is one global lock, plus
364 The global lock_ensures that mparams.magic and other unique
365 mparams values are initialized only once. It also protects
366 sequences of calls to MORECORE. In many cases sys_alloc requires
367 two calls, that should not be interleaved with calls by other
368 threads. This does not protect against direct calls to MORECORE
369 by other threads not using this lock, so there is still code to
370 cope the best we can on interference.
372 Per-mspace locks surround calls to malloc, free, etc.
373 By default, locks are simple non-reentrant mutexes.
375 Because lock-protected regions generally have bounded times, it is
376 OK to use the supplied simple spinlocks. Spinlocks are likely to
377 improve performance for lightly contended applications, but worsen
378 performance under heavy contention.
380 If USE_LOCKS is > 1, the definitions of lock routines here are
381 bypassed, in which case you will need to define the type MLOCK_T,
382 and at least INITIAL_LOCK, DESTROY_LOCK, ACQUIRE_LOCK, RELEASE_LOCK
383 and TRY_LOCK. You must also declare a
384 static MLOCK_T malloc_global_mutex = { initialization values };.
389 #define USE_LOCK_BIT (0U)
390 #define INITIAL_LOCK(l) (0)
391 #define DESTROY_LOCK(l) (0)
392 #define ACQUIRE_MALLOC_GLOBAL_LOCK()
393 #define RELEASE_MALLOC_GLOBAL_LOCK()
397 /* ----------------------- User-defined locks ------------------------ */
398 /* Define your own lock implementation here */
399 /* #define INITIAL_LOCK(lk) ... */
400 /* #define DESTROY_LOCK(lk) ... */
401 /* #define ACQUIRE_LOCK(lk) ... */
402 /* #define RELEASE_LOCK(lk) ... */
403 /* #define TRY_LOCK(lk) ... */
404 /* static MLOCK_T malloc_global_mutex = ... */
408 /* First, define CAS_LOCK and CLEAR_LOCK on ints */
409 /* Note CAS_LOCK defined to return 0 on success */
411 #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
412 #define CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
413 #define CLEAR_LOCK(sl) __sync_lock_release(sl)
415 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
416 /* Custom spin locks for older gcc on x86 */
417 static FORCEINLINE int x86_cas_lock(int *sl) {
421 __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
423 : "r" (val), "m" (*(sl)), "0"(cmp)
428 static FORCEINLINE void x86_clear_lock(int* sl) {
432 __asm__ __volatile__ ("lock; xchgl %0, %1"
434 : "m" (*(sl)), "0"(prev)
438 #define CAS_LOCK(sl) x86_cas_lock(sl)
439 #define CLEAR_LOCK(sl) x86_clear_lock(sl)
441 #else /* Win32 MSC */
442 #define CAS_LOCK(sl) interlockedexchange(sl, (LONG)1)
443 #define CLEAR_LOCK(sl) interlockedexchange (sl, (LONG)0)
445 #endif /* ... gcc spins locks ... */
447 /* How to yield for a spin lock */
448 #define SPINS_PER_YIELD 63
449 #if defined(_MSC_VER)
450 #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
451 #define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE)
452 #elif defined (__SVR4) && defined (__sun) /* solaris */
453 #define SPIN_LOCK_YIELD thr_yield();
454 #elif !defined(LACKS_SCHED_H)
455 #define SPIN_LOCK_YIELD sched_yield();
457 #define SPIN_LOCK_YIELD
458 #endif /* ... yield ... */
460 #if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0
461 /* Plain spin locks use single word (embedded in malloc_states) */
462 static int spin_acquire_lock(int *sl) {
464 while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) {
465 if ((++spins & SPINS_PER_YIELD) == 0) {
473 #define TRY_LOCK(sl) !CAS_LOCK(sl)
474 #define RELEASE_LOCK(sl) CLEAR_LOCK(sl)
475 #define ACQUIRE_LOCK(sl) (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0)
476 #define INITIAL_LOCK(sl) (*sl = 0)
477 #define DESTROY_LOCK(sl) (0)
478 static MLOCK_T malloc_global_mutex = 0;
480 #else /* USE_RECURSIVE_LOCKS */
481 /* types for lock owners */
483 #define THREAD_ID_T DWORD
484 #define CURRENT_THREAD GetCurrentThreadId()
485 #define EQ_OWNER(X,Y) ((X) == (Y))
488 Note: the following assume that pthread_t is a type that can be
489 initialized to (casted) zero. If this is not the case, you will need to
490 somehow redefine these or not use spin locks.
492 #define THREAD_ID_T pthread_t
493 #define CURRENT_THREAD pthread_self()
494 #define EQ_OWNER(X,Y) pthread_equal(X, Y)
497 struct malloc_recursive_lock {
500 THREAD_ID_T threadid;
503 #define MLOCK_T struct malloc_recursive_lock
504 static MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0};
506 static FORCEINLINE void recursive_release_lock(MLOCK_T *lk) {
513 static FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) {
514 THREAD_ID_T mythreadid = CURRENT_THREAD;
517 if (*((volatile int *)(&lk->sl)) == 0) {
518 if (!CAS_LOCK(&lk->sl)) {
519 lk->threadid = mythreadid;
524 else if (EQ_OWNER(lk->threadid, mythreadid)) {
528 if ((++spins & SPINS_PER_YIELD) == 0) {
534 static FORCEINLINE int recursive_try_lock(MLOCK_T *lk) {
535 THREAD_ID_T mythreadid = CURRENT_THREAD;
536 if (*((volatile int *)(&lk->sl)) == 0) {
537 if (!CAS_LOCK(&lk->sl)) {
538 lk->threadid = mythreadid;
543 else if (EQ_OWNER(lk->threadid, mythreadid)) {
550 #define RELEASE_LOCK(lk) recursive_release_lock(lk)
551 #define TRY_LOCK(lk) recursive_try_lock(lk)
552 #define ACQUIRE_LOCK(lk) recursive_acquire_lock(lk)
553 #define INITIAL_LOCK(lk) ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0)
554 #define DESTROY_LOCK(lk) (0)
555 #endif /* USE_RECURSIVE_LOCKS */
557 #elif defined(WIN32) /* Win32 critical sections */
558 #define MLOCK_T CRITICAL_SECTION
559 #define ACQUIRE_LOCK(lk) (EnterCriticalSection(lk), 0)
560 #define RELEASE_LOCK(lk) LeaveCriticalSection(lk)
561 #define TRY_LOCK(lk) TryEnterCriticalSection(lk)
562 #define INITIAL_LOCK(lk) (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000))
563 #define DESTROY_LOCK(lk) (DeleteCriticalSection(lk), 0)
564 #define NEED_GLOBAL_LOCK_INIT
566 static MLOCK_T malloc_global_mutex;
567 static volatile LONG malloc_global_mutex_status;
569 /* Use spin loop to initialize global lock */
570 static void init_malloc_global_mutex() {
572 long stat = malloc_global_mutex_status;
575 /* transition to < 0 while initializing, then to > 0) */
577 interlockedcompareexchange(&malloc_global_mutex_status, (LONG)-1, (LONG)0) == 0) {
578 InitializeCriticalSection(&malloc_global_mutex);
579 interlockedexchange(&malloc_global_mutex_status, (LONG)1);
586 #else /* pthreads-based locks */
587 #define MLOCK_T pthread_mutex_t
588 #define ACQUIRE_LOCK(lk) pthread_mutex_lock(lk)
589 #define RELEASE_LOCK(lk) pthread_mutex_unlock(lk)
590 #define TRY_LOCK(lk) (!pthread_mutex_trylock(lk))
591 #define INITIAL_LOCK(lk) pthread_init_lock(lk)
592 #define DESTROY_LOCK(lk) pthread_mutex_destroy(lk)
594 #if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE)
595 /* Cope with old-style linux recursive lock initialization by adding */
596 /* skipped internal declaration from pthread.h */
597 extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr,
599 #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
600 #define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y)
601 #endif /* USE_RECURSIVE_LOCKS ... */
603 static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER;
605 static int pthread_init_lock (MLOCK_T *lk) {
606 pthread_mutexattr_t attr;
607 if (pthread_mutexattr_init(&attr)) return 1;
608 #if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0
609 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1;
611 if (pthread_mutex_init(lk, &attr)) return 1;
612 if (pthread_mutexattr_destroy(&attr)) return 1;
616 #endif /* ... lock types ... */
618 /* Common code for all lock types */
619 #define USE_LOCK_BIT (2U)
621 #ifndef ACQUIRE_MALLOC_GLOBAL_LOCK
622 #define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex);
625 #ifndef RELEASE_MALLOC_GLOBAL_LOCK
626 #define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex);
629 #endif /* USE_LOCKS */
631 /* ----------------------- Chunk representations ------------------------ */
634 (The following includes lightly edited explanations by Colin Plumb.)
636 The malloc_chunk declaration below is misleading (but accurate and
637 necessary). It declares a "view" into memory allowing access to
638 necessary fields at known offsets from a given base.
640 Chunks of memory are maintained using a `boundary tag' method as
641 originally described by Knuth. (See the paper by Paul Wilson
642 ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
643 techniques.) Sizes of free chunks are stored both in the front of
644 each chunk and at the end. This makes consolidating fragmented
645 chunks into bigger chunks fast. The head fields also hold bits
646 representing whether chunks are free or in use.
648 Here are some pictures to make it clearer. They are "exploded" to
649 show that the state of a chunk can be thought of as extending from
650 the high 31 bits of the head field of its header through the
651 prev_foot and PINUSE_BIT bit of the following chunk header.
653 A chunk that's in use looks like:
655 chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
656 | Size of previous chunk (if P = 0) |
657 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
658 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
659 | Size of this chunk 1| +-+
660 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
666 +- size - sizeof(size_t) available payload bytes -+
670 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
671 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
672 | Size of next chunk (may or may not be in use) | +-+
673 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
675 And if it's free, it looks like this:
678 | User payload (must be in use, or we would have merged!) |
679 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
680 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
681 | Size of this chunk 0| +-+
682 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
684 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
686 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
688 +- size - sizeof(struct chunk) unused bytes -+
690 chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
691 | Size of this chunk |
692 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
693 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
694 | Size of next chunk (must be in use, or we would have merged)| +-+
695 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
699 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
702 Note that since we always merge adjacent free chunks, the chunks
703 adjacent to a free chunk must be in use.
705 Given a pointer to a chunk (which can be derived trivially from the
706 payload pointer) we can, in O(1) time, find out whether the adjacent
707 chunks are free, and if so, unlink them from the lists that they
708 are on and merge them with the current chunk.
710 Chunks always begin on even word boundaries, so the mem portion
711 (which is returned to the user) is also on an even word boundary, and
712 thus at least double-word aligned.
714 The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
715 chunk size (which is always a multiple of two words), is an in-use
716 bit for the *previous* chunk. If that bit is *clear*, then the
717 word before the current chunk size contains the previous chunk
718 size, and can be used to find the front of the previous chunk.
719 The very first chunk allocated always has this bit set, preventing
720 access to non-existent (or non-owned) memory. If pinuse is set for
721 any given chunk, then you CANNOT determine the size of the
722 previous chunk, and might even get a memory addressing fault when
725 The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
726 the chunk size redundantly records whether the current chunk is
727 inuse (unless the chunk is mmapped). This redundancy enables usage
728 checks within free and realloc, and reduces indirection when freeing
729 and consolidating chunks.
731 Each freshly allocated chunk must have both cinuse and pinuse set.
732 That is, each allocated chunk borders either a previously allocated
733 and still in-use chunk, or the base of its memory arena. This is
734 ensured by making all allocations from the `lowest' part of any
735 found chunk. Further, no free chunk physically borders another one,
736 so each free chunk is known to be preceded and followed by either
737 inuse chunks or the ends of memory.
739 Note that the `foot' of the current chunk is actually represented
740 as the prev_foot of the NEXT chunk. This makes it easier to
741 deal with alignments etc but can be very confusing when trying
742 to extend or adapt this code.
744 The exceptions to all this are
746 1. The special chunk `top' is the top-most available chunk (i.e.,
747 the one bordering the end of available memory). It is treated
748 specially. Top is never included in any bin, is used only if
749 no other chunk is available, and is released back to the
750 system if it is very large (see M_TRIM_THRESHOLD). In effect,
751 the top chunk is treated as larger (and thus less well
752 fitting) than any other available chunk. The top chunk
753 doesn't update its trailing size field since there is no next
754 contiguous chunk that would have to index off it. However,
755 space is still allocated for it (TOP_FOOT_SIZE) to enable
756 separation or merging when space is extended.
758 3. Chunks allocated via mmap, have both cinuse and pinuse bits
759 cleared in their head fields. Because they are allocated
760 one-by-one, each must carry its own prev_foot field, which is
761 also used to hold the offset this chunk has within its mmapped
762 region, which is needed to preserve alignment. Each mmapped
763 chunk is trailed by the first two fields of a fake next-chunk
764 for sake of usage checks.
768 struct malloc_chunk {
769 size_t prev_foot; /* Size of previous chunk (if free). */
770 size_t head; /* Size and inuse bits. */
771 struct malloc_chunk* fd; /* double links -- used only if free. */
772 struct malloc_chunk* bk;
775 typedef struct malloc_chunk mchunk;
776 typedef struct malloc_chunk* mchunkptr;
777 typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
778 typedef unsigned int bindex_t; /* Described below */
779 typedef unsigned int binmap_t; /* Described below */
780 typedef unsigned int flag_t; /* The type of various bit flag sets */
782 /* ------------------- Chunks sizes and alignments ----------------------- */
784 #define MCHUNK_SIZE (sizeof(mchunk))
787 #define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
789 #define CHUNK_OVERHEAD (SIZE_T_SIZE)
792 /* MMapped chunks need a second word of overhead ... */
793 #define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
794 /* ... and additional padding for fake next-chunk at foot */
795 #define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
797 /* The smallest size we can malloc is an aligned minimal chunk */
798 #define MIN_CHUNK_SIZE\
799 ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
801 /* conversion from malloc headers to user pointers, and back */
802 #define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES))
803 #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
804 /* chunk associated with aligned address A */
805 #define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
807 /* Bounds on request (not chunk) sizes. */
808 #define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
809 #define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
811 /* pad request bytes into a usable size */
812 #define pad_request(req) \
813 (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
815 /* pad request, checking for minimum (but not maximum) */
816 #define request2size(req) \
817 (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
820 /* ------------------ Operations on head and foot fields ----------------- */
823 The head field of a chunk is or'ed with PINUSE_BIT when previous
824 adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
825 use, unless mmapped, in which case both bits are cleared.
827 FLAG4_BIT is not used by this malloc, but might be useful in extensions.
830 #define PINUSE_BIT (SIZE_T_ONE)
831 #define CINUSE_BIT (SIZE_T_TWO)
832 #define FLAG4_BIT (SIZE_T_FOUR)
833 #define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
834 #define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT)
836 /* Head value for fenceposts */
837 #define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
839 /* extraction of fields from head words */
840 #define cinuse(p) ((p)->head & CINUSE_BIT)
841 #define pinuse(p) ((p)->head & PINUSE_BIT)
842 #define flag4inuse(p) ((p)->head & FLAG4_BIT)
843 #define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT)
844 #define is_mmapped(p) (((p)->head & INUSE_BITS) == 0)
846 #define chunksize(p) ((p)->head & ~(FLAG_BITS))
848 #define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
849 #define set_flag4(p) ((p)->head |= FLAG4_BIT)
850 #define clear_flag4(p) ((p)->head &= ~FLAG4_BIT)
852 /* Treat space at ptr +/- offset as a chunk */
853 #define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
854 #define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
856 /* Ptr to next or previous physical malloc_chunk. */
857 #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS)))
858 #define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
860 /* extract next chunk's pinuse bit */
861 #define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
863 /* Get/set size at footer */
864 #define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
865 #define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
867 /* Set size, pinuse bit, and foot */
868 #define set_size_and_pinuse_of_free_chunk(p, s)\
869 ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
871 /* Set size, pinuse bit, foot, and clear next pinuse */
872 #define set_free_with_pinuse(p, s, n)\
873 (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
875 /* Get the internal overhead associated with chunk p */
876 #define overhead_for(p)\
877 (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
879 /* Return true if malloced space is not necessarily cleared */
881 #define calloc_must_clear(p) (!is_mmapped(p))
882 #else /* MMAP_CLEARS */
883 #define calloc_must_clear(p) (1)
884 #endif /* MMAP_CLEARS */
886 /* ---------------------- Overlaid data structures ----------------------- */
889 When chunks are not in use, they are treated as nodes of either
892 "Small" chunks are stored in circular doubly-linked lists, and look
895 chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
896 | Size of previous chunk |
897 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
898 `head:' | Size of chunk, in bytes |P|
899 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
900 | Forward pointer to next chunk in list |
901 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
902 | Back pointer to previous chunk in list |
903 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
904 | Unused space (may be 0 bytes long) .
907 nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
908 `foot:' | Size of chunk, in bytes |
909 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911 Larger chunks are kept in a form of bitwise digital trees (aka
912 tries) keyed on chunksizes. Because malloc_tree_chunks are only for
913 free chunks greater than 256 bytes, their size doesn't impose any
914 constraints on user chunk sizes. Each node looks like:
916 chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
917 | Size of previous chunk |
918 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
919 `head:' | Size of chunk, in bytes |P|
920 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
921 | Forward pointer to next chunk of same size |
922 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
923 | Back pointer to previous chunk of same size |
924 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
925 | Pointer to left child (child[0]) |
926 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
927 | Pointer to right child (child[1]) |
928 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
929 | Pointer to parent |
930 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
931 | bin index of this chunk |
932 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
935 nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
936 `foot:' | Size of chunk, in bytes |
937 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
939 Each tree holding treenodes is a tree of unique chunk sizes. Chunks
940 of the same size are arranged in a circularly-linked list, with only
941 the oldest chunk (the next to be used, in our FIFO ordering)
942 actually in the tree. (Tree members are distinguished by a non-null
943 parent pointer.) If a chunk with the same size an an existing node
944 is inserted, it is linked off the existing node using pointers that
945 work in the same way as fd/bk pointers of small chunks.
947 Each tree contains a power of 2 sized range of chunk sizes (the
948 smallest is 0x100 <= x < 0x180), which is is divided in half at each
949 tree level, with the chunks in the smaller half of the range (0x100
950 <= x < 0x140 for the top nose) in the left subtree and the larger
951 half (0x140 <= x < 0x180) in the right subtree. This is, of course,
952 done by inspecting individual bits.
954 Using these rules, each node's left subtree contains all smaller
955 sizes than its right subtree. However, the node at the root of each
956 subtree has no particular ordering relationship to either. (The
957 dividing line between the subtree sizes is based on trie relation.)
958 If we remove the last chunk of a given size from the interior of the
959 tree, we need to replace it with a leaf node. The tree ordering
960 rules permit a node to be replaced by any leaf below it.
962 The smallest chunk in a tree (a common operation in a best-fit
963 allocator) can be found by walking a path to the leftmost leaf in
964 the tree. Unlike a usual binary tree, where we follow left child
965 pointers until we reach a null, here we follow the right child
966 pointer any time the left one is null, until we reach a leaf with
967 both child pointers null. The smallest chunk in the tree will be
968 somewhere along that path.
970 The worst case number of steps to add, find, or remove a node is
971 bounded by the number of bits differentiating chunks within
972 bins. Under current bin calculations, this ranges from 6 up to 21
973 (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
974 is of course much better.
977 struct malloc_tree_chunk {
978 /* The first four fields must be compatible with malloc_chunk */
981 struct malloc_tree_chunk* fd;
982 struct malloc_tree_chunk* bk;
984 struct malloc_tree_chunk* child[2];
985 struct malloc_tree_chunk* parent;
989 typedef struct malloc_tree_chunk tchunk;
990 typedef struct malloc_tree_chunk* tchunkptr;
991 typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
993 /* A little helper macro for trees */
994 #define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
996 /* ----------------------------- Segments -------------------------------- */
999 Each malloc space may include non-contiguous segments, held in a
1000 list headed by an embedded malloc_segment record representing the
1001 top-most space. Segments also include flags holding properties of
1002 the space. Large chunks that are directly allocated by mmap are not
1003 included in this list. They are instead independently created and
1004 destroyed without otherwise keeping track of them.
1006 Segment management mainly comes into play for spaces allocated by
1007 MMAP. Any call to MMAP might or might not return memory that is
1008 adjacent to an existing segment. MORECORE normally contiguously
1009 extends the current space, so this space is almost always adjacent,
1010 which is simpler and faster to deal with. (This is why MORECORE is
1011 used preferentially to MMAP when both are available -- see
1012 sys_alloc.) When allocating using MMAP, we don't use any of the
1013 hinting mechanisms (inconsistently) supported in various
1014 implementations of unix mmap, or distinguish reserving from
1015 committing memory. Instead, we just ask for space, and exploit
1016 contiguity when we get it. It is probably possible to do
1017 better than this on some systems, but no general scheme seems
1018 to be significantly better.
1020 Management entails a simpler variant of the consolidation scheme
1021 used for chunks to reduce fragmentation -- new adjacent memory is
1022 normally prepended or appended to an existing segment. However,
1023 there are limitations compared to chunk consolidation that mostly
1024 reflect the fact that segment processing is relatively infrequent
1025 (occurring only when getting memory from system) and that we
1026 don't expect to have huge numbers of segments:
1028 * Segments are not indexed, so traversal requires linear scans. (It
1029 would be possible to index these, but is not worth the extra
1030 overhead and complexity for most programs on most platforms.)
1031 * New segments are only appended to old ones when holding top-most
1032 memory; if they cannot be prepended to others, they are held in
1035 Except for the top-most segment of an mstate, each segment record
1036 is kept at the tail of its segment. Segments are added by pushing
1037 segment records onto the list headed by &mstate.seg for the
1040 Segment flags control allocation/merge/deallocation policies:
1041 * If EXTERN_BIT set, then we did not allocate this segment,
1042 and so should not try to deallocate or merge with others.
1043 (This currently holds only for the initial segment passed
1044 into create_mspace_with_base.)
1045 * If USE_MMAP_BIT set, the segment may be merged with
1046 other surrounding mmapped segments and trimmed/de-allocated
1048 * If neither bit is set, then the segment was obtained using
1049 MORECORE so can be merged with surrounding MORECORE'd segments
1050 and deallocated/trimmed using MORECORE with negative arguments.
1053 struct malloc_segment {
1054 char* base; /* base address */
1055 size_t size; /* allocated size */
1056 struct malloc_segment* next; /* ptr to next segment */
1057 flag_t sflags; /* mmap and extern flag */
1060 #define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT)
1061 #define is_extern_segment(S) ((S)->sflags & EXTERN_BIT)
1063 typedef struct malloc_segment msegment;
1064 typedef struct malloc_segment* msegmentptr;
1066 /* ---------------------------- malloc_state ----------------------------- */
1069 A malloc_state holds all of the bookkeeping for a space.
1070 The main fields are:
1073 The topmost chunk of the currently active segment. Its size is
1074 cached in topsize. The actual size of topmost space is
1075 topsize+TOP_FOOT_SIZE, which includes space reserved for adding
1076 fenceposts and segment records if necessary when getting more
1077 space from the system. The size at which to autotrim top is
1078 cached from mparams in trim_check, except that it is disabled if
1081 Designated victim (dv)
1082 This is the preferred chunk for servicing small requests that
1083 don't have exact fits. It is normally the chunk split off most
1084 recently to service another small request. Its size is cached in
1085 dvsize. The link fields of this chunk are not maintained since it
1086 is not kept in a bin.
1089 An array of bin headers for free chunks. These bins hold chunks
1090 with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
1091 chunks of all the same size, spaced 8 bytes apart. To simplify
1092 use in double-linked lists, each bin header acts as a malloc_chunk
1093 pointing to the real first node, if it exists (else pointing to
1094 itself). This avoids special-casing for headers. But to avoid
1095 waste, we allocate only the fd/bk pointers of bins, and then use
1096 repositioning tricks to treat these as the fields of a chunk.
1099 Treebins are pointers to the roots of trees holding a range of
1100 sizes. There are 2 equally spaced treebins for each power of two
1101 from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
1105 There is one bit map for small bins ("smallmap") and one for
1106 treebins ("treemap). Each bin sets its bit when non-empty, and
1107 clears the bit when empty. Bit operations are then used to avoid
1108 bin-by-bin searching -- nearly all "search" is done without ever
1109 looking at bins that won't be selected. The bit maps
1110 conservatively use 32 bits per map word, even if on 64bit system.
1111 For a good description of some of the bit-based techniques used
1112 here, see Henry S. Warren Jr's book "Hacker's Delight" (and
1113 supplement at http://hackersdelight.org/). Many of these are
1114 intended to reduce the branchiness of paths through malloc etc, as
1115 well as to reduce the number of memory locations read or written.
1118 A list of segments headed by an embedded malloc_segment record
1119 representing the initial space.
1121 Address check support
1122 The least_addr field is the least address ever obtained from
1123 MORECORE or MMAP. Attempted frees and reallocs of any address less
1124 than this are trapped (unless INSECURE is defined).
1127 A cross-check field that should always hold same value as mparams.magic.
1129 Max allowed footprint
1130 The maximum allowed bytes to allocate from system (zero means no limit)
1133 Bits recording whether to use MMAP, locks, or contiguous MORECORE
1136 Each space keeps track of current and maximum system memory
1137 obtained via MORECORE or MMAP.
1140 Fields holding the amount of unused topmost memory that should trigger
1141 trimming, and a counter to force periodic scanning to release unused
1142 non-topmost segments.
1145 If USE_LOCKS is defined, the "mutex" lock is acquired and released
1146 around every public call using this mspace.
1149 A void* pointer and a size_t field that can be used to help implement
1150 extensions to this malloc.
1153 /* Bin types, widths and sizes */
1154 #define NSMALLBINS (32U)
1155 #define NTREEBINS (32U)
1156 #define SMALLBIN_SHIFT (3U)
1157 #define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
1158 #define TREEBIN_SHIFT (8U)
1159 #define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
1160 #define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
1161 #define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
1163 struct malloc_state {
1172 size_t release_checks;
1174 mchunkptr smallbins[(NSMALLBINS+1)*2];
1175 tbinptr treebins[NTREEBINS];
1177 size_t max_footprint;
1178 size_t footprint_limit; /* zero means no limit */
1181 MLOCK_T mutex; /* locate lock among fields that rarely change */
1182 #endif /* USE_LOCKS */
1184 void* extp; /* Unused but available for extensions */
1188 typedef struct malloc_state* mstate;
1190 /* ------------- Global malloc_state and malloc_params ------------------- */
1193 malloc_params holds global properties, including those that can be
1194 dynamically set using mallopt. There is a single instance, mparams,
1195 initialized in init_mparams. Note that the non-zeroness of "magic"
1196 also serves as an initialization flag.
1199 struct malloc_params {
1203 size_t mmap_threshold;
1204 size_t trim_threshold;
1205 flag_t default_mflags;
1208 static struct malloc_params mparams;
1210 /* Ensure mparams initialized */
1211 #define ensure_initialization() (void)(mparams.magic != 0 || init_mparams())
1215 /* The global malloc_state used for all non-"mspace" calls */
1216 static struct malloc_state _gm_;
1218 #define is_global(M) ((M) == &_gm_)
1220 #endif /* !ONLY_MSPACES */
1222 #define is_initialized(M) ((M)->top != 0)
1224 /* -------------------------- system alloc setup ------------------------- */
1226 /* Operations on mflags */
1228 #define use_lock(M) ((M)->mflags & USE_LOCK_BIT)
1229 #define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT)
1231 #define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT)
1233 #define disable_lock(M)
1236 #define use_mmap(M) ((M)->mflags & USE_MMAP_BIT)
1237 #define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT)
1239 #define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT)
1241 #define disable_mmap(M)
1244 #define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT)
1245 #define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT)
1246 #define use_noexpand(M) ((M)->mflags & USE_NOEXPAND_BIT)
1247 #define disable_expand(M) ((M)->mflags |= USE_NOEXPAND_BIT)
1248 #define use_trace(M) ((M)->mflags & USE_TRACE_BIT)
1249 #define enable_trace(M) ((M)->mflags |= USE_TRACE_BIT)
1250 #define disable_trace(M) ((M)->mflags |= USE_TRACE_BIT)
1252 #define set_lock(M,L)\
1253 ((M)->mflags = (L)?\
1254 ((M)->mflags | USE_LOCK_BIT) :\
1255 ((M)->mflags & ~USE_LOCK_BIT))
1257 /* page-align a size */
1258 #define page_align(S)\
1259 (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE))
1261 /* granularity-align a size */
1262 #define granularity_align(S)\
1263 (((S) + (mparams.granularity - SIZE_T_ONE))\
1264 & ~(mparams.granularity - SIZE_T_ONE))
1267 /* For mmap, use granularity alignment on windows, else page-align */
1269 #define mmap_align(S) granularity_align(S)
1271 #define mmap_align(S) page_align(S)
1274 /* For sys_alloc, enough padding to ensure can malloc request on success */
1275 #define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
1277 #define is_page_aligned(S)\
1278 (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
1279 #define is_granularity_aligned(S)\
1280 (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
1282 /* True if segment S holds address A */
1283 #define segment_holds(S, A)\
1284 ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
1286 /* Return segment holding given address */
1287 static msegmentptr segment_holding(mstate m, char* addr) {
1288 msegmentptr sp = &m->seg;
1290 if (addr >= sp->base && addr < sp->base + sp->size)
1292 if ((sp = sp->next) == 0)
1297 /* Return true if segment contains a segment link */
1298 static int has_segment_link(mstate m, msegmentptr ss) {
1299 msegmentptr sp = &m->seg;
1301 if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
1303 if ((sp = sp->next) == 0)
1308 #ifndef MORECORE_CANNOT_TRIM
1309 #define should_trim(M,s) ((s) > (M)->trim_check)
1310 #else /* MORECORE_CANNOT_TRIM */
1311 #define should_trim(M,s) (0)
1312 #endif /* MORECORE_CANNOT_TRIM */
1315 TOP_FOOT_SIZE is padding at the end of a segment, including space
1316 that may be needed to place segment records and fenceposts when new
1317 noncontiguous segments are added.
1319 #define TOP_FOOT_SIZE\
1320 (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
1323 /* ------------------------------- Hooks -------------------------------- */
1326 PREACTION should be defined to return 0 on success, and nonzero on
1327 failure. If you are not using locking, you can redefine these to do
1332 #define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
1333 #define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
1334 #else /* USE_LOCKS */
1337 #define PREACTION(M) (0)
1338 #endif /* PREACTION */
1341 #define POSTACTION(M)
1342 #endif /* POSTACTION */
1344 #endif /* USE_LOCKS */
1347 CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
1348 USAGE_ERROR_ACTION is triggered on detected bad frees and
1349 reallocs. The argument p is an address that might have triggered the
1350 fault. It is ignored by the two predefined actions, but might be
1351 useful in custom actions that try to help diagnose errors.
1354 #if PROCEED_ON_ERROR
1356 /* A count of the number of corruption errors causing resets */
1357 int malloc_corruption_error_count;
1359 /* default corruption action */
1360 static void reset_on_error(mstate m);
1362 #define CORRUPTION_ERROR_ACTION(m) reset_on_error(m)
1363 #define USAGE_ERROR_ACTION(m, p)
1365 #else /* PROCEED_ON_ERROR */
1367 #ifndef CORRUPTION_ERROR_ACTION
1368 #define CORRUPTION_ERROR_ACTION(m) DLM_ABORT
1369 #endif /* CORRUPTION_ERROR_ACTION */
1371 #ifndef USAGE_ERROR_ACTION
1372 #define USAGE_ERROR_ACTION(m,p) DLM_ABORT
1373 #endif /* USAGE_ERROR_ACTION */
1375 #endif /* PROCEED_ON_ERROR */
1378 /* -------------------------- Debugging setup ---------------------------- */
1382 #define check_free_chunk(M,P)
1383 #define check_inuse_chunk(M,P)
1384 #define check_malloced_chunk(M,P,N)
1385 #define check_mmapped_chunk(M,P)
1386 #define check_malloc_state(M)
1387 #define check_top_chunk(M,P)
1390 #define check_free_chunk(M,P) do_check_free_chunk(M,P)
1391 #define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P)
1392 #define check_top_chunk(M,P) do_check_top_chunk(M,P)
1393 #define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
1394 #define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P)
1395 #define check_malloc_state(M) do_check_malloc_state(M)
1397 static void do_check_any_chunk(mstate m, mchunkptr p);
1398 static void do_check_top_chunk(mstate m, mchunkptr p);
1399 static void do_check_mmapped_chunk(mstate m, mchunkptr p);
1400 static void do_check_inuse_chunk(mstate m, mchunkptr p);
1401 static void do_check_free_chunk(mstate m, mchunkptr p);
1402 static void do_check_malloced_chunk(mstate m, void* mem, size_t s);
1403 static void do_check_tree(mstate m, tchunkptr t);
1404 static void do_check_treebin(mstate m, bindex_t i);
1405 static void do_check_smallbin(mstate m, bindex_t i);
1406 static void do_check_malloc_state(mstate m);
1407 static int bin_find(mstate m, mchunkptr x);
1408 static size_t traverse_and_check(mstate m);
1411 /* ---------------------------- Indexing Bins ---------------------------- */
1413 #define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
1414 #define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT)
1415 #define small_index2size(i) ((i) << SMALLBIN_SHIFT)
1416 #define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
1418 /* addressing by index. See above about smallbin repositioning */
1419 #define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
1420 #define treebin_at(M,i) (&((M)->treebins[i]))
1422 /* assign tree index for size S to variable I. Use x86 asm if possible */
1423 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1424 #define compute_tree_index(S, I)\
1426 unsigned int X = S >> TREEBIN_SHIFT;\
1429 else if (X > 0xFFFF)\
1432 unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \
1433 I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
1437 #elif defined (__INTEL_COMPILER)
1438 #define compute_tree_index(S, I)\
1440 size_t X = S >> TREEBIN_SHIFT;\
1443 else if (X > 0xFFFF)\
1446 unsigned int K = _bit_scan_reverse (X); \
1447 I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
1451 #elif defined(_MSC_VER) && _MSC_VER>=1300
1452 #define compute_tree_index(S, I)\
1454 size_t X = S >> TREEBIN_SHIFT;\
1457 else if (X > 0xFFFF)\
1461 _BitScanReverse((DWORD *) &K, (DWORD) X);\
1462 I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
1467 #define compute_tree_index(S, I)\
1469 size_t X = S >> TREEBIN_SHIFT;\
1472 else if (X > 0xFFFF)\
1475 unsigned int Y = (unsigned int)X;\
1476 unsigned int N = ((Y - 0x100) >> 16) & 8;\
1477 unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
1479 N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
1480 K = 14 - N + ((Y <<= K) >> 15);\
1481 I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
1486 /* Bit representing maximum resolved size in a treebin at i */
1487 #define bit_for_tree_index(i) \
1488 (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
1490 /* Shift placing maximum resolved bit in a treebin at i as sign bit */
1491 #define leftshift_for_tree_index(i) \
1492 ((i == NTREEBINS-1)? 0 : \
1493 ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
1495 /* The size of the smallest chunk held in bin with index i */
1496 #define minsize_for_tree_index(i) \
1497 ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
1498 (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
1501 /* ------------------------ Operations on bin maps ----------------------- */
1503 /* bit corresponding to given index */
1504 #define idx2bit(i) ((binmap_t)(1) << (i))
1506 /* Mark/Clear bits with given index */
1507 #define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
1508 #define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
1509 #define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
1511 #define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
1512 #define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
1513 #define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
1515 /* isolate the least set bit of a bitmap */
1516 #define least_bit(x) ((x) & -(x))
1518 /* mask with all bits to left of least bit of x on */
1519 #define left_bits(x) ((x<<1) | -(x<<1))
1521 /* mask with all bits to left of or equal to least bit of x on */
1522 #define same_or_left_bits(x) ((x) | -(x))
1524 /* index corresponding to given bit. Use x86 asm if possible */
1526 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1527 #define compute_bit2idx(X, I)\
1530 J = __builtin_ctz(X); \
1534 #elif defined (__INTEL_COMPILER)
1535 #define compute_bit2idx(X, I)\
1538 J = _bit_scan_forward (X); \
1542 #elif defined(_MSC_VER) && _MSC_VER>=1300
1543 #define compute_bit2idx(X, I)\
1546 _BitScanForward((DWORD *) &J, X);\
1550 #elif USE_BUILTIN_FFS
1551 #define compute_bit2idx(X, I) I = ffs(X)-1
1554 #define compute_bit2idx(X, I)\
1556 unsigned int Y = X - 1;\
1557 unsigned int K = Y >> (16-4) & 16;\
1558 unsigned int N = K; Y >>= K;\
1559 N += K = Y >> (8-3) & 8; Y >>= K;\
1560 N += K = Y >> (4-2) & 4; Y >>= K;\
1561 N += K = Y >> (2-1) & 2; Y >>= K;\
1562 N += K = Y >> (1-0) & 1; Y >>= K;\
1563 I = (bindex_t)(N + Y);\
1568 /* ----------------------- Runtime Check Support ------------------------- */
1571 For security, the main invariant is that malloc/free/etc never
1572 writes to a static address other than malloc_state, unless static
1573 malloc_state itself has been corrupted, which cannot occur via
1574 malloc (because of these checks). In essence this means that we
1575 believe all pointers, sizes, maps etc held in malloc_state, but
1576 check all of those linked or offsetted from other embedded data
1577 structures. These checks are interspersed with main code in a way
1578 that tends to minimize their run-time cost.
1580 When FOOTERS is defined, in addition to range checking, we also
1581 verify footer fields of inuse chunks, which can be used guarantee
1582 that the mstate controlling malloc/free is intact. This is a
1583 streamlined version of the approach described by William Robertson
1584 et al in "Run-time Detection of Heap-based Overflows" LISA'03
1585 http://www.usenix.org/events/lisa03/tech/robertson.html The footer
1586 of an inuse chunk holds the xor of its mstate and a random seed,
1587 that is checked upon calls to free() and realloc(). This is
1588 (probabalistically) unguessable from outside the program, but can be
1589 computed by any code successfully malloc'ing any chunk, so does not
1590 itself provide protection against code that has already broken
1591 security through some other means. Unlike Robertson et al, we
1592 always dynamically check addresses of all offset chunks (previous,
1593 next, etc). This turns out to be cheaper than relying on hashes.
1597 /* Check if address a is at least as high as any from MORECORE or MMAP */
1598 #define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
1599 /* Check if address of next chunk n is higher than base chunk p */
1600 #define ok_next(p, n) ((char*)(p) < (char*)(n))
1601 /* Check if p has inuse status */
1602 #define ok_inuse(p) is_inuse(p)
1603 /* Check if p has its pinuse bit on */
1604 #define ok_pinuse(p) pinuse(p)
1606 #else /* !INSECURE */
1607 #define ok_address(M, a) (1)
1608 #define ok_next(b, n) (1)
1609 #define ok_inuse(p) (1)
1610 #define ok_pinuse(p) (1)
1611 #endif /* !INSECURE */
1613 #if (FOOTERS && !INSECURE)
1614 /* Check if (alleged) mstate m has expected magic field */
1615 #define ok_magic(M) ((M)->magic == mparams.magic)
1616 #else /* (FOOTERS && !INSECURE) */
1617 #define ok_magic(M) (1)
1618 #endif /* (FOOTERS && !INSECURE) */
1620 /* In gcc, use __builtin_expect to minimize impact of checks */
1622 #if defined(__GNUC__) && __GNUC__ >= 3
1623 #define RTCHECK(e) __builtin_expect(e, 1)
1625 #define RTCHECK(e) (e)
1627 #else /* !INSECURE */
1628 #define RTCHECK(e) (1)
1629 #endif /* !INSECURE */
1631 /* macros to set up inuse chunks with or without footers */
1635 #define mark_inuse_foot(M,p,s)
1637 /* Macros for setting head/foot of non-mmapped chunks */
1639 /* Set cinuse bit and pinuse bit of next chunk */
1640 #define set_inuse(M,p,s)\
1641 ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
1642 ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
1644 /* Set cinuse and pinuse of this chunk and pinuse of next chunk */
1645 #define set_inuse_and_pinuse(M,p,s)\
1646 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
1647 ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
1649 /* Set size, cinuse and pinuse bit of this chunk */
1650 #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
1651 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
1655 /* Set foot of inuse chunk to be xor of mstate and seed */
1656 #define mark_inuse_foot(M,p,s)\
1657 (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
1659 #define get_mstate_for(p)\
1660 ((mstate)(((mchunkptr)((char*)(p) +\
1661 (chunksize(p))))->prev_foot ^ mparams.magic))
1663 #define set_inuse(M,p,s)\
1664 ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
1665 (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
1666 mark_inuse_foot(M,p,s))
1668 #define set_inuse_and_pinuse(M,p,s)\
1669 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
1670 (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
1671 mark_inuse_foot(M,p,s))
1673 #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
1674 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
1675 mark_inuse_foot(M, p, s))
1677 #endif /* !FOOTERS */
1679 /* ---------------------------- setting mparams -------------------------- */
1682 static void pre_fork(void) { ACQUIRE_LOCK(&(gm)->mutex); }
1683 static void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); }
1684 static void post_fork_child(void) { INITIAL_LOCK(&(gm)->mutex); }
1685 #endif /* LOCK_AT_FORK */
1687 /* Initialize mparams */
1688 static int init_mparams(void) {
1689 #ifdef NEED_GLOBAL_LOCK_INIT
1690 if (malloc_global_mutex_status <= 0)
1691 init_malloc_global_mutex();
1694 ACQUIRE_MALLOC_GLOBAL_LOCK();
1695 if (mparams.magic == 0) {
1701 psize = malloc_getpagesize;
1702 gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize);
1705 SYSTEM_INFO system_info;
1706 GetSystemInfo(&system_info);
1707 psize = system_info.dwPageSize;
1708 gsize = ((DEFAULT_GRANULARITY != 0)?
1709 DEFAULT_GRANULARITY : system_info.dwAllocationGranularity);
1713 /* Sanity-check configuration:
1714 size_t must be unsigned and as wide as pointer type.
1715 ints must be at least 4 bytes.
1716 alignment must be at least 8.
1717 Alignment, min chunk size, and page size must all be powers of 2.
1719 if ((sizeof(size_t) != sizeof(char*)) ||
1720 (MAX_SIZE_T < MIN_CHUNK_SIZE) ||
1721 (sizeof(int) < 4) ||
1722 (MALLOC_ALIGNMENT < (size_t)8U) ||
1723 ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
1724 ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) ||
1725 ((gsize & (gsize-SIZE_T_ONE)) != 0) ||
1726 ((psize & (psize-SIZE_T_ONE)) != 0))
1728 mparams.granularity = gsize;
1729 mparams.page_size = psize;
1730 mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
1731 mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
1732 #if MORECORE_CONTIGUOUS
1733 mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
1734 #else /* MORECORE_CONTIGUOUS */
1735 mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
1736 #endif /* MORECORE_CONTIGUOUS */
1739 /* Set up lock for main malloc area */
1740 gm->mflags = mparams.default_mflags;
1741 (void)INITIAL_LOCK(&gm->mutex);
1744 pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child);
1750 unsigned char buf[sizeof(size_t)];
1751 /* Try to use /dev/urandom, else fall back on using time */
1752 if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
1753 read(fd, buf, sizeof(buf)) == sizeof(buf)) {
1754 magic = *((size_t *) buf);
1758 #endif /* USE_DEV_RANDOM */
1760 magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U);
1761 #elif defined(LACKS_TIME_H)
1762 magic = (size_t)&magic ^ (size_t)0x55555555U;
1764 magic = (size_t)(time(0) ^ (size_t)0x55555555U);
1766 magic |= (size_t)8U; /* ensure nonzero */
1767 magic &= ~(size_t)7U; /* improve chances of fault for bad values */
1768 #ifdef DLM_MAGIC_CONSTANT
1769 magic = DLM_MAGIC_CONSTANT;
1771 /* Until memory modes commonly available, use volatile-write */
1772 (*(volatile size_t *)(&(mparams.magic))) = magic;
1776 RELEASE_MALLOC_GLOBAL_LOCK();
1780 /* support for mallopt */
1781 static int change_mparam(int param_number, int value) {
1783 ensure_initialization();
1784 val = (value == -1)? MAX_SIZE_T : (size_t)value;
1785 switch(param_number) {
1786 case M_TRIM_THRESHOLD:
1787 mparams.trim_threshold = val;
1790 if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
1791 mparams.granularity = val;
1796 case M_MMAP_THRESHOLD:
1797 mparams.mmap_threshold = val;
1805 /* ------------------------- Debugging Support --------------------------- */
1807 /* Check properties of any chunk, whether free, inuse, mmapped etc */
1808 static void do_check_any_chunk(mstate m, mchunkptr p) {
1809 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1810 assert(ok_address(m, p));
1813 /* Check properties of top chunk */
1814 static void do_check_top_chunk(mstate m, mchunkptr p) {
1815 msegmentptr sp = segment_holding(m, (char*)p);
1816 size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */
1818 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1819 assert(ok_address(m, p));
1820 assert(sz == m->topsize);
1822 assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
1824 assert(!pinuse(chunk_plus_offset(p, sz)));
1827 /* Check properties of (inuse) mmapped chunks */
1828 static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
1829 size_t sz = chunksize(p);
1830 size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD);
1831 assert(is_mmapped(p));
1832 assert(use_mmap(m));
1833 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1834 assert(ok_address(m, p));
1835 assert(!is_small(sz));
1836 assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
1837 assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
1838 assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
1841 /* Check properties of inuse chunks */
1842 static void do_check_inuse_chunk(mstate m, mchunkptr p) {
1843 do_check_any_chunk(m, p);
1844 assert(is_inuse(p));
1845 assert(next_pinuse(p));
1846 /* If not pinuse and not mmapped, previous chunk has OK offset */
1847 assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
1849 do_check_mmapped_chunk(m, p);
1852 /* Check properties of free chunks */
1853 static void do_check_free_chunk(mstate m, mchunkptr p) {
1854 size_t sz = chunksize(p);
1855 mchunkptr next = chunk_plus_offset(p, sz);
1856 do_check_any_chunk(m, p);
1857 assert(!is_inuse(p));
1858 assert(!next_pinuse(p));
1859 assert (!is_mmapped(p));
1860 if (p != m->dv && p != m->top) {
1861 if (sz >= MIN_CHUNK_SIZE) {
1862 assert((sz & CHUNK_ALIGN_MASK) == 0);
1863 assert(is_aligned(chunk2mem(p)));
1864 assert(next->prev_foot == sz);
1866 assert (next == m->top || is_inuse(next));
1867 assert(p->fd->bk == p);
1868 assert(p->bk->fd == p);
1870 else /* markers are always of size SIZE_T_SIZE */
1871 assert(sz == SIZE_T_SIZE);
1875 /* Check properties of malloced chunks at the point they are malloced */
1876 static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
1878 mchunkptr p = mem2chunk(mem);
1879 size_t sz = p->head & ~INUSE_BITS;
1880 do_check_inuse_chunk(m, p);
1881 assert((sz & CHUNK_ALIGN_MASK) == 0);
1882 assert(sz >= MIN_CHUNK_SIZE);
1884 /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
1885 assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
1889 /* Check a tree and its subtrees. */
1890 static void do_check_tree(mstate m, tchunkptr t) {
1893 bindex_t tindex = t->index;
1894 size_t tsize = chunksize(t);
1896 compute_tree_index(tsize, idx);
1897 assert(tindex == idx);
1898 assert(tsize >= MIN_LARGE_SIZE);
1899 assert(tsize >= minsize_for_tree_index(idx));
1900 assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
1902 do { /* traverse through chain of same-sized nodes */
1903 do_check_any_chunk(m, ((mchunkptr)u));
1904 assert(u->index == tindex);
1905 assert(chunksize(u) == tsize);
1906 assert(!is_inuse(u));
1907 assert(!next_pinuse(u));
1908 assert(u->fd->bk == u);
1909 assert(u->bk->fd == u);
1910 if (u->parent == 0) {
1911 assert(u->child[0] == 0);
1912 assert(u->child[1] == 0);
1915 assert(head == 0); /* only one node on chain has parent */
1917 assert(u->parent != u);
1918 assert (u->parent->child[0] == u ||
1919 u->parent->child[1] == u ||
1920 *((tbinptr*)(u->parent)) == u);
1921 if (u->child[0] != 0) {
1922 assert(u->child[0]->parent == u);
1923 assert(u->child[0] != u);
1924 do_check_tree(m, u->child[0]);
1926 if (u->child[1] != 0) {
1927 assert(u->child[1]->parent == u);
1928 assert(u->child[1] != u);
1929 do_check_tree(m, u->child[1]);
1931 if (u->child[0] != 0 && u->child[1] != 0) {
1932 assert(chunksize(u->child[0]) < chunksize(u->child[1]));
1940 /* Check all the chunks in a treebin. */
1941 static void do_check_treebin(mstate m, bindex_t i) {
1942 tbinptr* tb = treebin_at(m, i);
1944 int empty = (m->treemap & (1U << i)) == 0;
1948 do_check_tree(m, t);
1951 /* Check all the chunks in a smallbin. */
1952 static void do_check_smallbin(mstate m, bindex_t i) {
1953 sbinptr b = smallbin_at(m, i);
1954 mchunkptr p = b->bk;
1955 unsigned int empty = (m->smallmap & (1U << i)) == 0;
1959 for (; p != b; p = p->bk) {
1960 size_t size = chunksize(p);
1962 /* each chunk claims to be free */
1963 do_check_free_chunk(m, p);
1964 /* chunk belongs in bin */
1965 assert(small_index(size) == i);
1966 assert(p->bk == b || chunksize(p->bk) == chunksize(p));
1967 /* chunk is followed by an inuse chunk */
1969 if (q->head != FENCEPOST_HEAD)
1970 do_check_inuse_chunk(m, q);
1975 /* Find x in a bin. Used in other check functions. */
1976 static int bin_find(mstate m, mchunkptr x) {
1977 size_t size = chunksize(x);
1978 if (is_small(size)) {
1979 bindex_t sidx = small_index(size);
1980 sbinptr b = smallbin_at(m, sidx);
1981 if (smallmap_is_marked(m, sidx)) {
1986 } while ((p = p->fd) != b);
1991 compute_tree_index(size, tidx);
1992 if (treemap_is_marked(m, tidx)) {
1993 tchunkptr t = *treebin_at(m, tidx);
1994 size_t sizebits = size << leftshift_for_tree_index(tidx);
1995 while (t != 0 && chunksize(t) != size) {
1996 t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
2002 if (u == (tchunkptr)x)
2004 } while ((u = u->fd) != t);
2011 /* Traverse each chunk and check it; return total */
2012 static size_t traverse_and_check(mstate m) {
2014 if (is_initialized(m)) {
2015 msegmentptr s = &m->seg;
2016 sum += m->topsize + TOP_FOOT_SIZE;
2018 mchunkptr q = align_as_chunk(s->base);
2019 mchunkptr lastq = 0;
2021 while (segment_holds(s, q) &&
2022 q != m->top && q->head != FENCEPOST_HEAD) {
2023 sum += chunksize(q);
2025 assert(!bin_find(m, q));
2026 do_check_inuse_chunk(m, q);
2029 assert(q == m->dv || bin_find(m, q));
2030 assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */
2031 do_check_free_chunk(m, q);
2043 /* Check all properties of malloc_state. */
2044 static void do_check_malloc_state(mstate m) {
2048 for (i = 0; i < NSMALLBINS; ++i)
2049 do_check_smallbin(m, i);
2050 for (i = 0; i < NTREEBINS; ++i)
2051 do_check_treebin(m, i);
2053 if (m->dvsize != 0) { /* check dv chunk */
2054 do_check_any_chunk(m, m->dv);
2055 assert(m->dvsize == chunksize(m->dv));
2056 assert(m->dvsize >= MIN_CHUNK_SIZE);
2057 assert(bin_find(m, m->dv) == 0);
2060 if (m->top != 0) { /* check top chunk */
2061 do_check_top_chunk(m, m->top);
2062 /*assert(m->topsize == chunksize(m->top)); redundant */
2063 assert(m->topsize > 0);
2064 assert(bin_find(m, m->top) == 0);
2067 total = traverse_and_check(m);
2068 assert(total <= m->footprint);
2069 assert(m->footprint <= m->max_footprint);
2073 /* ----------------------------- statistics ------------------------------ */
2076 static struct mallinfo internal_mallinfo(mstate m) {
2077 struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2078 ensure_initialization();
2079 if (!PREACTION(m)) {
2080 check_malloc_state(m);
2081 if (is_initialized(m)) {
2082 size_t nfree = SIZE_T_ONE; /* top always free */
2083 size_t mfree = m->topsize + TOP_FOOT_SIZE;
2085 msegmentptr s = &m->seg;
2087 mchunkptr q = align_as_chunk(s->base);
2088 while (segment_holds(s, q) &&
2089 q != m->top && q->head != FENCEPOST_HEAD) {
2090 size_t sz = chunksize(q);
2103 nm.hblkhd = m->footprint - sum;
2104 nm.usmblks = m->max_footprint;
2105 nm.uordblks = m->footprint - mfree;
2106 nm.fordblks = mfree;
2107 nm.keepcost = m->topsize;
2114 #endif /* !NO_MALLINFO */
2116 #if !NO_MALLOC_STATS
2117 static void internal_malloc_stats(mstate m) {
2118 ensure_initialization();
2119 if (!PREACTION(m)) {
2123 check_malloc_state(m);
2124 if (is_initialized(m)) {
2125 msegmentptr s = &m->seg;
2126 maxfp = m->max_footprint;
2128 used = fp - (m->topsize + TOP_FOOT_SIZE);
2131 mchunkptr q = align_as_chunk(s->base);
2132 while (segment_holds(s, q) &&
2133 q != m->top && q->head != FENCEPOST_HEAD) {
2135 used -= chunksize(q);
2141 POSTACTION(m); /* drop lock */
2142 fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
2143 fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp));
2144 fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used));
2147 #endif /* NO_MALLOC_STATS */
2149 /* ----------------------- Operations on smallbins ----------------------- */
2152 Various forms of linking and unlinking are defined as macros. Even
2153 the ones for trees, which are very long but have very short typical
2154 paths. This is ugly but reduces reliance on inlining support of
2158 /* Link a free chunk into a smallbin */
2159 #define insert_small_chunk(M, P, S) {\
2160 bindex_t I = small_index(S);\
2161 mchunkptr B = smallbin_at(M, I);\
2163 assert(S >= MIN_CHUNK_SIZE);\
2164 if (!smallmap_is_marked(M, I))\
2165 mark_smallmap(M, I);\
2166 else if (RTCHECK(ok_address(M, B->fd)))\
2169 CORRUPTION_ERROR_ACTION(M);\
2177 /* Unlink a chunk from a smallbin */
2178 #define unlink_small_chunk(M, P, S) {\
2179 mchunkptr F = P->fd;\
2180 mchunkptr B = P->bk;\
2181 bindex_t I = small_index(S);\
2184 assert(chunksize(P) == small_index2size(I));\
2185 if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \
2187 clear_smallmap(M, I);\
2189 else if (RTCHECK(B == smallbin_at(M,I) ||\
2190 (ok_address(M, B) && B->fd == P))) {\
2195 CORRUPTION_ERROR_ACTION(M);\
2199 CORRUPTION_ERROR_ACTION(M);\
2203 /* Unlink the first chunk from a smallbin */
2204 #define unlink_first_small_chunk(M, B, P, I) {\
2205 mchunkptr F = P->fd;\
2208 assert(chunksize(P) == small_index2size(I));\
2210 clear_smallmap(M, I);\
2212 else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\
2217 CORRUPTION_ERROR_ACTION(M);\
2221 /* Replace dv node, binning the old one */
2222 /* Used only when dvsize known to be small */
2223 #define replace_dv(M, P, S) {\
2224 size_t DVS = M->dvsize;\
2225 assert(is_small(DVS));\
2227 mchunkptr DV = M->dv;\
2228 insert_small_chunk(M, DV, DVS);\
2234 /* ------------------------- Operations on trees ------------------------- */
2236 /* Insert chunk into tree */
2237 #define insert_large_chunk(M, X, S) {\
2240 compute_tree_index(S, I);\
2241 H = treebin_at(M, I);\
2243 X->child[0] = X->child[1] = 0;\
2244 if (!treemap_is_marked(M, I)) {\
2245 mark_treemap(M, I);\
2247 X->parent = (tchunkptr)H;\
2252 size_t K = S << leftshift_for_tree_index(I);\
2254 if (chunksize(T) != S) {\
2255 tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
2259 else if (RTCHECK(ok_address(M, C))) {\
2266 CORRUPTION_ERROR_ACTION(M);\
2271 tchunkptr F = T->fd;\
2272 if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
2280 CORRUPTION_ERROR_ACTION(M);\
2291 1. If x is a chained node, unlink it from its same-sized fd/bk links
2292 and choose its bk node as its replacement.
2293 2. If x was the last node of its size, but not a leaf node, it must
2294 be replaced with a leaf node (not merely one with an open left or
2295 right), to make sure that lefts and rights of descendents
2296 correspond properly to bit masks. We use the rightmost descendent
2297 of x. We could use any other leaf, but this is easy to locate and
2298 tends to counteract removal of leftmosts elsewhere, and so keeps
2299 paths shorter than minimally guaranteed. This doesn't loop much
2300 because on average a node in a tree is near the bottom.
2301 3. If x is the base of a chain (i.e., has parent links) relink
2302 x's parent and children to x's replacement (or null if none).
2305 #define unlink_large_chunk(M, X) {\
2306 tchunkptr XP = X->parent;\
2309 tchunkptr F = X->fd;\
2311 if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\
2316 CORRUPTION_ERROR_ACTION(M);\
2321 if (((R = *(RP = &(X->child[1]))) != 0) ||\
2322 ((R = *(RP = &(X->child[0]))) != 0)) {\
2324 while ((*(CP = &(R->child[1])) != 0) ||\
2325 (*(CP = &(R->child[0])) != 0)) {\
2328 if (RTCHECK(ok_address(M, RP)))\
2331 CORRUPTION_ERROR_ACTION(M);\
2336 tbinptr* H = treebin_at(M, X->index);\
2338 if ((*H = R) == 0) \
2339 clear_treemap(M, X->index);\
2341 else if (RTCHECK(ok_address(M, XP))) {\
2342 if (XP->child[0] == X) \
2348 CORRUPTION_ERROR_ACTION(M);\
2350 if (RTCHECK(ok_address(M, R))) {\
2353 if ((C0 = X->child[0]) != 0) {\
2354 if (RTCHECK(ok_address(M, C0))) {\
2359 CORRUPTION_ERROR_ACTION(M);\
2361 if ((C1 = X->child[1]) != 0) {\
2362 if (RTCHECK(ok_address(M, C1))) {\
2367 CORRUPTION_ERROR_ACTION(M);\
2371 CORRUPTION_ERROR_ACTION(M);\
2376 /* Relays to large vs small bin operations */
2378 #define insert_chunk(M, P, S)\
2379 if (is_small(S)) insert_small_chunk(M, P, S)\
2380 else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
2382 #define unlink_chunk(M, P, S)\
2383 if (is_small(S)) unlink_small_chunk(M, P, S)\
2384 else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
2387 /* Relays to internal calls to malloc/free from realloc, memalign etc */
2390 #define internal_malloc(m, b) mspace_malloc(m, b)
2391 #define internal_free(m, mem) mspace_free(m,mem);
2392 #else /* ONLY_MSPACES */
2394 #define internal_malloc(m, b)\
2395 ((m == gm)? dlmalloc(b) : mspace_malloc(m, b))
2396 #define internal_free(m, mem)\
2397 if (m == gm) dlfree(mem); else mspace_free(m,mem);
2399 #define internal_malloc(m, b) dlmalloc(b)
2400 #define internal_free(m, mem) dlfree(mem)
2401 #endif /* MSPACES */
2402 #endif /* ONLY_MSPACES */
2404 /* ----------------------- Direct-mmapping chunks ----------------------- */
2407 Directly mmapped chunks are set up with an offset to the start of
2408 the mmapped region stored in the prev_foot field of the chunk. This
2409 allows reconstruction of the required argument to MUNMAP when freed,
2410 and also allows adjustment of the returned chunk to meet alignment
2411 requirements (especially in memalign).
2414 /* Malloc using mmap */
2415 static void* mmap_alloc(mstate m, size_t nb) {
2416 size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2417 if (m->footprint_limit != 0) {
2418 size_t fp = m->footprint + mmsize;
2419 if (fp <= m->footprint || fp > m->footprint_limit)
2422 if (mmsize > nb) { /* Check for wrap around 0 */
2423 char* mm = (char*)(CALL_DIRECT_MMAP(mmsize));
2425 size_t offset = align_offset(chunk2mem(mm));
2426 size_t psize = mmsize - offset - MMAP_FOOT_PAD;
2427 mchunkptr p = (mchunkptr)(mm + offset);
2428 p->prev_foot = offset;
2430 mark_inuse_foot(m, p, psize);
2431 chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
2432 chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
2434 if (m->least_addr == 0 || mm < m->least_addr)
2436 if ((m->footprint += mmsize) > m->max_footprint)
2437 m->max_footprint = m->footprint;
2438 assert(is_aligned(chunk2mem(p)));
2439 check_mmapped_chunk(m, p);
2440 return chunk2mem(p);
2446 /* Realloc using mmap */
2447 static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) {
2448 size_t oldsize = chunksize(oldp);
2449 (void)flags; /* placate people compiling -Wunused */
2450 if (is_small(nb)) /* Can't shrink mmap regions below small size */
2452 /* Keep old chunk if big enough but not too big */
2453 if (oldsize >= nb + SIZE_T_SIZE &&
2454 (oldsize - nb) <= (mparams.granularity << 1))
2457 size_t offset = oldp->prev_foot;
2458 size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
2459 size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2460 char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
2461 oldmmsize, newmmsize, flags);
2463 mchunkptr newp = (mchunkptr)(cp + offset);
2464 size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
2466 mark_inuse_foot(m, newp, psize);
2467 chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
2468 chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
2470 if (cp < m->least_addr)
2472 if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
2473 m->max_footprint = m->footprint;
2474 check_mmapped_chunk(m, newp);
2482 /* -------------------------- mspace management -------------------------- */
2484 /* Initialize top chunk and its size */
2485 static void init_top(mstate m, mchunkptr p, size_t psize) {
2486 /* Ensure alignment */
2487 size_t offset = align_offset(chunk2mem(p));
2488 p = (mchunkptr)((char*)p + offset);
2493 p->head = psize | PINUSE_BIT;
2494 /* set size of fake trailing chunk holding overhead space only once */
2495 chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
2496 m->trim_check = mparams.trim_threshold; /* reset on each update */
2499 /* Initialize bins for a new mstate that is otherwise zeroed out */
2500 static void init_bins(mstate m) {
2501 /* Establish circular links for smallbins */
2503 for (i = 0; i < NSMALLBINS; ++i) {
2504 sbinptr bin = smallbin_at(m,i);
2505 bin->fd = bin->bk = bin;
2509 #if PROCEED_ON_ERROR
2511 /* default corruption action */
2512 static void reset_on_error(mstate m) {
2514 ++malloc_corruption_error_count;
2515 /* Reinitialize fields to forget about all memory */
2516 m->smallmap = m->treemap = 0;
2517 m->dvsize = m->topsize = 0;
2522 for (i = 0; i < NTREEBINS; ++i)
2523 *treebin_at(m, i) = 0;
2526 #endif /* PROCEED_ON_ERROR */
2528 /* Allocate chunk and prepend remainder with chunk in successor base. */
2529 static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
2531 mchunkptr p = align_as_chunk(newbase);
2532 mchunkptr oldfirst = align_as_chunk(oldbase);
2533 size_t psize = (char*)oldfirst - (char*)p;
2534 mchunkptr q = chunk_plus_offset(p, nb);
2535 size_t qsize = psize - nb;
2536 set_size_and_pinuse_of_inuse_chunk(m, p, nb);
2538 assert((char*)oldfirst > (char*)q);
2539 assert(pinuse(oldfirst));
2540 assert(qsize >= MIN_CHUNK_SIZE);
2542 /* consolidate remainder with first chunk of old base */
2543 if (oldfirst == m->top) {
2544 size_t tsize = m->topsize += qsize;
2546 q->head = tsize | PINUSE_BIT;
2547 check_top_chunk(m, q);
2549 else if (oldfirst == m->dv) {
2550 size_t dsize = m->dvsize += qsize;
2552 set_size_and_pinuse_of_free_chunk(q, dsize);
2555 if (!is_inuse(oldfirst)) {
2556 size_t nsize = chunksize(oldfirst);
2557 unlink_chunk(m, oldfirst, nsize);
2558 oldfirst = chunk_plus_offset(oldfirst, nsize);
2561 set_free_with_pinuse(q, qsize, oldfirst);
2562 insert_chunk(m, q, qsize);
2563 check_free_chunk(m, q);
2566 check_malloced_chunk(m, chunk2mem(p), nb);
2567 return chunk2mem(p);
2570 /* Add a segment to hold a new noncontiguous region */
2571 static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
2572 /* Determine locations and sizes of segment, fenceposts, old top */
2573 char* old_top = (char*)m->top;
2574 msegmentptr oldsp = segment_holding(m, old_top);
2575 char* old_end = oldsp->base + oldsp->size;
2576 size_t ssize = pad_request(sizeof(struct malloc_segment));
2577 char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2578 size_t offset = align_offset(chunk2mem(rawsp));
2579 char* asp = rawsp + offset;
2580 char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
2581 mchunkptr sp = (mchunkptr)csp;
2582 msegmentptr ss = (msegmentptr)(chunk2mem(sp));
2583 mchunkptr tnext = chunk_plus_offset(sp, ssize);
2584 mchunkptr p = tnext;
2587 /* reset top to new space */
2588 init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
2590 /* Set up segment record */
2591 assert(is_aligned(ss));
2592 set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
2593 *ss = m->seg; /* Push current record */
2594 m->seg.base = tbase;
2595 m->seg.size = tsize;
2596 m->seg.sflags = mmapped;
2599 /* Insert trailing fenceposts */
2601 mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
2602 p->head = FENCEPOST_HEAD;
2604 if ((char*)(&(nextp->head)) < old_end)
2609 assert(nfences >= 2);
2611 /* Insert the rest of old top into a bin as an ordinary free chunk */
2612 if (csp != old_top) {
2613 mchunkptr q = (mchunkptr)old_top;
2614 size_t psize = csp - old_top;
2615 mchunkptr tn = chunk_plus_offset(q, psize);
2616 set_free_with_pinuse(q, psize, tn);
2617 insert_chunk(m, q, psize);
2620 check_top_chunk(m, m->top);
2623 /* -------------------------- System allocation -------------------------- */
2625 /* Get memory from system using MORECORE or MMAP */
2626 static void* sys_alloc(mstate m, size_t nb) {
2627 char* tbase = CMFAIL;
2629 flag_t mmap_flag = 0;
2630 size_t asize; /* allocation size */
2632 ensure_initialization();
2634 if (use_noexpand(m))
2637 /* Directly map large chunks, but only if already initialized */
2638 if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) {
2639 void* mem = mmap_alloc(m, nb);
2644 asize = granularity_align(nb + SYS_ALLOC_PADDING);
2646 return 0; /* wraparound */
2647 if (m->footprint_limit != 0) {
2648 size_t fp = m->footprint + asize;
2649 if (fp <= m->footprint || fp > m->footprint_limit)
2654 Try getting memory in any of three ways (in most-preferred to
2655 least-preferred order):
2656 1. A call to MORECORE that can normally contiguously extend memory.
2657 (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
2658 or main space is mmapped or a previous contiguous call failed)
2659 2. A call to MMAP new space (disabled if not HAVE_MMAP).
2660 Note that under the default settings, if MORECORE is unable to
2661 fulfill a request, and HAVE_MMAP is true, then mmap is
2662 used as a noncontiguous system allocator. This is a useful backup
2663 strategy for systems with holes in address spaces -- in this case
2664 sbrk cannot contiguously expand the heap, but mmap may be able to
2666 3. A call to MORECORE that cannot usually contiguously extend memory.
2667 (disabled if not HAVE_MORECORE)
2669 In all cases, we need to request enough bytes from system to ensure
2670 we can malloc nb bytes upon success, so pad with enough space for
2671 top_foot, plus alignment-pad to make sure we don't lose bytes if
2672 not on boundary, and round this up to a granularity unit.
2675 if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
2677 size_t ssize = asize; /* sbrk call size */
2678 msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
2679 ACQUIRE_MALLOC_GLOBAL_LOCK();
2681 if (ss == 0) { /* First time through or recovery */
2682 char* base = (char*)CALL_MORECORE(0);
2683 if (base != CMFAIL) {
2685 /* Adjust to end on a page boundary */
2686 if (!is_page_aligned(base))
2687 ssize += (page_align((size_t)base) - (size_t)base);
2688 fp = m->footprint + ssize; /* recheck limits */
2689 if (ssize > nb && ssize < HALF_MAX_SIZE_T &&
2690 (m->footprint_limit == 0 ||
2691 (fp > m->footprint && fp <= m->footprint_limit)) &&
2692 (br = (char*)(CALL_MORECORE(ssize))) == base) {
2699 /* Subtract out existing available top space from MORECORE request. */
2700 ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING);
2701 /* Use mem here only if it did continuously extend old space */
2702 if (ssize < HALF_MAX_SIZE_T &&
2703 (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) {
2709 if (tbase == CMFAIL) { /* Cope with partial failure */
2710 if (br != CMFAIL) { /* Try to use/extend the space we did get */
2711 if (ssize < HALF_MAX_SIZE_T &&
2712 ssize < nb + SYS_ALLOC_PADDING) {
2713 size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize);
2714 if (esize < HALF_MAX_SIZE_T) {
2715 char* end = (char*)CALL_MORECORE(esize);
2718 else { /* Can't use; try to release */
2719 (void) CALL_MORECORE(-ssize);
2725 if (br != CMFAIL) { /* Use the space we did get */
2730 disable_contiguous(m); /* Don't try contiguous path in the future */
2733 RELEASE_MALLOC_GLOBAL_LOCK();
2736 if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */
2737 char* mp = (char*)(CALL_MMAP(asize));
2741 mmap_flag = USE_MMAP_BIT;
2745 if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
2746 if (asize < HALF_MAX_SIZE_T) {
2749 ACQUIRE_MALLOC_GLOBAL_LOCK();
2750 br = (char*)(CALL_MORECORE(asize));
2751 end = (char*)(CALL_MORECORE(0));
2752 RELEASE_MALLOC_GLOBAL_LOCK();
2753 if (br != CMFAIL && end != CMFAIL && br < end) {
2754 size_t ssize = end - br;
2755 if (ssize > nb + TOP_FOOT_SIZE) {
2763 if (tbase != CMFAIL) {
2765 if ((m->footprint += tsize) > m->max_footprint)
2766 m->max_footprint = m->footprint;
2768 if (!is_initialized(m)) { /* first-time initialization */
2769 if (m->least_addr == 0 || tbase < m->least_addr)
2770 m->least_addr = tbase;
2771 m->seg.base = tbase;
2772 m->seg.size = tsize;
2773 m->seg.sflags = mmap_flag;
2774 m->magic = mparams.magic;
2775 m->release_checks = MAX_RELEASE_CHECK_RATE;
2779 init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
2783 /* Offset top by embedded malloc_state */
2784 mchunkptr mn = next_chunk(mem2chunk(m));
2785 init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
2790 /* Try to merge with an existing segment */
2791 msegmentptr sp = &m->seg;
2792 /* Only consider most recent segment if traversal suppressed */
2793 while (sp != 0 && tbase != sp->base + sp->size)
2794 sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
2796 !is_extern_segment(sp) &&
2797 (sp->sflags & USE_MMAP_BIT) == mmap_flag &&
2798 segment_holds(sp, m->top)) { /* append */
2800 init_top(m, m->top, m->topsize + tsize);
2803 if (tbase < m->least_addr)
2804 m->least_addr = tbase;
2806 while (sp != 0 && sp->base != tbase + tsize)
2807 sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
2809 !is_extern_segment(sp) &&
2810 (sp->sflags & USE_MMAP_BIT) == mmap_flag) {
2811 char* oldbase = sp->base;
2814 return prepend_alloc(m, tbase, oldbase, nb);
2817 add_segment(m, tbase, tsize, mmap_flag);
2821 if (nb < m->topsize) { /* Allocate from new or extended top space */
2822 size_t rsize = m->topsize -= nb;
2823 mchunkptr p = m->top;
2824 mchunkptr r = m->top = chunk_plus_offset(p, nb);
2825 r->head = rsize | PINUSE_BIT;
2826 set_size_and_pinuse_of_inuse_chunk(m, p, nb);
2827 check_top_chunk(m, m->top);
2828 check_malloced_chunk(m, chunk2mem(p), nb);
2829 return chunk2mem(p);
2833 MALLOC_FAILURE_ACTION;
2837 /* ----------------------- system deallocation -------------------------- */
2839 /* Unmap and unlink any mmapped segments that don't contain used chunks */
2840 static size_t release_unused_segments(mstate m) {
2841 size_t released = 0;
2843 msegmentptr pred = &m->seg;
2844 msegmentptr sp = pred->next;
2846 char* base = sp->base;
2847 size_t size = sp->size;
2848 msegmentptr next = sp->next;
2850 if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
2851 mchunkptr p = align_as_chunk(base);
2852 size_t psize = chunksize(p);
2853 /* Can unmap if first chunk holds entire segment and not pinned */
2854 if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
2855 tchunkptr tp = (tchunkptr)p;
2856 assert(segment_holds(sp, (char*)sp));
2862 unlink_large_chunk(m, tp);
2864 if (CALL_MUNMAP(base, size) == 0) {
2866 m->footprint -= size;
2867 /* unlink obsoleted record */
2871 else { /* back out if cannot unmap */
2872 insert_large_chunk(m, tp, psize);
2876 if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */
2881 /* Reset check counter */
2882 m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)?
2883 (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE);
2887 static int sys_trim(mstate m, size_t pad) {
2888 size_t released = 0;
2889 ensure_initialization();
2890 if (pad < MAX_REQUEST && is_initialized(m)) {
2891 pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
2893 if (m->topsize > pad) {
2894 /* Shrink top space in granularity-size units, keeping at least one */
2895 size_t unit = mparams.granularity;
2896 size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
2898 msegmentptr sp = segment_holding(m, (char*)m->top);
2900 if (!is_extern_segment(sp)) {
2901 if (is_mmapped_segment(sp)) {
2903 sp->size >= extra &&
2904 !has_segment_link(m, sp)) { /* can't shrink if pinned */
2905 size_t newsize = sp->size - extra;
2906 (void)newsize; /* placate people compiling -Wunused-variable */
2907 /* Prefer mremap, fall back to munmap */
2908 if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
2909 (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
2914 else if (HAVE_MORECORE) {
2915 if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
2916 extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
2917 ACQUIRE_MALLOC_GLOBAL_LOCK();
2919 /* Make sure end of memory is where we last set it. */
2920 char* old_br = (char*)(CALL_MORECORE(0));
2921 if (old_br == sp->base + sp->size) {
2922 char* rel_br = (char*)(CALL_MORECORE(-extra));
2923 char* new_br = (char*)(CALL_MORECORE(0));
2924 if (rel_br != CMFAIL && new_br < old_br)
2925 released = old_br - new_br;
2928 RELEASE_MALLOC_GLOBAL_LOCK();
2932 if (released != 0) {
2933 sp->size -= released;
2934 m->footprint -= released;
2935 init_top(m, m->top, m->topsize - released);
2936 check_top_chunk(m, m->top);
2940 /* Unmap any unused mmapped segments */
2942 released += release_unused_segments(m);
2944 /* On failure, disable autotrim to avoid repeated failed future calls */
2945 if (released == 0 && m->topsize > m->trim_check)
2946 m->trim_check = MAX_SIZE_T;
2949 return (released != 0)? 1 : 0;
2952 /* Consolidate and bin a chunk. Differs from exported versions
2953 of free mainly in that the chunk need not be marked as inuse.
2955 static void dispose_chunk(mstate m, mchunkptr p, size_t psize) {
2956 mchunkptr next = chunk_plus_offset(p, psize);
2959 size_t prevsize = p->prev_foot;
2960 if (is_mmapped(p)) {
2961 psize += prevsize + MMAP_FOOT_PAD;
2962 if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
2963 m->footprint -= psize;
2966 prev = chunk_minus_offset(p, prevsize);
2969 if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */
2971 unlink_chunk(m, p, prevsize);
2973 else if ((next->head & INUSE_BITS) == INUSE_BITS) {
2975 set_free_with_pinuse(p, psize, next);
2980 CORRUPTION_ERROR_ACTION(m);
2984 if (RTCHECK(ok_address(m, next))) {
2985 if (!cinuse(next)) { /* consolidate forward */
2986 if (next == m->top) {
2987 size_t tsize = m->topsize += psize;
2989 p->head = tsize | PINUSE_BIT;
2996 else if (next == m->dv) {
2997 size_t dsize = m->dvsize += psize;
2999 set_size_and_pinuse_of_free_chunk(p, dsize);
3003 size_t nsize = chunksize(next);
3005 unlink_chunk(m, next, nsize);
3006 set_size_and_pinuse_of_free_chunk(p, psize);
3014 set_free_with_pinuse(p, psize, next);
3016 insert_chunk(m, p, psize);
3019 CORRUPTION_ERROR_ACTION(m);
3023 /* ---------------------------- malloc --------------------------- */
3025 /* allocate a large request from the best fitting chunk in a treebin */
3026 static void* tmalloc_large(mstate m, size_t nb) {
3028 size_t rsize = -nb; /* Unsigned negation */
3031 compute_tree_index(nb, idx);
3032 if ((t = *treebin_at(m, idx)) != 0) {
3033 /* Traverse tree for this bin looking for node with size == nb */
3034 size_t sizebits = nb << leftshift_for_tree_index(idx);
3035 tchunkptr rst = 0; /* The deepest untaken right subtree */
3038 size_t trem = chunksize(t) - nb;
3041 if ((rsize = trem) == 0)
3045 t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
3046 if (rt != 0 && rt != t)
3049 t = rst; /* set t to least subtree holding sizes > nb */
3055 if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
3056 binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
3057 if (leftbits != 0) {
3059 binmap_t leastbit = least_bit(leftbits);
3060 compute_bit2idx(leastbit, i);
3061 t = *treebin_at(m, i);
3065 while (t != 0) { /* find smallest of tree or subtree */
3066 size_t trem = chunksize(t) - nb;
3071 t = leftmost_child(t);
3074 /* If dv is a better fit, return 0 so malloc will use it */
3075 if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
3076 if (RTCHECK(ok_address(m, v))) { /* split */
3077 mchunkptr r = chunk_plus_offset(v, nb);
3078 assert(chunksize(v) == rsize + nb);
3079 if (RTCHECK(ok_next(v, r))) {
3080 unlink_large_chunk(m, v);
3081 if (rsize < MIN_CHUNK_SIZE)
3082 set_inuse_and_pinuse(m, v, (rsize + nb));
3084 set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3085 set_size_and_pinuse_of_free_chunk(r, rsize);
3086 insert_chunk(m, r, rsize);
3088 return chunk2mem(v);
3091 CORRUPTION_ERROR_ACTION(m);
3096 /* allocate a small request from the best fitting chunk in a treebin */
3097 static void* tmalloc_small(mstate m, size_t nb) {
3101 binmap_t leastbit = least_bit(m->treemap);
3102 compute_bit2idx(leastbit, i);
3103 v = t = *treebin_at(m, i);
3104 rsize = chunksize(t) - nb;
3106 while ((t = leftmost_child(t)) != 0) {
3107 size_t trem = chunksize(t) - nb;
3114 if (RTCHECK(ok_address(m, v))) {
3115 mchunkptr r = chunk_plus_offset(v, nb);
3116 assert(chunksize(v) == rsize + nb);
3117 if (RTCHECK(ok_next(v, r))) {
3118 unlink_large_chunk(m, v);
3119 if (rsize < MIN_CHUNK_SIZE)
3120 set_inuse_and_pinuse(m, v, (rsize + nb));
3122 set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3123 set_size_and_pinuse_of_free_chunk(r, rsize);
3124 replace_dv(m, r, rsize);
3126 return chunk2mem(v);
3130 CORRUPTION_ERROR_ACTION(m);
3136 void* dlmalloc(size_t bytes) {
3139 If a small request (< 256 bytes minus per-chunk overhead):
3140 1. If one exists, use a remainderless chunk in associated smallbin.
3141 (Remainderless means that there are too few excess bytes to
3142 represent as a chunk.)
3143 2. If it is big enough, use the dv chunk, which is normally the
3144 chunk adjacent to the one used for the most recent small request.
3145 3. If one exists, split the smallest available chunk in a bin,
3146 saving remainder in dv.
3147 4. If it is big enough, use the top chunk.
3148 5. If available, get memory from system and use it
3149 Otherwise, for a large request:
3150 1. Find the smallest available binned chunk that fits, and use it
3151 if it is better fitting than dv chunk, splitting if necessary.
3152 2. If better fitting than any binned chunk, use the dv chunk.
3153 3. If it is big enough, use the top chunk.
3154 4. If request size >= mmap threshold, try to directly mmap this chunk.
3155 5. If available, get memory from system and use it
3157 The ugly goto's here ensure that postaction occurs along all paths.
3161 ensure_initialization(); /* initialize in sys_alloc if not using locks */
3164 if (!PREACTION(gm)) {
3167 if (bytes <= MAX_SMALL_REQUEST) {
3170 nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
3171 idx = small_index(nb);
3172 smallbits = gm->smallmap >> idx;
3174 if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
3176 idx += ~smallbits & 1; /* Uses next bin if idx empty */
3177 b = smallbin_at(gm, idx);
3179 assert(chunksize(p) == small_index2size(idx));
3180 unlink_first_small_chunk(gm, b, p, idx);
3181 set_inuse_and_pinuse(gm, p, small_index2size(idx));
3183 check_malloced_chunk(gm, mem, nb);
3187 else if (nb > gm->dvsize) {
3188 if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
3192 binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
3193 binmap_t leastbit = least_bit(leftbits);
3194 compute_bit2idx(leastbit, i);
3195 b = smallbin_at(gm, i);
3197 assert(chunksize(p) == small_index2size(i));
3198 unlink_first_small_chunk(gm, b, p, i);
3199 rsize = small_index2size(i) - nb;
3200 /* Fit here cannot be remainderless if 4byte sizes */
3201 if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
3202 set_inuse_and_pinuse(gm, p, small_index2size(i));
3204 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3205 r = chunk_plus_offset(p, nb);
3206 set_size_and_pinuse_of_free_chunk(r, rsize);
3207 replace_dv(gm, r, rsize);
3210 check_malloced_chunk(gm, mem, nb);
3214 else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
3215 check_malloced_chunk(gm, mem, nb);
3220 else if (bytes >= MAX_REQUEST)
3221 nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
3223 nb = pad_request(bytes);
3224 if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
3225 check_malloced_chunk(gm, mem, nb);
3230 if (nb <= gm->dvsize) {
3231 size_t rsize = gm->dvsize - nb;
3232 mchunkptr p = gm->dv;
3233 if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
3234 mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
3236 set_size_and_pinuse_of_free_chunk(r, rsize);
3237 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3239 else { /* exhaust dv */
3240 size_t dvs = gm->dvsize;
3243 set_inuse_and_pinuse(gm, p, dvs);
3246 check_malloced_chunk(gm, mem, nb);
3250 else if (nb < gm->topsize) { /* Split top */
3251 size_t rsize = gm->topsize -= nb;
3252 mchunkptr p = gm->top;
3253 mchunkptr r = gm->top = chunk_plus_offset(p, nb);
3254 r->head = rsize | PINUSE_BIT;
3255 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3257 check_top_chunk(gm, gm->top);
3258 check_malloced_chunk(gm, mem, nb);
3262 mem = sys_alloc(gm, nb);
3272 /* ---------------------------- free --------------------------- */
3274 void dlfree(void* mem) {
3276 Consolidate freed chunks with preceeding or succeeding bordering
3277 free chunks, if they exist, and then place in a bin. Intermixed
3278 with special cases for top, dv, mmapped chunks, and usage errors.
3282 mchunkptr p = mem2chunk(mem);
3284 mstate fm = get_mstate_for(p);
3285 if (!ok_magic(fm)) {
3286 USAGE_ERROR_ACTION(fm, p);
3291 #endif /* FOOTERS */
3292 if (!PREACTION(fm)) {
3293 check_inuse_chunk(fm, p);
3294 if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
3295 size_t psize = chunksize(p);
3296 mchunkptr next = chunk_plus_offset(p, psize);
3298 size_t prevsize = p->prev_foot;
3299 if (is_mmapped(p)) {
3300 psize += prevsize + MMAP_FOOT_PAD;
3301 if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
3302 fm->footprint -= psize;
3306 mchunkptr prev = chunk_minus_offset(p, prevsize);
3309 if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
3311 unlink_chunk(fm, p, prevsize);
3313 else if ((next->head & INUSE_BITS) == INUSE_BITS) {
3315 set_free_with_pinuse(p, psize, next);
3324 if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
3325 if (!cinuse(next)) { /* consolidate forward */
3326 if (next == fm->top) {
3327 size_t tsize = fm->topsize += psize;
3329 p->head = tsize | PINUSE_BIT;
3334 if (should_trim(fm, tsize))
3338 else if (next == fm->dv) {
3339 size_t dsize = fm->dvsize += psize;
3341 set_size_and_pinuse_of_free_chunk(p, dsize);
3345 size_t nsize = chunksize(next);
3347 unlink_chunk(fm, next, nsize);
3348 set_size_and_pinuse_of_free_chunk(p, psize);
3356 set_free_with_pinuse(p, psize, next);
3358 if (is_small(psize)) {
3359 insert_small_chunk(fm, p, psize);
3360 check_free_chunk(fm, p);
3363 tchunkptr tp = (tchunkptr)p;
3364 insert_large_chunk(fm, tp, psize);
3365 check_free_chunk(fm, p);
3366 if (--fm->release_checks == 0)
3367 release_unused_segments(fm);
3373 USAGE_ERROR_ACTION(fm, p);
3380 #endif /* FOOTERS */
3383 void* dlcalloc(size_t n_elements, size_t elem_size) {
3386 if (n_elements != 0) {
3387 req = n_elements * elem_size;
3388 if (((n_elements | elem_size) & ~(size_t)0xffff) &&
3389 (req / n_elements != elem_size))
3390 req = MAX_SIZE_T; /* force downstream failure on overflow */
3392 mem = dlmalloc(req);
3393 if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
3394 memset(mem, 0, req);
3398 #endif /* !ONLY_MSPACES */
3400 /* ------------ Internal support for realloc, memalign, etc -------------- */
3402 /* Try to realloc; only in-place unless can_move true */
3403 static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb,
3406 size_t oldsize = chunksize(p);
3407 mchunkptr next = chunk_plus_offset(p, oldsize);
3408 if (RTCHECK(ok_address(m, p) && ok_inuse(p) &&
3409 ok_next(p, next) && ok_pinuse(next))) {
3410 if (is_mmapped(p)) {
3411 newp = mmap_resize(m, p, nb, can_move);
3413 else if (oldsize >= nb) { /* already big enough */
3414 size_t rsize = oldsize - nb;
3415 if (rsize >= MIN_CHUNK_SIZE) { /* split off remainder */
3416 mchunkptr r = chunk_plus_offset(p, nb);
3417 set_inuse(m, p, nb);
3418 set_inuse(m, r, rsize);
3419 dispose_chunk(m, r, rsize);
3423 else if (next == m->top) { /* extend into top */
3424 if (oldsize + m->topsize > nb) {
3425 size_t newsize = oldsize + m->topsize;
3426 size_t newtopsize = newsize - nb;
3427 mchunkptr newtop = chunk_plus_offset(p, nb);
3428 set_inuse(m, p, nb);
3429 newtop->head = newtopsize |PINUSE_BIT;
3431 m->topsize = newtopsize;
3435 else if (next == m->dv) { /* extend into dv */
3436 size_t dvs = m->dvsize;
3437 if (oldsize + dvs >= nb) {
3438 size_t dsize = oldsize + dvs - nb;
3439 if (dsize >= MIN_CHUNK_SIZE) {
3440 mchunkptr r = chunk_plus_offset(p, nb);
3441 mchunkptr n = chunk_plus_offset(r, dsize);
3442 set_inuse(m, p, nb);
3443 set_size_and_pinuse_of_free_chunk(r, dsize);
3448 else { /* exhaust dv */
3449 size_t newsize = oldsize + dvs;
3450 set_inuse(m, p, newsize);
3457 else if (!cinuse(next)) { /* extend into next free chunk */
3458 size_t nextsize = chunksize(next);
3459 if (oldsize + nextsize >= nb) {
3460 size_t rsize = oldsize + nextsize - nb;
3461 unlink_chunk(m, next, nextsize);
3462 if (rsize < MIN_CHUNK_SIZE) {
3463 size_t newsize = oldsize + nextsize;
3464 set_inuse(m, p, newsize);
3467 mchunkptr r = chunk_plus_offset(p, nb);
3468 set_inuse(m, p, nb);
3469 set_inuse(m, r, rsize);
3470 dispose_chunk(m, r, rsize);
3477 USAGE_ERROR_ACTION(m, chunk2mem(p));
3482 static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
3484 if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
3485 alignment = MIN_CHUNK_SIZE;
3486 if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
3487 size_t a = MALLOC_ALIGNMENT << 1;
3488 while (a < alignment) a <<= 1;
3491 if (bytes >= MAX_REQUEST - alignment) {
3492 if (m != 0) { /* Test isn't needed but avoids compiler warning */
3493 MALLOC_FAILURE_ACTION;
3497 size_t nb = request2size(bytes);
3498 size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
3499 mem = internal_malloc(m, req);
3501 mchunkptr p = mem2chunk(mem);
3504 if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */
3506 Find an aligned spot inside chunk. Since we need to give
3507 back leading space in a chunk of at least MIN_CHUNK_SIZE, if
3508 the first calculation places us at a spot with less than
3509 MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
3510 We've allocated enough total room so that this is always
3513 char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment -
3516 char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
3518 mchunkptr newp = (mchunkptr)pos;
3519 size_t leadsize = pos - (char*)(p);
3520 size_t newsize = chunksize(p) - leadsize;
3522 if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
3523 newp->prev_foot = p->prev_foot + leadsize;
3524 newp->head = newsize;
3526 else { /* Otherwise, give back leader, use the rest */
3527 set_inuse(m, newp, newsize);
3528 set_inuse(m, p, leadsize);
3529 dispose_chunk(m, p, leadsize);
3534 /* Give back spare room at the end */
3535 if (!is_mmapped(p)) {
3536 size_t size = chunksize(p);
3537 if (size > nb + MIN_CHUNK_SIZE) {
3538 size_t remainder_size = size - nb;
3539 mchunkptr remainder = chunk_plus_offset(p, nb);
3540 set_inuse(m, p, nb);
3541 set_inuse(m, remainder, remainder_size);
3542 dispose_chunk(m, remainder, remainder_size);
3547 assert (chunksize(p) >= nb);
3548 assert(((size_t)mem & (alignment - 1)) == 0);
3549 check_inuse_chunk(m, p);
3557 Common support for independent_X routines, handling
3558 all of the combinations that can result.
3560 bit 0 set if all elements are same size (using sizes[0])
3561 bit 1 set if elements should be zeroed
3563 static void** ialloc(mstate m,
3569 size_t element_size; /* chunksize of each element, if all same */
3570 size_t contents_size; /* total size of elements */
3571 size_t array_size; /* request size of pointer array */
3572 void* mem; /* malloced aggregate space */
3573 mchunkptr p; /* corresponding chunk */
3574 size_t remainder_size; /* remaining bytes while splitting */
3575 void** marray; /* either "chunks" or malloced ptr array */
3576 mchunkptr array_chunk; /* chunk for malloced ptr array */
3577 flag_t was_enabled; /* to disable mmap */
3581 ensure_initialization();
3582 /* compute array length, if needed */
3584 if (n_elements == 0)
3585 return chunks; /* nothing to do */
3590 /* if empty req, must still return chunk representing empty array */
3591 if (n_elements == 0)
3592 return (void**)internal_malloc(m, 0);
3594 array_size = request2size(n_elements * (sizeof(void*)));
3597 /* compute total element size */
3598 if (opts & 0x1) { /* all-same-size */
3599 element_size = request2size(*sizes);
3600 contents_size = n_elements * element_size;
3602 else { /* add up all the sizes */
3605 for (i = 0; i != n_elements; ++i)
3606 contents_size += request2size(sizes[i]);
3609 size = contents_size + array_size;
3612 Allocate the aggregate chunk. First disable direct-mmapping so
3613 malloc won't use it, since we would not be able to later
3614 free/realloc space internal to a segregated mmap region.
3616 was_enabled = use_mmap(m);
3618 mem = internal_malloc(m, size - CHUNK_OVERHEAD);
3624 if (PREACTION(m)) return 0;
3626 remainder_size = chunksize(p);
3628 assert(!is_mmapped(p));
3630 if (opts & 0x2) { /* optionally clear the elements */
3631 memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
3634 /* If not provided, allocate the pointer array as final part of chunk */
3636 size_t array_chunk_size;
3637 array_chunk = chunk_plus_offset(p, contents_size);
3638 array_chunk_size = remainder_size - contents_size;
3639 marray = (void**) (chunk2mem(array_chunk));
3640 set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
3641 remainder_size = contents_size;
3644 /* split out elements */
3645 for (i = 0; ; ++i) {
3646 marray[i] = chunk2mem(p);
3647 if (i != n_elements-1) {
3648 if (element_size != 0)
3649 size = element_size;
3651 size = request2size(sizes[i]);
3652 remainder_size -= size;
3653 set_size_and_pinuse_of_inuse_chunk(m, p, size);
3654 p = chunk_plus_offset(p, size);
3656 else { /* the final element absorbs any overallocation slop */
3657 set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
3663 if (marray != chunks) {
3664 /* final element must have exactly exhausted chunk */
3665 if (element_size != 0) {
3666 assert(remainder_size == element_size);
3669 assert(remainder_size == request2size(sizes[i]));
3671 check_inuse_chunk(m, mem2chunk(marray));
3673 for (i = 0; i != n_elements; ++i)
3674 check_inuse_chunk(m, mem2chunk(marray[i]));
3682 /* Try to free all pointers in the given array.
3683 Note: this could be made faster, by delaying consolidation,
3684 at the price of disabling some user integrity checks, We
3685 still optimize some consolidations by combining adjacent
3686 chunks before freeing, which will occur often if allocated
3687 with ialloc or the array is sorted.
3689 static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) {
3691 if (!PREACTION(m)) {
3693 void** fence = &(array[nelem]);
3694 for (a = array; a != fence; ++a) {
3697 mchunkptr p = mem2chunk(mem);
3698 size_t psize = chunksize(p);
3700 if (get_mstate_for(p) != m) {
3705 check_inuse_chunk(m, p);
3707 if (RTCHECK(ok_address(m, p) && ok_inuse(p))) {
3708 void ** b = a + 1; /* try to merge with next chunk */
3709 mchunkptr next = next_chunk(p);
3710 if (b != fence && *b == chunk2mem(next)) {
3711 size_t newsize = chunksize(next) + psize;
3712 set_inuse(m, p, newsize);
3716 dispose_chunk(m, p, psize);
3719 CORRUPTION_ERROR_ACTION(m);
3724 if (should_trim(m, m->topsize))
3732 #if MALLOC_INSPECT_ALL
3733 static void internal_inspect_all(mstate m,
3734 void(*handler)(void *start,
3737 void* callback_arg),
3739 if (is_initialized(m)) {
3740 mchunkptr top = m->top;
3742 for (s = &m->seg; s != 0; s = s->next) {
3743 mchunkptr q = align_as_chunk(s->base);
3744 while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) {
3745 mchunkptr next = next_chunk(q);
3746 size_t sz = chunksize(q);
3750 used = sz - CHUNK_OVERHEAD; /* must not be mmapped */
3751 start = chunk2mem(q);
3755 if (is_small(sz)) { /* offset by possible bookkeeping */
3756 start = (void*)((char*)q + sizeof(struct malloc_chunk));
3759 start = (void*)((char*)q + sizeof(struct malloc_tree_chunk));
3762 if (start < (void*)next) /* skip if all space is bookkeeping */
3763 handler(start, next, used, arg);
3771 #endif /* MALLOC_INSPECT_ALL */
3773 /* ------------------ Exported realloc, memalign, etc -------------------- */
3777 void* dlrealloc(void* oldmem, size_t bytes) {
3780 mem = dlmalloc(bytes);
3782 else if (bytes >= MAX_REQUEST) {
3783 MALLOC_FAILURE_ACTION;
3785 #ifdef REALLOC_ZERO_BYTES_FREES
3786 else if (bytes == 0) {
3789 #endif /* REALLOC_ZERO_BYTES_FREES */
3791 size_t nb = request2size(bytes);
3792 mchunkptr oldp = mem2chunk(oldmem);
3796 mstate m = get_mstate_for(oldp);
3798 USAGE_ERROR_ACTION(m, oldmem);
3801 #endif /* FOOTERS */
3802 if (!PREACTION(m)) {
3803 mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1);
3806 check_inuse_chunk(m, newp);
3807 mem = chunk2mem(newp);
3810 mem = internal_malloc(m, bytes);
3812 size_t oc = chunksize(oldp) - overhead_for(oldp);
3813 memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
3814 internal_free(m, oldmem);
3822 void* dlrealloc_in_place(void* oldmem, size_t bytes) {
3825 if (bytes >= MAX_REQUEST) {
3826 MALLOC_FAILURE_ACTION;
3829 size_t nb = request2size(bytes);
3830 mchunkptr oldp = mem2chunk(oldmem);
3834 mstate m = get_mstate_for(oldp);
3836 USAGE_ERROR_ACTION(m, oldmem);
3839 #endif /* FOOTERS */
3840 if (!PREACTION(m)) {
3841 mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0);
3844 check_inuse_chunk(m, newp);
3853 void* dlmemalign(size_t alignment, size_t bytes) {
3854 if (alignment <= MALLOC_ALIGNMENT) {
3855 return dlmalloc(bytes);
3857 return internal_memalign(gm, alignment, bytes);
3860 int dlposix_memalign(void** pp, size_t alignment, size_t bytes) {
3862 if (alignment == MALLOC_ALIGNMENT)
3863 mem = dlmalloc(bytes);
3865 size_t d = alignment / sizeof(void*);
3866 size_t r = alignment % sizeof(void*);
3867 if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0)
3869 else if (bytes <= MAX_REQUEST - alignment) {
3870 if (alignment < MIN_CHUNK_SIZE)
3871 alignment = MIN_CHUNK_SIZE;
3872 mem = internal_memalign(gm, alignment, bytes);
3883 void* dlvalloc(size_t bytes) {
3885 ensure_initialization();
3886 pagesz = mparams.page_size;
3887 return dlmemalign(pagesz, bytes);
3890 void* dlpvalloc(size_t bytes) {
3892 ensure_initialization();
3893 pagesz = mparams.page_size;
3894 return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
3897 void** dlindependent_calloc(size_t n_elements, size_t elem_size,
3899 size_t sz = elem_size; /* serves as 1-element array */
3900 return ialloc(gm, n_elements, &sz, 3, chunks);
3903 void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
3905 return ialloc(gm, n_elements, sizes, 0, chunks);
3908 size_t dlbulk_free(void* array[], size_t nelem) {
3909 return internal_bulk_free(gm, array, nelem);
3912 #if MALLOC_INSPECT_ALL
3913 void dlmalloc_inspect_all(void(*handler)(void *start,
3916 void* callback_arg),
3918 ensure_initialization();
3919 if (!PREACTION(gm)) {
3920 internal_inspect_all(gm, handler, arg);
3924 #endif /* MALLOC_INSPECT_ALL */
3926 int dlmalloc_trim(size_t pad) {
3928 ensure_initialization();
3929 if (!PREACTION(gm)) {
3930 result = sys_trim(gm, pad);
3936 size_t dlmalloc_footprint(void) {
3937 return gm->footprint;
3940 size_t dlmalloc_max_footprint(void) {
3941 return gm->max_footprint;
3944 size_t dlmalloc_footprint_limit(void) {
3945 size_t maf = gm->footprint_limit;
3946 return maf == 0 ? MAX_SIZE_T : maf;
3949 size_t dlmalloc_set_footprint_limit(size_t bytes) {
3950 size_t result; /* invert sense of 0 */
3952 result = granularity_align(1); /* Use minimal size */
3953 if (bytes == MAX_SIZE_T)
3954 result = 0; /* disable */
3956 result = granularity_align(bytes);
3957 return gm->footprint_limit = result;
3961 struct mallinfo dlmallinfo(void) {
3962 return internal_mallinfo(gm);
3964 #endif /* NO_MALLINFO */
3966 #if !NO_MALLOC_STATS
3967 void dlmalloc_stats() {
3968 internal_malloc_stats(gm);
3970 #endif /* NO_MALLOC_STATS */
3972 int dlmallopt(int param_number, int value) {
3973 return change_mparam(param_number, value);
3976 size_t dlmalloc_usable_size(void* mem) {
3978 mchunkptr p = mem2chunk(mem);
3980 return chunksize(p) - overhead_for(p);
3985 #endif /* !ONLY_MSPACES */
3987 /* ----------------------------- user mspaces ---------------------------- */
3991 static mstate init_user_mstate(char* tbase, size_t tsize) {
3992 size_t msize = pad_request(sizeof(struct malloc_state));
3994 mchunkptr msp = align_as_chunk(tbase);
3995 mstate m = (mstate)(chunk2mem(msp));
3996 memset(m, 0, msize);
3997 (void)INITIAL_LOCK(&m->mutex);
3998 msp->head = (msize|INUSE_BITS);
3999 m->seg.base = m->least_addr = tbase;
4000 m->seg.size = m->footprint = m->max_footprint = tsize;
4001 m->magic = mparams.magic;
4002 m->release_checks = MAX_RELEASE_CHECK_RATE;
4003 m->mflags = mparams.default_mflags;
4006 disable_contiguous(m);
4008 mn = next_chunk(mem2chunk(m));
4009 init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
4010 check_top_chunk(m, m->top);
4014 mspace create_mspace(size_t capacity, int locked) {
4017 ensure_initialization();
4018 msize = pad_request(sizeof(struct malloc_state));
4019 if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4020 size_t rs = ((capacity == 0)? mparams.granularity :
4021 (capacity + TOP_FOOT_SIZE + msize));
4022 size_t tsize = granularity_align(rs);
4023 char* tbase = (char*)(CALL_MMAP(tsize));
4024 if (tbase != CMFAIL) {
4025 m = init_user_mstate(tbase, tsize);
4026 m->seg.sflags = USE_MMAP_BIT;
4027 set_lock(m, locked);
4033 mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
4036 ensure_initialization();
4037 msize = pad_request(sizeof(struct malloc_state));
4038 if (capacity > msize + TOP_FOOT_SIZE &&
4039 capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4040 m = init_user_mstate((char*)base, capacity);
4041 m->seg.sflags = EXTERN_BIT;
4042 set_lock(m, locked);
4047 int mspace_track_large_chunks(mspace msp, int enable) {
4049 mstate ms = (mstate)msp;
4050 if (!PREACTION(ms)) {
4051 if (!use_mmap(ms)) {
4064 size_t destroy_mspace(mspace msp) {
4066 mstate ms = (mstate)msp;
4068 msegmentptr sp = &ms->seg;
4069 (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */
4071 char* base = sp->base;
4072 size_t size = sp->size;
4073 flag_t flag = sp->sflags;
4074 (void)base; /* placate people compiling -Wunused-variable */
4076 if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) &&
4077 CALL_MUNMAP(base, size) == 0)
4082 USAGE_ERROR_ACTION(ms,ms);
4087 void mspace_get_address_and_size (mspace msp, unsigned long long *addrp,
4088 unsigned long long *sizep)
4094 this_seg = &ms->seg;
4096 *addrp = (unsigned long long) this_seg->base;
4097 *sizep = this_seg->size;
4100 int mspace_is_heap_object (mspace msp, void *p)
4108 this_seg = &ms->seg;
4113 base = this_seg->base;
4114 if (pp >= base && pp < (base + this_seg->size))
4116 this_seg = this_seg->next;
4121 void *mspace_least_addr (mspace msp)
4123 mstate ms = (mstate) msp;
4124 return (void *) ms->least_addr;
4127 void mspace_disable_expand (mspace msp)
4129 mstate ms = (mstate)msp;
4131 disable_expand (ms);
4134 int mspace_enable_disable_trace (mspace msp, int enable)
4136 mstate ms = (mstate)msp;
4137 int was_enabled = 0;
4147 return (was_enabled);
4150 void* mspace_get_aligned (mspace msp,
4151 unsigned long long n_user_data_bytes,
4152 unsigned long long align,
4153 unsigned long long align_offset) {
4155 unsigned long long searchp;
4156 unsigned *wwp; /* "where's Waldo" pointer */
4157 mstate ms = (mstate)msp;
4160 * Allocate space for the "Where's Waldo?" pointer
4161 * the base of the dlmalloc object
4163 n_user_data_bytes += sizeof(unsigned);
4166 * Alignment requests less than the size of an mmx vector are ignored
4169 rv = mspace_malloc (msp, n_user_data_bytes);
4173 if (use_trace(ms)) {
4174 mchunkptr p = mem2chunk(rv);
4175 size_t psize = chunksize(p);
4177 mheap_get_trace ((u64)rv + sizeof (unsigned), psize);
4180 wwp = (unsigned *)rv;
4182 rv += sizeof (unsigned);
4188 * Alignment requests greater than 4K must be at offset zero,
4189 * and must be freed using mspace_free_no_offset - or never freed -
4190 * since the "Where's Waldo?" pointer would waste too much space.
4192 * Waldo is the address of the chunk of memory returned by mspace_malloc,
4193 * which we need later to call mspace_free...
4195 if (align > 4<<10 || align_offset == ~0ULL) {
4196 n_user_data_bytes -= sizeof(unsigned);
4197 assert(align_offset == 0);
4198 rv = internal_memalign(ms, (size_t)align, n_user_data_bytes);
4200 /* Trace the allocation */
4201 if (rv && use_trace(ms)) {
4202 mchunkptr p = mem2chunk(rv);
4203 size_t psize = chunksize(p);
4204 mheap_get_trace ((u64)rv, psize);
4209 align = clib_max (align, MALLOC_ALIGNMENT);
4210 align = max_pow2 (align);
4212 /* Correct align offset to be smaller than alignment. */
4213 align_offset &= (align - 1);
4215 n_user_data_bytes += align;
4216 rv = mspace_malloc (msp, n_user_data_bytes);
4221 /* Honor the alignment request */
4222 searchp = (unsigned long long)(rv + sizeof (unsigned));
4224 #if 0 /* this is the idea... */
4225 while ((searchp + align_offset) % align)
4230 unsigned long long where_now, delta;
4232 where_now = (searchp + align_offset) % align;
4233 delta = align - where_now;
4238 wwp = (unsigned *)(searchp - sizeof(unsigned));
4239 *wwp = (searchp - (((unsigned long long) rv) + sizeof (*wwp)));
4240 assert (*wwp < align);
4242 if (use_trace(ms)) {
4243 mchunkptr p = mem2chunk(rv);
4244 size_t psize = chunksize(p);
4245 mheap_get_trace ((u64)rv, psize);
4247 return (void *) searchp;
4250 void mspace_put (mspace msp, void *p_arg)
4252 char *object_header;
4254 mstate ms = (mstate)msp;
4256 /* Find the object header delta */
4257 wwp = (unsigned *)p_arg;
4260 /* Recover the dlmalloc object pointer */
4261 object_header = (char *)wwp;
4262 object_header -= *wwp;
4264 /* Tracing (if enabled) */
4267 mchunkptr p = mem2chunk(object_header);
4268 size_t psize = chunksize(p);
4270 mheap_put_trace ((u64)p_arg, psize);
4273 /* And free it... */
4274 mspace_free (msp, object_header);
4277 void mspace_put_no_offset (mspace msp, void *p_arg)
4279 mstate ms = (mstate)msp;
4283 mchunkptr p = mem2chunk(p_arg);
4284 size_t psize = chunksize(p);
4286 mheap_put_trace ((u64)p_arg, psize);
4288 mspace_free (msp, p_arg);
4291 size_t mspace_usable_size_with_delta (const void *p)
4294 char *object_header;
4297 /* Find the object header delta */
4298 wwp = (unsigned *)p;
4301 /* Recover the dlmalloc object pointer */
4302 object_header = (char *)wwp;
4303 object_header -= *wwp;
4305 usable_size = mspace_usable_size (object_header);
4306 /* account for the offset and the size of the offset... */
4307 usable_size -= (*wwp + sizeof (*wwp));
4312 mspace versions of routines are near-clones of the global
4313 versions. This is not so nice but better than the alternatives.
4316 void* mspace_malloc(mspace msp, size_t bytes) {
4317 mstate ms = (mstate)msp;
4318 if (!ok_magic(ms)) {
4319 USAGE_ERROR_ACTION(ms,ms);
4322 if (!PREACTION(ms)) {
4325 if (bytes <= MAX_SMALL_REQUEST) {
4328 nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4329 idx = small_index(nb);
4330 smallbits = ms->smallmap >> idx;
4332 if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4334 idx += ~smallbits & 1; /* Uses next bin if idx empty */
4335 b = smallbin_at(ms, idx);
4337 assert(chunksize(p) == small_index2size(idx));
4338 unlink_first_small_chunk(ms, b, p, idx);
4339 set_inuse_and_pinuse(ms, p, small_index2size(idx));
4341 check_malloced_chunk(ms, mem, nb);
4345 else if (nb > ms->dvsize) {
4346 if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4350 binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4351 binmap_t leastbit = least_bit(leftbits);
4352 compute_bit2idx(leastbit, i);
4353 b = smallbin_at(ms, i);
4355 assert(chunksize(p) == small_index2size(i));
4356 unlink_first_small_chunk(ms, b, p, i);
4357 rsize = small_index2size(i) - nb;
4358 /* Fit here cannot be remainderless if 4byte sizes */
4359 if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4360 set_inuse_and_pinuse(ms, p, small_index2size(i));
4362 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4363 r = chunk_plus_offset(p, nb);
4364 set_size_and_pinuse_of_free_chunk(r, rsize);
4365 replace_dv(ms, r, rsize);
4368 check_malloced_chunk(ms, mem, nb);
4372 else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
4373 check_malloced_chunk(ms, mem, nb);
4378 else if (bytes >= MAX_REQUEST)
4379 nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
4381 nb = pad_request(bytes);
4382 if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
4383 check_malloced_chunk(ms, mem, nb);
4388 if (nb <= ms->dvsize) {
4389 size_t rsize = ms->dvsize - nb;
4390 mchunkptr p = ms->dv;
4391 if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4392 mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
4394 set_size_and_pinuse_of_free_chunk(r, rsize);
4395 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4397 else { /* exhaust dv */
4398 size_t dvs = ms->dvsize;
4401 set_inuse_and_pinuse(ms, p, dvs);
4404 check_malloced_chunk(ms, mem, nb);
4408 else if (nb < ms->topsize) { /* Split top */
4409 size_t rsize = ms->topsize -= nb;
4410 mchunkptr p = ms->top;
4411 mchunkptr r = ms->top = chunk_plus_offset(p, nb);
4412 r->head = rsize | PINUSE_BIT;
4413 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4415 check_top_chunk(ms, ms->top);
4416 check_malloced_chunk(ms, mem, nb);
4420 mem = sys_alloc(ms, nb);
4430 void mspace_free(mspace msp, void* mem) {
4432 mchunkptr p = mem2chunk(mem);
4434 mstate fm = get_mstate_for(p);
4435 (void)msp; /* placate people compiling -Wunused */
4437 mstate fm = (mstate)msp;
4438 #endif /* FOOTERS */
4439 if (!ok_magic(fm)) {
4440 USAGE_ERROR_ACTION(fm, p);
4443 if (!PREACTION(fm)) {
4444 check_inuse_chunk(fm, p);
4445 if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
4446 size_t psize = chunksize(p);
4447 mchunkptr next = chunk_plus_offset(p, psize);
4449 size_t prevsize = p->prev_foot;
4450 if (is_mmapped(p)) {
4451 psize += prevsize + MMAP_FOOT_PAD;
4452 if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4453 fm->footprint -= psize;
4457 mchunkptr prev = chunk_minus_offset(p, prevsize);
4460 if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4462 unlink_chunk(fm, p, prevsize);
4464 else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4466 set_free_with_pinuse(p, psize, next);
4475 if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4476 if (!cinuse(next)) { /* consolidate forward */
4477 if (next == fm->top) {
4478 size_t tsize = fm->topsize += psize;
4480 p->head = tsize | PINUSE_BIT;
4485 if (should_trim(fm, tsize))
4489 else if (next == fm->dv) {
4490 size_t dsize = fm->dvsize += psize;
4492 set_size_and_pinuse_of_free_chunk(p, dsize);
4496 size_t nsize = chunksize(next);
4498 unlink_chunk(fm, next, nsize);
4499 set_size_and_pinuse_of_free_chunk(p, psize);
4507 set_free_with_pinuse(p, psize, next);
4509 if (is_small(psize)) {
4510 insert_small_chunk(fm, p, psize);
4511 check_free_chunk(fm, p);
4514 tchunkptr tp = (tchunkptr)p;
4515 insert_large_chunk(fm, tp, psize);
4516 check_free_chunk(fm, p);
4517 if (--fm->release_checks == 0)
4518 release_unused_segments(fm);
4524 USAGE_ERROR_ACTION(fm, p);
4531 void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
4534 mstate ms = (mstate)msp;
4535 if (!ok_magic(ms)) {
4536 USAGE_ERROR_ACTION(ms,ms);
4539 if (n_elements != 0) {
4540 req = n_elements * elem_size;
4541 if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4542 (req / n_elements != elem_size))
4543 req = MAX_SIZE_T; /* force downstream failure on overflow */
4545 mem = internal_malloc(ms, req);
4546 if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4547 memset(mem, 0, req);
4551 void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
4554 mem = mspace_malloc(msp, bytes);
4556 else if (bytes >= MAX_REQUEST) {
4557 MALLOC_FAILURE_ACTION;
4559 #ifdef REALLOC_ZERO_BYTES_FREES
4560 else if (bytes == 0) {
4561 mspace_free(msp, oldmem);
4563 #endif /* REALLOC_ZERO_BYTES_FREES */
4565 size_t nb = request2size(bytes);
4566 mchunkptr oldp = mem2chunk(oldmem);
4568 mstate m = (mstate)msp;
4570 mstate m = get_mstate_for(oldp);
4572 USAGE_ERROR_ACTION(m, oldmem);
4575 #endif /* FOOTERS */
4576 if (!PREACTION(m)) {
4577 mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1);
4580 check_inuse_chunk(m, newp);
4581 mem = chunk2mem(newp);
4584 mem = mspace_malloc(m, bytes);
4586 size_t oc = chunksize(oldp) - overhead_for(oldp);
4587 memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
4588 mspace_free(m, oldmem);
4596 void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) {
4599 if (bytes >= MAX_REQUEST) {
4600 MALLOC_FAILURE_ACTION;
4603 size_t nb = request2size(bytes);
4604 mchunkptr oldp = mem2chunk(oldmem);
4606 mstate m = (mstate)msp;
4608 mstate m = get_mstate_for(oldp);
4609 (void)msp; /* placate people compiling -Wunused */
4611 USAGE_ERROR_ACTION(m, oldmem);
4614 #endif /* FOOTERS */
4615 if (!PREACTION(m)) {
4616 mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0);
4619 check_inuse_chunk(m, newp);
4628 void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
4629 mstate ms = (mstate)msp;
4630 if (!ok_magic(ms)) {
4631 USAGE_ERROR_ACTION(ms,ms);
4634 if (alignment <= MALLOC_ALIGNMENT)
4635 return mspace_malloc(msp, bytes);
4636 return internal_memalign(ms, alignment, bytes);
4639 void** mspace_independent_calloc(mspace msp, size_t n_elements,
4640 size_t elem_size, void* chunks[]) {
4641 size_t sz = elem_size; /* serves as 1-element array */
4642 mstate ms = (mstate)msp;
4643 if (!ok_magic(ms)) {
4644 USAGE_ERROR_ACTION(ms,ms);
4647 return ialloc(ms, n_elements, &sz, 3, chunks);
4650 void** mspace_independent_comalloc(mspace msp, size_t n_elements,
4651 size_t sizes[], void* chunks[]) {
4652 mstate ms = (mstate)msp;
4653 if (!ok_magic(ms)) {
4654 USAGE_ERROR_ACTION(ms,ms);
4657 return ialloc(ms, n_elements, sizes, 0, chunks);
4660 size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) {
4661 return internal_bulk_free((mstate)msp, array, nelem);
4664 #if MALLOC_INSPECT_ALL
4665 void mspace_inspect_all(mspace msp,
4666 void(*handler)(void *start,
4669 void* callback_arg),
4671 mstate ms = (mstate)msp;
4673 if (!PREACTION(ms)) {
4674 internal_inspect_all(ms, handler, arg);
4679 USAGE_ERROR_ACTION(ms,ms);
4682 #endif /* MALLOC_INSPECT_ALL */
4684 int mspace_trim(mspace msp, size_t pad) {
4686 mstate ms = (mstate)msp;
4688 if (!PREACTION(ms)) {
4689 result = sys_trim(ms, pad);
4694 USAGE_ERROR_ACTION(ms,ms);
4699 #if !NO_MALLOC_STATS
4700 void mspace_malloc_stats(mspace msp) {
4701 mstate ms = (mstate)msp;
4703 internal_malloc_stats(ms);
4706 USAGE_ERROR_ACTION(ms,ms);
4709 #endif /* NO_MALLOC_STATS */
4711 size_t mspace_footprint(mspace msp) {
4713 mstate ms = (mstate)msp;
4715 result = ms->footprint;
4718 USAGE_ERROR_ACTION(ms,ms);
4723 size_t mspace_max_footprint(mspace msp) {
4725 mstate ms = (mstate)msp;
4727 result = ms->max_footprint;
4730 USAGE_ERROR_ACTION(ms,ms);
4735 size_t mspace_footprint_limit(mspace msp) {
4737 mstate ms = (mstate)msp;
4739 size_t maf = ms->footprint_limit;
4740 result = (maf == 0) ? MAX_SIZE_T : maf;
4743 USAGE_ERROR_ACTION(ms,ms);
4748 size_t mspace_set_footprint_limit(mspace msp, size_t bytes) {
4750 mstate ms = (mstate)msp;
4753 result = granularity_align(1); /* Use minimal size */
4754 if (bytes == MAX_SIZE_T)
4755 result = 0; /* disable */
4757 result = granularity_align(bytes);
4758 ms->footprint_limit = result;
4761 USAGE_ERROR_ACTION(ms,ms);
4767 struct mallinfo mspace_mallinfo(mspace msp) {
4768 mstate ms = (mstate)msp;
4769 if (!ok_magic(ms)) {
4770 USAGE_ERROR_ACTION(ms,ms);
4772 return internal_mallinfo(ms);
4774 #endif /* NO_MALLINFO */
4776 size_t mspace_usable_size(const void* mem) {
4778 mchunkptr p = mem2chunk(mem);
4780 return chunksize(p) - overhead_for(p);
4785 int mspace_mallopt(int param_number, int value) {
4786 return change_mparam(param_number, value);
4789 #endif /* MSPACES */
4792 /* -------------------- Alternative MORECORE functions ------------------- */
4795 Guidelines for creating a custom version of MORECORE:
4797 * For best performance, MORECORE should allocate in multiples of pagesize.
4798 * MORECORE may allocate more memory than requested. (Or even less,
4799 but this will usually result in a malloc failure.)
4800 * MORECORE must not allocate memory when given argument zero, but
4801 instead return one past the end address of memory from previous
4803 * For best performance, consecutive calls to MORECORE with positive
4804 arguments should return increasing addresses, indicating that
4805 space has been contiguously extended.
4806 * Even though consecutive calls to MORECORE need not return contiguous
4807 addresses, it must be OK for malloc'ed chunks to span multiple
4808 regions in those cases where they do happen to be contiguous.
4809 * MORECORE need not handle negative arguments -- it may instead
4810 just return MFAIL when given negative arguments.
4811 Negative arguments are always multiples of pagesize. MORECORE
4812 must not misinterpret negative args as large positive unsigned
4813 args. You can suppress all such calls from even occurring by defining
4814 MORECORE_CANNOT_TRIM,
4816 As an example alternative MORECORE, here is a custom allocator
4817 kindly contributed for pre-OSX macOS. It uses virtually but not
4818 necessarily physically contiguous non-paged memory (locked in,
4819 present and won't get swapped out). You can use it by uncommenting
4820 this section, adding some #includes, and setting up the appropriate
4823 #define MORECORE osMoreCore
4825 There is also a shutdown routine that should somehow be called for
4826 cleanup upon program exit.
4828 #define MAX_POOL_ENTRIES 100
4829 #define MINIMUM_MORECORE_SIZE (64 * 1024U)
4830 static int next_os_pool;
4831 void *our_os_pools[MAX_POOL_ENTRIES];
4833 void *osMoreCore(int size)
4836 static void *sbrk_top = 0;
4840 if (size < MINIMUM_MORECORE_SIZE)
4841 size = MINIMUM_MORECORE_SIZE;
4842 if (CurrentExecutionLevel() == kTaskLevel)
4843 ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
4846 return (void *) MFAIL;
4848 // save ptrs so they can be freed during cleanup
4849 our_os_pools[next_os_pool] = ptr;
4851 ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
4852 sbrk_top = (char *) ptr + size;
4857 // we don't currently support shrink behavior
4858 return (void *) MFAIL;
4866 // cleanup any allocated memory pools
4867 // called as last thing before shutting down driver
4869 void osCleanupMem(void)
4873 for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
4876 PoolDeallocate(*ptr);
4884 /* -----------------------------------------------------------------------
4886 v2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea
4887 * fix bad comparison in dlposix_memalign
4888 * don't reuse adjusted asize in sys_alloc
4889 * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion
4890 * reduce compiler warnings -- thanks to all who reported/suggested these
4892 v2.8.5 Sun May 22 10:26:02 2011 Doug Lea (dl at gee)
4893 * Always perform unlink checks unless INSECURE
4894 * Add posix_memalign.
4895 * Improve realloc to expand in more cases; expose realloc_in_place.
4896 Thanks to Peter Buhr for the suggestion.
4897 * Add footprint_limit, inspect_all, bulk_free. Thanks
4898 to Barry Hayes and others for the suggestions.
4899 * Internal refactorings to avoid calls while holding locks
4900 * Use non-reentrant locks by default. Thanks to Roland McGrath
4902 * Small fixes to mspace_destroy, reset_on_error.
4903 * Various configuration extensions/changes. Thanks
4904 to all who contributed these.
4906 V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu)
4907 * Update Creative Commons URL
4909 V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee)
4910 * Use zeros instead of prev foot for is_mmapped
4911 * Add mspace_track_large_chunks; thanks to Jean Brouwers
4912 * Fix set_inuse in internal_realloc; thanks to Jean Brouwers
4913 * Fix insufficient sys_alloc padding when using 16byte alignment
4914 * Fix bad error check in mspace_footprint
4915 * Adaptations for ptmalloc; thanks to Wolfram Gloger.
4916 * Reentrant spin locks; thanks to Earl Chew and others
4917 * Win32 improvements; thanks to Niall Douglas and Earl Chew
4918 * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options
4919 * Extension hook in malloc_state
4920 * Various small adjustments to reduce warnings on some compilers
4921 * Various configuration extensions/changes for more platforms. Thanks
4922 to all who contributed these.
4924 V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee)
4925 * Add max_footprint functions
4926 * Ensure all appropriate literals are size_t
4927 * Fix conditional compilation problem for some #define settings
4928 * Avoid concatenating segments with the one provided
4929 in create_mspace_with_base
4930 * Rename some variables to avoid compiler shadowing warnings
4931 * Use explicit lock initialization.
4932 * Better handling of sbrk interference.
4933 * Simplify and fix segment insertion, trimming and mspace_destroy
4934 * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
4935 * Thanks especially to Dennis Flanagan for help on these.
4937 V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee)
4938 * Fix memalign brace error.
4940 V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee)
4941 * Fix improper #endif nesting in C++
4942 * Add explicit casts needed for C++
4944 V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee)
4945 * Use trees for large bins
4947 * Use segments to unify sbrk-based and mmap-based system allocation,
4948 removing need for emulation on most platforms without sbrk.
4949 * Default safety checks
4950 * Optional footer checks. Thanks to William Robertson for the idea.
4951 * Internal code refactoring
4952 * Incorporate suggestions and platform-specific changes.
4953 Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
4954 Aaron Bachmann, Emery Berger, and others.
4955 * Speed up non-fastbin processing enough to remove fastbins.
4956 * Remove useless cfree() to avoid conflicts with other apps.
4957 * Remove internal memcpy, memset. Compilers handle builtins better.
4958 * Remove some options that no one ever used and rename others.
4960 V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
4961 * Fix malloc_state bitmap array misdeclaration
4963 V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee)
4964 * Allow tuning of FIRST_SORTED_BIN_SIZE
4965 * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
4966 * Better detection and support for non-contiguousness of MORECORE.
4967 Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
4968 * Bypass most of malloc if no frees. Thanks To Emery Berger.
4969 * Fix freeing of old top non-contiguous chunk im sysmalloc.
4970 * Raised default trim and map thresholds to 256K.
4971 * Fix mmap-related #defines. Thanks to Lubos Lunak.
4972 * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
4973 * Branch-free bin calculation
4974 * Default trim and mmap thresholds now 256K.
4976 V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee)
4977 * Introduce independent_comalloc and independent_calloc.
4978 Thanks to Michael Pachos for motivation and help.
4979 * Make optional .h file available
4980 * Allow > 2GB requests on 32bit systems.
4981 * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
4982 Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
4984 * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
4986 * memalign: check alignment arg
4987 * realloc: don't try to shift chunks backwards, since this
4988 leads to more fragmentation in some programs and doesn't
4989 seem to help in any others.
4990 * Collect all cases in malloc requiring system memory into sysmalloc
4991 * Use mmap as backup to sbrk
4992 * Place all internal state in malloc_state
4993 * Introduce fastbins (although similar to 2.5.1)
4994 * Many minor tunings and cosmetic improvements
4995 * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
4996 * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
4997 Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
4998 * Include errno.h to support default failure action.
5000 V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee)
5001 * return null for negative arguments
5002 * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
5003 * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
5004 (e.g. WIN32 platforms)
5005 * Cleanup header file inclusion for WIN32 platforms
5006 * Cleanup code to avoid Microsoft Visual C++ compiler complaints
5007 * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
5008 memory allocation routines
5009 * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
5010 * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
5011 usage of 'assert' in non-WIN32 code
5012 * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
5014 * Always call 'fREe()' rather than 'free()'
5016 V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee)
5017 * Fixed ordering problem with boundary-stamping
5019 V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
5020 * Added pvalloc, as recommended by H.J. Liu
5021 * Added 64bit pointer support mainly from Wolfram Gloger
5022 * Added anonymously donated WIN32 sbrk emulation
5023 * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
5024 * malloc_extend_top: fix mask error that caused wastage after
5026 * Add linux mremap support code from HJ Liu
5028 V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
5029 * Integrated most documentation with the code.
5030 * Add support for mmap, with help from
5031 Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5032 * Use last_remainder in more cases.
5033 * Pack bins using idea from colin@nyx10.cs.du.edu
5034 * Use ordered bins instead of best-fit threshhold
5035 * Eliminate block-local decls to simplify tracing and debugging.
5036 * Support another case of realloc via move into top
5037 * Fix error occuring when initial sbrk_base not word-aligned.
5038 * Rely on page size for units instead of SBRK_UNIT to
5039 avoid surprises about sbrk alignment conventions.
5040 * Add mallinfo, mallopt. Thanks to Raymond Nijssen
5041 (raymond@es.ele.tue.nl) for the suggestion.
5042 * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
5043 * More precautions for cases where other routines call sbrk,
5044 courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5045 * Added macros etc., allowing use in linux libc from
5046 H.J. Lu (hjl@gnu.ai.mit.edu)
5047 * Inverted this history list
5049 V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
5050 * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
5051 * Removed all preallocation code since under current scheme
5052 the work required to undo bad preallocations exceeds
5053 the work saved in good cases for most test programs.
5054 * No longer use return list or unconsolidated bins since
5055 no scheme using them consistently outperforms those that don't
5056 given above changes.
5057 * Use best fit for very large chunks to prevent some worst-cases.
5058 * Added some support for debugging
5060 V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
5061 * Removed footers when chunks are in use. Thanks to
5062 Paul Wilson (wilson@cs.texas.edu) for the suggestion.
5064 V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
5065 * Added malloc_trim, with help from Wolfram Gloger
5066 (wmglo@Dent.MED.Uni-Muenchen.DE).
5068 V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
5070 V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
5071 * realloc: try to expand in both directions
5072 * malloc: swap order of clean-bin strategy;
5073 * realloc: only conditionally expand backwards
5074 * Try not to scavenge used bins
5075 * Use bin counts as a guide to preallocation
5076 * Occasionally bin return list chunks in first scan
5077 * Add a few optimizations from colin@nyx10.cs.du.edu
5079 V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
5080 * faster bin computation & slightly different binning
5081 * merged all consolidations to one part of malloc proper
5082 (eliminating old malloc_find_space & malloc_clean_bin)
5083 * Scan 2 returns chunks (not just 1)
5084 * Propagate failure in realloc if malloc returns 0
5085 * Add stuff to allow compilation on non-ANSI compilers
5086 from kpv@research.att.com
5088 V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
5089 * removed potential for odd address access in prev_chunk
5090 * removed dependency on getpagesize.h
5091 * misc cosmetics and a bit more internal documentation
5092 * anticosmetics: mangled names in macros to evade debugger strangeness
5093 * tested on sparc, hp-700, dec-mips, rs6000
5094 with gcc & native cc (hp, dec only) allowing
5095 Detlefs & Zorn comparison study (in SIGPLAN Notices.)
5097 Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
5098 * Based loosely on libg++-1.2X malloc. (It retains some of the overall
5099 structure of old version, but most details differ.)