From f701dc2abbcfb64c0c4d02ac899dccb03ee2b246 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 30 Sep 2011 10:07:40 -0700 Subject: [PATCH] Remove dependency on glibc malloc internals. * alloc.c (XMALLOC_OVERRUN_CHECK_OVERHEAD, XMALLOC_OVERRUN_CHECK_SIZE): Move back here from lisp.h, but with their new implementations. (XMALLOC_BASE_ALIGNMENT, COMMON_MULTIPLE, XMALLOC_HEADER_ALIGNMENT) (XMALLOC_OVERRUN_SIZE_SIZE): Move these new lisp.h macros here. * charset.c (charset_table_init): New static var. (syms_of_charset): Use it instead of xmalloc. This removes a dependency on glibc malloc internals. See Eli Zaretskii's comment in . * lisp.h (XMALLOC_OVERRUN_CHECK_OVERHEAD, XMALLOC_OVERRUN_CHECK_SIZE): Move back to alloc.c. (XMALLOC_BASE_ALIGNMENT, COMMON_MULTIPLE, XMALLOC_HEADER_ALIGNMENT) (XMALLOC_OVERRUN_SIZE_SIZE): Move to alloc.c. --- src/ChangeLog | 16 ++++++++++++++++ src/alloc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- src/charset.c | 38 ++++++++++++++++++-------------------- src/lisp.h | 48 ------------------------------------------------ 4 files changed, 79 insertions(+), 70 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 37d2de93c11..89e705efd73 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2011-09-30 Paul Eggert + + Remove dependency on glibc malloc internals. + * alloc.c (XMALLOC_OVERRUN_CHECK_OVERHEAD, XMALLOC_OVERRUN_CHECK_SIZE): + Move back here from lisp.h, but with their new implementations. + (XMALLOC_BASE_ALIGNMENT, COMMON_MULTIPLE, XMALLOC_HEADER_ALIGNMENT) + (XMALLOC_OVERRUN_SIZE_SIZE): Move these new lisp.h macros here. + * charset.c (charset_table_init): New static var. + (syms_of_charset): Use it instead of xmalloc. This removes a + dependency on glibc malloc internals. See Eli Zaretskii's comment in + . + * lisp.h (XMALLOC_OVERRUN_CHECK_OVERHEAD, XMALLOC_OVERRUN_CHECK_SIZE): + Move back to alloc.c. + (XMALLOC_BASE_ALIGNMENT, COMMON_MULTIPLE, XMALLOC_HEADER_ALIGNMENT) + (XMALLOC_OVERRUN_SIZE_SIZE): Move to alloc.c. + 2011-09-30 Jan Djärv * nsterm.m (windowDidResize): Call x_set_window_size only when diff --git a/src/alloc.c b/src/alloc.c index 4c5094b8f48..ead5c8a8ca4 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -482,10 +482,53 @@ buffer_memory_full (EMACS_INT nbytes) xsignal (Qnil, Vmemory_signal_data); } -#ifdef XMALLOC_OVERRUN_CHECK + +#ifndef XMALLOC_OVERRUN_CHECK +#define XMALLOC_OVERRUN_CHECK_OVERHEAD 0 +#else /* Check for overrun in malloc'ed buffers by wrapping a header and trailer - around each block. */ + around each block. + + The header consists of XMALLOC_OVERRUN_CHECK_SIZE fixed bytes + followed by XMALLOC_OVERRUN_SIZE_SIZE bytes containing the original + block size in little-endian order. The trailer consists of + XMALLOC_OVERRUN_CHECK_SIZE fixed bytes. + + The header is used to detect whether this block has been allocated + through these functions, as some low-level libc functions may + bypass the malloc hooks. */ + +#define XMALLOC_OVERRUN_CHECK_SIZE 16 +#define XMALLOC_OVERRUN_CHECK_OVERHEAD \ + (2 * XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE) + +/* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to + hold a size_t value and (2) the header size is a multiple of the + alignment that Emacs needs for C types and for USE_LSB_TAG. */ +#define XMALLOC_BASE_ALIGNMENT \ + offsetof ( \ + struct { \ + union { long double d; intmax_t i; void *p; } u; \ + char c; \ + }, \ + c) +#ifdef USE_LSB_TAG +/* A common multiple of the positive integers A and B. Ideally this + would be the least common multiple, but there's no way to do that + as a constant expression in C, so do the best that we can easily do. */ +# define COMMON_MULTIPLE(a, b) \ + ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) +# define XMALLOC_HEADER_ALIGNMENT \ + COMMON_MULTIPLE (1 << GCTYPEBITS, XMALLOC_BASE_ALIGNMENT) +#else +# define XMALLOC_HEADER_ALIGNMENT XMALLOC_BASE_ALIGNMENT +#endif +#define XMALLOC_OVERRUN_SIZE_SIZE \ + (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \ + + XMALLOC_HEADER_ALIGNMENT - 1) \ + / XMALLOC_HEADER_ALIGNMENT * XMALLOC_HEADER_ALIGNMENT) \ + - XMALLOC_OVERRUN_CHECK_SIZE) static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] = { '\x9a', '\x9b', '\xae', '\xaf', diff --git a/src/charset.c b/src/charset.c index f1b4897ffe6..8d6a3982d14 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1162,10 +1162,10 @@ usage: (define-charset-internal ...) */) sizeof *charset_table); memcpy (new_table, charset_table, old_size * sizeof *new_table); charset_table = new_table; - /* FIXME: Doesn't this leak memory? The old charset_table becomes - unreachable. It could be that this is intentional, because the - old charset table may be in a dumped emacs, and reallocating such - a table may not work. If the memory leak is intentional, a + /* FIXME: This leaks memory, as the old charset_table becomes + unreachable. If the old charset table is charset_table_init + then this leak is intentional; otherwise, it's unclear. + If the latter memory leak is intentional, a comment should be added to explain this. If not, the old charset_table should be freed, by passing it as the 1st argument to xpalloc and removing the memcpy. */ @@ -2327,22 +2327,21 @@ init_charset_once (void) #ifdef emacs +/* Allocate an initial charset table that is large enough to handle + Emacs while it is bootstrapping. As of September 2011, the size + needs to be at least 166; make it a bit bigger to allow for future + expansion. + + Don't make the value so small that the table is reallocated during + bootstrapping, as glibc malloc calls larger than just under 64 KiB + during an initial bootstrap wreak havoc after dumping; see the + M_MMAP_THRESHOLD value in alloc.c, plus there is a extra overhead + internal to glibc malloc and perhaps to Emacs malloc debugging. */ +static struct charset charset_table_init[180]; + void syms_of_charset (void) { - /* Allocate an initial charset table that is just under 64 KiB in size. - This should be large enough so that the charset table need not be - reallocated during an initial bootstrap. Allocating anything larger than - 64 KiB in an initial run may not work, because glibc malloc might use - mmap for larger allocations, and these don't work well across dumped - systems. */ - enum { - glibc_malloc_overhead = 3 * sizeof (size_t) - 1, - initial_malloc_max = - (1 << 16) - 1 - glibc_malloc_overhead - XMALLOC_OVERRUN_CHECK_OVERHEAD, - charset_table_size_init = initial_malloc_max / sizeof (struct charset) - }; - DEFSYM (Qcharsetp, "charsetp"); DEFSYM (Qascii, "ascii"); @@ -2375,9 +2374,8 @@ syms_of_charset (void) Vcharset_hash_table = Fmake_hash_table (2, args); } - charset_table = (struct charset *) xmalloc (sizeof (struct charset) - * charset_table_size_init); - charset_table_size = charset_table_size_init; + charset_table = charset_table_init; + charset_table_size = sizeof charset_table_init / sizeof *charset_table_init; charset_table_used = 0; defsubr (&Scharsetp); diff --git a/src/lisp.h b/src/lisp.h index 7aba299f162..e9a525a32b5 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3568,54 +3568,6 @@ extern int initialized; extern int immediate_quit; /* Nonzero means ^G can quit instantly */ -/* Overhead for overrun check in malloc'ed buffers. The check - operates by wrapping a header and trailer around each block. - - The header consists of XMALLOC_OVERRUN_CHECK_SIZE fixed bytes - followed by XMALLOC_OVERRUN_SIZE_SIZE bytes containing the original - block size in little-endian order. The trailer consists of - XMALLOC_OVERRUN_CHECK_SIZE fixed bytes. - - The header is used to detect whether this block has been allocated - through these functions, as some low-level libc functions may - bypass the malloc hooks. */ - -#ifndef XMALLOC_OVERRUN_CHECK -# define XMALLOC_OVERRUN_CHECK_OVERHEAD 0 -#else - -# define XMALLOC_OVERRUN_CHECK_SIZE 16 -# define XMALLOC_OVERRUN_CHECK_OVERHEAD \ - (2 * XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE) - -/* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to - hold a size_t value and (2) the header size is a multiple of the - alignment that Emacs needs for C types and for USE_LSB_TAG. */ -# define XMALLOC_BASE_ALIGNMENT \ - offsetof ( \ - struct { \ - union { long double d; intmax_t i; void *p; } u; \ - char c; \ - }, \ - c) -# ifdef USE_LSB_TAG -/* A common multiple of the positive integers A and B. Ideally this - would be the least common multiple, but there's no way to do that - as a constant expression in C, so do the best that we can easily do. */ -# define COMMON_MULTIPLE(a, b) \ - ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) -# define XMALLOC_HEADER_ALIGNMENT \ - COMMON_MULTIPLE (1 << GCTYPEBITS, XMALLOC_BASE_ALIGNMENT) -# else -# define XMALLOC_HEADER_ALIGNMENT XMALLOC_BASE_ALIGNMENT -# endif -# define XMALLOC_OVERRUN_SIZE_SIZE \ - (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \ - + XMALLOC_HEADER_ALIGNMENT - 1) \ - / XMALLOC_HEADER_ALIGNMENT * XMALLOC_HEADER_ALIGNMENT) \ - - XMALLOC_OVERRUN_CHECK_SIZE) -#endif - extern POINTER_TYPE *xmalloc (size_t); extern POINTER_TYPE *xrealloc (POINTER_TYPE *, size_t); extern void xfree (POINTER_TYPE *); -- 2.39.2