aboutsummaryrefslogtreecommitdiffstats
path: root/src/gmalloc.c
diff options
context:
space:
mode:
authorKen Brown2014-08-28 10:48:02 -0400
committerKen Brown2014-08-28 10:48:02 -0400
commitea652500776aacbb8cb64f9ecca16a2d2c7add80 (patch)
treec759fc62dfa422e8fb636aef6dbb04df2c68cc7e /src/gmalloc.c
parenta7ef7a0e53ae1f391f4bda207bb5e9b9d833d354 (diff)
downloademacs-ea652500776aacbb8cb64f9ecca16a2d2c7add80.tar.gz
emacs-ea652500776aacbb8cb64f9ecca16a2d2c7add80.zip
Add support for HYBRID_MALLOC, allowing the use of gmalloc before
dumping and the system malloc after dumping. (Bug#18222) * configure.ac (HYBRID_MALLOC): New macro; define to use gmalloc before dumping and the system malloc after dumping. Define on Cygwin. * src/conf_post.h (malloc, realloc, calloc, free) [HYBRID_MALLOC]: Define as macros, expanding to hybrid_malloc, etc. (HYBRID_GET_CURRENT_DIR_NAME): New macro. (get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: Define as macro. * src/gmalloc.c: Set up the infrastructure for HYBRID_MALLOC, with a full implementation on Cygwin. Remove Cygwin-specific code that is no longer needed. (malloc, realloc, calloc, free, aligned_alloc) [HYBRID_MALLOC]: Redefine as macros expanding to gmalloc, grealloc, etc. (DUMPED, ALLOCATED_BEFORE_DUMPING) [CYGWIN]: New macros. (get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: Undefine. (USE_PTHREAD, posix_memalign) [HYBRID_MALLOC]: Don't define. (hybrid_malloc, hybrid_calloc, hybrid_free, hybrid_realloc) [HYBRID_MALLOC]: (hybrid_get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: (hybrid_aligned_alloc) [HYBRID_MALLOC && (HAVE_ALIGNED_ALLOC || HAVE_POSIX_MEMALIGN)]: New functions. * src/alloc.c (aligned_alloc) [HYBRID_MALLOC && (ALIGNED_ALLOC || HAVE_POSIX_MEMALIGN)]: Define as macro expanding to hybrid_aligned_alloc; declare. (USE_ALIGNED_ALLOC) [HYBRID_MALLOC && (ALIGNED_ALLOC || HAVE_POSIX_MEMALIGN)]: Define. (refill_memory_reserve) [HYBRID_MALLOC]: Do nothing. * src/sysdep.c (get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: Define as macro, expanding to gget_current_dir_name, and define the latter. * src/emacs.c (main) [HYBRID_MALLOC]: Don't call memory_warnings() or malloc_enable_thread(). Don't initialize malloc. * src/lisp.h (NONPOINTER_BITS) [CYGWIN]: Define (because GNU_MALLOC is no longer defined on Cygwin). (refill_memory_reserve) [HYBRID_MALLOC]: Don't declare. * src/sheap.c (bss_sbrk_buffer_end): New variable. * src/unexcw.c (__malloc_initialized): Remove variable. * src/ralloc.c: Throughout, treat HYBRID_MALLOC the same as SYSTEM_MALLOC. * src/xdisp.c (decode_mode_spec) [HYBRID_MALLOC]: Don't check Vmemory_full.
Diffstat (limited to 'src/gmalloc.c')
-rw-r--r--src/gmalloc.c231
1 files changed, 149 insertions, 82 deletions
diff --git a/src/gmalloc.c b/src/gmalloc.c
index 27965e37539..f4a32c79ca1 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -19,15 +19,27 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 The author may be reached (Email) at the address mike@ai.mit.edu, 19 The author may be reached (Email) at the address mike@ai.mit.edu,
20 or (US mail) as Mike Haertel c/o Free Software Foundation. */ 20 or (US mail) as Mike Haertel c/o Free Software Foundation. */
21 21
22/* If HYBRID_MALLOC is defined in config.h, then conf_post.h #defines
23 malloc and friends as macros before including stdlib.h. In this
24 file we will need the prototypes for the system malloc, so we must
25 include stdlib.h before config.h. And we have to do this
26 unconditionally, since HYBRID_MALLOC hasn't been defined yet. */
27#include <stdlib.h>
28
22#include <config.h> 29#include <config.h>
23 30
24#ifdef HAVE_PTHREAD 31#if defined HAVE_PTHREAD && !defined HYBRID_MALLOC
25#define USE_PTHREAD 32#define USE_PTHREAD
26#endif 33#endif
27 34
28#include <string.h> 35#include <string.h>
29#include <limits.h> 36#include <limits.h>
30#include <stdint.h> 37#include <stdint.h>
38
39#ifdef HYBRID_GET_CURRENT_DIR_NAME
40#undef get_current_dir_name
41#endif
42
31#include <unistd.h> 43#include <unistd.h>
32 44
33#ifdef USE_PTHREAD 45#ifdef USE_PTHREAD
@@ -42,6 +54,41 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
42extern void emacs_abort (void); 54extern void emacs_abort (void);
43#endif 55#endif
44 56
57/* If HYBRID_MALLOC is defined, then temacs will use malloc,
58 realloc... as defined in this file (and renamed gmalloc,
59 grealloc... via the macros that follow). The dumped emacs,
60 however, will use the system malloc, realloc.... In other source
61 files, malloc, realloc... are renamed hybrid_malloc,
62 hybrid_realloc... via macros in conf_post.h. hybrid_malloc and
63 friends are wrapper functions defined later in this file.
64 aligned_alloc is defined as a macro only in alloc.c.
65
66 As of this writing (August 2014), Cygwin is the only platform on
67 which HYBRID_MACRO is defined. Any other platform that wants to
68 define it will have to define the macros DUMPED and
69 ALLOCATED_BEFORE_DUMPING, defined below for Cygwin. */
70#ifdef HYBRID_MALLOC
71#undef malloc
72#undef realloc
73#undef calloc
74#undef free
75#define malloc gmalloc
76#define realloc grealloc
77#define calloc gcalloc
78#define aligned_alloc galigned_alloc
79#define free gfree
80#endif /* HYBRID_MALLOC */
81
82#ifdef CYGWIN
83extern void *bss_sbrk (ptrdiff_t size);
84extern int bss_sbrk_did_unexec;
85extern char *bss_sbrk_buffer;
86extern char *bss_sbrk_buffer_end;
87#define DUMPED bss_sbrk_did_unexec
88#define ALLOCATED_BEFORE_DUMPING(P) \
89 ((char *) (P) < bss_sbrk_buffer_end && (char *) (P) >= bss_sbrk_buffer)
90#endif
91
45#ifdef __cplusplus 92#ifdef __cplusplus
46extern "C" 93extern "C"
47{ 94{
@@ -306,22 +353,6 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
306 353
307#include <errno.h> 354#include <errno.h>
308 355
309/* On Cygwin there are two heaps. temacs uses the static heap
310 (defined in sheap.c and managed with bss_sbrk), and the dumped
311 emacs uses the Cygwin heap (managed with sbrk). When emacs starts
312 on Cygwin, it reinitializes malloc, and we save the old info for
313 use by free and realloc if they're called with a pointer into the
314 static heap.
315
316 Currently (2011-08-16) the Cygwin build doesn't use ralloc.c; if
317 this is changed in the future, we'll have to similarly deal with
318 reinitializing ralloc. */
319#ifdef CYGWIN
320extern void *bss_sbrk (ptrdiff_t size);
321extern int bss_sbrk_did_unexec;
322char *bss_sbrk_heapbase; /* _heapbase for static heap */
323malloc_info *bss_sbrk_heapinfo; /* _heapinfo for static heap */
324#endif
325void *(*__morecore) (ptrdiff_t size) = __default_morecore; 356void *(*__morecore) (ptrdiff_t size) = __default_morecore;
326 357
327/* Debugging hook for `malloc'. */ 358/* Debugging hook for `malloc'. */
@@ -490,18 +521,8 @@ register_heapinfo (void)
490} 521}
491 522
492#ifdef USE_PTHREAD 523#ifdef USE_PTHREAD
493/* On Cygwin prior to 1.7.31, pthread_mutexes were ERRORCHECK mutexes
494 by default. When the default changed to NORMAL in Cygwin-1.7.31,
495 deadlocks occurred (bug#18222). As a temporary workaround, we
496 explicitly set the mutexes to be of ERRORCHECK type, restoring the
497 previous behavior. */
498#ifdef CYGWIN
499pthread_mutex_t _malloc_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
500pthread_mutex_t _aligned_blocks_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
501#else /* not CYGWIN */
502pthread_mutex_t _malloc_mutex = PTHREAD_MUTEX_INITIALIZER; 524pthread_mutex_t _malloc_mutex = PTHREAD_MUTEX_INITIALIZER;
503pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER; 525pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER;
504#endif /* not CYGWIN */
505int _malloc_thread_enabled_p; 526int _malloc_thread_enabled_p;
506 527
507static void 528static void
@@ -536,17 +557,8 @@ malloc_enable_thread (void)
536 initialized mutexes when they are used first. To avoid such a 557 initialized mutexes when they are used first. To avoid such a
537 situation, we initialize mutexes here while their use is 558 situation, we initialize mutexes here while their use is
538 disabled in malloc etc. */ 559 disabled in malloc etc. */
539#ifdef CYGWIN
540 /* Use ERRORCHECK mutexes; see comment above. */
541 pthread_mutexattr_t attr;
542 pthread_mutexattr_init (&attr);
543 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK);
544 pthread_mutex_init (&_malloc_mutex, &attr);
545 pthread_mutex_init (&_aligned_blocks_mutex, &attr);
546#else /* not CYGWIN */
547 pthread_mutex_init (&_malloc_mutex, NULL); 560 pthread_mutex_init (&_malloc_mutex, NULL);
548 pthread_mutex_init (&_aligned_blocks_mutex, NULL); 561 pthread_mutex_init (&_aligned_blocks_mutex, NULL);
549#endif /* not CYGWIN */
550 pthread_atfork (malloc_atfork_handler_prepare, 562 pthread_atfork (malloc_atfork_handler_prepare,
551 malloc_atfork_handler_parent, 563 malloc_atfork_handler_parent,
552 malloc_atfork_handler_child); 564 malloc_atfork_handler_child);
@@ -561,16 +573,6 @@ malloc_initialize_1 (void)
561 mcheck (NULL); 573 mcheck (NULL);
562#endif 574#endif
563 575
564#ifdef CYGWIN
565 if (bss_sbrk_did_unexec)
566 /* we're reinitializing the dumped emacs */
567 {
568 bss_sbrk_heapbase = _heapbase;
569 bss_sbrk_heapinfo = _heapinfo;
570 memset (_fraghead, 0, BLOCKLOG * sizeof (struct list));
571 }
572#endif
573
574 if (__malloc_initialize_hook) 576 if (__malloc_initialize_hook)
575 (*__malloc_initialize_hook) (); 577 (*__malloc_initialize_hook) ();
576 578
@@ -1027,12 +1029,6 @@ _free_internal_nolock (void *ptr)
1027 if (ptr == NULL) 1029 if (ptr == NULL)
1028 return; 1030 return;
1029 1031
1030#ifdef CYGWIN
1031 if ((char *) ptr < _heapbase)
1032 /* We're being asked to free something in the static heap. */
1033 return;
1034#endif
1035
1036 PROTECT_MALLOC_STATE (0); 1032 PROTECT_MALLOC_STATE (0);
1037 1033
1038 LOCK_ALIGNED_BLOCKS (); 1034 LOCK_ALIGNED_BLOCKS ();
@@ -1317,29 +1313,6 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
1317#define min(A, B) ((A) < (B) ? (A) : (B)) 1313#define min(A, B) ((A) < (B) ? (A) : (B))
1318#endif 1314#endif
1319 1315
1320/* On Cygwin the dumped emacs may try to realloc storage allocated in
1321 the static heap. We just malloc space in the new heap and copy the
1322 data. */
1323#ifdef CYGWIN
1324void *
1325special_realloc (void *ptr, size_t size)
1326{
1327 void *result;
1328 int type;
1329 size_t block, oldsize;
1330
1331 block = ((char *) ptr - bss_sbrk_heapbase) / BLOCKSIZE + 1;
1332 type = bss_sbrk_heapinfo[block].busy.type;
1333 oldsize =
1334 type == 0 ? bss_sbrk_heapinfo[block].busy.info.size * BLOCKSIZE
1335 : (size_t) 1 << type;
1336 result = _malloc_internal_nolock (size);
1337 if (result)
1338 return memcpy (result, ptr, min (oldsize, size));
1339 return result;
1340}
1341#endif
1342
1343/* Debugging hook for realloc. */ 1316/* Debugging hook for realloc. */
1344void *(*__realloc_hook) (void *ptr, size_t size); 1317void *(*__realloc_hook) (void *ptr, size_t size);
1345 1318
@@ -1364,12 +1337,6 @@ _realloc_internal_nolock (void *ptr, size_t size)
1364 else if (ptr == NULL) 1337 else if (ptr == NULL)
1365 return _malloc_internal_nolock (size); 1338 return _malloc_internal_nolock (size);
1366 1339
1367#ifdef CYGWIN
1368 if ((char *) ptr < _heapbase)
1369 /* ptr points into the static heap */
1370 return special_realloc (ptr, size);
1371#endif
1372
1373 block = BLOCK (ptr); 1340 block = BLOCK (ptr);
1374 1341
1375 PROTECT_MALLOC_STATE (0); 1342 PROTECT_MALLOC_STATE (0);
@@ -1566,7 +1533,7 @@ __default_morecore (ptrdiff_t increment)
1566{ 1533{
1567 void *result; 1534 void *result;
1568#if defined (CYGWIN) 1535#if defined (CYGWIN)
1569 if (!bss_sbrk_did_unexec) 1536 if (!DUMPED)
1570 { 1537 {
1571 return bss_sbrk (increment); 1538 return bss_sbrk (increment);
1572 } 1539 }
@@ -1689,6 +1656,9 @@ memalign (size_t alignment, size_t size)
1689 return aligned_alloc (alignment, size); 1656 return aligned_alloc (alignment, size);
1690} 1657}
1691 1658
1659/* If HYBRID_MALLOC is defined, we may want to use the system
1660 posix_memalign below. */
1661#ifndef HYBRID_MALLOC
1692int 1662int
1693posix_memalign (void **memptr, size_t alignment, size_t size) 1663posix_memalign (void **memptr, size_t alignment, size_t size)
1694{ 1664{
@@ -1707,6 +1677,7 @@ posix_memalign (void **memptr, size_t alignment, size_t size)
1707 1677
1708 return 0; 1678 return 0;
1709} 1679}
1680#endif
1710 1681
1711/* Allocate memory on a page boundary. 1682/* Allocate memory on a page boundary.
1712 Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc. 1683 Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc.
@@ -1747,6 +1718,102 @@ valloc (size_t size)
1747 return aligned_alloc (pagesize, size); 1718 return aligned_alloc (pagesize, size);
1748} 1719}
1749 1720
1721#ifdef HYBRID_MALLOC
1722#undef malloc
1723#undef realloc
1724#undef calloc
1725#undef aligned_alloc
1726#undef free
1727
1728/* See the comments near the beginning of this file for explanations
1729 of the following functions. */
1730
1731void *
1732hybrid_malloc (size_t size)
1733{
1734 if (DUMPED)
1735 return malloc (size);
1736 return gmalloc (size);
1737}
1738
1739void *
1740hybrid_calloc (size_t nmemb, size_t size)
1741{
1742 if (DUMPED)
1743 return calloc (nmemb, size);
1744 return gcalloc (nmemb, size);
1745}
1746
1747void
1748hybrid_free (void *ptr)
1749{
1750 if (!DUMPED)
1751 gfree (ptr);
1752 else if (!ALLOCATED_BEFORE_DUMPING (ptr))
1753 free (ptr);
1754 /* Otherwise the dumped emacs is trying to free something allocated
1755 before dumping; do nothing. */
1756 return;
1757}
1758
1759#if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN
1760void *
1761hybrid_aligned_alloc (size_t alignment, size_t size)
1762{
1763 if (!DUMPED)
1764 return galigned_alloc (alignment, size);
1765 /* The following is copied from alloc.c */
1766#ifdef HAVE_ALIGNED_ALLOC
1767 return aligned_alloc (alignment, size);
1768#else /* HAVE_POSIX_MEMALIGN */
1769 void *p;
1770 return posix_memalign (&p, alignment, size) == 0 ? p : 0;
1771#endif
1772}
1773#endif
1774
1775void *
1776hybrid_realloc (void *ptr, size_t size)
1777{
1778 void *result;
1779 int type;
1780 size_t block, oldsize;
1781
1782 if (!DUMPED)
1783 return grealloc (ptr, size);
1784 if (!ALLOCATED_BEFORE_DUMPING (ptr))
1785 return realloc (ptr, size);
1786
1787 /* The dumped emacs is trying to realloc storage allocated before
1788 dumping. We just malloc new space and copy the data. */
1789 if (size == 0 || ptr == NULL)
1790 return malloc (size);
1791 block = ((char *) ptr - _heapbase) / BLOCKSIZE + 1;
1792 type = _heapinfo[block].busy.type;
1793 oldsize =
1794 type == 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE
1795 : (size_t) 1 << type;
1796 result = malloc (size);
1797 if (result)
1798 return memcpy (result, ptr, min (oldsize, size));
1799 return result;
1800}
1801
1802#ifdef HYBRID_GET_CURRENT_DIR_NAME
1803/* Defined in sysdep.c. */
1804char *gget_current_dir_name (void);
1805
1806char *
1807hybrid_get_current_dir_name (void)
1808{
1809 if (DUMPED)
1810 return get_current_dir_name ();
1811 return gget_current_dir_name ();
1812}
1813#endif
1814
1815#endif /* HYBRID_MALLOC */
1816
1750#ifdef GC_MCHECK 1817#ifdef GC_MCHECK
1751 1818
1752/* Standard debugging hooks for `malloc'. 1819/* Standard debugging hooks for `malloc'.