8acea8bc2bf3ba1d1f3b2a782b4e57ef0727e6f4
[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       /* Until memory modes commonly available, use volatile-write */
1769       (*(volatile size_t *)(&(mparams.magic))) = magic;
1770     }
1771   }
1772
1773   RELEASE_MALLOC_GLOBAL_LOCK();
1774   return 1;
1775 }
1776
1777 /* support for mallopt */
1778 static int change_mparam(int param_number, int value) {
1779   size_t val;
1780   ensure_initialization();
1781   val = (value == -1)? MAX_SIZE_T : (size_t)value;
1782   switch(param_number) {
1783   case M_TRIM_THRESHOLD:
1784     mparams.trim_threshold = val;
1785     return 1;
1786   case M_GRANULARITY:
1787     if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
1788       mparams.granularity = val;
1789       return 1;
1790     }
1791     else
1792       return 0;
1793   case M_MMAP_THRESHOLD:
1794     mparams.mmap_threshold = val;
1795     return 1;
1796   default:
1797     return 0;
1798   }
1799 }
1800
1801 #if DEBUG
1802 /* ------------------------- Debugging Support --------------------------- */
1803
1804 /* Check properties of any chunk, whether free, inuse, mmapped etc  */
1805 static void do_check_any_chunk(mstate m, mchunkptr p) {
1806   assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1807   assert(ok_address(m, p));
1808 }
1809
1810 /* Check properties of top chunk */
1811 static void do_check_top_chunk(mstate m, mchunkptr p) {
1812   msegmentptr sp = segment_holding(m, (char*)p);
1813   size_t  sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */
1814   assert(sp != 0);
1815   assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1816   assert(ok_address(m, p));
1817   assert(sz == m->topsize);
1818   assert(sz > 0);
1819   assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
1820   assert(pinuse(p));
1821   assert(!pinuse(chunk_plus_offset(p, sz)));
1822 }
1823
1824 /* Check properties of (inuse) mmapped chunks */
1825 static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
1826   size_t  sz = chunksize(p);
1827   size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD);
1828   assert(is_mmapped(p));
1829   assert(use_mmap(m));
1830   assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
1831   assert(ok_address(m, p));
1832   assert(!is_small(sz));
1833   assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
1834   assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
1835   assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
1836 }
1837
1838 /* Check properties of inuse chunks */
1839 static void do_check_inuse_chunk(mstate m, mchunkptr p) {
1840   do_check_any_chunk(m, p);
1841   assert(is_inuse(p));
1842   assert(next_pinuse(p));
1843   /* If not pinuse and not mmapped, previous chunk has OK offset */
1844   assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
1845   if (is_mmapped(p))
1846     do_check_mmapped_chunk(m, p);
1847 }
1848
1849 /* Check properties of free chunks */
1850 static void do_check_free_chunk(mstate m, mchunkptr p) {
1851   size_t sz = chunksize(p);
1852   mchunkptr next = chunk_plus_offset(p, sz);
1853   do_check_any_chunk(m, p);
1854   assert(!is_inuse(p));
1855   assert(!next_pinuse(p));
1856   assert (!is_mmapped(p));
1857   if (p != m->dv && p != m->top) {
1858     if (sz >= MIN_CHUNK_SIZE) {
1859       assert((sz & CHUNK_ALIGN_MASK) == 0);
1860       assert(is_aligned(chunk2mem(p)));
1861       assert(next->prev_foot == sz);
1862       assert(pinuse(p));
1863       assert (next == m->top || is_inuse(next));
1864       assert(p->fd->bk == p);
1865       assert(p->bk->fd == p);
1866     }
1867     else  /* markers are always of size SIZE_T_SIZE */
1868       assert(sz == SIZE_T_SIZE);
1869   }
1870 }
1871
1872 /* Check properties of malloced chunks at the point they are malloced */
1873 static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
1874   if (mem != 0) {
1875     mchunkptr p = mem2chunk(mem);
1876     size_t sz = p->head & ~INUSE_BITS;
1877     do_check_inuse_chunk(m, p);
1878     assert((sz & CHUNK_ALIGN_MASK) == 0);
1879     assert(sz >= MIN_CHUNK_SIZE);
1880     assert(sz >= s);
1881     /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
1882     assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
1883   }
1884 }
1885
1886 /* Check a tree and its subtrees.  */
1887 static void do_check_tree(mstate m, tchunkptr t) {
1888   tchunkptr head = 0;
1889   tchunkptr u = t;
1890   bindex_t tindex = t->index;
1891   size_t tsize = chunksize(t);
1892   bindex_t idx;
1893   compute_tree_index(tsize, idx);
1894   assert(tindex == idx);
1895   assert(tsize >= MIN_LARGE_SIZE);
1896   assert(tsize >= minsize_for_tree_index(idx));
1897   assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
1898
1899   do { /* traverse through chain of same-sized nodes */
1900     do_check_any_chunk(m, ((mchunkptr)u));
1901     assert(u->index == tindex);
1902     assert(chunksize(u) == tsize);
1903     assert(!is_inuse(u));
1904     assert(!next_pinuse(u));
1905     assert(u->fd->bk == u);
1906     assert(u->bk->fd == u);
1907     if (u->parent == 0) {
1908       assert(u->child[0] == 0);
1909       assert(u->child[1] == 0);
1910     }
1911     else {
1912       assert(head == 0); /* only one node on chain has parent */
1913       head = u;
1914       assert(u->parent != u);
1915       assert (u->parent->child[0] == u ||
1916               u->parent->child[1] == u ||
1917               *((tbinptr*)(u->parent)) == u);
1918       if (u->child[0] != 0) {
1919         assert(u->child[0]->parent == u);
1920         assert(u->child[0] != u);
1921         do_check_tree(m, u->child[0]);
1922       }
1923       if (u->child[1] != 0) {
1924         assert(u->child[1]->parent == u);
1925         assert(u->child[1] != u);
1926         do_check_tree(m, u->child[1]);
1927       }
1928       if (u->child[0] != 0 && u->child[1] != 0) {
1929         assert(chunksize(u->child[0]) < chunksize(u->child[1]));
1930       }
1931     }
1932     u = u->fd;
1933   } while (u != t);
1934   assert(head != 0);
1935 }
1936
1937 /*  Check all the chunks in a treebin.  */
1938 static void do_check_treebin(mstate m, bindex_t i) {
1939   tbinptr* tb = treebin_at(m, i);
1940   tchunkptr t = *tb;
1941   int empty = (m->treemap & (1U << i)) == 0;
1942   if (t == 0)
1943     assert(empty);
1944   if (!empty)
1945     do_check_tree(m, t);
1946 }
1947
1948 /*  Check all the chunks in a smallbin.  */
1949 static void do_check_smallbin(mstate m, bindex_t i) {
1950   sbinptr b = smallbin_at(m, i);
1951   mchunkptr p = b->bk;
1952   unsigned int empty = (m->smallmap & (1U << i)) == 0;
1953   if (p == b)
1954     assert(empty);
1955   if (!empty) {
1956     for (; p != b; p = p->bk) {
1957       size_t size = chunksize(p);
1958       mchunkptr q;
1959       /* each chunk claims to be free */
1960       do_check_free_chunk(m, p);
1961       /* chunk belongs in bin */
1962       assert(small_index(size) == i);
1963       assert(p->bk == b || chunksize(p->bk) == chunksize(p));
1964       /* chunk is followed by an inuse chunk */
1965       q = next_chunk(p);
1966       if (q->head != FENCEPOST_HEAD)
1967         do_check_inuse_chunk(m, q);
1968     }
1969   }
1970 }
1971
1972 /* Find x in a bin. Used in other check functions. */
1973 static int bin_find(mstate m, mchunkptr x) {
1974   size_t size = chunksize(x);
1975   if (is_small(size)) {
1976     bindex_t sidx = small_index(size);
1977     sbinptr b = smallbin_at(m, sidx);
1978     if (smallmap_is_marked(m, sidx)) {
1979       mchunkptr p = b;
1980       do {
1981         if (p == x)
1982           return 1;
1983       } while ((p = p->fd) != b);
1984     }
1985   }
1986   else {
1987     bindex_t tidx;
1988     compute_tree_index(size, tidx);
1989     if (treemap_is_marked(m, tidx)) {
1990       tchunkptr t = *treebin_at(m, tidx);
1991       size_t sizebits = size << leftshift_for_tree_index(tidx);
1992       while (t != 0 && chunksize(t) != size) {
1993         t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
1994         sizebits <<= 1;
1995       }
1996       if (t != 0) {
1997         tchunkptr u = t;
1998         do {
1999           if (u == (tchunkptr)x)
2000             return 1;
2001         } while ((u = u->fd) != t);
2002       }
2003     }
2004   }
2005   return 0;
2006 }
2007
2008 /* Traverse each chunk and check it; return total */
2009 static size_t traverse_and_check(mstate m) {
2010   size_t sum = 0;
2011   if (is_initialized(m)) {
2012     msegmentptr s = &m->seg;
2013     sum += m->topsize + TOP_FOOT_SIZE;
2014     while (s != 0) {
2015       mchunkptr q = align_as_chunk(s->base);
2016       mchunkptr lastq = 0;
2017       assert(pinuse(q));
2018       while (segment_holds(s, q) &&
2019              q != m->top && q->head != FENCEPOST_HEAD) {
2020         sum += chunksize(q);
2021         if (is_inuse(q)) {
2022           assert(!bin_find(m, q));
2023           do_check_inuse_chunk(m, q);
2024         }
2025         else {
2026           assert(q == m->dv || bin_find(m, q));
2027           assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */
2028           do_check_free_chunk(m, q);
2029         }
2030         lastq = q;
2031         q = next_chunk(q);
2032       }
2033       s = s->next;
2034     }
2035   }
2036   return sum;
2037 }
2038
2039
2040 /* Check all properties of malloc_state. */
2041 static void do_check_malloc_state(mstate m) {
2042   bindex_t i;
2043   size_t total;
2044   /* check bins */
2045   for (i = 0; i < NSMALLBINS; ++i)
2046     do_check_smallbin(m, i);
2047   for (i = 0; i < NTREEBINS; ++i)
2048     do_check_treebin(m, i);
2049
2050   if (m->dvsize != 0) { /* check dv chunk */
2051     do_check_any_chunk(m, m->dv);
2052     assert(m->dvsize == chunksize(m->dv));
2053     assert(m->dvsize >= MIN_CHUNK_SIZE);
2054     assert(bin_find(m, m->dv) == 0);
2055   }
2056
2057   if (m->top != 0) {   /* check top chunk */
2058     do_check_top_chunk(m, m->top);
2059     /*assert(m->topsize == chunksize(m->top)); redundant */
2060     assert(m->topsize > 0);
2061     assert(bin_find(m, m->top) == 0);
2062   }
2063
2064   total = traverse_and_check(m);
2065   assert(total <= m->footprint);
2066   assert(m->footprint <= m->max_footprint);
2067 }
2068 #endif /* DEBUG */
2069
2070 /* ----------------------------- statistics ------------------------------ */
2071
2072 #if !NO_MALLINFO
2073 static struct mallinfo internal_mallinfo(mstate m) {
2074   struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2075   ensure_initialization();
2076   if (!PREACTION(m)) {
2077     check_malloc_state(m);
2078     if (is_initialized(m)) {
2079       size_t nfree = SIZE_T_ONE; /* top always free */
2080       size_t mfree = m->topsize + TOP_FOOT_SIZE;
2081       size_t sum = mfree;
2082       msegmentptr s = &m->seg;
2083       while (s != 0) {
2084         mchunkptr q = align_as_chunk(s->base);
2085         while (segment_holds(s, q) &&
2086                q != m->top && q->head != FENCEPOST_HEAD) {
2087           size_t sz = chunksize(q);
2088           sum += sz;
2089           if (!is_inuse(q)) {
2090             mfree += sz;
2091             ++nfree;
2092           }
2093           q = next_chunk(q);
2094         }
2095         s = s->next;
2096       }
2097
2098       nm.arena    = sum;
2099       nm.ordblks  = nfree;
2100       nm.hblkhd   = m->footprint - sum;
2101       nm.usmblks  = m->max_footprint;
2102       nm.uordblks = m->footprint - mfree;
2103       nm.fordblks = mfree;
2104       nm.keepcost = m->topsize;
2105     }
2106
2107     POSTACTION(m);
2108   }
2109   return nm;
2110 }
2111 #endif /* !NO_MALLINFO */
2112
2113 #if !NO_MALLOC_STATS
2114 static void internal_malloc_stats(mstate m) {
2115   ensure_initialization();
2116   if (!PREACTION(m)) {
2117     size_t maxfp = 0;
2118     size_t fp = 0;
2119     size_t used = 0;
2120     check_malloc_state(m);
2121     if (is_initialized(m)) {
2122       msegmentptr s = &m->seg;
2123       maxfp = m->max_footprint;
2124       fp = m->footprint;
2125       used = fp - (m->topsize + TOP_FOOT_SIZE);
2126
2127       while (s != 0) {
2128         mchunkptr q = align_as_chunk(s->base);
2129         while (segment_holds(s, q) &&
2130                q != m->top && q->head != FENCEPOST_HEAD) {
2131           if (!is_inuse(q))
2132             used -= chunksize(q);
2133           q = next_chunk(q);
2134         }
2135         s = s->next;
2136       }
2137     }
2138     POSTACTION(m); /* drop lock */
2139     fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
2140     fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
2141     fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
2142   }
2143 }
2144 #endif /* NO_MALLOC_STATS */
2145
2146 /* ----------------------- Operations on smallbins ----------------------- */
2147
2148 /*
2149   Various forms of linking and unlinking are defined as macros.  Even
2150   the ones for trees, which are very long but have very short typical
2151   paths.  This is ugly but reduces reliance on inlining support of
2152   compilers.
2153 */
2154
2155 /* Link a free chunk into a smallbin  */
2156 #define insert_small_chunk(M, P, S) {\
2157   bindex_t I  = small_index(S);\
2158   mchunkptr B = smallbin_at(M, I);\
2159   mchunkptr F = B;\
2160   assert(S >= MIN_CHUNK_SIZE);\
2161   if (!smallmap_is_marked(M, I))\
2162     mark_smallmap(M, I);\
2163   else if (RTCHECK(ok_address(M, B->fd)))\
2164     F = B->fd;\
2165   else {\
2166     CORRUPTION_ERROR_ACTION(M);\
2167   }\
2168   B->fd = P;\
2169   F->bk = P;\
2170   P->fd = F;\
2171   P->bk = B;\
2172 }
2173
2174 /* Unlink a chunk from a smallbin  */
2175 #define unlink_small_chunk(M, P, S) {\
2176   mchunkptr F = P->fd;\
2177   mchunkptr B = P->bk;\
2178   bindex_t I = small_index(S);\
2179   assert(P != B);\
2180   assert(P != F);\
2181   assert(chunksize(P) == small_index2size(I));\
2182   if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \
2183     if (B == F) {\
2184       clear_smallmap(M, I);\
2185     }\
2186     else if (RTCHECK(B == smallbin_at(M,I) ||\
2187                      (ok_address(M, B) && B->fd == P))) {\
2188       F->bk = B;\
2189       B->fd = F;\
2190     }\
2191     else {\
2192       CORRUPTION_ERROR_ACTION(M);\
2193     }\
2194   }\
2195   else {\
2196     CORRUPTION_ERROR_ACTION(M);\
2197   }\
2198 }
2199
2200 /* Unlink the first chunk from a smallbin */
2201 #define unlink_first_small_chunk(M, B, P, I) {\
2202   mchunkptr F = P->fd;\
2203   assert(P != B);\
2204   assert(P != F);\
2205   assert(chunksize(P) == small_index2size(I));\
2206   if (B == F) {\
2207     clear_smallmap(M, I);\
2208   }\
2209   else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\
2210     F->bk = B;\
2211     B->fd = F;\
2212   }\
2213   else {\
2214     CORRUPTION_ERROR_ACTION(M);\
2215   }\
2216 }
2217
2218 /* Replace dv node, binning the old one */
2219 /* Used only when dvsize known to be small */
2220 #define replace_dv(M, P, S) {\
2221   size_t DVS = M->dvsize;\
2222   assert(is_small(DVS));\
2223   if (DVS != 0) {\
2224     mchunkptr DV = M->dv;\
2225     insert_small_chunk(M, DV, DVS);\
2226   }\
2227   M->dvsize = S;\
2228   M->dv = P;\
2229 }
2230
2231 /* ------------------------- Operations on trees ------------------------- */
2232
2233 /* Insert chunk into tree */
2234 #define insert_large_chunk(M, X, S) {\
2235   tbinptr* H;\
2236   bindex_t I;\
2237   compute_tree_index(S, I);\
2238   H = treebin_at(M, I);\
2239   X->index = I;\
2240   X->child[0] = X->child[1] = 0;\
2241   if (!treemap_is_marked(M, I)) {\
2242     mark_treemap(M, I);\
2243     *H = X;\
2244     X->parent = (tchunkptr)H;\
2245     X->fd = X->bk = X;\
2246   }\
2247   else {\
2248     tchunkptr T = *H;\
2249     size_t K = S << leftshift_for_tree_index(I);\
2250     for (;;) {\
2251       if (chunksize(T) != S) {\
2252         tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
2253         K <<= 1;\
2254         if (*C != 0)\
2255           T = *C;\
2256         else if (RTCHECK(ok_address(M, C))) {\
2257           *C = X;\
2258           X->parent = T;\
2259           X->fd = X->bk = X;\
2260           break;\
2261         }\
2262         else {\
2263           CORRUPTION_ERROR_ACTION(M);\
2264           break;\
2265         }\
2266       }\
2267       else {\
2268         tchunkptr F = T->fd;\
2269         if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
2270           T->fd = F->bk = X;\
2271           X->fd = F;\
2272           X->bk = T;\
2273           X->parent = 0;\
2274           break;\
2275         }\
2276         else {\
2277           CORRUPTION_ERROR_ACTION(M);\
2278           break;\
2279         }\
2280       }\
2281     }\
2282   }\
2283 }
2284
2285 /*
2286   Unlink steps:
2287
2288   1. If x is a chained node, unlink it from its same-sized fd/bk links
2289      and choose its bk node as its replacement.
2290   2. If x was the last node of its size, but not a leaf node, it must
2291      be replaced with a leaf node (not merely one with an open left or
2292      right), to make sure that lefts and rights of descendents
2293      correspond properly to bit masks.  We use the rightmost descendent
2294      of x.  We could use any other leaf, but this is easy to locate and
2295      tends to counteract removal of leftmosts elsewhere, and so keeps
2296      paths shorter than minimally guaranteed.  This doesn't loop much
2297      because on average a node in a tree is near the bottom.
2298   3. If x is the base of a chain (i.e., has parent links) relink
2299      x's parent and children to x's replacement (or null if none).
2300 */
2301
2302 #define unlink_large_chunk(M, X) {\
2303   tchunkptr XP = X->parent;\
2304   tchunkptr R;\
2305   if (X->bk != X) {\
2306     tchunkptr F = X->fd;\
2307     R = X->bk;\
2308     if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\
2309       F->bk = R;\
2310       R->fd = F;\
2311     }\
2312     else {\
2313       CORRUPTION_ERROR_ACTION(M);\
2314     }\
2315   }\
2316   else {\
2317     tchunkptr* RP;\
2318     if (((R = *(RP = &(X->child[1]))) != 0) ||\
2319         ((R = *(RP = &(X->child[0]))) != 0)) {\
2320       tchunkptr* CP;\
2321       while ((*(CP = &(R->child[1])) != 0) ||\
2322              (*(CP = &(R->child[0])) != 0)) {\
2323         R = *(RP = CP);\
2324       }\
2325       if (RTCHECK(ok_address(M, RP)))\
2326         *RP = 0;\
2327       else {\
2328         CORRUPTION_ERROR_ACTION(M);\
2329       }\
2330     }\
2331   }\
2332   if (XP != 0) {\
2333     tbinptr* H = treebin_at(M, X->index);\
2334     if (X == *H) {\
2335       if ((*H = R) == 0) \
2336         clear_treemap(M, X->index);\
2337     }\
2338     else if (RTCHECK(ok_address(M, XP))) {\
2339       if (XP->child[0] == X) \
2340         XP->child[0] = R;\
2341       else \
2342         XP->child[1] = R;\
2343     }\
2344     else\
2345       CORRUPTION_ERROR_ACTION(M);\
2346     if (R != 0) {\
2347       if (RTCHECK(ok_address(M, R))) {\
2348         tchunkptr C0, C1;\
2349         R->parent = XP;\
2350         if ((C0 = X->child[0]) != 0) {\
2351           if (RTCHECK(ok_address(M, C0))) {\
2352             R->child[0] = C0;\
2353             C0->parent = R;\
2354           }\
2355           else\
2356             CORRUPTION_ERROR_ACTION(M);\
2357         }\
2358         if ((C1 = X->child[1]) != 0) {\
2359           if (RTCHECK(ok_address(M, C1))) {\
2360             R->child[1] = C1;\
2361             C1->parent = R;\
2362           }\
2363           else\
2364             CORRUPTION_ERROR_ACTION(M);\
2365         }\
2366       }\
2367       else\
2368         CORRUPTION_ERROR_ACTION(M);\
2369     }\
2370   }\
2371 }
2372
2373 /* Relays to large vs small bin operations */
2374
2375 #define insert_chunk(M, P, S)\
2376   if (is_small(S)) insert_small_chunk(M, P, S)\
2377   else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
2378
2379 #define unlink_chunk(M, P, S)\
2380   if (is_small(S)) unlink_small_chunk(M, P, S)\
2381   else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
2382
2383
2384 /* Relays to internal calls to malloc/free from realloc, memalign etc */
2385
2386 #if ONLY_MSPACES
2387 #define internal_malloc(m, b) mspace_malloc(m, b)
2388 #define internal_free(m, mem) mspace_free(m,mem);
2389 #else /* ONLY_MSPACES */
2390 #if MSPACES
2391 #define internal_malloc(m, b)\
2392   ((m == gm)? dlmalloc(b) : mspace_malloc(m, b))
2393 #define internal_free(m, mem)\
2394    if (m == gm) dlfree(mem); else mspace_free(m,mem);
2395 #else /* MSPACES */
2396 #define internal_malloc(m, b) dlmalloc(b)
2397 #define internal_free(m, mem) dlfree(mem)
2398 #endif /* MSPACES */
2399 #endif /* ONLY_MSPACES */
2400
2401 /* -----------------------  Direct-mmapping chunks ----------------------- */
2402
2403 /*
2404   Directly mmapped chunks are set up with an offset to the start of
2405   the mmapped region stored in the prev_foot field of the chunk. This
2406   allows reconstruction of the required argument to MUNMAP when freed,
2407   and also allows adjustment of the returned chunk to meet alignment
2408   requirements (especially in memalign).
2409 */
2410
2411 /* Malloc using mmap */
2412 static void* mmap_alloc(mstate m, size_t nb) {
2413   size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2414   if (m->footprint_limit != 0) {
2415     size_t fp = m->footprint + mmsize;
2416     if (fp <= m->footprint || fp > m->footprint_limit)
2417       return 0;
2418   }
2419   if (mmsize > nb) {     /* Check for wrap around 0 */
2420     char* mm = (char*)(CALL_DIRECT_MMAP(mmsize));
2421     if (mm != CMFAIL) {
2422       size_t offset = align_offset(chunk2mem(mm));
2423       size_t psize = mmsize - offset - MMAP_FOOT_PAD;
2424       mchunkptr p = (mchunkptr)(mm + offset);
2425       p->prev_foot = offset;
2426       p->head = psize;
2427       mark_inuse_foot(m, p, psize);
2428       chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
2429       chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
2430
2431       if (m->least_addr == 0 || mm < m->least_addr)
2432         m->least_addr = mm;
2433       if ((m->footprint += mmsize) > m->max_footprint)
2434         m->max_footprint = m->footprint;
2435       assert(is_aligned(chunk2mem(p)));
2436       check_mmapped_chunk(m, p);
2437       return chunk2mem(p);
2438     }
2439   }
2440   return 0;
2441 }
2442
2443 /* Realloc using mmap */
2444 static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) {
2445   size_t oldsize = chunksize(oldp);
2446   (void)flags; /* placate people compiling -Wunused */
2447   if (is_small(nb)) /* Can't shrink mmap regions below small size */
2448     return 0;
2449   /* Keep old chunk if big enough but not too big */
2450   if (oldsize >= nb + SIZE_T_SIZE &&
2451       (oldsize - nb) <= (mparams.granularity << 1))
2452     return oldp;
2453   else {
2454     size_t offset = oldp->prev_foot;
2455     size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
2456     size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2457     char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
2458                                   oldmmsize, newmmsize, flags);
2459     if (cp != CMFAIL) {
2460       mchunkptr newp = (mchunkptr)(cp + offset);
2461       size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
2462       newp->head = psize;
2463       mark_inuse_foot(m, newp, psize);
2464       chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
2465       chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
2466
2467       if (cp < m->least_addr)
2468         m->least_addr = cp;
2469       if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
2470         m->max_footprint = m->footprint;
2471       check_mmapped_chunk(m, newp);
2472       return newp;
2473     }
2474   }
2475   return 0;
2476 }
2477
2478
2479 /* -------------------------- mspace management -------------------------- */
2480
2481 /* Initialize top chunk and its size */
2482 static void init_top(mstate m, mchunkptr p, size_t psize) {
2483   /* Ensure alignment */
2484   size_t offset = align_offset(chunk2mem(p));
2485   p = (mchunkptr)((char*)p + offset);
2486   psize -= offset;
2487
2488   m->top = p;
2489   m->topsize = psize;
2490   p->head = psize | PINUSE_BIT;
2491   /* set size of fake trailing chunk holding overhead space only once */
2492   chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
2493   m->trim_check = mparams.trim_threshold; /* reset on each update */
2494 }
2495
2496 /* Initialize bins for a new mstate that is otherwise zeroed out */
2497 static void init_bins(mstate m) {
2498   /* Establish circular links for smallbins */
2499   bindex_t i;
2500   for (i = 0; i < NSMALLBINS; ++i) {
2501     sbinptr bin = smallbin_at(m,i);
2502     bin->fd = bin->bk = bin;
2503   }
2504 }
2505
2506 #if PROCEED_ON_ERROR
2507
2508 /* default corruption action */
2509 static void reset_on_error(mstate m) {
2510   int i;
2511   ++malloc_corruption_error_count;
2512   /* Reinitialize fields to forget about all memory */
2513   m->smallmap = m->treemap = 0;
2514   m->dvsize = m->topsize = 0;
2515   m->seg.base = 0;
2516   m->seg.size = 0;
2517   m->seg.next = 0;
2518   m->top = m->dv = 0;
2519   for (i = 0; i < NTREEBINS; ++i)
2520     *treebin_at(m, i) = 0;
2521   init_bins(m);
2522 }
2523 #endif /* PROCEED_ON_ERROR */
2524
2525 /* Allocate chunk and prepend remainder with chunk in successor base. */
2526 static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
2527                            size_t nb) {
2528   mchunkptr p = align_as_chunk(newbase);
2529   mchunkptr oldfirst = align_as_chunk(oldbase);
2530   size_t psize = (char*)oldfirst - (char*)p;
2531   mchunkptr q = chunk_plus_offset(p, nb);
2532   size_t qsize = psize - nb;
2533   set_size_and_pinuse_of_inuse_chunk(m, p, nb);
2534
2535   assert((char*)oldfirst > (char*)q);
2536   assert(pinuse(oldfirst));
2537   assert(qsize >= MIN_CHUNK_SIZE);
2538
2539   /* consolidate remainder with first chunk of old base */
2540   if (oldfirst == m->top) {
2541     size_t tsize = m->topsize += qsize;
2542     m->top = q;
2543     q->head = tsize | PINUSE_BIT;
2544     check_top_chunk(m, q);
2545   }
2546   else if (oldfirst == m->dv) {
2547     size_t dsize = m->dvsize += qsize;
2548     m->dv = q;
2549     set_size_and_pinuse_of_free_chunk(q, dsize);
2550   }
2551   else {
2552     if (!is_inuse(oldfirst)) {
2553       size_t nsize = chunksize(oldfirst);
2554       unlink_chunk(m, oldfirst, nsize);
2555       oldfirst = chunk_plus_offset(oldfirst, nsize);
2556       qsize += nsize;
2557     }
2558     set_free_with_pinuse(q, qsize, oldfirst);
2559     insert_chunk(m, q, qsize);
2560     check_free_chunk(m, q);
2561   }
2562
2563   check_malloced_chunk(m, chunk2mem(p), nb);
2564   return chunk2mem(p);
2565 }
2566
2567 /* Add a segment to hold a new noncontiguous region */
2568 static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
2569   /* Determine locations and sizes of segment, fenceposts, old top */
2570   char* old_top = (char*)m->top;
2571   msegmentptr oldsp = segment_holding(m, old_top);
2572   char* old_end = oldsp->base + oldsp->size;
2573   size_t ssize = pad_request(sizeof(struct malloc_segment));
2574   char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
2575   size_t offset = align_offset(chunk2mem(rawsp));
2576   char* asp = rawsp + offset;
2577   char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
2578   mchunkptr sp = (mchunkptr)csp;
2579   msegmentptr ss = (msegmentptr)(chunk2mem(sp));
2580   mchunkptr tnext = chunk_plus_offset(sp, ssize);
2581   mchunkptr p = tnext;
2582   int nfences = 0;
2583
2584   /* reset top to new space */
2585   init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
2586
2587   /* Set up segment record */
2588   assert(is_aligned(ss));
2589   set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
2590   *ss = m->seg; /* Push current record */
2591   m->seg.base = tbase;
2592   m->seg.size = tsize;
2593   m->seg.sflags = mmapped;
2594   m->seg.next = ss;
2595
2596   /* Insert trailing fenceposts */
2597   for (;;) {
2598     mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
2599     p->head = FENCEPOST_HEAD;
2600     ++nfences;
2601     if ((char*)(&(nextp->head)) < old_end)
2602       p = nextp;
2603     else
2604       break;
2605   }
2606   assert(nfences >= 2);
2607
2608   /* Insert the rest of old top into a bin as an ordinary free chunk */
2609   if (csp != old_top) {
2610     mchunkptr q = (mchunkptr)old_top;
2611     size_t psize = csp - old_top;
2612     mchunkptr tn = chunk_plus_offset(q, psize);
2613     set_free_with_pinuse(q, psize, tn);
2614     insert_chunk(m, q, psize);
2615   }
2616
2617   check_top_chunk(m, m->top);
2618 }
2619
2620 /* -------------------------- System allocation -------------------------- */
2621
2622 /* Get memory from system using MORECORE or MMAP */
2623 static void* sys_alloc(mstate m, size_t nb) {
2624   char* tbase = CMFAIL;
2625   size_t tsize = 0;
2626   flag_t mmap_flag = 0;
2627   size_t asize; /* allocation size */
2628
2629   ensure_initialization();
2630
2631   if (use_noexpand(m))
2632       return 0;
2633
2634   /* Directly map large chunks, but only if already initialized */
2635   if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) {
2636     void* mem = mmap_alloc(m, nb);
2637     if (mem != 0)
2638       return mem;
2639   }
2640
2641   asize = granularity_align(nb + SYS_ALLOC_PADDING);
2642   if (asize <= nb)
2643     return 0; /* wraparound */
2644   if (m->footprint_limit != 0) {
2645     size_t fp = m->footprint + asize;
2646     if (fp <= m->footprint || fp > m->footprint_limit)
2647       return 0;
2648   }
2649
2650   /*
2651     Try getting memory in any of three ways (in most-preferred to
2652     least-preferred order):
2653     1. A call to MORECORE that can normally contiguously extend memory.
2654        (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
2655        or main space is mmapped or a previous contiguous call failed)
2656     2. A call to MMAP new space (disabled if not HAVE_MMAP).
2657        Note that under the default settings, if MORECORE is unable to
2658        fulfill a request, and HAVE_MMAP is true, then mmap is
2659        used as a noncontiguous system allocator. This is a useful backup
2660        strategy for systems with holes in address spaces -- in this case
2661        sbrk cannot contiguously expand the heap, but mmap may be able to
2662        find space.
2663     3. A call to MORECORE that cannot usually contiguously extend memory.
2664        (disabled if not HAVE_MORECORE)
2665
2666    In all cases, we need to request enough bytes from system to ensure
2667    we can malloc nb bytes upon success, so pad with enough space for
2668    top_foot, plus alignment-pad to make sure we don't lose bytes if
2669    not on boundary, and round this up to a granularity unit.
2670   */
2671
2672   if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
2673     char* br = CMFAIL;
2674     size_t ssize = asize; /* sbrk call size */
2675     msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
2676     ACQUIRE_MALLOC_GLOBAL_LOCK();
2677
2678     if (ss == 0) {  /* First time through or recovery */
2679       char* base = (char*)CALL_MORECORE(0);
2680       if (base != CMFAIL) {
2681         size_t fp;
2682         /* Adjust to end on a page boundary */
2683         if (!is_page_aligned(base))
2684           ssize += (page_align((size_t)base) - (size_t)base);
2685         fp = m->footprint + ssize; /* recheck limits */
2686         if (ssize > nb && ssize < HALF_MAX_SIZE_T &&
2687             (m->footprint_limit == 0 ||
2688              (fp > m->footprint && fp <= m->footprint_limit)) &&
2689             (br = (char*)(CALL_MORECORE(ssize))) == base) {
2690           tbase = base;
2691           tsize = ssize;
2692         }
2693       }
2694     }
2695     else {
2696       /* Subtract out existing available top space from MORECORE request. */
2697       ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING);
2698       /* Use mem here only if it did continuously extend old space */
2699       if (ssize < HALF_MAX_SIZE_T &&
2700           (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) {
2701         tbase = br;
2702         tsize = ssize;
2703       }
2704     }
2705
2706     if (tbase == CMFAIL) {    /* Cope with partial failure */
2707       if (br != CMFAIL) {    /* Try to use/extend the space we did get */
2708         if (ssize < HALF_MAX_SIZE_T &&
2709             ssize < nb + SYS_ALLOC_PADDING) {
2710           size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize);
2711           if (esize < HALF_MAX_SIZE_T) {
2712             char* end = (char*)CALL_MORECORE(esize);
2713             if (end != CMFAIL)
2714               ssize += esize;
2715             else {            /* Can't use; try to release */
2716               (void) CALL_MORECORE(-ssize);
2717               br = CMFAIL;
2718             }
2719           }
2720         }
2721       }
2722       if (br != CMFAIL) {    /* Use the space we did get */
2723         tbase = br;
2724         tsize = ssize;
2725       }
2726       else
2727         disable_contiguous(m); /* Don't try contiguous path in the future */
2728     }
2729
2730     RELEASE_MALLOC_GLOBAL_LOCK();
2731   }
2732
2733   if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
2734     char* mp = (char*)(CALL_MMAP(asize));
2735     if (mp != CMFAIL) {
2736       tbase = mp;
2737       tsize = asize;
2738       mmap_flag = USE_MMAP_BIT;
2739     }
2740   }
2741
2742   if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
2743     if (asize < HALF_MAX_SIZE_T) {
2744       char* br = CMFAIL;
2745       char* end = CMFAIL;
2746       ACQUIRE_MALLOC_GLOBAL_LOCK();
2747       br = (char*)(CALL_MORECORE(asize));
2748       end = (char*)(CALL_MORECORE(0));
2749       RELEASE_MALLOC_GLOBAL_LOCK();
2750       if (br != CMFAIL && end != CMFAIL && br < end) {
2751         size_t ssize = end - br;
2752         if (ssize > nb + TOP_FOOT_SIZE) {
2753           tbase = br;
2754           tsize = ssize;
2755         }
2756       }
2757     }
2758   }
2759
2760   if (tbase != CMFAIL) {
2761
2762     if ((m->footprint += tsize) > m->max_footprint)
2763       m->max_footprint = m->footprint;
2764
2765     if (!is_initialized(m)) { /* first-time initialization */
2766       if (m->least_addr == 0 || tbase < m->least_addr)
2767         m->least_addr = tbase;
2768       m->seg.base = tbase;
2769       m->seg.size = tsize;
2770       m->seg.sflags = mmap_flag;
2771       m->magic = mparams.magic;
2772       m->release_checks = MAX_RELEASE_CHECK_RATE;
2773       init_bins(m);
2774 #if !ONLY_MSPACES
2775       if (is_global(m))
2776         init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
2777       else
2778 #endif
2779       {
2780         /* Offset top by embedded malloc_state */
2781         mchunkptr mn = next_chunk(mem2chunk(m));
2782         init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
2783       }
2784     }
2785
2786     else {
2787       /* Try to merge with an existing segment */
2788       msegmentptr sp = &m->seg;
2789       /* Only consider most recent segment if traversal suppressed */
2790       while (sp != 0 && tbase != sp->base + sp->size)
2791         sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
2792       if (sp != 0 &&
2793           !is_extern_segment(sp) &&
2794           (sp->sflags & USE_MMAP_BIT) == mmap_flag &&
2795           segment_holds(sp, m->top)) { /* append */
2796         sp->size += tsize;
2797         init_top(m, m->top, m->topsize + tsize);
2798       }
2799       else {
2800         if (tbase < m->least_addr)
2801           m->least_addr = tbase;
2802         sp = &m->seg;
2803         while (sp != 0 && sp->base != tbase + tsize)
2804           sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
2805         if (sp != 0 &&
2806             !is_extern_segment(sp) &&
2807             (sp->sflags & USE_MMAP_BIT) == mmap_flag) {
2808           char* oldbase = sp->base;
2809           sp->base = tbase;
2810           sp->size += tsize;
2811           return prepend_alloc(m, tbase, oldbase, nb);
2812         }
2813         else
2814           add_segment(m, tbase, tsize, mmap_flag);
2815       }
2816     }
2817
2818     if (nb < m->topsize) { /* Allocate from new or extended top space */
2819       size_t rsize = m->topsize -= nb;
2820       mchunkptr p = m->top;
2821       mchunkptr r = m->top = chunk_plus_offset(p, nb);
2822       r->head = rsize | PINUSE_BIT;
2823       set_size_and_pinuse_of_inuse_chunk(m, p, nb);
2824       check_top_chunk(m, m->top);
2825       check_malloced_chunk(m, chunk2mem(p), nb);
2826       return chunk2mem(p);
2827     }
2828   }
2829
2830   MALLOC_FAILURE_ACTION;
2831   return 0;
2832 }
2833
2834 /* -----------------------  system deallocation -------------------------- */
2835
2836 /* Unmap and unlink any mmapped segments that don't contain used chunks */
2837 static size_t release_unused_segments(mstate m) {
2838   size_t released = 0;
2839   int nsegs = 0;
2840   msegmentptr pred = &m->seg;
2841   msegmentptr sp = pred->next;
2842   while (sp != 0) {
2843     char* base = sp->base;
2844     size_t size = sp->size;
2845     msegmentptr next = sp->next;
2846     ++nsegs;
2847     if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
2848       mchunkptr p = align_as_chunk(base);
2849       size_t psize = chunksize(p);
2850       /* Can unmap if first chunk holds entire segment and not pinned */
2851       if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
2852         tchunkptr tp = (tchunkptr)p;
2853         assert(segment_holds(sp, (char*)sp));
2854         if (p == m->dv) {
2855           m->dv = 0;
2856           m->dvsize = 0;
2857         }
2858         else {
2859           unlink_large_chunk(m, tp);
2860         }
2861         if (CALL_MUNMAP(base, size) == 0) {
2862           released += size;
2863           m->footprint -= size;
2864           /* unlink obsoleted record */
2865           sp = pred;
2866           sp->next = next;
2867         }
2868         else { /* back out if cannot unmap */
2869           insert_large_chunk(m, tp, psize);
2870         }
2871       }
2872     }
2873     if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */
2874       break;
2875     pred = sp;
2876     sp = next;
2877   }
2878   /* Reset check counter */
2879   m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)?
2880                        (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE);
2881   return released;
2882 }
2883
2884 static int sys_trim(mstate m, size_t pad) {
2885   size_t released = 0;
2886   ensure_initialization();
2887   if (pad < MAX_REQUEST && is_initialized(m)) {
2888     pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
2889
2890     if (m->topsize > pad) {
2891       /* Shrink top space in granularity-size units, keeping at least one */
2892       size_t unit = mparams.granularity;
2893       size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
2894                       SIZE_T_ONE) * unit;
2895       msegmentptr sp = segment_holding(m, (char*)m->top);
2896
2897       if (!is_extern_segment(sp)) {
2898         if (is_mmapped_segment(sp)) {
2899           if (HAVE_MMAP &&
2900               sp->size >= extra &&
2901               !has_segment_link(m, sp)) { /* can't shrink if pinned */
2902             size_t newsize = sp->size - extra;
2903             (void)newsize; /* placate people compiling -Wunused-variable */
2904             /* Prefer mremap, fall back to munmap */
2905             if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
2906                 (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
2907               released = extra;
2908             }
2909           }
2910         }
2911         else if (HAVE_MORECORE) {
2912           if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
2913             extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
2914           ACQUIRE_MALLOC_GLOBAL_LOCK();
2915           {
2916             /* Make sure end of memory is where we last set it. */
2917             char* old_br = (char*)(CALL_MORECORE(0));
2918             if (old_br == sp->base + sp->size) {
2919               char* rel_br = (char*)(CALL_MORECORE(-extra));
2920               char* new_br = (char*)(CALL_MORECORE(0));
2921               if (rel_br != CMFAIL && new_br < old_br)
2922                 released = old_br - new_br;
2923             }
2924           }
2925           RELEASE_MALLOC_GLOBAL_LOCK();
2926         }
2927       }
2928
2929       if (released != 0) {
2930         sp->size -= released;
2931         m->footprint -= released;
2932         init_top(m, m->top, m->topsize - released);
2933         check_top_chunk(m, m->top);
2934       }
2935     }
2936
2937     /* Unmap any unused mmapped segments */
2938     if (HAVE_MMAP)
2939       released += release_unused_segments(m);
2940
2941     /* On failure, disable autotrim to avoid repeated failed future calls */
2942     if (released == 0 && m->topsize > m->trim_check)
2943       m->trim_check = MAX_SIZE_T;
2944   }
2945
2946   return (released != 0)? 1 : 0;
2947 }
2948
2949 /* Consolidate and bin a chunk. Differs from exported versions
2950    of free mainly in that the chunk need not be marked as inuse.
2951 */
2952 static void dispose_chunk(mstate m, mchunkptr p, size_t psize) {
2953   mchunkptr next = chunk_plus_offset(p, psize);
2954   if (!pinuse(p)) {
2955     mchunkptr prev;
2956     size_t prevsize = p->prev_foot;
2957     if (is_mmapped(p)) {
2958       psize += prevsize + MMAP_FOOT_PAD;
2959       if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
2960         m->footprint -= psize;
2961       return;
2962     }
2963     prev = chunk_minus_offset(p, prevsize);
2964     psize += prevsize;
2965     p = prev;
2966     if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */
2967       if (p != m->dv) {
2968         unlink_chunk(m, p, prevsize);
2969       }
2970       else if ((next->head & INUSE_BITS) == INUSE_BITS) {
2971         m->dvsize = psize;
2972         set_free_with_pinuse(p, psize, next);
2973         return;
2974       }
2975     }
2976     else {
2977       CORRUPTION_ERROR_ACTION(m);
2978       return;
2979     }
2980   }
2981   if (RTCHECK(ok_address(m, next))) {
2982     if (!cinuse(next)) {  /* consolidate forward */
2983       if (next == m->top) {
2984         size_t tsize = m->topsize += psize;
2985         m->top = p;
2986         p->head = tsize | PINUSE_BIT;
2987         if (p == m->dv) {
2988           m->dv = 0;
2989           m->dvsize = 0;
2990         }
2991         return;
2992       }
2993       else if (next == m->dv) {
2994         size_t dsize = m->dvsize += psize;
2995         m->dv = p;
2996         set_size_and_pinuse_of_free_chunk(p, dsize);
2997         return;
2998       }
2999       else {
3000         size_t nsize = chunksize(next);
3001         psize += nsize;
3002         unlink_chunk(m, next, nsize);
3003         set_size_and_pinuse_of_free_chunk(p, psize);
3004         if (p == m->dv) {
3005           m->dvsize = psize;
3006           return;
3007         }
3008       }
3009     }
3010     else {
3011       set_free_with_pinuse(p, psize, next);
3012     }
3013     insert_chunk(m, p, psize);
3014   }
3015   else {
3016     CORRUPTION_ERROR_ACTION(m);
3017   }
3018 }
3019
3020 /* ---------------------------- malloc --------------------------- */
3021
3022 /* allocate a large request from the best fitting chunk in a treebin */
3023 static void* tmalloc_large(mstate m, size_t nb) {
3024   tchunkptr v = 0;
3025   size_t rsize = -nb; /* Unsigned negation */
3026   tchunkptr t;
3027   bindex_t idx;
3028   compute_tree_index(nb, idx);
3029   if ((t = *treebin_at(m, idx)) != 0) {
3030     /* Traverse tree for this bin looking for node with size == nb */
3031     size_t sizebits = nb << leftshift_for_tree_index(idx);
3032     tchunkptr rst = 0;  /* The deepest untaken right subtree */
3033     for (;;) {
3034       tchunkptr rt;
3035       size_t trem = chunksize(t) - nb;
3036       if (trem < rsize) {
3037         v = t;
3038         if ((rsize = trem) == 0)
3039           break;
3040       }
3041       rt = t->child[1];
3042       t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
3043       if (rt != 0 && rt != t)
3044         rst = rt;
3045       if (t == 0) {
3046         t = rst; /* set t to least subtree holding sizes > nb */
3047         break;
3048       }
3049       sizebits <<= 1;
3050     }
3051   }
3052   if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
3053     binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
3054     if (leftbits != 0) {
3055       bindex_t i;
3056       binmap_t leastbit = least_bit(leftbits);
3057       compute_bit2idx(leastbit, i);
3058       t = *treebin_at(m, i);
3059     }
3060   }
3061
3062   while (t != 0) { /* find smallest of tree or subtree */
3063     size_t trem = chunksize(t) - nb;
3064     if (trem < rsize) {
3065       rsize = trem;
3066       v = t;
3067     }
3068     t = leftmost_child(t);
3069   }
3070
3071   /*  If dv is a better fit, return 0 so malloc will use it */
3072   if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
3073     if (RTCHECK(ok_address(m, v))) { /* split */
3074       mchunkptr r = chunk_plus_offset(v, nb);
3075       assert(chunksize(v) == rsize + nb);
3076       if (RTCHECK(ok_next(v, r))) {
3077         unlink_large_chunk(m, v);
3078         if (rsize < MIN_CHUNK_SIZE)
3079           set_inuse_and_pinuse(m, v, (rsize + nb));
3080         else {
3081           set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3082           set_size_and_pinuse_of_free_chunk(r, rsize);
3083           insert_chunk(m, r, rsize);
3084         }
3085         return chunk2mem(v);
3086       }
3087     }
3088     CORRUPTION_ERROR_ACTION(m);
3089   }
3090   return 0;
3091 }
3092
3093 /* allocate a small request from the best fitting chunk in a treebin */
3094 static void* tmalloc_small(mstate m, size_t nb) {
3095   tchunkptr t, v;
3096   size_t rsize;
3097   bindex_t i;
3098   binmap_t leastbit = least_bit(m->treemap);
3099   compute_bit2idx(leastbit, i);
3100   v = t = *treebin_at(m, i);
3101   rsize = chunksize(t) - nb;
3102
3103   while ((t = leftmost_child(t)) != 0) {
3104     size_t trem = chunksize(t) - nb;
3105     if (trem < rsize) {
3106       rsize = trem;
3107       v = t;
3108     }
3109   }
3110
3111   if (RTCHECK(ok_address(m, v))) {
3112     mchunkptr r = chunk_plus_offset(v, nb);
3113     assert(chunksize(v) == rsize + nb);
3114     if (RTCHECK(ok_next(v, r))) {
3115       unlink_large_chunk(m, v);
3116       if (rsize < MIN_CHUNK_SIZE)
3117         set_inuse_and_pinuse(m, v, (rsize + nb));
3118       else {
3119         set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3120         set_size_and_pinuse_of_free_chunk(r, rsize);
3121         replace_dv(m, r, rsize);
3122       }
3123       return chunk2mem(v);
3124     }
3125   }
3126
3127   CORRUPTION_ERROR_ACTION(m);
3128   return 0;
3129 }
3130
3131 #if !ONLY_MSPACES
3132
3133 void* dlmalloc(size_t bytes) {
3134   /*
3135      Basic algorithm:
3136      If a small request (< 256 bytes minus per-chunk overhead):
3137        1. If one exists, use a remainderless chunk in associated smallbin.
3138           (Remainderless means that there are too few excess bytes to
3139           represent as a chunk.)
3140        2. If it is big enough, use the dv chunk, which is normally the
3141           chunk adjacent to the one used for the most recent small request.
3142        3. If one exists, split the smallest available chunk in a bin,
3143           saving remainder in dv.
3144        4. If it is big enough, use the top chunk.
3145        5. If available, get memory from system and use it
3146      Otherwise, for a large request:
3147        1. Find the smallest available binned chunk that fits, and use it
3148           if it is better fitting than dv chunk, splitting if necessary.
3149        2. If better fitting than any binned chunk, use the dv chunk.
3150        3. If it is big enough, use the top chunk.
3151        4. If request size >= mmap threshold, try to directly mmap this chunk.
3152        5. If available, get memory from system and use it
3153
3154      The ugly goto's here ensure that postaction occurs along all paths.
3155   */
3156
3157 #if USE_LOCKS
3158   ensure_initialization(); /* initialize in sys_alloc if not using locks */
3159 #endif
3160
3161   if (!PREACTION(gm)) {
3162     void* mem;
3163     size_t nb;
3164     if (bytes <= MAX_SMALL_REQUEST) {
3165       bindex_t idx;
3166       binmap_t smallbits;
3167       nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
3168       idx = small_index(nb);
3169       smallbits = gm->smallmap >> idx;
3170
3171       if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
3172         mchunkptr b, p;
3173         idx += ~smallbits & 1;       /* Uses next bin if idx empty */
3174         b = smallbin_at(gm, idx);
3175         p = b->fd;
3176         assert(chunksize(p) == small_index2size(idx));
3177         unlink_first_small_chunk(gm, b, p, idx);
3178         set_inuse_and_pinuse(gm, p, small_index2size(idx));
3179         mem = chunk2mem(p);
3180         check_malloced_chunk(gm, mem, nb);
3181         goto postaction;
3182       }
3183
3184       else if (nb > gm->dvsize) {
3185         if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
3186           mchunkptr b, p, r;
3187           size_t rsize;
3188           bindex_t i;
3189           binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
3190           binmap_t leastbit = least_bit(leftbits);
3191           compute_bit2idx(leastbit, i);
3192           b = smallbin_at(gm, i);
3193           p = b->fd;
3194           assert(chunksize(p) == small_index2size(i));
3195           unlink_first_small_chunk(gm, b, p, i);
3196           rsize = small_index2size(i) - nb;
3197           /* Fit here cannot be remainderless if 4byte sizes */
3198           if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
3199             set_inuse_and_pinuse(gm, p, small_index2size(i));
3200           else {
3201             set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3202             r = chunk_plus_offset(p, nb);
3203             set_size_and_pinuse_of_free_chunk(r, rsize);
3204             replace_dv(gm, r, rsize);
3205           }
3206           mem = chunk2mem(p);
3207           check_malloced_chunk(gm, mem, nb);
3208           goto postaction;
3209         }
3210
3211         else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
3212           check_malloced_chunk(gm, mem, nb);
3213           goto postaction;
3214         }
3215       }
3216     }
3217     else if (bytes >= MAX_REQUEST)
3218       nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
3219     else {
3220       nb = pad_request(bytes);
3221       if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
3222         check_malloced_chunk(gm, mem, nb);
3223         goto postaction;
3224       }
3225     }
3226
3227     if (nb <= gm->dvsize) {
3228       size_t rsize = gm->dvsize - nb;
3229       mchunkptr p = gm->dv;
3230       if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
3231         mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
3232         gm->dvsize = rsize;
3233         set_size_and_pinuse_of_free_chunk(r, rsize);
3234         set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3235       }
3236       else { /* exhaust dv */
3237         size_t dvs = gm->dvsize;
3238         gm->dvsize = 0;
3239         gm->dv = 0;
3240         set_inuse_and_pinuse(gm, p, dvs);
3241       }
3242       mem = chunk2mem(p);
3243       check_malloced_chunk(gm, mem, nb);
3244       goto postaction;
3245     }
3246
3247     else if (nb < gm->topsize) { /* Split top */
3248       size_t rsize = gm->topsize -= nb;
3249       mchunkptr p = gm->top;
3250       mchunkptr r = gm->top = chunk_plus_offset(p, nb);
3251       r->head = rsize | PINUSE_BIT;
3252       set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
3253       mem = chunk2mem(p);
3254       check_top_chunk(gm, gm->top);
3255       check_malloced_chunk(gm, mem, nb);
3256       goto postaction;
3257     }
3258
3259     mem = sys_alloc(gm, nb);
3260
3261   postaction:
3262     POSTACTION(gm);
3263     return mem;
3264   }
3265
3266   return 0;
3267 }
3268
3269 /* ---------------------------- free --------------------------- */
3270
3271 void dlfree(void* mem) {
3272   /*
3273      Consolidate freed chunks with preceeding or succeeding bordering
3274      free chunks, if they exist, and then place in a bin.  Intermixed
3275      with special cases for top, dv, mmapped chunks, and usage errors.
3276   */
3277
3278   if (mem != 0) {
3279     mchunkptr p  = mem2chunk(mem);
3280 #if FOOTERS
3281     mstate fm = get_mstate_for(p);
3282     if (!ok_magic(fm)) {
3283       USAGE_ERROR_ACTION(fm, p);
3284       return;
3285     }
3286 #else /* FOOTERS */
3287 #define fm gm
3288 #endif /* FOOTERS */
3289     if (!PREACTION(fm)) {
3290       check_inuse_chunk(fm, p);
3291       if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
3292         size_t psize = chunksize(p);
3293         mchunkptr next = chunk_plus_offset(p, psize);
3294         if (!pinuse(p)) {
3295           size_t prevsize = p->prev_foot;
3296           if (is_mmapped(p)) {
3297             psize += prevsize + MMAP_FOOT_PAD;
3298             if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
3299               fm->footprint -= psize;
3300             goto postaction;
3301           }
3302           else {
3303             mchunkptr prev = chunk_minus_offset(p, prevsize);
3304             psize += prevsize;
3305             p = prev;
3306             if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
3307               if (p != fm->dv) {
3308                 unlink_chunk(fm, p, prevsize);
3309               }
3310               else if ((next->head & INUSE_BITS) == INUSE_BITS) {
3311                 fm->dvsize = psize;
3312                 set_free_with_pinuse(p, psize, next);
3313                 goto postaction;
3314               }
3315             }
3316             else
3317               goto erroraction;
3318           }
3319         }
3320
3321         if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
3322           if (!cinuse(next)) {  /* consolidate forward */
3323             if (next == fm->top) {
3324               size_t tsize = fm->topsize += psize;
3325               fm->top = p;
3326               p->head = tsize | PINUSE_BIT;
3327               if (p == fm->dv) {
3328                 fm->dv = 0;
3329                 fm->dvsize = 0;
3330               }
3331               if (should_trim(fm, tsize))
3332                 sys_trim(fm, 0);
3333               goto postaction;
3334             }
3335             else if (next == fm->dv) {
3336               size_t dsize = fm->dvsize += psize;
3337               fm->dv = p;
3338               set_size_and_pinuse_of_free_chunk(p, dsize);
3339               goto postaction;
3340             }
3341             else {
3342               size_t nsize = chunksize(next);
3343               psize += nsize;
3344               unlink_chunk(fm, next, nsize);
3345               set_size_and_pinuse_of_free_chunk(p, psize);
3346               if (p == fm->dv) {
3347                 fm->dvsize = psize;
3348                 goto postaction;
3349               }
3350             }
3351           }
3352           else
3353             set_free_with_pinuse(p, psize, next);
3354
3355           if (is_small(psize)) {
3356             insert_small_chunk(fm, p, psize);
3357             check_free_chunk(fm, p);
3358           }
3359           else {
3360             tchunkptr tp = (tchunkptr)p;
3361             insert_large_chunk(fm, tp, psize);
3362             check_free_chunk(fm, p);
3363             if (--fm->release_checks == 0)
3364               release_unused_segments(fm);
3365           }
3366           goto postaction;
3367         }
3368       }
3369     erroraction:
3370       USAGE_ERROR_ACTION(fm, p);
3371     postaction:
3372       POSTACTION(fm);
3373     }
3374   }
3375 #if !FOOTERS
3376 #undef fm
3377 #endif /* FOOTERS */
3378 }
3379
3380 void* dlcalloc(size_t n_elements, size_t elem_size) {
3381   void* mem;
3382   size_t req = 0;
3383   if (n_elements != 0) {
3384     req = n_elements * elem_size;
3385     if (((n_elements | elem_size) & ~(size_t)0xffff) &&
3386         (req / n_elements != elem_size))
3387       req = MAX_SIZE_T; /* force downstream failure on overflow */
3388   }
3389   mem = dlmalloc(req);
3390   if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
3391     memset(mem, 0, req);
3392   return mem;
3393 }
3394
3395 #endif /* !ONLY_MSPACES */
3396
3397 /* ------------ Internal support for realloc, memalign, etc -------------- */
3398
3399 /* Try to realloc; only in-place unless can_move true */
3400 static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb,
3401                                    int can_move) {
3402   mchunkptr newp = 0;
3403   size_t oldsize = chunksize(p);
3404   mchunkptr next = chunk_plus_offset(p, oldsize);
3405   if (RTCHECK(ok_address(m, p) && ok_inuse(p) &&
3406               ok_next(p, next) && ok_pinuse(next))) {
3407     if (is_mmapped(p)) {
3408       newp = mmap_resize(m, p, nb, can_move);
3409     }
3410     else if (oldsize >= nb) {             /* already big enough */
3411       size_t rsize = oldsize - nb;
3412       if (rsize >= MIN_CHUNK_SIZE) {      /* split off remainder */
3413         mchunkptr r = chunk_plus_offset(p, nb);
3414         set_inuse(m, p, nb);
3415         set_inuse(m, r, rsize);
3416         dispose_chunk(m, r, rsize);
3417       }
3418       newp = p;
3419     }
3420     else if (next == m->top) {  /* extend into top */
3421       if (oldsize + m->topsize > nb) {
3422         size_t newsize = oldsize + m->topsize;
3423         size_t newtopsize = newsize - nb;
3424         mchunkptr newtop = chunk_plus_offset(p, nb);
3425         set_inuse(m, p, nb);
3426         newtop->head = newtopsize |PINUSE_BIT;
3427         m->top = newtop;
3428         m->topsize = newtopsize;
3429         newp = p;
3430       }
3431     }
3432     else if (next == m->dv) { /* extend into dv */
3433       size_t dvs = m->dvsize;
3434       if (oldsize + dvs >= nb) {
3435         size_t dsize = oldsize + dvs - nb;
3436         if (dsize >= MIN_CHUNK_SIZE) {
3437           mchunkptr r = chunk_plus_offset(p, nb);
3438           mchunkptr n = chunk_plus_offset(r, dsize);
3439           set_inuse(m, p, nb);
3440           set_size_and_pinuse_of_free_chunk(r, dsize);
3441           clear_pinuse(n);
3442           m->dvsize = dsize;
3443           m->dv = r;
3444         }
3445         else { /* exhaust dv */
3446           size_t newsize = oldsize + dvs;
3447           set_inuse(m, p, newsize);
3448           m->dvsize = 0;
3449           m->dv = 0;
3450         }
3451         newp = p;
3452       }
3453     }
3454     else if (!cinuse(next)) { /* extend into next free chunk */
3455       size_t nextsize = chunksize(next);
3456       if (oldsize + nextsize >= nb) {
3457         size_t rsize = oldsize + nextsize - nb;
3458         unlink_chunk(m, next, nextsize);
3459         if (rsize < MIN_CHUNK_SIZE) {
3460           size_t newsize = oldsize + nextsize;
3461           set_inuse(m, p, newsize);
3462         }
3463         else {
3464           mchunkptr r = chunk_plus_offset(p, nb);
3465           set_inuse(m, p, nb);
3466           set_inuse(m, r, rsize);
3467           dispose_chunk(m, r, rsize);
3468         }
3469         newp = p;
3470       }
3471     }
3472   }
3473   else {
3474     USAGE_ERROR_ACTION(m, chunk2mem(p));
3475   }
3476   return newp;
3477 }
3478
3479 static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
3480   void* mem = 0;
3481   if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
3482     alignment = MIN_CHUNK_SIZE;
3483   if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
3484     size_t a = MALLOC_ALIGNMENT << 1;
3485     while (a < alignment) a <<= 1;
3486     alignment = a;
3487   }
3488   if (bytes >= MAX_REQUEST - alignment) {
3489     if (m != 0)  { /* Test isn't needed but avoids compiler warning */
3490       MALLOC_FAILURE_ACTION;
3491     }
3492   }
3493   else {
3494     size_t nb = request2size(bytes);
3495     size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
3496     mem = internal_malloc(m, req);
3497     if (mem != 0) {
3498       mchunkptr p = mem2chunk(mem);
3499       if (PREACTION(m))
3500         return 0;
3501       if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */
3502         /*
3503           Find an aligned spot inside chunk.  Since we need to give
3504           back leading space in a chunk of at least MIN_CHUNK_SIZE, if
3505           the first calculation places us at a spot with less than
3506           MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
3507           We've allocated enough total room so that this is always
3508           possible.
3509         */
3510         char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment -
3511                                                        SIZE_T_ONE)) &
3512                                              -alignment));
3513         char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
3514           br : br+alignment;
3515         mchunkptr newp = (mchunkptr)pos;
3516         size_t leadsize = pos - (char*)(p);
3517         size_t newsize = chunksize(p) - leadsize;
3518
3519         if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
3520           newp->prev_foot = p->prev_foot + leadsize;
3521           newp->head = newsize;
3522         }
3523         else { /* Otherwise, give back leader, use the rest */
3524           set_inuse(m, newp, newsize);
3525           set_inuse(m, p, leadsize);
3526           dispose_chunk(m, p, leadsize);
3527         }
3528         p = newp;
3529       }
3530
3531       /* Give back spare room at the end */
3532       if (!is_mmapped(p)) {
3533         size_t size = chunksize(p);
3534         if (size > nb + MIN_CHUNK_SIZE) {
3535           size_t remainder_size = size - nb;
3536           mchunkptr remainder = chunk_plus_offset(p, nb);
3537           set_inuse(m, p, nb);
3538           set_inuse(m, remainder, remainder_size);
3539           dispose_chunk(m, remainder, remainder_size);
3540         }
3541       }
3542
3543       mem = chunk2mem(p);
3544       assert (chunksize(p) >= nb);
3545       assert(((size_t)mem & (alignment - 1)) == 0);
3546       check_inuse_chunk(m, p);
3547       POSTACTION(m);
3548     }
3549   }
3550   return mem;
3551 }
3552
3553 /*
3554   Common support for independent_X routines, handling
3555     all of the combinations that can result.
3556   The opts arg has:
3557     bit 0 set if all elements are same size (using sizes[0])
3558     bit 1 set if elements should be zeroed
3559 */
3560 static void** ialloc(mstate m,
3561                      size_t n_elements,
3562                      size_t* sizes,
3563                      int opts,
3564                      void* chunks[]) {
3565
3566   size_t    element_size;   /* chunksize of each element, if all same */
3567   size_t    contents_size;  /* total size of elements */
3568   size_t    array_size;     /* request size of pointer array */
3569   void*     mem;            /* malloced aggregate space */
3570   mchunkptr p;              /* corresponding chunk */
3571   size_t    remainder_size; /* remaining bytes while splitting */
3572   void**    marray;         /* either "chunks" or malloced ptr array */
3573   mchunkptr array_chunk;    /* chunk for malloced ptr array */
3574   flag_t    was_enabled;    /* to disable mmap */
3575   size_t    size;
3576   size_t    i;
3577
3578   ensure_initialization();
3579   /* compute array length, if needed */
3580   if (chunks != 0) {
3581     if (n_elements == 0)
3582       return chunks; /* nothing to do */
3583     marray = chunks;
3584     array_size = 0;
3585   }
3586   else {
3587     /* if empty req, must still return chunk representing empty array */
3588     if (n_elements == 0)
3589       return (void**)internal_malloc(m, 0);
3590     marray = 0;
3591     array_size = request2size(n_elements * (sizeof(void*)));
3592   }
3593
3594   /* compute total element size */
3595   if (opts & 0x1) { /* all-same-size */
3596     element_size = request2size(*sizes);
3597     contents_size = n_elements * element_size;
3598   }
3599   else { /* add up all the sizes */
3600     element_size = 0;
3601     contents_size = 0;
3602     for (i = 0; i != n_elements; ++i)
3603       contents_size += request2size(sizes[i]);
3604   }
3605
3606   size = contents_size + array_size;
3607
3608   /*
3609      Allocate the aggregate chunk.  First disable direct-mmapping so
3610      malloc won't use it, since we would not be able to later
3611      free/realloc space internal to a segregated mmap region.
3612   */
3613   was_enabled = use_mmap(m);
3614   disable_mmap(m);
3615   mem = internal_malloc(m, size - CHUNK_OVERHEAD);
3616   if (was_enabled)
3617     enable_mmap(m);
3618   if (mem == 0)
3619     return 0;
3620
3621   if (PREACTION(m)) return 0;
3622   p = mem2chunk(mem);
3623   remainder_size = chunksize(p);
3624
3625   assert(!is_mmapped(p));
3626
3627   if (opts & 0x2) {       /* optionally clear the elements */
3628     memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
3629   }
3630
3631   /* If not provided, allocate the pointer array as final part of chunk */
3632   if (marray == 0) {
3633     size_t  array_chunk_size;
3634     array_chunk = chunk_plus_offset(p, contents_size);
3635     array_chunk_size = remainder_size - contents_size;
3636     marray = (void**) (chunk2mem(array_chunk));
3637     set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
3638     remainder_size = contents_size;
3639   }
3640
3641   /* split out elements */
3642   for (i = 0; ; ++i) {
3643     marray[i] = chunk2mem(p);
3644     if (i != n_elements-1) {
3645       if (element_size != 0)
3646         size = element_size;
3647       else
3648         size = request2size(sizes[i]);
3649       remainder_size -= size;
3650       set_size_and_pinuse_of_inuse_chunk(m, p, size);
3651       p = chunk_plus_offset(p, size);
3652     }
3653     else { /* the final element absorbs any overallocation slop */
3654       set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
3655       break;
3656     }
3657   }
3658
3659 #if DEBUG
3660   if (marray != chunks) {
3661     /* final element must have exactly exhausted chunk */
3662     if (element_size != 0) {
3663       assert(remainder_size == element_size);
3664     }
3665     else {
3666       assert(remainder_size == request2size(sizes[i]));
3667     }
3668     check_inuse_chunk(m, mem2chunk(marray));
3669   }
3670   for (i = 0; i != n_elements; ++i)
3671     check_inuse_chunk(m, mem2chunk(marray[i]));
3672
3673 #endif /* DEBUG */
3674
3675   POSTACTION(m);
3676   return marray;
3677 }
3678
3679 /* Try to free all pointers in the given array.
3680    Note: this could be made faster, by delaying consolidation,
3681    at the price of disabling some user integrity checks, We
3682    still optimize some consolidations by combining adjacent
3683    chunks before freeing, which will occur often if allocated
3684    with ialloc or the array is sorted.
3685 */
3686 static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) {
3687   size_t unfreed = 0;
3688   if (!PREACTION(m)) {
3689     void** a;
3690     void** fence = &(array[nelem]);
3691     for (a = array; a != fence; ++a) {
3692       void* mem = *a;
3693       if (mem != 0) {
3694         mchunkptr p = mem2chunk(mem);
3695         size_t psize = chunksize(p);
3696 #if FOOTERS
3697         if (get_mstate_for(p) != m) {
3698           ++unfreed;
3699           continue;
3700         }
3701 #endif
3702         check_inuse_chunk(m, p);
3703         *a = 0;
3704         if (RTCHECK(ok_address(m, p) && ok_inuse(p))) {
3705           void ** b = a + 1; /* try to merge with next chunk */
3706           mchunkptr next = next_chunk(p);
3707           if (b != fence && *b == chunk2mem(next)) {
3708             size_t newsize = chunksize(next) + psize;
3709             set_inuse(m, p, newsize);
3710             *b = chunk2mem(p);
3711           }
3712           else
3713             dispose_chunk(m, p, psize);
3714         }
3715         else {
3716           CORRUPTION_ERROR_ACTION(m);
3717           break;
3718         }
3719       }
3720     }
3721     if (should_trim(m, m->topsize))
3722       sys_trim(m, 0);
3723     POSTACTION(m);
3724   }
3725   return unfreed;
3726 }
3727
3728 /* Traversal */
3729 #if MALLOC_INSPECT_ALL
3730 static void internal_inspect_all(mstate m,
3731                                  void(*handler)(void *start,
3732                                                 void *end,
3733                                                 size_t used_bytes,
3734                                                 void* callback_arg),
3735                                  void* arg) {
3736   if (is_initialized(m)) {
3737     mchunkptr top = m->top;
3738     msegmentptr s;
3739     for (s = &m->seg; s != 0; s = s->next) {
3740       mchunkptr q = align_as_chunk(s->base);
3741       while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) {
3742         mchunkptr next = next_chunk(q);
3743         size_t sz = chunksize(q);
3744         size_t used;
3745         void* start;
3746         if (is_inuse(q)) {
3747           used = sz - CHUNK_OVERHEAD; /* must not be mmapped */
3748           start = chunk2mem(q);
3749         }
3750         else {
3751           used = 0;
3752           if (is_small(sz)) {     /* offset by possible bookkeeping */
3753             start = (void*)((char*)q + sizeof(struct malloc_chunk));
3754           }
3755           else {
3756             start = (void*)((char*)q + sizeof(struct malloc_tree_chunk));
3757           }
3758         }
3759         if (start < (void*)next)  /* skip if all space is bookkeeping */
3760           handler(start, next, used, arg);
3761         if (q == top)
3762           break;
3763         q = next;
3764       }
3765     }
3766   }
3767 }
3768 #endif /* MALLOC_INSPECT_ALL */
3769
3770 /* ------------------ Exported realloc, memalign, etc -------------------- */
3771
3772 #if !ONLY_MSPACES
3773
3774 void* dlrealloc(void* oldmem, size_t bytes) {
3775   void* mem = 0;
3776   if (oldmem == 0) {
3777     mem = dlmalloc(bytes);
3778   }
3779   else if (bytes >= MAX_REQUEST) {
3780     MALLOC_FAILURE_ACTION;
3781   }
3782 #ifdef REALLOC_ZERO_BYTES_FREES
3783   else if (bytes == 0) {
3784     dlfree(oldmem);
3785   }
3786 #endif /* REALLOC_ZERO_BYTES_FREES */
3787   else {
3788     size_t nb = request2size(bytes);
3789     mchunkptr oldp = mem2chunk(oldmem);
3790 #if ! FOOTERS
3791     mstate m = gm;
3792 #else /* FOOTERS */
3793     mstate m = get_mstate_for(oldp);
3794     if (!ok_magic(m)) {
3795       USAGE_ERROR_ACTION(m, oldmem);
3796       return 0;
3797     }
3798 #endif /* FOOTERS */
3799     if (!PREACTION(m)) {
3800       mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1);
3801       POSTACTION(m);
3802       if (newp != 0) {
3803         check_inuse_chunk(m, newp);
3804         mem = chunk2mem(newp);
3805       }
3806       else {
3807         mem = internal_malloc(m, bytes);
3808         if (mem != 0) {
3809           size_t oc = chunksize(oldp) - overhead_for(oldp);
3810           memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
3811           internal_free(m, oldmem);
3812         }
3813       }
3814     }
3815   }
3816   return mem;
3817 }
3818
3819 void* dlrealloc_in_place(void* oldmem, size_t bytes) {
3820   void* mem = 0;
3821   if (oldmem != 0) {
3822     if (bytes >= MAX_REQUEST) {
3823       MALLOC_FAILURE_ACTION;
3824     }
3825     else {
3826       size_t nb = request2size(bytes);
3827       mchunkptr oldp = mem2chunk(oldmem);
3828 #if ! FOOTERS
3829       mstate m = gm;
3830 #else /* FOOTERS */
3831       mstate m = get_mstate_for(oldp);
3832       if (!ok_magic(m)) {
3833         USAGE_ERROR_ACTION(m, oldmem);
3834         return 0;
3835       }
3836 #endif /* FOOTERS */
3837       if (!PREACTION(m)) {
3838         mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0);
3839         POSTACTION(m);
3840         if (newp == oldp) {
3841           check_inuse_chunk(m, newp);
3842           mem = oldmem;
3843         }
3844       }
3845     }
3846   }
3847   return mem;
3848 }
3849
3850 void* dlmemalign(size_t alignment, size_t bytes) {
3851   if (alignment <= MALLOC_ALIGNMENT) {
3852     return dlmalloc(bytes);
3853   }
3854   return internal_memalign(gm, alignment, bytes);
3855 }
3856
3857 int dlposix_memalign(void** pp, size_t alignment, size_t bytes) {
3858   void* mem = 0;
3859   if (alignment == MALLOC_ALIGNMENT)
3860     mem = dlmalloc(bytes);
3861   else {
3862     size_t d = alignment / sizeof(void*);
3863     size_t r = alignment % sizeof(void*);
3864     if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0)
3865       return EINVAL;
3866     else if (bytes <= MAX_REQUEST - alignment) {
3867       if (alignment <  MIN_CHUNK_SIZE)
3868         alignment = MIN_CHUNK_SIZE;
3869       mem = internal_memalign(gm, alignment, bytes);
3870     }
3871   }
3872   if (mem == 0)
3873     return ENOMEM;
3874   else {
3875     *pp = mem;
3876     return 0;
3877   }
3878 }
3879
3880 void* dlvalloc(size_t bytes) {
3881   size_t pagesz;
3882   ensure_initialization();
3883   pagesz = mparams.page_size;
3884   return dlmemalign(pagesz, bytes);
3885 }
3886
3887 void* dlpvalloc(size_t bytes) {
3888   size_t pagesz;
3889   ensure_initialization();
3890   pagesz = mparams.page_size;
3891   return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
3892 }
3893
3894 void** dlindependent_calloc(size_t n_elements, size_t elem_size,
3895                             void* chunks[]) {
3896   size_t sz = elem_size; /* serves as 1-element array */
3897   return ialloc(gm, n_elements, &sz, 3, chunks);
3898 }
3899
3900 void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
3901                               void* chunks[]) {
3902   return ialloc(gm, n_elements, sizes, 0, chunks);
3903 }
3904
3905 size_t dlbulk_free(void* array[], size_t nelem) {
3906   return internal_bulk_free(gm, array, nelem);
3907 }
3908
3909 #if MALLOC_INSPECT_ALL
3910 void dlmalloc_inspect_all(void(*handler)(void *start,
3911                                          void *end,
3912                                          size_t used_bytes,
3913                                          void* callback_arg),
3914                           void* arg) {
3915   ensure_initialization();
3916   if (!PREACTION(gm)) {
3917     internal_inspect_all(gm, handler, arg);
3918     POSTACTION(gm);
3919   }
3920 }
3921 #endif /* MALLOC_INSPECT_ALL */
3922
3923 int dlmalloc_trim(size_t pad) {
3924   int result = 0;
3925   ensure_initialization();
3926   if (!PREACTION(gm)) {
3927     result = sys_trim(gm, pad);
3928     POSTACTION(gm);
3929   }
3930   return result;
3931 }
3932
3933 size_t dlmalloc_footprint(void) {
3934   return gm->footprint;
3935 }
3936
3937 size_t dlmalloc_max_footprint(void) {
3938   return gm->max_footprint;
3939 }
3940
3941 size_t dlmalloc_footprint_limit(void) {
3942   size_t maf = gm->footprint_limit;
3943   return maf == 0 ? MAX_SIZE_T : maf;
3944 }
3945
3946 size_t dlmalloc_set_footprint_limit(size_t bytes) {
3947   size_t result;  /* invert sense of 0 */
3948   if (bytes == 0)
3949     result = granularity_align(1); /* Use minimal size */
3950   if (bytes == MAX_SIZE_T)
3951     result = 0;                    /* disable */
3952   else
3953     result = granularity_align(bytes);
3954   return gm->footprint_limit = result;
3955 }
3956
3957 #if !NO_MALLINFO
3958 struct mallinfo dlmallinfo(void) {
3959   return internal_mallinfo(gm);
3960 }
3961 #endif /* NO_MALLINFO */
3962
3963 #if !NO_MALLOC_STATS
3964 void dlmalloc_stats() {
3965   internal_malloc_stats(gm);
3966 }
3967 #endif /* NO_MALLOC_STATS */
3968
3969 int dlmallopt(int param_number, int value) {
3970   return change_mparam(param_number, value);
3971 }
3972
3973 size_t dlmalloc_usable_size(void* mem) {
3974   if (mem != 0) {
3975     mchunkptr p = mem2chunk(mem);
3976     if (is_inuse(p))
3977       return chunksize(p) - overhead_for(p);
3978   }
3979   return 0;
3980 }
3981
3982 #endif /* !ONLY_MSPACES */
3983
3984 /* ----------------------------- user mspaces ---------------------------- */
3985
3986 #if MSPACES
3987
3988 static mstate init_user_mstate(char* tbase, size_t tsize) {
3989   size_t msize = pad_request(sizeof(struct malloc_state));
3990   mchunkptr mn;
3991   mchunkptr msp = align_as_chunk(tbase);
3992   mstate m = (mstate)(chunk2mem(msp));
3993   memset(m, 0, msize);
3994   (void)INITIAL_LOCK(&m->mutex);
3995   msp->head = (msize|INUSE_BITS);
3996   m->seg.base = m->least_addr = tbase;
3997   m->seg.size = m->footprint = m->max_footprint = tsize;
3998   m->magic = mparams.magic;
3999   m->release_checks = MAX_RELEASE_CHECK_RATE;
4000   m->mflags = mparams.default_mflags;
4001   m->extp = 0;
4002   m->exts = 0;
4003   disable_contiguous(m);
4004   init_bins(m);
4005   mn = next_chunk(mem2chunk(m));
4006   init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
4007   check_top_chunk(m, m->top);
4008   return m;
4009 }
4010
4011 mspace create_mspace(size_t capacity, int locked) {
4012   mstate m = 0;
4013   size_t msize;
4014   ensure_initialization();
4015   msize = pad_request(sizeof(struct malloc_state));
4016   if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4017     size_t rs = ((capacity == 0)? mparams.granularity :
4018                  (capacity + TOP_FOOT_SIZE + msize));
4019     size_t tsize = granularity_align(rs);
4020     char* tbase = (char*)(CALL_MMAP(tsize));
4021     if (tbase != CMFAIL) {
4022       m = init_user_mstate(tbase, tsize);
4023       m->seg.sflags = USE_MMAP_BIT;
4024       set_lock(m, locked);
4025     }
4026   }
4027   return (mspace)m;
4028 }
4029
4030 mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
4031   mstate m = 0;
4032   size_t msize;
4033   ensure_initialization();
4034   msize = pad_request(sizeof(struct malloc_state));
4035   if (capacity > msize + TOP_FOOT_SIZE &&
4036       capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4037     m = init_user_mstate((char*)base, capacity);
4038     m->seg.sflags = EXTERN_BIT;
4039     set_lock(m, locked);
4040   }
4041   return (mspace)m;
4042 }
4043
4044 int mspace_track_large_chunks(mspace msp, int enable) {
4045   int ret = 0;
4046   mstate ms = (mstate)msp;
4047   if (!PREACTION(ms)) {
4048     if (!use_mmap(ms)) {
4049       ret = 1;
4050     }
4051     if (!enable) {
4052       enable_mmap(ms);
4053     } else {
4054       disable_mmap(ms);
4055     }
4056     POSTACTION(ms);
4057   }
4058   return ret;
4059 }
4060
4061 size_t destroy_mspace(mspace msp) {
4062   size_t freed = 0;
4063   mstate ms = (mstate)msp;
4064   if (ok_magic(ms)) {
4065     msegmentptr sp = &ms->seg;
4066     (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */
4067     while (sp != 0) {
4068       char* base = sp->base;
4069       size_t size = sp->size;
4070       flag_t flag = sp->sflags;
4071       (void)base; /* placate people compiling -Wunused-variable */
4072       sp = sp->next;
4073       if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) &&
4074           CALL_MUNMAP(base, size) == 0)
4075         freed += size;
4076     }
4077   }
4078   else {
4079     USAGE_ERROR_ACTION(ms,ms);
4080   }
4081   return freed;
4082 }
4083
4084 void mspace_get_address_and_size (mspace msp, unsigned long long *addrp,
4085                                   unsigned long long *sizep)
4086 {
4087   mstate ms;
4088   msegment *this_seg;
4089   
4090   ms = (mstate)msp;
4091   this_seg = &ms->seg;
4092
4093   *addrp = (unsigned long long) this_seg->base;
4094   *sizep = this_seg->size;
4095 }
4096
4097 int mspace_is_heap_object (mspace msp, void *p)
4098 {
4099   msegment *this_seg;
4100   char *pp, *base;
4101   mstate ms;
4102
4103   ms = (mstate)msp;
4104
4105   this_seg = &ms->seg;
4106   pp = (char *) p;
4107
4108   while (this_seg)
4109     {
4110       base = this_seg->base;
4111       if (pp >= base && pp < (base + this_seg->size))
4112         return 1;
4113       this_seg = this_seg->next;
4114     }
4115   return 0;
4116 }
4117
4118 void *mspace_least_addr (mspace msp)
4119 {
4120   mstate ms = (mstate) msp;
4121   return (void *) ms->least_addr;
4122 }
4123
4124 void mspace_disable_expand (mspace msp)
4125 {
4126   mstate ms = (mstate)msp;
4127
4128   disable_expand (ms);
4129 }
4130
4131 int mspace_enable_disable_trace (mspace msp, int enable)
4132 {
4133   mstate ms = (mstate)msp;
4134   int was_enabled = 0;
4135
4136   if (use_trace(ms) == 1)
4137     was_enabled = 1;
4138
4139   if (enable)
4140     enable_trace (ms);
4141   else
4142     disable_trace (ms);
4143
4144   return (was_enabled);
4145 }
4146
4147 void* mspace_get_aligned (mspace msp, 
4148                           unsigned long long n_user_data_bytes,
4149                           unsigned long long align, 
4150                           unsigned long long align_offset) {
4151   char *rv;
4152   unsigned long long searchp;
4153   unsigned *wwp;                /* "where's Waldo" pointer */
4154   mstate ms = (mstate)msp;
4155
4156   /*
4157    * Allocate space for the "Where's Waldo?" pointer 
4158    * the base of the dlmalloc object
4159    */
4160   n_user_data_bytes += sizeof(unsigned);
4161
4162   /* 
4163    * Alignment requests less than the size of an mmx vector are ignored 
4164    */
4165   if (align < 16) {
4166     rv = mspace_malloc (msp, n_user_data_bytes);
4167     if (rv == 0)
4168         return rv;
4169
4170     if (use_trace(ms)) {
4171       mchunkptr p  = mem2chunk(rv);
4172       size_t psize = chunksize(p);
4173       
4174       mheap_get_trace ((u64)rv + sizeof (unsigned), psize);
4175     }
4176
4177     wwp = (unsigned *)rv;
4178     *wwp = 0;
4179     rv += sizeof (unsigned);
4180
4181     return rv;
4182   }
4183
4184   /*
4185    * Alignment requests greater than 4K must be at offset zero,
4186    * and must be freed using mspace_free_no_offset - or never freed -
4187    * since the "Where's Waldo?" pointer would waste too much space.
4188    * 
4189    * Waldo is the address of the chunk of memory returned by mspace_malloc, 
4190    * which we need later to call mspace_free...
4191    */
4192   if (align > 4<<10 || align_offset == ~0ULL) {
4193     n_user_data_bytes -= sizeof(unsigned);
4194     assert(align_offset == 0);
4195     rv = internal_memalign(ms, (size_t)align, n_user_data_bytes);
4196     
4197     /* Trace the allocation */
4198     if (rv && use_trace(ms)) {
4199       mchunkptr p  = mem2chunk(rv);
4200       size_t psize = chunksize(p);
4201       mheap_get_trace ((u64)rv, psize);
4202     }
4203     return rv;
4204   }
4205
4206   align = clib_max (align, MALLOC_ALIGNMENT);
4207   align = max_pow2 (align);
4208
4209   /* Correct align offset to be smaller than alignment. */
4210   align_offset &= (align - 1);
4211
4212   n_user_data_bytes += align;
4213   rv = mspace_malloc (msp, n_user_data_bytes);
4214
4215   if (rv == 0)
4216       return rv;
4217
4218   /* Honor the alignment request */
4219   searchp = (unsigned long long)(rv + sizeof (unsigned));
4220
4221 #if 0  /* this is the idea... */
4222   while ((searchp + align_offset) % align)
4223     searchp++;
4224 #endif
4225
4226   {
4227     unsigned long long where_now, delta;
4228
4229     where_now = (searchp + align_offset) % align;
4230     delta = align - where_now;
4231
4232     searchp += delta;
4233   }
4234
4235   wwp = (unsigned *)(searchp - sizeof(unsigned));
4236   *wwp = (searchp - (((unsigned long long) rv) + sizeof (*wwp)));
4237   assert (*wwp < align);
4238
4239   if (use_trace(ms)) {
4240     mchunkptr p  = mem2chunk(rv);
4241     size_t psize = chunksize(p);
4242     mheap_get_trace ((u64)rv, psize);
4243   }
4244   return (void *) searchp;
4245 }
4246
4247 void mspace_put (mspace msp, void *p_arg)
4248 {
4249   char *object_header;
4250   unsigned *wwp;
4251   mstate ms = (mstate)msp;
4252
4253   /* Find the object header delta */
4254   wwp = (unsigned *)p_arg;
4255   wwp --;
4256
4257   /* Recover the dlmalloc object pointer */
4258   object_header = (char *)wwp;
4259   object_header -= *wwp;
4260
4261   /* Tracing (if enabled) */
4262   if (use_trace(ms))
4263     {
4264       mchunkptr p  = mem2chunk(object_header);
4265       size_t psize = chunksize(p);
4266
4267       mheap_put_trace ((u64)p_arg, psize);
4268     }
4269
4270   /* And free it... */
4271   mspace_free (msp, object_header);
4272 }
4273
4274 void mspace_put_no_offset (mspace msp, void *p_arg)
4275 {
4276   mstate ms = (mstate)msp;
4277
4278   if (use_trace(ms))
4279     {
4280       mchunkptr p  = mem2chunk(p_arg);
4281       size_t psize = chunksize(p);
4282
4283       mheap_put_trace ((u64)p_arg, psize);
4284     }
4285   mspace_free (msp, p_arg);
4286 }
4287
4288 size_t mspace_usable_size_with_delta (const void *p)
4289 {
4290   size_t usable_size;
4291   char *object_header;
4292   unsigned *wwp;
4293
4294   /* Find the object header delta */
4295   wwp = (unsigned *)p;
4296   wwp --;
4297
4298   /* Recover the dlmalloc object pointer */
4299   object_header = (char *)wwp;
4300   object_header -= *wwp;
4301
4302   usable_size = mspace_usable_size (object_header);
4303   /* account for the offset and the size of the offset... */
4304   usable_size -= (*wwp + sizeof (*wwp));
4305   return usable_size;
4306 }
4307
4308 /*
4309   mspace versions of routines are near-clones of the global
4310   versions. This is not so nice but better than the alternatives.
4311 */
4312
4313 void* mspace_malloc(mspace msp, size_t bytes) {
4314   mstate ms = (mstate)msp;
4315   if (!ok_magic(ms)) {
4316     USAGE_ERROR_ACTION(ms,ms);
4317     return 0;
4318   }
4319   if (!PREACTION(ms)) {
4320     void* mem;
4321     size_t nb;
4322     if (bytes <= MAX_SMALL_REQUEST) {
4323       bindex_t idx;
4324       binmap_t smallbits;
4325       nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4326       idx = small_index(nb);
4327       smallbits = ms->smallmap >> idx;
4328
4329       if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4330         mchunkptr b, p;
4331         idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4332         b = smallbin_at(ms, idx);
4333         p = b->fd;
4334         assert(chunksize(p) == small_index2size(idx));
4335         unlink_first_small_chunk(ms, b, p, idx);
4336         set_inuse_and_pinuse(ms, p, small_index2size(idx));
4337         mem = chunk2mem(p);
4338         check_malloced_chunk(ms, mem, nb);
4339         goto postaction;
4340       }
4341
4342       else if (nb > ms->dvsize) {
4343         if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4344           mchunkptr b, p, r;
4345           size_t rsize;
4346           bindex_t i;
4347           binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4348           binmap_t leastbit = least_bit(leftbits);
4349           compute_bit2idx(leastbit, i);
4350           b = smallbin_at(ms, i);
4351           p = b->fd;
4352           assert(chunksize(p) == small_index2size(i));
4353           unlink_first_small_chunk(ms, b, p, i);
4354           rsize = small_index2size(i) - nb;
4355           /* Fit here cannot be remainderless if 4byte sizes */
4356           if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4357             set_inuse_and_pinuse(ms, p, small_index2size(i));
4358           else {
4359             set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4360             r = chunk_plus_offset(p, nb);
4361             set_size_and_pinuse_of_free_chunk(r, rsize);
4362             replace_dv(ms, r, rsize);
4363           }
4364           mem = chunk2mem(p);
4365           check_malloced_chunk(ms, mem, nb);
4366           goto postaction;
4367         }
4368
4369         else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
4370           check_malloced_chunk(ms, mem, nb);
4371           goto postaction;
4372         }
4373       }
4374     }
4375     else if (bytes >= MAX_REQUEST)
4376       nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
4377     else {
4378       nb = pad_request(bytes);
4379       if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
4380         check_malloced_chunk(ms, mem, nb);
4381         goto postaction;
4382       }
4383     }
4384
4385     if (nb <= ms->dvsize) {
4386       size_t rsize = ms->dvsize - nb;
4387       mchunkptr p = ms->dv;
4388       if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4389         mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
4390         ms->dvsize = rsize;
4391         set_size_and_pinuse_of_free_chunk(r, rsize);
4392         set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4393       }
4394       else { /* exhaust dv */
4395         size_t dvs = ms->dvsize;
4396         ms->dvsize = 0;
4397         ms->dv = 0;
4398         set_inuse_and_pinuse(ms, p, dvs);
4399       }
4400       mem = chunk2mem(p);
4401       check_malloced_chunk(ms, mem, nb);
4402       goto postaction;
4403     }
4404
4405     else if (nb < ms->topsize) { /* Split top */
4406       size_t rsize = ms->topsize -= nb;
4407       mchunkptr p = ms->top;
4408       mchunkptr r = ms->top = chunk_plus_offset(p, nb);
4409       r->head = rsize | PINUSE_BIT;
4410       set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4411       mem = chunk2mem(p);
4412       check_top_chunk(ms, ms->top);
4413       check_malloced_chunk(ms, mem, nb);
4414       goto postaction;
4415     }
4416
4417     mem = sys_alloc(ms, nb);
4418
4419   postaction:
4420     POSTACTION(ms);
4421     return mem;
4422   }
4423
4424   return 0;
4425 }
4426
4427 void mspace_free(mspace msp, void* mem) {
4428   if (mem != 0) {
4429     mchunkptr p  = mem2chunk(mem);
4430 #if FOOTERS
4431     mstate fm = get_mstate_for(p);
4432     (void)msp; /* placate people compiling -Wunused */
4433 #else /* FOOTERS */
4434     mstate fm = (mstate)msp;
4435 #endif /* FOOTERS */
4436     if (!ok_magic(fm)) {
4437       USAGE_ERROR_ACTION(fm, p);
4438       return;
4439     }
4440     if (!PREACTION(fm)) {
4441       check_inuse_chunk(fm, p);
4442       if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
4443         size_t psize = chunksize(p);
4444         mchunkptr next = chunk_plus_offset(p, psize);
4445         if (!pinuse(p)) {
4446           size_t prevsize = p->prev_foot;
4447           if (is_mmapped(p)) {
4448             psize += prevsize + MMAP_FOOT_PAD;
4449             if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4450               fm->footprint -= psize;
4451             goto postaction;
4452           }
4453           else {
4454             mchunkptr prev = chunk_minus_offset(p, prevsize);
4455             psize += prevsize;
4456             p = prev;
4457             if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4458               if (p != fm->dv) {
4459                 unlink_chunk(fm, p, prevsize);
4460               }
4461               else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4462                 fm->dvsize = psize;
4463                 set_free_with_pinuse(p, psize, next);
4464                 goto postaction;
4465               }
4466             }
4467             else
4468               goto erroraction;
4469           }
4470         }
4471
4472         if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4473           if (!cinuse(next)) {  /* consolidate forward */
4474             if (next == fm->top) {
4475               size_t tsize = fm->topsize += psize;
4476               fm->top = p;
4477               p->head = tsize | PINUSE_BIT;
4478               if (p == fm->dv) {
4479                 fm->dv = 0;
4480                 fm->dvsize = 0;
4481               }
4482               if (should_trim(fm, tsize))
4483                 sys_trim(fm, 0);
4484               goto postaction;
4485             }
4486             else if (next == fm->dv) {
4487               size_t dsize = fm->dvsize += psize;
4488               fm->dv = p;
4489               set_size_and_pinuse_of_free_chunk(p, dsize);
4490               goto postaction;
4491             }
4492             else {
4493               size_t nsize = chunksize(next);
4494               psize += nsize;
4495               unlink_chunk(fm, next, nsize);
4496               set_size_and_pinuse_of_free_chunk(p, psize);
4497               if (p == fm->dv) {
4498                 fm->dvsize = psize;
4499                 goto postaction;
4500               }
4501             }
4502           }
4503           else
4504             set_free_with_pinuse(p, psize, next);
4505
4506           if (is_small(psize)) {
4507             insert_small_chunk(fm, p, psize);
4508             check_free_chunk(fm, p);
4509           }
4510           else {
4511             tchunkptr tp = (tchunkptr)p;
4512             insert_large_chunk(fm, tp, psize);
4513             check_free_chunk(fm, p);
4514             if (--fm->release_checks == 0)
4515               release_unused_segments(fm);
4516           }
4517           goto postaction;
4518         }
4519       }
4520     erroraction:
4521       USAGE_ERROR_ACTION(fm, p);
4522     postaction:
4523       POSTACTION(fm);
4524     }
4525   }
4526 }
4527
4528 void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
4529   void* mem;
4530   size_t req = 0;
4531   mstate ms = (mstate)msp;
4532   if (!ok_magic(ms)) {
4533     USAGE_ERROR_ACTION(ms,ms);
4534     return 0;
4535   }
4536   if (n_elements != 0) {
4537     req = n_elements * elem_size;
4538     if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4539         (req / n_elements != elem_size))
4540       req = MAX_SIZE_T; /* force downstream failure on overflow */
4541   }
4542   mem = internal_malloc(ms, req);
4543   if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4544     memset(mem, 0, req);
4545   return mem;
4546 }
4547
4548 void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
4549   void* mem = 0;
4550   if (oldmem == 0) {
4551     mem = mspace_malloc(msp, bytes);
4552   }
4553   else if (bytes >= MAX_REQUEST) {
4554     MALLOC_FAILURE_ACTION;
4555   }
4556 #ifdef REALLOC_ZERO_BYTES_FREES
4557   else if (bytes == 0) {
4558     mspace_free(msp, oldmem);
4559   }
4560 #endif /* REALLOC_ZERO_BYTES_FREES */
4561   else {
4562     size_t nb = request2size(bytes);
4563     mchunkptr oldp = mem2chunk(oldmem);
4564 #if ! FOOTERS
4565     mstate m = (mstate)msp;
4566 #else /* FOOTERS */
4567     mstate m = get_mstate_for(oldp);
4568     if (!ok_magic(m)) {
4569       USAGE_ERROR_ACTION(m, oldmem);
4570       return 0;
4571     }
4572 #endif /* FOOTERS */
4573     if (!PREACTION(m)) {
4574       mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1);
4575       POSTACTION(m);
4576       if (newp != 0) {
4577         check_inuse_chunk(m, newp);
4578         mem = chunk2mem(newp);
4579       }
4580       else {
4581         mem = mspace_malloc(m, bytes);
4582         if (mem != 0) {
4583           size_t oc = chunksize(oldp) - overhead_for(oldp);
4584           memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
4585           mspace_free(m, oldmem);
4586         }
4587       }
4588     }
4589   }
4590   return mem;
4591 }
4592
4593 void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) {
4594   void* mem = 0;
4595   if (oldmem != 0) {
4596     if (bytes >= MAX_REQUEST) {
4597       MALLOC_FAILURE_ACTION;
4598     }
4599     else {
4600       size_t nb = request2size(bytes);
4601       mchunkptr oldp = mem2chunk(oldmem);
4602 #if ! FOOTERS
4603       mstate m = (mstate)msp;
4604 #else /* FOOTERS */
4605       mstate m = get_mstate_for(oldp);
4606       (void)msp; /* placate people compiling -Wunused */
4607       if (!ok_magic(m)) {
4608         USAGE_ERROR_ACTION(m, oldmem);
4609         return 0;
4610       }
4611 #endif /* FOOTERS */
4612       if (!PREACTION(m)) {
4613         mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0);
4614         POSTACTION(m);
4615         if (newp == oldp) {
4616           check_inuse_chunk(m, newp);
4617           mem = oldmem;
4618         }
4619       }
4620     }
4621   }
4622   return mem;
4623 }
4624
4625 void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
4626   mstate ms = (mstate)msp;
4627   if (!ok_magic(ms)) {
4628     USAGE_ERROR_ACTION(ms,ms);
4629     return 0;
4630   }
4631   if (alignment <= MALLOC_ALIGNMENT)
4632     return mspace_malloc(msp, bytes);
4633   return internal_memalign(ms, alignment, bytes);
4634 }
4635
4636 void** mspace_independent_calloc(mspace msp, size_t n_elements,
4637                                  size_t elem_size, void* chunks[]) {
4638   size_t sz = elem_size; /* serves as 1-element array */
4639   mstate ms = (mstate)msp;
4640   if (!ok_magic(ms)) {
4641     USAGE_ERROR_ACTION(ms,ms);
4642     return 0;
4643   }
4644   return ialloc(ms, n_elements, &sz, 3, chunks);
4645 }
4646
4647 void** mspace_independent_comalloc(mspace msp, size_t n_elements,
4648                                    size_t sizes[], void* chunks[]) {
4649   mstate ms = (mstate)msp;
4650   if (!ok_magic(ms)) {
4651     USAGE_ERROR_ACTION(ms,ms);
4652     return 0;
4653   }
4654   return ialloc(ms, n_elements, sizes, 0, chunks);
4655 }
4656
4657 size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) {
4658   return internal_bulk_free((mstate)msp, array, nelem);
4659 }
4660
4661 #if MALLOC_INSPECT_ALL
4662 void mspace_inspect_all(mspace msp,
4663                         void(*handler)(void *start,
4664                                        void *end,
4665                                        size_t used_bytes,
4666                                        void* callback_arg),
4667                         void* arg) {
4668   mstate ms = (mstate)msp;
4669   if (ok_magic(ms)) {
4670     if (!PREACTION(ms)) {
4671       internal_inspect_all(ms, handler, arg);
4672       POSTACTION(ms);
4673     }
4674   }
4675   else {
4676     USAGE_ERROR_ACTION(ms,ms);
4677   }
4678 }
4679 #endif /* MALLOC_INSPECT_ALL */
4680
4681 int mspace_trim(mspace msp, size_t pad) {
4682   int result = 0;
4683   mstate ms = (mstate)msp;
4684   if (ok_magic(ms)) {
4685     if (!PREACTION(ms)) {
4686       result = sys_trim(ms, pad);
4687       POSTACTION(ms);
4688     }
4689   }
4690   else {
4691     USAGE_ERROR_ACTION(ms,ms);
4692   }
4693   return result;
4694 }
4695
4696 #if !NO_MALLOC_STATS
4697 void mspace_malloc_stats(mspace msp) {
4698   mstate ms = (mstate)msp;
4699   if (ok_magic(ms)) {
4700     internal_malloc_stats(ms);
4701   }
4702   else {
4703     USAGE_ERROR_ACTION(ms,ms);
4704   }
4705 }
4706 #endif /* NO_MALLOC_STATS */
4707
4708 size_t mspace_footprint(mspace msp) {
4709   size_t result = 0;
4710   mstate ms = (mstate)msp;
4711   if (ok_magic(ms)) {
4712     result = ms->footprint;
4713   }
4714   else {
4715     USAGE_ERROR_ACTION(ms,ms);
4716   }
4717   return result;
4718 }
4719
4720 size_t mspace_max_footprint(mspace msp) {
4721   size_t result = 0;
4722   mstate ms = (mstate)msp;
4723   if (ok_magic(ms)) {
4724     result = ms->max_footprint;
4725   }
4726   else {
4727     USAGE_ERROR_ACTION(ms,ms);
4728   }
4729   return result;
4730 }
4731
4732 size_t mspace_footprint_limit(mspace msp) {
4733   size_t result = 0;
4734   mstate ms = (mstate)msp;
4735   if (ok_magic(ms)) {
4736     size_t maf = ms->footprint_limit;
4737     result = (maf == 0) ? MAX_SIZE_T : maf;
4738   }
4739   else {
4740     USAGE_ERROR_ACTION(ms,ms);
4741   }
4742   return result;
4743 }
4744
4745 size_t mspace_set_footprint_limit(mspace msp, size_t bytes) {
4746   size_t result = 0;
4747   mstate ms = (mstate)msp;
4748   if (ok_magic(ms)) {
4749     if (bytes == 0)
4750       result = granularity_align(1); /* Use minimal size */
4751     if (bytes == MAX_SIZE_T)
4752       result = 0;                    /* disable */
4753     else
4754       result = granularity_align(bytes);
4755     ms->footprint_limit = result;
4756   }
4757   else {
4758     USAGE_ERROR_ACTION(ms,ms);
4759   }
4760   return result;
4761 }
4762
4763 #if !NO_MALLINFO
4764 struct mallinfo mspace_mallinfo(mspace msp) {
4765   mstate ms = (mstate)msp;
4766   if (!ok_magic(ms)) {
4767     USAGE_ERROR_ACTION(ms,ms);
4768   }
4769   return internal_mallinfo(ms);
4770 }
4771 #endif /* NO_MALLINFO */
4772
4773 size_t mspace_usable_size(const void* mem) {
4774   if (mem != 0) {
4775     mchunkptr p = mem2chunk(mem);
4776     if (is_inuse(p))
4777       return chunksize(p) - overhead_for(p);
4778   }
4779   return 0;
4780 }
4781
4782 int mspace_mallopt(int param_number, int value) {
4783   return change_mparam(param_number, value);
4784 }
4785
4786 #endif /* MSPACES */
4787
4788
4789 /* -------------------- Alternative MORECORE functions ------------------- */
4790
4791 /*
4792   Guidelines for creating a custom version of MORECORE:
4793
4794   * For best performance, MORECORE should allocate in multiples of pagesize.
4795   * MORECORE may allocate more memory than requested. (Or even less,
4796       but this will usually result in a malloc failure.)
4797   * MORECORE must not allocate memory when given argument zero, but
4798       instead return one past the end address of memory from previous
4799       nonzero call.
4800   * For best performance, consecutive calls to MORECORE with positive
4801       arguments should return increasing addresses, indicating that
4802       space has been contiguously extended.
4803   * Even though consecutive calls to MORECORE need not return contiguous
4804       addresses, it must be OK for malloc'ed chunks to span multiple
4805       regions in those cases where they do happen to be contiguous.
4806   * MORECORE need not handle negative arguments -- it may instead
4807       just return MFAIL when given negative arguments.
4808       Negative arguments are always multiples of pagesize. MORECORE
4809       must not misinterpret negative args as large positive unsigned
4810       args. You can suppress all such calls from even occurring by defining
4811       MORECORE_CANNOT_TRIM,
4812
4813   As an example alternative MORECORE, here is a custom allocator
4814   kindly contributed for pre-OSX macOS.  It uses virtually but not
4815   necessarily physically contiguous non-paged memory (locked in,
4816   present and won't get swapped out).  You can use it by uncommenting
4817   this section, adding some #includes, and setting up the appropriate
4818   defines above:
4819
4820       #define MORECORE osMoreCore
4821
4822   There is also a shutdown routine that should somehow be called for
4823   cleanup upon program exit.
4824
4825   #define MAX_POOL_ENTRIES 100
4826   #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
4827   static int next_os_pool;
4828   void *our_os_pools[MAX_POOL_ENTRIES];
4829
4830   void *osMoreCore(int size)
4831   {
4832     void *ptr = 0;
4833     static void *sbrk_top = 0;
4834
4835     if (size > 0)
4836     {
4837       if (size < MINIMUM_MORECORE_SIZE)
4838          size = MINIMUM_MORECORE_SIZE;
4839       if (CurrentExecutionLevel() == kTaskLevel)
4840          ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
4841       if (ptr == 0)
4842       {
4843         return (void *) MFAIL;
4844       }
4845       // save ptrs so they can be freed during cleanup
4846       our_os_pools[next_os_pool] = ptr;
4847       next_os_pool++;
4848       ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
4849       sbrk_top = (char *) ptr + size;
4850       return ptr;
4851     }
4852     else if (size < 0)
4853     {
4854       // we don't currently support shrink behavior
4855       return (void *) MFAIL;
4856     }
4857     else
4858     {
4859       return sbrk_top;
4860     }
4861   }
4862
4863   // cleanup any allocated memory pools
4864   // called as last thing before shutting down driver
4865
4866   void osCleanupMem(void)
4867   {
4868     void **ptr;
4869
4870     for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
4871       if (*ptr)
4872       {
4873          PoolDeallocate(*ptr);
4874          *ptr = 0;
4875       }
4876   }
4877
4878 */
4879
4880
4881 /* -----------------------------------------------------------------------
4882 History:
4883     v2.8.6 Wed Aug 29 06:57:58 2012  Doug Lea
4884       * fix bad comparison in dlposix_memalign
4885       * don't reuse adjusted asize in sys_alloc
4886       * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion
4887       * reduce compiler warnings -- thanks to all who reported/suggested these
4888
4889     v2.8.5 Sun May 22 10:26:02 2011  Doug Lea  (dl at gee)
4890       * Always perform unlink checks unless INSECURE
4891       * Add posix_memalign.
4892       * Improve realloc to expand in more cases; expose realloc_in_place.
4893         Thanks to Peter Buhr for the suggestion.
4894       * Add footprint_limit, inspect_all, bulk_free. Thanks
4895         to Barry Hayes and others for the suggestions.
4896       * Internal refactorings to avoid calls while holding locks
4897       * Use non-reentrant locks by default. Thanks to Roland McGrath
4898         for the suggestion.
4899       * Small fixes to mspace_destroy, reset_on_error.
4900       * Various configuration extensions/changes. Thanks
4901          to all who contributed these.
4902
4903     V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu)
4904       * Update Creative Commons URL
4905
4906     V2.8.4 Wed May 27 09:56:23 2009  Doug Lea  (dl at gee)
4907       * Use zeros instead of prev foot for is_mmapped
4908       * Add mspace_track_large_chunks; thanks to Jean Brouwers
4909       * Fix set_inuse in internal_realloc; thanks to Jean Brouwers
4910       * Fix insufficient sys_alloc padding when using 16byte alignment
4911       * Fix bad error check in mspace_footprint
4912       * Adaptations for ptmalloc; thanks to Wolfram Gloger.
4913       * Reentrant spin locks; thanks to Earl Chew and others
4914       * Win32 improvements; thanks to Niall Douglas and Earl Chew
4915       * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options
4916       * Extension hook in malloc_state
4917       * Various small adjustments to reduce warnings on some compilers
4918       * Various configuration extensions/changes for more platforms. Thanks
4919          to all who contributed these.
4920
4921     V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
4922       * Add max_footprint functions
4923       * Ensure all appropriate literals are size_t
4924       * Fix conditional compilation problem for some #define settings
4925       * Avoid concatenating segments with the one provided
4926         in create_mspace_with_base
4927       * Rename some variables to avoid compiler shadowing warnings
4928       * Use explicit lock initialization.
4929       * Better handling of sbrk interference.
4930       * Simplify and fix segment insertion, trimming and mspace_destroy
4931       * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
4932       * Thanks especially to Dennis Flanagan for help on these.
4933
4934     V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
4935       * Fix memalign brace error.
4936
4937     V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
4938       * Fix improper #endif nesting in C++
4939       * Add explicit casts needed for C++
4940
4941     V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
4942       * Use trees for large bins
4943       * Support mspaces
4944       * Use segments to unify sbrk-based and mmap-based system allocation,
4945         removing need for emulation on most platforms without sbrk.
4946       * Default safety checks
4947       * Optional footer checks. Thanks to William Robertson for the idea.
4948       * Internal code refactoring
4949       * Incorporate suggestions and platform-specific changes.
4950         Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
4951         Aaron Bachmann,  Emery Berger, and others.
4952       * Speed up non-fastbin processing enough to remove fastbins.
4953       * Remove useless cfree() to avoid conflicts with other apps.
4954       * Remove internal memcpy, memset. Compilers handle builtins better.
4955       * Remove some options that no one ever used and rename others.
4956
4957     V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
4958       * Fix malloc_state bitmap array misdeclaration
4959
4960     V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
4961       * Allow tuning of FIRST_SORTED_BIN_SIZE
4962       * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
4963       * Better detection and support for non-contiguousness of MORECORE.
4964         Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
4965       * Bypass most of malloc if no frees. Thanks To Emery Berger.
4966       * Fix freeing of old top non-contiguous chunk im sysmalloc.
4967       * Raised default trim and map thresholds to 256K.
4968       * Fix mmap-related #defines. Thanks to Lubos Lunak.
4969       * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
4970       * Branch-free bin calculation
4971       * Default trim and mmap thresholds now 256K.
4972
4973     V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
4974       * Introduce independent_comalloc and independent_calloc.
4975         Thanks to Michael Pachos for motivation and help.
4976       * Make optional .h file available
4977       * Allow > 2GB requests on 32bit systems.
4978       * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
4979         Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
4980         and Anonymous.
4981       * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
4982         helping test this.)
4983       * memalign: check alignment arg
4984       * realloc: don't try to shift chunks backwards, since this
4985         leads to  more fragmentation in some programs and doesn't
4986         seem to help in any others.
4987       * Collect all cases in malloc requiring system memory into sysmalloc
4988       * Use mmap as backup to sbrk
4989       * Place all internal state in malloc_state
4990       * Introduce fastbins (although similar to 2.5.1)
4991       * Many minor tunings and cosmetic improvements
4992       * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
4993       * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
4994         Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
4995       * Include errno.h to support default failure action.
4996
4997     V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
4998       * return null for negative arguments
4999       * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
5000          * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
5001           (e.g. WIN32 platforms)
5002          * Cleanup header file inclusion for WIN32 platforms
5003          * Cleanup code to avoid Microsoft Visual C++ compiler complaints
5004          * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
5005            memory allocation routines
5006          * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
5007          * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
5008            usage of 'assert' in non-WIN32 code
5009          * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
5010            avoid infinite loop
5011       * Always call 'fREe()' rather than 'free()'
5012
5013     V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
5014       * Fixed ordering problem with boundary-stamping
5015
5016     V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
5017       * Added pvalloc, as recommended by H.J. Liu
5018       * Added 64bit pointer support mainly from Wolfram Gloger
5019       * Added anonymously donated WIN32 sbrk emulation
5020       * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
5021       * malloc_extend_top: fix mask error that caused wastage after
5022         foreign sbrks
5023       * Add linux mremap support code from HJ Liu
5024
5025     V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
5026       * Integrated most documentation with the code.
5027       * Add support for mmap, with help from
5028         Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5029       * Use last_remainder in more cases.
5030       * Pack bins using idea from  colin@nyx10.cs.du.edu
5031       * Use ordered bins instead of best-fit threshhold
5032       * Eliminate block-local decls to simplify tracing and debugging.
5033       * Support another case of realloc via move into top
5034       * Fix error occuring when initial sbrk_base not word-aligned.
5035       * Rely on page size for units instead of SBRK_UNIT to
5036         avoid surprises about sbrk alignment conventions.
5037       * Add mallinfo, mallopt. Thanks to Raymond Nijssen
5038         (raymond@es.ele.tue.nl) for the suggestion.
5039       * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
5040       * More precautions for cases where other routines call sbrk,
5041         courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5042       * Added macros etc., allowing use in linux libc from
5043         H.J. Lu (hjl@gnu.ai.mit.edu)
5044       * Inverted this history list
5045
5046     V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
5047       * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
5048       * Removed all preallocation code since under current scheme
5049         the work required to undo bad preallocations exceeds
5050         the work saved in good cases for most test programs.
5051       * No longer use return list or unconsolidated bins since
5052         no scheme using them consistently outperforms those that don't
5053         given above changes.
5054       * Use best fit for very large chunks to prevent some worst-cases.
5055       * Added some support for debugging
5056
5057     V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
5058       * Removed footers when chunks are in use. Thanks to
5059         Paul Wilson (wilson@cs.texas.edu) for the suggestion.
5060
5061     V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
5062       * Added malloc_trim, with help from Wolfram Gloger
5063         (wmglo@Dent.MED.Uni-Muenchen.DE).
5064
5065     V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
5066
5067     V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
5068       * realloc: try to expand in both directions
5069       * malloc: swap order of clean-bin strategy;
5070       * realloc: only conditionally expand backwards
5071       * Try not to scavenge used bins
5072       * Use bin counts as a guide to preallocation
5073       * Occasionally bin return list chunks in first scan
5074       * Add a few optimizations from colin@nyx10.cs.du.edu
5075
5076     V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
5077       * faster bin computation & slightly different binning
5078       * merged all consolidations to one part of malloc proper
5079          (eliminating old malloc_find_space & malloc_clean_bin)
5080       * Scan 2 returns chunks (not just 1)
5081       * Propagate failure in realloc if malloc returns 0
5082       * Add stuff to allow compilation on non-ANSI compilers
5083           from kpv@research.att.com
5084
5085     V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
5086       * removed potential for odd address access in prev_chunk
5087       * removed dependency on getpagesize.h
5088       * misc cosmetics and a bit more internal documentation
5089       * anticosmetics: mangled names in macros to evade debugger strangeness
5090       * tested on sparc, hp-700, dec-mips, rs6000
5091           with gcc & native cc (hp, dec only) allowing
5092           Detlefs & Zorn comparison study (in SIGPLAN Notices.)
5093
5094     Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
5095       * Based loosely on libg++-1.2X malloc. (It retains some of the overall
5096          structure of old version,  but most details differ.)
5097
5098 */