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