1 /* DistriNet malloc (dnmalloc): a more secure memory allocator.
2    Copyright (C) 2005, Yves Younan, Wouter Joosen, Frank Piessens
3    and Rainer Wichmann
4 
5    The authors can be contacted by:
6       Email: dnmalloc@fort-knox.org
7       Address:
8 #if defined(WITH_TPT)
9       	     Yves Younan
10       	     Celestijnenlaan 200A
11       	     B-3001 Heverlee
12       	     Belgium
13 
14    This library is free software; you can redistribute it and/or
15    modify it under the terms of the GNU Lesser General Public
16    License as published by the Free Software Foundation; either
17    version 2.1 of the License, or (at your option) any later version.
18 
19    This library is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    Lesser General Public License for more details.
23 
24    You should have received a copy of the GNU Lesser General Public
25    License along with this library; if not, write to the Free Software
26    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
27 
28 */
29 
30 /* Current version: dnmalloc 1.0 */
31 /* Includes arc4random from OpenBSD, which is under the BDS license     */
32 
33 /* Versions:
34    0.1-0.5:
35    Proof of concept implementation by Hans Van den Eynden and Yves Younan
36    0.6-0.7:
37    Bug fixes by Yves Younan
38    0.8-1.0.beta4:
39    Reimplementation from scratch by Yves Younan
40    1.0.beta4:
41    Public release
42    1.0.beta5:
43    Prev_chunkinfo speeded up, was really slow because of the way we did lookups
44    A freechunkinfo region is now freed when it is completely empty and
45    not the current one
46 
47    1.0 (Rainer Wichmann [support at la dash samhna dot org]):
48    ---------------------
49 
50    Compiler warnings fixed
51    Define REALLOC_ZERO_BYTES_FREES because it's what GNU libc does
52        (and what the standard says)
53    Removed unused code
54    Fix       assert(aligned_OK(chunk(newp)));
55          ->  assert(aligned_OK(chunk(oldp)));
56    Fix statistics in sYSMALLOc
57    Fix overwrite of av->top in sYSMALLOc
58    Provide own assert(), glibc assert() doesn't work (calls malloc)
59    Fix bug in mEMALIGn(), put remainder in hashtable before calling fREe
60    Remove cfree, independent_cmalloc, independent_comalloc (untested
61        public functions not covered by any standard)
62    Provide posix_memalign (that one is in the standard)
63    Move the malloc_state struct to mmapped memory protected by guard pages
64    Add arc4random function to initialize random canary on startup
65    Implement random canary at end of (re|m)alloced/memaligned buffer,
66        check at free/realloc
67    Remove code conditional on !HAVE_MMAP, since mmap is required anyway.
68    Use standard HAVE_foo macros (as generated by autoconf) instead of LACKS_foo
69 
70    Profiling: Reorder branches in hashtable_add, next_chunkinfo,
71                   prev_chunkinfo, hashtable_insert, mALLOc, fREe, request2size,
72 	          checked_request2size (gcc predicts if{} branch to be taken).
73 	      Use UNLIKELY macro (gcc __builtin_expect()) where branch
74                   reordering would make the code awkward.
75 
76    Portability: Hashtable always covers full 32bit address space to
77                 avoid assumptions about memory layout.
78    Portability: Try hard to enforce mapping of mmapped memory into
79                 32bit address space, even on 64bit systems.
80    Portability: Provide a dnmalloc_pthread_init() function, since
81                 pthread locking on HP-UX only works if initialized
82 		after the application has entered main().
83    Portability: On *BSD, pthread_mutex_lock is unusable since it
84                 calls malloc, use spinlocks instead.
85    Portability: Dynamically detect whether the heap is within
86                 32bit address range (e.g. on Linux x86_64, it isn't).
87 		Don't use sbrk() if the heap is mapped to an address
88 		outside the 32bit range, since this doesn't work with
89 		the hashtable. New macro morecore32bit.
90 
91    Success on: HP-UX 11.11/pthread, Linux/pthread (32/64 bit),
92                FreeBSD/pthread, and Solaris 10 i386/pthread.
93    Fail    on: OpenBSD/pthread (in  _thread_machdep_save_float_state),
94                might be related to OpenBSD pthread internals (??).
95 	       Non-treaded version (#undef USE_MALLOC_LOCK)
96 	       works on OpenBSD.
97 
98    further to 1.0:
99    Valgrind client requests inserted (#define USE_VALGRIND)
100    Fix: malloc_consolidate (nextchunk->fd, nextchunk->bck may be NULL)
101    Portability: minsize = 32 bit on 64bit architecture
102    Minor cleanups
103    Fix: eliminate prototypes for memset, memcpy (they're in string.h)
104    Fix: one more malloc_consolidate segfault
105 
106    There may be some bugs left in this version. please use with caution.
107 */
108 
109 
110 
111 /* Please read the following papers for documentation:
112 
113    Yves Younan, Wouter Joosen, and Frank Piessens, A Methodology for Designing
114    Countermeasures against Current and Future Code Injection Attacks,
115    Proceedings of the Third IEEE International Information Assurance
116    Workshop 2005 (IWIA2005), College Park, Maryland, U.S.A., March 2005,
117    IEEE, IEEE Press.
118    http://www.fort-knox.org/younany_countermeasures.pdf
119 
120    Yves Younan, Wouter Joosen and Frank Piessens and Hans Van den
121    Eynden. Security of Memory Allocators for C and C++. Technical Report
122    CW419, Departement Computerwetenschappen, Katholieke Universiteit
123    Leuven, July 2005. http://www.fort-knox.org/CW419.pdf
124 
125  */
126 
127 /* Compile:
128    gcc -fPIC -rdynamic -c -Wall dnmalloc-portable.c
129    "Link":
130    Dynamic:
131    gcc -shared -Wl,-soname,libdnmalloc.so.0 -o libdnmalloc.so.0.0 dnmalloc-portable.o -lc
132    Static:
133    ar -rv libdnmalloc.a dnmalloc-portable.o
134 
135 */
136 
137 /*
138    dnmalloc is based on dlmalloc 2.7.2 (by Doug Lea (dl@cs.oswego.edu))
139    dlmalloc was released as public domain and contained the following license:
140 
141    "This is a version (aka dlmalloc) of malloc/free/realloc written by
142    Doug Lea and released to the public domain.  Use, modify, and
143    redistribute this code without permission or acknowledgement in any
144    way you wish.  Send questions, comments, complaints, performance
145    data, etc to dl@cs.oswego.edu
146 
147    * VERSION 2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
148 
149    Note: There may be an updated version of this malloc obtainable at
150    ftp://gee.cs.oswego.edu/pub/misc/malloc.c
151    Check before installing!"
152 
153 */
154 
155 /* The following preprocessor macros are tested,
156  *   and hence should have #define directives:
157  *
158  *   HAVE_CONFIG_H    Define to #include "config.h" (autoconf-generated)
159  *
160  *   HAVE_UNISTD_H    Define to #include <unistd.h>
161  *
162  *   HAVE_SYS_UIO_H   Define to #include <sys/uio.h> (for writev)
163  *   HAVE_WRITEV      Define if the 'writev' function is available
164  *
165  *   HAVE_SYS_PARAM_H Define to #include <sys/param.h> (for pagesize)
166  *
167  *   HAVE_MALLOC_H    Define to #include <malloc.h> (for struct mallinfo)
168  *
169  *   HAVE_FCNTL_H     Define to #include <fcntl.h>
170  *
171  *   HAVE_SYS_MMAN_H  Define to #include <sys/mman.h>
172  *   HAVE_MMAP        Define if the 'mmap' function is available.
173  *
174  *   HAVE_SCHED_H     Define to #include <sched.h>
175  *   HAVE_SCHED_YIELD Define id the 'sched_yield' function is available
176  */
177 
178 
179 /*
180   __STD_C should be nonzero if using ANSI-standard C compiler, a C++
181   compiler, or a C compiler sufficiently close to ANSI to get away
182   with it.
183 */
184 
185 #ifdef HAVE_CONFIG_H
186 #include "config.h"
187 #endif
188 
189 #ifdef USE_VALGRIND
190 #include <valgrind/memcheck.h>
191 #else
192 #define VALGRIND_FREELIKE_BLOCK(a,b)       ((void)0)
193 #define VALGRIND_MALLOCLIKE_BLOCK(a,b,c,d) ((void)0)
194 #define VALGRIND_CREATE_MEMPOOL(a,b,c)     ((void)0)
195 #define VALGRIND_MEMPOOL_ALLOC(a,b,c)      ((void)0)
196 #define VALGRIND_MEMPOOL_FREE(a,b)         ((void)0)
197 #define VALGRIND_DESTROY_MEMPOOL(a)        ((void)0)
198 #define VALGRIND_MAKE_MEM_DEFINED(a,b)     ((void)0)
199 #define VALGRIND_MAKE_MEM_UNDEFINED(a,b)   ((void)0)
200 #define VALGRIND_MAKE_MEM_NOACCESS(a,b)    ((void)0)
201 #endif
202 
203 #if defined (__GNUC__) && __GNUC__ > 2
204 # define LIKELY(expression) (__builtin_expect(!!(expression), 1))
205 # define UNLIKELY(expression) (__builtin_expect(!!(expression), 0))
206 # define __attribute_malloc__ __attribute__ ((__malloc__))
207 #else
208 # define LIKELY(x)       (x)
209 # define UNLIKELY(x)     (x)
210 # define __attribute_malloc__ /* Ignore */
211 #endif
212 
213 /*
214   Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
215   large blocks.  This is currently only possible on Linux with
216   kernel versions newer than 1.3.77.
217 */
218 
219 #ifndef HAVE_MREMAP
220 #ifdef linux
221 #define HAVE_MREMAP 1
222 #define _GNU_SOURCE 1
223 #else
224 #define HAVE_MREMAP 0
225 #endif
226 #endif /* HAVE_MREMAP */
227 
228 
229 
230 #ifndef __STD_C
231 #if defined(__STDC__) || defined(_cplusplus)
232 #define __STD_C     1
233 #else
234 #define __STD_C     0
235 #endif
236 #endif /*__STD_C*/
237 
238 
239 /*
240   Void_t* is the pointer type that malloc should say it returns
241 */
242 
243 #ifndef Void_t
244 #if (__STD_C || defined(WIN32))
245 #define Void_t      void
246 #else
247 #define Void_t      char
248 #endif
249 #endif /*Void_t*/
250 
251 #if __STD_C
252 #include <stddef.h>   /* for size_t */
253 #else
254 #include <sys/types.h>
255 #endif
256 
257 #if !defined(USE_SYSTEM_MALLOC)
258 
259 #ifdef __cplusplus
260 extern "C" {
261 #endif
262 
263 /* define HAVE_UNISTD_H if your system has a <unistd.h>. */
264 
265 #ifdef HAVE_UNISTD_H
266 #include <unistd.h>
267 #endif
268 
269 #ifdef HAVE_SYS_UIO_H
270 #include <sys/uio.h>
271 #endif
272 
273 #include <stdio.h>    /* needed for malloc_stats */
274 #include <errno.h>    /* needed for optional MALLOC_FAILURE_ACTION */
275 
276 #include <string.h>
277 #include <stdlib.h>
278 
279 #include <sys/resource.h>
280 
281 extern int errno;
282 
283   /* 0: lazy,
284    * 1: medium (assertions compiled in),
285    * 2: high (guard pages at end of hash table and ciregions)
286    * 3: paranoid (guards at end of each allocated chunk, check at free)
287    */
288 #ifndef PARANOIA
289 #define PARANOIA 9
290 #endif
291 
292   /* Using assert() with multithreading will cause the code
293    * to deadlock since glibc __assert_fail will call malloc().
294    * We need our very own assert().
295    */
296 typedef void assert_handler_tp(const char * error, const char *file, int line);
297 
298 #if  PARANOIA > 0
299 
300 #ifdef NDEBUG
301 #undef NDEBUG
302 #endif
303 
default_assert_handler(const char * error,const char * file,int line)304 static void default_assert_handler(const char *error,
305 				   const char *file, int line)
306 {
307 #ifdef HAVE_WRITEV
308   struct iovec iov[5];
309   char * i1 = "assertion failed (";
310   char * i3 = "): ";
311   char * i5 = "\n";
312   int    res = 0;
313   char   ifile[128];
314   char   ierr[128];
315 
316   strncpy(ifile, file, sizeof(ifile)); ifile[sizeof(ifile)-1] = '\0';
317   strncpy(ierr, error, sizeof(ierr));  ierr[sizeof(ierr)-1]   = '\0';
318 
319   iov[0].iov_base = i1;     iov[0].iov_len = strlen(i1);
320   iov[1].iov_base = ifile;  iov[1].iov_len = strlen(ifile);
321   iov[2].iov_base = i3;     iov[2].iov_len = strlen(i3);
322   iov[3].iov_base = ierr;   iov[3].iov_len = strlen(ierr);
323   iov[4].iov_base = i5;     iov[4].iov_len = strlen(i5);
324   do {
325     res = writev(STDERR_FILENO, iov, 5);
326   } while (res < 0 && errno == EINTR);
327 #else
328   fputs("assertion failed (", stderr);
329   fputs(file, stderr);
330   fputs("): ", stderr);
331   fputs(error, stderr);
332   fputc('\n', stderr);
333 #endif
334   (void) line;
335   abort();
336 }
337 static assert_handler_tp *assert_handler = default_assert_handler;
338 
339 
340 #define assert(x)                               \
341   do {		                                \
342     if (UNLIKELY(!(x))) {			\
343       assert_handler(#x, __FILE__, __LINE__);	\
344     }                                           \
345   } while (0)
346 
347 #else
348 
349 static assert_handler_tp *assert_handler = NULL;
350 #ifndef NDEBUG
351 #define NDEBUG
352 #endif
353 #define assert(x) ((void)0)
354 
355 #endif
356 
dnmalloc_set_handler(assert_handler_tp * new)357 assert_handler_tp *dnmalloc_set_handler(assert_handler_tp *new)
358 {
359   assert_handler_tp *old = assert_handler;
360   assert_handler = new;
361   return old;
362 }
363 
364 
365 #include <stdarg.h>
366 
367   /* define for debugging */
368   /* #define DNMALLOC_DEBUG */
369 
370   /* Do some extra checks? if not, covered by assrt()s */
371   /* #define DNMALLOC_CHECKS */
372 
373   /*
374     The unsigned integer type used for comparing any two chunk sizes.
375     This should be at least as wide as size_t, but should not be signed.
376   */
377 
378 #ifndef CHUNK_SIZE_T
379 #define CHUNK_SIZE_T unsigned long
380 #endif
381 
382 /*
383   The unsigned integer type used to hold addresses when they are are
384   manipulated as integers. Except that it is not defined on all
385   systems, intptr_t would suffice.
386 */
387 #ifndef PTR_UINT
388 #define PTR_UINT unsigned long
389 #endif
390 
391 
392 /*
393   INTERNAL_SIZE_T is the word-size used for internal bookkeeping
394   of chunk sizes.
395 
396   The default version is the same as size_t.
397 
398   While not strictly necessary, it is best to define this as an
399   unsigned type, even if size_t is a signed type. This may avoid some
400   artificial size limitations on some systems.
401 
402   On a 64-bit machine, you may be able to reduce malloc overhead by
403   defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' at the
404   expense of not being able to handle more than 2^32 of malloced
405   space. If this limitation is acceptable, you are encouraged to set
406   this unless you are on a platform requiring 16byte alignments. In
407   this case the alignment requirements turn out to negate any
408   potential advantages of decreasing size_t word size.
409 
410   Implementors: Beware of the possible combinations of:
411      - INTERNAL_SIZE_T might be signed or unsigned, might be 32 or 64 bits,
412        and might be the same width as int or as long
413      - size_t might have different width and signedness as INTERNAL_SIZE_T
414      - int and long might be 32 or 64 bits, and might be the same width
415   To deal with this, most comparisons and difference computations
416   among INTERNAL_SIZE_Ts should cast them to CHUNK_SIZE_T, being
417   aware of the fact that casting an unsigned int to a wider long does
418   not sign-extend. (This also makes checking for negative numbers
419   awkward.) Some of these casts result in harmless compiler warnings
420   on some systems.
421 */
422 
423 #ifndef INTERNAL_SIZE_T
424 #define INTERNAL_SIZE_T size_t
425 #endif
426 
427 /* The corresponding word size */
428 #define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))
429 
430 
431 
432 /*
433   MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.
434   It must be a power of two at least 2 * SIZE_SZ, even on machines
435   for which smaller alignments would suffice. It may be defined as
436   larger than this though. Note however that code and data structures
437   are optimized for the case of 8-byte alignment.
438 */
439 
440 
441 #ifndef MALLOC_ALIGNMENT
442 #define MALLOC_ALIGNMENT       (2 * SIZE_SZ)
443 #endif
444 
445 /* The corresponding bit mask value */
446 #define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)
447 
448 
449 
450 /*
451   REALLOC_ZERO_BYTES_FREES should be set if a call to
452   realloc with zero bytes should be the same as a call to free.
453   Some people think it should. Otherwise, since this malloc
454   returns a unique pointer for malloc(0), so does realloc(p, 0).
455 */
456 
457 #define REALLOC_ZERO_BYTES_FREES
458 
459 /*
460   TRIM_FASTBINS controls whether free() of a very small chunk can
461   immediately lead to trimming. Setting to true (1) can reduce memory
462   footprint, but will almost always slow down programs that use a lot
463   of small chunks.
464 
465   Define this only if you are willing to give up some speed to more
466   aggressively reduce system-level memory footprint when releasing
467   memory in programs that use many small chunks.  You can get
468   essentially the same effect by setting MXFAST to 0, but this can
469   lead to even greater slowdowns in programs using many small chunks.
470   TRIM_FASTBINS is an in-between compile-time option, that disables
471   only those chunks bordering topmost memory from being placed in
472   fastbins.
473 */
474 
475 #ifndef TRIM_FASTBINS
476 #define TRIM_FASTBINS  0
477 #endif
478 
479 
480 /*
481   USE_DL_PREFIX will prefix all public routines with the string 'dl'.
482   This is necessary when you only want to use this malloc in one part
483   of a program, using your regular system malloc elsewhere.
484 */
485 
486 /* #define USE_DL_PREFIX */
487 
488 
489 /*
490   USE_MALLOC_LOCK causes wrapper functions to surround each
491   callable routine with pthread mutex lock/unlock.
492 
493   USE_MALLOC_LOCK forces USE_PUBLIC_MALLOC_WRAPPERS to be defined
494 */
495 
496 /* #define USE_MALLOC_LOCK */
497 
498 
499 /*
500   If USE_PUBLIC_MALLOC_WRAPPERS is defined, every public routine is
501   actually a wrapper function that first calls MALLOC_PREACTION, then
502   calls the internal routine, and follows it with
503   MALLOC_POSTACTION. This is needed for locking, but you can also use
504   this, without USE_MALLOC_LOCK, for purposes of interception,
505   instrumentation, etc. It is a sad fact that using wrappers often
506   noticeably degrades performance of malloc-intensive programs.
507 */
508 
509 
510 #ifdef USE_MALLOC_LOCK
511 #define USE_PUBLIC_MALLOC_WRAPPERS
512 #else
513 /* #define USE_PUBLIC_MALLOC_WRAPPERS */
514 #endif
515 
516 
517 /*
518    Two-phase name translation.
519    All of the actual routines are given mangled names.
520    When wrappers are used, they become the public callable versions.
521    When DL_PREFIX is used, the callable names are prefixed.
522 */
523 
524 #ifndef USE_PUBLIC_MALLOC_WRAPPERS
525 #define cALLOc      public_cALLOc
526 #define fREe        public_fREe
527 #define mALLOc      public_mALLOc
528 #define mEMALIGn    public_mEMALIGn
529 #define posix_mEMALIGn    public_posix_mEMALIGn
530 #define rEALLOc     public_rEALLOc
531 #define vALLOc      public_vALLOc
532 #define pVALLOc     public_pVALLOc
533 #define mALLINFo    public_mALLINFo
534 #define mALLOPt     public_mALLOPt
535 #define mTRIm       public_mTRIm
536 #define mSTATs      public_mSTATs
537 #define mUSABLe     public_mUSABLe
538 #endif
539 
540 #ifdef USE_DL_PREFIX
541 #define public_cALLOc    dlcalloc
542 #define public_fREe      dlfree
543 #define public_mALLOc    dlmalloc
544 #define public_mEMALIGn  dlmemalign
545 #define public_posix_mEMALIGn  dlposix_memalign
546 #define public_rEALLOc   dlrealloc
547 #define public_vALLOc    dlvalloc
548 #define public_pVALLOc   dlpvalloc
549 #define public_mALLINFo  dlmallinfo
550 #define public_mALLOPt   dlmallopt
551 #define public_mTRIm     dlmalloc_trim
552 #define public_mSTATs    dlmalloc_stats
553 #define public_mUSABLe   dlmalloc_usable_size
554 #else /* USE_DL_PREFIX */
555 #define public_cALLOc    calloc
556 #define public_fREe      free
557 #define public_mALLOc    malloc
558 #define public_mEMALIGn  memalign
559 #define public_posix_mEMALIGn  posix_memalign
560 #define public_rEALLOc   realloc
561 #define public_vALLOc    valloc
562 #define public_pVALLOc   pvalloc
563 #define public_mALLINFo  mallinfo
564 #define public_mALLOPt   mallopt
565 #define public_mTRIm     malloc_trim
566 #define public_mSTATs    malloc_stats
567 #define public_mUSABLe   malloc_usable_size
568 #endif /* USE_DL_PREFIX */
569 
570 
571 /*
572   HAVE_MEMCPY should be defined if you are not otherwise using
573   ANSI STD C, but still have memcpy and memset in your C library
574   and want to use them in calloc and realloc. Otherwise simple
575   macro versions are defined below.
576 
577   USE_MEMCPY should be defined as 1 if you actually want to
578   have memset and memcpy called. People report that the macro
579   versions are faster than libc versions on some systems.
580 
581   Even if USE_MEMCPY is set to 1, loops to copy/clear small chunks
582   (of <= 36 bytes) are manually unrolled in realloc and calloc.
583 */
584 
585 #ifndef HAVE_MEMCPY
586 #define HAVE_MEMCPY
587 #endif
588 
589 #ifndef USE_MEMCPY
590 #ifdef HAVE_MEMCPY
591 #define USE_MEMCPY 1
592 #else
593 #define USE_MEMCPY 0
594 #endif
595 #endif
596 
597 
598 #if (__STD_C || defined(HAVE_MEMCPY))
599 
600 #ifdef WIN32
601   /* On Win32 memset and memcpy are already declared in windows.h */
602 #else
603 #if __STD_C
604   /* Defined in string.h */
605 #else
606 Void_t* memset();
607 Void_t* memcpy();
608 #endif
609 #endif
610 #endif
611 
612 /*
613   MALLOC_FAILURE_ACTION is the action to take before "return 0" when
614   malloc fails to be able to return memory, either because memory is
615   exhausted or because of illegal arguments.
616 
617   By default, sets errno if running on STD_C platform, else does nothing.
618 */
619 
620 #ifndef MALLOC_FAILURE_ACTION
621 #if __STD_C
622 #define MALLOC_FAILURE_ACTION \
623    errno = ENOMEM;
624 
625 #else
626 #define MALLOC_FAILURE_ACTION
627 #endif
628 #endif
629 
630 /*
631   MORECORE-related declarations. By default, rely on sbrk
632 */
633 
634 
635 #if !defined(HAVE_UNISTD_H)
636 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
637 #if __STD_C
638 extern Void_t*     sbrk(ptrdiff_t);
639 #else
640 extern Void_t*     sbrk();
641 #endif
642 #endif
643 #endif
644 
645 /*
646   MORECORE_FAILURE is the value returned upon failure of MORECORE
647   as well as mmap. Since it cannot be an otherwise valid memory address,
648   and must reflect values of standard sys calls, you probably ought not
649   try to redefine it.
650 */
651 
652 #ifndef MORECORE_FAILURE
653 #define MORECORE_FAILURE ((void*)(-1UL))
654 #endif
655 
656 /*
657   MORECORE is the name of the routine to call to obtain more memory
658   from the system.  See below for general guidance on writing
659   alternative MORECORE functions, as well as a version for WIN32 and a
660   sample version for pre-OSX macos.
661 */
662 
663 #ifndef MORECORE
664 #define MORECORE sbrk
665 #endif
666 
667 
668 /*
669   If MORECORE_CONTIGUOUS is true, take advantage of fact that
670   consecutive calls to MORECORE with positive arguments always return
671   contiguous increasing addresses.  This is true of unix sbrk.  Even
672   if not defined, when regions happen to be contiguous, malloc will
673   permit allocations spanning regions obtained from different
674   calls. But defining this when applicable enables some stronger
675   consistency checks and space efficiencies.
676 */
677 
678 #ifndef MORECORE_CONTIGUOUS
679 #define MORECORE_CONTIGUOUS 1
680 #endif
681 
682 /*
683   Define MORECORE_CANNOT_TRIM if your version of MORECORE
684   cannot release space back to the system when given negative
685   arguments. This is generally necessary only if you are using
686   a hand-crafted MORECORE function that cannot handle negative arguments.
687 */
688 
689 /* #define MORECORE_CANNOT_TRIM */
690 
691 
692 /*
693   This malloc requires mmap for heap management data. It is an error
694   if mmap is not available.
695 
696   Additionally, mmap will be used to satisfy large requests.
697 */
698 
699 #ifndef HAVE_MMAP
700 #  error HAVE_MMAP not defined, has your operating system mmap?
701 #endif
702 
703 /*
704    Standard unix mmap using /dev/zero clears memory so calloc doesn't
705    need to.
706 */
707 
708 #ifndef MMAP_CLEARS
709 #define MMAP_CLEARS 1
710 #endif
711 
712 
713 /*
714    MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if
715    sbrk fails, and mmap is used as a backup (which is done only if
716    HAVE_MMAP).  The value must be a multiple of page size.  This
717    backup strategy generally applies only when systems have "holes" in
718    address space, so sbrk cannot perform contiguous expansion, but
719    there is still space available on system.  On systems for which
720    this is known to be useful (i.e. most linux kernels), this occurs
721    only when programs allocate huge amounts of memory.  Between this,
722    and the fact that mmap regions tend to be limited, the size should
723    be large, to avoid too many mmap calls and thus avoid running out
724    of kernel resources.
725 */
726 
727 #ifndef MMAP_AS_MORECORE_SIZE
728 #define MMAP_AS_MORECORE_SIZE (1024 * 1024)
729 #endif
730 
731 
732 /*
733   The system page size. To the extent possible, this malloc manages
734   memory from the system in page-size units.  Note that this value is
735   cached during initialization into a field of malloc_state. So even
736   if malloc_getpagesize is a function, it is only called once.
737 
738   The following mechanics for getpagesize were adapted from bsd/gnu
739   getpagesize.h. If none of the system-probes here apply, a value of
740   4096 is used, which should be OK: If they don't apply, then using
741   the actual value probably doesn't impact performance.
742 */
743 
744 
745 #ifndef malloc_getpagesize
746 
747 #  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
748 #    ifndef _SC_PAGE_SIZE
749 #      define _SC_PAGE_SIZE _SC_PAGESIZE
750 #    endif
751 #  endif
752 
753 #  ifdef _SC_PAGE_SIZE
754 #    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
755 #  else
756 #    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
757        extern size_t getpagesize();
758 #      define malloc_getpagesize getpagesize()
759 #    else
760 #      ifdef WIN32 /* use supplied emulation of getpagesize */
761 #        define malloc_getpagesize getpagesize()
762 #      else
763 #        if defined(HAVE_SYS_PARAM_H)
764 #          include <sys/param.h>
765 #        endif
766 #        ifdef EXEC_PAGESIZE
767 #          define malloc_getpagesize EXEC_PAGESIZE
768 #        else
769 #          ifdef NBPG
770 #            ifndef CLSIZE
771 #              define malloc_getpagesize NBPG
772 #            else
773 #              define malloc_getpagesize (NBPG * CLSIZE)
774 #            endif
775 #          else
776 #            ifdef NBPC
777 #              define malloc_getpagesize NBPC
778 #            else
779 #              ifdef PAGESIZE
780 #                define malloc_getpagesize PAGESIZE
781 #              else /* just guess */
782 #                define malloc_getpagesize (4096)
783 #              endif
784 #            endif
785 #          endif
786 #        endif
787 #      endif
788 #    endif
789 #  endif
790 #endif
791 
792 /*
793   This version of malloc supports the standard SVID/XPG mallinfo
794   routine that returns a struct containing usage properties and
795   statistics. It should work on any SVID/XPG compliant system that has
796   a /usr/include/malloc.h defining struct mallinfo. (If you'd like to
797   install such a thing yourself, cut out the preliminary declarations
798   as described above and below and save them in a malloc.h file. But
799   there's no compelling reason to bother to do this.)
800 
801   The main declaration needed is the mallinfo struct that is returned
802   (by-copy) by mallinfo().  The SVID/XPG malloinfo struct contains a
803   bunch of fields that are not even meaningful in this version of
804   malloc.  These fields are are instead filled by mallinfo() with
805   other numbers that might be of interest.
806 
807   HAVE_MALLOC_H should be set if you have a
808   /usr/include/malloc.h file that includes a declaration of struct
809   mallinfo.  If so, it is included; else an SVID2/XPG2 compliant
810   version is declared below.  These must be precisely the same for
811   mallinfo() to work.  The original SVID version of this struct,
812   defined on most systems with mallinfo, declares all fields as
813   ints. But some others define as unsigned long. If your system
814   defines the fields using a type of different width than listed here,
815   you must #include your system version and #define
816   HAVE_MALLOC_H.
817 */
818 
819 /* #define HAVE_MALLOC_H */
820 
821 /* On *BSD, malloc.h is deprecated, and on some *BSD including
822  * it may actually raise an error.
823  */
824 #if defined(HAVE_MALLOC_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && defined(__GLIBC__)
825 #include <malloc.h>
826 #else
827 
828 /* SVID2/XPG mallinfo structure */
829 
830 struct mallinfo {
831   int arena;    /* non-mmapped space allocated from system */
832   int ordblks;  /* number of free chunks */
833   int smblks;   /* number of fastbin blocks */
834   int hblks;    /* number of mmapped regions */
835   int hblkhd;   /* space in mmapped regions */
836   int usmblks;  /* maximum total allocated space */
837   int fsmblks;  /* space available in freed fastbin blocks */
838   int uordblks; /* total allocated space */
839   int fordblks; /* total free space */
840   int keepcost; /* top-most, releasable (via malloc_trim) space */
841 };
842 
843 /*
844   SVID/XPG defines four standard parameter numbers for mallopt,
845   normally defined in malloc.h.  Only one of these (M_MXFAST) is used
846   in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply,
847   so setting them has no effect. But this malloc also supports other
848   options in mallopt described below.
849 */
850 #endif
851 
852 
853 /* ---------- description of public routines ------------ */
854 
855 /*
856   malloc(size_t n)
857   Returns a pointer to a newly allocated chunk of at least n bytes, or null
858   if no space is available. Additionally, on failure, errno is
859   set to ENOMEM on ANSI C systems.
860 
861   If n is zero, malloc returns a minumum-sized chunk. (The minimum
862   size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit
863   systems.)  On most systems, size_t is an unsigned type, so calls
864   with negative arguments are interpreted as requests for huge amounts
865   of space, which will often fail. The maximum supported value of n
866   differs across systems, but is in all cases less than the maximum
867   representable value of a size_t.
868 */
869 #if __STD_C
870 Void_t*  public_mALLOc(size_t) __attribute_malloc__;
871 #else
872 Void_t*  public_mALLOc();
873 #endif
874 
875 /*
876   free(Void_t* p)
877   Releases the chunk of memory pointed to by p, that had been previously
878   allocated using malloc or a related routine such as realloc.
879   It has no effect if p is null. It can have arbitrary (i.e., bad!)
880   effects if p has already been freed.
881 
882   Unless disabled (using mallopt), freeing very large spaces will
883   when possible, automatically trigger operations that give
884   back unused memory to the system, thus reducing program footprint.
885 */
886 #if __STD_C
887 void     public_fREe(Void_t*);
888 #else
889 void     public_fREe();
890 #endif
891 
892 /*
893   calloc(size_t n_elements, size_t element_size);
894   Returns a pointer to n_elements * element_size bytes, with all locations
895   set to zero.
896 */
897 #if __STD_C
898 Void_t*  public_cALLOc(size_t, size_t) __attribute_malloc__;
899 #else
900 Void_t*  public_cALLOc();
901 #endif
902 
903 /*
904   realloc(Void_t* p, size_t n)
905   Returns a pointer to a chunk of size n that contains the same data
906   as does chunk p up to the minimum of (n, p's size) bytes, or null
907   if no space is available.
908 
909   The returned pointer may or may not be the same as p. The algorithm
910   prefers extending p when possible, otherwise it employs the
911   equivalent of a malloc-copy-free sequence.
912 
913   If p is null, realloc is equivalent to malloc.
914 
915   If space is not available, realloc returns null, errno is set (if on
916   ANSI) and p is NOT freed.
917 
918   if n is for fewer bytes than already held by p, the newly unused
919   space is lopped off and freed if possible.  Unless the #define
920   REALLOC_ZERO_BYTES_FREES is set, realloc with a size argument of
921   zero (re)allocates a minimum-sized chunk.
922 
923   Large chunks that were internally obtained via mmap will always
924   be reallocated using malloc-copy-free sequences unless
925   the system supports MREMAP (currently only linux).
926 
927   The old unix realloc convention of allowing the last-free'd chunk
928   to be used as an argument to realloc is not supported.
929 */
930 #if __STD_C
931 Void_t*  public_rEALLOc(Void_t*, size_t) __attribute_malloc__;
932 #else
933 Void_t*  public_rEALLOc();
934 #endif
935 
936 /*
937   memalign(size_t alignment, size_t n);
938   Returns a pointer to a newly allocated chunk of n bytes, aligned
939   in accord with the alignment argument.
940 
941   The alignment argument should be a power of two. If the argument is
942   not a power of two, the nearest greater power is used.
943   8-byte alignment is guaranteed by normal malloc calls, so don't
944   bother calling memalign with an argument of 8 or less.
945 
946   Overreliance on memalign is a sure way to fragment space.
947 */
948 #if __STD_C
949 Void_t*  public_mEMALIGn(size_t, size_t) __attribute_malloc__;
950 #else
951 Void_t*  public_mEMALIGn();
952 #endif
953 
954 /*
955   posix_memalign(void** memptr, size_t alignment, size_t n);
956   Sets *memptr to the address of a newly allocated chunk of n bytes, aligned
957   in accord with the alignment argument. Returns 0 on success, otherwise
958   an error (EINVAL for incorrect alignment, ENOMEM for out of memory).
959 
960   The alignment must be a power of two, and a multiple of sizeof(void *).
961 */
962 #if __STD_C
963 int public_posix_mEMALIGn(Void_t**, size_t, size_t);
964 #else
965 int public_posix_mEMALIGn();
966 #endif
967 
968 /*
969   valloc(size_t n);
970   Equivalent to memalign(pagesize, n), where pagesize is the page
971   size of the system. If the pagesize is unknown, 4096 is used.
972 */
973 #if __STD_C
974 Void_t*  public_vALLOc(size_t) __attribute_malloc__;
975 #else
976 Void_t*  public_vALLOc();
977 #endif
978 
979 
980 
981 /*
982   mallopt(int parameter_number, int parameter_value)
983   Sets tunable parameters The format is to provide a
984   (parameter-number, parameter-value) pair.  mallopt then sets the
985   corresponding parameter to the argument value if it can (i.e., so
986   long as the value is meaningful), and returns 1 if successful else
987   0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
988   normally defined in malloc.h.  Only one of these (M_MXFAST) is used
989   in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply,
990   so setting them has no effect. But this malloc also supports four
991   other options in mallopt. See below for details.  Briefly, supported
992   parameters are as follows (listed defaults are for "typical"
993   configurations).
994 
995   Symbol            param #   default    allowed param values
996   M_MXFAST          1         64         0-80  (0 disables fastbins)
997   M_TRIM_THRESHOLD -1         256*1024   any   (-1U disables trimming)
998   M_TOP_PAD        -2         0          any
999   M_MMAP_THRESHOLD -3         256*1024   any   (or 0 if no MMAP support)
1000   M_MMAP_MAX       -4         65536      any   (0 disables use of mmap)
1001 */
1002 #if __STD_C
1003 int      public_mALLOPt(int, int);
1004 #else
1005 int      public_mALLOPt();
1006 #endif
1007 
1008 
1009 /*
1010   mallinfo()
1011   Returns (by copy) a struct containing various summary statistics:
1012 
1013   arena:     current total non-mmapped bytes allocated from system
1014   ordblks:   the number of free chunks
1015   smblks:    the number of fastbin blocks (i.e., small chunks that
1016                have been freed but not use resused or consolidated)
1017   hblks:     current number of mmapped regions
1018   hblkhd:    total bytes held in mmapped regions
1019   usmblks:   the maximum total allocated space. This will be greater
1020                 than current total if trimming has occurred.
1021   fsmblks:   total bytes held in fastbin blocks
1022   uordblks:  current total allocated space (normal or mmapped)
1023   fordblks:  total free space
1024   keepcost:  the maximum number of bytes that could ideally be released
1025                back to system via malloc_trim. ("ideally" means that
1026                it ignores page restrictions etc.)
1027 
1028   Because these fields are ints, but internal bookkeeping may
1029   be kept as longs, the reported values may wrap around zero and
1030   thus be inaccurate.
1031 */
1032 #if __STD_C
1033 struct mallinfo public_mALLINFo(void);
1034 #else
1035 struct mallinfo public_mALLINFo();
1036 #endif
1037 
1038 /*
1039   pvalloc(size_t n);
1040   Equivalent to valloc(minimum-page-that-holds(n)), that is,
1041   round up n to nearest pagesize.
1042  */
1043 #if __STD_C
1044 Void_t*  public_pVALLOc(size_t) __attribute_malloc__;
1045 #else
1046 Void_t*  public_pVALLOc();
1047 #endif
1048 
1049 /*
1050   malloc_trim(size_t pad);
1051 
1052   If possible, gives memory back to the system (via negative
1053   arguments to sbrk) if there is unused memory at the `high' end of
1054   the malloc pool. You can call this after freeing large blocks of
1055   memory to potentially reduce the system-level memory requirements
1056   of a program. However, it cannot guarantee to reduce memory. Under
1057   some allocation patterns, some large free blocks of memory will be
1058   locked between two used chunks, so they cannot be given back to
1059   the system.
1060 
1061   The `pad' argument to malloc_trim represents the amount of free
1062   trailing space to leave untrimmed. If this argument is zero,
1063   only the minimum amount of memory to maintain internal data
1064   structures will be left (one page or less). Non-zero arguments
1065   can be supplied to maintain enough trailing space to service
1066   future expected allocations without having to re-obtain memory
1067   from the system.
1068 
1069   Malloc_trim returns 1 if it actually released any memory, else 0.
1070   On systems that do not support "negative sbrks", it will always
1071   rreturn 0.
1072 */
1073 #if __STD_C
1074 int      public_mTRIm(size_t);
1075 #else
1076 int      public_mTRIm();
1077 #endif
1078 
1079 /*
1080   malloc_usable_size(Void_t* p);
1081 
1082   Returns the number of bytes you can actually use in
1083   an allocated chunk, which may be more than you requested (although
1084   often not) due to alignment and minimum size constraints.
1085   You can use this many bytes without worrying about
1086   overwriting other allocated objects. This is not a particularly great
1087   programming practice. malloc_usable_size can be more useful in
1088   debugging and assertions, for example:
1089 
1090   p = malloc(n);
1091   assert(malloc_usable_size(p) >= 256);
1092 
1093 */
1094 #if __STD_C
1095 size_t   public_mUSABLe(Void_t*);
1096 #else
1097 size_t   public_mUSABLe();
1098 #endif
1099 
1100 /*
1101   malloc_stats();
1102   Prints on stderr the amount of space obtained from the system (both
1103   via sbrk and mmap), the maximum amount (which may be more than
1104   current if malloc_trim and/or munmap got called), and the current
1105   number of bytes allocated via malloc (or realloc, etc) but not yet
1106   freed. Note that this is the number of bytes allocated, not the
1107   number requested. It will be larger than the number requested
1108   because of alignment and bookkeeping overhead. Because it includes
1109   alignment wastage as being in use, this figure may be greater than
1110   zero even when no user-level chunks are allocated.
1111 
1112   The reported current and maximum system memory can be inaccurate if
1113   a program makes other calls to system memory allocation functions
1114   (normally sbrk) outside of malloc.
1115 
1116   malloc_stats prints only the most commonly interesting statistics.
1117   More information can be obtained by calling mallinfo.
1118 
1119 */
1120 #if __STD_C
1121 void     public_mSTATs();
1122 #else
1123 void     public_mSTATs();
1124 #endif
1125 
1126 /* mallopt tuning options */
1127 
1128 /*
1129   M_MXFAST is the maximum request size used for "fastbins", special bins
1130   that hold returned chunks without consolidating their spaces. This
1131   enables future requests for chunks of the same size to be handled
1132   very quickly, but can increase fragmentation, and thus increase the
1133   overall memory footprint of a program.
1134 
1135   This malloc manages fastbins very conservatively yet still
1136   efficiently, so fragmentation is rarely a problem for values less
1137   than or equal to the default.  The maximum supported value of MXFAST
1138   is 80. You wouldn't want it any higher than this anyway.  Fastbins
1139   are designed especially for use with many small structs, objects or
1140   strings -- the default handles structs/objects/arrays with sizes up
1141   to 16 4byte fields, or small strings representing words, tokens,
1142   etc. Using fastbins for larger objects normally worsens
1143   fragmentation without improving speed.
1144 
1145   M_MXFAST is set in REQUEST size units. It is internally used in
1146   chunksize units, which adds padding and alignment.  You can reduce
1147   M_MXFAST to 0 to disable all use of fastbins.  This causes the malloc
1148   algorithm to be a closer approximation of fifo-best-fit in all cases,
1149   not just for larger requests, but will generally cause it to be
1150   slower.
1151 */
1152 
1153 
1154 /* M_MXFAST is a standard SVID/XPG tuning option, usually listed in malloc.h */
1155 #ifndef M_MXFAST
1156 #define M_MXFAST            1
1157 #endif
1158 
1159 #ifndef DEFAULT_MXFAST
1160 #define DEFAULT_MXFAST     64
1161 #endif
1162 
1163 
1164 /*
1165   M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
1166   to keep before releasing via malloc_trim in free().
1167 
1168   Automatic trimming is mainly useful in long-lived programs.
1169   Because trimming via sbrk can be slow on some systems, and can
1170   sometimes be wasteful (in cases where programs immediately
1171   afterward allocate more large chunks) the value should be high
1172   enough so that your overall system performance would improve by
1173   releasing this much memory.
1174 
1175   The trim threshold and the mmap control parameters (see below)
1176   can be traded off with one another. Trimming and mmapping are
1177   two different ways of releasing unused memory back to the
1178   system. Between these two, it is often possible to keep
1179   system-level demands of a long-lived program down to a bare
1180   minimum. For example, in one test suite of sessions measuring
1181   the XF86 X server on Linux, using a trim threshold of 128K and a
1182   mmap threshold of 192K led to near-minimal long term resource
1183   consumption.
1184 
1185   If you are using this malloc in a long-lived program, it should
1186   pay to experiment with these values.  As a rough guide, you
1187   might set to a value close to the average size of a process
1188   (program) running on your system.  Releasing this much memory
1189   would allow such a process to run in memory.  Generally, it's
1190   worth it to tune for trimming rather tham memory mapping when a
1191   program undergoes phases where several large chunks are
1192   allocated and released in ways that can reuse each other's
1193   storage, perhaps mixed with phases where there are no such
1194   chunks at all.  And in well-behaved long-lived programs,
1195   controlling release of large blocks via trimming versus mapping
1196   is usually faster.
1197 
1198   However, in most programs, these parameters serve mainly as
1199   protection against the system-level effects of carrying around
1200   massive amounts of unneeded memory. Since frequent calls to
1201   sbrk, mmap, and munmap otherwise degrade performance, the default
1202   parameters are set to relatively high values that serve only as
1203   safeguards.
1204 
1205   The trim value must be greater than page size to have any useful
1206   effect.  To disable trimming completely, you can set to
1207   (unsigned long)(-1)
1208 
1209   Trim settings interact with fastbin (MXFAST) settings: Unless
1210   TRIM_FASTBINS is defined, automatic trimming never takes place upon
1211   freeing a chunk with size less than or equal to MXFAST. Trimming is
1212   instead delayed until subsequent freeing of larger chunks. However,
1213   you can still force an attempted trim by calling malloc_trim.
1214 
1215   Also, trimming is not generally possible in cases where
1216   the main arena is obtained via mmap.
1217 
1218   Note that the trick some people use of mallocing a huge space and
1219   then freeing it at program startup, in an attempt to reserve system
1220   memory, doesn't have the intended effect under automatic trimming,
1221   since that memory will immediately be returned to the system.
1222 */
1223 
1224 #define M_TRIM_THRESHOLD       -1
1225 
1226 #ifndef DEFAULT_TRIM_THRESHOLD
1227 #define DEFAULT_TRIM_THRESHOLD (256 * 1024)
1228 #endif
1229 
1230 /*
1231   M_TOP_PAD is the amount of extra `padding' space to allocate or
1232   retain whenever sbrk is called. It is used in two ways internally:
1233 
1234   * When sbrk is called to extend the top of the arena to satisfy
1235   a new malloc request, this much padding is added to the sbrk
1236   request.
1237 
1238   * When malloc_trim is called automatically from free(),
1239   it is used as the `pad' argument.
1240 
1241   In both cases, the actual amount of padding is rounded
1242   so that the end of the arena is always a system page boundary.
1243 
1244   The main reason for using padding is to avoid calling sbrk so
1245   often. Having even a small pad greatly reduces the likelihood
1246   that nearly every malloc request during program start-up (or
1247   after trimming) will invoke sbrk, which needlessly wastes
1248   time.
1249 
1250   Automatic rounding-up to page-size units is normally sufficient
1251   to avoid measurable overhead, so the default is 0.  However, in
1252   systems where sbrk is relatively slow, it can pay to increase
1253   this value, at the expense of carrying around more memory than
1254   the program needs.
1255 */
1256 
1257 #define M_TOP_PAD              -2
1258 
1259 #ifndef DEFAULT_TOP_PAD
1260 #define DEFAULT_TOP_PAD        (0)
1261 #endif
1262 
1263 /*
1264   M_MMAP_THRESHOLD is the request size threshold for using mmap()
1265   to service a request. Requests of at least this size that cannot
1266   be allocated using already-existing space will be serviced via mmap.
1267   (If enough normal freed space already exists it is used instead.)
1268 
1269   Using mmap segregates relatively large chunks of memory so that
1270   they can be individually obtained and released from the host
1271   system. A request serviced through mmap is never reused by any
1272   other request (at least not directly; the system may just so
1273   happen to remap successive requests to the same locations).
1274 
1275   Segregating space in this way has the benefits that:
1276 
1277    1. Mmapped space can ALWAYS be individually released back
1278       to the system, which helps keep the system level memory
1279       demands of a long-lived program low.
1280    2. Mapped memory can never become `locked' between
1281       other chunks, as can happen with normally allocated chunks, which
1282       means that even trimming via malloc_trim would not release them.
1283    3. On some systems with "holes" in address spaces, mmap can obtain
1284       memory that sbrk cannot.
1285 
1286   However, it has the disadvantages that:
1287 
1288    1. The space cannot be reclaimed, consolidated, and then
1289       used to service later requests, as happens with normal chunks.
1290    2. It can lead to more wastage because of mmap page alignment
1291       requirements
1292    3. It causes malloc performance to be more dependent on host
1293       system memory management support routines which may vary in
1294       implementation quality and may impose arbitrary
1295       limitations. Generally, servicing a request via normal
1296       malloc steps is faster than going through a system's mmap.
1297 
1298   The advantages of mmap nearly always outweigh disadvantages for
1299   "large" chunks, but the value of "large" varies across systems.  The
1300   default is an empirically derived value that works well in most
1301   systems.
1302 */
1303 
1304 #define M_MMAP_THRESHOLD      -3
1305 
1306 #ifndef DEFAULT_MMAP_THRESHOLD
1307 #define DEFAULT_MMAP_THRESHOLD (256 * 1024)
1308 #endif
1309 
1310 /*
1311   M_MMAP_MAX is the maximum number of requests to simultaneously
1312   service using mmap. This parameter exists because
1313 . Some systems have a limited number of internal tables for
1314   use by mmap, and using more than a few of them may degrade
1315   performance.
1316 
1317   The default is set to a value that serves only as a safeguard.
1318   Setting to 0 disables use of mmap for servicing large requests.  If
1319   HAVE_MMAP is not set, the default value is 0, and attempts to set it
1320   to non-zero values in mallopt will fail.
1321 */
1322 
1323 #define M_MMAP_MAX             -4
1324 
1325 #ifndef DEFAULT_MMAP_MAX
1326 #define DEFAULT_MMAP_MAX       (65536)
1327 #endif
1328 
1329 #ifdef __cplusplus
1330 };  /* end of extern "C" */
1331 #endif
1332 
1333 /*
1334   ========================================================================
1335   To make a fully customizable malloc.h header file, cut everything
1336   above this line, put into file malloc.h, edit to suit, and #include it
1337   on the next line, as well as in programs that use this malloc.
1338   ========================================================================
1339 */
1340 
1341 /* #include "malloc.h" */
1342 
1343 /* --------------------- public wrappers ---------------------- */
1344 
1345 #ifdef USE_PUBLIC_MALLOC_WRAPPERS
1346 
1347 /* DL_STATIC used to make functions (deep down) consistent
1348  * with prototypes (otherwise the prototypes are static
1349  * with USE_PUBLIC_MALLOC_WRAPPERS, but the functions aren't).
1350  * The gcc compiler doesn't care, but the HP-UX compiler does.
1351  */
1352 #define DL_STATIC static
1353 
1354 /* Declare all routines as internal */
1355 #if __STD_C
1356 static Void_t*  mALLOc(size_t) __attribute_malloc__;
1357 static void     fREe(Void_t*);
1358 static Void_t*  rEALLOc(Void_t*, size_t) __attribute_malloc__;
1359 static Void_t*  mEMALIGn(size_t, size_t) __attribute_malloc__;
1360 static int      posix_mEMALIGn(Void_t**, size_t, size_t);
1361 static Void_t*  vALLOc(size_t) __attribute_malloc__;
1362 static Void_t*  pVALLOc(size_t) __attribute_malloc__;
1363 static Void_t*  cALLOc(size_t, size_t) __attribute_malloc__;
1364 static int      mTRIm(size_t);
1365 static size_t   mUSABLe(Void_t*);
1366 static void     mSTATs();
1367 static int      mALLOPt(int, int);
1368 static struct mallinfo mALLINFo(void);
1369 #else
1370 static Void_t*  mALLOc();
1371 static void     fREe();
1372 static Void_t*  rEALLOc();
1373 static Void_t*  mEMALIGn();
1374 static int      posix_mEMALIGn();
1375 static Void_t*  vALLOc();
1376 static Void_t*  pVALLOc();
1377 static Void_t*  cALLOc();
1378 static int      mTRIm();
1379 static size_t   mUSABLe();
1380 static void     mSTATs();
1381 static int      mALLOPt();
1382 static struct mallinfo mALLINFo();
1383 #endif
1384 
1385 /*
1386   MALLOC_PREACTION and MALLOC_POSTACTION should be
1387   defined to return 0 on success, and nonzero on failure.
1388   The return value of MALLOC_POSTACTION is currently ignored
1389   in wrapper functions since there is no reasonable default
1390   action to take on failure.
1391 */
1392 
1393 
1394 #ifdef USE_MALLOC_LOCK
1395 
1396 # ifdef WIN32
1397 
1398 static int mALLOC_MUTEx;
1399 #define MALLOC_PREACTION   slwait(&mALLOC_MUTEx)
1400 #define MALLOC_POSTACTION  slrelease(&mALLOC_MUTEx)
dnmalloc_pthread_init(void)1401 int dnmalloc_pthread_init(void) { return 0; }
1402 
1403 # elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
1404 
1405 #   if defined(__NetBSD__)
1406 #include <reentrant.h>
1407 extern int __isthreaded;
1408 static mutex_t thread_lock = MUTEX_INITIALIZER;
1409 #define _MALLOC_LOCK()   if (__isthreaded) mutex_lock(&thread_lock)
1410 #define _MALLOC_UNLOCK() if (__isthreaded) mutex_unlock(&thread_lock)
_malloc_prefork(void)1411 void _malloc_prefork(void) {  _MALLOC_LOCK(); }
_malloc_postfork(void)1412 void _malloc_postfork(void) { _MALLOC_UNLOCK(); }
1413 #   endif
1414 
1415 #   if defined(__OpenBSD__)
1416 extern int  __isthreaded;
1417 void   _thread_malloc_lock(void);
1418 void   _thread_malloc_unlock(void);
1419 #define _MALLOC_LOCK()           if (__isthreaded) _thread_malloc_lock()
1420 #define _MALLOC_UNLOCK()         if (__isthreaded) _thread_malloc_unlock()
1421 #   endif
1422 
1423 #   if defined(__FreeBSD__)
1424 extern int      __isthreaded;
1425 struct _spinlock {
1426 	volatile long	access_lock;
1427 	volatile long	lock_owner;
1428 	volatile char	*fname;
1429 	volatile int	lineno;
1430 };
1431 typedef struct _spinlock spinlock_t;
1432 #define	_SPINLOCK_INITIALIZER	{ 0, 0, 0, 0 }
1433 void	_spinlock(spinlock_t *);
1434 void	_spinunlock(spinlock_t *);
1435 /* # include "/usr/src/lib/libc/include/spinlock.h" */
1436 static spinlock_t thread_lock   = _SPINLOCK_INITIALIZER;
1437 spinlock_t *__malloc_lock       = &thread_lock;
1438 #define _MALLOC_LOCK()           if (__isthreaded) _spinlock(&thread_lock)
1439 #define _MALLOC_UNLOCK()         if (__isthreaded) _spinunlock(&thread_lock)
1440 #   endif
1441 
1442 /* Common for all three *BSD
1443  */
1444 static int malloc_active = 0;
dnmalloc_mutex_lock()1445 static int dnmalloc_mutex_lock()
1446 {
1447   _MALLOC_LOCK();
1448   if (!malloc_active)
1449     {
1450       ++malloc_active;
1451       return 0;
1452     }
1453   assert(malloc_active == 0);
1454   _MALLOC_UNLOCK();
1455   errno = EDEADLK;
1456   return 1;
1457 }
dnmalloc_mutex_unlock()1458 static int dnmalloc_mutex_unlock()
1459 {
1460   --malloc_active;
1461   _MALLOC_UNLOCK();
1462   return 0;
1463 }
1464 #define MALLOC_PREACTION   dnmalloc_mutex_lock()
1465 #define MALLOC_POSTACTION  dnmalloc_mutex_unlock()
dnmalloc_pthread_init(void)1466 int dnmalloc_pthread_init(void) { return 0; }
1467 
1468 # else
1469 
1470 /* Wrapping malloc with pthread_mutex_lock/pthread_mutex_unlock
1471  *
1472  * Works fine on linux (no malloc in pthread_mutex_lock)
1473  * Works with on HP-UX if initialized after entering main()
1474  */
1475 #include <pthread.h>
1476 static int malloc_active      = 0;
1477 void dnmalloc_fork_prepare(void);
1478 void dnmalloc_fork_parent(void);
1479 void dnmalloc_fork_child(void);
1480 
1481 #if !defined(__linux__)
1482 
1483 static pthread_mutex_t mALLOC_MUTEx;
1484 pthread_once_t dnmalloc_once_control = PTHREAD_ONCE_INIT;
1485 static int dnmalloc_use_mutex = 0;
dnmalloc_pthread_init_int(void)1486 static void dnmalloc_pthread_init_int(void)
1487 {
1488   pthread_mutexattr_t   mta;
1489   pthread_mutexattr_init(&mta);
1490   pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
1491   pthread_mutex_init(&(mALLOC_MUTEx), &mta);
1492   pthread_mutexattr_destroy(&mta);
1493   pthread_atfork(dnmalloc_fork_prepare,
1494 		 dnmalloc_fork_parent,
1495 		 dnmalloc_fork_child);
1496   dnmalloc_use_mutex = 1;
1497 }
dnmalloc_pthread_init(void)1498 int dnmalloc_pthread_init(void)
1499 {
1500   return pthread_once(&dnmalloc_once_control, dnmalloc_pthread_init_int);
1501 }
1502 
1503 #else
1504 
1505 static pthread_mutex_t mALLOC_MUTEx = PTHREAD_MUTEX_INITIALIZER;
1506 static int dnmalloc_use_mutex = 1;
dnmalloc_pthread_init(void)1507 int dnmalloc_pthread_init(void) {
1508   return pthread_atfork(dnmalloc_fork_prepare,
1509 			dnmalloc_fork_parent,
1510 			dnmalloc_fork_child);
1511 }
1512 #endif /* !defined(__linux__) */
1513 
dnmalloc_fork_prepare(void)1514 void dnmalloc_fork_prepare(void) {
1515   if (dnmalloc_use_mutex)
1516     pthread_mutex_lock(&mALLOC_MUTEx);
1517 }
dnmalloc_fork_parent(void)1518 void dnmalloc_fork_parent(void) {
1519   if (dnmalloc_use_mutex)
1520     pthread_mutex_unlock(&mALLOC_MUTEx);
1521 }
dnmalloc_fork_child(void)1522 void dnmalloc_fork_child(void) {
1523   int rc = 0;
1524 #ifdef __GLIBC__
1525   if (dnmalloc_use_mutex)
1526     {
1527       pthread_mutex_unlock (&mALLOC_MUTEx);
1528       pthread_mutex_destroy(&mALLOC_MUTEx);
1529       rc = pthread_mutex_init(&mALLOC_MUTEx, NULL);
1530     }
1531 #else
1532   if (dnmalloc_use_mutex)
1533     rc = pthread_mutex_unlock(&mALLOC_MUTEx);
1534 #endif
1535   if (rc != 0)
1536     {
1537       fputs("fork_child failed", stderr);
1538       _exit(EXIT_FAILURE);
1539     }
1540 }
dnmalloc_mutex_lock(pthread_mutex_t * mutex)1541 static int dnmalloc_mutex_lock(pthread_mutex_t *mutex)
1542 {
1543   if (dnmalloc_use_mutex)
1544     {
1545       int rc = pthread_mutex_lock(mutex);
1546       if (rc == 0)
1547 	{
1548 	  if (!malloc_active)
1549 	    {
1550 	      ++malloc_active;
1551 	      return 0;
1552 	    }
1553 	  assert(malloc_active == 0);
1554 	  (void) pthread_mutex_unlock(mutex);
1555 	  errno = EDEADLK;
1556 	  return 1;
1557 	}
1558       return rc;
1559     }
1560   return 0;
1561 }
dnmalloc_mutex_unlock(pthread_mutex_t * mutex)1562 static int dnmalloc_mutex_unlock(pthread_mutex_t *mutex)
1563 {
1564   if (dnmalloc_use_mutex)
1565     {
1566       --malloc_active;
1567       return pthread_mutex_unlock(mutex);
1568     }
1569   return 0;
1570 }
1571 # define MALLOC_PREACTION   dnmalloc_mutex_lock(&mALLOC_MUTEx)
1572 # define MALLOC_POSTACTION  dnmalloc_mutex_unlock(&mALLOC_MUTEx)
1573 
1574 # endif
1575 
1576 #else
1577 
1578 /* Substitute anything you like for these */
1579 
1580 # define MALLOC_PREACTION   (0)
1581 # define MALLOC_POSTACTION  (0)
dnmalloc_pthread_init(void)1582 int dnmalloc_pthread_init(void) { return 0; }
1583 
1584 #endif /* USE_MALLOC_LOCK */
1585 
public_mALLOc(size_t bytes)1586 Void_t* public_mALLOc(size_t bytes) {
1587   Void_t* m;
1588   if (MALLOC_PREACTION == 0) {
1589     m = mALLOc(bytes);
1590     (void) MALLOC_POSTACTION;
1591     return m;
1592   }
1593   return 0;
1594 }
1595 
public_fREe(Void_t * m)1596 void public_fREe(Void_t* m) {
1597   if (MALLOC_PREACTION == 0) {
1598     fREe(m);
1599     (void) MALLOC_POSTACTION;
1600   }
1601 }
1602 
public_rEALLOc(Void_t * m,size_t bytes)1603 Void_t* public_rEALLOc(Void_t* m, size_t bytes) {
1604   if (MALLOC_PREACTION == 0) {
1605     m = rEALLOc(m, bytes);
1606     (void) MALLOC_POSTACTION;
1607     return m;
1608   }
1609   return 0;
1610 }
1611 
public_mEMALIGn(size_t alignment,size_t bytes)1612 Void_t* public_mEMALIGn(size_t alignment, size_t bytes) {
1613   Void_t* m;
1614   if (MALLOC_PREACTION == 0) {
1615     m = mEMALIGn(alignment, bytes);
1616     (void) MALLOC_POSTACTION;
1617     return m;
1618   }
1619   return 0;
1620 }
1621 
public_posix_mEMALIGn(Void_t ** memptr,size_t alignment,size_t bytes)1622 int public_posix_mEMALIGn(Void_t**memptr, size_t alignment, size_t bytes) {
1623   int m, ret;
1624   if ((ret = MALLOC_PREACTION) == 0) {
1625     m = posix_mEMALIGn(memptr, alignment, bytes);
1626     (void) MALLOC_POSTACTION;
1627     return m;
1628   }
1629   return ret;
1630 }
1631 
public_vALLOc(size_t bytes)1632 Void_t* public_vALLOc(size_t bytes) {
1633   Void_t* m;
1634   if (MALLOC_PREACTION == 0) {
1635     m = vALLOc(bytes);
1636     (void) MALLOC_POSTACTION;
1637     return m;
1638   }
1639   return 0;
1640 }
1641 
public_pVALLOc(size_t bytes)1642 Void_t* public_pVALLOc(size_t bytes) {
1643   Void_t* m;
1644   if (MALLOC_PREACTION == 0) {
1645     m = pVALLOc(bytes);
1646     (void) MALLOC_POSTACTION;
1647     return m;
1648   }
1649   return 0;
1650 }
1651 
public_cALLOc(size_t n,size_t elem_size)1652 Void_t* public_cALLOc(size_t n, size_t elem_size) {
1653   Void_t* m;
1654   if (MALLOC_PREACTION == 0) {
1655     m = cALLOc(n, elem_size);
1656     (void) MALLOC_POSTACTION;
1657     return m;
1658   }
1659   return 0;
1660 }
1661 
public_mTRIm(size_t s)1662 int public_mTRIm(size_t s) {
1663   int result;
1664   if (MALLOC_PREACTION == 0) {
1665     result = mTRIm(s);
1666     (void) MALLOC_POSTACTION;
1667     return result;
1668   }
1669   return 0;
1670 }
1671 
public_mUSABLe(Void_t * m)1672 size_t public_mUSABLe(Void_t* m) {
1673   size_t result;
1674   if (MALLOC_PREACTION == 0) {
1675     result = mUSABLe(m);
1676     (void) MALLOC_POSTACTION;
1677     return result;
1678   }
1679   return 0;
1680 }
1681 
public_mSTATs()1682 void public_mSTATs() {
1683   if (MALLOC_PREACTION == 0) {
1684     mSTATs();
1685     (void) MALLOC_POSTACTION;
1686   }
1687 }
1688 
public_mALLINFo()1689 struct mallinfo public_mALLINFo() {
1690   struct mallinfo m;
1691   if (MALLOC_PREACTION == 0) {
1692     m = mALLINFo();
1693     (void) MALLOC_POSTACTION;
1694     return m;
1695   } else {
1696     struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1697     return nm;
1698   }
1699 }
1700 
public_mALLOPt(int p,int v)1701 int public_mALLOPt(int p, int v) {
1702   int result;
1703   if (MALLOC_PREACTION == 0) {
1704     result = mALLOPt(p, v);
1705     (void) MALLOC_POSTACTION;
1706     return result;
1707   }
1708   return 0;
1709 }
1710 
1711 #else
1712 
dnmalloc_pthread_init(void)1713 int dnmalloc_pthread_init(void) { return 0; }
1714 #define DL_STATIC
1715 
1716 #endif /* USE_PUBLIC_MALLOC_WRAPPERS */
1717 
1718 
1719 
1720 /* ------------- Optional versions of memcopy ---------------- */
1721 
1722 
1723 #if USE_MEMCPY
1724 
1725 /*
1726   Note: memcpy is ONLY invoked with non-overlapping regions,
1727   so the (usually slower) memmove is not needed.
1728 */
1729 
1730 #define MALLOC_COPY(dest, src, nbytes)  memcpy(dest, src, nbytes)
1731 #define MALLOC_ZERO(dest, nbytes)       memset(dest, 0,   nbytes)
1732 
1733 #else /* !USE_MEMCPY */
1734 
1735 /* Use Duff's device for good zeroing/copying performance. */
1736 
1737 #define MALLOC_ZERO(charp, nbytes)                                            \
1738 do {                                                                          \
1739   INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp);                           \
1740   CHUNK_SIZE_T  mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T);                     \
1741   long mcn;                                                                   \
1742   if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
1743   switch (mctmp) {                                                            \
1744     case 0: for(;;) { *mzp++ = 0;                                             \
1745     case 7:           *mzp++ = 0;                                             \
1746     case 6:           *mzp++ = 0;                                             \
1747     case 5:           *mzp++ = 0;                                             \
1748     case 4:           *mzp++ = 0;                                             \
1749     case 3:           *mzp++ = 0;                                             \
1750     case 2:           *mzp++ = 0;                                             \
1751     case 1:           *mzp++ = 0; if(mcn <= 0) break; mcn--; }                \
1752   }                                                                           \
1753 } while(0)
1754 
1755 #define MALLOC_COPY(dest,src,nbytes)                                          \
1756 do {                                                                          \
1757   INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src;                            \
1758   INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest;                           \
1759   CHUNK_SIZE_T  mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T);                     \
1760   long mcn;                                                                   \
1761   if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
1762   switch (mctmp) {                                                            \
1763     case 0: for(;;) { *mcdst++ = *mcsrc++;                                    \
1764     case 7:           *mcdst++ = *mcsrc++;                                    \
1765     case 6:           *mcdst++ = *mcsrc++;                                    \
1766     case 5:           *mcdst++ = *mcsrc++;                                    \
1767     case 4:           *mcdst++ = *mcsrc++;                                    \
1768     case 3:           *mcdst++ = *mcsrc++;                                    \
1769     case 2:           *mcdst++ = *mcsrc++;                                    \
1770     case 1:           *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; }       \
1771   }                                                                           \
1772 } while(0)
1773 
1774 #endif
1775 
1776 /* ------------------ MMAP support ------------------  */
1777 
1778 
1779 #if defined(HAVE_FCNTL_H)
1780 #include <fcntl.h>
1781 #endif
1782 
1783 #if defined(HAVE_SYS_MMAN_H)
1784 #include <sys/mman.h>
1785 #endif
1786 
1787 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
1788 #define MAP_ANONYMOUS MAP_ANON
1789 #endif
1790 
1791 /*
1792    Nearly all versions of mmap support MAP_ANONYMOUS,
1793    so the following is unlikely to be needed, but is
1794    supplied just in case.
1795 */
1796 
1797 #ifndef MAP_ANONYMOUS
1798 
1799 /* rw 19.05.2008 changed to avoid cached file descriptor, untested
1800  */
anon_mmap(void * addr,size_t length,int prot,int flags)1801 void * anon_mmap (void *addr, size_t length, int prot, int flags)
1802 {
1803   void * retval   = NULL;
1804   int dev_zero_fd = -1; /* File descriptor for /dev/zero. */
1805 
1806   dev_zero_fd = open("/dev/zero", O_RDWR);
1807   if (dev_zero_fd >= 0)
1808     {
1809       retval = mmap((addr), (size), (prot), (flags), dev_zero_fd, 0);
1810       /* closing the file descriptor does not unmap the region */
1811       close(dev_zero_fd);
1812     }
1813   return retval;
1814 }
1815 
1816 #define MMAP(addr, size, prot, flags) \
1817   (anon_mmap((addr), (size), (prot), (flags)))
1818 
1819 
1820 #else /* have MAP_ANONYMOUS */
1821 
1822 #if !defined(MAP_32BIT) && defined(MAP_ADDR32)
1823 #define MAP_32BIT MAP_ADDR32
1824 #endif
1825 
1826 #if defined(MAP_32BIT)
1827 #define MMAP(addr, size, prot, flags) \
1828  (mmap((addr), (size), (prot), (flags)|MAP_ANONYMOUS|MAP_32BIT, -1, 0))
1829 #elif defined(__sun)
1830 /*
1831  * Hint an address within 32bit address space
1832  */
1833 #define MMAP(addr, size, prot, flags) \
1834  (mmap((void*)0xC0000000, (size), (prot), (flags)|MAP_ANONYMOUS, -1, 0))
1835 #else
1836 /* *BSD */
1837 #define MMAP(addr, size, prot, flags) \
1838  (mmap((void*)0x80000000, (size), (prot), (flags)|MAP_ANONYMOUS, -1, 0))
1839 #endif
1840 
1841 #endif /* have MAP_ANONYMOUS */
1842 
1843 
1844 /*
1845   -----------------------  Chunk representations -----------------------
1846 */
1847 
1848 typedef void * mchunkptr;
1849 
1850 struct chunkinfo {
1851    INTERNAL_SIZE_T      prev_size;  /* Size of previous in bytes          */
1852    INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */
1853    INTERNAL_SIZE_T      req;        /* Original request size, for guard.  */
1854    struct chunkinfo* hash_next;     /* contains a pointer to the next chunk
1855                                        in the linked list if the hash
1856                                        value is the same as the chunk     */
1857    struct chunkinfo* fd;	    /* double links -- used only if free. */
1858    struct chunkinfo* bk;
1859    mchunkptr chunk;
1860 };
1861 
1862 typedef struct chunkinfo* chunkinfoptr;
1863 
1864 struct cireginfo {
1865 	unsigned long position;
1866 	unsigned long *freebitmap;
1867 	struct cireginfo* next;
1868 	struct chunkinfo *freelist;
1869 	struct chunkinfo *begin;
1870 	unsigned long freecounter;
1871 };
1872 
1873 /*
1874   ---------- Size and alignment checks and conversions ----------
1875 */
1876 
1877 /* conversion from malloc headers to user pointers, and back */
1878 #define chunk(p) (p->chunk)
1879 
1880 
1881 #define chunk2mem(p)   (chunk(p))
1882 #define mem2chunk(mem) (hashtable_lookup(mem))
1883 
1884 /* The smallest possible chunk      */
1885 /* #define MIN_CHUNK_SIZE        16 */
1886 #if (SIZEOF_UNSIGNED_LONG == 8) || defined(__arch64__) || defined(__ia64__) || defined(__x86_64__) || defined(__LP64__) || defined(__64BIT__) || defined(_LP64) || defined(_M_IA64) || (defined(_MIPS_SZLONG) && (_MIPS_SZLONG == 64))
1887 #  define MIN_CHUNK_SIZE 32
1888 #else
1889 #  define MIN_CHUNK_SIZE 16
1890 #endif
1891 
1892 /* The smallest size we can malloc is an aligned minimal chunk */
1893 
1894 #define MINSIZE  \
1895   (CHUNK_SIZE_T)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
1896 
1897 /* Check if m has acceptable alignment */
1898 
1899 #define aligned_OK(m)  (((PTR_UINT)((m)) & (MALLOC_ALIGN_MASK)) == 0)
1900 
1901 #define GUARD_SIZE 4
1902 
1903 /*
1904    Check if a request is so large that it would wrap around zero when
1905    padded and aligned. To simplify some other code, the bound is made
1906    low enough so that adding MINSIZE will also not wrap around zero.
1907 
1908    Make it 4*MINSIZE.
1909 */
1910 
1911 #define REQUEST_OUT_OF_RANGE(req)                                 \
1912   ((CHUNK_SIZE_T)(req) >=                                         \
1913    (CHUNK_SIZE_T)(INTERNAL_SIZE_T)(-4 * MINSIZE))
1914 
1915 /* pad request bytes into a usable size -- internal version */
1916 
1917 #define request2size(req)                                         \
1918   (((req) + GUARD_SIZE + MALLOC_ALIGN_MASK >= MINSIZE)  ?         \
1919    ((req) + GUARD_SIZE + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK :\
1920    MINSIZE)
1921 
1922 /*  Same, except also perform argument check */
1923 
1924 #define checked_request2size(req, sz)                             \
1925   if (!REQUEST_OUT_OF_RANGE(req)) {                               \
1926     (sz) = request2size(req);                                     \
1927     assert((sz-req) >= GUARD_SIZE);                               \
1928   } else {                                                        \
1929     MALLOC_FAILURE_ACTION;                                        \
1930     return 0;                                                     \
1931   }
1932 
1933 #if PARANOIA > 2
1934 static char * guard_set_p;
1935 static char * guard_set_q;
1936 
1937 #define guard_set(guard, P, request, sz)			  \
1938   assert((sz-request) >= GUARD_SIZE);                             \
1939   guard_set_p = (char*)(chunk(P));                                \
1940   guard_set_p += request;                                         \
1941   VALGRIND_MAKE_MEM_UNDEFINED(guard_set_p,GUARD_SIZE);            \
1942   guard_set_q = (char*)(guard);                                   \
1943   *guard_set_p = *guard_set_q; ++guard_set_p; ++guard_set_q;      \
1944   *guard_set_p = *guard_set_q; ++guard_set_p; ++guard_set_q;      \
1945   *guard_set_p = *guard_set_q; ++guard_set_p; ++guard_set_q;      \
1946   *guard_set_p = *guard_set_q;                                    \
1947   VALGRIND_MAKE_MEM_NOACCESS((((char*)chunk(P))+request),GUARD_SIZE);	\
1948   (P)->req = request
1949 
1950 #define guard_check(guard, P)				          \
1951   VALGRIND_MAKE_MEM_DEFINED((((char *)chunk(P))+(P)->req), GUARD_SIZE); \
1952   assert(0 == memcmp((((char *)chunk(P))+(P)->req),(void*)(guard),GUARD_SIZE));\
1953   VALGRIND_MAKE_MEM_NOACCESS((((char *)chunk(P))+(P)->req), GUARD_SIZE);
1954 
1955 #else
1956 #define guard_set(guard, P, request, sz) ((void)0)
1957 #define guard_check(guard, P) ((void)0)
1958 #endif /* PARANOIA > 2 */
1959 
1960 /* dnmalloc forward declarations */
1961 static char * dnmalloc_arc4random(void);
1962 static void dnmalloc_init (void);
1963 static void malloc_mmap_state(void);
1964 static void cireg_extend (void);
1965 static chunkinfoptr cireg_getfree (void);
1966 static void hashtable_add (chunkinfoptr ci);
1967 static void hashtable_insert (chunkinfoptr ci_orig, chunkinfoptr ci_insert);
1968 static void hashtable_remove (mchunkptr p);
1969 static void hashtable_skiprm (chunkinfoptr ci_orig, chunkinfoptr ci_todelete);
1970 static chunkinfoptr hashtable_lookup (mchunkptr p);
1971 static chunkinfoptr next_chunkinfo (chunkinfoptr ci);
1972 static chunkinfoptr prev_chunkinfo (chunkinfoptr ci);
1973 
1974 
1975 
1976 /*
1977   --------------- Physical chunk operations ---------------
1978 */
1979 
1980 
1981 /* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
1982 #define PREV_INUSE 0x1
1983 
1984 /* extract inuse bit of previous chunk */
1985 #define prev_inuse(p)       ((p)->size & PREV_INUSE)
1986 
1987 /* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
1988 #define IS_MMAPPED 0x2
1989 
1990 /* check for mmap()'ed chunk */
1991 #define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
1992 
1993 
1994 /* size field is or'ed when the chunk is in use */
1995 #define INUSE 0x4
1996 
1997 /* extract inuse bit of chunk */
1998 #define inuse(p)       ((p)->size & INUSE)
1999 
2000 /*
2001   Bits to mask off when extracting size
2002 
2003   Note: IS_MMAPPED is intentionally not masked off from size field in
2004   macros for which mmapped chunks should never be seen. This should
2005   cause helpful core dumps to occur if it is tried by accident by
2006   people extending or adapting this malloc.
2007 */
2008 #define SIZE_BITS (PREV_INUSE|IS_MMAPPED|INUSE)
2009 
2010 /* Bits to mask off when extracting size of chunks for macros which do not use mmap */
2011 #define SIZE_NOMMAP (PREV_INUSE|INUSE)
2012 
2013 /* Get size, ignoring use bits */
2014 #define chunksize(p)         ((p)->size & ~(SIZE_BITS))
2015 
2016 /* Ptr to chunkinfo of next physical malloc_chunk. */
2017 #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & SIZE_NOMMAP) ))
2018 
2019 /* Treat space at ptr + offset as a chunk */
2020 #define chunk_at_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
2021 
2022 /* set/clear chunk as being inuse without otherwise disturbing */
2023 #define set_inuse(p) ((p)->size |= INUSE)
2024 
2025 #define clear_inuse(p) ((p)->size &= ~(INUSE))
2026 
2027 #define set_previnuse(p) ((p)->size |= PREV_INUSE)
2028 
2029 #define clear_previnuse(p) ((p)->size &= ~(PREV_INUSE))
2030 
set_previnuse_next(chunkinfoptr p)2031 static void set_previnuse_next (chunkinfoptr p)
2032 {
2033    chunkinfoptr q;
2034    q = next_chunkinfo (p);
2035    if (q)
2036       set_previnuse (q);
2037 }
2038 
2039 #define set_all_inuse(p) \
2040 set_inuse(p); \
2041 set_previnuse_next(p);
2042 
2043 
2044 /* Set size at head, without disturbing its use bit */
2045 #define set_head_size(p, s)  ((p)->size = (((p)->size & SIZE_NOMMAP) | (s)))
2046 
2047 /* Set size/use field */
2048 #define set_head(p, s)       ((p)->size = (s))
2049 
2050 /*
2051   Bins
2052 
2053     An array of bin headers for free chunks. Each bin is doubly
2054     linked.  The bins are approximately proportionally (log) spaced.
2055     There are a lot of these bins (128). This may look excessive, but
2056     works very well in practice.  Most bins hold sizes that are
2057     unusual as malloc request sizes, but are more usual for fragments
2058     and consolidated sets of chunks, which is what these bins hold, so
2059     they can be found quickly.  All procedures maintain the invariant
2060     that no consolidated chunk physically borders another one, so each
2061     chunk in a list is known to be preceeded and followed by either
2062     inuse chunks or the ends of memory.
2063 
2064     Chunks in bins are kept in size order, with ties going to the
2065     approximately least recently used chunk. Ordering isn't needed
2066     for the small bins, which all contain the same-sized chunks, but
2067     facilitates best-fit allocation for larger chunks. These lists
2068     are just sequential. Keeping them in order almost never requires
2069     enough traversal to warrant using fancier ordered data
2070     structures.
2071 
2072     Chunks of the same size are linked with the most
2073     recently freed at the front, and allocations are taken from the
2074     back.  This results in LRU (FIFO) allocation order, which tends
2075     to give each chunk an equal opportunity to be consolidated with
2076     adjacent freed chunks, resulting in larger free chunks and less
2077     fragmentation.
2078 
2079     To simplify use in double-linked lists, each bin header acts
2080     as a malloc_chunk. This avoids special-casing for headers.
2081     But to conserve space and improve locality, we allocate
2082     only the fd/bk pointers of bins, and then use repositioning tricks
2083     to treat these as the fields of a malloc_chunk*.
2084 */
2085 
2086 typedef struct chunkinfo* mbinptr;
2087 
2088 /* addressing -- note that bin_at(0) does not exist */
2089 #define bin_at(m, i) (&(m)->bins[i])
2090 
2091 /* analog of ++bin */
2092 #define next_bin(b)  (b+1)
2093 
2094 /* Reminders about list directionality within bins */
2095 #define first(b)     ((b)->fd)
2096 #define last(b)      ((b)->bk)
2097 
2098 /* Take a chunk off a bin list */
2099 #define unlink(P, BK, FD) {                                            \
2100   FD = P->fd;                                                          \
2101   BK = P->bk;                                                          \
2102   FD->bk = BK;                                                         \
2103   BK->fd = FD;                                                         \
2104 }
2105 
2106 /*
2107   Indexing
2108 
2109     Bins for sizes < 512 bytes contain chunks of all the same size, spaced
2110     8 bytes apart. Larger bins are approximately logarithmically spaced:
2111 
2112     64 bins of size       8
2113     32 bins of size      64
2114     16 bins of size     512
2115      8 bins of size    4096
2116      4 bins of size   32768
2117      2 bins of size  262144
2118      1 bin  of size what's left
2119 
2120     The bins top out around 1MB because we expect to service large
2121     requests via mmap.
2122 */
2123 
2124 #define NBINS              96
2125 #define NSMALLBINS         32
2126 #define SMALLBIN_WIDTH      8
2127 #define MIN_LARGE_SIZE    256
2128 
2129 #define in_smallbin_range(sz)  \
2130   ((CHUNK_SIZE_T)(sz) < (CHUNK_SIZE_T)MIN_LARGE_SIZE)
2131 
2132 #define smallbin_index(sz)     (((unsigned)(sz)) >> 3)
2133 
2134 /*
2135   Compute index for size. We expect this to be inlined when
2136   compiled with optimization, else not, which works out well.
2137 */
largebin_index(size_t sz)2138 static int largebin_index(size_t sz) {
2139 
2140   unsigned long  xx = sz >> SMALLBIN_WIDTH;
2141 
2142   if (xx < 0x10000)
2143     {
2144       unsigned int  m;           /* bit position of highest set bit of m */
2145 
2146       /* On intel, use BSRL instruction to find highest bit */
2147 #if defined(__GNUC__) && defined(i386) && !defined(USE_UNO)
2148 
2149       unsigned int  x = (unsigned int) xx;
2150 
2151       __asm__("bsrl %1,%0\n\t"
2152 	      : "=r" (m)
2153 	      : "rm"  (x));
2154 
2155 #elif defined(__GNUC__) && defined(x86_64) && !defined(USE_UNO)
2156 
2157       __asm__("bsrq %1,%0\n\t"
2158               : "=r" (m)
2159               : "rm"  (xx));
2160 
2161 #else
2162 
2163       /* Taken from Bit Twiddling Hacks
2164        * http://graphics.stanford.edu/~seander/bithacks.html
2165        * public domain
2166        */
2167       unsigned int  v  = (unsigned int) xx;
2168       register unsigned int shift;
2169 
2170       m =     (v > 0xFFFF) << 4; v >>= m;
2171       shift = (v > 0xFF  ) << 3; v >>= shift; m |= shift;
2172       shift = (v > 0xF   ) << 2; v >>= shift; m |= shift;
2173       shift = (v > 0x3   ) << 1; v >>= shift; m |= shift;
2174       m |= (v >> 1);
2175 
2176 #endif
2177 
2178       /* Use next 2 bits to create finer-granularity bins */
2179       return NSMALLBINS + (m << 2) + ((sz >> (m + 6)) & 3);
2180     }
2181   else
2182     {
2183       return NBINS-1;
2184     }
2185 }
2186 
2187 #define bin_index(sz) \
2188  ((in_smallbin_range(sz)) ? smallbin_index(sz) : largebin_index(sz))
2189 
2190 /*
2191   FIRST_SORTED_BIN_SIZE is the chunk size corresponding to the
2192   first bin that is maintained in sorted order. This must
2193   be the smallest size corresponding to a given bin.
2194 
2195   Normally, this should be MIN_LARGE_SIZE. But you can weaken
2196   best fit guarantees to sometimes speed up malloc by increasing value.
2197   Doing this means that malloc may choose a chunk that is
2198   non-best-fitting by up to the width of the bin.
2199 
2200   Some useful cutoff values:
2201       512 - all bins sorted
2202      2560 - leaves bins <=     64 bytes wide unsorted
2203     12288 - leaves bins <=    512 bytes wide unsorted
2204     65536 - leaves bins <=   4096 bytes wide unsorted
2205    262144 - leaves bins <=  32768 bytes wide unsorted
2206        -1 - no bins sorted (not recommended!)
2207 */
2208 
2209 /* #define FIRST_SORTED_BIN_SIZE 65536 */
2210 
2211 #define FIRST_SORTED_BIN_SIZE MIN_LARGE_SIZE
2212 
2213 
2214 /*
2215   Unsorted chunks
2216 
2217     All remainders from chunk splits, as well as all returned chunks,
2218     are first placed in the "unsorted" bin. They are then placed
2219     in regular bins after malloc gives them ONE chance to be used before
2220     binning. So, basically, the unsorted_chunks list acts as a queue,
2221     with chunks being placed on it in free (and malloc_consolidate),
2222     and taken off (to be either used or placed in bins) in malloc.
2223 */
2224 
2225 /* The otherwise unindexable 1-bin is used to hold unsorted chunks. */
2226 #define unsorted_chunks(M)          (bin_at(M, 1))
2227 
2228 /*
2229   Top
2230 
2231     The top-most available chunk (i.e., the one bordering the end of
2232     available memory) is treated specially. It is never included in
2233     any bin, is used only if no other chunk is available, and is
2234     released back to the system if it is very large (see
2235     M_TRIM_THRESHOLD).  Because top initially
2236     points to its own bin with initial zero size, thus forcing
2237     extension on the first malloc request, we avoid having any special
2238     code in malloc to check whether it even exists yet. But we still
2239     need to do so when getting memory from system, so we make
2240     initial_top treat the bin as a legal but unusable chunk during the
2241     interval between initialization and the first call to
2242     sYSMALLOc. (This is somewhat delicate, since it relies on
2243     the 2 preceding words to be zero during this interval as well.)
2244 */
2245 
2246 /* Conveniently, the unsorted bin can be used as dummy top on first call */
2247 #define initial_top(M)              (unsorted_chunks(M))
2248 
2249 /*
2250   Binmap
2251 
2252     To help compensate for the large number of bins, a one-level index
2253     structure is used for bin-by-bin searching.  `binmap' is a
2254     bitvector recording whether bins are definitely empty so they can
2255     be skipped over during during traversals.  The bits are NOT always
2256     cleared as soon as bins are empty, but instead only
2257     when they are noticed to be empty during traversal in malloc.
2258 */
2259 
2260 /* Conservatively use 32 bits per map word, even if on 64bit system */
2261 #define BINMAPSHIFT      5
2262 #define BITSPERMAP       (1U << BINMAPSHIFT)
2263 #define BINMAPSIZE       (NBINS / BITSPERMAP)
2264 
2265 #define idx2block(i)     ((i) >> BINMAPSHIFT)
2266 #define idx2bit(i)       ((1U << ((i) & ((1U << BINMAPSHIFT)-1))))
2267 
2268 #define mark_bin(m,i)    ((m)->binmap[idx2block(i)] |=  idx2bit(i))
2269 #define unmark_bin(m,i)  ((m)->binmap[idx2block(i)] &= ~(idx2bit(i)))
2270 #define get_binmap(m,i)  ((m)->binmap[idx2block(i)] &   idx2bit(i))
2271 
2272 /*
2273   Fastbins
2274 
2275     An array of lists holding recently freed small chunks.  Fastbins
2276     are not doubly linked.  It is faster to single-link them, and
2277     since chunks are never removed from the middles of these lists,
2278     double linking is not necessary. Also, unlike regular bins, they
2279     are not even processed in FIFO order (they use faster LIFO) since
2280     ordering doesn't much matter in the transient contexts in which
2281     fastbins are normally used.
2282 
2283     Chunks in fastbins keep their inuse bit set, so they cannot
2284     be consolidated with other free chunks. malloc_consolidate
2285     releases all chunks in fastbins and consolidates them with
2286     other free chunks.
2287 */
2288 
2289 typedef struct chunkinfo* mfastbinptr;
2290 
2291 /* offset 2 to use otherwise unindexable first 2 bins */
2292 #define fastbin_index(sz)        ((((unsigned int)(sz)) >> 3) - 2)
2293 
2294 /* The maximum fastbin request size we support */
2295 #define MAX_FAST_SIZE     80
2296 
2297 #define NFASTBINS  (fastbin_index(request2size(MAX_FAST_SIZE))+1)
2298 
2299 /*
2300   FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free()
2301   that triggers automatic consolidation of possibly-surrounding
2302   fastbin chunks. This is a heuristic, so the exact value should not
2303   matter too much. It is defined at half the default trim threshold as a
2304   compromise heuristic to only attempt consolidation if it is likely
2305   to lead to trimming. However, it is not dynamically tunable, since
2306   consolidation reduces fragmentation surrounding loarge chunks even
2307   if trimming is not used.
2308 */
2309 
2310 #define FASTBIN_CONSOLIDATION_THRESHOLD  \
2311   ((unsigned long)(DEFAULT_TRIM_THRESHOLD) >> 1)
2312 
2313 /*
2314   Since the lowest 2 bits in max_fast don't matter in size comparisons,
2315   they are used as flags.
2316 */
2317 
2318 /*
2319   ANYCHUNKS_BIT held in max_fast indicates that there may be any
2320   freed chunks at all. It is set true when entering a chunk into any
2321   bin.
2322 */
2323 
2324 #define ANYCHUNKS_BIT        (1U)
2325 
2326 #define have_anychunks(M)     (((M)->max_fast &  ANYCHUNKS_BIT))
2327 #define set_anychunks(M)      ((M)->max_fast |=  ANYCHUNKS_BIT)
2328 #define clear_anychunks(M)    ((M)->max_fast &= ~ANYCHUNKS_BIT)
2329 
2330 /*
2331   FASTCHUNKS_BIT held in max_fast indicates that there are probably
2332   some fastbin chunks. It is set true on entering a chunk into any
2333   fastbin, and cleared only in malloc_consolidate.
2334 */
2335 
2336 #define FASTCHUNKS_BIT        (2U)
2337 
2338 #define have_fastchunks(M)   (((M)->max_fast &  FASTCHUNKS_BIT))
2339 #define set_fastchunks(M)    ((M)->max_fast |=  (FASTCHUNKS_BIT|ANYCHUNKS_BIT))
2340 #define clear_fastchunks(M)  ((M)->max_fast &= ~(FASTCHUNKS_BIT))
2341 
2342 /*
2343    Set value of max_fast.
2344    Use impossibly small value if 0.
2345 */
2346 
2347 #define set_max_fast(M, s) \
2348   (M)->max_fast = (((s) == 0)? SMALLBIN_WIDTH: request2size(s)) | \
2349   ((M)->max_fast &  (FASTCHUNKS_BIT|ANYCHUNKS_BIT))
2350 
2351 #define get_max_fast(M) \
2352   ((M)->max_fast & ~(FASTCHUNKS_BIT | ANYCHUNKS_BIT))
2353 
2354 
2355 /*
2356   morecore_properties is a status word holding dynamically discovered
2357   or controlled properties of the morecore function
2358 */
2359 
2360 #define MORECORE_CONTIGUOUS_BIT  (1U)
2361 
2362 #define contiguous(M) \
2363         (((M)->morecore_properties &  MORECORE_CONTIGUOUS_BIT))
2364 #define noncontiguous(M) \
2365         (((M)->morecore_properties &  MORECORE_CONTIGUOUS_BIT) == 0)
2366 #define set_contiguous(M) \
2367         ((M)->morecore_properties |=  MORECORE_CONTIGUOUS_BIT)
2368 #define set_noncontiguous(M) \
2369         ((M)->morecore_properties &= ~MORECORE_CONTIGUOUS_BIT)
2370 
2371 #define MORECORE_32BIT_BIT  (2U)
2372 
2373 #define morecore32bit(M) \
2374         (((M)->morecore_properties &  MORECORE_32BIT_BIT))
2375 #define nonmorecore32bit(M) \
2376         (((M)->morecore_properties &  MORECORE_32BIT_BIT) == 0)
2377 #define set_morecore32bit(M) \
2378         ((M)->morecore_properties |=  MORECORE_32BIT_BIT)
2379 #define set_nonmorecore32bit(M) \
2380         ((M)->morecore_properties &= ~MORECORE_32BIT_BIT)
2381 
2382 
2383 
2384 /* ----------------- dnmalloc -------------------- */
2385 
2386 /* size of pages */
2387 #define PGSIZE malloc_getpagesize
2388 /* pointer size */
2389 #define PTRSIZE sizeof(long)
2390 
2391 
2392 
2393 /* TODO: mmapped chunks are always multiples of pagesize -> we're wasting
2394    address space: the hashtable has granularity of 16*8, set it to something
2395    closer to pagesize for mmapped chunks (current waste: 32 positions/mmapped
2396    page)
2397 */
2398 
2399 /* The maximum heap size that dnmalloc can operate with
2400  * represented in hex to avoid annoying gcc warning
2401  *
2402  * Avoid integer overflow, cover complete 32bit address
2403  * space for portability. With deferred allocation, the
2404  * hashtable size is a non-issue.
2405  */
2406 #define HEAPMAXSIZE_HALF 0x80000000UL
2407 
2408 /* How many elements are stored in the linked list */
2409 #define LINKEDLSTELS 8
2410 
2411 /* Minimum size of a chunk */
2412 
2413 #if (SIZEOF_UNSIGNED_LONG == 8) || defined(__arch64__) || defined(__ia64__) || defined(__x86_64__) || defined(__LP64__) || defined(__64BIT__) || defined(_LP64) || defined(_M_IA64) || (defined(_MIPS_SZLONG) && (_MIPS_SZLONG == 64))
2414 #  define MINCHUNKSIZE 32
2415 #else
2416 #  define MINCHUNKSIZE 16
2417 #endif
2418 
2419 
2420 /* The amount of hashtable entries for each page:
2421 Pagesize divded by the numer of elements in the linkedlists
2422 divided by the minimum chunk size
2423 */
2424 #define CHUNKINFOPAGE (PGSIZE / LINKEDLSTELS / MINCHUNKSIZE)
2425 
2426 /* The amount of hashtable entries needed to manage the memory:
2427 Maximum heap size divided by page size multiplied by the amount
2428 of chunk info's per page
2429 */
2430 #define AMOUNTHASH ((HEAPMAXSIZE_HALF / PGSIZE) * CHUNKINFOPAGE * 2)
2431 
2432 /* Initial size of the map for the hashtable
2433 Amount of entries muliplied by pointer size
2434 */
2435 #define  HASHTABLESIZE (AMOUNTHASH * PTRSIZE)
2436 
2437 /* Amount of free chunks that the system should allocate at the start */
2438 #define NUMBER_FREE_CHUNKS 32768
2439 
2440 /* Initial size of the chunk info region,
2441 also used when growing the region */
2442 #define CIREGSIZE (NUMBER_FREE_CHUNKS * sizeof(struct chunkinfo))
2443 
2444 /* Start address of the heap */
2445 char *startheap;
2446 
2447 /* pointer to the hashtable: struct chunkinfo **hashtable -> *hashtable[] */
2448 chunkinfoptr *hashtable;
2449 
2450 /* Current chunkinfo region */
2451 struct cireginfo *currciinfo = 0;
2452 struct cireginfo *firstciinfo = 0;
2453 
2454 unsigned long totalcictr = 0;
2455 
2456 
2457 /* Initialize the area for chunkinfos and the hashtable and protect
2458  * it with non-writable pages
2459  */
2460 static void
dnmalloc_init()2461 dnmalloc_init ()
2462 {
2463    void *hashtb;
2464    int mprot;
2465    int flags = MAP_PRIVATE;
2466 
2467    /* Allocate the malloc_state struct */
2468    malloc_mmap_state();
2469 
2470    /* Use MAP_NORESERVE if available (Solaris, HP-UX; most other
2471     * systems use defered allocation anyway.
2472     */
2473 #ifdef MAP_NORESERVE
2474    flags |= MAP_NORESERVE;
2475 #endif
2476 
2477    /* Always start at 0, hashtable covers whole 32bit address space
2478     */
2479 #define STARTHEAP_IS_ZERO
2480    startheap = 0;
2481 
2482    /* Map space for the hashtable */
2483 #if PARANOIA > 1
2484    hashtb = MMAP(0, HASHTABLESIZE+(2*PGSIZE), PROT_READ|PROT_WRITE, flags);
2485 #else
2486    hashtb = MMAP(0, HASHTABLESIZE+PGSIZE, PROT_READ|PROT_WRITE, flags);
2487 #endif
2488 
2489 #ifdef NDEBUG
2490    if (hashtb == MAP_FAILED) {
2491       fprintf (stderr, "Couldn't mmap hashtable: %s\n", strerror (errno));
2492       abort ();
2493    }
2494 #else
2495    assert(hashtb != MAP_FAILED);
2496 #endif
2497 
2498    /* Protect the hashtable with non-writable pages */
2499    mprot = mprotect(hashtb, (size_t) PGSIZE, PROT_NONE);
2500 #ifdef NDEBUG
2501    if (mprot == -1) {
2502      fprintf (stderr, "Couldn't mprotect first non-rw page for hashtable: %s\n",
2503 	      strerror (errno));
2504      abort ();
2505    }
2506 #else
2507    assert(mprot != -1);
2508 #endif
2509 
2510    /* HP-UX: Cannot do arithmetic with pointers to objects of unknown size. */
2511    hashtable = (chunkinfoptr *) (((char*)hashtb) + PGSIZE);
2512 
2513    /* Protect the hashtable with non-writable pages */
2514 #if PARANOIA > 1
2515    mprot = mprotect((void*)((char*)hashtb+HASHTABLESIZE+PGSIZE), (size_t) PGSIZE, PROT_NONE);
2516 #ifdef NDEBUG
2517    if (mprot == -1) {
2518      fprintf (stderr, "Couldn't mprotect last non-rw page for hashtable: %s\n",
2519 	      strerror (errno));
2520      abort ();
2521    }
2522 #else
2523    assert(mprot != -1);
2524 #endif
2525 #endif
2526 }
2527 
2528 
2529 
2530 /* Extend the region for chunk infos by mapping more memory before the region */
2531 static void
cireg_extend()2532 cireg_extend ()
2533 {
2534    void *newcireg;
2535    int mprot;
2536    struct cireginfo *tempciinfo = 0;
2537 
2538 #if PARANOIA > 1
2539    newcireg = MMAP(0, CIREGSIZE+(2*PGSIZE), PROT_READ|PROT_WRITE, MAP_PRIVATE);
2540 #else
2541    newcireg = MMAP(0, CIREGSIZE+PGSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE);
2542 #endif
2543 
2544 #ifdef NDEBUG
2545    if (newcireg == MAP_FAILED)
2546    {
2547 	   fprintf (stderr, "Couldn't extend chunkinfo region: %s\n",
2548 		    strerror (errno));
2549 	   abort ();
2550    }
2551 #else
2552    assert(newcireg != MAP_FAILED);
2553 #endif
2554    mprot = mprotect(newcireg, PGSIZE, PROT_NONE);
2555 #ifdef NDEBUG
2556    if (mprot == -1) {
2557 	   fprintf (stderr, "Couldn't mprotect first non-rw page for extended region: %s\n",
2558 		    strerror (errno));
2559 	   abort ();
2560    }
2561 #else
2562    assert(mprot != -1);
2563 #endif
2564    newcireg = ((char*)newcireg)+PGSIZE;
2565 
2566 #if PARANOIA > 1
2567    mprot = mprotect((void*)((char*)newcireg+CIREGSIZE), (size_t) PGSIZE, PROT_NONE);
2568 #ifdef NDEBUG
2569    if (mprot == -1) {
2570      fprintf (stderr, "Couldn't mprotect last non-rw page for extended region: %s\n",
2571 	      strerror (errno));
2572      abort ();
2573    }
2574 #else
2575    assert(mprot != -1);
2576 #endif
2577 #endif
2578 
2579    tempciinfo = currciinfo;
2580    currciinfo = (struct cireginfo *) newcireg;
2581    if (tempciinfo)
2582 	   tempciinfo->next = currciinfo;
2583    currciinfo->position = 1;
2584    currciinfo->freecounter = NUMBER_FREE_CHUNKS;
2585    if (!firstciinfo)
2586 	   firstciinfo = currciinfo;
2587    totalcictr++;
2588    VALGRIND_CREATE_MEMPOOL(newcireg, 0, 0);
2589 }
2590 
2591 
2592 /* Get a free chunkinfo */
2593 static chunkinfoptr
cireg_getfree()2594 cireg_getfree ()
2595 {
2596    chunkinfoptr freeci;
2597    chunkinfoptr freelst = 0;
2598    struct cireginfo *newciinfo = firstciinfo;
2599 
2600    if (newciinfo) {
2601    	freelst = newciinfo->freelist;
2602 
2603 	if (!freelst && newciinfo->next) {
2604 	  do {
2605 	    newciinfo = newciinfo->next;
2606 	    freelst = newciinfo->freelist;
2607 	  } while (!freelst && newciinfo->next);
2608 	}
2609    }
2610 
2611    /* Check if there are any free chunkinfos on the list of free chunkinfos */
2612    if (freelst)
2613    {
2614      freeci = freelst;
2615      newciinfo->freecounter--;
2616      newciinfo->freelist = freelst->fd;
2617 
2618      VALGRIND_MEMPOOL_ALLOC((char*)currciinfo, (char*)freeci,
2619 			    sizeof(struct chunkinfo));
2620 
2621      freeci->prev_size = 0;
2622      freeci->size      = 0;
2623      freeci->req       = 0;
2624      freeci->hash_next = NULL;
2625      freeci->fd        = NULL;
2626      freeci->bk        = NULL;
2627      freeci->chunk     = NULL;
2628      return (freeci);
2629    }
2630    else
2631    {
2632      /* No free chunkinfos, check if chunkinfo region still has place
2633       * for a chunkinfo. If not, extend the region.
2634       */
2635      if (UNLIKELY(!currciinfo || currciinfo->position == NUMBER_FREE_CHUNKS))
2636        cireg_extend ();
2637      /* Get a chunkinfo from the chunkinfo region */
2638      freeci = (chunkinfoptr) currciinfo + currciinfo->position;
2639      currciinfo->freecounter--;
2640      currciinfo->position++;
2641 
2642      VALGRIND_MEMPOOL_ALLOC((char*)currciinfo, (char*)freeci,
2643 			    sizeof(struct chunkinfo));
2644 
2645      return (freeci);
2646    }
2647 }
2648 
freeciregion(struct cireginfo * freeme)2649 static void freeciregion(struct cireginfo *freeme) {
2650   /* free the chunkinfo region */
2651   struct cireginfo *newciinfo = firstciinfo;
2652   struct cireginfo *prevciinfo = firstciinfo;
2653   void *unmapme;
2654 
2655   while (newciinfo && newciinfo != freeme) {
2656     prevciinfo = newciinfo;
2657     newciinfo = newciinfo->next;
2658   }
2659   assert(freeme == newciinfo); /* rw */
2660   assert(newciinfo != NULL);   /* rw */
2661   if (newciinfo)
2662     prevciinfo->next = newciinfo->next;
2663   unmapme = (void *) ((char*)freeme - PGSIZE);
2664   VALGRIND_DESTROY_MEMPOOL((char*)freeme);
2665 #if PARANOIA > 1
2666   munmap(unmapme, CIREGSIZE+(2*PGSIZE));
2667 #else
2668   munmap(unmapme, CIREGSIZE+PGSIZE);
2669 #endif
2670 }
2671 
2672 
freecilst_add(chunkinfoptr p)2673 static void freecilst_add(chunkinfoptr p) {
2674 
2675   struct cireginfo *newciinfo;
2676 
2677   newciinfo = currciinfo;
2678   if (((chunkinfoptr) newciinfo < p) && (p  <  (chunkinfoptr) (newciinfo+NUMBER_FREE_CHUNKS))) {
2679     p->fd = newciinfo->freelist;
2680     newciinfo->freelist = p;
2681     newciinfo->freecounter++;
2682     VALGRIND_MEMPOOL_FREE((char*)newciinfo, (char*)p);
2683     VALGRIND_MAKE_MEM_DEFINED(p,sizeof(struct chunkinfo));
2684     VALGRIND_MAKE_MEM_NOACCESS(p->size,     sizeof(INTERNAL_SIZE_T));
2685     VALGRIND_MAKE_MEM_NOACCESS(p->req,      sizeof(INTERNAL_SIZE_T));
2686     VALGRIND_MAKE_MEM_NOACCESS(p->bk,       sizeof(struct chunkinfo*));
2687     VALGRIND_MAKE_MEM_NOACCESS(p->chunk,    sizeof(mchunkptr));
2688   } else {
2689     newciinfo = firstciinfo;
2690     if (newciinfo) {
2691       do {
2692 	if (((chunkinfoptr) newciinfo < p) && (p  <  (chunkinfoptr) (newciinfo+NUMBER_FREE_CHUNKS))) {
2693 	  p->fd = newciinfo->freelist;
2694 	  newciinfo->freelist = p;
2695 	  newciinfo->freecounter++;
2696 	  VALGRIND_MEMPOOL_FREE((char*)newciinfo, (char*)p);
2697 	  VALGRIND_MAKE_MEM_DEFINED(p,sizeof(struct chunkinfo));
2698 	  VALGRIND_MAKE_MEM_NOACCESS(p->size,     sizeof(INTERNAL_SIZE_T));
2699 	  VALGRIND_MAKE_MEM_NOACCESS(p->req,      sizeof(INTERNAL_SIZE_T));
2700 	  VALGRIND_MAKE_MEM_NOACCESS(p->bk,       sizeof(struct chunkinfo*));
2701 	  VALGRIND_MAKE_MEM_NOACCESS(p->chunk,    sizeof(mchunkptr));
2702 	  if (UNLIKELY(newciinfo->freecounter == NUMBER_FREE_CHUNKS))
2703 	    freeciregion(newciinfo);
2704 	  break;
2705 	}
2706 	newciinfo = newciinfo->next;
2707       } while (newciinfo);
2708     }
2709   }
2710 }
2711 
2712 /* Calculate the hash table entry for a chunk */
2713 #ifdef STARTHEAP_IS_ZERO
2714 #define hash(p)  (((unsigned long) p) >> 7)
2715 #else
2716 #define hash(p)  (((unsigned long) p - (unsigned long) startheap) >> 7)
2717 #endif
2718 
2719 static void
hashtable_add(chunkinfoptr ci)2720 hashtable_add (chunkinfoptr ci)
2721 {
2722    chunkinfoptr temp, next;
2723    unsigned long hashval;
2724    mchunkptr cic = chunk (ci);
2725 
2726    hashval = hash (cic);
2727 
2728    if (hashval < AMOUNTHASH) {
2729 
2730      temp = hashtable[hashval];
2731 
2732 #ifdef DNMALLOC_DEBUG
2733      fprintf(stderr, "hashtable_add: %p, %lu\n", chunk(ci), hashval);
2734 #endif
2735 
2736      /* If no pointer to a chunk info list is stored at this location
2737       * in the hashtable or if the chunk's address is smaller than the
2738       * one present, add the chunk to the front of the linked list
2739       */
2740      if (temp == 0 || chunk (temp) > cic)
2741        {
2742 	 ci->hash_next = temp;
2743 	 hashtable[hashval] = ci;
2744 	 if (!temp) /* more likely case */
2745 	   goto out;
2746 	 temp->prev_size = chunksize(ci);
2747 	 return;
2748        }
2749      else
2750        {
2751 	 /* We must place the chunk in the linked list for this hashentry
2752 	  * Loop to end of list or to a position where temp's chunk's address
2753 	  * is larger than the new chunkinfo's chunk's address
2754 	  */
2755 	 if (!temp->hash_next || (chunk (temp->hash_next) > cic))
2756 	   {
2757 	     ci->hash_next = temp->hash_next;
2758 	     temp->hash_next = ci;
2759 	   }
2760 	 else
2761 	   {
2762 	     while ((temp->hash_next != 0) && (chunk (temp->hash_next) < cic))
2763 	       {
2764 		 temp = temp->hash_next;
2765 	       }
2766 	     /* Place in linked list if not already there */
2767 	     if (!temp->hash_next || !(chunk (temp->hash_next) == cic))
2768 	       {
2769 		 ci->hash_next = temp->hash_next;
2770 		 temp->hash_next = ci;
2771 	       }
2772 	   }
2773        }
2774    }
2775    else {
2776 #ifdef DNMALLOC_CHECKS
2777      if (hashval >= AMOUNTHASH) {
2778        fprintf(stderr, "Dnmalloc error: trying to write outside of the bounds of the hashtable, this is definitely a bug, please email dnmalloc@fort-knox.org (hashval: %lu, AMOUNTHASH: %lu, HEAPMAXSIZE_HALF %lu PGSIZE %ld CHUNKINFOPAGE %ld chunk: %p, chunkinfo: %p, startheap: %p).\n", hashval, AMOUNTHASH, HEAPMAXSIZE_HALF, PGSIZE, CHUNKINFOPAGE, chunk(ci), ci, startheap);
2779 	   abort();
2780      }
2781 #else
2782      assert(hashval < AMOUNTHASH);
2783 #endif
2784    }
2785 
2786  out:
2787    next = next_chunkinfo(ci);
2788    if (!next)
2789      return;
2790    next->prev_size = chunksize(ci);
2791 }
2792 
2793 static void
hashtable_insert(chunkinfoptr ci_orig,chunkinfoptr ci_insert)2794 hashtable_insert (chunkinfoptr ci_orig, chunkinfoptr ci_insert)
2795 {
2796    chunkinfoptr next;
2797 
2798 #ifdef DNMALLOC_DEBUG
2799    fprintf(stderr, "hashtable_ins: %p, %lu\n", chunk(ci_insert),
2800 	   (unsigned long)hash(chunk(ci_insert));
2801 #endif
2802 
2803    if (hash(chunk(ci_orig)) != hash(chunk(ci_insert))) {
2804       hashtable_add(ci_insert);
2805    }
2806    else {
2807 
2808       ci_insert->hash_next = ci_orig->hash_next;
2809       ci_orig->hash_next = ci_insert;
2810 
2811       /* added for prevsize */
2812       if (!(ci_insert->hash_next))
2813 	      next = next_chunkinfo(ci_insert);
2814       else
2815 	      next = ci_insert->hash_next;
2816 
2817       if (!next)
2818 	{
2819 	  ci_insert->prev_size = chunksize(ci_orig);
2820 	}
2821       else
2822 	{
2823 	  next->prev_size = chunksize(ci_insert);
2824 	  ci_insert->prev_size = chunksize(ci_orig);
2825 	}
2826    }
2827 }
2828 
2829 static void
2830 hashtable_remove (mchunkptr p)
2831 {
2832   chunkinfoptr prevtemp, temp;
2833   unsigned long hashval;
2834 
2835   hashval = hash (p);
2836 #ifdef DNMALLOC_DEBUG
2837   fprintf(stderr, "hashtable_rem: %p, %lu\n", p, hashval);
2838 #endif
2839   assert(hashval < AMOUNTHASH); /* rw */
2840   prevtemp = temp = hashtable[hashval];
2841   if (chunk (temp) == p) {
2842     hashtable[hashval] = temp->hash_next;
2843   }
2844   else
2845     {
2846       if (temp && chunk (temp) != p) {
2847 	do
2848 	  {
2849 	    prevtemp = temp;
2850 	    temp = temp->hash_next;
2851 	  } while (temp && chunk (temp) != p);
2852       }
2853 #ifdef DNMALLOC_CHECKS
2854       if (!temp) {
2855 	fprintf (stderr,
2856 		 "Dnmalloc error (hash_rm): could not find a chunkinfo for the chunk %p in the hashtable at entry %lu\n This is definitely a bug, please report it to dnmalloc@fort-knox.org.\n",
2857 		 p, hashval);
2858 	abort();
2859       }
2860 #else
2861       assert(temp != NULL);
2862 #endif
2863       if (temp) prevtemp->hash_next = temp->hash_next;
2864     }
2865 }
2866 
2867 /* mmapped chunks are multiples of pagesize, no hash_nexts,
2868  * just remove from the hashtable
2869  */
2870 #define hashtable_remove_mmapped(p) hashtable[hash(p)] = 0;
2871 
2872 static void
2873 hashtable_skiprm (chunkinfoptr ci_orig, chunkinfoptr ci_todelete)
2874 {
2875    unsigned long hashval;
2876    chunkinfoptr next;
2877 
2878 #ifdef DNMALLOC_DEBUG
2879    fprintf(stderr, "hashtable_skiprm: %p, %lu\n", chunk(ci_todelete), hash(chunk(ci_todelete)));
2880 #endif
2881 
2882    if (ci_orig->hash_next != ci_todelete) {
2883      hashval = hash(chunk(ci_todelete));
2884      assert(hashval < AMOUNTHASH); /* rw */
2885 #ifdef DNMALLOC_CHECKS
2886      if (hashtable[hashval] != ci_todelete ) {
2887 	   fprintf(stderr, "Dnmalloc error: trying to delete wrong value (hash: %lu): ci_todelete: %p (%p), hashtable[hashval]: %p (%p)\n This is definitely a bug, please report it to dnmalloc@fort-knox.org.\n", hashval, ci_todelete, chunk(ci_todelete), hashtable[hashval], chunk(hashtable[hashval]));
2888      }
2889 #else
2890      assert(hashtable[hashval] == ci_todelete);
2891 #endif
2892      hashtable[hashval] = ci_todelete->hash_next;
2893    }
2894 
2895    else {
2896      ci_orig->hash_next = ci_todelete->hash_next;
2897      if (!ci_orig->hash_next) {
2898        next = next_chunkinfo(ci_orig);
2899      } else {
2900        next = ci_orig->hash_next;
2901      }
2902      if (next)
2903        next->prev_size = chunksize(ci_orig);
2904 
2905    }
2906 }
2907 
2908 
2909 static chunkinfoptr
2910 hashtable_lookup (mchunkptr p)
2911 {
2912    chunkinfoptr ci;
2913    unsigned long hashval;
2914 
2915    /* if we were called wrongly
2916     * if ((char *) p < startheap) return 0;
2917     */
2918    if ((char *) p >= startheap)
2919      {
2920        hashval = hash (p);
2921        assert(hashval < AMOUNTHASH); /* rw */
2922        ci = hashtable[hashval];
2923        if (ci && chunk (ci) == p)
2924 	 return ci;
2925 
2926        if (ci) {
2927 	 do {
2928 	   ci = ci->hash_next;
2929 	 } while (ci && chunk (ci) != p);
2930        }
2931 #ifdef DNMALLOC_CHECKS
2932        /* This should never occur but if it does, we'd like to know */
2933        if (!ci) {
2934 	 fprintf (stderr,
2935 		  "Dnmalloc error: could not find a chunkinfo for the chunk %p in the hashtable at entry %lu\n This is definitely a bug, please report it to dnmalloc@fort-knox.org.\n",
2936 		  p, hashval);
2937 	 abort();
2938        }
2939 #else
2940        assert(ci != NULL);
2941 #endif
2942        return ci;
2943      }
2944    return 0;
2945 }
2946 
2947 
2948 
2949 /*
2950    ----------- Internal state representation and initialization -----------
2951 */
2952 
2953 struct malloc_state {
2954 
2955   /* The maximum chunk size to be eligible for fastbin */
2956   INTERNAL_SIZE_T  max_fast;   /* low 2 bits used as flags */
2957 
2958   /* Fastbins */
2959   mfastbinptr      fastbins[NFASTBINS];
2960 
2961   /* Base of the topmost chunk -- not otherwise kept in a bin */
2962   chunkinfoptr        top;
2963 
2964   /* The remainder from the most recent split of a small request */
2965   chunkinfoptr        last_remainder;
2966 
2967   /* Normal bins */
2968   struct chunkinfo bins[NBINS];
2969 
2970   /* Bitmap of bins. Trailing zero map handles cases of largest binned size */
2971   unsigned int     binmap[BINMAPSIZE+1];
2972 
2973   /* Tunable parameters */
2974   CHUNK_SIZE_T     trim_threshold;
2975   INTERNAL_SIZE_T  top_pad;
2976   INTERNAL_SIZE_T  mmap_threshold;
2977 
2978   /* Memory map support */
2979   int              n_mmaps;
2980   int              n_mmaps_max;
2981   int              max_n_mmaps;
2982 
2983   /* Cache malloc_getpagesize */
2984   unsigned int     pagesize;
2985 
2986   /* Canary */
2987   char             guard_stored[GUARD_SIZE];
2988 
2989   /* Track properties of MORECORE */
2990   unsigned int     morecore_properties;
2991 
2992   /* Statistics */
2993   INTERNAL_SIZE_T  mmapped_mem;
2994   INTERNAL_SIZE_T  sbrked_mem;
2995   INTERNAL_SIZE_T  max_sbrked_mem;
2996   INTERNAL_SIZE_T  max_mmapped_mem;
2997   INTERNAL_SIZE_T  max_total_mem;
2998 };
2999 
3000 typedef struct malloc_state *mstate;
3001 
3002 /*
3003    There is exactly one instance of this struct in this malloc.
3004    If you are adapting this malloc in a way that does NOT use a static
3005    malloc_state, you MUST explicitly zero-fill it before using. This
3006    malloc relies on the property that malloc_state is initialized to
3007    all zeroes (as is true of C statics).
3008 */
3009 
3010 static struct malloc_state * av_ = NULL;  /* never directly referenced */
3011 
3012 /*
3013    All uses of av_ are via get_malloc_state().
3014    At most one "call" to get_malloc_state is made per invocation of
3015    the public versions of malloc and free, but other routines
3016    that in turn invoke malloc and/or free may call more then once.
3017    Also, it is called in check* routines if DEBUG is set.
3018 */
3019 
3020 #define get_malloc_state() (av_)
3021 
3022 /*
3023   Initialize a malloc_state struct.
3024 
3025   This is called only from within malloc_consolidate, which needs
3026   be called in the same contexts anyway.  It is never called directly
3027   outside of malloc_consolidate because some optimizing compilers try
3028   to inline it at all call points, which turns out not to be an
3029   optimization at all. (Inlining it in malloc_consolidate is fine though.)
3030 */
3031 
3032 #if __STD_C
3033 static void malloc_mmap_state(void)
3034 #else
3035 static void malloc_mmap_state()
3036 #endif
3037 {
3038   int mprot;
3039   unsigned long pagesize = malloc_getpagesize;
3040   size_t size = (sizeof(struct malloc_state) + pagesize - 1) & ~(pagesize - 1);
3041 
3042   void * foo = MMAP(0, size+(2*pagesize), PROT_READ|PROT_WRITE, MAP_PRIVATE);
3043 
3044 
3045 #ifdef NDEBUG
3046    if (foo == MAP_FAILED) {
3047       fprintf (stderr, "Couldn't mmap struct malloc_state: %s\n", strerror (errno));
3048       abort ();
3049    }
3050 #else
3051    assert(foo != MAP_FAILED);
3052 #endif
3053 
3054    mprot = mprotect(foo, pagesize, PROT_NONE);
3055 #ifdef NDEBUG
3056    if (mprot == -1) {
3057      fprintf (stderr, "Couldn't mprotect first non-rw page for struct malloc_state: %s\n",
3058 	      strerror (errno));
3059      abort ();
3060    }
3061 #else
3062    assert(mprot != -1);
3063 #endif
3064 
3065    av_ = (struct malloc_state *) ((char*)foo + pagesize);
3066 
3067    MALLOC_ZERO(av_, sizeof(struct malloc_state));
3068 
3069    mprot = mprotect((void*)((char*)foo + size + pagesize), (size_t) pagesize, PROT_NONE);
3070 #ifdef NDEBUG
3071    if (mprot == -1) {
3072      fprintf (stderr,
3073 	      "Couldn't mprotect last non-rw page for struct malloc_state: %s\n",
3074 	      strerror (errno));
3075      abort ();
3076    }
3077 #else
3078    assert(mprot != -1);
3079 #endif
3080 }
3081 
3082 #if __STD_C
3083 static void malloc_init_state(mstate av)
3084 #else
3085 static void malloc_init_state(av) mstate av;
3086 #endif
3087 {
3088   int     i;
3089   mbinptr bin;
3090 
3091   void *  morecore_test = MORECORE(0);
3092   unsigned long hashval;
3093 
3094   /* Test morecore function
3095    */
3096   set_morecore32bit(av);
3097 
3098   if (morecore_test == MORECORE_FAILURE)
3099     {
3100       set_nonmorecore32bit(av);
3101     }
3102   else
3103     {
3104       /* On 64bit systems, the heap may be located above the
3105        * 32bit address space. Since mmap() probably still can be
3106        * convinced to map within 32bit, we don't use sbrk().
3107        */
3108       hashval = hash (morecore_test);
3109       if (hashval >= AMOUNTHASH)
3110 	{
3111 	  set_nonmorecore32bit(av);
3112 	}
3113     }
3114 
3115 
3116   /* Establish circular links for normal bins */
3117   for (i = 1; i < NBINS; ++i) {
3118     bin = bin_at(av,i);
3119     bin->fd = bin->bk = bin;
3120   }
3121 
3122   av->top_pad        = DEFAULT_TOP_PAD;
3123   av->n_mmaps_max    = DEFAULT_MMAP_MAX;
3124   av->mmap_threshold = DEFAULT_MMAP_THRESHOLD;
3125   av->trim_threshold = DEFAULT_TRIM_THRESHOLD;
3126 
3127 #if MORECORE_CONTIGUOUS
3128   set_contiguous(av);
3129 #else
3130   set_noncontiguous(av);
3131 #endif
3132 
3133   set_max_fast(av, DEFAULT_MXFAST);
3134 
3135   av->top = cireg_getfree ();
3136   av->top->chunk     = (mchunkptr) startheap;
3137   av->top->size      = 0;
3138   set_previnuse(av->top);
3139   clear_inuse(av->top);
3140   hashtable[0]       = av->top;
3141   av->pagesize       = malloc_getpagesize;
3142 
3143   memcpy(av->guard_stored, dnmalloc_arc4random(), GUARD_SIZE);
3144 
3145 }
3146 
3147 /*
3148    Other internal utilities operating on mstates
3149 */
3150 
3151 #if __STD_C
3152 static Void_t*  sYSMALLOc(INTERNAL_SIZE_T, mstate);
3153 static int      sYSTRIm(size_t, mstate);
3154 static void     malloc_consolidate(mstate);
3155 #else
3156 static Void_t*  sYSMALLOc();
3157 static int      sYSTRIm();
3158 static void     malloc_consolidate();
3159 #endif
3160 
3161 /* dnmalloc functions */
3162 /* needs mstate so moved here */
3163 
3164 static chunkinfoptr
3165 next_chunkinfo (chunkinfoptr ci)
3166 {
3167    mchunkptr nextp;
3168    unsigned long hashval;
3169    chunkinfoptr cinfonextp;
3170    mstate av = get_malloc_state();
3171 
3172    /* ci is not the last element in the linked list, just
3173       return the next chunkinfo from the list
3174    */
3175    if (!ci->hash_next)
3176      {
3177        /* ci is the last element, find the next chunkinfo by
3178 	* looking up the chunkinfo for the chunk that is after p's chunk
3179 	*/
3180        nextp = (mchunkptr) (((char *) (ci->chunk)) + chunksize (ci));
3181 
3182        if (!(nextp == av->top->chunk))
3183 	 {
3184 	   hashval = hash (nextp);
3185 	   /* assert(hashval < AMOUNTHASH); *//* major bottleneck */
3186 	   cinfonextp = hashtable[hashval];
3187 	   if (cinfonextp && chunk (cinfonextp) == nextp)
3188 	     return cinfonextp;
3189 
3190 #ifdef DNMALLOC_CHECKS_EXTRA
3191 	   /* This seems bogus; a chunkinfo may legally have no nextp if
3192 	    * it's the last one allocated (?)
3193 	    */
3194 	   else {
3195 	     if (cinfonextp)
3196 	       fprintf (stderr,
3197 			"Dnmalloc error: could not find a next chunkinfo for the chunk %p in the hashtable at entry %lu, cinfonextp: %p, chunk(cinfonextp): %p, nextp: %p\n This is definitely a bug, please report it to dnmalloc@fort-knox.org.\n",
3198 			chunk(ci), hashval, cinfonextp, chunk(cinfonextp), nextp);
3199 	     else
3200 	       fprintf (stderr,
3201 			"Dnmalloc error: could not find a next chunkinfo for the chunk %p in the hashtable at entry %lu, cinfonextp: %s, chunk(cinfonextp): %s, nextp: %p\n This is definitely a bug, please report it to dnmalloc@fort-knox.org.\n",
3202 			chunk(ci), hashval, "null", "null", nextp);
3203 	   }
3204 #endif
3205 
3206 	   return NULL;
3207 	 }
3208        else
3209 	 {
3210 	   return av->top;
3211 	 }
3212 
3213      }
3214    else
3215      {
3216        return (ci->hash_next);
3217      }
3218 }
3219 
3220 static int is_next_chunk(chunkinfoptr oldp, chunkinfoptr newp) {
3221 	mchunkptr nextp;
3222 	if (oldp->hash_next == newp)
3223 		return 1;
3224 	nextp = (mchunkptr) (((char *) (oldp->chunk)) + chunksize (oldp));
3225 	if (nextp == chunk(newp))
3226 		return 1;
3227 	return 0;
3228 }
3229 
3230 
3231 
3232 /* Get the chunkinfo of the physically previous chunk */
3233 /* Since we disposed of prev_size, we need this function to find the previous */
3234 
3235 static chunkinfoptr
3236 prev_chunkinfo (chunkinfoptr ci)
3237 {
3238    unsigned int i;
3239    chunkinfoptr prev;
3240    mchunkptr prevchunk = 0;
3241    /* chunkinfoptr temp; */
3242 
3243    /* Get the hashtable location of the chunkinfo */
3244    i = hash (chunk (ci));
3245    assert(i < AMOUNTHASH); /* rw */
3246 
3247    /* Get the first element of the linked list of chunkinfo's that contains p */
3248    prev = hashtable[i];
3249 
3250    if (ci == prev) {
3251      prevchunk = (mchunkptr) (((char *) (ci->chunk)) - (ci->prev_size));
3252      i = hash(prevchunk);
3253      assert(i < AMOUNTHASH); /* rw */
3254      /* Loop over the linked list until we reach the last element */
3255      for (prev = hashtable[i]; prev->hash_next != 0; prev = prev->hash_next) ;
3256    } else {
3257      /* p is not the first element in the linked list, we can just
3258 	loop over the list and return the previous
3259      */
3260      for (prev = hashtable[i]; prev->hash_next != ci; prev = prev->hash_next);
3261    }
3262 
3263    return prev;
3264 }
3265 
3266 
3267 /*
3268   Debugging support
3269   Dnmalloc broke dlmallocs debugging functions, should fix them some
3270   time in the future, for now leave them undefined.
3271 */
3272 
3273 #define check_chunk(P)
3274 #define check_free_chunk(P)
3275 #define check_inuse_chunk(P)
3276 #define check_remalloced_chunk(P,N)
3277 #define check_malloced_chunk(P,N)
3278 #define check_malloc_state()
3279 
3280 
3281 /* ----------- Routines dealing with system allocation -------------- */
3282 
3283 /*
3284   sysmalloc handles malloc cases requiring more memory from the system.
3285   On entry, it is assumed that av->top does not have enough
3286   space to service request for nb bytes, thus requiring that av->top
3287   be extended or replaced.
3288 */
3289 
3290 #if __STD_C
3291 static Void_t* sYSMALLOc(INTERNAL_SIZE_T nb, mstate av)
3292 #else
3293 static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
3294 #endif
3295 {
3296   chunkinfoptr    old_top;        /* incoming value of av->top */
3297   INTERNAL_SIZE_T old_size;       /* its size */
3298   char*           old_end;        /* its end address */
3299 
3300   long            size;           /* arg to first MORECORE or mmap call */
3301   char*           brk;            /* return value from MORECORE */
3302 
3303   long            correction;     /* arg to 2nd MORECORE call */
3304   char*           snd_brk;        /* 2nd return val */
3305 
3306   INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
3307   INTERNAL_SIZE_T end_misalign;   /* partial page left at end of new space */
3308   char*           aligned_brk;    /* aligned offset into brk */
3309 
3310   chunkinfoptr    p;              /* the allocated/returned chunk */
3311   chunkinfoptr    remainder;      /* remainder from allocation */
3312   chunkinfoptr    fencepost;      /* fencepost */
3313   CHUNK_SIZE_T    remainder_size; /* its size */
3314 
3315   CHUNK_SIZE_T    sum;            /* for updating stats */
3316 
3317   size_t          pagemask  = av->pagesize - 1;
3318 
3319 #ifdef DNMALLOC_DEBUG
3320   fprintf(stderr, "Enter sysmalloc\n");
3321 #endif
3322   /*
3323     If there is space available in fastbins, consolidate and retry
3324     malloc from scratch rather than getting memory from system.  This
3325     can occur only if nb is in smallbin range so we didn't consolidate
3326     upon entry to malloc. It is much easier to handle this case here
3327     than in malloc proper.
3328   */
3329 
3330 
3331   if (have_fastchunks(av)) {
3332     Void_t * retval;
3333     assert(in_smallbin_range(nb));
3334     malloc_consolidate(av);
3335 #ifdef DNMALLOC_DEBUG
3336     fprintf(stderr, "Return sysmalloc have_fastchunks\n");
3337 #endif
3338     retval = mALLOc(nb - MALLOC_ALIGN_MASK);
3339     VALGRIND_FREELIKE_BLOCK(retval, 0);
3340     return retval;
3341   }
3342 
3343 
3344   /*
3345     If have mmap, and the request size meets the mmap threshold, and
3346     the system supports mmap, and there are few enough currently
3347     allocated mmapped regions, try to directly map this request
3348     rather than expanding top.
3349   */
3350 
3351   if (UNLIKELY((CHUNK_SIZE_T)(nb) >= (CHUNK_SIZE_T)(av->mmap_threshold) &&
3352 	       (av->n_mmaps < av->n_mmaps_max))) {
3353 
3354     char* mm;             /* return value from mmap call*/
3355 
3356     /*
3357       Round up size to nearest page.  For mmapped chunks, the overhead
3358       is one SIZE_SZ unit larger than for normal chunks, because there
3359       is no following chunk whose prev_size field could be used.
3360     */
3361     size = (nb + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
3362 
3363     /* Don't try if size wraps around 0 */
3364     if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb)) {
3365 
3366 
3367       mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));
3368 
3369       if (mm != (char*)(MORECORE_FAILURE)) {
3370 
3371 	VALGRIND_MAKE_MEM_NOACCESS(mm,size);
3372 
3373         /*
3374           The offset to the start of the mmapped region is stored
3375           in the prev_size field of the chunk. This allows us to adjust
3376           returned start address to meet alignment requirements here
3377           and in memalign(), and still be able to compute proper
3378           address argument for later munmap in free() and realloc().
3379         */
3380 
3381         front_misalign = (INTERNAL_SIZE_T) mm & MALLOC_ALIGN_MASK;
3382 	p = cireg_getfree();
3383 
3384         if (front_misalign > 0) {
3385           correction = MALLOC_ALIGNMENT - front_misalign;
3386           p->chunk = (mchunkptr)(mm + correction);
3387           p->hash_next = (chunkinfoptr) correction;
3388           set_head(p, (size - correction) |INUSE|IS_MMAPPED);
3389         }
3390         else {
3391           p->chunk = (mchunkptr)mm;
3392           p->hash_next = 0;
3393           set_head(p, size|INUSE|IS_MMAPPED);
3394         }
3395         hashtable_add(p);
3396         /* update statistics */
3397 
3398         if (++av->n_mmaps > av->max_n_mmaps)
3399           av->max_n_mmaps = av->n_mmaps;
3400 
3401         sum = av->mmapped_mem += size;
3402         if (sum > (CHUNK_SIZE_T)(av->max_mmapped_mem))
3403           av->max_mmapped_mem = sum;
3404         sum += av->sbrked_mem;
3405         if (sum > (CHUNK_SIZE_T)(av->max_total_mem))
3406           av->max_total_mem = sum;
3407 
3408         check_chunk(p);
3409 
3410 #ifdef DNMALLOC_DEBUG
3411 	fprintf(stderr, "Return mmapped (%lu, total %lu)\n",
3412 		size, (unsigned long)/* size_t */av->max_total_mem );
3413 #endif
3414         return chunk(p);
3415       }
3416     }
3417   }
3418 
3419   /* Record incoming configuration of top */
3420 
3421   old_top  = av->top;
3422   old_size = chunksize(old_top);
3423   old_end  = (char*)(chunk_at_offset(chunk(old_top), old_size));
3424 
3425   brk = snd_brk = (char*)(MORECORE_FAILURE);
3426 
3427   /*
3428      If not the first time through, we require old_size to be
3429      at least MINSIZE and to have prev_inuse set.
3430   */
3431 
3432   /* assert((old_top == initial_top(av) && old_size == 0) ||
3433 	 ((CHUNK_SIZE_T) (old_size) >= MINSIZE &&
3434 	 prev_inuse(old_top))); */
3435 
3436   /* Precondition: not enough current space to satisfy nb request */
3437   assert((CHUNK_SIZE_T)(old_size) < (CHUNK_SIZE_T)(nb + MINSIZE));
3438 
3439   /* Precondition: all fastbins are consolidated */
3440   assert(!have_fastchunks(av));
3441 
3442   /* Request enough space for nb + pad + overhead */
3443   size = nb + av->top_pad + MINSIZE;
3444 
3445   /*
3446     If contiguous, we can subtract out existing space that we hope to
3447     combine with new space. We add it back later only if
3448     we don't actually get contiguous space.
3449   */
3450   if (contiguous(av))
3451     size -= old_size;
3452 
3453   /*
3454     Round to a multiple of page size.
3455     If MORECORE is not contiguous, this ensures that we only call it
3456     with whole-page arguments.  And if MORECORE is contiguous and
3457     this is not first time through, this preserves page-alignment of
3458     previous calls. Otherwise, we correct to page-align below.
3459   */
3460 
3461   size = (size + pagemask) & ~pagemask;
3462 
3463   /*
3464     Don't try to call MORECORE if argument is so big as to appear
3465     negative. Note that since mmap takes size_t arg, it may succeed
3466     below even if we cannot call MORECORE.
3467   */
3468   if (size > 0 && morecore32bit(av))
3469     brk = (char*)(MORECORE(size));
3470 
3471   /*
3472     If have mmap, try using it as a backup when MORECORE fails or
3473     cannot be used. This is worth doing on systems that have "holes" in
3474     address space, so sbrk cannot extend to give contiguous space, but
3475     space is available elsewhere.  Note that we ignore mmap max count
3476     and threshold limits, since the space will not be used as a
3477     segregated mmap region.
3478   */
3479   if (brk != (char*)(MORECORE_FAILURE)) {
3480     av->sbrked_mem += size;
3481     VALGRIND_MAKE_MEM_NOACCESS(brk,size);
3482   }
3483 
3484   else {
3485 
3486 #ifdef DNMALLOC_DEBUG
3487     fprintf(stderr, "Morecore failure in sysmalloc\n");
3488 #endif
3489 
3490     /* Cannot merge with old top, so add its size back in */
3491     if (contiguous(av))
3492       size = (size + old_size + pagemask) & ~pagemask;
3493 
3494     /* If we are relying on mmap as backup, then use larger units */
3495     if ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(MMAP_AS_MORECORE_SIZE))
3496       size = MMAP_AS_MORECORE_SIZE;
3497 
3498     /* Don't try if size wraps around 0 */
3499     if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb)) {
3500 
3501 #ifdef DNMALLOC_DEBUG
3502       fprintf(stderr, "Try mmap in sysmalloc\n");
3503 #endif
3504       brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));
3505 
3506       if (brk != (char*)(MORECORE_FAILURE)) {
3507 
3508 	VALGRIND_MAKE_MEM_NOACCESS(brk,size);
3509 
3510 	av->mmapped_mem += size;
3511 #ifdef DNMALLOC_DEBUG
3512 	fprintf(stderr, "Mmapped successfully in sysmalloc %p\n", brk);
3513 #endif
3514 
3515         /* We do not need, and cannot use, another sbrk call to find end */
3516         snd_brk = brk + size;
3517 
3518         /*
3519            Record that we no longer have a contiguous sbrk region.
3520            After the first time mmap is used as backup, we do not
3521            ever rely on contiguous space since this could incorrectly
3522            bridge regions.
3523         */
3524         set_noncontiguous(av);
3525       }
3526     }
3527   }
3528 
3529   if (brk != (char*)(MORECORE_FAILURE)) {
3530 #ifdef DNMALLOC_DEBUG
3531     fprintf(stderr, "Success path %lu allocated, sbrked %lu\n",
3532 	    size, (unsigned long)av->sbrked_mem);
3533 #endif
3534     /* av->sbrked_mem += size; moved up */
3535 
3536     /*
3537       If MORECORE extends previous space, we can likewise extend top size.
3538     */
3539 
3540     if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {
3541       set_head(old_top, (size + old_size) | PREV_INUSE);
3542 #ifdef DNMALLOC_DEBUG
3543       fprintf(stderr, "Previous space extended\n");
3544 #endif
3545     }
3546 
3547     /*
3548       Otherwise, make adjustments:
3549 
3550       * If the first time through or noncontiguous, we need to call sbrk
3551         just to find out where the end of memory lies.
3552 
3553       * We need to ensure that all returned chunks from malloc will meet
3554         MALLOC_ALIGNMENT
3555 
3556       * If there was an intervening foreign sbrk, we need to adjust sbrk
3557         request size to account for fact that we will not be able to
3558         combine new space with existing space in old_top.
3559 
3560       * Almost all systems internally allocate whole pages at a time, in
3561         which case we might as well use the whole last page of request.
3562         So we allocate enough more memory to hit a page boundary now,
3563         which in turn causes future contiguous calls to page-align.
3564     */
3565 
3566     else {
3567       /* front_misalign = 0; *//*superfluous */
3568       /* end_misalign = 0; *//*superfluous */
3569       correction = 0;
3570       aligned_brk = brk;
3571 
3572       /*
3573         If MORECORE returns an address lower than we have seen before,
3574         we know it isn't really contiguous.  This and some subsequent
3575         checks help cope with non-conforming MORECORE functions and
3576         the presence of "foreign" calls to MORECORE from outside of
3577         malloc or by other threads.  We cannot guarantee to detect
3578         these in all cases, but cope with the ones we do detect.
3579       */
3580       if (contiguous(av) && old_size != 0 && brk < old_end) {
3581         set_noncontiguous(av);
3582       }
3583 
3584       /* handle contiguous cases */
3585       if (contiguous(av)) {
3586 
3587 #ifdef DNMALLOC_DEBUG
3588 	fprintf(stderr, "Handle contiguous cases\n");
3589 #endif
3590         /*
3591            We can tolerate forward non-contiguities here (usually due
3592            to foreign calls) but treat them as part of our space for
3593            stats reporting.
3594         */
3595         if (old_size != 0)
3596           av->sbrked_mem += brk - old_end;
3597 
3598         /* Guarantee alignment of first new chunk made from this space */
3599 
3600         front_misalign = (INTERNAL_SIZE_T) brk & MALLOC_ALIGN_MASK;
3601         if (front_misalign > 0) {
3602 
3603           /*
3604             Skip over some bytes to arrive at an aligned position.
3605             We don't need to specially mark these wasted front bytes.
3606             They will never be accessed anyway because
3607             prev_inuse of av->top (and any chunk created from its start)
3608             is always true after initialization.
3609           */
3610 
3611           correction = MALLOC_ALIGNMENT - front_misalign;
3612           aligned_brk += correction;
3613         }
3614 
3615         /*
3616           If this isn't adjacent to existing space, then we will not
3617           be able to merge with old_top space, so must add to 2nd request.
3618         */
3619 
3620         correction += old_size;
3621 
3622         /* Extend the end address to hit a page boundary */
3623         end_misalign = (INTERNAL_SIZE_T)(brk + size + correction);
3624         correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;
3625 
3626         assert(correction >= 0);
3627         snd_brk = (char*)(MORECORE(correction));
3628 
3629         if (snd_brk == (char*)(MORECORE_FAILURE)) {
3630           /*
3631             If can't allocate correction, try to at least find out current
3632             brk.  It might be enough to proceed without failing.
3633           */
3634           correction = 0;
3635           snd_brk = (char*)(MORECORE(0));
3636         }
3637         else if (snd_brk < brk) {
3638           /*
3639             If the second call gives noncontiguous space even though
3640             it says it won't, the only course of action is to ignore
3641             results of second call, and conservatively estimate where
3642             the first call left us. Also set noncontiguous, so this
3643             won't happen again, leaving at most one hole.
3644 
3645             Note that this check is intrinsically incomplete.  Because
3646             MORECORE is allowed to give more space than we ask for,
3647             there is no reliable way to detect a noncontiguity
3648             producing a forward gap for the second call.
3649           */
3650           snd_brk = brk + size;
3651           correction = 0;
3652           set_noncontiguous(av);
3653         }
3654 	else {
3655 	  VALGRIND_MAKE_MEM_NOACCESS(snd_brk,correction);
3656 	}
3657 
3658       }
3659 
3660       /* handle non-contiguous cases */
3661       else {
3662 
3663 #ifdef DNMALLOC_DEBUG
3664 	fprintf(stderr, "Handle non-contiguous cases\n");
3665 #endif
3666 
3667         /* MORECORE/mmap must correctly align */
3668         assert(aligned_OK(brk));
3669 
3670         /* Find out current end of memory */
3671         if (snd_brk == (char*)(MORECORE_FAILURE)) {
3672           snd_brk = (char*)(MORECORE(0));
3673           av->sbrked_mem += snd_brk - brk - size;
3674         }
3675 #ifdef DNMALLOC_DEBUG
3676 	fprintf(stderr, "Sbrked now %lu\n", (unsigned long)av->sbrked_mem);
3677 #endif
3678       }
3679 
3680       /* Adjust top based on results of second sbrk.
3681        *
3682        * If mmap() has been used as backup for failed morecore(),
3683        * we end up in this branch as well.
3684        */
3685       if (snd_brk != (char*)(MORECORE_FAILURE)) {
3686 #ifdef DNMALLOC_DEBUG
3687 	fprintf(stderr, "Adjust top, correction %lu\n", correction);
3688 #endif
3689         /* hashtable_remove(chunk(av->top)); *//* rw 19.05.2008 removed */
3690 	av->top =  cireg_getfree();
3691         av->top->chunk = (mchunkptr)aligned_brk;
3692         set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
3693 #ifdef DNMALLOC_DEBUG
3694 	fprintf(stderr, "Adjust top, top %p size %lu\n",
3695 		av->top, (unsigned long)chunksize(av->top));
3696 #endif
3697         hashtable_add(av->top);
3698         av->sbrked_mem += correction;
3699 
3700         /*
3701           If not the first time through, we either have a
3702           gap due to foreign sbrk or a non-contiguous region.  Insert a
3703           double fencepost at old_top to prevent consolidation with space
3704           we don't own. These fenceposts are artificial chunks that are
3705           marked as inuse. Original dlmalloc had two of these but too
3706           small to use. To ensure that the linked lists contain a maximum
3707           of 8 elements we only use 1. Inuse is determined by the
3708           current rather than the next chunk anyway.
3709         */
3710 
3711         if (old_size != 0) {
3712 #ifdef DNMALLOC_DEBUG
3713 	  fprintf(stderr, "Shrink old_top to insert fenceposts\n");
3714 #endif
3715           /*
3716              Shrink old_top to insert fenceposts, keeping size a
3717              multiple of MALLOC_ALIGNMENT. We know there is at least
3718              enough space in old_top to do this.
3719           */
3720 #ifdef DNMALLOC_DEBUG
3721 	  fprintf(stderr, "Adjust top, old_top %p old_size before %lu\n",
3722 		  old_top, (unsigned long)old_size);
3723 #endif
3724           old_size = (old_size - 4*SIZE_SZ) & ~MALLOC_ALIGN_MASK;
3725           set_head(old_top, old_size | PREV_INUSE);
3726 #ifdef DNMALLOC_DEBUG
3727 	  fprintf(stderr, "Adjust top, old_size after %lu\n",
3728 		  (unsigned long)old_size);
3729 #endif
3730 
3731           /*
3732             Note that the following assignments completely overwrite
3733             old_top when old_size was previously MINSIZE.  This is
3734             intentional. We need the fencepost, even if old_top otherwise gets
3735             lost.
3736           */
3737           /* dnmalloc, we need the fencepost to be 16 bytes, however since
3738 	     it's marked inuse it will never be coalesced
3739 	  */
3740           fencepost = cireg_getfree();
3741           fencepost->chunk = (mchunkptr) chunk_at_offset(chunk(old_top),
3742 							 old_size);
3743           fencepost->size = 16|INUSE|PREV_INUSE;
3744           hashtable_add(fencepost);
3745           /*
3746              If possible, release the rest, suppressing trimming.
3747           */
3748           if (old_size >= MINSIZE) {
3749             INTERNAL_SIZE_T tt = av->trim_threshold;
3750 #ifdef DNMALLOC_DEBUG
3751 	    fprintf(stderr, "Release\n");
3752 #endif
3753             av->trim_threshold = (INTERNAL_SIZE_T)(-1);
3754 	    set_head(old_top, old_size | PREV_INUSE | INUSE);
3755 	    guard_set(av->guard_stored, old_top, 0, old_size);
3756 	    VALGRIND_MALLOCLIKE_BLOCK(chunk(old_top), old_size, 0, 0);
3757             fREe(chunk(old_top));
3758             av->trim_threshold = tt;
3759 #ifdef DNMALLOC_DEBUG
3760 	    fprintf(stderr, "Release done\n");
3761 #endif
3762           }
3763 
3764 #ifdef DNMALLOC_DEBUG
3765 	  fprintf(stderr, "Adjust top, size %lu\n",
3766 		  (unsigned long)chunksize(av->top));
3767 #endif
3768 
3769         } /* fenceposts */
3770       } /* adjust top */
3771     } /* not extended previous region */
3772 
3773     /* Update statistics */
3774     sum = av->sbrked_mem;
3775     if (sum > (CHUNK_SIZE_T)(av->max_sbrked_mem))
3776       av->max_sbrked_mem = sum;
3777 
3778     sum += av->mmapped_mem;
3779     if (sum > (CHUNK_SIZE_T)(av->max_total_mem))
3780       av->max_total_mem = sum;
3781 
3782     check_malloc_state();
3783 
3784     /* finally, do the allocation */
3785 
3786     p = av->top;
3787     size = chunksize(p);
3788 
3789 #ifdef DNMALLOC_DEBUG
3790     fprintf(stderr, "Size: %lu  nb+MINSIZE: %lu\n",
3791 	    (CHUNK_SIZE_T)(size), (CHUNK_SIZE_T)(nb + MINSIZE));
3792 #endif
3793 
3794     /* check that one of the above allocation paths succeeded */
3795     if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb + MINSIZE)) {
3796       remainder_size = size - nb;
3797       remainder = cireg_getfree();
3798       remainder->chunk = chunk_at_offset(chunk(p), nb);
3799       av->top = remainder;
3800       set_head(p, nb | PREV_INUSE | INUSE);
3801       set_head(remainder, remainder_size | PREV_INUSE);
3802       hashtable_insert (p, av->top);
3803       check_malloced_chunk(p, nb);
3804 #ifdef DNMALLOC_DEBUG
3805       fprintf(stderr, "Return any (total %lu)\n",
3806 	      (unsigned long)/* size_t */av->max_total_mem );
3807 #endif
3808       return chunk(p);
3809     }
3810 
3811   }
3812 
3813 #ifdef DNMALLOC_DEBUG
3814   fprintf(stderr, "Return failed (total %lu)\n",
3815 	  (unsigned long)/* size_t */av->max_total_mem );
3816 #endif
3817 
3818   /* catch all failure paths */
3819   MALLOC_FAILURE_ACTION;
3820   return 0;
3821 }
3822 
3823 
3824 
3825 
3826 /*
3827   sYSTRIm is an inverse of sorts to sYSMALLOc.  It gives memory back
3828   to the system (via negative arguments to sbrk) if there is unused
3829   memory at the `high' end of the malloc pool. It is called
3830   automatically by free() when top space exceeds the trim
3831   threshold. It is also called by the public malloc_trim routine.  It
3832   returns 1 if it actually released any memory, else 0.
3833 */
3834 
3835 #if __STD_C
3836 static int sYSTRIm(size_t pad, mstate av)
3837 #else
3838 static int sYSTRIm(pad, av) size_t pad; mstate av;
3839 #endif
3840 {
3841   long  top_size;        /* Amount of top-most memory */
3842   long  extra;           /* Amount to release */
3843   long  released;        /* Amount actually released */
3844   char* current_brk;     /* address returned by pre-check sbrk call */
3845   char* new_brk;         /* address returned by post-check sbrk call */
3846   size_t pagesz;
3847 
3848   pagesz = av->pagesize;
3849   top_size = chunksize(av->top);
3850 
3851   /* Release in pagesize units, keeping at least one page */
3852   extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
3853 
3854   if (extra > 0) {
3855 
3856     /*
3857       Only proceed if end of memory is where we last set it.
3858       This avoids problems if there were foreign sbrk calls.
3859     */
3860     current_brk = (char*)(MORECORE(0));
3861     if (current_brk == (char*)(av->top) + top_size) {
3862 
3863       /*
3864         Attempt to release memory. We ignore MORECORE return value,
3865         and instead call again to find out where new end of memory is.
3866         This avoids problems if first call releases less than we asked,
3867         of if failure somehow altered brk value. (We could still
3868         encounter problems if it altered brk in some very bad way,
3869         but the only thing we can do is adjust anyway, which will cause
3870         some downstream failure.)
3871       */
3872 
3873       MORECORE(-extra);
3874       new_brk = (char*)(MORECORE(0));
3875 
3876       if (new_brk != (char*)MORECORE_FAILURE) {
3877         released = (long)(current_brk - new_brk);
3878 
3879         if (released != 0) {
3880           /* Success. Adjust top. */
3881           av->sbrked_mem -= released;
3882           set_head(av->top, (top_size - released) | PREV_INUSE);
3883           check_malloc_state();
3884           return 1;
3885         }
3886       }
3887     }
3888   }
3889   return 0;
3890 }
3891 
3892 /*
3893   ------------------------------ malloc ------------------------------
3894 */
3895 
3896 
3897 #if __STD_C
3898 DL_STATIC Void_t* mALLOc(size_t bytes)
3899 #else
3900 DL_STATIC   Void_t* mALLOc(bytes) size_t bytes;
3901 #endif
3902 {
3903   mstate av = get_malloc_state();
3904 
3905   INTERNAL_SIZE_T nb;               /* normalized request size */
3906   unsigned int    idx;              /* associated bin index */
3907   mbinptr         bin;              /* associated bin */
3908   mfastbinptr*    fb;               /* associated fastbin */
3909 
3910   chunkinfoptr       victim;           /* inspected/selected chunk */
3911   INTERNAL_SIZE_T size;             /* its size */
3912   int             victim_index;     /* its bin index */
3913 
3914   chunkinfoptr       remainder;        /* remainder from a split */
3915   CHUNK_SIZE_T    remainder_size;   /* its size */
3916 
3917   unsigned int    block;            /* bit map traverser */
3918   unsigned int    bit;              /* bit map traverser */
3919   unsigned int    map;              /* current word of binmap */
3920 
3921   chunkinfoptr       fwd;              /* misc temp for linking */
3922   chunkinfoptr       bck;              /* misc temp for linking */
3923 
3924   Void_t*         retval;
3925 
3926   /* chunkinfoptr	  next; */
3927 
3928 
3929   /*
3930     Convert request size to internal form by adding SIZE_SZ bytes
3931     overhead plus possibly more to obtain necessary alignment and/or
3932     to obtain a size of at least MINSIZE, the smallest allocatable
3933     size. Also, checked_request2size traps (returning 0) request sizes
3934     that are so large that they wrap around zero when padded and
3935     aligned.
3936   */
3937 #if defined(SH_CUTEST)
3938   extern int malloc_count;
3939   ++malloc_count;
3940 #endif
3941 
3942   checked_request2size(bytes, nb);
3943 
3944   /*
3945     Bypass search if no frees yet
3946    */
3947   if (av && have_anychunks(av)) {
3948     goto av_initialized;
3949   }
3950   else {
3951     if (!av || av->max_fast == 0) { /* initialization check */
3952       malloc_consolidate(av);
3953       av = get_malloc_state();
3954     }
3955     goto use_top;
3956   }
3957 
3958  av_initialized:
3959 
3960   /*
3961     If the size qualifies as a fastbin, first check corresponding bin.
3962   */
3963   if ((CHUNK_SIZE_T)(nb) <= (CHUNK_SIZE_T)(av->max_fast)) {
3964     fb = &(av->fastbins[(fastbin_index(nb))]);
3965     if ( (victim = *fb) != 0) {
3966       *fb = victim->fd;
3967       check_remalloced_chunk(victim, nb);
3968       guard_set(av->guard_stored, victim, bytes, nb);
3969       VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
3970       return chunk(victim);
3971     }
3972   }
3973 
3974   /*
3975     If a small request, check regular bin.  Since these "smallbins"
3976     hold one size each, no searching within bins is necessary.
3977     (For a large request, we need to wait until unsorted chunks are
3978     processed to find best fit. But for small ones, fits are exact
3979     anyway, so we can check now, which is faster.)
3980   */
3981 
3982   if (in_smallbin_range(nb)) {
3983     idx = smallbin_index(nb);
3984     bin = bin_at(av,idx);
3985 
3986     if ((victim = last(bin)) != bin) {
3987       bck = victim->bk;
3988       bin->bk = bck;
3989       bck->fd = bin;
3990 
3991       set_all_inuse(victim);
3992 
3993       check_malloced_chunk(victim, nb);
3994       guard_set(av->guard_stored, victim, bytes, nb);
3995       VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
3996       return chunk(victim);
3997     }
3998   }
3999 
4000   /*
4001      If this is a large request, consolidate fastbins before continuing.
4002      While it might look excessive to kill all fastbins before
4003      even seeing if there is space available, this avoids
4004      fragmentation problems normally associated with fastbins.
4005      Also, in practice, programs tend to have runs of either small or
4006      large requests, but less often mixtures, so consolidation is not
4007      invoked all that often in most programs. And the programs that
4008      it is called frequently in otherwise tend to fragment.
4009   */
4010 
4011   else {
4012     idx = largebin_index(nb);
4013     if (have_fastchunks(av))
4014       malloc_consolidate(av);
4015   }
4016 
4017   /*
4018     Process recently freed or remaindered chunks, taking one only if
4019     it is exact fit, or, if this a small request, the chunk is remainder from
4020     the most recent non-exact fit.  Place other traversed chunks in
4021     bins.  Note that this step is the only place in any routine where
4022     chunks are placed in bins.
4023   */
4024 
4025   while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
4026     bck = victim->bk;
4027     size = chunksize(victim);
4028 
4029     /*
4030        If a small request, try to use last remainder if it is the
4031        only chunk in unsorted bin.  This helps promote locality for
4032        runs of consecutive small requests. This is the only
4033        exception to best-fit, and applies only when there is
4034        no exact fit for a small chunk.
4035     */
4036 
4037     if (UNLIKELY(in_smallbin_range(nb) &&
4038 		 bck == unsorted_chunks(av) &&
4039 		 victim == av->last_remainder &&
4040 		 (CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb + MINSIZE))) {
4041 
4042       /* split and reattach remainder */
4043       remainder_size = size - nb;
4044       remainder = cireg_getfree();
4045       remainder->chunk = chunk_at_offset(chunk(victim), nb);
4046       unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
4047       av->last_remainder = remainder;
4048       remainder->bk = remainder->fd = unsorted_chunks(av);
4049 
4050       set_head(victim, nb | PREV_INUSE|INUSE);
4051       set_head(remainder, remainder_size | PREV_INUSE);
4052       hashtable_insert(victim, remainder);
4053 
4054       check_malloced_chunk(victim, nb);
4055       guard_set(av->guard_stored, victim, bytes, nb);
4056       VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
4057       return chunk(victim);
4058     }
4059 
4060     /* remove from unsorted list */
4061     unsorted_chunks(av)->bk = bck;
4062     bck->fd = unsorted_chunks(av);
4063 
4064     /* Take now instead of binning if exact fit */
4065 
4066     if (UNLIKELY(size == nb)) {
4067       set_all_inuse(victim)
4068       check_malloced_chunk(victim, nb);
4069       guard_set(av->guard_stored, victim, bytes, nb);
4070       VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
4071       return chunk(victim);
4072     }
4073 
4074     /* place chunk in bin */
4075 
4076     if (in_smallbin_range(size)) {
4077 
4078       victim_index = smallbin_index(size);
4079       bck = bin_at(av, victim_index);
4080       fwd = bck->fd;
4081     }
4082     else {
4083       victim_index = largebin_index(size);
4084       bck = bin_at(av, victim_index);
4085       fwd = bck->fd;
4086 
4087       if (UNLIKELY(fwd != bck)) {
4088         /* if smaller than smallest, place first */
4089         if ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(bck->bk->size)) {
4090           fwd = bck;
4091           bck = bck->bk;
4092         }
4093         else if ((CHUNK_SIZE_T)(size) >=
4094                  (CHUNK_SIZE_T)(FIRST_SORTED_BIN_SIZE)) {
4095 
4096           /* maintain large bins in sorted order */
4097           size |= PREV_INUSE|INUSE; /* Or with inuse bits to speed comparisons */
4098           while ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(fwd->size))
4099             fwd = fwd->fd;
4100           bck = fwd->bk;
4101         }
4102       }
4103     }
4104 
4105     mark_bin(av, victim_index);
4106     victim->bk = bck;
4107     victim->fd = fwd;
4108     fwd->bk = victim;
4109     bck->fd = victim;
4110   }
4111 
4112   /*
4113     If a large request, scan through the chunks of current bin to
4114     find one that fits.  (This will be the smallest that fits unless
4115     FIRST_SORTED_BIN_SIZE has been changed from default.)  This is
4116     the only step where an unbounded number of chunks might be
4117     scanned without doing anything useful with them. However the
4118     lists tend to be short.
4119   */
4120 
4121   if (!in_smallbin_range(nb)) {
4122     bin = bin_at(av, idx);
4123 
4124     victim = last(bin);
4125 
4126     if (UNLIKELY(victim != bin)) {
4127 
4128       do {
4129 	size = chunksize(victim);
4130 
4131 	if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb)) {
4132 	  remainder_size = size - nb;
4133 	  unlink(victim, bck, fwd);
4134 
4135 	  /* Split */
4136 	  if (remainder_size >= MINSIZE) {
4137 	    remainder = cireg_getfree();
4138 	    remainder->chunk = chunk_at_offset(chunk(victim), nb);
4139 	    unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
4140 	    remainder->bk = remainder->fd = unsorted_chunks(av);
4141 	    set_head(victim, nb | PREV_INUSE | INUSE);
4142 	    set_head(remainder, remainder_size | PREV_INUSE);
4143 	    hashtable_insert(victim, remainder);
4144 	    check_malloced_chunk(victim, nb);
4145 	    guard_set(av->guard_stored, victim, bytes, nb);
4146 	    VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
4147 	    return chunk(victim);
4148 	  }
4149 	  /* Exhaust */
4150 	  else  {
4151 	    set_all_inuse(victim);
4152 	    check_malloced_chunk(victim, nb);
4153 	    guard_set(av->guard_stored, victim, bytes, nb);
4154 	    VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
4155 	    return chunk(victim);
4156 	  }
4157 	}
4158 	victim = victim->bk;
4159       } while(victim != bin);
4160     }
4161   }
4162 
4163   /*
4164     Search for a chunk by scanning bins, starting with next largest
4165     bin. This search is strictly by best-fit; i.e., the smallest
4166     (with ties going to approximately the least recently used) chunk
4167     that fits is selected.
4168 
4169     The bitmap avoids needing to check that most blocks are nonempty.
4170   */
4171 
4172 
4173   ++idx;
4174   bin = bin_at(av,idx);
4175   block = idx2block(idx);
4176   map = av->binmap[block];
4177   bit = idx2bit(idx);
4178 
4179   for (;;) {
4180 
4181     /* Skip rest of block if there are no more set bits in this block.  */
4182     if (bit > map || bit == 0) {
4183       do {
4184         if (++block >= BINMAPSIZE)  /* out of bins */
4185           goto use_top;
4186       } while ( (map = av->binmap[block]) == 0);
4187 
4188       bin = bin_at(av, (block << BINMAPSHIFT));
4189       bit = 1;
4190     }
4191 
4192     /* Advance to bin with set bit. There must be one. */
4193     while ((bit & map) == 0) {
4194       bin = next_bin(bin);
4195       bit <<= 1;
4196       assert(bit != 0);
4197     }
4198 
4199     /* Inspect the bin. It is likely to be non-empty */
4200     victim = last(bin);
4201 
4202     /*  If a false alarm (empty bin), clear the bit. */
4203     if (victim == bin) {
4204       av->binmap[block] = map &= ~bit; /* Write through */
4205       bin = next_bin(bin);
4206       bit <<= 1;
4207     }
4208 
4209     else {
4210       size = chunksize(victim);
4211 
4212       /*  We know the first chunk in this bin is big enough to use. */
4213       assert((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb));
4214 
4215       remainder_size = size - nb;
4216 
4217       /* unlink */
4218       bck = victim->bk;
4219       bin->bk = bck;
4220       bck->fd = bin;
4221 
4222       /* Split */
4223       if (remainder_size >= MINSIZE) {
4224         remainder = cireg_getfree();
4225         remainder->chunk = chunk_at_offset(chunk(victim), nb);
4226 
4227         unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
4228         remainder->bk = remainder->fd = unsorted_chunks(av);
4229         /* advertise as last remainder */
4230         if (in_smallbin_range(nb))
4231 	  av->last_remainder = remainder;
4232 
4233         set_head(victim, nb | PREV_INUSE | INUSE);
4234         set_head(remainder, remainder_size | PREV_INUSE);
4235         hashtable_insert(victim, remainder);
4236         check_malloced_chunk(victim, nb);
4237 	guard_set(av->guard_stored, victim, bytes, nb);
4238 	VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
4239         return chunk(victim);
4240       }
4241       /* Exhaust */
4242       else {
4243         set_all_inuse(victim);
4244         check_malloced_chunk(victim, nb);
4245 	guard_set(av->guard_stored, victim, bytes, nb);
4246 	VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
4247         return chunk(victim);
4248       }
4249 
4250     }
4251   }
4252 
4253   use_top:
4254 
4255 
4256   /*
4257     If large enough, split off the chunk bordering the end of memory
4258     (held in av->top). Note that this is in accord with the best-fit
4259     search rule.  In effect, av->top is treated as larger (and thus
4260     less well fitting) than any other available chunk since it can
4261     be extended to be as large as necessary (up to system
4262     limitations).
4263 
4264     We require that av->top always exists (i.e., has size >=
4265     MINSIZE) after initialization, so if it would otherwise be
4266     exhuasted by current request, it is replenished. (The main
4267     reason for ensuring it exists is that we may need MINSIZE space
4268     to put in fenceposts in sysmalloc.)
4269   */
4270 
4271   victim = av->top;
4272   size = chunksize(victim);
4273 
4274   if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb + MINSIZE)) {
4275     remainder = cireg_getfree();
4276     remainder_size = size - nb;
4277     remainder->chunk = chunk_at_offset(chunk(victim), nb);
4278     av->top = remainder;
4279     set_head(victim, nb | PREV_INUSE | INUSE);
4280     set_head(remainder, remainder_size | PREV_INUSE);
4281     hashtable_insert(victim, remainder);
4282     check_malloced_chunk(victim, nb);
4283     guard_set(av->guard_stored, victim, bytes, nb);
4284     VALGRIND_MALLOCLIKE_BLOCK(chunk(victim), bytes, 0, 0);
4285     return chunk(victim);
4286   }
4287 
4288   /*
4289      If no space in top, relay to handle system-dependent cases
4290   */
4291   retval = sYSMALLOc(nb, av);
4292   if (retval) {
4293 #if PARANOIA > 2
4294     victim = mem2chunk(retval); /* is used in guard_set macro */
4295 #endif
4296     guard_set(av->guard_stored, victim, bytes, nb);
4297   }
4298   VALGRIND_MALLOCLIKE_BLOCK(retval, bytes, 0, 0);
4299   return retval;
4300 }
4301 
4302 /*
4303   ------------------------------ free ------------------------------
4304 */
4305 
4306 #if __STD_C
4307 DL_STATIC void fREe(Void_t* mem)
4308 #else
4309 DL_STATIC void fREe(mem) Void_t* mem;
4310 #endif
4311 {
4312   mstate av = get_malloc_state();
4313 
4314   chunkinfoptr       p;           /* chunk corresponding to mem */
4315   INTERNAL_SIZE_T size;        /* its size */
4316   mfastbinptr*    fb;          /* associated fastbin */
4317   chunkinfoptr       prevchunk;   /* previous physical chunk */
4318   chunkinfoptr       nextchunk;   /* next contiguous chunk */
4319   INTERNAL_SIZE_T nextsize;    /* its size */
4320   INTERNAL_SIZE_T prevsize;    /* size of previous contiguous chunk */
4321   chunkinfoptr       bck;         /* misc temp for linking */
4322   chunkinfoptr       fwd;         /* misc temp for linking */
4323   chunkinfoptr	     next;
4324 #if defined(SH_CUTEST)
4325   extern int malloc_count;
4326   --malloc_count;
4327 #endif
4328 
4329   /* free(0) has no effect */
4330   if (mem != 0) {
4331     p = hashtable_lookup(mem);
4332     /* check that memory is managed by us
4333      * and is inuse
4334      */
4335     if (UNLIKELY(!p || !inuse(p)))
4336       {
4337 #ifdef DNMALLOC_CHECKS
4338 	if (p) {
4339 	  fprintf(stderr, "Attempt to free memory not in use\n");
4340 	  abort();
4341 	} else {
4342 	  fprintf(stderr, "Attempt to free memory not allocated\n");
4343 	  abort();
4344 	}
4345 #endif
4346 	assert(p && inuse(p));
4347 	return;
4348       }
4349 
4350     VALGRIND_FREELIKE_BLOCK(mem, 0);
4351 
4352     guard_check(av->guard_stored, p);
4353 
4354     size = chunksize(p);
4355 
4356     check_inuse_chunk(p);
4357 
4358     /*
4359       If eligible, place chunk on a fastbin so it can be found
4360       and used quickly in malloc.
4361     */
4362 
4363     if ((CHUNK_SIZE_T)(size) <= (CHUNK_SIZE_T)(av->max_fast)
4364 
4365 #if TRIM_FASTBINS
4366         /*
4367            If TRIM_FASTBINS set, don't place chunks
4368            bordering top into fastbins
4369         */
4370         && (chunk_at_offset(chunk(p), size) != av->top)
4371 #endif
4372         ) {
4373 
4374       set_fastchunks(av);
4375       fb = &(av->fastbins[fastbin_index(size)]);
4376       p->fd = *fb;
4377       *fb = p;
4378     }
4379 
4380     /*
4381        Consolidate other non-mmapped chunks as they arrive.
4382     */
4383 
4384     else if (!chunk_is_mmapped(p)) {
4385       set_anychunks(av);
4386 
4387       nextchunk = next_chunkinfo(p);
4388       if (nextchunk)
4389 	nextsize = chunksize(nextchunk);
4390       else
4391 	nextsize = 0;/* gcc doesn't notice that it's only used if (nextchunk)*/
4392 
4393       /* consolidate backward */
4394       if (UNLIKELY(!prev_inuse(p))) {
4395         prevchunk = prev_chunkinfo(p);
4396         prevsize = chunksize(prevchunk);
4397 #ifdef DNMALLOC_CHECKS
4398 	if (inuse(prevchunk)) {
4399 		fprintf(stderr, "Dnmalloc error: trying to unlink an inuse chunk: %p (chunk: %p)\n This is definitely a bug, please report it to dnmalloc@fort-knox.org.\n", prevchunk, chunk(prevchunk));
4400 		abort();
4401 	}
4402 #else
4403 	assert(!inuse(prevchunk));
4404 #endif
4405         size += prevsize;
4406         unlink(prevchunk, bck, fwd);
4407 	set_head(p, size | PREV_INUSE);
4408         hashtable_skiprm(prevchunk,p);
4409         /* This chunk no longer exists in any form: release the chunkinfoptr
4410 	 */
4411         freecilst_add(p);
4412         p = prevchunk;
4413       }
4414 
4415       if (nextchunk) {
4416 	if (nextchunk != av->top) {
4417 	  /* get and clear inuse bit */
4418 	  clear_previnuse(nextchunk);
4419 
4420 	  /* consolidate forward */
4421 	  if (!inuse(nextchunk)) {
4422 	    /* if mmap is used instead of sbrk, we may have a
4423 	     * chunk with !nextchunk->fd && !nextchunk->bk
4424 	     */
4425 	    if (nextchunk->fd && nextchunk->fd)
4426 	      {
4427 		unlink(nextchunk, bck, fwd);
4428 		size += nextsize;
4429 		set_head(p, size | PREV_INUSE);
4430 		hashtable_skiprm(p, nextchunk);
4431 		freecilst_add (nextchunk);
4432 	      }
4433 	  }
4434 
4435 	  set_head(p, size | PREV_INUSE);
4436 	  next = next_chunkinfo(p);
4437 	  if (next)
4438 	    next->prev_size = size;
4439 
4440 	  /*
4441 	    Place the chunk in unsorted chunk list. Chunks are
4442 	    not placed into regular bins until after they have
4443 	    been given one chance to be used in malloc.
4444 	  */
4445 
4446 	  bck = unsorted_chunks(av);
4447 	  fwd = bck->fd;
4448 	  p->bk = bck;
4449 	  p->fd = fwd;
4450 	  bck->fd = p;
4451 	  fwd->bk = p;
4452 
4453 	  nextchunk = next_chunkinfo(p);
4454 	  if (nextchunk)
4455 	    nextchunk->prev_size = chunksize(p);
4456 
4457 	  check_free_chunk(p);
4458 	}
4459 
4460 	/*
4461 	  If the chunk borders the current high end of memory,
4462 	  consolidate into top
4463 	*/
4464 
4465 	else {
4466 	  size += nextsize;
4467 	  set_head(p, size | PREV_INUSE);
4468 	  hashtable_remove(chunk(av->top));
4469 	  freecilst_add(av->top);
4470 	  av->top = p;
4471 	  check_chunk(p);
4472 	}
4473       } /* if (nextchunk) */
4474 
4475       /*
4476         If freeing a large space, consolidate possibly-surrounding
4477         chunks. Then, if the total unused topmost memory exceeds trim
4478         threshold, ask malloc_trim to reduce top.
4479 
4480         Unless max_fast is 0, we don't know if there are fastbins
4481         bordering top, so we cannot tell for sure whether threshold
4482         has been reached unless fastbins are consolidated.  But we
4483         don't want to consolidate on each free.  As a compromise,
4484         consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
4485         is reached.
4486       */
4487 
4488       if (UNLIKELY((CHUNK_SIZE_T)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD)) {
4489         if (have_fastchunks(av))
4490           malloc_consolidate(av);
4491 
4492 #ifndef MORECORE_CANNOT_TRIM
4493         if ((CHUNK_SIZE_T)(chunksize(av->top)) >=
4494             (CHUNK_SIZE_T)(av->trim_threshold))
4495 	  {
4496 	    if (morecore32bit(av))
4497 	      {
4498 #ifdef DNMALLOC_DEBUG
4499 		fprintf(stderr, "Calling systrim from free()\n");
4500 #endif
4501 		sYSTRIm(av->top_pad, av);
4502 #ifdef DNMALLOC_DEBUG
4503 		fprintf(stderr, "Systrim done\n");
4504 #endif
4505 	      }
4506 	  }
4507 #endif
4508       }
4509 
4510     }
4511     /*
4512       If the chunk was allocated via mmap, release via munmap()
4513       Note that if HAVE_MMAP is false but chunk_is_mmapped is
4514       true, then user must have overwritten memory. There's nothing
4515       we can do to catch this error unless DEBUG is set, in which case
4516       check_inuse_chunk (above) will have triggered error.
4517     */
4518 
4519     else {
4520 #if  PARANOIA > 0
4521       int ret;
4522 #endif
4523       INTERNAL_SIZE_T offset = (INTERNAL_SIZE_T) p->hash_next;
4524       av->n_mmaps--;
4525       av->mmapped_mem -= (size + offset);
4526 #if  PARANOIA > 0
4527       ret = munmap((char*) chunk(p) - offset, size + offset);
4528 #else
4529       munmap((char*) chunk(p) - offset, size + offset);
4530 #endif
4531       hashtable_remove_mmapped(chunk(p));
4532       freecilst_add(p);
4533       /* munmap returns non-zero on failure */
4534       assert(ret == 0);
4535     }
4536   }
4537 }
4538 
4539 /*
4540   ------------------------- malloc_consolidate -------------------------
4541 
4542   malloc_consolidate is a specialized version of free() that tears
4543   down chunks held in fastbins.  Free itself cannot be used for this
4544   purpose since, among other things, it might place chunks back onto
4545   fastbins.  So, instead, we need to use a minor variant of the same
4546   code.
4547 
4548   Also, because this routine needs to be called the first time through
4549   malloc anyway, it turns out to be the perfect place to trigger
4550   initialization code.
4551 */
4552 
4553 #if __STD_C
4554 static void malloc_consolidate(mstate av)
4555 #else
4556 static void malloc_consolidate(av) mstate av;
4557 #endif
4558 {
4559   mfastbinptr*    fb;                 /* current fastbin being consolidated */
4560   mfastbinptr*    maxfb;              /* last fastbin (for loop control) */
4561   chunkinfoptr       p;                  /* current chunk being consolidated */
4562   chunkinfoptr       nextp;              /* next chunk to consolidate */
4563   chunkinfoptr       prevp;
4564   chunkinfoptr       unsorted_bin;       /* bin header */
4565   chunkinfoptr       first_unsorted;     /* chunk to link to */
4566 
4567   /* These have same use as in free() */
4568   chunkinfoptr       nextchunk;
4569   INTERNAL_SIZE_T size;
4570   INTERNAL_SIZE_T nextsize;
4571   INTERNAL_SIZE_T prevsize;
4572   chunkinfoptr       bck;
4573   chunkinfoptr       fwd;
4574   chunkinfoptr	     next;
4575 
4576   /*
4577     If max_fast is 0, we know that av hasn't
4578     yet been initialized, in which case do so below
4579   */
4580   if (av && av->max_fast != 0) {
4581 
4582     clear_fastchunks(av);
4583 
4584     unsorted_bin = unsorted_chunks(av);
4585 
4586     /*
4587       Remove each chunk from fast bin and consolidate it, placing it
4588       then in unsorted bin. Among other reasons for doing this,
4589       placing in unsorted bin avoids needing to calculate actual bins
4590       until malloc is sure that chunks aren't immediately going to be
4591       reused anyway.
4592     */
4593 
4594     maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
4595     fb = &(av->fastbins[0]);
4596     do {
4597       if ( UNLIKELY((p = *fb) != 0)) {
4598         *fb = 0;
4599 	do {
4600           check_inuse_chunk(p);
4601           nextp = p->fd;
4602 
4603           /*
4604 	   * Slightly streamlined version of consolidation code in free()
4605 	   */
4606 
4607           size = chunksize(p);
4608           nextchunk = next_chunkinfo(p);
4609 
4610 	  /* gcc doesn't notice that it's only used if (nextchunk) */
4611 	  if (nextchunk)
4612 	    nextsize = chunksize(nextchunk);
4613 	  else
4614 	    nextsize = 0;
4615 
4616 	  if (!prev_inuse(p)) {
4617              prevp = prev_chunkinfo(p);
4618              prevsize = chunksize(prevp);
4619              size += prevsize;
4620 #ifdef DNMALLOC_CHECKS
4621 	     if (inuse(prevp)) {
4622 		fprintf(stderr, "Dnmalloc error: trying to unlink an inuse chunk (2): %p (chunk: %p)\n This is definitely a bug, please report it to dnmalloc@fort-knox.org.\n", prevp, chunk(prevp));
4623 		     abort();
4624 	     }
4625 #else
4626 	     assert(!inuse(prevp));
4627 #endif
4628              unlink(prevp, bck, fwd);
4629              set_head(p, size | PREV_INUSE);
4630              hashtable_skiprm(prevp,p);
4631              freecilst_add(p);
4632              p=prevp;
4633           }
4634 
4635 	  if (nextchunk) {
4636 	    if (nextchunk != av->top) {
4637 
4638 	      clear_previnuse(nextchunk);
4639 
4640 	      /* if mmap is used instead of sbrk, we may have a
4641 	       * chunk with !nextchunk->fd && !nextchunk->bk
4642 	       */
4643 	      if (!inuse(nextchunk)) {
4644 		if( nextchunk->fd && nextchunk->bk) {
4645 		  size += nextsize;
4646 		  unlink(nextchunk, bck, fwd);
4647 		  set_head(p, size | PREV_INUSE);
4648 		  hashtable_skiprm(p,nextchunk);
4649 		  freecilst_add(nextchunk);
4650 		}
4651 	      }
4652 
4653 	      first_unsorted = unsorted_bin->fd;
4654 	      unsorted_bin->fd = p;
4655 	      first_unsorted->bk = p;
4656 
4657 	      set_head(p, size | PREV_INUSE);
4658 	      p->bk = unsorted_bin;
4659 	      p->fd = first_unsorted;
4660 	      next = next_chunkinfo(p);
4661 	      if (next)
4662 	    	next->prev_size = size;
4663 
4664 
4665 	    }
4666 
4667 	    else if (nextchunk == av->top) {
4668 	      size += nextsize;
4669 	      set_head(p, size | PREV_INUSE);
4670 	      hashtable_remove(chunk(av->top));
4671 	      freecilst_add(av->top);
4672 	      av->top = p;
4673 	    }
4674 	  } /* if (nextchunk) */
4675 
4676         } while ( (p = nextp) != 0);
4677 
4678       }
4679     } while (fb++ != maxfb);
4680   }
4681   else {
4682     /* Initialize dnmalloc */
4683     dnmalloc_init();
4684     malloc_init_state(get_malloc_state());
4685     check_malloc_state();
4686   }
4687 }
4688 
4689 /*
4690   ------------------------------ realloc ------------------------------
4691 */
4692 
4693 
4694 #if __STD_C
4695 DL_STATIC Void_t* rEALLOc(Void_t* oldmem, size_t bytes)
4696 #else
4697 DL_STATIC Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
4698 #endif
4699 {
4700   mstate av = get_malloc_state();
4701 
4702   INTERNAL_SIZE_T  nb;              /* padded request size */
4703 
4704   chunkinfoptr        oldp;            /* chunk corresponding to oldmem */
4705   INTERNAL_SIZE_T  oldsize;         /* its size */
4706 
4707   chunkinfoptr        newp;            /* chunk to return */
4708   INTERNAL_SIZE_T  newsize;         /* its size */
4709   Void_t*          newmem;          /* corresponding user mem */
4710 
4711   chunkinfoptr        next;            /* next contiguous chunk after oldp */
4712 
4713   chunkinfoptr        remainder;       /* extra space at end of newp */
4714   CHUNK_SIZE_T     remainder_size;  /* its size */
4715 
4716   chunkinfoptr        bck;             /* misc temp for linking */
4717   chunkinfoptr        fwd;             /* misc temp for linking */
4718 
4719   CHUNK_SIZE_T     copysize;        /* bytes to copy */
4720   unsigned int     ncopies;         /* INTERNAL_SIZE_T words to copy */
4721   INTERNAL_SIZE_T* s;               /* copy source */
4722   INTERNAL_SIZE_T* d;               /* copy destination */
4723 
4724 
4725 #ifdef REALLOC_ZERO_BYTES_FREES
4726   if (UNLIKELY(bytes == 0)) {
4727     fREe(oldmem);
4728     return 0;
4729   }
4730 #endif
4731 
4732   if (UNLIKELY(!av || av->max_fast == 0)) {
4733     malloc_consolidate(av);
4734     av = get_malloc_state();
4735   }
4736 
4737   /* realloc of null is supposed to be same as malloc */
4738   if (UNLIKELY(oldmem == 0))
4739     return mALLOc(bytes);
4740 
4741   checked_request2size(bytes, nb);
4742 
4743   oldp    = hashtable_lookup(oldmem);
4744 
4745   if (UNLIKELY(!oldp || !inuse(oldp))){
4746      /* attempt to either realloc memory not managed by us
4747       * or memory that is not in use
4748       */
4749 #ifdef DNMALLOC_CHECKS
4750     if (oldp) {
4751       fprintf(stderr, "Attempt to free memory not in use\n");
4752       abort();
4753     } else {
4754       fprintf(stderr, "Attempt to free memory not allocated\n");
4755       abort();
4756     }
4757 #endif
4758     assert(oldp && inuse(oldp));
4759     return 0;
4760   }
4761 
4762   VALGRIND_FREELIKE_BLOCK(oldmem, 0);
4763   guard_check(av->guard_stored, oldp);
4764 
4765   oldsize = chunksize(oldp);
4766 
4767   check_inuse_chunk(oldp);
4768 
4769   if (!chunk_is_mmapped(oldp)) {
4770 
4771     if (UNLIKELY((CHUNK_SIZE_T)(oldsize) >= (CHUNK_SIZE_T)(nb))) {
4772       /* already big enough; split below */
4773       newp    = oldp;
4774       newsize = oldsize;
4775     }
4776 
4777     else {
4778       next = next_chunkinfo(oldp);
4779       if (next)
4780       	next->prev_size = oldsize;
4781       /* Try to expand forward into top */
4782       if (next && next == av->top &&
4783           (CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >=
4784           (CHUNK_SIZE_T)(nb + MINSIZE)) {
4785          set_head_size(oldp, nb);
4786          hashtable_remove(chunk(av->top));
4787          av->top->chunk = chunk_at_offset(chunk(oldp), nb);
4788          set_head(av->top, (newsize - nb) | PREV_INUSE);
4789          /* av->top->chunk has been moved move in hashtable */
4790          hashtable_insert(oldp, av->top);
4791 	 guard_set(av->guard_stored, oldp, bytes, nb);
4792 	 VALGRIND_MALLOCLIKE_BLOCK(chunk(oldp), bytes, 0, 0);
4793          return chunk(oldp);
4794       }
4795 
4796       /* Try to expand forward into next chunk;  split off remainder below */
4797       else if (next && next != av->top &&
4798                !inuse(next) &&
4799                (CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >=
4800                (CHUNK_SIZE_T)(nb)) {
4801         newp = oldp;
4802         unlink(next, bck, fwd);
4803         hashtable_remove(chunk(next));
4804         freecilst_add(next);
4805 	next = next_chunkinfo(oldp);
4806 	if (next)
4807 	  next->prev_size = newsize;
4808       }
4809 
4810       /* allocate, copy, free */
4811       else {
4812 
4813         newmem = mALLOc(nb - MALLOC_ALIGN_MASK);
4814          if (newmem == 0)
4815           return 0; /* propagate failure */
4816 
4817         newp = hashtable_lookup(newmem);
4818         newsize = chunksize(newp);
4819 
4820 
4821         /* next = next_chunkinfo(oldp); *//* 'next' never used rw 19.05.2008 */
4822         /*
4823           Avoid copy if newp is next chunk after oldp.
4824         */
4825 	if (UNLIKELY(is_next_chunk(oldp, newp))) {
4826 	  newsize += oldsize;
4827 	  set_head_size(oldp, newsize);
4828 	  hashtable_skiprm(oldp, newp);
4829 	  freecilst_add(newp);
4830           newp = oldp;
4831         }
4832         else {
4833           /*
4834             Unroll copy of <= 40 bytes (80 if 8byte sizes)
4835             We know that contents have an even number of
4836             INTERNAL_SIZE_T-sized words; minimally 4 (2 on amd64).
4837           */
4838 
4839 	  VALGRIND_MALLOCLIKE_BLOCK(chunk(oldp), chunksize(oldp), 0, 0);
4840 
4841           copysize = oldsize;
4842           s = (INTERNAL_SIZE_T*)(oldmem);
4843           d = (INTERNAL_SIZE_T*)(newmem);
4844           ncopies = copysize / sizeof(INTERNAL_SIZE_T);
4845           assert(ncopies >= 2);
4846 
4847           if (ncopies > 10)
4848             MALLOC_COPY(d, s, copysize);
4849 
4850           else {
4851             *(d+0) = *(s+0);
4852             *(d+1) = *(s+1);
4853 	    if (ncopies > 2) {
4854 	      *(d+2) = *(s+2);
4855 	      *(d+3) = *(s+3);
4856 	      if (ncopies > 4) {
4857 		*(d+4) = *(s+4);
4858 		*(d+5) = *(s+5);
4859 		if (ncopies > 6) {
4860 		  *(d+6) = *(s+6);
4861 		  *(d+7) = *(s+7);
4862 		  if (ncopies > 8) {
4863 		    *(d+8) = *(s+8);
4864 		    *(d+9) = *(s+9);
4865 		  }
4866                 }
4867               }
4868             }
4869           }
4870 
4871           fREe(oldmem);
4872           check_inuse_chunk(newp);
4873 	  guard_set(av->guard_stored, newp, bytes, nb);
4874           return chunk(newp);
4875         }
4876       }
4877     }
4878 
4879     /* If possible, free extra space in old or extended chunk */
4880 
4881     assert((CHUNK_SIZE_T)(newsize) >= (CHUNK_SIZE_T)(nb));
4882 
4883     remainder_size = newsize - nb;
4884 
4885     if (remainder_size >= MINSIZE) { /* split remainder */
4886       remainder = cireg_getfree();
4887       remainder->chunk = chunk_at_offset(chunk(newp), nb);
4888       set_head_size(newp, nb);
4889       set_head(remainder, remainder_size | PREV_INUSE | INUSE);
4890       remainder->prev_size = nb;
4891       hashtable_insert(newp, remainder);
4892       /* Mark remainder as inuse so free() won't complain */
4893       set_all_inuse(remainder);
4894       guard_set(av->guard_stored, remainder, 0, remainder_size);
4895       VALGRIND_MALLOCLIKE_BLOCK(chunk(remainder), remainder_size, 0, 0);
4896       fREe(chunk(remainder));
4897     }
4898     else { /* not enough extra to split off */
4899       set_head_size(newp, newsize);
4900       set_all_inuse(newp);
4901     }
4902 
4903     check_inuse_chunk(newp);
4904     guard_set(av->guard_stored, newp, bytes, nb);
4905     VALGRIND_MALLOCLIKE_BLOCK(chunk(newp), bytes, 0, 0);
4906     return chunk(newp);
4907   }
4908 
4909   /*
4910     Handle mmap cases
4911   */
4912 
4913   else {
4914 
4915 #if HAVE_MREMAP
4916     INTERNAL_SIZE_T offset = (INTERNAL_SIZE_T) oldp->hash_next;
4917     size_t pagemask = av->pagesize - 1;
4918     char *cp;
4919     CHUNK_SIZE_T  sum;
4920 
4921 
4922     /* Note the extra SIZE_SZ overhead */
4923     /* newsize = (nb + offset + SIZE_SZ + pagemask) & ~pagemask; */
4924     newsize = (nb + offset + pagemask) & ~pagemask;
4925 
4926     /* don't need to remap if still within same page */
4927     if (oldsize == newsize - offset)
4928       {
4929 	guard_set(av->guard_stored, oldp, bytes, nb);
4930 	VALGRIND_FREELIKE_BLOCK(oldmem, 0);
4931 	VALGRIND_MALLOCLIKE_BLOCK(oldmem, bytes, 0, 0);
4932 	return oldmem;
4933       }
4934 
4935     cp = (char*)mremap((char*)chunk(oldp) - offset, oldsize + offset, newsize, 1);
4936 
4937     if (cp != (char*)MORECORE_FAILURE) {
4938 
4939       hashtable_remove_mmapped(chunk(oldp));
4940 
4941       oldp->chunk = (mchunkptr)(cp + offset);
4942       set_head(oldp, (newsize - offset)|IS_MMAPPED|INUSE);
4943 
4944       hashtable_add(oldp);
4945 
4946       assert(aligned_OK(chunk(oldp))); /* rw fix: newp -> oldp */
4947       assert(( ((INTERNAL_SIZE_T) oldp->hash_next) == offset));
4948 
4949       /* update statistics */
4950       sum = av->mmapped_mem += newsize - oldsize;
4951       if (sum > (CHUNK_SIZE_T)(av->max_mmapped_mem))
4952         av->max_mmapped_mem = sum;
4953       sum += av->sbrked_mem;
4954       if (sum > (CHUNK_SIZE_T)(av->max_total_mem))
4955         av->max_total_mem = sum;
4956 
4957       guard_set(av->guard_stored, oldp, bytes, nb);
4958       VALGRIND_FREELIKE_BLOCK(oldmem, 0);
4959       VALGRIND_MALLOCLIKE_BLOCK(chunk(oldp), bytes, 0, 0);
4960       return chunk(oldp);
4961     }
4962 #endif /* have MREMAP */
4963 
4964     /* Note the extra SIZE_SZ overhead. */
4965     if ((CHUNK_SIZE_T)(oldsize) >= (CHUNK_SIZE_T)(nb + SIZE_SZ))
4966       newmem = oldmem; /* do nothing */
4967     else {
4968       /* Must alloc, copy, free. */
4969       newmem = mALLOc(nb - MALLOC_ALIGN_MASK);
4970       if (newmem != 0) {
4971         MALLOC_COPY(newmem, oldmem, oldsize);
4972         fREe(oldmem);
4973       }
4974     }
4975     VALGRIND_MALLOCLIKE_BLOCK(newmem, bytes, 0, 0);
4976     guard_set(av->guard_stored, mem2chunk(newmem), bytes, nb);
4977     return newmem;
4978   }
4979 }
4980 
4981 /*
4982   ---------------------------posix_memalign ----------------------------
4983 */
4984 
4985 #if __STD_C
4986 DL_STATIC int posix_mEMALIGn(Void_t** memptr, size_t alignment, size_t bytes)
4987 #else
4988 DL_STATIC int posix_mEMALIGn(memptr, alignment, bytes) Void_t** memptr; size_t alignment; size_t bytes;
4989 #endif
4990 {
4991   mstate av;
4992 
4993   if (alignment % sizeof(void *) != 0)
4994     return EINVAL;
4995   if ((alignment & (alignment - 1)) != 0)
4996     return EINVAL;
4997 
4998   av = get_malloc_state();
4999   if (!av || av->max_fast == 0) malloc_consolidate(av);
5000   *memptr =  mEMALIGn(alignment, bytes);
5001 
5002   return (*memptr != NULL ? 0 : ENOMEM);
5003 }
5004 
5005 /*
5006   ------------------------------ memalign ------------------------------
5007 */
5008 
5009 #if __STD_C
5010 DL_STATIC Void_t* mEMALIGn(size_t alignment, size_t bytes)
5011 #else
5012 DL_STATIC Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
5013 #endif
5014 {
5015   INTERNAL_SIZE_T nb;             /* padded  request size */
5016   char*           m;              /* memory returned by malloc call */
5017   chunkinfoptr       p;              /* corresponding chunk */
5018   char*           brk;            /* alignment point within p */
5019   chunkinfoptr       newp;           /* chunk to return */
5020   INTERNAL_SIZE_T newsize;        /* its size */
5021   INTERNAL_SIZE_T leadsize;       /* leading space before alignment point */
5022   chunkinfoptr       remainder;      /* spare room at end to split off */
5023   CHUNK_SIZE_T    remainder_size; /* its size */
5024   INTERNAL_SIZE_T size;
5025 #if PARANOIA > 2
5026   mstate          av;
5027 #endif
5028 
5029   /* If need less alignment than we give anyway, just relay to malloc */
5030 
5031   if (UNLIKELY(alignment <= MALLOC_ALIGNMENT)) return mALLOc(bytes);
5032 
5033   /* Otherwise, ensure that it is at least a minimum chunk size */
5034 
5035   if (alignment <  MINSIZE) alignment = MINSIZE;
5036 
5037   /* Make sure alignment is power of 2 (in case MINSIZE is not).  */
5038   if (UNLIKELY((alignment & (alignment - 1)) != 0)) {
5039     size_t a = MALLOC_ALIGNMENT * 2;
5040     while ((CHUNK_SIZE_T)a < (CHUNK_SIZE_T)alignment) a <<= 1;
5041     alignment = a;
5042   }
5043 
5044   checked_request2size(bytes, nb);
5045 
5046   /*
5047     Strategy: find a spot within that chunk that meets the alignment
5048     request, and then possibly free the leading and trailing space.
5049   */
5050 
5051 
5052   /* Call malloc with worst case padding to hit alignment. */
5053 
5054   m  = (char*)(mALLOc(nb + alignment + MINSIZE));
5055 
5056   if (m == 0) return 0; /* propagate failure */
5057 
5058 #if PARANOIA > 2
5059   av = get_malloc_state();
5060 #endif
5061 
5062   p = hashtable_lookup((mchunkptr) m);
5063 
5064   if ((((PTR_UINT)(m)) % alignment) != 0) { /* misaligned */
5065 
5066     /*
5067       Find an aligned spot inside chunk.  Since we need to give back
5068       leading space in a chunk of at least MINSIZE, if the first
5069       calculation places us at a spot with less than MINSIZE leader,
5070       we can move to the next aligned spot -- we've allocated enough
5071       total room so that this is always possible.
5072     */
5073 
5074     brk = (char*) ((PTR_UINT)(((PTR_UINT)(m + alignment - 1)) &
5075                            -((signed long) alignment)));
5076     if ((CHUNK_SIZE_T)(brk - (char*)(chunk(p))) < MINSIZE)
5077       brk += alignment;
5078 
5079     newp = cireg_getfree();
5080     newp->chunk = (mchunkptr)brk;
5081     leadsize = brk - (char*)(chunk(p));
5082     newsize = chunksize(p) - leadsize;
5083 
5084     /* For mmapped chunks, just adjust offset */
5085     if (UNLIKELY(chunk_is_mmapped(p))) {
5086       newp->hash_next = (chunkinfoptr) (((INTERNAL_SIZE_T) p->hash_next) + leadsize);
5087       set_head(newp, newsize|IS_MMAPPED|INUSE);
5088       hashtable_remove_mmapped(chunk(p));
5089       freecilst_add(p);
5090       hashtable_add(newp);
5091       guard_set(av->guard_stored, newp, bytes, nb);
5092       return chunk(newp);
5093     }
5094 
5095     /* Otherwise, give back leader, use the rest */
5096     set_head(newp, newsize | PREV_INUSE | INUSE);
5097     set_head_size(p, leadsize);
5098     set_all_inuse(newp);
5099     hashtable_add(newp); /* 20.05.2008 rw */
5100     guard_set(av->guard_stored, p, 0, leadsize);
5101     fREe(chunk(p));
5102     p = newp;
5103 
5104     assert (newsize >= nb &&
5105             (((PTR_UINT)(chunk(p))) % alignment) == 0);
5106   }
5107 
5108   /* Also give back spare room at the end */
5109   if (!chunk_is_mmapped(p)) {
5110     size = chunksize(p);
5111     if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb + MINSIZE)) {
5112        remainder = cireg_getfree();
5113        remainder_size = size - nb;
5114        remainder->chunk = chunk_at_offset(chunk(p), nb);
5115        set_head(remainder, remainder_size | PREV_INUSE | INUSE);
5116        set_head_size(p, nb);
5117        hashtable_add(remainder); /* 20.05.2008 rw */
5118        guard_set(av->guard_stored, remainder, 0, remainder_size);
5119        fREe(chunk(remainder));
5120     }
5121   }
5122 
5123   check_inuse_chunk(p);
5124   guard_set(av->guard_stored, p, bytes, nb);
5125   return chunk(p);
5126 }
5127 
5128 /*
5129   ------------------------------ calloc ------------------------------
5130 */
5131 
5132 #if __STD_C
5133 DL_STATIC Void_t* cALLOc(size_t n_elements, size_t elem_size)
5134 #else
5135 DL_STATIC Void_t* cALLOc(n_elements, elem_size) size_t n_elements; size_t elem_size;
5136 #endif
5137 {
5138   chunkinfoptr p;
5139   CHUNK_SIZE_T  clearsize;
5140   CHUNK_SIZE_T  nclears;
5141   INTERNAL_SIZE_T* d;
5142   Void_t* mem;
5143 
5144 
5145   mem = mALLOc(n_elements * elem_size);
5146 
5147   if (mem != 0) {
5148     p = hashtable_lookup(mem);
5149 
5150     if (!chunk_is_mmapped(p))
5151     {
5152       /*
5153         Unroll clear of <= 40 bytes (80 if 8byte sizes)
5154         We know that contents have an even number of
5155         INTERNAL_SIZE_T-sized words; minimally 4 (2 on amd64).
5156       */
5157 
5158       d = (INTERNAL_SIZE_T*)mem;
5159       clearsize = chunksize(p);
5160       nclears = clearsize / sizeof(INTERNAL_SIZE_T);
5161       assert(nclears >= 2);
5162 
5163       if (nclears > 10) {
5164         MALLOC_ZERO(d, clearsize);
5165       }
5166 
5167       else {
5168         *(d+0) = 0;
5169         *(d+1) = 0;
5170 	if (nclears > 2) {
5171 	  *(d+2) = 0;
5172 	  *(d+3) = 0;
5173 	  if (nclears > 4) {
5174 	    *(d+4) = 0;
5175 	    *(d+5) = 0;
5176 	    if (nclears > 6) {
5177 	      *(d+6) = 0;
5178 	      *(d+7) = 0;
5179 	      if (nclears > 8) {
5180 		*(d+8) = 0;
5181 		*(d+9) = 0;
5182 	      }
5183             }
5184           }
5185         }
5186       }
5187     }
5188 #if ! MMAP_CLEARS
5189     else
5190     {
5191       d = (INTERNAL_SIZE_T*)mem;
5192       clearsize = chunksize(p);
5193       MALLOC_ZERO(d, clearsize);
5194     }
5195 #endif
5196     /* Set guard again, since we just cleared it
5197      */
5198     guard_set(get_malloc_state()->guard_stored, p, (n_elements * elem_size), p->size);
5199   }
5200 
5201   return mem;
5202 }
5203 
5204 /*
5205   ------------------------------ valloc ------------------------------
5206 */
5207 
5208 #if __STD_C
5209 DL_STATIC Void_t* vALLOc(size_t bytes)
5210 #else
5211 DL_STATIC Void_t* vALLOc(bytes) size_t bytes;
5212 #endif
5213 {
5214   /* Ensure initialization */
5215   mstate av = get_malloc_state();
5216   if (!av || av->max_fast == 0) {
5217     malloc_consolidate(av);
5218     av = get_malloc_state();
5219   }
5220   return mEMALIGn(av->pagesize, bytes);
5221 }
5222 
5223 /*
5224   ------------------------------ pvalloc ------------------------------
5225 */
5226 
5227 
5228 #if __STD_C
5229 DL_STATIC Void_t* pVALLOc(size_t bytes)
5230 #else
5231 DL_STATIC Void_t* pVALLOc(bytes) size_t bytes;
5232 #endif
5233 {
5234   mstate av = get_malloc_state();
5235   size_t pagesz;
5236 
5237   /* Ensure initialization */
5238   if (!av || av->max_fast == 0) {
5239     malloc_consolidate(av);
5240     av = get_malloc_state();
5241   }
5242   pagesz = av->pagesize;
5243   return mEMALIGn(pagesz, (bytes + pagesz - 1) & ~(pagesz - 1));
5244 }
5245 
5246 
5247 /*
5248   ------------------------------ malloc_trim ------------------------------
5249 */
5250 
5251 #if __STD_C
5252 DL_STATIC int mTRIm(size_t pad)
5253 #else
5254 DL_STATIC int mTRIm(pad) size_t pad;
5255 #endif
5256 {
5257   mstate av = get_malloc_state();
5258   /* Ensure initialization/consolidation */
5259   malloc_consolidate(av);
5260   av = get_malloc_state();
5261 #ifndef MORECORE_CANNOT_TRIM
5262   if (morecore32bit(av))
5263     return sYSTRIm(pad, av);
5264   else
5265     return 0;
5266 #else
5267   return 0;
5268 #endif
5269 }
5270 
5271 
5272 
5273 /*
5274   ------------------------- malloc_usable_size -------------------------
5275 */
5276 
5277 #if __STD_C
5278 DL_STATIC size_t mUSABLe(Void_t* mem)
5279 #else
5280 DL_STATIC size_t mUSABLe(mem) Void_t* mem;
5281 #endif
5282 {
5283   chunkinfoptr p;
5284   if (mem != 0) {
5285     p = hashtable_lookup(mem);
5286     if (p && inuse(p)) return chunksize(p);
5287   }
5288   return 0;
5289 }
5290 
5291 /*
5292   ------------------------------ mallinfo ------------------------------
5293 */
5294 
5295 DL_STATIC struct mallinfo mALLINFo()
5296 {
5297   mstate av = get_malloc_state();
5298   static struct mallinfo mi;
5299   unsigned int i;
5300   mbinptr b;
5301   chunkinfoptr p;
5302   INTERNAL_SIZE_T avail;
5303   INTERNAL_SIZE_T fastavail;
5304   int nblocks;
5305   int nfastblocks;
5306 
5307   /* Ensure initialization */
5308   if (!av || av->top == 0) {
5309     malloc_consolidate(av);
5310     av = get_malloc_state();
5311   }
5312   check_malloc_state();
5313 
5314   if (!av || av->top == 0) {
5315     return mi;
5316   }
5317 
5318   /* Account for top */
5319   avail = chunksize(av->top);
5320   nblocks = 1;  /* top always exists */
5321 
5322   /* traverse fastbins */
5323   nfastblocks = 0;
5324   fastavail = 0;
5325 
5326   for (i = 0; i < NFASTBINS; ++i) {
5327     for (p = av->fastbins[i]; p != 0; p = p->fd) {
5328       ++nfastblocks;
5329       fastavail += chunksize(p);
5330     }
5331   }
5332 
5333   avail += fastavail;
5334 
5335   /* traverse regular bins */
5336   for (i = 1; i < NBINS; ++i) {
5337     b = bin_at(av, i);
5338     for (p = last(b); p != b; p = p->bk) {
5339       ++nblocks;
5340       avail += chunksize(p);
5341     }
5342   }
5343 
5344   mi.smblks = nfastblocks;
5345   mi.ordblks = nblocks;
5346   mi.fordblks = avail;
5347   mi.uordblks = av->sbrked_mem - avail;
5348   mi.arena = av->sbrked_mem;
5349   mi.hblks = av->n_mmaps;
5350   mi.hblkhd = av->mmapped_mem;
5351   mi.fsmblks = fastavail;
5352   mi.keepcost = chunksize(av->top);
5353   mi.usmblks = av->max_total_mem;
5354   return mi;
5355 }
5356 
5357 /*
5358   ------------------------------ malloc_stats ------------------------------
5359 */
5360 
5361 DL_STATIC void mSTATs()
5362 {
5363   struct mallinfo mi = mALLINFo();
5364 
5365   fprintf(stderr, "hashtable = %10lu MB\n",
5366 	  (CHUNK_SIZE_T)(HASHTABLESIZE / (1024*1024)));
5367   fprintf(stderr, "max system bytes = %10lu\n",
5368 	  (CHUNK_SIZE_T)(mi.usmblks));
5369   fprintf(stderr, "system bytes     = %10lu  (%10lu sbrked, %10lu mmaped)\n",
5370 	  (CHUNK_SIZE_T)(mi.arena + mi.hblkhd),
5371 	  (CHUNK_SIZE_T)(mi.arena),
5372 	  (CHUNK_SIZE_T)(mi.hblkhd));
5373   fprintf(stderr, "in use bytes     = %10lu\n",
5374 	  (CHUNK_SIZE_T)(mi.uordblks + mi.hblkhd));
5375 }
5376 
5377 
5378 /*
5379   ------------------------------ mallopt ------------------------------
5380 */
5381 
5382 #if __STD_C
5383 DL_STATIC int mALLOPt(int param_number, int value)
5384 #else
5385 DL_STATIC int mALLOPt(param_number, value) int param_number; int value;
5386 #endif
5387 {
5388   mstate av = get_malloc_state();
5389   /* Ensure initialization/consolidation */
5390   malloc_consolidate(av);
5391   av = get_malloc_state();
5392 
5393   switch(param_number) {
5394   case M_MXFAST:
5395     if (value >= 0 && value <= MAX_FAST_SIZE) {
5396       set_max_fast(av, value);
5397       return 1;
5398     }
5399     else
5400       return 0;
5401 
5402   case M_TRIM_THRESHOLD:
5403     av->trim_threshold = value;
5404     return 1;
5405 
5406   case M_TOP_PAD:
5407     av->top_pad = value;
5408     return 1;
5409 
5410   case M_MMAP_THRESHOLD:
5411     av->mmap_threshold = value;
5412     return 1;
5413 
5414   case M_MMAP_MAX:
5415     if (value != 0)
5416       return 0;
5417     av->n_mmaps_max = value;
5418     return 1;
5419 
5420   default:
5421     return 0;
5422   }
5423 }
5424 
5425 
5426 /*	$OpenBSD: arc4random.c,v 1.19 2008/06/04 00:50:23 djm Exp $	*/
5427 
5428 /*
5429  * Copyright (c) 1996, David Mazieres <dm@uun.org>
5430  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
5431  *
5432  * Permission to use, copy, modify, and distribute this software for any
5433  * purpose with or without fee is hereby granted, provided that the above
5434  * copyright notice and this permission notice appear in all copies.
5435  *
5436  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
5437  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
5438  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
5439  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
5440  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
5441  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
5442  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5443  */
5444 
5445 /*
5446  * Arc4 random number generator for OpenBSD.
5447  *
5448  * This code is derived from section 17.1 of Applied Cryptography,
5449  * second edition, which describes a stream cipher allegedly
5450  * compatible with RSA Labs "RC4" cipher (the actual description of
5451  * which is a trade secret).  The same algorithm is used as a stream
5452  * cipher called "arcfour" in Tatu Ylonen's ssh package.
5453  *
5454  * Here the stream cipher has been modified always to include the time
5455  * when initializing the state.  That makes it impossible to
5456  * regenerate the same random sequence twice, so this can't be used
5457  * for encryption, but will generate good random numbers.
5458  *
5459  * RC4 is a registered trademark of RSA Laboratories.
5460  */
5461 
5462 /* Moved u_int8_t -> unsigned char (portability)
5463  * Eliminated unneeded functions, added read from /dev/urandom taken from:
5464  $MirOS: contrib/code/Snippets/arc4random.c,v 1.3 2008-03-04 22:53:14 tg Exp $
5465  * Modified by Robert Connolly from OpenBSD lib/libc/crypt/arc4random.c v1.11.
5466  * This is arc4random(3) using urandom.
5467  */
5468 
5469 #include <fcntl.h>
5470 #include <limits.h>
5471 #include <stdlib.h>
5472 #include <sys/param.h>
5473 #include <sys/time.h>
5474 
5475 struct arc4_stream {
5476 	unsigned char i;
5477 	unsigned char j;
5478 	unsigned char s[256];
5479 };
5480 
5481 static int rs_initialized;
5482 static struct arc4_stream rs;
5483 static pid_t arc4_stir_pid;
5484 static int arc4_count;
5485 
5486 static unsigned char arc4_getbyte(void);
5487 
5488 static void
5489 arc4_init(void)
5490 {
5491 	int     n;
5492 
5493 	for (n = 0; n < 256; n++)
5494 		rs.s[n] = n;
5495 	rs.i = 0;
5496 	rs.j = 0;
5497 }
5498 
5499 static inline void
5500 arc4_addrandom(unsigned char *dat, int datlen)
5501 {
5502 	int     n;
5503 	unsigned char si;
5504 
5505 	rs.i--;
5506 	for (n = 0; n < 256; n++) {
5507 		rs.i = (rs.i + 1);
5508 		si = rs.s[rs.i];
5509 		rs.j = (rs.j + si + dat[n % datlen]);
5510 		rs.s[rs.i] = rs.s[rs.j];
5511 		rs.s[rs.j] = si;
5512 	}
5513 	rs.j = rs.i;
5514 }
5515 
5516 #ifdef HAVE_SCHED_H
5517 #include <sched.h>
5518 #endif
5519 
5520 static void
5521 arc4_stir(void)
5522 {
5523 	int     i;
5524         struct {
5525                 struct timeval tv1;
5526                 struct timeval tv2;
5527                 unsigned char rnd[(128 - 2*sizeof(struct timeval)) / sizeof(unsigned char)];
5528         } rdat;
5529 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
5530         ssize_t sz = 0;
5531 	int    fd;
5532 #endif
5533 
5534         gettimeofday(&rdat.tv1, NULL);
5535 
5536 
5537 	if (!rs_initialized) {
5538 		arc4_init();
5539 		rs_initialized = 1;
5540 	}
5541 
5542 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
5543 
5544 #ifdef HAVE_SCHED_YIELD
5545 	/* Yield the processor to introduce some random delay. */
5546 	(void) sched_yield();
5547 #endif
5548 
5549 	/*
5550 	 * Pthread problem in multithreaded code on *BSD.
5551 	 */
5552         fd = open("/dev/urandom", O_RDONLY);
5553         if (fd != -1) {
5554 	        sz = (size_t)read(fd, rdat.rnd, sizeof (rdat.rnd));
5555 		/*
5556 		 * gcc complains if we ignore the return value of read(), and
5557 		 * the llvm/clang analyzer complains if we don't use it...
5558 		 */
5559 		if (sz > (-256)) /* always true */
5560 		  close(fd);
5561         }
5562 	/*
5563         if (sz > sizeof (rdat.rnd))
5564                 sz = 0;
5565 	*/
5566  #endif
5567 
5568 	arc4_stir_pid = getpid();
5569         gettimeofday(&rdat.tv2, NULL);
5570 
5571         arc4_addrandom((void *)&rdat, sizeof(rdat));
5572 
5573 	/*
5574 	 * Discard early keystream, as per recommendations in:
5575 	 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
5576 	 */
5577 	for (i = 0; i < 256; i++)
5578 		(void)arc4_getbyte();
5579 	arc4_count = 1600000;
5580 }
5581 
5582 static unsigned char
5583 arc4_getbyte(void)
5584 {
5585 	unsigned char si, sj;
5586 
5587 	rs.i = (rs.i + 1);
5588 	si = rs.s[rs.i];
5589 	rs.j = (rs.j + si);
5590 	sj = rs.s[rs.j];
5591 	rs.s[rs.i] = sj;
5592 	rs.s[rs.j] = si;
5593 	return (rs.s[(si + sj) & 0xff]);
5594 }
5595 
5596 
5597  /* Changed to return char* */
5598 static char *
5599 dnmalloc_arc4random(void)
5600 {
5601 	static char val[4];
5602 
5603 	/* We only call this once, hence no need for locking. */
5604 
5605 	/* _ARC4_LOCK(); */
5606 	arc4_count -= 4;
5607 	if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != getpid())
5608 		arc4_stir();
5609 
5610 	val[0] = (char) arc4_getbyte();
5611 	val[1] = (char) arc4_getbyte();
5612 	val[2] = (char) arc4_getbyte();
5613 	val[3] = (char) arc4_getbyte();
5614 
5615 	arc4_stir();
5616 	/* _ARC4_UNLOCK(); */
5617 	return val;
5618 }
5619 
5620 #else
5621 int dnmalloc_pthread_init() { return 0; }
5622 #endif /* ! USE_SYSTEM_MALLOC */
5623