summaryrefslogtreecommitdiff
path: root/src/gmalloc.c
diff options
context:
space:
mode:
authorKen Brown <kbrown@cornell.edu>2011-08-16 09:27:12 -0400
committerKen Brown <kbrown@cornell.edu>2011-08-16 09:27:12 -0400
commita4579d332d432ea629a1ad2168ce8023d172d563 (patch)
tree518252a17be98424e3744bc35dcc96fedf41c84a /src/gmalloc.c
parent9adfcd0bf50066cc678ba65fb1b236d1c4ca0334 (diff)
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.
Diffstat (limited to 'src/gmalloc.c')
-rw-r--r--src/gmalloc.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/src/gmalloc.c b/src/gmalloc.c
index 916bb300fe..61046ad9d1 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -351,10 +351,17 @@ Fifth Floor, Boston, MA 02110-1301, USA.
#endif
#include <errno.h>
-/* 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);