|
|
|
@@ -47,10 +47,10 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nextf[i] is the pointer to the next free block of size 2^(i+3). The
|
|
|
|
|
* smallest allocatable block is 8 bytes. The overhead information will
|
|
|
|
|
* go in the first int of the block, and the returned pointer will point
|
|
|
|
|
* to the second.
|
|
|
|
|
* nextf[i] is the pointer to the next free block of size 2^(i+5). The
|
|
|
|
|
* smallest allocatable block is 32 bytes. The overhead information will
|
|
|
|
|
* go in the first 16 bytes of the block, and the returned pointer will point
|
|
|
|
|
* to the rest.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Define MEMSCRAMBLE to have free() write 0xcf into memory as it's freed, to
|
|
|
|
@@ -121,8 +121,8 @@
|
|
|
|
|
# define NO_VALLOC
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* SIZEOF_LONG * 4 - 2, usable bins from 1..NBUCKETS-1 */
|
|
|
|
|
#define NBUCKETS 30
|
|
|
|
|
#define MALLOC_PAGESIZE_MIN 4096
|
|
|
|
|
#define MALLOC_INCR_PAGES 8192
|
|
|
|
|
|
|
|
|
|
#define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */
|
|
|
|
|
#define ISFREE ((char) 0x54) /* magic byte that implies free block */
|
|
|
|
@@ -140,20 +140,14 @@
|
|
|
|
|
enough room in the block for the new size. Range checking is always
|
|
|
|
|
done. */
|
|
|
|
|
union mhead {
|
|
|
|
|
#if SIZEOF_CHAR_P == 8
|
|
|
|
|
bits64_t mh_align[2]; /* 16 */
|
|
|
|
|
#else
|
|
|
|
|
bits64_t mh_align; /* 8 */
|
|
|
|
|
#endif
|
|
|
|
|
struct {
|
|
|
|
|
char mi_alloc; /* ISALLOC or ISFREE */ /* 1 */
|
|
|
|
|
char mi_index; /* index in nextf[] */ /* 1 */
|
|
|
|
|
/* Remainder are valid only when block is allocated */
|
|
|
|
|
u_bits16_t mi_magic2; /* should be == MAGIC2 */ /* 2 */
|
|
|
|
|
u_bits32_t mi_nbytes; /* # of bytes allocated */ /* 4 */
|
|
|
|
|
#if SIZEOF_CHAR_P == 8
|
|
|
|
|
char mi_magic8[8]; /* MAGIC1 guard bytes */ /* 8 */
|
|
|
|
|
#endif
|
|
|
|
|
} minfo;
|
|
|
|
|
};
|
|
|
|
|
#define mh_alloc minfo.mi_alloc
|
|
|
|
@@ -162,14 +156,14 @@ union mhead {
|
|
|
|
|
#define mh_magic2 minfo.mi_magic2
|
|
|
|
|
#define mh_magic8 minfo.mi_magic8
|
|
|
|
|
|
|
|
|
|
#define MAGIC8_NUMBYTES 8
|
|
|
|
|
#define MALLOC_SIZE_T u_bits32_t
|
|
|
|
|
|
|
|
|
|
#define MOVERHEAD sizeof(union mhead)
|
|
|
|
|
|
|
|
|
|
#if SIZEOF_CHAR_P == 8
|
|
|
|
|
#define MALIGN_MASK 15
|
|
|
|
|
#else
|
|
|
|
|
#define MALIGN_MASK 7 /* one less than desired alignment */
|
|
|
|
|
#endif
|
|
|
|
|
#define MALIGN_MASK 15 /* one less than desired alignment */
|
|
|
|
|
|
|
|
|
|
/* Guard bytes we write at the end of the allocation, encoding the size. */
|
|
|
|
|
typedef union _malloc_guard {
|
|
|
|
|
char s[4];
|
|
|
|
|
u_bits32_t i;
|
|
|
|
@@ -181,6 +175,8 @@ typedef union _malloc_guard {
|
|
|
|
|
because we want sizeof (union mhead)
|
|
|
|
|
to describe the overhead for when the block is in use,
|
|
|
|
|
and we do not want the free-list pointer to count in that. */
|
|
|
|
|
/* If we have mmap, this is not used for chunks larger than mmap_threshold,
|
|
|
|
|
since we munmap immediately on free(). */
|
|
|
|
|
|
|
|
|
|
/* If SIZEOF_CHAR_P == 8, this goes into the mh_magic8 buffer at the end of
|
|
|
|
|
the rest of the struct. This may need adjusting. */
|
|
|
|
@@ -194,10 +190,11 @@ typedef union _malloc_guard {
|
|
|
|
|
/* Written in the bytes before the block's real space (-SIZEOF_CHAR_P bytes) */
|
|
|
|
|
#define MAGIC1 0x55
|
|
|
|
|
#define MAGIC2 0x5555
|
|
|
|
|
#define MSLOP 4 /* 4 bytes extra for u_bits32_t size */
|
|
|
|
|
|
|
|
|
|
#define MSLOP 4 /* 4 bytes extra for u_bits32_t end guard size */
|
|
|
|
|
|
|
|
|
|
/* How many bytes are actually allocated for a request of size N --
|
|
|
|
|
rounded up to nearest multiple of 2*SIZEOF_CHAR_P after accounting for
|
|
|
|
|
rounded up to nearest multiple of 16 (alignment) after accounting for
|
|
|
|
|
malloc overhead. */
|
|
|
|
|
#define ALLOCATED_BYTES(n) \
|
|
|
|
|
(((n) + MOVERHEAD + MSLOP + MALIGN_MASK) & ~MALIGN_MASK)
|
|
|
|
@@ -211,18 +208,22 @@ typedef union _malloc_guard {
|
|
|
|
|
|
|
|
|
|
/* Minimum and maximum bucket indices for block splitting (and to bound
|
|
|
|
|
the search for a block to split). */
|
|
|
|
|
#define SPLIT_MIN 2 /* XXX - was 3 */
|
|
|
|
|
#define SPLIT_MID 11
|
|
|
|
|
#define SPLIT_MAX 14
|
|
|
|
|
#define SPLIT_MIN 1 /* 64 */
|
|
|
|
|
#define SPLIT_MID 9 /* 16384 */
|
|
|
|
|
#define SPLIT_MAX 12 /* 131072 */
|
|
|
|
|
|
|
|
|
|
/* Minimum and maximum bucket indices for block coalescing. */
|
|
|
|
|
#define COMBINE_MIN 2
|
|
|
|
|
#define COMBINE_MAX (pagebucket - 1) /* XXX */
|
|
|
|
|
#define COMBINE_MIN 1 /* 64 */
|
|
|
|
|
#define COMBINE_MAX (pagebucket - 1) /* 2048 for 4096-byte pages */
|
|
|
|
|
|
|
|
|
|
#define LESSCORE_MIN 10
|
|
|
|
|
#define LESSCORE_FRC 13
|
|
|
|
|
#define LESSCORE_MIN 8 /* 8192 */
|
|
|
|
|
#define LESSCORE_FRC 11 /* 65536 */
|
|
|
|
|
|
|
|
|
|
#define STARTBUCK 1
|
|
|
|
|
/* Which bin do we prepopulate with the initial sbrk memory? */
|
|
|
|
|
#define PREPOP_BIN 1
|
|
|
|
|
#define PREPOP_SIZE 64
|
|
|
|
|
|
|
|
|
|
#define STARTBUCK 0
|
|
|
|
|
|
|
|
|
|
/* Should we use mmap for large allocations? */
|
|
|
|
|
#if defined (HAVE_MMAP)
|
|
|
|
@@ -232,15 +233,19 @@ typedef union _malloc_guard {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined (HAVE_MMAP) && defined (MAP_ANONYMOUS)
|
|
|
|
|
# define USE_MMAP
|
|
|
|
|
# define USE_MMAP 1
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined (USE_MMAP)
|
|
|
|
|
# define MMAP_THRESHOLD 14 /* must be >= SPLIT_MAX, COMBINE_MAX */
|
|
|
|
|
# define MMAP_THRESHOLD 12 /* must be >= SPLIT_MAX, COMBINE_MAX */
|
|
|
|
|
#else
|
|
|
|
|
# define MMAP_THRESHOLD (8 * SIZEOF_LONG)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* usable bins from STARTBUCK..NBUCKETS-1 */
|
|
|
|
|
|
|
|
|
|
#define NBUCKETS 28
|
|
|
|
|
|
|
|
|
|
/* Flags for the internal functions. */
|
|
|
|
|
#define MALLOC_WRAPPER 0x01 /* wrapper function */
|
|
|
|
|
#define MALLOC_INTERNAL 0x02 /* internal function calling another */
|
|
|
|
@@ -265,7 +270,7 @@ typedef union _malloc_guard {
|
|
|
|
|
#define RIGHT_BUCKET(nb, nu) \
|
|
|
|
|
(((nb) > binsizes[(nu)-1]) && ((nb) <= binsizes[(nu)]))
|
|
|
|
|
|
|
|
|
|
/* nextf[i] is free list of blocks of size 2**(i + 3) */
|
|
|
|
|
/* nextf[i] is free list of blocks of size 2**(i + 5) */
|
|
|
|
|
|
|
|
|
|
static union mhead *nextf[NBUCKETS];
|
|
|
|
|
|
|
|
|
@@ -280,16 +285,18 @@ static int maxbuck; /* highest bucket receiving allocation request. */
|
|
|
|
|
static char *memtop; /* top of heap */
|
|
|
|
|
|
|
|
|
|
static const unsigned long binsizes[NBUCKETS] = {
|
|
|
|
|
8UL, 16UL, 32UL, 64UL, 128UL, 256UL, 512UL, 1024UL, 2048UL, 4096UL,
|
|
|
|
|
32UL, 64UL, 128UL, 256UL, 512UL, 1024UL, 2048UL, 4096UL,
|
|
|
|
|
8192UL, 16384UL, 32768UL, 65536UL, 131072UL, 262144UL, 524288UL,
|
|
|
|
|
1048576UL, 2097152UL, 4194304UL, 8388608UL, 16777216UL, 33554432UL,
|
|
|
|
|
67108864UL, 134217728UL, 268435456UL, 536870912UL, 1073741824UL,
|
|
|
|
|
2147483648UL, 4294967295UL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* binsizes[x] == (1 << ((x) + 3)) */
|
|
|
|
|
/* binsizes[x] == (1 << ((x) + 5)) */
|
|
|
|
|
#define binsize(x) binsizes[(x)]
|
|
|
|
|
|
|
|
|
|
#define MAXALLOC_SIZE binsizes[NBUCKETS-1]
|
|
|
|
|
|
|
|
|
|
#if !defined (errno)
|
|
|
|
|
extern int errno;
|
|
|
|
|
#endif
|
|
|
|
@@ -306,6 +313,7 @@ static void internal_cfree PARAMS((PTR_T, const char *, int, int));
|
|
|
|
|
#ifndef NO_VALLOC
|
|
|
|
|
static PTR_T internal_valloc PARAMS((size_t, const char *, int, int));
|
|
|
|
|
#endif
|
|
|
|
|
static PTR_T internal_remap PARAMS((PTR_T, size_t, int, int));
|
|
|
|
|
|
|
|
|
|
#if defined (botch)
|
|
|
|
|
extern void botch ();
|
|
|
|
@@ -741,14 +749,6 @@ malloc_debug_dummy ()
|
|
|
|
|
write (1, "malloc_debug_dummy\n", 19);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if SIZEOF_CHAR_P == 8
|
|
|
|
|
#define PREPOP_BIN 3
|
|
|
|
|
#define PREPOP_SIZE 64
|
|
|
|
|
#else
|
|
|
|
|
#define PREPOP_BIN 2
|
|
|
|
|
#define PREPOP_SIZE 32
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
pagealign ()
|
|
|
|
|
{
|
|
|
|
@@ -758,8 +758,8 @@ pagealign ()
|
|
|
|
|
char *curbrk;
|
|
|
|
|
|
|
|
|
|
pagesz = getpagesize ();
|
|
|
|
|
if (pagesz < 1024)
|
|
|
|
|
pagesz = 1024;
|
|
|
|
|
if (pagesz < MALLOC_PAGESIZE_MIN)
|
|
|
|
|
pagesz = MALLOC_PAGESIZE_MIN;
|
|
|
|
|
|
|
|
|
|
/* OK, how much do we need to allocate to make things page-aligned?
|
|
|
|
|
Some of this partial page will be wasted space, but we'll use as
|
|
|
|
@@ -825,7 +825,7 @@ internal_malloc (n, file, line, flags) /* get a block */
|
|
|
|
|
register union mhead *p;
|
|
|
|
|
register int nunits;
|
|
|
|
|
register char *m, *z;
|
|
|
|
|
long nbytes;
|
|
|
|
|
MALLOC_SIZE_T nbytes;
|
|
|
|
|
mguard_t mg;
|
|
|
|
|
|
|
|
|
|
/* Get the system page size and align break pointer so future sbrks will
|
|
|
|
@@ -839,6 +839,10 @@ internal_malloc (n, file, line, flags) /* get a block */
|
|
|
|
|
multiple of 8, then figure out which nextf[] area to use. Try to
|
|
|
|
|
be smart about where to start searching -- if the number of bytes
|
|
|
|
|
needed is greater than the page size, we can start at pagebucket. */
|
|
|
|
|
#if SIZEOF_SIZE_T == 8
|
|
|
|
|
if (ALLOCATED_BYTES(n) > MAXALLOC_SIZE)
|
|
|
|
|
return ((PTR_T) NULL);
|
|
|
|
|
#endif
|
|
|
|
|
nbytes = ALLOCATED_BYTES(n);
|
|
|
|
|
nunits = (nbytes <= (pagesz >> 1)) ? STARTBUCK : pagebucket;
|
|
|
|
|
for ( ; nunits < NBUCKETS; nunits++)
|
|
|
|
@@ -886,10 +890,8 @@ internal_malloc (n, file, line, flags) /* get a block */
|
|
|
|
|
p->mh_magic2 = MAGIC2;
|
|
|
|
|
p->mh_nbytes = n;
|
|
|
|
|
|
|
|
|
|
#if SIZEOF_CHAR_P == 8
|
|
|
|
|
/* Begin guard */
|
|
|
|
|
MALLOC_MEMSET ((char *)p->mh_magic8, MAGIC1, 8);
|
|
|
|
|
#endif
|
|
|
|
|
MALLOC_MEMSET ((char *)p->mh_magic8, MAGIC1, MAGIC8_NUMBYTES);
|
|
|
|
|
|
|
|
|
|
/* End guard */
|
|
|
|
|
mg.i = n;
|
|
|
|
@@ -945,8 +947,8 @@ internal_free (mem, file, line, flags)
|
|
|
|
|
register union mhead *p;
|
|
|
|
|
register char *ap, *z;
|
|
|
|
|
register int nunits;
|
|
|
|
|
register unsigned int nbytes;
|
|
|
|
|
int ubytes; /* caller-requested size */
|
|
|
|
|
register MALLOC_SIZE_T nbytes;
|
|
|
|
|
MALLOC_SIZE_T ubytes; /* caller-requested size */
|
|
|
|
|
mguard_t mg;
|
|
|
|
|
|
|
|
|
|
if ((ap = (char *)mem) == 0)
|
|
|
|
@@ -979,28 +981,25 @@ internal_free (mem, file, line, flags)
|
|
|
|
|
|
|
|
|
|
nunits = p->mh_index;
|
|
|
|
|
nbytes = ALLOCATED_BYTES(p->mh_nbytes);
|
|
|
|
|
/* Since the sizeof(u_bits32_t) bytes before the memory handed to the user
|
|
|
|
|
are now used for the number of bytes allocated, a simple check of
|
|
|
|
|
mh_magic2 is no longer sufficient to catch things like p[-1] = 'x'.
|
|
|
|
|
/* The MAGIC8_NUMBYTES bytes before the memory handed to the user are now
|
|
|
|
|
used for a simple check to catch things like p[-1] = 'x'.
|
|
|
|
|
We sanity-check the value of mh_nbytes against the size of the blocks
|
|
|
|
|
in the appropriate bucket before we use it. This can still cause problems
|
|
|
|
|
and obscure errors if mh_nbytes is wrong but still within range; the
|
|
|
|
|
checks against the size recorded at the end of the chunk will probably
|
|
|
|
|
fail then. Using MALLOC_REGISTER will help here, since it saves the
|
|
|
|
|
fail then. Using MALLOC_REGISTER will help here, since it saves the
|
|
|
|
|
original number of bytes requested. */
|
|
|
|
|
|
|
|
|
|
if (IN_BUCKET(nbytes, nunits) == 0)
|
|
|
|
|
xbotch (mem, ERR_UNDERFLOW,
|
|
|
|
|
_("free: underflow detected; mh_nbytes out of range"), file, line);
|
|
|
|
|
#if SIZEOF_CHAR_P == 8
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0, z = p->mh_magic8; i < 8; i++)
|
|
|
|
|
for (i = 0, z = p->mh_magic8; i < MAGIC8_NUMBYTES; i++)
|
|
|
|
|
if (*z++ != MAGIC1)
|
|
|
|
|
xbotch (mem, ERR_UNDERFLOW,
|
|
|
|
|
_("free: underflow detected; magic8 corrupted"), file, line);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ap += p->mh_nbytes;
|
|
|
|
|
z = mg.s;
|
|
|
|
@@ -1084,6 +1083,58 @@ free_return:
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if USE_MMAP == 1 && defined (HAVE_MREMAP)
|
|
|
|
|
/* Assume the caller (internal_realloc) has already performed the sanity and
|
|
|
|
|
overflow tests. Basically we kill the old guard information, determine the
|
|
|
|
|
new size, call mremap with the new size, and add the bookkeeping and guard
|
|
|
|
|
information back in. */
|
|
|
|
|
static PTR_T
|
|
|
|
|
internal_remap (mem, n, nunits, flags)
|
|
|
|
|
PTR_T mem;
|
|
|
|
|
register size_t n;
|
|
|
|
|
int nunits;
|
|
|
|
|
int flags;
|
|
|
|
|
{
|
|
|
|
|
register union mhead *p, *np;
|
|
|
|
|
char *m, *z;
|
|
|
|
|
mguard_t mg;
|
|
|
|
|
MALLOC_SIZE_T nbytes;
|
|
|
|
|
|
|
|
|
|
if (nunits >= NBUCKETS) /* Uh oh */
|
|
|
|
|
return ((PTR_T) NULL);
|
|
|
|
|
|
|
|
|
|
p = (union mhead *)mem - 1;
|
|
|
|
|
|
|
|
|
|
m = (char *)mem + p->mh_nbytes;
|
|
|
|
|
z = mg.s;
|
|
|
|
|
*m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; /* erase guard */
|
|
|
|
|
|
|
|
|
|
nbytes = ALLOCATED_BYTES(n);
|
|
|
|
|
|
|
|
|
|
busy[nunits] = 1;
|
|
|
|
|
np = (union mhead *)mremap (p, binsize (p->mh_index), binsize (nunits), MREMAP_MAYMOVE);
|
|
|
|
|
busy[nunits] = 0;
|
|
|
|
|
if (np == MAP_FAILED)
|
|
|
|
|
return (PTR_T)NULL;
|
|
|
|
|
|
|
|
|
|
if (np != p)
|
|
|
|
|
{
|
|
|
|
|
np->mh_alloc = ISALLOC;
|
|
|
|
|
np->mh_magic2 = MAGIC2;
|
|
|
|
|
MALLOC_MEMSET ((char *)np->mh_magic8, MAGIC1, MAGIC8_NUMBYTES);
|
|
|
|
|
}
|
|
|
|
|
np->mh_index = nunits;
|
|
|
|
|
np->mh_nbytes = n;
|
|
|
|
|
|
|
|
|
|
mg.i = n;
|
|
|
|
|
z = mg.s;
|
|
|
|
|
m = (char *)(np + 1) + n;
|
|
|
|
|
*m++ = *z++, *m++ = *z++, *m++ = *z++, *m++ = *z++;
|
|
|
|
|
|
|
|
|
|
return ((PTR_T)(np + 1));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static PTR_T
|
|
|
|
|
internal_realloc (mem, n, file, line, flags)
|
|
|
|
|
PTR_T mem;
|
|
|
|
@@ -1092,9 +1143,9 @@ internal_realloc (mem, n, file, line, flags)
|
|
|
|
|
int line, flags;
|
|
|
|
|
{
|
|
|
|
|
register union mhead *p;
|
|
|
|
|
register u_bits32_t tocopy;
|
|
|
|
|
register unsigned int nbytes;
|
|
|
|
|
register int nunits;
|
|
|
|
|
register MALLOC_SIZE_T tocopy;
|
|
|
|
|
register MALLOC_SIZE_T nbytes;
|
|
|
|
|
register int newunits, nunits;
|
|
|
|
|
register char *m, *z;
|
|
|
|
|
mguard_t mg;
|
|
|
|
|
|
|
|
|
@@ -1132,16 +1183,14 @@ internal_realloc (mem, n, file, line, flags)
|
|
|
|
|
if (IN_BUCKET(nbytes, nunits) == 0)
|
|
|
|
|
xbotch (mem, ERR_UNDERFLOW,
|
|
|
|
|
_("realloc: underflow detected; mh_nbytes out of range"), file, line);
|
|
|
|
|
#if SIZEOF_CHAR_P == 8
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0, z = p->mh_magic8; i < 8; i++)
|
|
|
|
|
for (i = 0, z = p->mh_magic8; i < MAGIC8_NUMBYTES; i++)
|
|
|
|
|
if (*z++ != MAGIC1)
|
|
|
|
|
xbotch (mem, ERR_UNDERFLOW,
|
|
|
|
|
_("realloc: underflow detected; magic8 corrupted"), file, line);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
m = (char *)mem + (tocopy = p->mh_nbytes);
|
|
|
|
|
z = mg.s;
|
|
|
|
@@ -1161,6 +1210,10 @@ internal_realloc (mem, n, file, line, flags)
|
|
|
|
|
if (n == p->mh_nbytes)
|
|
|
|
|
return mem;
|
|
|
|
|
|
|
|
|
|
#if SIZEOF_SIZE_T == 8
|
|
|
|
|
if (ALLOCATED_BYTES(n) > MAXALLOC_SIZE)
|
|
|
|
|
return ((PTR_T) NULL);
|
|
|
|
|
#endif
|
|
|
|
|
/* See if desired size rounds to same power of 2 as actual size. */
|
|
|
|
|
nbytes = ALLOCATED_BYTES(n);
|
|
|
|
|
|
|
|
|
@@ -1187,12 +1240,31 @@ internal_realloc (mem, n, file, line, flags)
|
|
|
|
|
_mstats.nrcopy++;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* If we are using mmap and have mremap, we could use it here. */
|
|
|
|
|
/* If we are using mmap and have mremap, we use it here. Make sure that
|
|
|
|
|
the old size and new size are above the threshold where we use mmap */
|
|
|
|
|
#if USE_MMAP == 1 && defined (HAVE_MREMAP)
|
|
|
|
|
if (nbytes > p->mh_nbytes)
|
|
|
|
|
newunits = nunits;
|
|
|
|
|
else
|
|
|
|
|
newunits = (nbytes <= (pagesz >> 1)) ? STARTBUCK : pagebucket;
|
|
|
|
|
for ( ; newunits < NBUCKETS; newunits++)
|
|
|
|
|
if (nbytes <= binsize(newunits))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (nunits > malloc_mmap_threshold && newunits > malloc_mmap_threshold)
|
|
|
|
|
{
|
|
|
|
|
m = internal_remap (mem, n, newunits, MALLOC_INTERNAL);
|
|
|
|
|
if (m == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
if ((m = internal_malloc (n, file, line, MALLOC_INTERNAL|MALLOC_NOTRACE|MALLOC_NOREG)) == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
FASTCOPY (mem, m, tocopy);
|
|
|
|
|
internal_free (mem, file, line, MALLOC_INTERNAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef MALLOC_TRACE
|
|
|
|
|
if (malloc_trace && (flags & MALLOC_NOTRACE) == 0)
|
|
|
|
|