malloc.h hygiene
This attempts to future-proof Emacs a bit against possible glibc changes, by having Emacs use <malloc.h> declarations rather than coding them up by hand. Problem noted by Florian Weimer in: https://sourceware.org/ml/libc-alpha/2016-01/msg00777.html Implement this mainly by moving malloc.h-related functions from emacs.c (which does not include <malloc.h>) to alloc.c (which does). * src/alloc.c (my_heap_start) [DOUG_LEA_MALLOC || GNU_LINUX]: New function. The remaining changes to this file apply only if DOUG_LEA_MALLOC. (alloc_unexec_pre, alloc_unexec_post): New functions. (malloc_initialize_hook): Use my_heap_start and alloc_unexec_post. (__MALLOC_HOOK_VOLATILE): New macro, if not already defined. (__malloc_initialize_hook): Use it. (malloc_state_ptr, malloc_initialize_hook, __malloc_initialize_hook): Move here from ... * src/emacs.c: ... here. (malloc_get_state, malloc_set_state): Remove extern decls. (my_heap_start) [DOUG_LEA_MALLOC || GNU_LINUX]: Remove static var. All uses changed to similarly-named new function. (Fdump_emacs): Use new functions alloc_unexec_pre, alloc_unexec_post. * src/lisp.h (my_heap_start, alloc_unexec_pre, alloc_unexec_post): New decls.
This commit is contained in:
parent
cf17002326
commit
b88e9cded7
3 changed files with 88 additions and 74 deletions
76
src/alloc.c
76
src/alloc.c
|
@ -92,6 +92,18 @@ static bool valgrind_p;
|
|||
#include "w32heap.h" /* for sbrk */
|
||||
#endif
|
||||
|
||||
#if defined DOUG_LEA_MALLOC || defined GNU_LINUX
|
||||
/* The address where the heap starts. */
|
||||
void *
|
||||
my_heap_start (void)
|
||||
{
|
||||
static void *start;
|
||||
if (! start)
|
||||
start = sbrk (0);
|
||||
return start;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUG_LEA_MALLOC
|
||||
|
||||
#include <malloc.h>
|
||||
|
@ -101,7 +113,69 @@ static bool valgrind_p;
|
|||
|
||||
#define MMAP_MAX_AREAS 100000000
|
||||
|
||||
#endif /* not DOUG_LEA_MALLOC */
|
||||
/* A pointer to the memory allocated that copies that static data
|
||||
inside glibc's malloc. */
|
||||
static void *malloc_state_ptr;
|
||||
|
||||
/* Get and free this pointer; useful around unexec. */
|
||||
void
|
||||
alloc_unexec_pre (void)
|
||||
{
|
||||
malloc_state_ptr = malloc_get_state ();
|
||||
}
|
||||
void
|
||||
alloc_unexec_post (void)
|
||||
{
|
||||
free (malloc_state_ptr);
|
||||
}
|
||||
|
||||
/* Restore the dumped malloc state. Because malloc can be invoked
|
||||
even before main (e.g. by the dynamic linker), the dumped malloc
|
||||
state must be restored as early as possible using this special hook. */
|
||||
static void
|
||||
malloc_initialize_hook (void)
|
||||
{
|
||||
static bool malloc_using_checking;
|
||||
|
||||
if (! initialized)
|
||||
{
|
||||
my_heap_start ();
|
||||
malloc_using_checking = getenv ("MALLOC_CHECK_") != NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!malloc_using_checking)
|
||||
{
|
||||
/* Work around a bug in glibc's malloc. MALLOC_CHECK_ must be
|
||||
ignored if the heap to be restored was constructed without
|
||||
malloc checking. Can't use unsetenv, since that calls malloc. */
|
||||
char **p = environ;
|
||||
if (p)
|
||||
for (; *p; p++)
|
||||
if (strncmp (*p, "MALLOC_CHECK_=", 14) == 0)
|
||||
{
|
||||
do
|
||||
*p = p[1];
|
||||
while (*++p);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
malloc_set_state (malloc_state_ptr);
|
||||
# ifndef XMALLOC_OVERRUN_CHECK
|
||||
alloc_unexec_post ();
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
# ifndef __MALLOC_HOOK_VOLATILE
|
||||
# define __MALLOC_HOOK_VOLATILE
|
||||
# endif
|
||||
voidfuncptr __MALLOC_HOOK_VOLATILE __malloc_initialize_hook
|
||||
= malloc_initialize_hook;
|
||||
|
||||
#endif
|
||||
|
||||
/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer
|
||||
to a struct Lisp_String. */
|
||||
|
|
78
src/emacs.c
78
src/emacs.c
|
@ -133,20 +133,7 @@ bool might_dump;
|
|||
extern void unexec_init_emacs_zone (void);
|
||||
#endif
|
||||
|
||||
#ifdef DOUG_LEA_MALLOC
|
||||
/* Preserves a pointer to the memory allocated that copies that
|
||||
static data inside glibc's malloc. */
|
||||
static void *malloc_state_ptr;
|
||||
/* From glibc, a routine that returns a copy of the malloc internal state. */
|
||||
extern void *malloc_get_state (void);
|
||||
/* From glibc, a routine that overwrites the malloc internal state. */
|
||||
extern int malloc_set_state (void *);
|
||||
/* True if the MALLOC_CHECK_ environment variable was set while
|
||||
dumping. Used to work around a bug in glibc's malloc. */
|
||||
static bool malloc_using_checking;
|
||||
#elif defined HAVE_PTHREAD && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
|
||||
extern void malloc_enable_thread (void);
|
||||
#endif
|
||||
|
||||
/* If true, Emacs should not attempt to use a window-specific code,
|
||||
but instead should use the virtual terminal under which it was started. */
|
||||
|
@ -165,11 +152,6 @@ bool display_arg;
|
|||
Tells GC how to save a copy of the stack. */
|
||||
char *stack_bottom;
|
||||
|
||||
#if defined (DOUG_LEA_MALLOC) || defined (GNU_LINUX)
|
||||
/* The address where the heap starts (from the first sbrk (0) call). */
|
||||
static void *my_heap_start;
|
||||
#endif
|
||||
|
||||
#ifdef GNU_LINUX
|
||||
/* The gap between BSS end and heap start as far as we can tell. */
|
||||
static uprintmax_t heap_bss_diff;
|
||||
|
@ -651,51 +633,6 @@ argmatch (char **argv, int argc, const char *sstr, const char *lstr,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DOUG_LEA_MALLOC
|
||||
|
||||
/* malloc can be invoked even before main (e.g. by the dynamic
|
||||
linker), so the dumped malloc state must be restored as early as
|
||||
possible using this special hook. */
|
||||
|
||||
static void
|
||||
malloc_initialize_hook (void)
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
if (!malloc_using_checking)
|
||||
/* Work around a bug in glibc's malloc. MALLOC_CHECK_ must be
|
||||
ignored if the heap to be restored was constructed without
|
||||
malloc checking. Can't use unsetenv, since that calls malloc. */
|
||||
{
|
||||
char **p;
|
||||
|
||||
for (p = environ; p && *p; p++)
|
||||
if (strncmp (*p, "MALLOC_CHECK_=", 14) == 0)
|
||||
{
|
||||
do
|
||||
*p = p[1];
|
||||
while (*++p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
malloc_set_state (malloc_state_ptr);
|
||||
#ifndef XMALLOC_OVERRUN_CHECK
|
||||
free (malloc_state_ptr);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (my_heap_start == 0)
|
||||
my_heap_start = sbrk (0);
|
||||
malloc_using_checking = getenv ("MALLOC_CHECK_") != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void (*__malloc_initialize_hook) (void) EXTERNALLY_VISIBLE = malloc_initialize_hook;
|
||||
|
||||
#endif /* DOUG_LEA_MALLOC */
|
||||
|
||||
/* Close standard output and standard error, reporting any write
|
||||
errors as best we can. This is intended for use with atexit. */
|
||||
static void
|
||||
|
@ -743,10 +680,8 @@ main (int argc, char **argv)
|
|||
#ifdef GNU_LINUX
|
||||
if (!initialized)
|
||||
{
|
||||
if (my_heap_start == 0)
|
||||
my_heap_start = sbrk (0);
|
||||
|
||||
heap_bss_diff = (char *)my_heap_start - max (my_endbss, my_endbss_static);
|
||||
char *heap_start = my_heap_start ();
|
||||
heap_bss_diff = heap_start - max (my_endbss, my_endbss_static);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2145,15 +2080,12 @@ You must run Emacs in batch mode in order to dump it. */)
|
|||
memory_warnings (my_edata, malloc_warning);
|
||||
#endif /* not WINDOWSNT */
|
||||
#endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */
|
||||
#ifdef DOUG_LEA_MALLOC
|
||||
malloc_state_ptr = malloc_get_state ();
|
||||
#endif
|
||||
|
||||
alloc_unexec_pre ();
|
||||
|
||||
unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0);
|
||||
|
||||
#ifdef DOUG_LEA_MALLOC
|
||||
free (malloc_state_ptr);
|
||||
#endif
|
||||
alloc_unexec_post ();
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
Vlibrary_cache = Qnil;
|
||||
|
|
|
@ -3590,6 +3590,7 @@ extern void parse_str_as_multibyte (const unsigned char *, ptrdiff_t,
|
|||
ptrdiff_t *, ptrdiff_t *);
|
||||
|
||||
/* Defined in alloc.c. */
|
||||
extern void *my_heap_start (void);
|
||||
extern void check_pure_size (void);
|
||||
extern void free_misc (Lisp_Object);
|
||||
extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
|
||||
|
@ -3601,6 +3602,13 @@ extern void mark_object (Lisp_Object);
|
|||
#if defined REL_ALLOC && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
|
||||
extern void refill_memory_reserve (void);
|
||||
#endif
|
||||
#ifdef DOUG_LEA_MALLOC
|
||||
extern void alloc_unexec_pre (void);
|
||||
extern void alloc_unexec_post (void);
|
||||
#else
|
||||
INLINE void alloc_unexec_pre (void) {}
|
||||
INLINE void alloc_unexec_post (void) {}
|
||||
#endif
|
||||
extern const char *pending_malloc_warning;
|
||||
extern Lisp_Object zero_vector;
|
||||
extern Lisp_Object *stack_base;
|
||||
|
|
Loading…
Add table
Reference in a new issue