Merge from trunk
[bpt/emacs.git] / src / gmalloc.c
index fcd9f65..8314798 100644 (file)
@@ -42,8 +42,7 @@ Fifth Floor, Boston, MA 02110-1301, USA.
 #endif
 
 #if ((defined __cplusplus || (defined (__STDC__) && __STDC__) \
-      || defined STDC_HEADERS || defined PROTOTYPES) \
-     && ! defined (BROKEN_PROTOTYPES))
+      || defined STDC_HEADERS || defined PROTOTYPES))
 #undef PP
 #define        PP(args)        args
 #undef __ptr_t
@@ -110,10 +109,6 @@ extern "C"
 #define        NULL    0
 #endif
 
-#ifndef FREE_RETURN_TYPE
-#define FREE_RETURN_TYPE void
-#endif
-
 
 /* Allocate SIZE bytes of memory.  */
 extern __ptr_t malloc PP ((__malloc_size_t __size));
@@ -123,12 +118,14 @@ extern __ptr_t realloc PP ((__ptr_t __ptr, __malloc_size_t __size));
 /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */
 extern __ptr_t calloc PP ((__malloc_size_t __nmemb, __malloc_size_t __size));
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
-extern FREE_RETURN_TYPE free PP ((__ptr_t __ptr));
+extern void free PP ((__ptr_t __ptr));
 
 /* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */
-#if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* Avoid conflict.  */
+#if !defined (_MALLOC_INTERNAL) || defined (MSDOS) /* Avoid conflict.  */
 extern __ptr_t memalign PP ((__malloc_size_t __alignment,
                             __malloc_size_t __size));
+extern int posix_memalign PP ((__ptr_t *, __malloc_size_t,
+                              __malloc_size_t size));
 #endif
 
 /* Allocate SIZE bytes on a page boundary.  */
@@ -136,6 +133,10 @@ extern __ptr_t memalign PP ((__malloc_size_t __alignment,
 extern __ptr_t valloc PP ((__malloc_size_t __size));
 #endif
 
+#ifdef USE_PTHREAD
+/* Set up mutexes and make malloc etc. thread-safe.  */
+extern void malloc_enable_thread PP ((void));
+#endif
 
 #ifdef _MALLOC_INTERNAL
 
@@ -242,10 +243,27 @@ extern void _free_internal_nolock PP ((__ptr_t __ptr));
 
 #ifdef USE_PTHREAD
 extern pthread_mutex_t _malloc_mutex, _aligned_blocks_mutex;
-#define LOCK()     pthread_mutex_lock (&_malloc_mutex)
-#define UNLOCK()   pthread_mutex_unlock (&_malloc_mutex)
-#define LOCK_ALIGNED_BLOCKS()     pthread_mutex_lock (&_aligned_blocks_mutex)
-#define UNLOCK_ALIGNED_BLOCKS()   pthread_mutex_unlock (&_aligned_blocks_mutex)
+extern int _malloc_thread_enabled_p;
+#define LOCK()                                 \
+  do {                                         \
+    if (_malloc_thread_enabled_p)              \
+      pthread_mutex_lock (&_malloc_mutex);     \
+  } while (0)
+#define UNLOCK()                               \
+  do {                                         \
+    if (_malloc_thread_enabled_p)              \
+      pthread_mutex_unlock (&_malloc_mutex);   \
+  } while (0)
+#define LOCK_ALIGNED_BLOCKS()                          \
+  do {                                                 \
+    if (_malloc_thread_enabled_p)                      \
+      pthread_mutex_lock (&_aligned_blocks_mutex);     \
+  } while (0)
+#define UNLOCK_ALIGNED_BLOCKS()                                \
+  do {                                                 \
+    if (_malloc_thread_enabled_p)                      \
+      pthread_mutex_unlock (&_aligned_blocks_mutex);   \
+  } while (0)
 #else
 #define LOCK()
 #define UNLOCK()
@@ -561,9 +579,49 @@ register_heapinfo ()
 }
 
 #ifdef USE_PTHREAD
-static pthread_once_t malloc_init_once_control = PTHREAD_ONCE_INIT;
 pthread_mutex_t _malloc_mutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER;
+int _malloc_thread_enabled_p;
+
+static void
+malloc_atfork_handler_prepare ()
+{
+  LOCK ();
+  LOCK_ALIGNED_BLOCKS ();
+}
+
+static void
+malloc_atfork_handler_parent ()
+{
+  UNLOCK_ALIGNED_BLOCKS ();
+  UNLOCK ();
+}
+
+static void
+malloc_atfork_handler_child ()
+{
+  UNLOCK_ALIGNED_BLOCKS ();
+  UNLOCK ();
+}
+
+/* Set up mutexes and make malloc etc. thread-safe.  */
+void
+malloc_enable_thread ()
+{
+  if (_malloc_thread_enabled_p)
+    return;
+
+  /* Some pthread implementations call malloc for statically
+     initialized mutexes when they are used first.  To avoid such a
+     situation, we initialize mutexes here while their use is
+     disabled in malloc etc.  */
+  pthread_mutex_init (&_malloc_mutex, NULL);
+  pthread_mutex_init (&_aligned_blocks_mutex, NULL);
+  pthread_atfork (malloc_atfork_handler_prepare,
+                 malloc_atfork_handler_parent,
+                 malloc_atfork_handler_child);
+  _malloc_thread_enabled_p = 1;
+}
 #endif
 
 static void
@@ -576,19 +634,6 @@ malloc_initialize_1 ()
   if (__malloc_initialize_hook)
     (*__malloc_initialize_hook) ();
 
-  /* We don't use recursive mutex because pthread_mutexattr_init may
-     call malloc internally.  */
-#if 0 /* defined (USE_PTHREAD) */
-  {
-    pthread_mutexattr_t attr;
-
-    pthread_mutexattr_init (&attr);
-    pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
-    pthread_mutex_init (&_malloc_mutex, &attr);
-    pthread_mutexattr_destroy (&attr);
-  }
-#endif
-
   heapsize = HEAP / BLOCKSIZE;
   _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
   if (_heapinfo == NULL)
@@ -607,18 +652,16 @@ malloc_initialize_1 ()
   return;
 }
 
