13f0dff8203d961594d86ef40abbc49f4d8f9ae5
[vpp.git] / src / vppinfra / dlmalloc.c
1 /*
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
6 */
7
8 #include <vppinfra/dlmalloc.h>
9 #include <vppinfra/sanitizer.h>
10
11 /*------------------------------ internal #includes ---------------------- */
12
13 #ifdef _MSC_VER
14 #pragma warning( disable : 4146 ) /* no "unsigned" warnings */
15 #endif /* _MSC_VER */
16 #if !NO_MALLOC_STATS
17 #include <stdio.h>       /* for printing in malloc_stats */
18 #endif /* NO_MALLOC_STATS */
19 #ifndef LACKS_ERRNO_H
20 #include <errno.h>       /* for MALLOC_FAILURE_ACTION */
21 #endif /* LACKS_ERRNO_H */
22 #ifdef DEBUG
23 #if DLM_ABORT_ON_ASSERT_FAILURE
24 #undef assert
25 #define assert(x) if(!(x)) DLM_ABORT
26 #else /* DLM_ABORT_ON_ASSERT_FAILURE */
27 #include <assert.h>
28 #endif /* DLM_ABORT_ON_ASSERT_FAILURE */
29 #else  /* DEBUG */
30 #ifndef assert
31 #define assert(x)
32 #endif
33 #define DEBUG 0
34 #endif /* DEBUG */
35 #if !defined(WIN32) && !defined(LACKS_TIME_H)
36 #include <time.h>        /* for magic initialization */
37 #endif /* WIN32 */
38 #ifndef LACKS_STDLIB_H
39 #include <stdlib.h>      /* for abort() */
40 #endif /* LACKS_STDLIB_H */
41 #ifndef LACKS_STRING_H
42 #include <string.h>      /* for memset etc */
43 #endif  /* LACKS_STRING_H */
44 #if USE_BUILTIN_FFS
45 #ifndef LACKS_STRINGS_H
46 #include <strings.h>     /* for ffs */
47 #endif /* LACKS_STRINGS_H */
48 #endif /* USE_BUILTIN_FFS */
49 #if HAVE_MMAP
50 #ifndef LACKS_SYS_MMAN_H
51 /* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */
52 #if (defined(linux) && !defined(__USE_GNU))
53 #define __USE_GNU 1
54 #include <sys/mman.h>    /* for mmap */
55 #undef __USE_GNU
56 #else
57 #include <sys/mman.h>    /* for mmap */
58 #endif /* linux */
59 #endif /* LACKS_SYS_MMAN_H */
60 #ifndef LACKS_FCNTL_H
61 #include <fcntl.h>
62 #endif /* LACKS_FCNTL_H */
63 #endif /* HAVE_MMAP */
64 #ifndef LACKS_UNISTD_H
65 #include <unistd.h>     /* for sbrk, sysconf */
66 #else /* LACKS_UNISTD_H */
67 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
68 extern void*     sbrk(ptrdiff_t);
69 #endif /* FreeBSD etc */
70 #endif /* LACKS_UNISTD_H */
71
72 /* Declarations for locking */
73 #if USE_LOCKS
74 #ifndef WIN32
75 #if defined (__SVR4) && defined (__sun)  /* solaris */
76 #include <thread.h>
77 #elif !defined(LACKS_SCHED_H)
78 #include <sched.h>
79 #endif /* solaris or LACKS_SCHED_H */
80 #if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS
81 #include <pthread.h>
82 #endif /* USE_RECURSIVE_LOCKS ... */
83 #elif defined(_MSC_VER)
84 #ifndef _M_AMD64
85 /* These are already defined on AMD64 builds */
86 #ifdef __cplusplus
87 extern "C" {
88 #endif /* __cplusplus */
89 LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp);
90 LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value);
91 #ifdef __cplusplus
92 }
93 #endif /* __cplusplus */
94 #endif /* _M_AMD64 */
95 #pragma intrinsic (_InterlockedCompareExchange)
96 #pragma intrinsic (_InterlockedExchange)
97 #define interlockedcompareexchange _InterlockedCompareExchange
98 #define interlockedexchange _InterlockedExchange
99 #elif defined(WIN32) && defined(__GNUC__)
100 #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
101 #define interlockedexchange __sync_lock_test_and_set
102 #endif /* Win32 */
103 #else /* USE_LOCKS */
104 #endif /* USE_LOCKS */
105
106 #ifndef LOCK_AT_FORK
107 #define LOCK_AT_FORK 0
108 #endif
109
110 /* Declarations for bit scanning on win32 */
111 #if defined(_MSC_VER) && _MSC_VER>=1300
112 #ifndef BitScanForward /* Try to avoid pulling in WinNT.h */
113 #ifdef __cplusplus
114 extern "C" {
115 #endif /* __cplusplus */
116 unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
117 unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
118 #ifdef __cplusplus
119 }
120 #endif /* __cplusplus */
121
122 #define BitScanForward _BitScanForward
123 #define BitScanReverse _BitScanReverse
124 #pragma intrinsic(_BitScanForward)
125 #pragma intrinsic(_BitScanReverse)
126 #endif /* BitScanForward */
127 #endif /* defined(_MSC_VER) && _MSC_VER>=1300 */
128
129 #ifndef WIN32
130 #ifndef malloc_getpagesize
131 #  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
132 #    ifndef _SC_PAGE_SIZE
133 #      define _SC_PAGE_SIZE _SC_PAGESIZE
134 #    endif
135 #  endif
136 #  ifdef _SC_PAGE_SIZE
137 #    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
138 #  else
139 #    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
140        extern size_t getpagesize();
141 #      define malloc_getpagesize getpagesize()
142 #    else
143 #      ifdef WIN32 /* use supplied emulation of getpagesize */
144 #        define malloc_getpagesize getpagesize()
145 #      else
146 #        ifndef LACKS_SYS_PARAM_H
147 #          include <sys/param.h>
148 #        endif
149 #        ifdef EXEC_PAGESIZE
150 #          define malloc_getpagesize EXEC_PAGESIZE
151 #        else
152 #          ifdef NBPG
153 #            ifndef CLSIZE
154 #              define malloc_getpagesize NBPG
155 #            else
156 #              define malloc_getpagesize (NBPG * CLSIZE)
157 #            endif
158 #          else
159 #            ifdef NBPC
160 #              define malloc_getpagesize NBPC
161 #            else
162 #              ifdef PAGESIZE
163 #                define malloc_getpagesize PAGESIZE
164 #              else /* just guess */
165 #                define malloc_getpagesize ((size_t)4096U)
166 #              endif
167 #            endif
168 #          endif
169 #        endif
170 #      endif
171 #    endif
172 #  endif
173 #endif
174 #endif
175
176 /* ------------------- size_t and alignment properties -------------------- */
177
178 /* The byte and bit size of a size_t */
179 #define SIZE_T_SIZE         (sizeof(size_t))
180 #define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
181
182 /* Some constants coerced to size_t */
183 /* Annoying but necessary to avoid errors on some platforms */
184 #define SIZE_T_ZERO         ((size_t)0)
185 #define SIZE_T_ONE          ((size_t)1)
186 #define SIZE_T_TWO          ((size_t)2)
187 #define SIZE_T_FOUR         ((size_t)4)
188 #define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
189 #define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
190 #define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
191 #define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
192
193 /* The bit mask value corresponding to MALLOC_ALIGNMENT */
194 #define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
195
196 /* True if address a has acceptable alignment */
197 #define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
198
199 /* the number of bytes to offset an address to align it */
200 #define align_offset(A)\
201  ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
202   ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
203
204 /* -------------------------- MMAP preliminaries ------------------------- */
205
206 /*
207    If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
208    checks to fail so compiler optimizer can delete code rather than
209    using so many "#if"s.
210 */
211
212
213 /* MORECORE and MMAP must return MFAIL on failure */
214 #define MFAIL                ((void*)(MAX_SIZE_T))
215 #define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
216
217 #if HAVE_MMAP
218
219 #ifndef WIN32
220 #define MUNMAP_DEFAULT(a, s)  munmap((a), (s))
221 #define MMAP_PROT            (PROT_READ|PROT_WRITE)
222 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
223 #define MAP_ANONYMOUS        MAP_ANON
224 #endif /* MAP_ANON */
225 #ifdef MAP_ANONYMOUS
226 #define MMAP_FLAGS           (MAP_PRIVATE|MAP_ANONYMOUS)
227 #define MMAP_DEFAULT(s)       mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
228 #else /* MAP_ANONYMOUS */
229 /*
230    Nearly all versions of mmap support MAP_ANONYMOUS, so the following
231    is unlikely to be needed, but is supplied just in case.
232 */
233 #define MMAP_FLAGS           (MAP_PRIVATE)
234 static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
235 #define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \
236            (dev_zero_fd = open("/dev/zero", O_RDWR), \
237             mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
238             mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
239 #endif /* MAP_ANONYMOUS */
240
241 #define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s)
242
243 #else /* WIN32 */
244
245 /* Win32 MMAP via VirtualAlloc */
246 static FORCEINLINE void* win32mmap(size_t size) {
247   void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
248   return (ptr != 0)? ptr: MFAIL;
249 }
250
251 /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
252 static FORCEINLINE void* win32direct_mmap(size_t size) {
253   void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
254                            PAGE_READWRITE);
255   return (ptr != 0)? ptr: MFAIL;
256 }
257
258 /* This function supports releasing coalesed segments */
259 static FORCEINLINE int win32munmap(void* ptr, size_t size) {
260   MEMORY_BASIC_INFORMATION minfo;
261   char* cptr = (char*)ptr;
262   while (size) {
263     if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
264       return -1;
265     if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
266         minfo.State != MEM_COMMIT || minfo.RegionSize > size)
267       return -1;
268     if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
269       return -1;
270     cptr += minfo.RegionSize;
271     size -= minfo.RegionSize;
272   }
273   return 0;
274 }
275
276 #define MMAP_DEFAULT(s)             win32mmap(s)
277 #define MUNMAP_DEFAULT(a, s)        win32munmap((a), (s))
278 #define DIRECT_MMAP_DEFAULT(s)      win32direct_mmap(s)
279 #endif /* WIN32 */
280 #endif /* HAVE_MMAP */
281
282 #if HAVE_MREMAP
283 #ifndef WIN32
284 #define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
285 #endif /* WIN32 */
286 #endif /* HAVE_MREMAP */
287
288 /**
289  * Define CALL_MORECORE
290  */
291 #if HAVE_MORECORE
292     #ifdef MORECORE
293         #define CALL_MORECORE(S)    MORECORE(S)
294     #else  /* MORECORE */
295         #define CALL_MORECORE(S)    MORECORE_DEFAULT(S)
296     #endif /* MORECORE */
297 #else  /* HAVE_MORECORE */
298     #define CALL_MORECORE(S)        MFAIL
299 #endif /* HAVE_MORECORE */
300
301 /**
302  * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP
303  */
304 #if HAVE_MMAP
305     #define USE_MMAP_BIT            (SIZE_T_ONE)
306
307     #ifdef MMAP
308         #define CALL_MMAP(s)        MMAP(s)
309     #else /* MMAP */
310         #define CALL_MMAP(s)        MMAP_DEFAULT(s)
311     #endif /* MMAP */
312     #ifdef MUNMAP
313         #define CALL_MUNMAP(a, s)   MUNMAP((a), (s))
314     #else /* MUNMAP */
315         #define CALL_MUNMAP(a, s)   MUNMAP_DEFAULT((a), (s))
316     #endif /* MUNMAP */
317     #ifdef DIRECT_MMAP
318         #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s)
319     #else /* DIRECT_MMAP */
320         #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s)
321     #endif /* DIRECT_MMAP */
322 #else  /* HAVE_MMAP */
323     #define USE_MMAP_BIT            (SIZE_T_ZERO)
324
325     #define MMAP(s)                 MFAIL
326     #define MUNMAP(a, s)            (-1)
327     #define DIRECT_MMAP(s)          MFAIL
328     #define CALL_DIRECT_MMAP(s)     DIRECT_MMAP(s)
329     #define CALL_MMAP(s)            MMAP(s)
330     #define CALL_MUNMAP(a, s)       MUNMAP((a), (s))
331 #endif /* HAVE_MMAP */
332
333 /**
334  * Define CALL_MREMAP
335  */
336 #if HAVE_MMAP && HAVE_MREMAP
337     #ifdef MREMAP
338         #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv))
339     #else /* MREMAP */
340         #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv))
341     #endif /* MREMAP */
342 #else  /* HAVE_MMAP && HAVE_MREMAP */
343     #define CALL_MREMAP(addr, osz, nsz, mv)     MFAIL
344 #endif /* HAVE_MMAP && HAVE_MREMAP */
345
346 /* mstate bit set if contiguous morecore disabled or failed */
347 #define USE_NONCONTIGUOUS_BIT (4U)
348
349 /* mstate bit set if no expansion allowed */
350 #define USE_NOEXPAND_BIT (8U)
351
352 /* trace allocations if set */
353 #define USE_TRACE_BIT (16U)
354
355 /* segment bit set in create_mspace_with_base */
356 #define EXTERN_BIT            (8U)
357
358
359 /* --------------------------- Lock preliminaries ------------------------ */
360
361 /*
362   When locks are defined, there is one global lock, plus
363   one per-mspace lock.
364
365   The global lock_ensures that mparams.magic and other unique
366   mparams values are initialized only once. It also protects
367   sequences of calls to MORECORE.  In many cases sys_alloc requires
368   two calls, that should not be interleaved with calls by other
369   threads.  This does not protect against direct calls to MORECORE
370   by other threads not using this lock, so there is still code to
371   cope the best we can on interference.
372
373   Per-mspace locks surround calls to malloc, free, etc.
374   By default, locks are simple non-reentrant mutexes.
375
376   Because lock-protected regions generally have bounded times, it is
377   OK to use the supplied simple spinlocks. Spinlocks are likely to
378   improve performance for lightly contended applications, but worsen
379   performance under heavy contention.
380
381   If USE_LOCKS is > 1, the definitions of lock routines here are
382   bypassed, in which case you will need to define the type MLOCK_T,
383   and at least INITIAL_LOCK, DESTROY_LOCK, ACQUIRE_LOCK, RELEASE_LOCK
384   and TRY_LOCK.  You must also declare a
385     static MLOCK_T malloc_global_mutex = { initialization values };.
386
387 */
388
389 #if !USE_LOCKS
390 #define USE_LOCK_BIT               (0U)
391 #define INITIAL_LOCK(l)            (0)
392 #define DESTROY_LOCK(l)            (0)
393 #define ACQUIRE_MALLOC_GLOBAL_LOCK()
394 #define RELEASE_MALLOC_GLOBAL_LOCK()
395
396 #else
397 #if USE_LOCKS > 1
398 /* -----------------------  User-defined locks ------------------------ */
399 /* Define your own lock implementation here */
400 /* #define INITIAL_LOCK(lk)  ... */
401 /* #define DESTROY_LOCK(lk)  ... */
402 /* #define ACQUIRE_LOCK(lk)  ... */
403 /* #define RELEASE_LOCK(lk)  ... */
404 /* #define TRY_LOCK(lk) ... */
405 /* static MLOCK_T malloc_global_mutex = ... */
406
407 #elif USE_SPIN_LOCKS
408
409 /* First, define CAS_LOCK and CLEAR_LOCK on ints */
410 /* Note CAS_LOCK defined to return 0 on success */
411
412 #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
413 #define CAS_LOCK(sl)     __sync_lock_test_and_set(sl, 1)
414 #define CLEAR_LOCK(sl)   __sync_lock_release(sl)
415
416 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
417 /* Custom spin locks for older gcc on x86 */
418 static FORCEINLINE int x86_cas_lock(int *sl) {
419   int ret;
420   int val = 1;
421   int cmp = 0;
422   __asm__ __volatile__  ("lock; cmpxchgl %1, %2"
423                          : "=a" (ret)
424                          : "r" (val), "m" (*(sl)), "0"(cmp)
425                          : "memory", "cc");
426   return ret;
427 }
428
429 static FORCEINLINE void x86_clear_lock(int* sl) {
430   assert(*sl != 0);
431   int prev = 0;
432   int ret;
433   __asm__ __volatile__ ("lock; xchgl %0, %1"
434                         : "=r" (ret)
435                         : "m" (*(sl)), "0"(prev)
436                         : "memory");
437 }
438
439 #define CAS_LOCK(sl)     x86_cas_lock(sl)
440 #define CLEAR_LOCK(sl)   x86_clear_lock(sl)
441
442 #else /* Win32 MSC */
443 #define CAS_LOCK(sl)     interlockedexchange(sl, (LONG)1)
444 #define CLEAR_LOCK(sl)   interlockedexchange (sl, (LONG)0)
445
446 #endif /* ... gcc spins locks ... */
447
448 /* How to yield for a spin lock */
449 #define SPINS_PER_YIELD       63
450 #if defined(_MSC_VER)
451 #define SLEEP_EX_DURATION     50 /* delay for yield/sleep */
452 #define SPIN_LOCK_YIELD  SleepEx(SLEEP_EX_DURATION, FALSE)
453 #elif defined (__SVR4) && defined (__sun) /* solaris */
454 #define SPIN_LOCK_YIELD   thr_yield();
455 #elif !defined(LACKS_SCHED_H)
456 #define SPIN_LOCK_YIELD   sched_yield();
457 #else
458 #define SPIN_LOCK_YIELD
459 #endif /* ... yield ... */
460
461 #if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0
462 /* Plain spin locks use single word (embedded in malloc_states) */
463 CLIB_NOSANITIZE_ADDR
464 static int spin_acquire_lock(int *sl) {
465   int spins = 0;
466   while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) {
467     if ((++spins & SPINS_PER_YIELD) == 0) {
468       SPIN_LOCK_YIELD;
469     }
470   }
471   return 0;
472 }
473
474 #define MLOCK_T               int
475 #define TRY_LOCK(sl)          !CAS_LOCK(sl)
476 #define RELEASE_LOCK(sl)      CLEAR_LOCK(sl)
477 #define ACQUIRE_LOCK(sl)      (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0)
478 #define INITIAL_LOCK(sl)      (*sl = 0)
479 #define DESTROY_LOCK(sl)      (0)
480 static MLOCK_T malloc_global_mutex = 0;
481
482 #else /* USE_RECURSIVE_LOCKS */
483 /* types for lock owners */
484 #ifdef WIN32
485 #define THREAD_ID_T           DWORD
486 #define CURRENT_THREAD        GetCurrentThreadId()
487 #define EQ_OWNER(X,Y)         ((X) == (Y))
488 #else
489 /*
490   Note: the following assume that pthread_t is a type that can be
491   initialized to (casted) zero. If this is not the case, you will need to
492   somehow redefine these or not use spin locks.
493 */
494 #define THREAD_ID_T           pthread_t
495 #define CURRENT_THREAD        pthread_self()
496 #define EQ_OWNER(X,Y)         pthread_equal(X, Y)
497 #endif
498
499 struct malloc_recursive_lock {
500   int sl;
501   unsigned int c;
502   THREAD_ID_T threadid;
503 };
504
505 #define MLOCK_T  struct malloc_recursive_lock
506 static MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0};
507
508 static FORCEINLINE void recursive_release_lock(MLOCK_T *lk) {
509   assert(lk->sl != 0);
510   if (--lk->c == 0) {
511     CLEAR_LOCK(&lk->sl);
512   }
513 }
514
515 static FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) {
516   THREAD_ID_T mythreadid = CURRENT_THREAD;
517   int spins = 0;
518   for (;;) {
519     if (*((volatile int *)(&lk->sl)) == 0) {
520       if (!CAS_LOCK(&lk->sl)) {
521         lk->threadid = mythreadid;
522         lk->c = 1;
523         return 0;
524       }
525     }
526     else if (EQ_OWNER(lk->threadid, mythreadid)) {
527       ++lk->c;
528       return 0;
529     }
530     if ((++spins & SPINS_PER_YIELD) == 0) {
531       SPIN_LOCK_YIELD;
532     }
533   }
534 }
535
536 static FORCEINLINE int recursive_try_lock(MLOCK_T *lk) {
537   THREAD_ID_T mythreadid = CURRENT_THREAD;
538   if (*((volatile int *)(&lk->sl)) == 0) {
539     if (!CAS_LOCK(&lk->sl)) {
540       lk->threadid = mythreadid;
541       lk->c = 1;
542       return 1;
543     }
544   }
545   else if (EQ_OWNER(lk->threadid, mythreadid)) {
546     ++lk->c;
547     return 1;
548   }
549   return 0;
550 }
551
552 #define RELEASE_LOCK(lk)      recursive_release_lock(lk)
553 #define TRY_LOCK(lk)          recursive_try_lock(lk)
554 #define ACQUIRE_LOCK(lk)      recursive_acquire_lock(lk)
555 #define INITIAL_LOCK(lk)      ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0)
556 #define DESTROY_LOCK(lk)      (0)
557 #endif /* USE_RECURSIVE_LOCKS */
558
559 #elif defined(WIN32) /* Win32 critical sections */
560 #define MLOCK_T               CRITICAL_SECTION
561 #define ACQUIRE_LOCK(lk)      (EnterCriticalSection(lk), 0)
562 #define RELEASE_LOCK(lk)      LeaveCriticalSection(lk)
563 #define TRY_LOCK(lk)          TryEnterCriticalSection(lk)
564 #define INITIAL_LOCK(lk)      (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000))
565 #define DESTROY_LOCK(lk)      (DeleteCriticalSection(lk), 0)
566 #define NEED_GLOBAL_LOCK_INIT
567
568 static MLOCK_T malloc_global_mutex;
569 static volatile LONG malloc_global_mutex_status;
570
571 /* Use spin loop to initialize global lock */
572 static void init_malloc_global_mutex() {
573   for (;;) {
574     long stat = malloc_global_mutex_status;
575     if (stat > 0)
576       return;
577     /* transition to < 0 while initializing, then to > 0) */
578     if (stat == 0 &&
579         interlockedcompareexchange(&malloc_global_mutex_status, (LONG)-1, (LONG)0) == 0) {
580       InitializeCriticalSection(&malloc_global_mutex);
581       interlockedexchange(&malloc_global_mutex_status, (LONG)1);
582       return;
583     }
584     SleepEx(0, FALSE);
585   }
586 }
587
588 #else /* pthreads-based locks */
589 #define MLOCK_T               pthread_mutex_t
590 #define ACQUIRE_LOCK(lk)      pthread_mutex_lock(lk)
591 #define RELEASE_LOCK(lk)      pthread_mutex_unlock(lk)
592 #define TRY_LOCK(lk)          (!pthread_mutex_trylock(lk))
593 #define INITIAL_LOCK(lk)      pthread_init_lock(lk)
594 #define DESTROY_LOCK(lk)      pthread_mutex_destroy(lk)
595
596 #if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE)
597 /* Cope with old-style linux recursive lock initialization by adding */
598 /* skipped internal declaration from pthread.h */
599 extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr,
600                                               int __kind));
601 #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
602 #define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y)
603 #endif /* USE_RECURSIVE_LOCKS ... */
604
605 static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER;
606
607 static int pthread_init_lock (MLOCK_T *lk) {
608   pthread_mutexattr_t attr;
609   if (pthread_mutexattr_init(&attr)) return 1;
610 #if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0
611   if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1;
612 #endif
613   if (pthread_mutex_init(lk, &attr)) return 1;
614   if (pthread_mutexattr_destroy(&attr)) return 1;
615   return 0;
616 }
617
618 #endif /* ... lock types ... */
619
620 /* Common code for all lock types */
621 #define USE_LOCK_BIT               (2U)
622
623 #ifndef ACQUIRE_MALLOC_GLOBAL_LOCK
624 #define ACQUIRE_MALLOC_GLOBAL_LOCK()  ACQUIRE_LOCK(&malloc_global_mutex);
625 #endif
626
627 #ifndef RELEASE_MALLOC_GLOBAL_LOCK
628 #define RELEASE_MALLOC_GLOBAL_LOCK()  RELEASE_LOCK(&malloc_global_mutex);
629 #endif
630
631 #endif /* USE_LOCKS */
632
633 /* -----------------------  Chunk representations ------------------------ */
634
635 /*
636   (The following includes lightly edited explanations by Colin Plumb.)
637
638   The malloc_chunk declaration below is misleading (but accurate and
639   necessary).  It declares a "view" into memory allowing access to
640   necessary fields at known offsets from a given base.
641
642   Chunks of memory are maintained using a `boundary tag' method as
643   originally described by Knuth.  (See the paper by Paul Wilson
644   ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
645   techniques.)  Sizes of free chunks are stored both in the front of
646   each chunk and at the end.  This makes consolidating fragmented
647   chunks into bigger chunks fast.  The head fields also hold bits
648   representing whether chunks are free or in use.
649
650   Here are some pictures to make it clearer.  They are "exploded" to
651   show that the state of a chunk can be thought of as extending from
652   the high 31 bits of the head field of its header through the
653   prev_foot and PINUSE_BIT bit of the following chunk header.
654
655   A chunk that's in use looks like:
656
657    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
658            | Size of previous chunk (if P = 0)                             |
659            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
660          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
661          | Size of this chunk                                         1| +-+
662    mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
663          |                                                               |
664          +-                                                             -+
665          |                                                               |
666          +-                                                             -+
667          |                                                               :
668          +-      size - sizeof(size_t) available payload bytes          -+
669          :                                                               |
670  chunk-> +-                                                             -+
671          |                                                               |
672          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
673        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
674        | Size of next chunk (may or may not be in use)               | +-+
675  mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676
677     And if it's free, it looks like this:
678
679    chunk-> +-                                                             -+
680            | User payload (must be in use, or we would have merged!)       |
681            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
682          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
683          | Size of this chunk                                         0| +-+
684    mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
685          | Next pointer                                                  |
686          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
687          | Prev pointer                                                  |
688          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
689          |                                                               :
690          +-      size - sizeof(struct chunk) unused bytes               -+
691          :                                                               |
692  chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
693          | Size of this chunk                                            |
694          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
695        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
696        | Size of next chunk (must be in use, or we would have merged)| +-+
697  mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
698        |                                                               :
699        +- User payload                                                -+
700        :                                                               |
701        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
702                                                                      |0|
703                                                                      +-+
704   Note that since we always merge adjacent free chunks, the chunks
705   adjacent to a free chunk must be in use.
706
707   Given a pointer to a chunk (which can be derived trivially from the
708   payload pointer) we can, in O(1) time, find out whether the adjacent
709   chunks are free, and if so, unlink them from the lists that they
710   are on and merge them with the current chunk.
711
712   Chunks always begin on even word boundaries, so the mem portion
713   (which is returned to the user) is also on an even word boundary, and
714   thus at least double-word aligned.
715
716   The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
717   chunk size (which is always a multiple of two words), is an in-use
718   bit for the *previous* chunk.  If that bit is *clear*, then the
719   word before the current chunk size contains the previous chunk
720   size, and can be used to find the front of the previous chunk.
721   The very first chunk allocated always has this bit set, preventing
722   access to non-existent (or non-owned) memory. If pinuse is set for
723   any given chunk, then you CANNOT determine the size of the
724   previous chunk, and might even get a memory addressing fault when
725   trying to do so.
726
727   The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
728   the chunk size redundantly records whether the current chunk is
729   inuse (unless the chunk is mmapped). This redundancy enables usage
730   checks within free and realloc, and reduces indirection when freeing
731   and consolidating chunks.
732
733   Each freshly allocated chunk must have both cinuse and pinuse set.
734   That is, each allocated chunk borders either a previously allocated
735   and still in-use chunk, or the base of its memory arena. This is
736   ensured by making all allocations from the `lowest' part of any
737   found chunk.  Further, no free chunk physically borders another one,
738   so each free chunk is known to be preceded and followed by either
739   inuse chunks or the ends of memory.
740
741   Note that the `foot' of the current chunk is actually represented
742   as the prev_foot of the NEXT chunk. This makes it easier to
743   deal with alignments etc but can be very confusing when trying
744   to extend or adapt this code.
745
746   The exceptions to all this are
747
748      1. The special chunk `top' is the top-most available chunk (i.e.,
749         the one bordering the end of available memory). It is treated
750         specially.  Top is never included in any bin, is used only if
751         no other chunk is available, and is released back to the
752         system if it is very large (see M_TRIM_THRESHOLD).  In effect,
753         the top chunk is treated as larger (and thus less well
754         fitting) than any other available chunk.  The top chunk
755         doesn't update its trailing size field since there is no next
756         contiguous chunk that would have to index off it. However,
757         space is still allocated for it (TOP_FOOT_SIZE) to enable
758         separation or merging when space is extended.
759
760      3. Chunks allocated via mmap, have both cinuse and pinuse bits
761         cleared in their head fields.  Because they are allocated
762         one-by-one, each must carry its own prev_foot field, which is
763         also used to hold the offset this chunk has within its mmapped
764         region, which is needed to preserve alignment. Each mmapped
765         chunk is trailed by the first two fields of a fake next-chunk
766         for sake of usage checks.
767
768 */
769
770 struct malloc_chunk {
771   size_t               prev_foot;  /* Size of previous chunk (if free).  */
772   size_t               head;       /* Size and inuse bits. */
773   struct malloc_chunk* fd;         /* double links -- used only if free. */
774   struct malloc_chunk* bk;
775 };
776
777 typedef struct malloc_chunk  mchunk;
778 typedef struct malloc_chunk* mchunkptr;
779 typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
780 typedef unsigned int bindex_t;         /* Described below */
781 typedef unsigned int binmap_t;         /* Described below */
782 typedef unsigned int flag_t;           /* The type of various bit flag sets */
783
784 /* ------------------- Chunks sizes and alignments ----------------------- */
785
786 #define MCHUNK_SIZE         (sizeof(mchunk))
787
788 #if FOOTERS
789 #define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)
790 #else /* FOOTERS */
791 #define CHUNK_OVERHEAD      (SIZE_T_SIZE)
792 #endif /* FOOTERS */
793
794 /* MMapped chunks need a second word of overhead ... */
795 #define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
796 /* ... and additional padding for fake next-chunk at foot */
797 #define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
798
799 /* The smallest size we can malloc is an aligned minimal chunk */
800 #define MIN_CHUNK_SIZE\
801   ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
802
803 /* conversion from malloc headers to user pointers, and back */
804 #define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
805 #define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
806 /* chunk associated with aligned address A */
807 #define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
808
809 /* Bounds on request (not chunk) sizes. */
810 #define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
811 #define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
812
813 /* pad request bytes into a usable size */
814 #define pad_request(req) \
815    (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
816
817 /* pad request, checking for minimum (but not maximum) */
818 #define request2size(req) \
819   (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
820
821
822 /* ------------------ Operations on head and foot fields ----------------- */
823
824 /*
825   The head field of a chunk is or'ed with PINUSE_BIT when previous
826   adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
827   use, unless mmapped, in which case both bits are cleared.
828
829   FLAG4_BIT is not used by this malloc, but might be useful in extensions.
830 */
831
832 #define PINUSE_BIT          (SIZE_T_ONE)
833 #define CINUSE_BIT          (SIZE_T_TWO)
834 #define FLAG4_BIT           (SIZE_T_FOUR)
835 #define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
836 #define FLAG_BITS           (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT)
837
838 /* Head value for fenceposts */
839 #define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
840
841 /* extraction of fields from head words */
842 #define cinuse(p)           ((p)->head & CINUSE_BIT)
843 #define pinuse(p)           ((p)->head & PINUSE_BIT)
844 #define flag4inuse(p)       ((p)->head & FLAG4_BIT)
845 #define is_inuse(p)         (((p)->head & INUSE_BITS) != PINUSE_BIT)
846 #define is_mmapped(p)       (((p)->head & INUSE_BITS) == 0)
847
848 #define chunksize(p)        ((p)->head & ~(FLAG_BITS))
849
850 #define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
851 #define set_flag4(p)        ((p)->head |= FLAG4_BIT)
852 #define clear_flag4(p)      ((p)->head &= ~FLAG4_BIT)
853
854 /* Treat space at ptr +/- offset as a chunk */
855 #define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
856 #define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
857
858 /* Ptr to next or previous physical malloc_chunk. */
859 #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS)))
860 #define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
861
862 /* extract next chunk's pinuse bit */
863 #define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
864
865 /* Get/set size at footer */
866 #define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
867 #define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
868
869 /* Set size, pinuse bit, and foot */
870 #define set_size_and_pinuse_of_free_chunk(p, s)\
871   ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
872
873 /* Set size, pinuse bit, foot, and clear next pinuse */
874 #define set_free_with_pinuse(p, s, n)\
875   (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
876
877 /* Get the internal overhead associated with chunk p */
878 #define overhead_for(p)\
879  (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
880
881 /* Return true if malloced space is not necessarily cleared */
882 #if MMAP_CLEARS
883 #define calloc_must_clear(p) (!is_mmapped(p))
884 #else /* MMAP_CLEARS */
885 #define calloc_must_clear(p) (1)
886 #endif /* MMAP_CLEARS */
887
888 /* ---------------------- Overlaid data structures ----------------------- */
889
890 /*
891   When chunks are not in use, they are treated as nodes of either
892   lists or trees.
893
894   "Small"  chunks are stored in circular doubly-linked lists, and look
895   like this:
896
897     chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
898             |             Size of previous chunk                            |
899             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
900     `head:' |             Size of chunk, in bytes                         |P|
901       mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
902             |             Forward pointer to next chunk in list             |
903             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
904             |             Back pointer to previous chunk in list            |
905             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
906             |             Unused space (may be 0 bytes long)                .
907             .                                                               .
908             .                                                               |
909 nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
910     `foot:' |             Size of chunk, in bytes                           |
911             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
912
913   Larger chunks are kept in a form of bitwise digital trees (aka
914   tries) keyed on chunksizes.  Because malloc_tree_chunks are only for
915   free chunks greater than 256 bytes, their size doesn't impose any
916   constraints on user chunk sizes.  Each node looks like:
917
918     chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
919             |             Size of previous chunk                            |
920             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
921     `head:' |             Size of chunk, in bytes                         |P|
922       mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
923             |             Forward pointer to next chunk of same size        |
924             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
925             |             Back pointer to previous chunk of same size       |
926             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
927             |             Pointer to left child (child[0])                  |
928             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
929             |             Pointer to right child (child[1])                 |
930             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
931             |             Pointer to parent                                 |
932             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
933             |             bin index of this chunk                           |
934             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
935             |             Unused space                                      .
936             .                                                               |
937 nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
938     `foot:' |             Size of chunk, in bytes                           |
939             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
940
941   Each tree holding treenodes is a tree of unique chunk sizes.  Chunks
942   of the same size are arranged in a circularly-linked list, with only
943   the oldest chunk (the next to be used, in our FIFO ordering)
944   actually in the tree.  (Tree members are distinguished by a non-null
945   parent pointer.)  If a chunk with the same size an an existing node
946   is inserted, it is linked off the existing node using pointers that
947   work in the same way as fd/bk pointers of small chunks.
948
949   Each tree contains a power of 2 sized range of chunk sizes (the
950   smallest is 0x100 <= x < 0x180), which is is divided in half at each
951   tree level, with the chunks in the smaller half of the range (0x100
952   <= x < 0x140 for the top nose) in the left subtree and the larger
953   half (0x140 <= x < 0x180) in the right subtree.  This is, of course,
954   done by inspecting individual bits.
955
956   Using these rules, each node's left subtree contains all smaller
957   sizes than its right subtree.  However, the node at the root of each
958   subtree has no particular ordering relationship to either.  (The
959   dividing line between the subtree sizes is based on trie relation.)
960   If we remove the last chunk of a given size from the interior of the
961   tree, we need to replace it with a leaf node.  The tree ordering
962   rules permit a node to be replaced by any leaf below it.
963
964   The smallest chunk in a tree (a common operation in a best-fit
965   allocator) can be found by walking a path to the leftmost leaf in
966   the tree.  Unlike a usual binary tree, where we follow left child
967   pointers until we reach a null, here we follow the right child
968   pointer any time the left one is null, until we reach a leaf with
969   both child pointers null. The smallest chunk in the tree will be
970   somewhere along that path.
971
972   The worst case number of steps to add, find, or remove a node is
973   bounded by the number of bits differentiating chunks within
974   bins. Under current bin calculations, this ranges from 6 up to 21
975   (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
976   is of course much better.
977 */
978
979 struct malloc_tree_chunk {
980   /* The first four fields must be compatible with malloc_chunk */
981   size_t                    prev_foot;
982   size_t                    head;
983   struct malloc_tree_chunk* fd;
984   struct malloc_tree_chunk* bk;
985
986   struct malloc_tree_chunk* child[2];
987   struct malloc_tree_chunk* parent;
988   bindex_t                  index;
989 };
990
991 typedef struct malloc_tree_chunk  tchunk;
992 typedef struct malloc_tree_chunk* tchunkptr;
993 typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
994
995 /* A little helper macro for trees */
996 #define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
997
998 /* ----------------------------- Segments -------------------------------- */
999
1000 /*
1001   Each malloc space may include non-contiguous segments, held in a
1002   list headed by an embedded malloc_segment record representing the
1003   top-most space. Segments also include flags holding properties of
1004   the space. Large chunks that are directly allocated by mmap are not
1005   included in this list. They are instead independently created and
1006   destroyed without otherwise keeping track of them.
1007
1008   Segment management mainly comes into play for spaces allocated by
1009   MMAP.  Any call to MMAP might or might not return memory that is
1010   adjacent to an existing segment.  MORECORE normally contiguously
1011   extends the current space, so this space is almost always adjacent,
1012   which is simpler and faster to deal with. (This is why MORECORE is
1013   used preferentially to MMAP when both are available -- see
1014   sys_alloc.)  When allocating using MMAP, we don't use any of the
1015   hinting mechanisms (inconsistently) supported in various
1016   implementations of unix mmap, or distinguish reserving from
1017   committing memory. Instead, we just ask for space, and exploit
1018   contiguity when we get it.  It is probably possible to do
1019   better than this on some systems, but no general scheme seems
1020   to be significantly better.
1021
1022   Management entails a simpler variant of the consolidation scheme
1023   used for chunks to reduce fragmentation -- new adjacent memory is
1024   normally prepended or appended to an existing segment. However,
1025   there are limitations compared to chunk consolidation that mostly
1026   reflect the fact that segment processing is relatively infrequent
1027   (occurring only when getting memory from system) and that we
1028   don't expect to have huge numbers of segments:
1029
1030   * Segments are not indexed, so traversal requires linear scans.  (It
1031     would be possible to index these, but is not worth the extra
1032     overhead and complexity for most programs on most platforms.)
1033   * New segments are only appended to old ones when holding top-most
1034     memory; if they cannot be prepended to others, they are held in
1035     different segments.
1036
1037   Except for the top-most segment of an mstate, each segment record
1038   is kept at the tail of its segment. Segments are added by pushing
1039   segment records onto the list headed by &mstate.seg for the
1040   containing mstate.
1041
1042   Segment flags control allocation/merge/deallocation policies:
1043   * If EXTERN_BIT set, then we did not allocate this segment,
1044     and so should not try to deallocate or merge with others.
1045     (This currently holds only for the initial segment passed
1046     into create_mspace_with_base.)
1047   * If USE_MMAP_BIT set, the segment may be merged with
1048     other surrounding mmapped segments and trimmed/de-allocated
1049     using munmap.
1050   * If neither bit is set, then the segment was obtained using
1051     MORECORE so can be merged with surrounding MORECORE'd segments
1052     and deallocated/trimmed using MORECORE with negative arguments.
1053 */
1054
1055 struct malloc_segment {
1056   char*        base;             /* base address */
1057   size_t       size;             /* allocated size */
1058   struct malloc_segment* next;   /* ptr to next segment */
1059   flag_t       sflags;           /* mmap and extern flag */
1060 };
1061
1062 #define is_mmapped_segment(S)  ((S)->sflags & USE_MMAP_BIT)
1063 #define is_extern_segment(S)   ((S)->sflags & EXTERN_BIT)
1064
1065 typedef struct malloc_segment  msegment;
1066 typedef struct malloc_segment* msegmentptr;
1067
1068 /* ---------------------------- malloc_state ----------------------------- */
1069
1070 /*
1071    A malloc_state holds all of the bookkeeping for a space.
1072    The main fields are:
1073
1074   Top
1075     The topmost chunk of the currently active segment. Its size is
1076     cached in topsize.  The actual size of topmost space is
1077     topsize+TOP_FOOT_SIZE, which includes space reserved for adding
1078     fenceposts and segment records if necessary when getting more
1079     space from the system.  The size at which to autotrim top is
1080     cached from mparams in trim_check, except that it is disabled if
1081     an autotrim fails.
1082
1083   Designated victim (dv)
1084     This is the preferred chunk for servicing small requests that
1085     don't have exact fits.  It is normally the chunk split off most
1086     recently to service another small request.  Its size is cached in
1087     dvsize. The link fields of this chunk are not maintained since it
1088     is not kept in a bin.
1089
1090   SmallBins
1091     An array of bin headers for free chunks.  These bins hold chunks
1092     with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
1093     chunks of all the same size, spaced 8 bytes apart.  To simplify
1094     use in double-linked lists, each bin header acts as a malloc_chunk
1095     pointing to the real first node, if it exists (else pointing to
1096     itself).  This avoids special-casing for headers.  But to avoid
1097     waste, we allocate only the fd/bk pointers of bins, and then use
1098     repositioning tricks to treat these as the fields of a chunk.
1099
1100   TreeBins
1101     Treebins are pointers to the roots of trees holding a range of
1102     sizes. There are 2 equally spaced treebins for each power of two
1103     from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
1104     larger.
1105
1106   Bin maps
1107     There is one bit map for small bins ("smallmap") and one for
1108     treebins ("treemap).  Each bin sets its bit when non-empty, and
1109     clears the bit when empty.  Bit operations are then used to avoid
1110     bin-by-bin searching -- nearly all "search" is done without ever
1111     looking at bins that won't be selected.  The bit maps
1112     conservatively use 32 bits per map word, even if on 64bit system.
1113     For a good description of some of the bit-based techniques used
1114     here, see Henry S. Warren Jr's book "Hacker's Delight" (and
1115     supplement at http://hackersdelight.org/). Many of these are
1116     intended to reduce the branchiness of paths through malloc etc, as
1117     well as to reduce the number of memory locations read or written.
1118
1119   Segments
1120     A list of segments headed by an embedded malloc_segment record
1121     representing the initial space.
1122
1123   Address check support
1124     The least_addr field is the least address ever obtained from
1125     MORECORE or MMAP. Attempted frees and reallocs of any address less
1126     than this are trapped (unless INSECURE is defined).
1127
1128   Magic tag
1129     A cross-check field that should always hold same value as mparams.magic.
1130
1131   Max allowed footprint
1132     The maximum allowed bytes to allocate from system (zero means no limit)
1133
1134   Flags
1135     Bits recording whether to use MMAP, locks, or contiguous MORECORE
1136
1137   Statistics
1138     Each space keeps track of current and maximum system memory
1139     obtained via MORECORE or MMAP.
1140
1141   Trim support
1142     Fields holding the amount of unused topmost memory that should trigger
1143     trimming, and a counter to force periodic scanning to release unused
1144     non-topmost segments.
1145
1146   Locking
1147     If USE_LOCKS is defined, the "mutex" lock is acquired and released
1148     around every public call using this mspace.
1149
1150   Extension support
1151     A void* pointer and a size_t field that can be used to help implement
1152     extensions to this malloc.
1153 */
1154
1155 /* Bin types, widths and sizes */
1156 #define NSMALLBINS        (32U)
1157 #define NTREEBINS         (32U)
1158 #define SMALLBIN_SHIFT    (3U)
1159 #define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
1160 #define TREEBIN_SHIFT     (8U)
1161 #define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
1162 #define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
1163 #define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
1164
1165 struct malloc_state {
1166   binmap_t   smallmap;
1167   binmap_t   treemap;
1168   size_t     dvsize;
1169   size_t     topsize;
1170   char*      least_addr;
1171   mchunkptr  dv;
1172   mchunkptr  top;
1173   size_t     trim_check;
1174   size_t     release_checks;
1175   size_t     magic;
1176   mchunkptr  smallbins[(NSMALLBINS+1)*2];
1177   tbinptr    treebins[NTREEBINS];
1178   size_t     footprint;
1179   size_t     max_footprint;
1180   size_t     footprint_limit; /* zero means no limit */
1181   flag_t     mflags;
1182 #if USE_LOCKS
1183   MLOCK_T    mutex;     /* locate lock among fields that rarely change */
1184 #endif /* USE_LOCKS */
1185   msegment   seg;
1186   void*      extp;      /* Unused but available for extensions */
1187   size_t     exts;
1188 };
1189
1190 typedef struct malloc_state*    mstate;
1191
1192 /* ------------- Global malloc_state and malloc_params ------------------- */
1193
1194 /*
1195   malloc_params holds global properties, including those that can be
1196   dynamically set using mallopt. There is a single instance, mparams,
1197   initialized in init_mparams. Note that the non-zeroness of "magic"
1198   also serves as an initialization flag.
1199 */
1200
1201 struct malloc_params {
1202   size_t magic;
1203   size_t page_size;
1204   size_t granularity;
1205   size_t mmap_threshold;
1206   size_t trim_threshold;
1207   flag_t default_mflags;
1208 };
1209
1210 static struct malloc_params mparams;
1211
1212 /* Ensure mparams initialized */
1213 #define ensure_initialization() (void)(mparams.magic != 0 || init_mparams())
1214
1215 #if !ONLY_MSPACES
1216
1217 /* The global malloc_state used for all non-"mspace" calls */
1218 static struct malloc_state _gm_;
1219 #define gm                 (&_gm_)
1220 #define is_global(M)       ((M) == &_gm_)
1221
1222 #endif /* !ONLY_MSPACES */
1223
1224 #define is_initialized(M)  ((M)->top != 0)
1225
1226 /* -------------------------- system alloc setup ------------------------- */
1227
1228 /* Operations on mflags */
1229
1230 #define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
1231 #define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
1232 #if USE_LOCKS
1233 #define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
1234 #else
1235 #define disable_lock(M)
1236 #endif
1237
1238 #define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
1239 #define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
1240 #if HAVE_MMAP
1241 #define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
1242 #else
1243 #define disable_mmap(M)
1244 #endif
1245
1246 #define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
1247 #define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
1248 #define use_noexpand(M) ((M)->mflags & USE_NOEXPAND_BIT)
1249 #define disable_expand(M) ((M)->mflags |= USE_NOEXPAND_BIT)
1250 #define use_trace(M) ((M)->mflags & USE_TRACE_BIT)
1251 #define enable_trace(M) ((M)->mflags |= USE_TRACE_BIT)
1252 #define disable_trace(M) ((M)->mflags |= USE_TRACE_BIT)
1253
1254 #define set_lock(M,L)\
1255  ((M)->mflags = (L)?\
1256   ((M)->mflags | USE_LOCK_BIT) :\
1257   ((M)->mflags & ~USE_LOCK_BIT))
1258
1259 /* page-align a size */
1260 #define page_align(S)\
1261  (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE))
1262
1263 /* granularity-align a size */
1264 #define granularity_align(S)\
1265   (((S) + (mparams.granularity - SIZE_T_ONE))\
1266    & ~(mparams.granularity - SIZE_T_ONE))
1267
1268
1269 /* For mmap, use granularity alignment on windows, else page-align */
1270 #ifdef WIN32
1271 #define mmap_align(S) granularity_align(S)
1272 #else
1273 #define mmap_align(S) page_align(S)
1274 #endif
1275
1276 /* For sys_alloc, enough padding to ensure can malloc request on success */
1277 #define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
1278
1279 #define is_page_aligned(S)\
1280    (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
1281 #define is_granularity_aligned(S)\
1282    (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
1283
1284 /*  True if segment S holds address A */
1285 #define segment_holds(S, A)\
1286   ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
1287
1288 /* Return segment holding given address */
1289 CLIB_NOSANITIZE_ADDR
1290 static msegmentptr segment_holding(mstate m, char* addr) {
1291   msegmentptr sp = &m->seg;
1292   for (;;) {
1293     if (addr >= sp->base && addr < sp->base + sp->size)
1294       return sp;
1295     if ((sp = sp->next) == 0)
1296       return 0;
1297   }
1298 }
1299
1300 /* Return true if segment contains a segment link */
1301 CLIB_NOSANITIZE_ADDR
1302 static int has_segment_link(mstate m, msegmentptr ss) {
1303   msegmentptr sp = &m->seg;
1304   for (;;) {
1305     if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
1306       return 1;
1307     if ((sp = sp->next) == 0)
1308       return 0;
1309   }
1310 }
1311
1312 #ifndef MORECORE_CANNOT_TRIM
1313 #define should_trim(M,s)  ((s) > (M)->trim_check)
1314 #else  /* MORECORE_CANNOT_TRIM */
1315 #define should_trim(M,s)  (0)
1316 #endif /* MORECORE_CANNOT_TRIM */
1317
1318 /*
1319   TOP_FOOT_SIZE is padding at the end of a segment, including space
1320   that may be needed to place segment records and fenceposts when new
1321   noncontiguous segments are added.
1322 */
1323 #define TOP_FOOT_SIZE\
1324   (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
1325
1326
1327 /* -------------------------------  Hooks -------------------------------- */
1328
1329 /*
1330   PREACTION should be defined to return 0 on success, and nonzero on
1331   failure. If you are not using locking, you can redefine these to do
1332   anything you like.
1333 */
1334
1335 #if USE_LOCKS
1336 #define PREACTION(M)  ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
1337 #define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
1338 #else /* USE_LOCKS */
1339
1340 #ifndef PREACTION
1341 #define PREACTION(M) (0)
1342 #endif  /* PREACTION */
1343
1344 #ifndef POSTACTION
1345 #define POSTACTION(M)
1346 #endif  /* POSTACTION */
1347
1348 #endif /* USE_LOCKS */
1349
1350 /*
1351   CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
1352   USAGE_ERROR_ACTION is triggered on detected bad frees and
1353   reallocs. The argument p is an address that might have triggered the
1354   fault. It is ignored by the two predefined actions, but might be
1355   useful in custom actions that try to help diagnose errors.
1356 */
1357
1358 #if PROCEED_ON_ERROR
1359
1360 /* A count of the number of corruption errors causing resets */
1361 int malloc_corruption_error_count;
1362
1363 /* default corruption action */
1364 static void reset_on_error(mstate m);
1365
1366 #define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)
1367 #define USAGE_ERROR_ACTION(m, p)
1368
1369 #else /* PROCEED_ON_ERROR */
1370
1371 #ifndef CORRUPTION_ERROR_ACTION
1372 #define CORRUPTION_ERROR_ACTION(m) DLM_ABORT
1373 #endif /* CORRUPTION_ERROR_ACTION */
1374
1375 #ifndef USAGE_ERROR_ACTION
1376 #define USAGE_ERROR_ACTION(m,p) DLM_ABORT
1377 #endif /* USAGE_ERROR_ACTION */
1378
1379 #endif /* PROCEED_ON_ERROR */
1380
1381
1382 /* -------------------------- Debugging setup ---------------------------- */
1383
1384 #if ! DEBUG
1385
1386 #define check_free_chunk(M,P)
1387 #define check_inuse_chunk(M,P)
1388 #define check_malloced_chunk(M,P,N)
1389 #define check_mmapped_chunk(M,P)
1390 #define check_malloc_state(M)
1391 #define check_top_chunk(M,P)
1392
1393 #else /* DEBUG */
1394 #define check_free_chunk(M,P)       do_check_free_chunk(M,P)
1395 #define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)
1396 #define check_top_chunk(M,P)        do_check_top_chunk(M,P)
1397 #define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
1398 #define check_mmapped_chunk(M,P)    do_check_mmapped_chunk(M,P)
1399 #define check_malloc_state(M)       do_check_malloc_state(M)
1400
1401 static void   do_check_any_chunk(mstate m, mchunkptr p);
1402 static void   do_check_top_chunk(mstate m, mchunkptr p);
1403 static void   do_check_mmapped_chunk(mstate m, mchunkptr p);
1404 static void   do_check_inuse_chunk(mstate m, mchunkptr p);
1405 static void   do_check_free_chunk(mstate m, mchunkptr p);
1406 static void   do_check_malloced_chunk(mstate m, void* mem, size_t s);
1407 static void   do_check_tree(mstate m, tchunkptr t);
1408 static void   do_check_treebin(mstate m, bindex_t i);
1409 static void   do_check_smallbin(mstate m, bindex_t i);
1410 static void   do_check_malloc_state(mstate m);
1411 static int    bin_find(mstate m, mchunkptr x);
1412 static size_t traverse_and_check(mstate m);
1413 #endif /* DEBUG */
1414
1415 /* ---------------------------- Indexing Bins ---------------------------- */
1416
1417 #define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
1418 #define small_index(s)      (bindex_t)((s)  >> SMALLBIN_SHIFT)
1419 #define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
1420 #define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
1421
1422 /* addressing by index. See above about smallbin repositioning */
1423 #define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
1424 #define treebin_at(M,i)     (&((M)->treebins[i]))
1425
1426 /* assign tree index for size S to variable I. Use x86 asm if possible  */
1427 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1428 #define compute_tree_index(S, I)\
1429 {\
1430   unsigned int X = S >> TREEBIN_SHIFT;\
1431   if (X == 0)\
1432     I = 0;\
1433   else if (X > 0xFFFF)\
1434     I = NTREEBINS-1;\
1435   else {\
1436     unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \
1437     I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
1438   }\
1439 }
1440
1441 #elif defined (__INTEL_COMPILER)
1442 #define compute_tree_index(S, I)\
1443 {\
1444   size_t X = S >> TREEBIN_SHIFT;\
1445   if (X == 0)\
1446     I = 0;\
1447   else if (X > 0xFFFF)\
1448     I = NTREEBINS-1;\
1449   else {\
1450     unsigned int K = _bit_scan_reverse (X); \
1451     I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
1452   }\
1453 }
1454
1455 #elif defined(_MSC_VER) && _MSC_VER>=1300
1456 #define compute_tree_index(S, I)\
1457 {\
1458   size_t X = S >> TREEBIN_SHIFT;\
1459   if (X == 0)\
1460     I = 0;\
1461   else if (X > 0xFFFF)\
1462     I = NTREEBINS-1;\
1463   else {\
1464     unsigned int K;\
1465     _BitScanReverse((DWORD *) &K, (DWORD) X);\
1466     I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
1467   }\
1468 }
1469
1470 #else /* GNUC */
1471 #define compute_tree_index(S, I)\
1472 {\
1473   size_t X = S >> TREEBIN_SHIFT;\
1474   if (X == 0)\
1475     I = 0;\
1476   else if (X > 0xFFFF)\
1477     I = NTREEBINS-1;\
1478   else {\
1479     unsigned int Y = (unsigned int)X;\
1480     unsigned int N = ((Y - 0x100) >> 16) & 8;\
1481     unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
1482     N += K;\
1483     N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
1484     K = 14 - N + ((Y <<= K) >> 15);\
1485     I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
1486   }\
1487 }
1488 #endif /* GNUC */
1489
1490 /* Bit representing maximum resolved size in a treebin at i */
1491 #define bit_for_tree_index(i) \
1492    (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
1493
1494 /* Shift placing maximum resolved bit in a treebin at i as sign bit */
1495 #define leftshift_for_tree_index(i) \
1496    ((i == NTREEBINS-1)? 0 : \
1497     ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
1498
1499 /* The size of the smallest chunk held in bin with index i */
1500 #define minsize_for_tree_index(i) \
1501    ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
1502    (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
1503
1504
1505 /* ------------------------ Operations on bin maps ----------------------- */
1506
1507 /* bit corresponding to given index */
1508 #define idx2bit(i)              ((binmap_t)(1) << (i))
1509
1510 /* Mark/Clear bits with given index */
1511 #define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
1512 #define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
1513 #define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
1514
1515 #define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
1516 #define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
1517 #define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
1518
1519 /* isolate the least set bit of a bitmap */
1520 #define least_bit(x)         ((x) & -(x))
1521
1522 /* mask with all bits to left of least bit of x on */
1523 #define left_bits(x)         ((x<<1) | -(x<<1))
1524
1525 /* mask with all bits to left of or equal to least bit of x on */
1526 #define same_or_left_bits(x) ((x) | -(x))
1527
1528 /* index corresponding to given bit. Use x86 asm if possible */
1529
1530 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1531 #define compute_bit2idx(X, I)\
1532 {\
1533   unsigned int J;\
1534   J = __builtin_ctz(X); \
1535   I = (bindex_t)J;\
1536 }
1537
1538 #elif defined (__INTEL_COMPILER)
1539 #define compute_bit2idx(X, I)\
1540 {\
1541   unsigned int J;\
1542   J = _bit_scan_forward (X); \
1543   I = (bindex_t)J;\
1544 }
1545
1546 #elif defined(_MSC_VER) && _MSC_VER>=1300
1547 #define compute_bit2idx(X, I)\
1548 {\
1549   unsigned int J;\
1550   _BitScanForward((DWORD *) &J, X);\
1551   I = (bindex_t)J;\
1552 }
1553
1554 #elif USE_BUILTIN_FFS
1555 #define compute_bit2idx(X, I) I = ffs(X)-1
1556
1557 #else
1558 #define compute_bit2idx(X, I)\
1559 {\
1560   unsigned int Y = X - 1;\
1561   unsigned int K = Y >> (16-4) & 16;\
1562   unsigned int N = K;        Y >>= K;\
1563   N += K = Y >> (8-3) &  8;  Y >>= K;\
1564   N += K = Y >> (4-2) &  4;  Y >>= K;\
1565   N += K = Y >> (2-1) &  2;  Y >>= K;\
1566   N += K = Y >> (1-0) &  1;  Y >>= K;\
1567   I = (bindex_t)(N + Y);\
1568 }
1569 #endif /* GNUC */
1570
1571
1572 /* ----------------------- Runtime Check Support ------------------------- */
1573
1574 /*
1575   For security, the main invariant is that malloc/free/etc never
1576   writes to a static address other than malloc_state, unless static
1577   malloc_state itself has been corrupted, which cannot occur via
1578   malloc (because of these checks). In essence this means that we
1579   believe all pointers, sizes, maps etc held in malloc_state, but
1580   check all of those linked or offsetted from other embedded data
1581   structures.  These checks are interspersed with main code in a way
1582   that tends to minimize their run-time cost.
1583
1584   When FOOTERS is defined, in addition to range checking, we also
1585   verify footer fields of inuse chunks, which can be used guarantee
1586   that the mstate controlling malloc/free is intact.  This is a
1587   streamlined version of the approach described by William Robertson
1588   et al in "Run-time Detection of Heap-based Overflows" LISA'03
1589   http://www.usenix.org/events/lisa03/tech/robertson.html The footer
1590   of an inuse chunk holds the xor of its mstate and a random seed,
1591   that is checked upon calls to free() and realloc().  This is
1592   (probabilistically) unguessable from outside the program, but can be
1593   computed by any code successfully malloc'ing any chunk, so does not
1594   itself provide protection against code that has already broken
1595   security through some other means.  Unlike Robertson et al, we
1596   always dynamically check addresses of all offset chunks (previous,
1597   next, etc). This turns out to be cheaper than relying on hashes.
1598 */
1599
1600 #if !INSECURE
1601 /* Check if address a is at least as high as any from MORECORE or MMAP */
1602 #define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
1603 /* Check if address of next chunk n is higher than base chunk p */
1604 #define ok_next(p, n)    ((char*)(p) < (char*)(n))
1605 /* Check if p has inuse status */
1606 #define ok_inuse(p)     is_inuse(p)
1607 /* Check if p has its pinuse bit on */
1608 #define ok_pinuse(p)     pinuse(p)
1609
1610 #else /* !INSECURE */
1611 #define ok_address(M, a) (1)
1612 #define ok_next(b, n)    (1)
1613 #define ok_inuse(p)      (1)
1614 #define ok_pinuse(p)     (1)
1615 #endif /* !INSECURE */
1616
1617 #if (FOOTERS && !INSECURE)
1618 /* Check if (alleged) mstate m has expected magic field */
1619 CLIB_NOSANITIZE_ADDR
1620 static inline int
1621 ok_magic (const mstate m)
1622 {
1623     return (m->magic == mparams.magic);
1624 }
1625 #else  /* (FOOTERS && !INSECURE) */
1626 #define ok_magic(M)      (1)
1627 #endif /* (FOOTERS && !INSECURE) */
1628
1629 /* In gcc, use __builtin_expect to minimize impact of checks */
1630 #if !INSECURE
1631 #if defined(__GNUC__) && __GNUC__ >= 3
1632 #define RTCHECK(e)  __builtin_expect(e, 1)
1633 #else /* GNUC */
1634 #define RTCHECK(e)  (e)
1635 #endif /* GNUC */
1636 #else /* !INSECURE */
1637 #define RTCHECK(e)  (1)
1638 #endif /* !INSECURE */
1639
1640 /* macros to set up inuse chunks with or without footers */
1641
1642 #if !FOOTERS
1643
1644 #define mark_inuse_foot(M,p,s)
1645
1646 /* Macros for setting head/foot of non-mmapped chunks */
1647
1648 /* Set cinuse bit and pinuse bit of next chunk */
1649 #define set_inuse(M,p,s)\
1650   ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
1651   ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
1652
1653 /* Set cinuse and pinuse of this chunk and pinuse of next chunk */
1654 #define set_inuse_and_pinuse(M,p,s)\
1655   ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
1656   ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
1657
1658 /* Set size, cinuse and pinuse bit of this chunk */
1659 #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
1660   ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
1661
1662 #else /* FOOTERS */
1663
1664 /* Set foot of inuse chunk to be xor of mstate and seed */
1665 #define mark_inuse_foot(M,p,s)\
1666   (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
1667
1668 #define get_mstate_for(p)\
1669   ((mstate)(((mchunkptr)((char*)(p) +\
1670     (chunksize(p))))->prev_foot ^ mparams.magic))
1671
1672 #define set_inuse(M,p,s)\
1673   ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
1674   (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
1675   mark_inuse_foot(M,p,s))
1676
1677 #define set_inuse_and_pinuse(M,p,s)\
1678   ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
1679   (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
1680  mark_inuse_foot(M,p,s))
1681
1682 #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
1683   ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
1684   mark_inuse_foot(M, p, s))
1685
1686 #endif /* !FOOTERS */
1687
1688 /* ---------------------------- setting mparams -------------------------- */
1689
1690 #if LOCK_AT_FORK
1691 static void pre_fork(void)         { ACQUIRE_LOCK(&(gm)->mutex); }
1692 static void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); }
1693 static void post_fork_child(void)  { INITIAL_LOCK(&(gm)->mutex); }
1694 #endif /* LOCK_AT_FORK */
1695
1696 /* Initialize mparams */
1697 static int init_mparams(void) {
1698 #ifdef NEED_GLOBAL_LOCK_INIT
1699   if (malloc_global_mutex_status <= 0)
1700     init_malloc_global_mutex();
1701 #endif
1702
1703   ACQUIRE_MALLOC_GLOBAL_LOCK();
1704   if (mparams.magic == 0) {
1705     size_t magic;
1706     size_t psize;
1707     size_t gsize;
1708
1709 #ifndef WIN32
1710     psize = malloc_getpagesize;
1711     gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize);
1712 #else /* WIN32 */
1713     {
1714       SYSTEM_INFO system_info;
1715       GetSystemInfo(&system_info);
1716       psize = system_info.dwPageSize;
1717       gsize = ((DEFAULT_GRANULARITY != 0)?
1718                DEFAULT_GRANULARITY : system_info.dwAllocationGranularity);
1719     }
1720 #endif /* WIN32 */
1721
1722     /* Sanity-check configuration:
1723        size_t must be unsigned and as wide as pointer type.
1724        ints must be at least 4 bytes.
1725        alignment must be at least 8.
1726        Alignment, min chunk size, and page size must all be powers of 2.
1727     */
1728     if ((sizeof(size_t) != sizeof(char*)) ||
1729         (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||
1730         (sizeof(int) < 4)  ||
1731         (MALLOC_ALIGNMENT < (size_t)8U) ||
1732         ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
1733         ((MCHUNK_SIZE      & (MCHUNK_SIZE-SIZE_T_ONE))      != 0) ||
1734         ((gsize            & (gsize-SIZE_T_ONE))            != 0) ||
1735         ((psize            & (psize-SIZE_T_ONE))            != 0))
1736       DLM_ABORT;
1737     mparams.granularity = gsize;
1738     mparams.page_size = psize;
1739     mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
1740     mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
1741 #if MORECORE_CONTIGUOUS
1742     mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
1743 #else  /* MORECORE_CONTIGUOUS */
1744     mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
1745 #endif /* MORECORE_CONTIGUOUS */
1746
1747 #if !ONLY_MSPACES
1748     /* Set up lock for main malloc area */
1749     gm->mflags = mparams.default_mflags;
1750     (void)INITIAL_LOCK(&gm->mutex);
1751 #endif
1752 #if LOCK_AT_FORK
1753     pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child);
1754 #endif
1755
1756     {
1757 #ifndef DLM_MAGIC_CONSTANT
1758 #if USE_DEV_RANDOM
1759       int fd;
1760       unsigned char buf[sizeof(size_t)];
1761       /* Try to use /dev/urandom, else fall back on using time */
1762       if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
1763           read(fd, buf, sizeof(buf)) == sizeof(buf)) {
1764         magic = *((size_t *) buf);
1765         close(fd);
1766       }
1767       else
1768 #endif /* USE_DEV_RANDOM */
1769 #ifdef WIN32
1770       magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U);
1771 #elif defined(LACKS_TIME_H)
1772       magic = (size_t)&magic ^ (size_t)0x55555555U;
1773 #else
1774       magic = (size_t)(time(0) ^ (size_t)0x55555555U);
1775 #endif
1776       magic |= (size_t)8U;    /* ensure nonzero */
1777       magic &= ~(size_t)7U;   /* improve chances of fault for bad values */
1778 #else
1779       magic = DLM_MAGIC_CONSTANT;
1780 #endif
1781       /* Until memory modes commonly available, use volatile-write */
1782       (*(volatile size_t *)(&(mparams.magic))) = magic;
1783     }
1784   }
1785
1786   RELEASE_MALLOC_GLOBAL_LOCK();
1787   return 1;
1788 }
1789
1790 /* support for mallopt */
1791 static int change_mparam(int param_number, int value) {
1792   size_t val;
1793   ensure_initialization();
1794   val = (value == -1)? MAX_SIZE_T : (size_t)value;
1795   switch(param_number) {
1796   case M_TRIM_THRESHOLD:
1797     mparams.trim_threshold = val;
1798     return 1;
1799   case M_GRANULARITY:
1800     if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
1801       mparams.granularity = val;
1802       return 1;
1803     }
1804     else
1805       return 0;
1806   case M_MMAP_THRESHOLD:
1807     mparams.mmap_threshold = val;
1808     return 1;
1809   default:
1810     return 0;
1811   }
1812 }
1813
1814 #if DEBUG
1815 /* ------------------------- Debugging Support --------------------------- */
1816
1817 /* Check properties of any chunk, whether free, inuse, mmapped etc  */
1818 static void do_check_any_chunk(mstate m, mchunkptr p) {
1819   assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1820   assert(ok_address(m, p));
1821 }
1822
1823 /* Check properties of top chunk */
1824 static void do_check_top_chunk(mstate m, mchunkptr p) {
1825   msegmentptr sp = segment_holding(m, (char*)p);
1826   size_t  sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */
1827   assert(sp != 0);
1828   assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1829   assert(ok_address(m, p));
1830   assert(sz == m->topsize);
1831   assert(sz > 0);
1832   assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
1833   assert(pinuse(p));
1834   assert(!pinuse(chunk_plus_offset(p, sz)));
1835 }
1836
1837 /* Check properties of (inuse) mmapped chunks */
1838 static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
1839   size_t  sz = chunksize(p);
1840   size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD);
1841   assert(is_mmapped(p));
1842   assert(use_mmap(m));
1843   assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1844   assert(ok_address(m, p));
1845   assert(!is_small(sz));
1846   assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
1847   assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
1848   assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
1849 }
1850
1851 /* Check properties of inuse chunks */
1852 static void do_check_inuse_chunk(mstate m, mchunkptr p) {
1853   do_check_any_chunk(m, p);
1854   assert(is_inuse(p));
1855   assert(next_pinuse(p));
1856   /* If not pinuse and not mmapped, previous chunk has OK offset */
1857   assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
1858   if (is_mmapped(p))
1859     do_check_mmapped_chunk(m, p);
1860 }
1861
1862 /* Check properties of free chunks */
1863 static void do_check_free_chunk(mstate m, mchunkptr p) {
1864   size_t sz = chunksize(p);
1865   mchunkptr next = chunk_plus_offset(p, sz);
1866   do_check_any_chunk(m, p);
1867   assert(!is_inuse(p));
1868   assert(!next_pinuse(p));
1869   assert (!is_mmapped(p));
1870   if (p != m->dv && p != m->top) {
1871     if (sz >= MIN_CHUNK_SIZE) {
1872       assert((sz & CHUNK_ALIGN_MASK) == 0);
1873       assert(is_aligned(chunk2mem(p)));
1874       assert(next->prev_foot == sz);
1875       assert(pinuse(p));
1876       assert (next == m->top || is_inuse(next));
1877       assert(p->fd->bk == p);
1878       assert(p->bk->fd == p);
1879     }
1880     else  /* markers are always of size SIZE_T_SIZE */
1881       assert(sz == SIZE_T_SIZE);
1882   }
1883 }
1884
1885 /* Check properties of malloced chunks at the point they are malloced */
1886 static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
1887   if (mem != 0) {
1888     mchunkptr p = mem2chunk(mem);
1889     size_t sz = p->head & ~INUSE_BITS;
1890     do_check_inuse_chunk(m, p);
1891     assert((sz & CHUNK_ALIGN_MASK) == 0);
1892     assert(sz >= MIN_CHUNK_SIZE);
1893     assert(sz >= s);
1894     /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
1895     assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
1896   }
1897 }
1898
1899 /* Check a tree and its subtrees.  */
1900 static void do_check_tree(mstate m, tchunkptr t) {
1901   tchunkptr head = 0;
1902   tchunkptr u = t;
1903   bindex_t tindex = t->index;
1904   size_t tsize = chunksize(t);
1905   bindex_t idx;
1906   compute_tree_index(tsize, idx);
1907   assert(tindex == idx);
1908   assert(tsize >= MIN_LARGE_SIZE);
1909   assert(tsize >= minsize_for_tree_index(idx));
1910   assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
1911
1912   do { /* traverse through chain of same-sized nodes */
1913     do_check_any_chunk(m, ((mchunkptr)u));
1914     assert(u->index == tindex);
1915     assert(chunksize(u) == tsize);
1916     assert(!is_inuse(u));
1917     assert(!next_pinuse(u));
1918     assert(u->fd->bk == u);
1919     assert(u->bk->fd == u);
1920     if (u->parent == 0) {
1921       assert(u->child[0] == 0);
1922       assert(u->child[1] == 0);
1923     }
1924     else {
1925       assert(head == 0); /* only one node on chain has parent */
1926       head = u;
1927       assert(u->parent != u);
1928       assert (u->parent->child[0] == u ||
1929               u->parent->child[1] == u ||
1930               *((tbinptr*)(u->parent)) == u);
1931       if (u->child[0] != 0) {
1932         assert(u->child[0]->parent == u);
1933         assert(u->child[0] != u);
1934         do_check_tree(m, u->child[0]);
1935       }
1936       if (u->child[1] != 0) {
1937         assert(u->child[1]->parent == u);
1938         assert(u->child[1] != u);
1939         do_check_tree(m, u->child[1]);
1940       }
1941       if (u->child[0] != 0 && u->child[1] != 0) {
1942         assert(chunksize(u->child[0]) < chunksize(u->child[1]));
1943       }
1944     }
1945     u = u->fd;
1946   } while (u != t);
1947   assert(head != 0);
1948 }
1949
1950 /*  Check all the chunks in a treebin.  */
1951 static void do_check_treebin(mstate m, bindex_t i) {
1952   tbinptr* tb = treebin_at(m, i);
1953   tchunkptr t = *tb;
1954   int empty = (m->treemap & (1U << i)) == 0;
1955   if (t == 0)
1956     assert(empty);
1957   if (!empty)
1958     do_check_tree(m, t);
1959 }
1960
1961 /*  Check all the chunks in a smallbin.  */
1962 static void do_check_smallbin(mstate m, bindex_t i) {
1963   sbinptr b = smallbin_at(m, i);
1964   mchunkptr p = b->bk;
1965   unsigned int empty = (m->smallmap & (1U << i)) == 0;
1966   if (p == b)
1967     assert(empty);
1968   if (!empty) {
1969     for (; p != b; p = p->bk) {
1970       size_t size = chunksize(p);
1971       mchunkptr q;
1972       /* each chunk claims to be free */
1973       do_check_free_chunk(m, p);
1974       /* chunk belongs in bin */
1975       assert(small_index(size) == i);
1976       assert(p->bk == b || chunksize(p->bk) == chunksize(p));
1977       /* chunk is followed by an inuse chunk */
1978       q = next_chunk(p);
1979       if (q->head != FENCEPOST_HEAD)
1980         do_check_inuse_chunk(m, q);
1981     }
1982   }
1983 }
1984
1985 /* Find x in a bin. Used in other check functions. */
1986 static int bin_find(mstate m, mchunkptr x) {
1987   size_t size = chunksize(x);
1988   if (is_small(size)) {
1989     bindex_t sidx = small_index(size);
1990     sbinptr b = smallbin_at(m, sidx);
1991     if (smallmap_is_marked(m, sidx)) {
1992       mchunkptr p = b;
1993       do {
1994         if (p == x)
1995           return 1;
1996       } while ((p = p->fd) != b);
1997     }
1998   }
1999   else {
2000     bindex_t tidx;
2001     compute_tree_index(size, tidx);
2002     if (treemap_is_marked(m, tidx)) {
2003       tchunkptr t = *treebin_at(m, tidx);
2004       size_t sizebits = size << leftshift_for_tree_index(tidx);
2005       while (t != 0 && chunksize(t) != size) {
2006         t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
2007         sizebits <<= 1;
2008       }
2009       if (t != 0) {
2010         tchunkptr u = t;
2011         do {
2012           if (u == (tchunkptr)x)
2013             return 1;
2014         } while ((u = u->fd) != t);
2015       }
2016     }
2017   }
2018   return 0;
2019 }
2020
2021 /* Traverse each chunk and check it; return total */
2022 static size_t traverse_and_check(mstate m) {
2023   size_t sum = 0;
2024   if (is_initialized(m)) {
2025     msegmentptr s = &m->seg;
2026     sum += m->topsize + TOP_FOOT_SIZE;
2027     while (s != 0) {
2028       mchunkptr q = align_as_chunk(s->base);
2029       mchunkptr lastq = 0;
2030       assert(pinuse(q));
2031       while (segment_holds(s, q) &&
2032              q != m->top && q->head != FENCEPOST_HEAD) {
2033         sum += chunksize(q);
2034         if (is_inuse(q)) {
2035           assert(!bin_find(m, q));
2036           do_check_inuse_chunk(m, q);
2037         }
2038         else {
2039           assert(q == m->dv || bin_find(m, q));
2040           assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */
2041           do_check_free_chunk(m, q);
2042         }
2043         lastq = q;
2044         q = next_chunk(q);
2045       }
2046       s = s->next;
2047     }
2048   }
2049   return sum;
2050 }
2051
2052
2053 /* Check all properties of malloc_state. */
2054 static void do_check_malloc_state(mstate m) {
2055   bindex_t i;
2056   size_t total;
2057   /* check bins */
2058   for (i = 0; i < NSMALLBINS; ++i)
2059     do_check_smallbin(m, i);
2060   for (i = 0; i < NTREEBINS; ++i)
2061     do_check_treebin(m, i);
2062
2063   if (m->dvsize != 0) { /* check dv chunk */
2064     do_check_any_chunk(m, m->dv);
2065     assert(m->dvsize == chunksize(m->dv));
2066     assert(m->dvsize >= MIN_CHUNK_SIZE);
2067     assert(bin_find(m, m->dv) == 0);
2068   }
2069
2070   if (m->top != 0) {   /* check top chunk */
2071     do_check_top_chunk(m, m->top);
2072     /*assert(m->topsize == chunksize(m->top)); redundant */
2073     assert(m->topsize > 0);
2074     assert(bin_find(m, m->top) == 0);
2075   }
2076
2077   total = traverse_and_check(m);
2078   assert(total <= m->footprint);
2079   assert(m->footprint <= m->max_footprint);
2080 }
2081 #endif /* DEBUG */
2082
2083 /* ----------------------------- statistics ------------------------------ */
2084
2085 #if !NO_MALLINFO
2086 CLIB_NOSANITIZE_ADDR
2087 static struct dlmallinfo internal_mallinfo(mstate m) {
2088   struct dlmallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2089   ensure_initialization();
2090   if (!PREACTION(m)) {
2091     check_malloc_state(m);
2092     if (is_initialized(m)) {
2093       size_t nfree = SIZE_T_ONE; /* top always free */
2094       size_t mfree = m->topsize + TOP_FOOT_SIZE;
2095       size_t sum = mfree;
2096       msegmentptr s = &m->seg;
2097       while (s != 0) {
2098         mchunkptr q = align_as_chunk(s->base);
2099         while (segment_holds(s, q) &&
2100                q != m->top && q->head != FENCEPOST_HEAD) {
2101           size_t sz = chunksize(q);
2102           sum += sz;
2103           if (!is_inuse(q)) {
2104             mfree += sz;
2105             ++nfree;
2106           }
2107           q = next_chunk(q);
2108         }
2109         s = s->next;
2110       }
2111
2112       nm.arena    = sum;
2113       nm.ordblks  = nfree;
2114       nm.hblkhd   = m->footprint - sum;
2115       nm.usmblks  = m->max_footprint;
2116       nm.uordblks = m->footprint - mfree;
2117       nm.fordblks = mfree;
2118       nm.keepcost = m->topsize;
2119     }
2120
2121     POSTACTION(m);
2122   }
2123   return nm;
2124 }
2125 #endif /* !NO_MALLINFO */
2126
2127 #if !NO_MALLOC_STATS
2128 static void internal_malloc_stats(mstate m) {
2129   ensure_initialization();
2130   if (!PREACTION(m)) {
2131     size_t maxfp = 0;
2132     size_t fp = 0;
2133     size_t used = 0;
2134     check_malloc_state(m);
2135     if (is_initialized(m)) {
2136       msegmentptr s = &m->seg;
2137       maxfp = m->max_footprint;
2138       fp = m->footprint;
2139       used = fp - (m->topsize + TOP_FOOT_SIZE);
2140
2141       while (s != 0) {
2142         mchunkptr q = align_as_chunk(s->base);
2143         while (segment_holds(s, q) &&
2144                q != m->top && q->head != FENCEPOST_HEAD) {
2145           if (!is_inuse(q))
2146             used -= chunksize(q);
2147           q = next_chunk(q);
2148         }
2149         s = s->next;
2150       }
2151     }
2152     POSTACTION(m); /* drop lock */
2153     fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
2154     fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
2155     fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
2156   }
2157 }
2158 #endif /* NO_MALLOC_STATS */
2159
2160 /* ----------------------- Operations on smallbins ----------------------- */
2161
2162 /*
2163   Various forms of linking and unlinking are defined as macros.  Even
2164   the ones for trees, which are very long but have very short typical
2165   paths.  This is ugly but reduces reliance on inlining support of
2166   compilers.
2167 */
2168
2169 /* Link a free chunk into a smallbin  */
2170 #define insert_small_chunk(M, P, S) {\
2171   bindex_t I  = small_index(S);\
2172   mchunkptr B = smallbin_at(M, I);\
2173   mchunkptr F = B;\
2174   assert(S >= MIN_CHUNK_SIZE);\
2175   if (!smallmap_is_marked(M, I))\
2176     mark_smallmap(M, I);\
2177   else if (RTCHECK(ok_address(M, B->fd)))\
2178     F = B->fd;\
2179   else {\
2180     CORRUPTION_ERROR_ACTION(M);\
2181   }\
2182   B->fd = P;\
2183   F->bk = P;\
2184   P->fd = F;\
2185   P->bk = B;\
2186 }
2187
2188 /* Unlink a chunk from a smallbin  */
2189 #define unlink_small_chunk(M, P, S) {\
2190   mchunkptr F = P->fd;\
2191   mchunkptr B = P->bk;\
2192   bindex_t I = small_index(S);\
2193   assert(P != B);\
2194   assert(P != F);\
2195   assert(chunksize(P) == small_index2size(I));\
2196   if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \
2197     if (B == F) {\
2198       clear_smallmap(M, I);\
2199     }\
2200     else if (RTCHECK(B == smallbin_at(M,I) ||\
2201                      (ok_address(M, B) && B->fd == P))) {\
2202       F->bk = B;\
2203       B->fd = F;\
2204     }\
2205     else {\
2206       CORRUPTION_ERROR_ACTION(M);\
2207     }\
2208   }\
2209   else {\
2210     CORRUPTION_ERROR_ACTION(M);\
2211   }\
2212 }
2213
2214 /* Unlink the first chunk from a smallbin */
2215 #define unlink_first_small_chunk(M, B, P, I) {\
2216   mchunkptr F = P->fd;\
2217   assert(P != B);\
2218   assert(P != F);\
2219   assert(chunksize(P) == small_index2size(I));\
2220   if (B == F) {\
2221     clear_smallmap(M, I);\
2222   }\
2223   else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\
2224     F->bk = B;\
2225     B->fd = F;\
2226   }\
2227   else {\
2228     CORRUPTION_ERROR_ACTION(M);\
2229   }\
2230 }
2231
2232 /* Replace dv node, binning the old one */
2233 /* Used only when dvsize known to be small */
2234 #define replace_dv(M, P, S) {\
2235   size_t DVS = M->dvsize;\
2236   assert(is_small(DVS));\
2237   if (DVS != 0) {\
2238     mchunkptr DV = M->dv;\
2239     insert_small_chunk(M, DV, DVS);\
2240   }\
2241   M->dvsize = S;\
2242   M->dv = P;\
2243 }
2244
2245 /* ------------------------- Operations on trees ------------------------- */
2246
2247 /* Insert chunk into tree */
2248 #define insert_large_chunk(M, X, S) {\
2249   tbinptr* H;\
2250   bindex_t I;\
2251   compute_tree_index(S, I);\
2252   H = treebin_at(M, I);\
2253   X->index = I;\
2254   X->child[0] = X->child[1] = 0;\
2255   if (!treemap_is_marked(M, I)) {\
2256     mark_treemap(M, I);\
2257     *H = X;\
2258     X->parent = (tchunkptr)H;\
2259     X->fd = X->bk = X;\
2260   }\
2261   else {\
2262     tchunkptr T = *H;\
2263     size_t K = S << leftshift_for_tree_index(I);\
2264     for (;;) {\
2265       if (chunksize(T) != S) {\
2266         tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
2267         K <<= 1;\
2268         if (*C != 0)\
2269           T = *C;\
2270         else if (RTCHECK(ok_address(M, C))) {\
2271           *C = X;\
2272           X->parent = T;\
2273           X->fd = X->bk = X;\
2274           break;\
2275         }\
2276         else {\
2277           CORRUPTION_ERROR_ACTION(M);\
2278           break;\
2279         }\
2280       }\
2281       else {\
2282         tchunkptr F = T->fd;\
2283         if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
2284           T->fd = F->bk = X;\
2285           X->fd = F;\
2286           X->bk = T;\
2287           X->parent = 0;\
2288           break;\
2289         }\
2290         else {\
2291           CORRUPTION_ERROR_ACTION(M);\
2292           break;\
2293         }\
2294       }\
2295     }\
2296   }\
2297 }
2298
2299 /*
2300   Unlink steps:
2301
2302   1. If x is a chained node, unlink it from its same-sized fd/bk links
2303      and choose its bk node as its replacement.
2304   2. If x was the last node of its size, but not a leaf node, it must
2305      be replaced with a leaf node (not merely one with an open left or
2306      right), to make sure that lefts and rights of descendents
2307      correspond properly to bit masks.  We use the rightmost descendent
2308      of x.  We could use any other leaf, but this is easy to locate and
2309      tends to counteract removal of leftmosts elsewhere, and so keeps
2310      paths shorter than minimally guaranteed.  This doesn't loop much
2311      because on average a node in a tree is near the bottom.
2312   3. If x is the base of a chain (i.e., has parent links) relink
2313      x's parent and children to x's replacement (or null if none).
2314 */
2315
2316 #define unlink_large_chunk(M, X) {\
2317   tchunkptr XP = X->parent;\
2318   tchunkptr R;\
2319   if (X->bk != X) {\
2320     tchunkptr F = X->fd;\
2321     R = X->bk;\
2322     if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\
2323       F->bk = R;\
2324       R->fd = F;\
2325     }\
2326     else {\
2327       CORRUPTION_ERROR_ACTION(M);\
2328     }\
2329   }\
2330   else {\
2331     tchunkptr* RP;\
2332     if (((R = *(RP = &(X->child[1]))) != 0) ||\
2333         ((R = *(RP = &(X->child[0]))) != 0)) {\
2334       tchunkptr* CP;\
2335       while ((*(CP = &(R->child[1])) != 0) ||\
2336              (*(CP = &(R->child[0])) != 0)) {\
2337         R = *(RP = CP);\
2338       }\
2339       if (RTCHECK(ok_address(M, RP)))\
2340         *RP = 0;\
2341       else {\
2342         CORRUPTION_ERROR_ACTION(M);\
2343       }\
2344     }\
2345   }\
2346   if (XP != 0) {\
2347     tbinptr* H = treebin_at(M, X->index);\
2348     if (X == *H) {\
2349       if ((*H = R) == 0) \
2350         clear_treemap(M, X->index);\
2351     }\
2352     else if (RTCHECK(ok_address(M, XP))) {\
2353       if (XP->child[0] == X) \
2354         XP->child[0] = R;\
2355       else \
2356         XP->child[1] = R;\
2357     }\
2358     else\
2359       CORRUPTION_ERROR_ACTION(M);\
2360     if (R != 0) {\
2361       if (RTCHECK(ok_address(M, R))) {\
2362         tchunkptr C0, C1;\
2363         R->parent = XP;\
2364         if ((C0 = X->child[0]) != 0) {\
2365           if (RTCHECK(ok_address(M, C0))) {\
2366             R->child[0] = C0;\
2367             C0->parent = R;\
2368           }\
2369           else\
2370             CORRUPTION_ERROR_ACTION(M);\
2371         }\
2372         if ((C1 = X->child[1]) != 0) {\
2373           if (RTCHECK(ok_address(M, C1))) {\
2374             R->child[1] = C1;\
2375             C1->parent = R;\
2376           }\
2377           else\
2378             CORRUPTION_ERROR_ACTION(M);\
2379         }\
2380       }\
2381       else\
2382         CORRUPTION_ERROR_ACTION(M);\
2383     }\
2384   }\
2385 }
2386
2387 /* Relays to large vs small bin operations */
2388
2389 #define insert_chunk(M, P, S)\
2390   if (is_small(S)) insert_small_chunk(M, P, S)\
2391   else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
2392
2393 #define unlink_chunk(M, P, S)\
2394   if (is_small(S)) unlink_small_chunk(M, P, S)\
2395   else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
2396
2397
2398 /* Relays to internal calls to malloc/free from realloc, memalign etc */
2399
2400 #if ONLY_MSPACES
2401 #define internal_malloc(m, b) mspace_malloc(m, b)
2402 #define internal_free(m, mem) mspace_free(m,mem);
2403 #else /* ONLY_MSPACES */
2404 #if MSPACES
2405 #define internal_malloc(m, b)\
2406   ((m == gm)? dlmalloc(b) : mspace_malloc(m, b))
2407 #define internal_free(m, mem)\
2408    if (m == gm) dlfree(mem); else mspace_free(m,mem);
2409 #else /* MSPACES */
2410 #define internal_malloc(m, b) dlmalloc(b)
2411 #define internal_free(m, mem) dlfree(mem)
2412 #endif /* MSPACES */
2413 #endif /* ONLY_MSPACES */
2414
2415 /* -----------------------  Direct-mmapping chunks ----------------------- */
2416
2417 /*
2418   Directly mmapped chunks are set up with an offset to the start of
2419   the mmapped region stored in the prev_foot field of the chunk. This
2420   allows reconstruction of the required argument to MUNMAP when freed,
2421   and also allows adjustment of the returned chunk to meet alignment
2422   requirements (especially in memalign).
2423 */
2424
2425 /* Malloc using mmap */
2426 static void* mmap_alloc(mstate m, size_t nb) {
2427   size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2428   if (m->footprint_limit != 0) {
2429     size_t fp = m->footprint + mmsize;
2430     if (fp <= m->footprint || fp > m->footprint_limit)
2431       return 0;
2432   }
2433   if (mmsize > nb) {     /* Check for wrap around 0 */
2434     char* mm = (char*)(CALL_DIRECT_MMAP(mmsize));
2435     if (mm != CMFAIL) {
2436       size_t offset = align_offset(chunk2mem(mm));
2437       size_t psize = mmsize - offset - MMAP_FOOT_PAD;
2438       mchunkptr p = (mchunkptr)(mm + offset);
2439       p->prev_foot = offset;
2440       p->head = psize;
2441       mark_inuse_foot(m, p, psize);
2442       chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
2443       chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
2444
2445       if (m->least_addr == 0 || mm < m->least_addr)
2446         m->least_addr = mm;
2447       if ((m->footprint += mmsize) > m->max_footprint)
2448         m->max_footprint = m->footprint;
2449       assert(is_aligned(chunk2mem(p)));
2450       check_mmapped_chunk(m, p);
2451       return chunk2mem(p);
2452     }
2453   }
2454   return 0;
2455 }
2456
2457 /* Realloc using mmap */
2458 static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) {
2459   size_t oldsize = chunksize(oldp);
2460   (void)flags; /* placate people compiling -Wunused */
2461   if (is_small(nb)) /* Can't shrink mmap regions below small size */
2462     return 0;
2463   /* Keep old chunk if big enough but not too big */
2464   if (oldsize >= nb + SIZE_T_SIZE &&
2465       (oldsize - nb) <= (mparams.granularity << 1))
2466     return oldp;
2467   else {
2468     size_t offset = oldp->prev_foot;
2469     size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
2470     size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2471     char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
2472                                   oldmmsize, newmmsize, flags);
2473     if (cp != CMFAIL) {
2474       mchunkptr newp = (mchunkptr)(cp + offset);
2475       size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
2476       newp->head = psize;
2477       mark_inuse_foot(m, newp, psize);
2478       chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
2479       chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
2480
2481       if (cp < m->least_addr)
2482         m->least_addr = cp;
2483       if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
2484         m->max_footprint = m->footprint;
2485       check_mmapped_chunk(m, newp);
2486       return newp;
2487     }
2488   }
2489   return 0;
2490 }
2491
2492
2493 /* -------------------------- mspace management -------------------------- */
2494
2495 /* Initialize top chunk and its size */
2496 static void init_top(mstate m, mchunkptr p, size_t psize) {
2497   /* Ensure alignment */
2498   size_t offset = align_offset(chunk2mem(p));
2499   p = (mchunkptr)((char*)p + offset);
2500   psize -= offset;
2501
2502   m->top = p;
2503   m->topsize = psize;
2504   p->head = psize | PINUSE_BIT;
2505   /* set size of fake trailing chunk holding overhead space only once */
2506   chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
2507   m->trim_check = mparams.trim_threshold; /* reset on each update */
2508 }
2509
2510 /* Initialize bins for a new mstate that is otherwise zeroed out */
2511 static void init_bins(mstate m) {
2512   /* Establish circular links for smallbins */
2513   bindex_t i;
2514   for (i = 0; i < NSMALLBINS; ++i) {
2515     sbinptr bin = smallbin_at(m,i);
2516     bin->fd = bin->bk = bin;
2517   }
2518 }
2519
2520 #if PROCEED_ON_ERROR
2521
2522 /* default corruption action */
2523 static void reset_on_error(mstate m) {
2524   int i;
2525   ++malloc_corruption_error_count;
2526   /* Reinitialize fields to forget about all memory */
2527   m->smallmap = m->treemap = 0;
2528   m->dvsize = m->topsize = 0;
2529   m->seg.base = 0;
2530   m->seg.size = 0;
2531   m->seg.next = 0;
2532   m->top = m->dv = 0;
2533   for (i = 0; i < NTREEBINS; ++i)
2534     *treebin_at(m, i) = 0;
2535   init_bins(m);
2536 }
2537 #endif /* PROCEED_ON_ERROR */
2538
2539 /* Allocate chunk and prepend remainder with chunk in successor base. */
2540 static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
2541                            size_t nb) {
2542   mchunkptr p = align_as_chunk(newbase);
2543   mchunkptr oldfirst = align_as_chunk(oldbase);
2544   size_t psize = (char*)oldfirst - (char*)p;
2545   mchunkptr q = chunk_plus_offset(p, nb);
2546   size_t qsize = psize - nb;
2547   set_size_and_pinuse_of_inuse_chunk(m, p, nb);
2548
2549   assert((char*)oldfirst > (char*)q);
2550   assert(pinuse(oldfirst));
2551   assert(qsize >= MIN_CHUNK_SIZE);
2552
2553   /* consolidate remainder with first chunk of old base */
2554   if (oldfirst == m->top) {
2555     size_t tsize = m->topsize += qsize;
2556     m->top = q;
2557     q->head = tsize | PINUSE_BIT;
2558     check_top_chunk(m, q);
2559   }
2560   else if (oldfirst == m->dv) {
2561     size_t dsize = m->dvsize += qsize;
2562     m->dv = q;
2563     set_size_and_pinuse_of_free_chunk(q, dsize);
2564   }
2565   else {
2566     if (!is_inuse(oldfirst)) {
2567       size_t nsize = chunksize(oldfirst);
2568       unlink_chunk(m, oldfirst, nsize);
2569       oldfirst = chunk_plus_offset(oldfirst, nsize);
2570       qsize += nsize;
2571     }
2572     set_free_with_pinuse(q, qsize, oldfirst);
2573     insert_chunk(m, q, qsize);
2574     check_free_chunk(m, q);
2575   }
2576
2577   check_malloced_chunk(m, chunk2mem(p), nb);
2578   return chunk2mem(p);
2579 }
2580
2581 /* Add a segment to hold a new noncontiguous region */
2582 static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
2583   /* Determine locations and sizes of segment, fenceposts, old top */
2584   char* old_top = (char*)m->top;
2585   msegmentptr oldsp = segment_holding(m, old_top);
2586   char* old_end = oldsp->base + oldsp->size;
2587   size_t ssize = pad_request(sizeof(struct malloc_segment));
2588   char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2589   size_t offset = align_offset(chunk2mem(rawsp));
2590   char* asp = rawsp + offset;
2591   char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
2592   mchunkptr sp = (mchunkptr)csp;
2593   msegmentptr ss = (msegmentptr)(chunk2mem(sp));
2594   mchunkptr tnext = chunk_plus_offset(sp, ssize);
2595   mchunkptr p = tnext;
2596   int nfences = 0;
2597
2598   /* reset top to new space */
2599   init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
2600
2601   /* Set up segment record */
2602   assert(is_aligned(ss));
2603   set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
2604   *ss = m->seg; /* Push current record */
2605   m->seg.base = tbase;
2606   m->seg.size = tsize;
2607   m->seg.sflags = mmapped;
2608   m->seg.next = ss;
2609
2610   /* Insert trailing fenceposts */
2611   for (;;) {
2612     mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
2613     p->head = FENCEPOST_HEAD;
2614     ++nfences;
2615     if ((char*)(&(nextp->head)) < old_end)
2616       p = nextp;
2617     else
2618       break;
2619   }
2620   assert(nfences >= 2);
2621
2622   /* Insert the rest of old top into a bin as an ordinary free chunk */
2623   if (csp != old_top) {
2624     mchunkptr q = (mchunkptr)old_top;
2625     size_t psize = csp - old_top;
2626     mchunkptr tn = chunk_plus_offset(q, psize);
2627     set_free_with_pinuse(q, psize, tn);
2628     insert_chunk(m, q, psize);
2629   }
2630
2631   check_top_chunk(m, m->top);
2632 }
2633
2634 /* -------------------------- System allocation -------------------------- */
2635
2636 /* Get memory from system using MORECORE or MMAP */
2637 static void* sys_alloc(mstate m, size_t nb) {
2638   char* tbase = CMFAIL;
2639   size_t tsize = 0;
2640   flag_t mmap_flag = 0;
2641   size_t asize; /* allocation size */
2642
2643   ensure_initialization();
2644
2645   if (use_noexpand(m))
2646       return 0;
2647
2648   /* Directly map large chunks, but only if already initialized */
2649   if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) {
2650     void* mem = mmap_alloc(m, nb);
2651     if (mem != 0)
2652       return mem;
2653   }
2654
2655   asize = granularity_align(nb + SYS_ALLOC_PADDING);
2656   if (asize <= nb)
2657     return 0; /* wraparound */
2658   if (m->footprint_limit != 0) {
2659     size_t fp = m->footprint + asize;
2660     if (fp <= m->footprint || fp > m->footprint_limit)
2661       return 0;
2662   }
2663
2664   /*
2665     Try getting memory in any of three ways (in most-preferred to
2666     least-preferred order):
2667     1. A call to MORECORE that can normally contiguously extend memory.
2668        (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
2669        or main space is mmapped or a previous contiguous call failed)
2670     2. A call to MMAP new space (disabled if not HAVE_MMAP).
2671        Note that under the default settings, if MORECORE is unable to
2672        fulfill a request, and HAVE_MMAP is true, then mmap is
2673        used as a noncontiguous system allocator. This is a useful backup
2674        strategy for systems with holes in address spaces -- in this case
2675        sbrk cannot contiguously expand the heap, but mmap may be able to
2676        find space.
2677     3. A call to MORECORE that cannot usually contiguously extend memory.
2678        (disabled if not HAVE_MORECORE)
2679
2680    In all cases, we need to request enough bytes from system to ensure
2681    we can malloc nb bytes upon success, so pad with enough space for
2682    top_foot, plus alignment-pad to make sure we don't lose bytes if
2683    not on boundary, and round this up to a granularity unit.
2684   */
2685
2686   if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
2687     char* br = CMFAIL;
2688     size_t ssize = asize; /* sbrk call size */
2689     msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
2690     ACQUIRE_MALLOC_GLOBAL_LOCK();
2691
2692     if (ss == 0) {  /* First time through or recovery */
2693       char* base = (char*)CALL_MORECORE(0);
2694       if (base != CMFAIL) {
2695         size_t fp;
2696         /* Adjust to end on a page boundary */
2697         if (!is_page_aligned(base))
2698           ssize += (page_align((size_t)base) - (size_t)base);
2699         fp = m->footprint + ssize; /* recheck limits */
2700         if (ssize > nb && ssize < HALF_MAX_SIZE_T &&
2701             (m->footprint_limit == 0 ||
2702              (fp > m->footprint && fp <= m->footprint_limit)) &&
2703             (br = (char*)(CALL_MORECORE(ssize))) == base) {
2704           tbase = base;
2705           tsize = ssize;
2706         }
2707       }
2708     }
2709     else {
2710       /* Subtract out existing available top space from MORECORE request. */
2711       ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING);
2712       /* Use mem here only if it did continuously extend old space */
2713       if (ssize < HALF_MAX_SIZE_T &&
2714           (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) {
2715         tbase = br;
2716         tsize = ssize;
2717       }
2718     }
2719
2720     if (tbase == CMFAIL) {    /* Cope with partial failure */
2721       if (br != CMFAIL) {    /* Try to use/extend the space we did get */
2722         if (ssize < HALF_MAX_SIZE_T &&
2723             ssize < nb + SYS_ALLOC_PADDING) {
2724           size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize);
2725           if (esize < HALF_MAX_SIZE_T) {
2726             char* end = (char*)CALL_MORECORE(esize);
2727             if (end != CMFAIL)
2728               ssize += esize;
2729             else {            /* Can't use; try to release */
2730               (void) CALL_MORECORE(-ssize);
2731               br = CMFAIL;
2732             }
2733           }
2734         }
2735       }
2736       if (br != CMFAIL) {    /* Use the space we did get */
2737         tbase = br;
2738         tsize = ssize;
2739       }
2740       else
2741         disable_contiguous(m); /* Don't try contiguous path in the future */
2742     }
2743
2744     RELEASE_MALLOC_GLOBAL_LOCK();
2745   }
2746
2747   if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
2748     char* mp = (char*)(CALL_MMAP(asize));
2749     if (mp != CMFAIL) {
2750       tbase = mp;
2751       tsize = asize;
2752       mmap_flag = USE_MMAP_BIT;
2753     }
2754   }
2755
2756   if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
2757     if (asize < HALF_MAX_SIZE_T) {
2758       char* br = CMFAIL;
2759       char* end = CMFAIL;
2760       ACQUIRE_MALLOC_GLOBAL_LOCK();
2761       br = (char*)(CALL_MORECORE(asize));
2762       end = (char*)(CALL_MORECORE(0));
2763       RELEASE_MALLOC_GLOBAL_LOCK();
2764       if (br != CMFAIL && end != CMFAIL && br < end) {
2765         size_t ssize = end - br;
2766         if (ssize > nb + TOP_FOOT_SIZE) {
2767           tbase = br;
2768           tsize = ssize;
2769         }
2770       }
2771     }
2772   }
2773
2774   if (tbase != CMFAIL) {
2775
2776     if ((m->footprint += tsize) > m->max_footprint)
2777       m->max_footprint = m->footprint;
2778
2779     if (!is_initialized(m)) { /* first-time initialization */
2780       if (m->least_addr == 0 || tbase < m->least_addr)
2781         m->least_addr = tbase;
2782       m->seg.base = tbase;
2783       m->seg.size = tsize;
2784       m->seg.sflags = mmap_flag;
2785       m->magic = mparams.magic;
2786       m->release_checks = MAX_RELEASE_CHECK_RATE;
2787       init_bins(m);
2788 #if !ONLY_MSPACES
2789       if (is_global(m))
2790         init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
2791       else
2792 #endif
2793       {
2794         /* Offset top by embedded malloc_state */
2795         mchunkptr mn = next_chunk(mem2chunk(m));
2796         init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
2797       }
2798     }
2799
2800     else {
2801       /* Try to merge with an existing segment */
2802       msegmentptr sp = &m->seg;
2803       /* Only consider most recent segment if traversal suppressed */
2804       while (sp != 0 && tbase != sp->base + sp->size)
2805         sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
2806       if (sp != 0 &&
2807           !is_extern_segment(sp) &&
2808           (sp->sflags & USE_MMAP_BIT) == mmap_flag &&
2809           segment_holds(sp, m->top)) { /* append */
2810         sp->size += tsize;
2811         init_top(m, m->top, m->topsize + tsize);
2812       }
2813       else {
2814         if (tbase < m->least_addr)
2815           m->least_addr = tbase;
2816         sp = &m->seg;
2817         while (sp != 0 && sp->base != tbase + tsize)
2818           sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
2819         if (sp != 0 &&
2820             !is_extern_segment(sp) &&
2821             (sp->sflags & USE_MMAP_BIT) == mmap_flag) {
2822           char* oldbase = sp->base;
2823           sp->base = tbase;
2824           sp->size += tsize;
2825           return prepend_alloc(m, tbase, oldbase, nb);
2826         }
2827         else
2828           add_segment(m, tbase, tsize, mmap_flag);
2829       }
2830     }
2831
2832     if (nb < m->topsize) { /* Allocate from new or extended top space */
2833       size_t rsize = m->topsize -= nb;
2834       mchunkptr p = m->top;
2835       mchunkptr r = m->top = chunk_plus_offset(p, nb);
2836       r->head = rsize | PINUSE_BIT;
2837       set_size_and_pinuse_of_inuse_chunk(m, p, nb);
2838       check_top_chunk(m, m->top);
2839       check_malloced_chunk(m, chunk2mem(p), nb);
2840       return chunk2mem(p);
2841     }
2842   }
2843
2844   MALLOC_FAILURE_ACTION;
2845   return 0;
2846 }
2847
2848 /* -----------------------  system deallocation -------------------------- */
2849
2850 /* Unmap and unlink any mmapped segments that don't contain used chunks */
2851 CLIB_NOSANITIZE_ADDR
2852 static size_t release_unused_segments(mstate m) {
2853   size_t released = 0;
2854   int nsegs = 0;
2855   msegmentptr pred = &m->seg;
2856   msegmentptr sp = pred->next;
2857   while (sp != 0) {
2858     char* base = sp->base;
2859     size_t size = sp->size;
2860     msegmentptr next = sp->next;
2861     ++nsegs;
2862     if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
2863       mchunkptr p = align_as_chunk(base);
2864       size_t psize = chunksize(p);
2865       /* Can unmap if first chunk holds entire segment and not pinned */
2866       if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
2867         tchunkptr tp = (tchunkptr)p;
2868         assert(segment_holds(sp, (char*)sp));
2869         if (p == m->dv) {
2870           m->dv = 0;
2871           m->dvsize = 0;
2872         }
2873         else {
2874           unlink_large_chunk(m, tp);
2875         }
2876         if (CALL_MUNMAP(base, size) == 0) {
2877           released += size;
2878           m->footprint -= size;
2879           /* unlink obsoleted record */
2880           sp = pred;
2881           sp->next = next;
2882         }
2883         else { /* back out if cannot unmap */
2884           insert_large_chunk(m, tp, psize);
2885         }
2886       }
2887     }
2888     if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */
2889       break;
2890     pred = sp;
2891     sp = next;
2892   }
2893   /* Reset check counter */
2894   m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)?
2895                        (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE);
2896   return released;
2897 }
2898
2899 CLIB_NOSANITIZE_ADDR
2900 static int sys_trim(mstate m, size_t pad) {
2901   size_t released = 0;
2902   ensure_initialization();
2903   if (pad < MAX_REQUEST && is_initialized(m)) {
2904     pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
2905
2906     if (m->topsize > pad) {
2907       /* Shrink top space in granularity-size units, keeping at least one */
2908       size_t unit = mparams.granularity;
2909       size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
2910                       SIZE_T_ONE) * unit;
2911       msegmentptr sp = segment_holding(m, (char*)m->top);
2912
2913       if (!is_extern_segment(sp)) {
2914         if (is_mmapped_segment(sp)) {
2915           if (HAVE_MMAP &&
2916               sp->size >= extra &&
2917               !has_segment_link(m, sp)) { /* can't shrink if pinned */
2918             size_t newsize = sp->size - extra;
2919             (void)newsize; /* placate people compiling -Wunused-variable */
2920             /* Prefer mremap, fall back to munmap */
2921             if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
2922                 (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
2923               released = extra;
2924             }
2925           }
2926         }
2927         else if (HAVE_MORECORE) {
2928           if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
2929             extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
2930           ACQUIRE_MALLOC_GLOBAL_LOCK();
2931           {
2932             /* Make sure end of memory is where we last set it. */
2933             char* old_br = (char*)(CALL_MORECORE(0));
2934             if (old_br == sp->base + sp->size) {
2935               char* rel_br = (char*)(CALL_MORECORE(-extra));
2936               char* new_br = (char*)(CALL_MORECORE(0));
2937               if (rel_br != CMFAIL && new_br < old_br)
2938                 released = old_br - new_br;
2939             }
2940           }
2941           RELEASE_MALLOC_GLOBAL_LOCK();
2942         }
2943       }
2944
2945       if (released != 0) {
2946         sp->size -= released;
2947         m->footprint -= released;
2948         init_top(m, m->top, m->topsize - released);
2949         check_top_chunk(m, m->top);
2950       }
2951     }
2952
2953     /* Unmap any unused mmapped segments */
2954     if (HAVE_MMAP)
2955       released += release_unused_segments(m);
2956
2957     /* On failure, disable autotrim to avoid repeated failed future calls */
2958     if (released == 0 && m->topsize > m->trim_check)
2959       m->trim_check = MAX_SIZE_T;
2960   }
2961
2962   return (released != 0)? 1 : 0;
2963 }
2964
2965 /* Consolidate and bin a chunk. Differs from exported versions
2966    of free mainly in that the chunk need not be marked as inuse.
2967 */
2968 CLIB_NOSANITIZE_ADDR
2969 static void dispose_chunk(mstate m, mchunkptr p, size_t psize) {
2970   mchunkptr next = chunk_plus_offset(p, psize);
2971   if (!pinuse(p)) {
2972     mchunkptr prev;
2973     size_t prevsize = p->prev_foot;
2974     if (is_mmapped(p)) {
2975       psize += prevsize + MMAP_FOOT_PAD;
2976       if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
2977         m->footprint -= psize;
2978       return;
2979     }
2980     prev = chunk_minus_offset(p, prevsize);
2981     psize += prevsize;
2982     p = prev;
2983     if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */
2984       if (p != m->dv) {
2985         unlink_chunk(m, p, prevsize);
2986       }
2987       else if ((next->head & INUSE_BITS) == INUSE_BITS) {
2988         m->dvsize = psize;
2989         set_free_with_pinuse(p, psize, next);
2990         return;
2991       }
2992     }
2993     else {
2994       CORRUPTION_ERROR_ACTION(m);
2995       return;
2996     }
2997   }
2998   if (RTCHECK(ok_address(m, next))) {
2999     if (!cinuse(next)) {  /* consolidate forward */
3000       if (next == m->top) {
3001         size_t tsize = m->topsize += psize;
3002         m->top = p;
3003         p->head = tsize | PINUSE_BIT;
3004         if (p == m->dv) {
3005           m->dv = 0;
3006           m->dvsize = 0;
3007         }
3008         return;
3009       }
3010       else if (next == m->dv) {
3011         size_t dsize = m->dvsize += psize;
3012         m->dv = p;
3013         set_size_and_pinuse_of_free_chunk(p, dsize);
3014         return;
3015       }
3016       else {
3017         size_t nsize = chunksize(next);
3018         psize += nsize;
3019         unlink_chunk(m, next, nsize);
3020         set_size_and_pinuse_of_free_chunk(p, psize);
3021         if (p == m->dv) {
3022           m->dvsize = psize;
3023           return;
3024         }
3025       }
3026     }
3027     else {
3028       set_free_with_pinuse(p, psize, next);
3029     }
3030     insert_chunk(m, p, psize);
3031   }
3032   else {
3033     CORRUPTION_ERROR_ACTION(m);
3034   }
3035 }
3036
3037 /* ---------------------------- malloc --------------------------- */
3038
3039 /* allocate a large request from the best fitting chunk in a treebin */
3040 CLIB_NOSANITIZE_ADDR
3041 static void* tmalloc_large(mstate m, size_t nb) {
3042   tchunkptr v = 0;
3043   size_t rsize = -nb; /* Unsigned negation */
3044   tchunkptr t;
3045   bindex_t idx;
3046   compute_tree_index(nb, idx);
3047   if ((t = *treebin_at(m, idx)) != 0) {
3048     /* Traverse tree for this bin looking for node with size == nb */
3049     size_t sizebits = nb << leftshift_for_tree_index(idx);
3050     tchunkptr rst = 0;  /* The deepest untaken right subtree */
3051     for (;;) {
3052       tchunkptr rt;
3053       size_t trem = chunksize(t) - nb;
3054       if (trem < rsize) {
3055         v = t;
3056         if ((rsize = trem) == 0)
3057           break;
3058       }
3059       rt = t->child[1];
3060       t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
3061       if (rt != 0 && rt != t)
3062         rst = rt;
3063       if (t == 0) {
3064         t = rst; /* set t to least subtree holding sizes > nb */
3065         break;
3066       }
3067       sizebits <<= 1;
3068     }
3069   }
3070   if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
3071     binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
3072     if (leftbits != 0) {
3073       bindex_t i;
3074       binmap_t leastbit = least_bit(leftbits);
3075       compute_bit2idx(leastbit, i);
3076       t = *treebin_at(m, i);
3077     }
3078   }
3079
3080   while (t != 0) { /* find smallest of tree or subtree */
3081     size_t trem = chunksize(t) - nb;
3082     if (trem < rsize) {
3083       rsize = trem;
3084       v = t;
3085     }
3086     t = leftmost_child(t);
3087   }
3088
3089   /*  If dv is a better fit, return 0 so malloc will use it */
3090   if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
3091     if (RTCHECK(ok_address(m, v))) { /* split */
3092       mchunkptr r = chunk_plus_offset(v, nb);
3093       assert(chunksize(v) == rsize + nb);
3094       if (RTCHECK(ok_next(v, r))) {
3095         unlink_large_chunk(m, v);
3096         if (rsize < MIN_CHUNK_SIZE)
3097           set_inuse_and_pinuse(m, v, (rsize + nb));
3098         else {
3099           set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3100           set_size_and_pinuse_of_free_chunk(r, rsize);
3101           insert_chunk(m, r, rsize);
3102         }
3103         return chunk2mem(v);
3104       }
3105     }
3106     CORRUPTION_ERROR_ACTION(m);
3107   }
3108   return 0;
3109 }
3110
3111 /* allocate a small request from the best fitting chunk in a treebin */
3112 CLIB_NOSANITIZE_ADDR
3113 static void* tmalloc_small(mstate m, size_t nb) {
3114   tchunkptr t, v;
3115   size_t rsize;
3116   bindex_t i;
3117   binmap_t leastbit = least_bit(m->treemap);
3118   compute_bit2idx(leastbit, i);
3119   v = t = *treebin_at(m, i);
3120   rsize = chunksize(t) - nb;
3121
3122   while ((t = leftmost_child(t)) != 0) {
3123     size_t trem = chunksize(t) - nb;
3124     if (trem < rsize) {
3125       rsize = trem;
3126       v = t;
3127     }
3128   }
3129
3130   if (RTCHECK(ok_address(m, v))) {
3131     mchunkptr r = chunk_plus_offset(v, nb);
3132     assert(chunksize(v) == rsize + nb);
3133     if (RTCHECK(ok_next(v, r))) {
3134       unlink_large_chunk(m, v);
3135       if (rsize < MIN_CHUNK_SIZE)
3136         set_inuse_and_pinuse(m, v, (rsize + nb));
3137       else {
3138         set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3139         set_size_and_pinuse_of_free_chunk(r, rsize);
3140         replace_dv(m, r, rsize);
3141       }
3142       return chunk2mem(v);
3143     }
3144   }
3145
3146   CORRUPTION_ERROR_ACTION(m);
3147   return 0;
3148 }
3149
3150 #if !ONLY_MSPACES
3151
3152 void* dlmalloc(size_t bytes) {
3153   /*
3154      Basic algorithm:
3155      If a small request (< 256 bytes minus per-chunk overhead):
3156        1. If one exists, use a remainderless chunk in associated smallbin.
3157           (Remainderless means that there are too few excess bytes to
3158           represent as a chunk.)
3159        2. If it is big enough, use the dv chunk, which is normally the
3160           chunk adjacent to the one used for the most recent small request.
3161        3. If one exists, split the smallest available chunk in a bin,
3162           saving remainder in dv.
3163        4. If it is big enough, use the top chunk.
3164        5. If available, get memory from system and use it
3165      Otherwise, for a large request:
3166        1. Find the smallest available binned chunk that fits, and use it
3167           if it is better fitting than dv chunk, splitting if necessary.
3168        2. If better fitting than any binned chunk, use the dv chunk.
3169        3. If it is big enough, use the top chunk.
3170        4. If request size >= mmap threshold, try to directly mmap this chunk.
3171        5. If available, get memory from system and use it
3172
3173      The ugly goto's here ensure that postaction occurs along all paths.
3174   */
3175
3176 #if USE_LOCKS
3177   ensure_initialization(); /* initialize in sys_alloc if not using locks */
3178 #endif
3179
3180   if (!PREACTION(gm)) {
3181     void* mem;
3182     size_t nb;
3183     if (bytes <= MAX_SMALL_REQUEST) {
3184       bindex_t idx;
3185       binmap_t smallbits;
3186       nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
3187       idx = small_index(nb);
3188       smallbits = gm->smallmap >> idx;
3189
3190       if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
3191         mchunkptr b, p;
3192         idx += ~smallbits & 1;       /* Uses next bin if idx empty */
3193         b = smallbin_at(gm, idx);
3194         p = b->fd;
3195         assert(chunksize(p) == small_index2size(idx));
3196         unlink_first_small_chunk(gm, b, p, idx);
3197         set_inuse_and_pinuse(gm, p, small_index2size(idx));
3198         mem = chunk2mem(p);
3199         check_malloced_chunk(gm, mem, nb);
3200         goto postaction;
3201       }
3202
3203       else if (nb > gm->dvsize) {
3204         if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
3205           mchunkptr b, p, r;
3206           size_t rsize;
3207           bindex_t i;
3208           binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
3209           binmap_t leastbit = least_bit(leftbits);
3210           compute_bit2idx(leastbit, i);
3211           b = smallbin_at(gm, i);
3212           p = b->fd;
3213           assert(chunksize(p) == small_index2size(i));
3214           unlink_first_small_chunk(gm, b, p, i);
3215           rsize = small_index2size(i) - nb;
3216           /* Fit here cannot be remainderless if 4byte sizes */
3217           if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
3218             set_inuse_and_pinuse(gm, p, small_index2size(i));
3219           else {
3220             set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3221             r = chunk_plus_offset(p, nb);
3222             set_size_and_pinuse_of_free_chunk(r, rsize);
3223             replace_dv(gm, r, rsize);
3224           }
3225           mem = chunk2mem(p);
3226           check_malloced_chunk(gm, mem, nb);
3227           goto postaction;
3228         }
3229
3230         else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
3231           check_malloced_chunk(gm, mem, nb);
3232           goto postaction;
3233         }
3234       }
3235     }
3236     else if (bytes >= MAX_REQUEST)
3237       nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
3238     else {
3239       nb = pad_request(bytes);
3240       if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
3241         check_malloced_chunk(gm, mem, nb);
3242         goto postaction;
3243       }
3244     }
3245
3246     if (nb <= gm->dvsize) {
3247       size_t rsize = gm->dvsize - nb;
3248       mchunkptr p = gm->dv;
3249       if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
3250         mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
3251         gm->dvsize = rsize;
3252         set_size_and_pinuse_of_free_chunk(r, rsize);
3253         set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3254       }
3255       else { /* exhaust dv */
3256         size_t dvs = gm->dvsize;
3257         gm->dvsize = 0;
3258         gm->dv = 0;
3259         set_inuse_and_pinuse(gm, p, dvs);
3260       }
3261       mem = chunk2mem(p);
3262       check_malloced_chunk(gm, mem, nb);
3263       goto postaction;
3264     }
3265
3266     else if (nb < gm->topsize) { /* Split top */
3267       size_t rsize = gm->topsize -= nb;
3268       mchunkptr p = gm->top;
3269       mchunkptr r = gm->top = chunk_plus_offset(p, nb);
3270       r->head = rsize | PINUSE_BIT;
3271       set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3272       mem = chunk2mem(p);
3273       check_top_chunk(gm, gm->top);
3274       check_malloced_chunk(gm, mem, nb);
3275       goto postaction;
3276     }
3277
3278     mem = sys_alloc(gm, nb);
3279
3280   postaction:
3281     POSTACTION(gm);
3282     return mem;
3283   }
3284
3285   return 0;
3286 }
3287
3288 /* ---------------------------- free --------------------------- */
3289
3290 void dlfree(void* mem) {
3291   /*
3292      Consolidate freed chunks with preceding or succeeding bordering
3293      free chunks, if they exist, and then place in a bin.  Intermixed
3294      with special cases for top, dv, mmapped chunks, and usage errors.
3295   */
3296
3297   if (mem != 0) {
3298     mchunkptr p  = mem2chunk(mem);
3299 #if FOOTERS
3300     mstate fm = get_mstate_for(p);
3301     if (!ok_magic(fm)) {
3302       USAGE_ERROR_ACTION(fm, p);
3303       return;
3304     }
3305 #else /* FOOTERS */
3306 #define fm gm
3307 #endif /* FOOTERS */
3308     if (!PREACTION(fm)) {
3309       check_inuse_chunk(fm, p);
3310       if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
3311         size_t psize = chunksize(p);
3312         mchunkptr next = chunk_plus_offset(p, psize);
3313         if (!pinuse(p)) {
3314           size_t prevsize = p->prev_foot;
3315           if (is_mmapped(p)) {
3316             psize += prevsize + MMAP_FOOT_PAD;
3317             if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
3318               fm->footprint -= psize;
3319             goto postaction;
3320           }
3321           else {
3322             mchunkptr prev = chunk_minus_offset(p, prevsize);
3323             psize += prevsize;
3324             p = prev;
3325             if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
3326               if (p != fm->dv) {
3327                 unlink_chunk(fm, p, prevsize);
3328               }
3329               else if ((next->head & INUSE_BITS) == INUSE_BITS) {
3330                 fm->dvsize = psize;
3331                 set_free_with_pinuse(p, psize, next);
3332                 goto postaction;
3333               }
3334             }
3335             else
3336               goto erroraction;
3337           }
3338         }
3339
3340         if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
3341           if (!cinuse(next)) {  /* consolidate forward */
3342             if (next == fm->top) {
3343               size_t tsize = fm->topsize += psize;
3344               fm->top = p;
3345               p->head = tsize | PINUSE_BIT;
3346               if (p == fm->dv) {
3347                 fm->dv = 0;
3348                 fm->dvsize = 0;
3349               }
3350               if (should_trim(fm, tsize))
3351                 sys_trim(fm, 0);
3352               goto postaction;
3353             }
3354             else if (next == fm->dv) {
3355               size_t dsize = fm->dvsize += psize;
3356               fm->dv = p;
3357               set_size_and_pinuse_of_free_chunk(p, dsize);
3358               goto postaction;
3359             }
3360             else {
3361               size_t nsize = chunksize(next);
3362               psize += nsize;
3363               unlink_chunk(fm, next, nsize);
3364               set_size_and_pinuse_of_free_chunk(p, psize);
3365               if (p == fm->dv) {
3366                 fm->dvsize = psize;
3367                 goto postaction;
3368               }
3369             }
3370           }
3371           else
3372             set_free_with_pinuse(p, psize, next);
3373
3374           if (is_small(psize)) {
3375             insert_small_chunk(fm, p, psize);
3376             check_free_chunk(fm, p);
3377           }
3378           else {
3379             tchunkptr tp = (tchunkptr)p;
3380             insert_large_chunk(fm, tp, psize);
3381             check_free_chunk(fm, p);
3382             if (--fm->release_checks == 0)
3383               release_unused_segments(fm);
3384           }
3385           goto postaction;
3386         }
3387       }
3388     erroraction:
3389       USAGE_ERROR_ACTION(fm, p);
3390     postaction:
3391       POSTACTION(fm);
3392     }
3393   }
3394 #if !FOOTERS
3395 #undef fm
3396 #endif /* FOOTERS */
3397 }
3398
3399 void* dlcalloc(size_t n_elements, size_t elem_size) {
3400   void* mem;
3401   size_t req = 0;
3402   if (n_elements != 0) {
3403     req = n_elements * elem_size;
3404     if (((n_elements | elem_size) & ~(size_t)0xffff) &&
3405         (req / n_elements != elem_size))
3406       req = MAX_SIZE_T; /* force downstream failure on overflow */
3407   }
3408   mem = dlmalloc(req);
3409   if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
3410     memset(mem, 0, req);
3411   return mem;
3412 }
3413
3414 #endif /* !ONLY_MSPACES */
3415
3416 /* ------------ Internal support for realloc, memalign, etc -------------- */
3417
3418 /* Try to realloc; only in-place unless can_move true */
3419 static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb,
3420                                    int can_move) {
3421   mchunkptr newp = 0;
3422   size_t oldsize = chunksize(p);
3423   mchunkptr next = chunk_plus_offset(p, oldsize);
3424   if (RTCHECK(ok_address(m, p) && ok_inuse(p) &&
3425               ok_next(p, next) && ok_pinuse(next))) {
3426     if (is_mmapped(p)) {
3427       newp = mmap_resize(m, p, nb, can_move);
3428     }
3429     else if (oldsize >= nb) {             /* already big enough */
3430       size_t rsize = oldsize - nb;
3431       if (rsize >= MIN_CHUNK_SIZE) {      /* split off remainder */
3432         mchunkptr r = chunk_plus_offset(p, nb);
3433         set_inuse(m, p, nb);
3434         set_inuse(m, r, rsize);
3435         dispose_chunk(m, r, rsize);
3436       }
3437       newp = p;
3438     }
3439     else if (next == m->top) {  /* extend into top */
3440       if (oldsize + m->topsize > nb) {
3441         size_t newsize = oldsize + m->topsize;
3442         size_t newtopsize = newsize - nb;
3443         mchunkptr newtop = chunk_plus_offset(p, nb);
3444         set_inuse(m, p, nb);
3445         newtop->head = newtopsize |PINUSE_BIT;
3446         m->top = newtop;
3447         m->topsize = newtopsize;
3448         newp = p;
3449       }
3450     }
3451     else if (next == m->dv) { /* extend into dv */
3452       size_t dvs = m->dvsize;
3453       if (oldsize + dvs >= nb) {
3454         size_t dsize = oldsize + dvs - nb;
3455         if (dsize >= MIN_CHUNK_SIZE) {
3456           mchunkptr r = chunk_plus_offset(p, nb);
3457           mchunkptr n = chunk_plus_offset(r, dsize);
3458           set_inuse(m, p, nb);
3459           set_size_and_pinuse_of_free_chunk(r, dsize);
3460           clear_pinuse(n);
3461           m->dvsize = dsize;
3462           m->dv = r;
3463         }
3464         else { /* exhaust dv */
3465           size_t newsize = oldsize + dvs;
3466           set_inuse(m, p, newsize);
3467           m->dvsize = 0;
3468           m->dv = 0;
3469         }
3470         newp = p;
3471       }
3472     }
3473     else if (!cinuse(next)) { /* extend into next free chunk */
3474       size_t nextsize = chunksize(next);
3475       if (oldsize + nextsize >= nb) {
3476         size_t rsize = oldsize + nextsize - nb;
3477         unlink_chunk(m, next, nextsize);
3478         if (rsize < MIN_CHUNK_SIZE) {
3479           size_t newsize = oldsize + nextsize;
3480           set_inuse(m, p, newsize);
3481         }
3482         else {
3483           mchunkptr r = chunk_plus_offset(p, nb);
3484           set_inuse(m, p, nb);
3485           set_inuse(m, r, rsize);
3486           dispose_chunk(m, r, rsize);
3487         }
3488         newp = p;
3489       }
3490     }
3491   }
3492   else {
3493     USAGE_ERROR_ACTION(m, chunk2mem(p));
3494   }
3495   return newp;
3496 }
3497
3498 CLIB_NOSANITIZE_ADDR
3499 static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
3500   void* mem = 0;
3501   if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
3502     alignment = MIN_CHUNK_SIZE;
3503   if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
3504     size_t a = MALLOC_ALIGNMENT << 1;
3505     while (a < alignment) a <<= 1;
3506     alignment = a;
3507   }
3508   if (bytes >= MAX_REQUEST - alignment) {
3509     if (m != 0)  { /* Test isn't needed but avoids compiler warning */
3510       MALLOC_FAILURE_ACTION;
3511     }
3512   }
3513   else {
3514     size_t nb = request2size(bytes);
3515     size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
3516     mem = internal_malloc(m, req);
3517     if (mem != 0) {
3518       mchunkptr p = mem2chunk(mem);
3519       if (PREACTION(m))
3520         return 0;
3521       if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */
3522         /*
3523           Find an aligned spot inside chunk.  Since we need to give
3524           back leading space in a chunk of at least MIN_CHUNK_SIZE, if
3525           the first calculation places us at a spot with less than
3526           MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
3527           We've allocated enough total room so that this is always
3528           possible.
3529         */
3530         char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment -
3531                                                        SIZE_T_ONE)) &
3532                                              -alignment));
3533         char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
3534           br : br+alignment;
3535         mchunkptr newp = (mchunkptr)pos;
3536         size_t leadsize = pos - (char*)(p);
3537         size_t newsize = chunksize(p) - leadsize;
3538
3539         if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
3540           newp->prev_foot = p->prev_foot + leadsize;
3541           newp->head = newsize;
3542         }
3543         else { /* Otherwise, give back leader, use the rest */
3544           set_inuse(m, newp, newsize);
3545           set_inuse(m, p, leadsize);
3546           dispose_chunk(m, p, leadsize);
3547         }
3548         p = newp;
3549       }
3550
3551       /* Give back spare room at the end */
3552       if (!is_mmapped(p)) {
3553         size_t size = chunksize(p);
3554         if (size > nb + MIN_CHUNK_SIZE) {
3555           size_t remainder_size = size - nb;
3556           mchunkptr remainder = chunk_plus_offset(p, nb);
3557           set_inuse(m, p, nb);
3558           set_inuse(m, remainder, remainder_size);
3559           dispose_chunk(m, remainder, remainder_size);
3560         }
3561       }
3562
3563       mem = chunk2mem(p);
3564       assert (chunksize(p) >= nb);
3565       assert(((size_t)mem & (alignment - 1)) == 0);
3566       check_inuse_chunk(m, p);
3567       POSTACTION(m);
3568     }
3569   }
3570   return mem;
3571 }
3572
3573 /*
3574   Common support for independent_X routines, handling
3575     all of the combinations that can result.
3576   The opts arg has:
3577     bit 0 set if all elements are same size (using sizes[0])
3578     bit 1 set if elements should be zeroed
3579 */
3580 static void** ialloc(mstate m,
3581                      size_t n_elements,
3582                      size_t* sizes,
3583                      int opts,
3584                      void* chunks[]) {
3585
3586   size_t    element_size;   /* chunksize of each element, if all same */
3587   size_t    contents_size;  /* total size of elements */
3588   size_t    array_size;     /* request size of pointer array */
3589   void*     mem;            /* malloced aggregate space */
3590   mchunkptr p;              /* corresponding chunk */
3591   size_t    remainder_size; /* remaining bytes while splitting */
3592   void**    marray;         /* either "chunks" or malloced ptr array */
3593   mchunkptr array_chunk;    /* chunk for malloced ptr array */
3594   flag_t    was_enabled;    /* to disable mmap */
3595   size_t    size;
3596   size_t    i;
3597
3598   ensure_initialization();
3599   /* compute array length, if needed */
3600   if (chunks != 0) {
3601     if (n_elements == 0)
3602       return chunks; /* nothing to do */
3603     marray = chunks;
3604     array_size = 0;
3605   }
3606   else {
3607     /* if empty req, must still return chunk representing empty array */
3608     if (n_elements == 0)
3609       return (void**)internal_malloc(m, 0);
3610     marray = 0;
3611     array_size = request2size(n_elements * (sizeof(void*)));
3612   }
3613
3614   /* compute total element size */
3615   if (opts & 0x1) { /* all-same-size */
3616     element_size = request2size(*sizes);
3617     contents_size = n_elements * element_size;
3618   }
3619   else { /* add up all the sizes */
3620     element_size = 0;
3621     contents_size = 0;
3622     for (i = 0; i != n_elements; ++i)
3623       contents_size += request2size(sizes[i]);
3624   }
3625
3626   size = contents_size + array_size;
3627
3628   /*
3629      Allocate the aggregate chunk.  First disable direct-mmapping so
3630      malloc won't use it, since we would not be able to later
3631      free/realloc space internal to a segregated mmap region.
3632   */
3633   was_enabled = use_mmap(m);
3634   disable_mmap(m);
3635   mem = internal_malloc(m, size - CHUNK_OVERHEAD);
3636   if (was_enabled)
3637     enable_mmap(m);
3638   if (mem == 0)
3639     return 0;
3640
3641   if (PREACTION(m)) return 0;
3642   p = mem2chunk(mem);
3643   remainder_size = chunksize(p);
3644
3645   assert(!is_mmapped(p));
3646
3647   if (opts & 0x2) {       /* optionally clear the elements */
3648     memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
3649   }
3650
3651   /* If not provided, allocate the pointer array as final part of chunk */
3652   if (marray == 0) {
3653     size_t  array_chunk_size;
3654     array_chunk = chunk_plus_offset(p, contents_size);
3655     array_chunk_size = remainder_size - contents_size;
3656     marray = (void**) (chunk2mem(array_chunk));
3657     set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
3658     remainder_size = contents_size;
3659   }
3660
3661   /* split out elements */
3662   for (i = 0; ; ++i) {
3663     marray[i] = chunk2mem(p);
3664     if (i != n_elements-1) {
3665       if (element_size != 0)
3666         size = element_size;
3667       else
3668         size = request2size(sizes[i]);
3669       remainder_size -= size;
3670       set_size_and_pinuse_of_inuse_chunk(m, p, size);
3671       p = chunk_plus_offset(p, size);
3672     }
3673     else { /* the final element absorbs any overallocation slop */
3674       set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
3675       break;
3676     }
3677   }
3678
3679 #if DEBUG
3680   if (marray != chunks) {
3681     /* final element must have exactly exhausted chunk */
3682     if (element_size != 0) {
3683       assert(remainder_size == element_size);
3684     }
3685     else {
3686       assert(remainder_size == request2size(sizes[i]));
3687     }
3688     check_inuse_chunk(m, mem2chunk(marray));
3689   }
3690   for (i = 0; i != n_elements; ++i)
3691     check_inuse_chunk(m, mem2chunk(marray[i]));
3692
3693 #endif /* DEBUG */
3694
3695   POSTACTION(m);
3696   return marray;
3697 }
3698
3699 /* Try to free all pointers in the given array.
3700    Note: this could be made faster, by delaying consolidation,
3701    at the price of disabling some user integrity checks, We
3702    still optimize some consolidations by combining adjacent
3703    chunks before freeing, which will occur often if allocated
3704    with ialloc or the array is sorted.
3705 */
3706 static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) {
3707   size_t unfreed = 0;
3708   if (!PREACTION(m)) {
3709     void** a;
3710     void** fence = &(array[nelem]);
3711     for (a = array; a != fence; ++a) {
3712       void* mem = *a;
3713       if (mem != 0) {
3714         mchunkptr p = mem2chunk(mem);
3715         size_t psize = chunksize(p);
3716 #if FOOTERS
3717         if (get_mstate_for(p) != m) {
3718           ++unfreed;
3719           continue;
3720         }
3721 #endif
3722         check_inuse_chunk(m, p);
3723         *a = 0;
3724         if (RTCHECK(ok_address(m, p) && ok_inuse(p))) {
3725           void ** b = a + 1; /* try to merge with next chunk */
3726           mchunkptr next = next_chunk(p);
3727           if (b != fence && *b == chunk2mem(next)) {
3728             size_t newsize = chunksize(next) + psize;
3729             set_inuse(m, p, newsize);
3730             *b = chunk2mem(p);
3731           }
3732           else
3733             dispose_chunk(m, p, psize);
3734         }
3735         else {
3736           CORRUPTION_ERROR_ACTION(m);
3737           break;
3738         }
3739       }
3740     }
3741     if (should_trim(m, m->topsize))
3742       sys_trim(m, 0);
3743     POSTACTION(m);
3744   }
3745   return unfreed;
3746 }
3747
3748 /* Traversal */
3749 #if MALLOC_INSPECT_ALL
3750 static void internal_inspect_all(mstate m,
3751                                  void(*handler)(void *start,
3752                                                 void *end,
3753                                                 size_t used_bytes,
3754                                                 void* callback_arg),
3755                                  void* arg) {
3756   if (is_initialized(m)) {
3757     mchunkptr top = m->top;
3758     msegmentptr s;
3759     for (s = &m->seg; s != 0; s = s->next) {
3760       mchunkptr q = align_as_chunk(s->base);
3761       while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) {
3762         mchunkptr next = next_chunk(q);
3763         size_t sz = chunksize(q);
3764         size_t used;
3765         void* start;
3766         if (is_inuse(q)) {
3767           used = sz - CHUNK_OVERHEAD; /* must not be mmapped */
3768           start = chunk2mem(q);
3769         }
3770         else {
3771           used = 0;
3772           if (is_small(sz)) {     /* offset by possible bookkeeping */
3773             start = (void*)((char*)q + sizeof(struct malloc_chunk));
3774           }
3775           else {
3776             start = (void*)((char*)q + sizeof(struct malloc_tree_chunk));
3777           }
3778         }
3779         if (start < (void*)next)  /* skip if all space is bookkeeping */
3780           handler(start, next, used, arg);
3781         if (q == top)
3782           break;
3783         q = next;
3784       }
3785     }
3786   }
3787 }
3788 #endif /* MALLOC_INSPECT_ALL */
3789
3790 /* ------------------ Exported realloc, memalign, etc -------------------- */
3791
3792 #if !ONLY_MSPACES
3793
3794 void* dlrealloc(void* oldmem, size_t bytes) {
3795   void* mem = 0;
3796   if (oldmem == 0) {
3797     mem = dlmalloc(bytes);
3798   }
3799   else if (bytes >= MAX_REQUEST) {
3800     MALLOC_FAILURE_ACTION;
3801   }
3802 #ifdef REALLOC_ZERO_BYTES_FREES
3803   else if (bytes == 0) {
3804     dlfree(oldmem);
3805   }
3806 #endif /* REALLOC_ZERO_BYTES_FREES */
3807   else {
3808     size_t nb = request2size(bytes);
3809     mchunkptr oldp = mem2chunk(oldmem);
3810 #if ! FOOTERS
3811     mstate m = gm;
3812 #else /* FOOTERS */
3813     mstate m = get_mstate_for(oldp);
3814     if (!ok_magic(m)) {
3815       USAGE_ERROR_ACTION(m, oldmem);
3816       return 0;
3817     }
3818 #endif /* FOOTERS */
3819     if (!PREACTION(m)) {
3820       mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1);
3821       POSTACTION(m);
3822       if (newp != 0) {
3823         check_inuse_chunk(m, newp);
3824         mem = chunk2mem(newp);
3825       }
3826       else {
3827         mem = internal_malloc(m, bytes);
3828         if (mem != 0) {
3829           size_t oc = chunksize(oldp) - overhead_for(oldp);
3830           memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
3831           internal_free(m, oldmem);
3832         }
3833       }
3834     }
3835   }
3836   return mem;
3837 }
3838
3839 void* dlrealloc_in_place(void* oldmem, size_t bytes) {
3840   void* mem = 0;
3841   if (oldmem != 0) {
3842     if (bytes >= MAX_REQUEST) {
3843       MALLOC_FAILURE_ACTION;
3844     }
3845     else {
3846       size_t nb = request2size(bytes);
3847       mchunkptr oldp = mem2chunk(oldmem);
3848 #if ! FOOTERS
3849       mstate m = gm;
3850 #else /* FOOTERS */
3851       mstate m = get_mstate_for(oldp);
3852       if (!ok_magic(m)) {
3853         USAGE_ERROR_ACTION(m, oldmem);
3854         return 0;
3855       }
3856 #endif /* FOOTERS */
3857       if (!PREACTION(m)) {
3858         mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0);
3859         POSTACTION(m);
3860         if (newp == oldp) {
3861           check_inuse_chunk(m, newp);
3862           mem = oldmem;
3863         }
3864       }
3865     }
3866   }
3867   return mem;
3868 }
3869
3870 void* dlmemalign(size_t alignment, size_t bytes) {
3871   if (alignment <= MALLOC_ALIGNMENT) {
3872     return dlmalloc(bytes);
3873   }
3874   return internal_memalign(gm, alignment, bytes);
3875 }
3876
3877 int dlposix_memalign(void** pp, size_t alignment, size_t bytes) {
3878   void* mem = 0;
3879   if (alignment == MALLOC_ALIGNMENT)
3880     mem = dlmalloc(bytes);
3881   else {
3882     size_t d = alignment / sizeof(void*);
3883     size_t r = alignment % sizeof(void*);
3884     if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0)
3885       return EINVAL;
3886     else if (bytes <= MAX_REQUEST - alignment) {
3887       if (alignment <  MIN_CHUNK_SIZE)
3888         alignment = MIN_CHUNK_SIZE;
3889       mem = internal_memalign(gm, alignment, bytes);
3890     }
3891   }
3892   if (mem == 0)
3893     return ENOMEM;
3894   else {
3895     *pp = mem;
3896     return 0;
3897   }
3898 }
3899
3900 void* dlvalloc(size_t bytes) {
3901   size_t pagesz;
3902   ensure_initialization();
3903   pagesz = mparams.page_size;
3904   return dlmemalign(pagesz, bytes);
3905 }
3906
3907 void* dlpvalloc(size_t bytes) {
3908   size_t pagesz;
3909   ensure_initialization();
3910   pagesz = mparams.page_size;
3911   return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
3912 }
3913
3914 void** dlindependent_calloc(size_t n_elements, size_t elem_size,
3915                             void* chunks[]) {
3916   size_t sz = elem_size; /* serves as 1-element array */
3917   return ialloc(gm, n_elements, &sz, 3, chunks);
3918 }
3919
3920 void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
3921                               void* chunks[]) {
3922   return ialloc(gm, n_elements, sizes, 0, chunks);
3923 }
3924
3925 size_t dlbulk_free(void* array[], size_t nelem) {
3926   return internal_bulk_free(gm, array, nelem);
3927 }
3928
3929 #if MALLOC_INSPECT_ALL
3930 void dlmalloc_inspect_all(void(*handler)(void *start,
3931                                          void *end,
3932                                          size_t used_bytes,
3933                                          void* callback_arg),
3934                           void* arg) {
3935   ensure_initialization();
3936   if (!PREACTION(gm)) {
3937     internal_inspect_all(gm, handler, arg);
3938     POSTACTION(gm);
3939   }
3940 }
3941 #endif /* MALLOC_INSPECT_ALL */
3942
3943 int dlmalloc_trim(size_t pad) {
3944   int result = 0;
3945   ensure_initialization();
3946   if (!PREACTION(gm)) {
3947     result = sys_trim(gm, pad);
3948     POSTACTION(gm);
3949   }
3950   return result;
3951 }
3952
3953 size_t dlmalloc_footprint(void) {
3954   return gm->footprint;
3955 }
3956
3957 size_t dlmalloc_max_footprint(void) {
3958   return gm->max_footprint;
3959 }
3960
3961 size_t dlmalloc_footprint_limit(void) {
3962   size_t maf = gm->footprint_limit;
3963   return maf == 0 ? MAX_SIZE_T : maf;
3964 }
3965
3966 size_t dlmalloc_set_footprint_limit(size_t bytes) {
3967   size_t result;  /* invert sense of 0 */
3968   if (bytes == 0)
3969     result = granularity_align(1); /* Use minimal size */
3970   if (bytes == MAX_SIZE_T)
3971     result = 0;                    /* disable */
3972   else
3973     result = granularity_align(bytes);
3974   return gm->footprint_limit = result;
3975 }
3976
3977 #if !NO_MALLINFO
3978 struct dlmallinfo dlmallinfo(void) {
3979   return internal_mallinfo(gm);
3980 }
3981 #endif /* NO_MALLINFO */
3982
3983 #if !NO_MALLOC_STATS
3984 void dlmalloc_stats() {
3985   internal_malloc_stats(gm);
3986 }
3987 #endif /* NO_MALLOC_STATS */
3988
3989 int dlmallopt(int param_number, int value) {
3990   return change_mparam(param_number, value);
3991 }
3992
3993 size_t dlmalloc_usable_size(void* mem) {
3994   if (mem != 0) {
3995     mchunkptr p = mem2chunk(mem);
3996     if (is_inuse(p))
3997       return chunksize(p) - overhead_for(p);
3998   }
3999   return 0;
4000 }
4001
4002 #endif /* !ONLY_MSPACES */
4003
4004 /* ----------------------------- user mspaces ---------------------------- */
4005
4006 #if MSPACES
4007
4008 static mstate init_user_mstate(char* tbase, size_t tsize) {
4009   size_t msize = pad_request(sizeof(struct malloc_state));
4010   mchunkptr mn;
4011   mchunkptr msp = align_as_chunk(tbase);
4012   mstate m = (mstate)(chunk2mem(msp));
4013   memset(m, 0, msize);
4014   (void)INITIAL_LOCK(&m->mutex);
4015   msp->head = (msize|INUSE_BITS);
4016   m->seg.base = m->least_addr = tbase;
4017   m->seg.size = m->footprint = m->max_footprint = tsize;
4018   m->magic = mparams.magic;
4019   m->release_checks = MAX_RELEASE_CHECK_RATE;
4020   m->mflags = mparams.default_mflags;
4021   m->extp = 0;
4022   m->exts = 0;
4023   disable_contiguous(m);
4024   init_bins(m);
4025   mn = next_chunk(mem2chunk(m));
4026   init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
4027   check_top_chunk(m, m->top);
4028   return m;
4029 }
4030
4031 mspace create_mspace(size_t capacity, int locked) {
4032   mstate m = 0;
4033   size_t msize;
4034   ensure_initialization();
4035   msize = pad_request(sizeof(struct malloc_state));
4036   if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4037     size_t rs = ((capacity == 0)? mparams.granularity :
4038                  (capacity + TOP_FOOT_SIZE + msize));
4039     size_t tsize = granularity_align(rs);
4040     char* tbase = (char*)(CALL_MMAP(tsize));
4041     if (tbase != CMFAIL) {
4042       m = init_user_mstate(tbase, tsize);
4043       m->seg.sflags = USE_MMAP_BIT;
4044       set_lock(m, locked);
4045     }
4046   }
4047   return (mspace)m;
4048 }
4049
4050 mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
4051   mstate m = 0;
4052   size_t msize;
4053   ensure_initialization();
4054   msize = pad_request(sizeof(struct malloc_state));
4055   if (capacity > msize + TOP_FOOT_SIZE &&
4056       capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4057     m = init_user_mstate((char*)base, capacity);
4058     m->seg.sflags = EXTERN_BIT;
4059     set_lock(m, locked);
4060   }
4061   return (mspace)m;
4062 }
4063
4064 int mspace_track_large_chunks(mspace msp, int enable) {
4065   int ret = 0;
4066   mstate ms = (mstate)msp;
4067   if (!PREACTION(ms)) {
4068     if (!use_mmap(ms)) {
4069       ret = 1;
4070     }
4071     if (!enable) {
4072       enable_mmap(ms);
4073     } else {
4074       disable_mmap(ms);
4075     }
4076     POSTACTION(ms);
4077   }
4078   return ret;
4079 }
4080
4081 size_t destroy_mspace(mspace msp) {
4082   size_t freed = 0;
4083   mstate ms = (mstate)msp;
4084   if (ok_magic(ms)) {
4085     msegmentptr sp = &ms->seg;
4086     (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */
4087     while (sp != 0) {
4088       char* base = sp->base;
4089       size_t size = sp->size;
4090       flag_t flag = sp->sflags;
4091       (void)base; /* placate people compiling -Wunused-variable */
4092       sp = sp->next;
4093       if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) &&
4094           CALL_MUNMAP(base, size) == 0)
4095         freed += size;
4096     }
4097   }
4098   else {
4099     USAGE_ERROR_ACTION(ms,ms);
4100   }
4101   return freed;
4102 }
4103
4104 void mspace_get_address_and_size (mspace msp, char **addrp, size_t *sizep)
4105 {
4106   mstate ms;
4107   msegment *this_seg;
4108
4109   ms = (mstate)msp;
4110   this_seg = &ms->seg;
4111
4112   *addrp = this_seg->base;
4113   *sizep = this_seg->size;
4114 }
4115
4116 CLIB_NOSANITIZE_ADDR
4117 int mspace_is_heap_object (mspace msp, void *p)
4118 {
4119   msegment *this_seg;
4120   char *pp, *base;
4121   mstate ms;
4122
4123   ms = (mstate)msp;
4124
4125   this_seg = &ms->seg;
4126   pp = (char *) p;
4127
4128   while (this_seg)
4129     {
4130       base = this_seg->base;
4131       if (pp >= base && pp < (base + this_seg->size))
4132         return 1;
4133       this_seg = this_seg->next;
4134     }
4135
4136   if (pp > ms->least_addr && pp <= ms->least_addr + ms->footprint)
4137     return 1;
4138
4139   return 0;
4140 }
4141
4142 CLIB_NOSANITIZE_ADDR
4143 void *mspace_least_addr (mspace msp)
4144 {
4145   mstate ms = (mstate) msp;
4146   return (void *) ms->least_addr;
4147 }
4148
4149 void mspace_disable_expand (mspace msp)
4150 {
4151   mstate ms = (mstate)msp;
4152
4153   disable_expand (ms);
4154 }
4155
4156 CLIB_NOSANITIZE_ADDR
4157 int mspace_enable_disable_trace (mspace msp, int enable)
4158 {
4159   mstate ms = (mstate)msp;
4160   int was_enabled = 0;
4161
4162   if (use_trace(ms))
4163     was_enabled = 1;
4164
4165   if (enable)
4166     enable_trace (ms);
4167   else
4168     disable_trace (ms);
4169
4170   return (was_enabled);
4171 }
4172
4173 CLIB_NOSANITIZE_ADDR
4174 int mspace_is_traced (mspace msp)
4175 {
4176   mstate ms = (mstate)msp;
4177
4178   if (use_trace(ms))
4179     return 1;
4180   return 0;
4181 }
4182
4183 CLIB_NOSANITIZE_ADDR
4184 void* mspace_get_aligned (mspace msp,
4185                           unsigned long n_user_data_bytes,
4186                           unsigned long align,
4187                           unsigned long align_offset) {
4188   char *rv;
4189   unsigned long searchp;
4190   unsigned *wwp;                /* "where's Waldo" pointer */
4191   mstate ms = (mstate)msp;
4192
4193   /*
4194    * Allocate space for the "Where's Waldo?" pointer
4195    * the base of the dlmalloc object
4196    */
4197   n_user_data_bytes += sizeof(unsigned);
4198
4199   /*
4200    * Alignment requests less than the size of an mmx vector are ignored
4201    */
4202   if (align < sizeof (uword)) {
4203     rv = mspace_malloc (msp, n_user_data_bytes);
4204     if (rv == 0)
4205         return rv;
4206
4207     if (use_trace(ms)) {
4208       mchunkptr p  = mem2chunk(rv);
4209       size_t psize = chunksize(p);
4210
4211       mheap_get_trace ((unsigned long)rv + sizeof (unsigned), psize);
4212     }
4213
4214     wwp = (unsigned *)rv;
4215     *wwp = 0;
4216     rv += sizeof (unsigned);
4217
4218     return rv;
4219   }
4220
4221   /*
4222    * Alignment requests greater than 4K must be at offset zero,
4223    * and must be freed using mspace_free_no_offset - or never freed -
4224    * since the "Where's Waldo?" pointer would waste too much space.
4225    *
4226    * Waldo is the address of the chunk of memory returned by mspace_malloc,
4227    * which we need later to call mspace_free...
4228    */
4229   if (align > 4<<10 || align_offset == ~0UL) {
4230     n_user_data_bytes -= sizeof(unsigned);
4231     assert(align_offset == 0);
4232     rv = internal_memalign(ms, (size_t)align, n_user_data_bytes);
4233
4234     /* Trace the allocation */
4235     if (rv && use_trace(ms)) {
4236       mchunkptr p  = mem2chunk(rv);
4237       size_t psize = chunksize(p);
4238       mheap_get_trace ((unsigned long)rv, psize);
4239     }
4240     return rv;
4241   }
4242
4243   align = clib_max (align, MALLOC_ALIGNMENT);
4244   align = max_pow2 (align);
4245
4246   /* Correct align offset to be smaller than alignment. */
4247   align_offset &= (align - 1);
4248
4249   n_user_data_bytes += align;
4250   rv = mspace_malloc (msp, n_user_data_bytes);
4251
4252   if (rv == 0)
4253       return rv;
4254
4255   /* Honor the alignment request */
4256   searchp = (unsigned long)(rv + sizeof (unsigned));
4257
4258 #if 0  /* this is the idea... */
4259   while ((searchp + align_offset) % align)
4260     searchp++;
4261 #endif
4262
4263   {
4264     unsigned long where_now, delta;
4265
4266     where_now = (searchp + align_offset) % align;
4267     delta = align - where_now;
4268
4269     searchp += delta;
4270   }
4271
4272   wwp = (unsigned *)(searchp - sizeof(unsigned));
4273   *wwp = (searchp - (((unsigned long) rv) + sizeof (*wwp)));
4274   assert (*wwp < align);
4275
4276   if (use_trace(ms)) {
4277     mchunkptr p  = mem2chunk(rv);
4278     size_t psize = chunksize(p);
4279     mheap_get_trace (searchp, psize);
4280   }
4281   return (void *) searchp;
4282 }
4283
4284 CLIB_NOSANITIZE_ADDR
4285 void mspace_put (mspace msp, void *p_arg)
4286 {
4287   char *object_header;
4288   unsigned *wwp;
4289   mstate ms = (mstate)msp;
4290
4291   /* Find the object header delta */
4292   wwp = (unsigned *)p_arg;
4293   wwp --;
4294
4295   /* Recover the dlmalloc object pointer */
4296   object_header = (char *)wwp;
4297   object_header -= *wwp;
4298
4299   /* Tracing (if enabled) */
4300   if (use_trace(ms))
4301     {
4302       mchunkptr p  = mem2chunk(object_header);
4303       size_t psize = chunksize(p);
4304
4305       mheap_put_trace ((unsigned long)p_arg, psize);
4306     }
4307
4308 #if CLIB_DEBUG > 0 && !defined(CLIB_SANITIZE_ADDR)
4309   /* Poison the object */
4310   {
4311     size_t psize = mspace_usable_size (object_header);
4312     memset (object_header, 0x13, psize);
4313   }
4314 #endif
4315
4316   /* And free it... */
4317   mspace_free (msp, object_header);
4318 }
4319
4320 void mspace_put_no_offset (mspace msp, void *p_arg)
4321 {
4322   mstate ms = (mstate)msp;
4323
4324   if (use_trace(ms))
4325     {
4326       mchunkptr p  = mem2chunk(p_arg);
4327       size_t psize = chunksize(p);
4328
4329       mheap_put_trace ((unsigned long)p_arg, psize);
4330     }
4331   mspace_free (msp, p_arg);
4332 }
4333
4334 CLIB_NOSANITIZE_ADDR
4335 size_t mspace_usable_size_with_delta (const void *p)
4336 {
4337   size_t usable_size;
4338   char *object_header;
4339   unsigned *wwp;
4340
4341   /* Find the object header delta */
4342   wwp = (unsigned *)p;
4343   wwp --;
4344
4345   /* Recover the dlmalloc object pointer */
4346   object_header = (char *)wwp;
4347   object_header -= *wwp;
4348
4349   usable_size = mspace_usable_size (object_header);
4350   /* account for the offset and the size of the offset... */
4351   usable_size -= (*wwp + sizeof (*wwp));
4352   return usable_size;
4353 }
4354
4355 /*
4356   mspace versions of routines are near-clones of the global
4357   versions. This is not so nice but better than the alternatives.
4358 */
4359
4360 CLIB_NOSANITIZE_ADDR
4361 void* mspace_malloc(mspace msp, size_t bytes) {
4362   mstate ms = (mstate)msp;
4363   if (!ok_magic(ms)) {
4364     USAGE_ERROR_ACTION(ms,ms);
4365     return 0;
4366   }
4367   if (!PREACTION(ms)) {
4368     void* mem;
4369     size_t nb;
4370     if (bytes <= MAX_SMALL_REQUEST) {
4371       bindex_t idx;
4372       binmap_t smallbits;
4373       nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4374       idx = small_index(nb);
4375       smallbits = ms->smallmap >> idx;
4376
4377       if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4378         mchunkptr b, p;
4379         idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4380         b = smallbin_at(ms, idx);
4381         p = b->fd;
4382         assert(chunksize(p) == small_index2size(idx));
4383         unlink_first_small_chunk(ms, b, p, idx);
4384         set_inuse_and_pinuse(ms, p, small_index2size(idx));
4385         mem = chunk2mem(p);
4386         check_malloced_chunk(ms, mem, nb);
4387         goto postaction;
4388       }
4389
4390       else if (nb > ms->dvsize) {
4391         if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4392           mchunkptr b, p, r;
4393           size_t rsize;
4394           bindex_t i;
4395           binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4396           binmap_t leastbit = least_bit(leftbits);
4397           compute_bit2idx(leastbit, i);
4398           b = smallbin_at(ms, i);
4399           p = b->fd;
4400           assert(chunksize(p) == small_index2size(i));
4401           unlink_first_small_chunk(ms, b, p, i);
4402           rsize = small_index2size(i) - nb;
4403           /* Fit here cannot be remainderless if 4byte sizes */
4404           if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4405             set_inuse_and_pinuse(ms, p, small_index2size(i));
4406           else {
4407             set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4408             r = chunk_plus_offset(p, nb);
4409             set_size_and_pinuse_of_free_chunk(r, rsize);
4410             replace_dv(ms, r, rsize);
4411           }
4412           mem = chunk2mem(p);
4413           check_malloced_chunk(ms, mem, nb);
4414           goto postaction;
4415         }
4416
4417         else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
4418           check_malloced_chunk(ms, mem, nb);
4419           goto postaction;
4420         }
4421       }
4422     }
4423     else if (bytes >= MAX_REQUEST)
4424       nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
4425     else {
4426       nb = pad_request(bytes);
4427       if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
4428         check_malloced_chunk(ms, mem, nb);
4429         goto postaction;
4430       }
4431     }
4432
4433     if (nb <= ms->dvsize) {
4434       size_t rsize = ms->dvsize - nb;
4435       mchunkptr p = ms->dv;
4436       if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4437         mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
4438         ms->dvsize = rsize;
4439         set_size_and_pinuse_of_free_chunk(r, rsize);
4440         set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4441       }
4442       else { /* exhaust dv */
4443         size_t dvs = ms->dvsize;
4444         ms->dvsize = 0;
4445         ms->dv = 0;
4446         set_inuse_and_pinuse(ms, p, dvs);
4447       }
4448       mem = chunk2mem(p);
4449       check_malloced_chunk(ms, mem, nb);
4450       goto postaction;
4451     }
4452
4453     else if (nb < ms->topsize) { /* Split top */
4454       size_t rsize = ms->topsize -= nb;
4455       mchunkptr p = ms->top;
4456       mchunkptr r = ms->top = chunk_plus_offset(p, nb);
4457       r->head = rsize | PINUSE_BIT;
4458       set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4459       mem = chunk2mem(p);
4460       check_top_chunk(ms, ms->top);
4461       check_malloced_chunk(ms, mem, nb);
4462       goto postaction;
4463     }
4464
4465     mem = sys_alloc(ms, nb);
4466
4467   postaction:
4468     POSTACTION(ms);
4469     return mem;
4470   }
4471
4472   return 0;
4473 }
4474
4475 CLIB_NOSANITIZE_ADDR
4476 void mspace_free(mspace msp, void* mem) {
4477   if (mem != 0) {
4478     mchunkptr p  = mem2chunk(mem);
4479 #if FOOTERS
4480     mstate fm = get_mstate_for(p);
4481     (void)msp; /* placate people compiling -Wunused */
4482 #else /* FOOTERS */
4483     mstate fm = (mstate)msp;
4484 #endif /* FOOTERS */
4485     if (!ok_magic(fm)) {
4486       USAGE_ERROR_ACTION(fm, p);
4487       return;
4488     }
4489     if (!PREACTION(fm)) {
4490       check_inuse_chunk(fm, p);
4491       if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
4492         size_t psize = chunksize(p);
4493         mchunkptr next = chunk_plus_offset(p, psize);
4494         if (!pinuse(p)) {
4495           size_t prevsize = p->prev_foot;
4496           if (is_mmapped(p)) {
4497             psize += prevsize + MMAP_FOOT_PAD;
4498             if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4499               fm->footprint -= psize;
4500             goto postaction;
4501           }
4502           else {
4503             mchunkptr prev = chunk_minus_offset(p, prevsize);
4504             psize += prevsize;
4505             p = prev;
4506             if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4507               if (p != fm->dv) {
4508                 unlink_chunk(fm, p, prevsize);
4509               }
4510               else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4511                 fm->dvsize = psize;
4512                 set_free_with_pinuse(p, psize, next);
4513                 goto postaction;
4514               }
4515             }
4516             else
4517               goto erroraction;
4518           }
4519         }
4520
4521         if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4522           if (!cinuse(next)) {  /* consolidate forward */
4523             if (next == fm->top) {
4524               size_t tsize = fm->topsize += psize;
4525               fm->top = p;
4526               p->head = tsize | PINUSE_BIT;
4527               if (p == fm->dv) {
4528                 fm->dv = 0;
4529                 fm->dvsize = 0;
4530               }
4531               if (should_trim(fm, tsize))
4532                 sys_trim(fm, 0);
4533               goto postaction;
4534             }
4535             else if (next == fm->dv) {
4536               size_t dsize = fm->dvsize += psize;
4537               fm->dv = p;
4538               set_size_and_pinuse_of_free_chunk(p, dsize);
4539               goto postaction;
4540             }
4541             else {
4542               size_t nsize = chunksize(next);
4543               psize += nsize;
4544               unlink_chunk(fm, next, nsize);
4545               set_size_and_pinuse_of_free_chunk(p, psize);
4546               if (p == fm->dv) {
4547                 fm->dvsize = psize;
4548                 goto postaction;
4549               }
4550             }
4551           }
4552           else
4553             set_free_with_pinuse(p, psize, next);
4554
4555           if (is_small(psize)) {
4556             insert_small_chunk(fm, p, psize);
4557             check_free_chunk(fm, p);
4558           }
4559           else {
4560             tchunkptr tp = (tchunkptr)p;
4561             insert_large_chunk(fm, tp, psize);
4562             check_free_chunk(fm, p);
4563             if (--fm->release_checks == 0)
4564               release_unused_segments(fm);
4565           }
4566           goto postaction;
4567         }
4568       }
4569     erroraction:
4570       USAGE_ERROR_ACTION(fm, p);
4571     postaction:
4572       POSTACTION(fm);
4573     }
4574   }
4575 }
4576
4577 void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
4578   void* mem;
4579   size_t req = 0;
4580   mstate ms = (mstate)msp;
4581   if (!ok_magic(ms)) {
4582     USAGE_ERROR_ACTION(ms,ms);
4583     return 0;
4584   }
4585   if (n_elements != 0) {
4586     req = n_elements * elem_size;
4587     if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4588         (req / n_elements != elem_size))
4589       req = MAX_SIZE_T; /* force downstream failure on overflow */
4590   }
4591   mem = internal_malloc(ms, req);
4592   if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4593     memset(mem, 0, req);
4594   return mem;
4595 }
4596
4597 void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
4598   void* mem = 0;
4599   if (oldmem == 0) {
4600     mem = mspace_malloc(msp, bytes);
4601   }
4602   else if (bytes >= MAX_REQUEST) {
4603     MALLOC_FAILURE_ACTION;
4604   }
4605 #ifdef REALLOC_ZERO_BYTES_FREES
4606   else if (bytes == 0) {
4607     mspace_free(msp, oldmem);
4608   }
4609 #endif /* REALLOC_ZERO_BYTES_FREES */
4610   else {
4611     size_t nb = request2size(bytes);
4612     mchunkptr oldp = mem2chunk(oldmem);
4613 #if ! FOOTERS
4614     mstate m = (mstate)msp;
4615 #else /* FOOTERS */
4616     mstate m = get_mstate_for(oldp);
4617     if (!ok_magic(m)) {
4618       USAGE_ERROR_ACTION(m, oldmem);
4619       return 0;
4620     }
4621 #endif /* FOOTERS */
4622     if (!PREACTION(m)) {
4623       mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1);
4624       POSTACTION(m);
4625       if (newp != 0) {
4626         check_inuse_chunk(m, newp);
4627         mem = chunk2mem(newp);
4628       }
4629       else {
4630         mem = mspace_malloc(m, bytes);
4631         if (mem != 0) {
4632           size_t oc = chunksize(oldp) - overhead_for(oldp);
4633           memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
4634           mspace_free(m, oldmem);
4635         }
4636       }
4637     }
4638   }
4639   return mem;
4640 }
4641
4642 void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) {
4643   void* mem = 0;
4644   if (oldmem != 0) {
4645     if (bytes >= MAX_REQUEST) {
4646       MALLOC_FAILURE_ACTION;
4647     }
4648     else {
4649       size_t nb = request2size(bytes);
4650       mchunkptr oldp = mem2chunk(oldmem);
4651 #if ! FOOTERS
4652       mstate m = (mstate)msp;
4653 #else /* FOOTERS */
4654       mstate m = get_mstate_for(oldp);
4655       (void)msp; /* placate people compiling -Wunused */
4656       if (!ok_magic(m)) {
4657         USAGE_ERROR_ACTION(m, oldmem);
4658         return 0;
4659       }
4660 #endif /* FOOTERS */
4661       if (!PREACTION(m)) {
4662         mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0);
4663         POSTACTION(m);
4664         if (newp == oldp) {
4665           check_inuse_chunk(m, newp);
4666           mem = oldmem;
4667         }
4668       }
4669     }
4670   }
4671   return mem;
4672 }
4673
4674 void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
4675   mstate ms = (mstate)msp;
4676   if (!ok_magic(ms)) {
4677     USAGE_ERROR_ACTION(ms,ms);
4678     return 0;
4679   }
4680   if (alignment <= MALLOC_ALIGNMENT)
4681     return mspace_malloc(msp, bytes);
4682   return internal_memalign(ms, alignment, bytes);
4683 }
4684
4685 void** mspace_independent_calloc(mspace msp, size_t n_elements,
4686                                  size_t elem_size, void* chunks[]) {
4687   size_t sz = elem_size; /* serves as 1-element array */
4688   mstate ms = (mstate)msp;
4689   if (!ok_magic(ms)) {
4690     USAGE_ERROR_ACTION(ms,ms);
4691     return 0;
4692   }
4693   return ialloc(ms, n_elements, &sz, 3, chunks);
4694 }
4695
4696 void** mspace_independent_comalloc(mspace msp, size_t n_elements,
4697                                    size_t sizes[], void* chunks[]) {
4698   mstate ms = (mstate)msp;
4699   if (!ok_magic(ms)) {
4700     USAGE_ERROR_ACTION(ms,ms);
4701     return 0;
4702   }
4703   return ialloc(ms, n_elements, sizes, 0, chunks);
4704 }
4705
4706 size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) {
4707   return internal_bulk_free((mstate)msp, array, nelem);
4708 }
4709
4710 #if MALLOC_INSPECT_ALL
4711 void mspace_inspect_all(mspace msp,
4712                         void(*handler)(void *start,
4713                                        void *end,
4714                                        size_t used_bytes,
4715                                        void* callback_arg),
4716                         void* arg) {
4717   mstate ms = (mstate)msp;
4718   if (ok_magic(ms)) {
4719     if (!PREACTION(ms)) {
4720       internal_inspect_all(ms, handler, arg);
4721       POSTACTION(ms);
4722     }
4723   }
4724   else {
4725     USAGE_ERROR_ACTION(ms,ms);
4726   }
4727 }
4728 #endif /* MALLOC_INSPECT_ALL */
4729
4730 int mspace_trim(mspace msp, size_t pad) {
4731   int result = 0;
4732   mstate ms = (mstate)msp;
4733   if (ok_magic(ms)) {
4734     if (!PREACTION(ms)) {
4735       result = sys_trim(ms, pad);
4736       POSTACTION(ms);
4737     }
4738   }
4739   else {
4740     USAGE_ERROR_ACTION(ms,ms);
4741   }
4742   return result;
4743 }
4744
4745 #if !NO_MALLOC_STATS
4746 void mspace_malloc_stats(mspace msp) {
4747   mstate ms = (mstate)msp;
4748   if (ok_magic(ms)) {
4749     internal_malloc_stats(ms);
4750   }
4751   else {
4752     USAGE_ERROR_ACTION(ms,ms);
4753   }
4754 }
4755 #endif /* NO_MALLOC_STATS */
4756
4757 size_t mspace_footprint(mspace msp) {
4758   size_t result = 0;
4759   mstate ms = (mstate)msp;
4760   if (ok_magic(ms)) {
4761     result = ms->footprint;
4762   }
4763   else {
4764     USAGE_ERROR_ACTION(ms,ms);
4765   }
4766   return result;
4767 }
4768
4769 size_t mspace_max_footprint(mspace msp) {
4770   size_t result = 0;
4771   mstate ms = (mstate)msp;
4772   if (ok_magic(ms)) {
4773     result = ms->max_footprint;
4774   }
4775   else {
4776     USAGE_ERROR_ACTION(ms,ms);
4777   }
4778   return result;
4779 }
4780
4781 size_t mspace_footprint_limit(mspace msp) {
4782   size_t result = 0;
4783   mstate ms = (mstate)msp;
4784   if (ok_magic(ms)) {
4785     size_t maf = ms->footprint_limit;
4786     result = (maf == 0) ? MAX_SIZE_T : maf;
4787   }
4788   else {
4789     USAGE_ERROR_ACTION(ms,ms);
4790   }
4791   return result;
4792 }
4793
4794 size_t mspace_set_footprint_limit(mspace msp, size_t bytes) {
4795   size_t result = 0;
4796   mstate ms = (mstate)msp;
4797   if (ok_magic(ms)) {
4798     if (bytes == 0)
4799       result = granularity_align(1); /* Use minimal size */
4800     if (bytes == MAX_SIZE_T)
4801       result = 0;                    /* disable */
4802     else
4803       result = granularity_align(bytes);
4804     ms->footprint_limit = result;
4805   }
4806   else {
4807     USAGE_ERROR_ACTION(ms,ms);
4808   }
4809   return result;
4810 }
4811
4812 #if !NO_MALLINFO
4813 CLIB_NOSANITIZE_ADDR
4814 struct dlmallinfo mspace_mallinfo(mspace msp) {
4815   mstate ms = (mstate)msp;
4816   if (!ok_magic(ms)) {
4817     USAGE_ERROR_ACTION(ms,ms);
4818   }
4819   return internal_mallinfo(ms);
4820 }
4821 #endif /* NO_MALLINFO */
4822
4823 CLIB_NOSANITIZE_ADDR
4824 size_t mspace_usable_size(const void* mem) {
4825   if (mem != 0) {
4826     mchunkptr p = mem2chunk(mem);
4827     if (is_inuse(p))
4828       return chunksize(p) - overhead_for(p);
4829   }
4830   return 0;
4831 }
4832
4833 int mspace_mallopt(int param_number, int value) {
4834   return change_mparam(param_number, value);
4835 }
4836
4837 #endif /* MSPACES */
4838
4839
4840 /* -------------------- Alternative MORECORE functions ------------------- */
4841
4842 /*
4843   Guidelines for creating a custom version of MORECORE:
4844
4845   * For best performance, MORECORE should allocate in multiples of pagesize.
4846   * MORECORE may allocate more memory than requested. (Or even less,
4847       but this will usually result in a malloc failure.)
4848   * MORECORE must not allocate memory when given argument zero, but
4849       instead return one past the end address of memory from previous
4850       nonzero call.
4851   * For best performance, consecutive calls to MORECORE with positive
4852       arguments should return increasing addresses, indicating that
4853       space has been contiguously extended.
4854   * Even though consecutive calls to MORECORE need not return contiguous
4855       addresses, it must be OK for malloc'ed chunks to span multiple
4856       regions in those cases where they do happen to be contiguous.
4857   * MORECORE need not handle negative arguments -- it may instead
4858       just return MFAIL when given negative arguments.
4859       Negative arguments are always multiples of pagesize. MORECORE
4860       must not misinterpret negative args as large positive unsigned
4861       args. You can suppress all such calls from even occurring by defining
4862       MORECORE_CANNOT_TRIM,
4863
4864   As an example alternative MORECORE, here is a custom allocator
4865   kindly contributed for pre-OSX macOS.  It uses virtually but not
4866   necessarily physically contiguous non-paged memory (locked in,
4867   present and won't get swapped out).  You can use it by uncommenting
4868   this section, adding some #includes, and setting up the appropriate
4869   defines above:
4870
4871       #define MORECORE osMoreCore
4872
4873   There is also a shutdown routine that should somehow be called for
4874   cleanup upon program exit.
4875
4876   #define MAX_POOL_ENTRIES 100
4877   #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
4878   static int next_os_pool;
4879   void *our_os_pools[MAX_POOL_ENTRIES];
4880
4881   void *osMoreCore(int size)
4882   {
4883     void *ptr = 0;
4884     static void *sbrk_top = 0;
4885
4886     if (size > 0)
4887     {
4888       if (size < MINIMUM_MORECORE_SIZE)
4889          size = MINIMUM_MORECORE_SIZE;
4890       if (CurrentExecutionLevel() == kTaskLevel)
4891          ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
4892       if (ptr == 0)
4893       {
4894         return (void *) MFAIL;
4895       }
4896       // save ptrs so they can be freed during cleanup
4897       our_os_pools[next_os_pool] = ptr;
4898       next_os_pool++;
4899       ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
4900       sbrk_top = (char *) ptr + size;
4901       return ptr;
4902     }
4903     else if (size < 0)
4904     {
4905       // we don't currently support shrink behavior
4906       return (void *) MFAIL;
4907     }
4908     else
4909     {
4910       return sbrk_top;
4911     }
4912   }
4913
4914   // cleanup any allocated memory pools
4915   // called as last thing before shutting down driver
4916
4917   void osCleanupMem(void)
4918   {
4919     void **ptr;
4920
4921     for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
4922       if (*ptr)
4923       {
4924          PoolDeallocate(*ptr);
4925          *ptr = 0;
4926       }
4927   }
4928
4929 */
4930
4931
4932 /* -----------------------------------------------------------------------
4933 History:
4934     v2.8.6 Wed Aug 29 06:57:58 2012  Doug Lea
4935       * fix bad comparison in dlposix_memalign
4936       * don't reuse adjusted asize in sys_alloc
4937       * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion
4938       * reduce compiler warnings -- thanks to all who reported/suggested these
4939
4940     v2.8.5 Sun May 22 10:26:02 2011  Doug Lea  (dl at gee)
4941       * Always perform unlink checks unless INSECURE
4942       * Add posix_memalign.
4943       * Improve realloc to expand in more cases; expose realloc_in_place.
4944         Thanks to Peter Buhr for the suggestion.
4945       * Add footprint_limit, inspect_all, bulk_free. Thanks
4946         to Barry Hayes and others for the suggestions.
4947       * Internal refactorings to avoid calls while holding locks
4948       * Use non-reentrant locks by default. Thanks to Roland McGrath
4949         for the suggestion.
4950       * Small fixes to mspace_destroy, reset_on_error.
4951       * Various configuration extensions/changes. Thanks
4952          to all who contributed these.
4953
4954     V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu)
4955       * Update Creative Commons URL
4956
4957     V2.8.4 Wed May 27 09:56:23 2009  Doug Lea  (dl at gee)
4958       * Use zeros instead of prev foot for is_mmapped
4959       * Add mspace_track_large_chunks; thanks to Jean Brouwers
4960       * Fix set_inuse in internal_realloc; thanks to Jean Brouwers
4961       * Fix insufficient sys_alloc padding when using 16byte alignment
4962       * Fix bad error check in mspace_footprint
4963       * Adaptations for ptmalloc; thanks to Wolfram Gloger.
4964       * Reentrant spin locks; thanks to Earl Chew and others
4965       * Win32 improvements; thanks to Niall Douglas and Earl Chew
4966       * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options
4967       * Extension hook in malloc_state
4968       * Various small adjustments to reduce warnings on some compilers
4969       * Various configuration extensions/changes for more platforms. Thanks
4970          to all who contributed these.
4971
4972     V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
4973       * Add max_footprint functions
4974       * Ensure all appropriate literals are size_t
4975       * Fix conditional compilation problem for some #define settings
4976       * Avoid concatenating segments with the one provided
4977         in create_mspace_with_base
4978       * Rename some variables to avoid compiler shadowing warnings
4979       * Use explicit lock initialization.
4980       * Better handling of sbrk interference.
4981       * Simplify and fix segment insertion, trimming and mspace_destroy
4982       * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
4983       * Thanks especially to Dennis Flanagan for help on these.
4984
4985     V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
4986       * Fix memalign brace error.
4987
4988     V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
4989       * Fix improper #endif nesting in C++
4990       * Add explicit casts needed for C++
4991
4992     V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
4993       * Use trees for large bins
4994       * Support mspaces
4995       * Use segments to unify sbrk-based and mmap-based system allocation,
4996         removing need for emulation on most platforms without sbrk.
4997       * Default safety checks
4998       * Optional footer checks. Thanks to William Robertson for the idea.
4999       * Internal code refactoring
5000       * Incorporate suggestions and platform-specific changes.
5001         Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
5002         Aaron Bachmann,  Emery Berger, and others.
5003       * Speed up non-fastbin processing enough to remove fastbins.
5004       * Remove useless cfree() to avoid conflicts with other apps.
5005       * Remove internal memcpy, memset. Compilers handle builtins better.
5006       * Remove some options that no one ever used and rename others.
5007
5008     V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
5009       * Fix malloc_state bitmap array misdeclaration
5010
5011     V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
5012       * Allow tuning of FIRST_SORTED_BIN_SIZE
5013       * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
5014       * Better detection and support for non-contiguousness of MORECORE.
5015         Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
5016       * Bypass most of malloc if no frees. Thanks To Emery Berger.
5017       * Fix freeing of old top non-contiguous chunk im sysmalloc.
5018       * Raised default trim and map thresholds to 256K.
5019       * Fix mmap-related #defines. Thanks to Lubos Lunak.
5020       * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
5021       * Branch-free bin calculation
5022       * Default trim and mmap thresholds now 256K.
5023
5024     V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
5025       * Introduce independent_comalloc and independent_calloc.
5026         Thanks to Michael Pachos for motivation and help.
5027       * Make optional .h file available
5028       * Allow > 2GB requests on 32bit systems.
5029       * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
5030         Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
5031         and Anonymous.
5032       * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
5033         helping test this.)
5034       * memalign: check alignment arg
5035       * realloc: don't try to shift chunks backwards, since this
5036         leads to  more fragmentation in some programs and doesn't
5037         seem to help in any others.
5038       * Collect all cases in malloc requiring system memory into sysmalloc
5039       * Use mmap as backup to sbrk
5040       * Place all internal state in malloc_state
5041       * Introduce fastbins (although similar to 2.5.1)
5042       * Many minor tunings and cosmetic improvements
5043       * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
5044       * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
5045         Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
5046       * Include errno.h to support default failure action.
5047
5048     V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
5049       * return null for negative arguments
5050       * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
5051          * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
5052           (e.g. WIN32 platforms)
5053          * Cleanup header file inclusion for WIN32 platforms
5054          * Cleanup code to avoid Microsoft Visual C++ compiler complaints
5055          * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
5056            memory allocation routines
5057          * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
5058          * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
5059            usage of 'assert' in non-WIN32 code
5060          * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
5061            avoid infinite loop
5062       * Always call 'fREe()' rather than 'free()'
5063
5064     V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
5065       * Fixed ordering problem with boundary-stamping
5066
5067     V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
5068       * Added pvalloc, as recommended by H.J. Liu
5069       * Added 64bit pointer support mainly from Wolfram Gloger
5070       * Added anonymously donated WIN32 sbrk emulation
5071       * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
5072       * malloc_extend_top: fix mask error that caused wastage after
5073         foreign sbrks
5074       * Add linux mremap support code from HJ Liu
5075
5076     V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
5077       * Integrated most documentation with the code.
5078       * Add support for mmap, with help from
5079         Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5080       * Use last_remainder in more cases.
5081       * Pack bins using idea from  colin@nyx10.cs.du.edu
5082       * Use ordered bins instead of best-fit threshold
5083       * Eliminate block-local decls to simplify tracing and debugging.
5084       * Support another case of realloc via move into top
5085       * Fix error occurring when initial sbrk_base not word-aligned.
5086       * Rely on page size for units instead of SBRK_UNIT to
5087         avoid surprises about sbrk alignment conventions.
5088       * Add mallinfo, mallopt. Thanks to Raymond Nijssen
5089         (raymond@es.ele.tue.nl) for the suggestion.
5090       * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
5091       * More precautions for cases where other routines call sbrk,
5092         courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5093       * Added macros etc., allowing use in linux libc from
5094         H.J. Lu (hjl@gnu.ai.mit.edu)
5095       * Inverted this history list
5096
5097     V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
5098       * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
5099       * Removed all preallocation code since under current scheme
5100         the work required to undo bad preallocations exceeds
5101         the work saved in good cases for most test programs.
5102       * No longer use return list or unconsolidated bins since
5103         no scheme using them consistently outperforms those that don't
5104         given above changes.
5105       * Use best fit for very large chunks to prevent some worst-cases.
5106       * Added some support for debugging
5107
5108     V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
5109       * Removed footers when chunks are in use. Thanks to
5110         Paul Wilson (wilson@cs.texas.edu) for the suggestion.
5111
5112     V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
5113       * Added malloc_trim, with help from Wolfram Gloger
5114         (wmglo@Dent.MED.Uni-Muenchen.DE).
5115
5116     V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
5117
5118     V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
5119       * realloc: try to expand in both directions
5120       * malloc: swap order of clean-bin strategy;
5121       * realloc: only conditionally expand backwards
5122       * Try not to scavenge used bins
5123       * Use bin counts as a guide to preallocation
5124       * Occasionally bin return list chunks in first scan
5125       * Add a few optimizations from colin@nyx10.cs.du.edu
5126
5127     V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
5128       * faster bin computation & slightly different binning
5129       * merged all consolidations to one part of malloc proper
5130          (eliminating old malloc_find_space & malloc_clean_bin)
5131       * Scan 2 returns chunks (not just 1)
5132       * Propagate failure in realloc if malloc returns 0
5133       * Add stuff to allow compilation on non-ANSI compilers
5134           from kpv@research.att.com
5135
5136     V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
5137       * removed potential for odd address access in prev_chunk
5138       * removed dependency on getpagesize.h
5139       * misc cosmetics and a bit more internal documentation
5140       * anticosmetics: mangled names in macros to evade debugger strangeness
5141       * tested on sparc, hp-700, dec-mips, rs6000
5142           with gcc & native cc (hp, dec only) allowing
5143           Detlefs & Zorn comparison study (in SIGPLAN Notices.)
5144
5145     Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
5146       * Based loosely on libg++-1.2X malloc. (It retains some of the overall
5147          structure of old version,  but most details differ.)
5148
5149 */