diff options
Diffstat (limited to 'lib/malloc/malloc.c')
| -rw-r--r-- | lib/malloc/malloc.c | 70 |
1 files changed, 60 insertions, 10 deletions
diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c index 88d777e5..5621adf4 100644 --- a/lib/malloc/malloc.c +++ b/lib/malloc/malloc.c @@ -84,6 +84,10 @@ #include <errno.h> #include <stdio.h> +#if defined (HAVE_MMAP) +#include <sys/mman.h> +#endif + /* Define getpagesize () if the system does not. */ #ifndef HAVE_GETPAGESIZE # include "getpagesize.h" @@ -111,6 +115,7 @@ # define NO_VALLOC #endif +/* SIZEOF_LONG * 4 - 2, usable bins from 1..NBUCKETS-1 */ #define NBUCKETS 30 #define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */ @@ -197,6 +202,23 @@ typedef union _malloc_guard { #define STARTBUCK 1 +/* Should we use mmap for large allocations? */ +#if defined (HAVE_MMAP) +# if !defined (MAP_ANON) && defined (MAP_ANONYMOUS) +# define MAP_ANON MAP_ANONYMOUS +# endif +#endif + +#if defined (HAVE_MMAP) && defined (MAP_ANON) +# define USE_MMAP +#endif + +#if defined (USE_MMAP) +# define MMAP_THRESHOLD 14 /* must be >= SPLIT_MAX, COMBINE_MAX */ +#else +# define MMAP_THRESHOLD (8 * SIZEOF_LONG) +#endif + /* Flags for the internal functions. */ #define MALLOC_WRAPPER 0x01 /* wrapper function */ #define MALLOC_INTERNAL 0x02 /* internal function calling another */ @@ -288,6 +310,9 @@ int malloc_flags = 0; /* future use */ int malloc_trace = 0; /* trace allocations and frees to stderr */ int malloc_register = 0; /* future use */ +/* Use a variable in case we want to dynamically adapt it in the future */ +int malloc_mmap_threshold = MMAP_THRESHOLD; + #ifdef MALLOC_TRACE char _malloc_trace_buckets[NBUCKETS]; @@ -594,7 +619,7 @@ morecore (nu) /* Try to split a larger block here, if we're within the range of sizes to split. */ - if (nu >= SPLIT_MIN) + if (nu >= SPLIT_MIN && nu <= malloc_mmap_threshold) { bsplit (nu); if (nextf[nu] != 0) @@ -603,7 +628,7 @@ morecore (nu) /* Try to coalesce two adjacent blocks from the free list on nextf[nu - 1], if we can, and we're within the range of the block coalescing limits. */ - if (nu >= COMBINE_MIN && nu < COMBINE_MAX && busy[nu - 1] == 0 && nextf[nu - 1]) + if (nu >= COMBINE_MIN && nu < COMBINE_MAX && nu <= malloc_mmap_threshold && busy[nu - 1] == 0 && nextf[nu - 1]) { bcoalesce (nu); if (nextf[nu] != 0) @@ -632,6 +657,25 @@ morecore (nu) nblks = 1; } +#if defined (USE_MMAP) + if (nu > malloc_mmap_threshold) + { + mp = (union mhead *)mmap (0, sbrk_amt, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if ((void *)mp == MAP_FAILED) + goto morecore_done; + nextf[nu] = mp; + mp->mh_alloc = ISFREE; + mp->mh_index = nu; + CHAIN (mp) = 0; +#ifdef MALLOC_STATS + _mstats.nmmap++; + _mstats.tmmap += sbrk_amt; +#endif + goto morecore_done; + } +#endif + + #ifdef MALLOC_STATS _mstats.nsbrk++; _mstats.tsbrk += sbrk_amt; @@ -915,6 +959,17 @@ internal_free (mem, file, line, flags) if (mg.i != p->mh_nbytes) xbotch (mem, ERR_ASSERT_FAILED, _("free: start and end chunk sizes differ"), file, line); +#if defined (USE_MMAP) + if (nunits > malloc_mmap_threshold) + { + munmap (p, binsize (nunits)); +#if defined (MALLOC_STATS) + _mstats.nlesscore[nunits]++; +#endif + goto free_return; + } +#endif + #if GLIBC21 if (nunits >= LESSCORE_MIN && ((char *)p + binsize(nunits) == sbrk (0))) #else @@ -1053,12 +1108,9 @@ internal_realloc (mem, n, file, line, flags) /* If ok, use the same block, just marking its size as changed. */ if (RIGHT_BUCKET(nbytes, nunits) || RIGHT_BUCKET(nbytes, nunits-1)) { -#if 0 - m = (char *)mem + p->mh_nbytes; -#else /* Compensate for increment above. */ m -= 4; -#endif + *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; m = (char *)mem + (p->mh_nbytes = n); @@ -1076,6 +1128,8 @@ internal_realloc (mem, n, file, line, flags) _mstats.nrcopy++; #endif + /* If we are using mmap and have mremap, we could use it here. */ + if ((m = internal_malloc (n, file, line, MALLOC_INTERNAL|MALLOC_NOTRACE|MALLOC_NOREG)) == 0) return 0; FASTCOPY (mem, m, tocopy); @@ -1120,11 +1174,7 @@ internal_memalign (alignment, size, file, line, flags) if (((long) ptr & (alignment - 1)) == 0) return ptr; /* Otherwise, get address of byte in the block that has that alignment. */ -#if 0 - aligned = (char *) (((long) ptr + alignment - 1) & -alignment); -#else aligned = (char *) (((long) ptr + alignment - 1) & (~alignment + 1)); -#endif /* Store a suitable indication of how to free the block, so that free can find the true beginning of it. */ |