-/* Set everything up and remember that we have.  */
+/* Set everything up and remember that we have.
+   main will call malloc which calls this function.  That is before any threads
+   or signal handlers has been set up, so we don't need thread protection.  */
 int
 __malloc_initialize ()
 {
-#ifdef USE_PTHREAD
-  pthread_once (&malloc_init_once_control, malloc_initialize_1);
-#else
   if (__malloc_initialized)
     return 0;
 
   malloc_initialize_1 ();
-#endif
 
   return __malloc_initialized;
 }
@@ -768,11 +811,6 @@ _malloc_internal_nolock (size)
   if (size < sizeof (struct list))
     size = sizeof (struct list);
 
-#ifdef SUNOS_LOCALTIME_BUG
-  if (size < 16)
-    size = 16;
-#endif
-
   /* Determine the allocation policy based on the request size.  */
   if (size <= BLOCKSIZE / 2)
     {
@@ -872,7 +910,7 @@ _malloc_internal_nolock (size)
                 final free block; if so we don't need to get as much.  */
              if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
                  /* We can't do this if we will have to make the heap info
-                     table bigger to accomodate the new space.  */
+                     table bigger to accommodate the new space.  */
                  block + wantblocks <= heapsize &&
                  get_contiguous_space ((wantblocks - lastblocks) * BLOCKSIZE,
                                        ADDRESS (block + lastblocks)))
@@ -1039,8 +1077,7 @@ Fifth Floor, Boston, MA 02110-1301, USA.
 
 /* Cope with systems lacking `memmove'.    */
 #ifndef memmove
-#if  (defined (MEMMOVE_MISSING) || \
-      !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
+#if  (!defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
 #ifdef emacs
 #undef __malloc_safe_bcopy
 #define __malloc_safe_bcopy safe_bcopy
@@ -1320,7 +1357,7 @@ _free_internal (ptr)
 
 /* Return memory to the heap.  */
 
