aboutsummaryrefslogtreecommitdiffstats
path: root/src/gmalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gmalloc.c')
-rw-r--r--src/gmalloc.c237
1 files changed, 154 insertions, 83 deletions
diff --git a/src/gmalloc.c b/src/gmalloc.c
index 27965e37539..3456ff0ec6f 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -21,13 +21,18 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
21 21
22#include <config.h> 22#include <config.h>
23 23
24#ifdef HAVE_PTHREAD 24#if defined HAVE_PTHREAD && !defined HYBRID_MALLOC
25#define USE_PTHREAD 25#define USE_PTHREAD
26#endif 26#endif
27 27
28#include <string.h> 28#include <string.h>
29#include <limits.h> 29#include <limits.h>
30#include <stdint.h> 30#include <stdint.h>
31
32#ifdef HYBRID_GET_CURRENT_DIR_NAME
33#undef get_current_dir_name
34#endif
35
31#include <unistd.h> 36#include <unistd.h>
32 37
33#ifdef USE_PTHREAD 38#ifdef USE_PTHREAD
@@ -42,6 +47,41 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
42extern void emacs_abort (void); 47extern void emacs_abort (void);
43#endif 48#endif
44 49
50/* If HYBRID_MALLOC is defined, then temacs will use malloc,
51 realloc... as defined in this file (and renamed gmalloc,
52 grealloc... via the macros that follow). The dumped emacs,
53 however, will use the system malloc, realloc.... In other source
54 files, malloc, realloc... are renamed hybrid_malloc,
55 hybrid_realloc... via macros in conf_post.h. hybrid_malloc and
56 friends are wrapper functions defined later in this file.
57 aligned_alloc is defined as a macro only in alloc.c.
58
59 As of this writing (August 2014), Cygwin is the only platform on
60 which HYBRID_MACRO is defined. Any other platform that wants to
61 define it will have to define the macros DUMPED and
62 ALLOCATED_BEFORE_DUMPING, defined below for Cygwin. */
63#ifdef HYBRID_MALLOC
64#undef malloc
65#undef realloc
66#undef calloc
67#undef free
68#define malloc gmalloc
69#define realloc grealloc
70#define calloc gcalloc
71#define aligned_alloc galigned_alloc
72#define free gfree
73#endif /* HYBRID_MALLOC */
74
75#ifdef CYGWIN
76extern void *bss_sbrk (ptrdiff_t size);
77extern int bss_sbrk_did_unexec;
78extern char bss_sbrk_buffer[];
79extern void *bss_sbrk_buffer_end;
80#define DUMPED bss_sbrk_did_unexec
81#define ALLOCATED_BEFORE_DUMPING(P) \
82 ((P) < bss_sbrk_buffer_end && (P) >= (void *) bss_sbrk_buffer)
83#endif
84
45#ifdef __cplusplus 85#ifdef __cplusplus
46extern "C" 86extern "C"
47{ 87{
@@ -306,22 +346,6 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
306 346
307#include <errno.h> 347#include <errno.h>
308 348
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; 349void *(*__morecore) (ptrdiff_t size) = __default_morecore;
326 350
327/* Debugging hook for `malloc'. */ 351/* Debugging hook for `malloc'. */
@@ -490,18 +514,8 @@ register_heapinfo (void)
490} 514}
491 515
492#ifdef USE_PTHREAD 516#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; 517pthread_mutex_t _malloc_mutex = PTHREAD_MUTEX_INITIALIZER;
503pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER; 518pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER;
504#endif /* not CYGWIN */
505int _malloc_thread_enabled_p; 519int _malloc_thread_enabled_p;
506 520
507static void 521static void
@@ -536,17 +550,8 @@ malloc_enable_thread (void)
536 initialized mutexes when they are used first. To avoid such a 550 initialized mutexes when they are used first. To avoid such a
537 situation, we initialize mutexes here while their use is 551 situation, we initialize mutexes here while their use is
538 disabled in malloc etc. */ 552 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); 553 pthread_mutex_init (&_malloc_mutex, NULL);
548 pthread_mutex_init (&_aligned_blocks_mutex, NULL); 554 pthread_mutex_init (&_aligned_blocks_mutex, NULL);
549#endif /* not CYGWIN */
550 pthread_atfork (malloc_atfork_handler_prepare, 555 pthread_atfork (malloc_atfork_handler_prepare,
551 malloc_atfork_handler_parent, 556 malloc_atfork_handler_parent,
552 malloc_atfork_handler_child); 557 malloc_atfork_handler_child);
@@ -561,16 +566,6 @@ malloc_initialize_1 (void)
561 mcheck (NULL); 566 mcheck (NULL);
562#endif 567#endif
563 568
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) 569 if (__malloc_initialize_hook)
575 (*__malloc_initialize_hook) (); 570 (*__malloc_initialize_hook) ();
576 571
@@ -1027,12 +1022,6 @@ _free_internal_nolock (void *ptr)
1027 if (ptr == NULL) 1022 if (ptr == NULL)
1028 return; 1023 return;
1029 1024
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); 1025 PROTECT_MALLOC_STATE (0);
1037 1026
1038 LOCK_ALIGNED_BLOCKS (); 1027 LOCK_ALIGNED_BLOCKS ();
@@ -1314,30 +1303,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
1314 or (US mail) as Mike Haertel c/o Free Software Foundation. */ 1303 or (US mail) as Mike Haertel c/o Free Software Foundation. */
1315 1304
1316#ifndef min 1305#ifndef min
1317#define min(A, B) ((A) < (B) ? (A) : (B)) 1306#define min(a, b) ((a) < (b) ? (a) : (b))
1318#endif
1319
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 1307#endif
1342 1308
1343/* Debugging hook for realloc. */ 1309/* Debugging hook for realloc. */
@@ -1364,12 +1330,6 @@ _realloc_internal_nolock (void *ptr, size_t size)
1364 else if (ptr == NULL) 1330 else if (ptr == NULL)
1365 return _malloc_internal_nolock (size); 1331 return _malloc_internal_nolock (size);
1366 1332
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); 1333 block = BLOCK (ptr);
1374 1334
1375 PROTECT_MALLOC_STATE (0); 1335 PROTECT_MALLOC_STATE (0);
@@ -1566,7 +1526,7 @@ __default_morecore (ptrdiff_t increment)
1566{ 1526{
1567 void *result; 1527 void *result;
1568#if defined (CYGWIN) 1528#if defined (CYGWIN)
1569 if (!bss_sbrk_did_unexec) 1529 if (!DUMPED)
1570 { 1530 {
1571 return bss_sbrk (increment); 1531 return bss_sbrk (increment);
1572 } 1532 }
@@ -1689,6 +1649,9 @@ memalign (size_t alignment, size_t size)
1689 return aligned_alloc (alignment, size); 1649 return aligned_alloc (alignment, size);
1690} 1650}
1691 1651
1652/* If HYBRID_MALLOC is defined, we may want to use the system
1653 posix_memalign below. */
1654#ifndef HYBRID_MALLOC
1692int 1655int
1693posix_memalign (void **memptr, size_t alignment, size_t size) 1656posix_memalign (void **memptr, size_t alignment, size_t size)
1694{ 1657{
@@ -1707,6 +1670,7 @@ posix_memalign (void **memptr, size_t alignment, size_t size)
1707 1670
1708 return 0; 1671 return 0;
1709} 1672}
1673#endif
1710 1674
1711/* Allocate memory on a page boundary. 1675/* Allocate memory on a page boundary.
1712 Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc. 1676 Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc.
@@ -1747,6 +1711,113 @@ valloc (size_t size)
1747 return aligned_alloc (pagesize, size); 1711 return aligned_alloc (pagesize, size);
1748} 1712}
1749 1713
1714#ifdef HYBRID_MALLOC
1715#undef malloc
1716#undef realloc
1717#undef calloc
1718#undef aligned_alloc
1719#undef free
1720
1721/* Declare system malloc and friends. */
1722extern void *malloc (size_t size);
1723extern void *realloc (void *ptr, size_t size);
1724extern void *calloc (size_t nmemb, size_t size);
1725extern void free (void *ptr);
1726#ifdef HAVE_ALIGNED_ALLOC
1727extern void *aligned_alloc (size_t alignment, size_t size);
1728#elif defined HAVE_POSIX_MEMALIGN
1729extern int posix_memalign (void **memptr, size_t alignment, size_t size);
1730#endif
1731
1732/* See the comments near the beginning of this file for explanations
1733 of the following functions. */
1734
1735void *
1736hybrid_malloc (size_t size)
1737{
1738 if (DUMPED)
1739 return malloc (size);
1740 return gmalloc (size);
1741}
1742
1743void *
1744hybrid_calloc (size_t nmemb, size_t size)
1745{
1746 if (DUMPED)
1747 return calloc (nmemb, size);
1748 return gcalloc (nmemb, size);
1749}
1750
1751void
1752hybrid_free (void *ptr)
1753{
1754 if (!DUMPED)
1755 gfree (ptr);
1756 else if (!ALLOCATED_BEFORE_DUMPING (ptr))
1757 free (ptr);
1758 /* Otherwise the dumped emacs is trying to free something allocated
1759 before dumping; do nothing. */
1760 return;
1761}
1762
1763#if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN
1764void *
1765hybrid_aligned_alloc (size_t alignment, size_t size)
1766{
1767 if (!DUMPED)
1768 return galigned_alloc (alignment, size);
1769 /* The following is copied from alloc.c */
1770#ifdef HAVE_ALIGNED_ALLOC
1771 return aligned_alloc (alignment, size);
1772#else /* HAVE_POSIX_MEMALIGN */
1773 void *p;
1774 return posix_memalign (&p, alignment, size) == 0 ? p : 0;
1775#endif
1776}
1777#endif
1778
1779void *
1780hybrid_realloc (void *ptr, size_t size)
1781{
1782 void *result;
1783 int type;
1784 size_t block, oldsize;
1785
1786 if (!DUMPED)
1787 return grealloc (ptr, size);
1788 if (!ALLOCATED_BEFORE_DUMPING (ptr))
1789 return realloc (ptr, size);
1790
1791 /* The dumped emacs is trying to realloc storage allocated before
1792 dumping. We just malloc new space and copy the data. */
1793 if (size == 0 || ptr == NULL)
1794 return malloc (size);
1795 block = ((char *) ptr - _heapbase) / BLOCKSIZE + 1;
1796 type = _heapinfo[block].busy.type;
1797 oldsize =
1798 type == 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE
1799 : (size_t) 1 << type;
1800 result = malloc (size);
1801 if (result)
1802 return memcpy (result, ptr, min (oldsize, size));
1803 return result;
1804}
1805
1806#ifdef HYBRID_GET_CURRENT_DIR_NAME
1807/* Defined in sysdep.c. */
1808char *gget_current_dir_name (void);
1809
1810char *
1811hybrid_get_current_dir_name (void)
1812{
1813 if (DUMPED)
1814 return get_current_dir_name ();
1815 return gget_current_dir_name ();
1816}
1817#endif
1818
1819#endif /* HYBRID_MALLOC */
1820
1750#ifdef GC_MCHECK 1821#ifdef GC_MCHECK
1751 1822
1752/* Standard debugging hooks for `malloc'. 1823/* Standard debugging hooks for `malloc'.