commit bash-20210206 snapshot

This commit is contained in:
Chet Ramey
2021-02-09 16:22:13 -05:00
parent 6110f1bc2b
commit 220a95cdfb
8 changed files with 195 additions and 64 deletions
+19
View File
@@ -9536,3 +9536,22 @@ array.h,variables.c
variables.c
- pop_args: a couple of code simplifications
2/7
---
lib/malloc/malloc.c
- pagesz: at least MALLOC_PAGESIZE_MIN (4096) bytes
- union mhead: now 16-byte aligned on all systems, 32-bit and 64-bit
pointers
- binsizes: since the smallest allocation overhead is now 16 bytes,
redo the buckets so binsizes[0] == 32; adjust the thresholds for
split/coalesce/prepopulate/mmap (NBUCKETS = 28; STARTBUCK = 0).
Sizes stay pretty much the same; indices change
- consistently use MALLOC_SIZE_T instead of long/unsigned int/int
- use MAGIC8_NUMBYTES as the length of the mh_magic8 buffer, in case
it changes later for alignment
- internal_remap: new function, calls mremap to reallocate a chunk of
memory allocated using mmap(); called from internal_realloc if the
old size and new size are both bigger than the mmap threshold
- internal_realloc: call internal_remap if the old size and new size
are both above the threshold where we use mmap for allocation
+3
View File
@@ -233,6 +233,9 @@
/* The number of bytes in a pointer to char. */
#undef SIZEOF_CHAR_P
/* The number of bytes in a size_t. */
#undef SIZEOF_SIZE_T
/* The number of bytes in a double (hopefully 8). */
#undef SIZEOF_DOUBLE
Vendored
+33
View File
@@ -16440,6 +16440,39 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5
$as_echo_n "checking size of size_t... " >&6; }
if ${ac_cv_sizeof_size_t+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"; then :
else
if test "$ac_cv_type_size_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (size_t)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_size_t=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5
$as_echo "$ac_cv_sizeof_size_t" >&6; }
cat >>confdefs.h <<_ACEOF
#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t
_ACEOF
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+1
View File
@@ -970,6 +970,7 @@ AC_CHECK_SIZEOF(short, 2)
AC_CHECK_SIZEOF(int, 4)
AC_CHECK_SIZEOF(long, 4)
AC_CHECK_SIZEOF(char *, 4)
AC_CHECK_SIZEOF(size_t, 4)
AC_CHECK_SIZEOF(double, 8)
AC_CHECK_SIZEOF([long long], 8)
+3
View File
@@ -683,6 +683,9 @@ check_binary_file (sample, sample_len)
register int i;
unsigned char c;
if (sample_len >= 4 && sample[0] == 0x7f && sample[1] == 'E' && sample[2] == 'L' && sample[3] == 'F')
return 1;
for (i = 0; i < sample_len; i++)
{
c = sample[i];
+134 -62
View File
@@ -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)
+1 -1
View File
@@ -27,7 +27,7 @@
/* This needs to change if the definition in malloc.c changes */
#ifndef NBUCKETS
# define NBUCKETS 30
# define NBUCKETS 28
#endif
/*
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/bash/bash-current
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR