From a4579d332d432ea629a1ad2168ce8023d172d563 Mon Sep 17 00:00:00 2001 From: Ken Brown Date: Tue, 16 Aug 2011 09:27:12 -0400 Subject: [PATCH] Fix memory allocation problems in Cygwin build (Bug#9273). * src/gmalloc.c [CYGWIN] (bss_sbrk_heapbase, bss_sbrk_heapinfo): New variables. (malloc_initialize_1) [CYGWIN]: Prepare for reinitializing the dumped emacs. (_free_internal_nolock) [CYGWIN]: Ignore requests to free storage in the static heap. [CYGWIN] (special_realloc): New function. (_realloc_internal_nolock) [CYGWIN]: Use the new function on requests to realloc storage in the static heap. * src/unexcw.c ( __malloc_initialized): Declare external variable. (fixup_executable): Force the dumped emacs to reinitialize malloc. --- src/ChangeLog | 17 +++++++++++++++ src/gmalloc.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/unexcw.c | 5 +++++ 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index b16606ce121..2364f71c6a4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ +2011-08-16 Ken Brown + + Fix memory allocation problems in Cygwin build (Bug#9273). + + * unexcw.c ( __malloc_initialized): Declare external variable. + (fixup_executable): Force the dumped emacs to reinitialize malloc. + + * gmalloc.c [CYGWIN] (bss_sbrk_heapbase, bss_sbrk_heapinfo): New + variables. + (malloc_initialize_1) [CYGWIN]: Prepare for reinitializing the + dumped emacs. + (_free_internal_nolock) [CYGWIN]: Ignore requests to free storage + in the static heap. + [CYGWIN] (special_realloc): New function. + (_realloc_internal_nolock) [CYGWIN]: Use the new function on + requests to realloc storage in the static heap. + 2011-08-15 Paul Eggert * bidi.c (bidi_initialize): Remove unused local. diff --git a/src/gmalloc.c b/src/gmalloc.c index 916bb300fe1..61046ad9d1b 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -351,10 +351,17 @@ Fifth Floor, Boston, MA 02110-1301, USA. #endif #include -/* How to really get more memory. */ -#if defined(CYGWIN) +/* On Cygwin there are two heaps. temacs uses the static heap + (defined in sheap.c and managed with bss_sbrk), and the dumped + emacs uses the Cygwin heap (managed with sbrk). When emacs starts + on Cygwin, it reinitializes malloc, and we save the old info for + use by free and realloc if they're called with a pointer into the + static heap. */ +#ifdef CYGWIN extern __ptr_t bss_sbrk PP ((ptrdiff_t __size)); extern int bss_sbrk_did_unexec; +char *bss_sbrk_heapbase; /* _heapbase for static heap */ +malloc_info *bss_sbrk_heapinfo; /* _heapinfo for static heap */ #endif __ptr_t (*__morecore) PP ((__malloc_ptrdiff_t __size)) = __default_morecore; @@ -584,6 +591,16 @@ malloc_initialize_1 () mcheck (NULL); #endif +#ifdef CYGWIN + if (bss_sbrk_did_unexec) + /* we're reinitializing the dumped emacs */ + { + bss_sbrk_heapbase = _heapbase; + bss_sbrk_heapinfo = _heapinfo; + memset (_fraghead, 0, BLOCKLOG * sizeof (struct list)); + } +#endif + if (__malloc_initialize_hook) (*__malloc_initialize_hook) (); @@ -1054,6 +1071,12 @@ _free_internal_nolock (ptr) if (ptr == NULL) return; +#ifdef CYGWIN + if (ptr < _heapbase) + /* We're being asked to free something in the static heap. */ + return; +#endif + PROTECT_MALLOC_STATE (0); LOCK_ALIGNED_BLOCKS (); @@ -1349,6 +1372,31 @@ Fifth Floor, Boston, MA 02110-1301, USA. #define min(A, B) ((A) < (B) ? (A) : (B)) +/* On Cygwin the dumped emacs may try to realloc storage allocated in + the static heap. We just malloc space in the new heap and copy the + data. */ +#ifdef CYGWIN +__ptr_t +special_realloc (ptr, size) + __ptr_t ptr; + __malloc_size_t size; +{ + __ptr_t result; + int type; + __malloc_size_t block, oldsize; + + block = ((char *) ptr - bss_sbrk_heapbase) / BLOCKSIZE + 1; + type = bss_sbrk_heapinfo[block].busy.type; + oldsize = + type == 0 ? bss_sbrk_heapinfo[block].busy.info.size * BLOCKSIZE + : (__malloc_size_t) 1 << type; + result = _malloc_internal_nolock (size); + if (result != NULL) + memcpy (result, ptr, min (oldsize, size)); + return result; +} +#endif + /* Debugging hook for realloc. */ __ptr_t (*__realloc_hook) PP ((__ptr_t __ptr, __malloc_size_t __size)); @@ -1375,6 +1423,12 @@ _realloc_internal_nolock (ptr, size) else if (ptr == NULL) return _malloc_internal_nolock (size); +#ifdef CYGWIN + if (ptr < _heapbase) + /* ptr points into the static heap */ + return special_realloc (ptr, size); +#endif + block = BLOCK (ptr); PROTECT_MALLOC_STATE (0); diff --git a/src/unexcw.c b/src/unexcw.c index f643c196de0..62df82ec3bc 100644 --- a/src/unexcw.c +++ b/src/unexcw.c @@ -33,6 +33,8 @@ along with GNU Emacs. If not, see . */ extern int bss_sbrk_did_unexec; +extern int __malloc_initialized; + /* emacs symbols that indicate where bss and data end for emacs internals */ extern char my_endbss[]; extern char my_edata[]; @@ -210,9 +212,12 @@ fixup_executable (int fd) lseek (fd, (long) (exe_header->section_header[i].s_scnptr), SEEK_SET); assert (ret != -1); + /* force the dumped emacs to reinitialize malloc */ + __malloc_initialized = 0; ret = write (fd, (char *) start_address, my_endbss - (char *) start_address); + __malloc_initialized = 1; assert (ret == (my_endbss - (char *) start_address)); if (debug_unexcw) printf (" .bss, mem start 0x%08x mem length %d\n", -- 2.39.2