-FREE_RETURN_TYPE
+void
 free (ptr)
      __ptr_t ptr;
 {
@@ -1373,8 +1410,7 @@ Fifth Floor, Boston, MA 02110-1301, USA.
 
 
 /* Cope with systems lacking `memmove'.    */
-#if  (defined (MEMMOVE_MISSING) || \
-      !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
+#if  (!defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
 
 #ifdef emacs
 #undef __malloc_safe_bcopy
@@ -1669,17 +1705,17 @@ MA 02110-1301, USA.  */
 #include <malloc.h>
 #endif
 
-#ifndef        __GNU_LIBRARY__
+/* uClibc defines __GNU_LIBRARY__, but it is not completely
+   compatible.  */
+#if !defined(__GNU_LIBRARY__) || defined(__UCLIBC__)
 #define        __sbrk  sbrk
-#endif
-
-#ifdef __GNU_LIBRARY__
+#else /* __GNU_LIBRARY__ && ! defined (__UCLIBC__) */
 /* It is best not to declare this and cast its result on foreign operating
    systems with potentially hostile include files.  */
 
 #include <stddef.h>
 extern __ptr_t __sbrk PP ((ptrdiff_t increment));
-#endif
+#endif /* __GNU_LIBRARY__ && ! defined (__UCLIBC__) */
 
 #ifndef NULL
 #define NULL 0
@@ -1726,13 +1762,6 @@ Fifth Floor, Boston, MA 02110-1301, USA.  */
 #include <malloc.h>
 #endif
 
-#if __DJGPP__ - 0 == 1
-
-/* There is some problem with memalign in DJGPP v1 and we are supposed
-   to omit it.  Noone told me why, they just told me to do it.  */
-
-#else
-
 __ptr_t (*__memalign_hook) PP ((__malloc_size_t __size,
                                __malloc_size_t __alignment));
 
@@ -1811,7 +1840,36 @@ memalign (alignment, size)
   return result;
 }
 
-#endif /* Not DJGPP v1 */
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+
+int
+posix_memalign (memptr, alignment, size)
+     __ptr_t *memptr;
+     __malloc_size_t alignment;
+     __malloc_size_t size;
+{
+  __ptr_t mem;
+
+  if (alignment == 0
+      || alignment % sizeof (__ptr_t) != 0
+      || (alignment & (alignment - 1)) != 0)
+    return EINVAL;
+
+  mem = memalign (alignment, size);
+  if (mem == NULL)
+    return ENOMEM;
+
+  *memptr = mem;
+
+  return 0;
+}
+
 /* Allocate memory on a page boundary.
    Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc.
 
@@ -1911,12 +1969,12 @@ Fifth Floor, Boston, MA 02110-1301, USA.
 #endif
 
 /* Old hook values.  */
-static void (*old_free_hook) __P ((__ptr_t ptr));
-static __ptr_t (*old_malloc_hook) __P ((__malloc_size_t size));
-static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size));
+static void (*old_free_hook) (__ptr_t ptr);
+static __ptr_t (*old_malloc_hook) (__malloc_size_t size);
+static __ptr_t (*old_realloc_hook) (__ptr_t ptr, __malloc_size_t size);
 
 /* Function to call when something awful happens.  */
-static void (*abortfunc) __P ((enum mcheck_status));
+static void (*abortfunc) (enum mcheck_status);
 
 /* Arbitrary magical numbers.  */
 #define MAGICWORD      0xfedabeeb
@@ -1934,7 +1992,7 @@ struct hdr
 #if    defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
 #define flood memset
 #else
-static void flood __P ((__ptr_t, int, __malloc_size_t));
+static void flood (__ptr_t, int, __malloc_size_t);
 static void
 flood (ptr, val, size)
      __ptr_t ptr;
@@ -1947,7 +2005,7 @@ flood (ptr, val, size)
 }
 #endif
 
-static enum mcheck_status checkhdr __P ((const struct hdr *));
+static enum mcheck_status checkhdr (const struct hdr *);
 static enum mcheck_status
 checkhdr (hdr)
      const struct hdr *hdr;
@@ -1973,7 +2031,7 @@ checkhdr (hdr)
   return status;
 }
 
-static void freehook __P ((__ptr_t));
+static void freehook (__ptr_t);
 static void
 freehook (ptr)
      __ptr_t ptr;
@@ -1995,7 +2053,7 @@ freehook (ptr)
   __free_hook = freehook;
 }
 
-static __ptr_t mallochook __P ((__malloc_size_t));
+static __ptr_t mallochook (__malloc_size_t);
 static __ptr_t
 mallochook (size)
      __malloc_size_t size;
@@ -2015,7 +2073,7 @@ mallochook (size)
   return (__ptr_t) (hdr + 1);
 }
 
-static __ptr_t reallochook __P ((__ptr_t, __malloc_size_t));
+static __ptr_t reallochook (__ptr_t, __malloc_size_t);
 static __ptr_t
 reallochook (ptr, size)
      __ptr_t ptr;
@@ -2088,7 +2146,7 @@ static int mcheck_used = 0;
 
 int
 mcheck (func)
-     void (*func) __P ((enum mcheck_status));
+     void (*func) (enum mcheck_status);
 {
   abortfunc = (func != NULL) ? func : &mabort;