source: trunk/src/dnmalloc.c@ 592

Last change on this file since 592 was 592, checked in by katerina, 2 days ago

Fixes for compiler warnings.

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