aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-01-26 23:00:10 -0800
committerPaul Eggert2016-01-26 23:01:48 -0800
commitb88e9cded7ae3756e3a2ec4a23e8df352a0239f9 (patch)
tree201806e4c770722fa29ef77365030df930751d06 /src
parentcf17002326ba29d78f20118e0016dbd32fc3527e (diff)
downloademacs-b88e9cded7ae3756e3a2ec4a23e8df352a0239f9.tar.gz
emacs-b88e9cded7ae3756e3a2ec4a23e8df352a0239f9.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c76
-rw-r--r--src/emacs.c78
-rw-r--r--src/lisp.h8
3 files changed, 88 insertions, 74 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 03dacc77c6e..d379761c168 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -92,6 +92,18 @@ static bool valgrind_p;
92#include "w32heap.h" /* for sbrk */ 92#include "w32heap.h" /* for sbrk */
93#endif 93#endif
94 94
95#if defined DOUG_LEA_MALLOC || defined GNU_LINUX
96/* The address where the heap starts. */
97void *
98my_heap_start (void)
99{
100 static void *start;
101 if (! start)
102 start = sbrk (0);
103 return start;
104}
105#endif
106
95#ifdef DOUG_LEA_MALLOC 107#ifdef DOUG_LEA_MALLOC
96 108
97#include <malloc.h> 109#include <malloc.h>
@@ -101,7 +113,69 @@ static bool valgrind_p;
101 113
102#define MMAP_MAX_AREAS 100000000 114#define MMAP_MAX_AREAS 100000000
103 115
104#endif /* not DOUG_LEA_MALLOC */ 116/* A pointer to the memory allocated that copies that static data
117 inside glibc's malloc. */
118static void *malloc_state_ptr;
119
120/* Get and free this pointer; useful around unexec. */
121void
122alloc_unexec_pre (void)
123{
124 malloc_state_ptr = malloc_get_state ();
125}
126void
127alloc_unexec_post (void)
128{
129 free (malloc_state_ptr);
130}
131
132/* Restore the dumped malloc state. Because malloc can be invoked
133 even before main (e.g. by the dynamic linker), the dumped malloc
134 state must be restored as early as possible using this special hook. */
135static void
136malloc_initialize_hook (void)
137{
138 static bool malloc_using_checking;
139
140 if (! initialized)
141 {
142 my_heap_start ();
143 malloc_using_checking = getenv ("MALLOC_CHECK_") != NULL;
144 }
145 else
146 {
147 if (!malloc_using_checking)
148 {
149 /* Work around a bug in glibc's malloc. MALLOC_CHECK_ must be
150 ignored if the heap to be restored was constructed without
151 malloc checking. Can't use unsetenv, since that calls malloc. */
152 char **p = environ;
153 if (p)
154 for (; *p; p++)
155 if (strncmp (*p, "MALLOC_CHECK_=", 14) == 0)
156 {
157 do
158 *p = p[1];
159 while (*++p);
160
161 break;
162 }
163 }
164
165 malloc_set_state (malloc_state_ptr);
166# ifndef XMALLOC_OVERRUN_CHECK
167 alloc_unexec_post ();
168# endif
169 }
170}
171
172# ifndef __MALLOC_HOOK_VOLATILE
173# define __MALLOC_HOOK_VOLATILE
174# endif
175voidfuncptr __MALLOC_HOOK_VOLATILE __malloc_initialize_hook
176 = malloc_initialize_hook;
177
178#endif
105 179
106/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer 180/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer
107 to a struct Lisp_String. */ 181 to a struct Lisp_String. */
diff --git a/src/emacs.c b/src/emacs.c
index 89d8ca784ae..e3cfad0f7f8 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -133,20 +133,7 @@ bool might_dump;
133extern void unexec_init_emacs_zone (void); 133extern void unexec_init_emacs_zone (void);
134#endif 134#endif
135 135
136#ifdef DOUG_LEA_MALLOC
137/* Preserves a pointer to the memory allocated that copies that
138 static data inside glibc's malloc. */
139static void *malloc_state_ptr;
140/* From glibc, a routine that returns a copy of the malloc internal state. */
141extern void *malloc_get_state (void);
142/* From glibc, a routine that overwrites the malloc internal state. */
143extern int malloc_set_state (void *);
144/* True if the MALLOC_CHECK_ environment variable was set while
145 dumping. Used to work around a bug in glibc's malloc. */
146static bool malloc_using_checking;
147#elif defined HAVE_PTHREAD && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
148extern void malloc_enable_thread (void); 136extern void malloc_enable_thread (void);
149#endif
150 137
151/* If true, Emacs should not attempt to use a window-specific code, 138/* If true, Emacs should not attempt to use a window-specific code,
152 but instead should use the virtual terminal under which it was started. */ 139 but instead should use the virtual terminal under which it was started. */
@@ -165,11 +152,6 @@ bool display_arg;
165 Tells GC how to save a copy of the stack. */ 152 Tells GC how to save a copy of the stack. */
166char *stack_bottom; 153char *stack_bottom;
167 154
168#if defined (DOUG_LEA_MALLOC) || defined (GNU_LINUX)
169/* The address where the heap starts (from the first sbrk (0) call). */
170static void *my_heap_start;
171#endif
172
173#ifdef GNU_LINUX 155#ifdef GNU_LINUX
174/* The gap between BSS end and heap start as far as we can tell. */ 156/* The gap between BSS end and heap start as far as we can tell. */
175static uprintmax_t heap_bss_diff; 157static uprintmax_t heap_bss_diff;
@@ -651,51 +633,6 @@ argmatch (char **argv, int argc, const char *sstr, const char *lstr,
651 } 633 }
652} 634}
653 635
654#ifdef DOUG_LEA_MALLOC
655
656/* malloc can be invoked even before main (e.g. by the dynamic
657 linker), so the dumped malloc state must be restored as early as
658 possible using this special hook. */
659
660static void
661malloc_initialize_hook (void)
662{
663 if (initialized)
664 {
665 if (!malloc_using_checking)
666 /* Work around a bug in glibc's malloc. MALLOC_CHECK_ must be
667 ignored if the heap to be restored was constructed without
668 malloc checking. Can't use unsetenv, since that calls malloc. */
669 {
670 char **p;
671
672 for (p = environ; p && *p; p++)
673 if (strncmp (*p, "MALLOC_CHECK_=", 14) == 0)
674 {
675 do
676 *p = p[1];
677 while (*++p);
678 break;
679 }
680 }
681
682 malloc_set_state (malloc_state_ptr);
683#ifndef XMALLOC_OVERRUN_CHECK
684 free (malloc_state_ptr);
685#endif
686 }
687 else
688 {
689 if (my_heap_start == 0)
690 my_heap_start = sbrk (0);
691 malloc_using_checking = getenv ("MALLOC_CHECK_") != NULL;
692 }
693}
694
695void (*__malloc_initialize_hook) (void) EXTERNALLY_VISIBLE = malloc_initialize_hook;
696
697#endif /* DOUG_LEA_MALLOC */
698
699/* Close standard output and standard error, reporting any write 636/* Close standard output and standard error, reporting any write
700 errors as best we can. This is intended for use with atexit. */ 637 errors as best we can. This is intended for use with atexit. */
701static void 638static void
@@ -743,10 +680,8 @@ main (int argc, char **argv)
743#ifdef GNU_LINUX 680#ifdef GNU_LINUX
744 if (!initialized) 681 if (!initialized)
745 { 682 {
746 if (my_heap_start == 0) 683 char *heap_start = my_heap_start ();
747 my_heap_start = sbrk (0); 684 heap_bss_diff = heap_start - max (my_endbss, my_endbss_static);
748
749 heap_bss_diff = (char *)my_heap_start - max (my_endbss, my_endbss_static);
750 } 685 }
751#endif 686#endif
752 687
@@ -2145,15 +2080,12 @@ You must run Emacs in batch mode in order to dump it. */)
2145 memory_warnings (my_edata, malloc_warning); 2080 memory_warnings (my_edata, malloc_warning);
2146#endif /* not WINDOWSNT */ 2081#endif /* not WINDOWSNT */
2147#endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */ 2082#endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */
2148#ifdef DOUG_LEA_MALLOC 2083
2149 malloc_state_ptr = malloc_get_state (); 2084 alloc_unexec_pre ();
2150#endif
2151 2085
2152 unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0); 2086 unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0);
2153 2087
2154#ifdef DOUG_LEA_MALLOC 2088 alloc_unexec_post ();
2155 free (malloc_state_ptr);
2156#endif
2157 2089
2158#ifdef WINDOWSNT 2090#ifdef WINDOWSNT
2159 Vlibrary_cache = Qnil; 2091 Vlibrary_cache = Qnil;
diff --git a/src/lisp.h b/src/lisp.h
index 6be2104ef9e..82cbca8e6ba 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3590,6 +3590,7 @@ extern void parse_str_as_multibyte (const unsigned char *, ptrdiff_t,
3590 ptrdiff_t *, ptrdiff_t *); 3590 ptrdiff_t *, ptrdiff_t *);
3591 3591
3592/* Defined in alloc.c. */ 3592/* Defined in alloc.c. */
3593extern void *my_heap_start (void);
3593extern void check_pure_size (void); 3594extern void check_pure_size (void);
3594extern void free_misc (Lisp_Object); 3595extern void free_misc (Lisp_Object);
3595extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT); 3596extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
@@ -3601,6 +3602,13 @@ extern void mark_object (Lisp_Object);
3601#if defined REL_ALLOC && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC 3602#if defined REL_ALLOC && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
3602extern void refill_memory_reserve (void); 3603extern void refill_memory_reserve (void);
3603#endif 3604#endif
3605#ifdef DOUG_LEA_MALLOC
3606extern void alloc_unexec_pre (void);
3607extern void alloc_unexec_post (void);
3608#else
3609INLINE void alloc_unexec_pre (void) {}
3610INLINE void alloc_unexec_post (void) {}
3611#endif
3604extern const char *pending_malloc_warning; 3612extern const char *pending_malloc_warning;
3605extern Lisp_Object zero_vector; 3613extern Lisp_Object zero_vector;
3606extern Lisp_Object *stack_base; 3614extern Lisp_Object *stack_base;