$TERM is now set to dumb.
[bpt/emacs.git] / src / gmalloc.c
index 4f13239..ccc08e1 100644 (file)
@@ -5,23 +5,24 @@
 /* The malloc headers and source files from the C library follow here.  */
 
 /* Declarations for `malloc' and friends.
-   Copyright 1990, 91, 92, 93, 95, 96 Free Software Foundation, Inc.
+   Copyright (C) 1990, 1991, 1992, 1993, 1995, 1996, 1999, 2002, 2003, 2004,
+                 2005, 2006, 2007 Free Software Foundation, Inc.
                  Written May 1989 by Mike Haertel.
 
 This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
+modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of the
 License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public
+License along with this library; see the file COPYING.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+Fifth Floor, Boston, MA 02110-1301, USA.
 
    The author may be reached (Email) at the address mike@ai.mit.edu,
    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
@@ -36,7 +37,13 @@ Cambridge, MA 02139, USA.
 #include <config.h>
 #endif
 
-#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+#ifdef HAVE_GTK_AND_PTHREAD
+#define USE_PTHREAD
+#endif
+
+#if ((defined __cplusplus || (defined (__STDC__) && __STDC__) \
+      || defined STDC_HEADERS || defined PROTOTYPES) \
+     && ! defined (BROKEN_PROTOTYPES))
 #undef PP
 #define        PP(args)        args
 #undef __ptr_t
@@ -44,8 +51,6 @@ Cambridge, MA 02139, USA.
 #else /* Not C++ or ANSI C.  */
 #undef PP
 #define        PP(args)        ()
-#undef const
-#define        const
 #undef __ptr_t
 #define        __ptr_t         char *
 #endif /* C++ or ANSI C.  */
@@ -61,18 +66,21 @@ Cambridge, MA 02139, USA.
 #endif
 #endif
 
-#if    defined (__GNU_LIBRARY__) || (defined (__STDC__) && __STDC__)
+#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#else
+#endif
 #ifndef CHAR_BIT
 #define        CHAR_BIT        8
 #endif
-#endif
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
+#ifdef USE_PTHREAD
+#include <pthread.h>
+#endif
+
 #endif /* _MALLOC_INTERNAL.  */
 
 
@@ -81,12 +89,20 @@ extern "C"
 {
 #endif
 
-#if defined (__STDC__) && __STDC__
+#ifdef STDC_HEADERS
 #include <stddef.h>
 #define        __malloc_size_t         size_t
 #define        __malloc_ptrdiff_t      ptrdiff_t
 #else
+#ifdef __GNUC__
+#include <stddef.h>
+#ifdef __SIZE_TYPE__
+#define        __malloc_size_t         __SIZE_TYPE__
+#endif
+#endif
+#ifndef __malloc_size_t
 #define        __malloc_size_t         unsigned int
+#endif
 #define        __malloc_ptrdiff_t      int
 #endif
 
@@ -94,6 +110,10 @@ 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));
@@ -103,12 +123,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 void free PP ((__ptr_t __ptr));
+extern FREE_RETURN_TYPE free PP ((__ptr_t __ptr));
 
 /* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */
 #if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* 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.  */
@@ -116,6 +138,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
 
@@ -216,6 +242,39 @@ extern __malloc_size_t _bytes_free;
 extern __ptr_t _malloc_internal PP ((__malloc_size_t __size));
 extern __ptr_t _realloc_internal PP ((__ptr_t __ptr, __malloc_size_t __size));
 extern void _free_internal PP ((__ptr_t __ptr));
+extern __ptr_t _malloc_internal_nolock PP ((__malloc_size_t __size));
+extern __ptr_t _realloc_internal_nolock PP ((__ptr_t __ptr, __malloc_size_t __size));
+extern void _free_internal_nolock PP ((__ptr_t __ptr));
+
+#ifdef USE_PTHREAD
+extern pthread_mutex_t _malloc_mutex, _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()
+#define LOCK_ALIGNED_BLOCKS()
+#define UNLOCK_ALIGNED_BLOCKS()
+#endif
 
 #endif /* _MALLOC_INTERNAL.  */
 
@@ -317,19 +376,19 @@ extern __ptr_t r_re_alloc PP ((__ptr_t *__handleptr, __malloc_size_t __size));
                  Written May 1989 by Mike Haertel.
 
 This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
+modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of the
 License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public
+License along with this library; see the file COPYING.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+Fifth Floor, Boston, MA 02110-1301, USA.
 
    The author may be reached (Email) at the address mike@ai.mit.edu,
    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
@@ -341,7 +400,11 @@ Cambridge, MA 02139, USA.
 #include <errno.h>
 
 /* How to really get more memory.  */
-__ptr_t (*__morecore) PP ((ptrdiff_t __size)) = __default_morecore;
+#if defined(CYGWIN)
+extern __ptr_t bss_sbrk PP ((ptrdiff_t __size));
+extern int bss_sbrk_did_unexec;
+#endif
+__ptr_t (*__morecore) PP ((__malloc_ptrdiff_t __size)) = __default_morecore;
 
 /* Debugging hook for `malloc'.  */
 __ptr_t (*__malloc_hook) PP ((__malloc_size_t __size));
@@ -378,6 +441,53 @@ __malloc_size_t __malloc_extra_blocks;
 void (*__malloc_initialize_hook) PP ((void));
 void (*__after_morecore_hook) PP ((void));
 
+#if defined GC_MALLOC_CHECK && defined GC_PROTECT_MALLOC_STATE
+
+/* Some code for hunting a bug writing into _heapinfo.
+
+   Call this macro with argument PROT non-zero to protect internal
+   malloc state against writing to it, call it with a zero argument to
+   make it readable and writable.
+
+   Note that this only works if BLOCKSIZE == page size, which is
+   the case on the i386.  */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+static int state_protected_p;
+static __malloc_size_t last_state_size;
+static malloc_info *last_heapinfo;
+
+void
+protect_malloc_state (protect_p)
+     int protect_p;
+{
+  /* If _heapinfo has been relocated, make sure its old location
+     isn't left read-only; it will be reused by malloc.  */
+  if (_heapinfo != last_heapinfo
+      && last_heapinfo
+      && state_protected_p)
+    mprotect (last_heapinfo, last_state_size, PROT_READ | PROT_WRITE);
+
+  last_state_size = _heaplimit * sizeof *_heapinfo;
+  last_heapinfo   = _heapinfo;
+
+  if (protect_p != state_protected_p)
+    {
+      state_protected_p = protect_p;
+      if (mprotect (_heapinfo, last_state_size,
+                   protect_p ? PROT_READ : PROT_READ | PROT_WRITE) != 0)
+       abort ();
+    }
+}
+
+#define PROTECT_MALLOC_STATE(PROT) protect_malloc_state(PROT)
+
+#else
+#define PROTECT_MALLOC_STATE(PROT)     /* empty */
+#endif
+
 
 /* Aligned allocation.  */
 static __ptr_t align PP ((__malloc_size_t));
@@ -388,7 +498,14 @@ align (size)
   __ptr_t result;
   unsigned long int adj;
 
-  result = (*__morecore) (size);
+  /* align accepts an unsigned argument, but __morecore accepts a
+     signed one.  This could lead to trouble if SIZE overflows a
+     signed int type accepted by __morecore.  We just punt in that
+     case, since they are requesting a ludicrous amount anyway.  */
+  if ((__malloc_ptrdiff_t)size < 0)
+    result = 0;
+  else
+    result = (*__morecore) (size);
   adj = (unsigned long int) ((unsigned long int) ((char *) result -
                                                  (char *) NULL)) % BLOCKSIZE;
   if (adj != 0)
@@ -466,12 +583,58 @@ register_heapinfo ()
     _heapinfo[block + blocks].busy.info.size = -blocks;
 }
 
-/* Set everything up and remember that we have.  */
-int
-__malloc_initialize ()
+#ifdef USE_PTHREAD
+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 ()
 {
-  if (__malloc_initialized)
-    return 0;
+  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
+malloc_initialize_1 ()
+{
+#ifdef GC_MCHECK
+  mcheck (NULL);
+#endif
 
   if (__malloc_initialize_hook)
     (*__malloc_initialize_hook) ();
@@ -479,7 +642,7 @@ __malloc_initialize ()
   heapsize = HEAP / BLOCKSIZE;
   _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
   if (_heapinfo == NULL)
-    return 0;
+    return;
   memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
   _heapinfo[0].free.size = 0;
   _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
@@ -490,16 +653,31 @@ __malloc_initialize ()
   register_heapinfo ();
 
   __malloc_initialized = 1;
-  return 1;
+  PROTECT_MALLOC_STATE (1);
+  return;
+}
+
+/* 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 ()
+{
+  if (__malloc_initialized)
+    return 0;
+
+  malloc_initialize_1 ();
+
+  return __malloc_initialized;
 }
 
 static int morecore_recursing;
 
 /* Get neatly aligned memory, initializing or
    growing the heap info table as necessary. */
-static __ptr_t morecore PP ((__malloc_size_t));
+static __ptr_t morecore_nolock PP ((__malloc_size_t));
 static __ptr_t
-morecore (size)
+morecore_nolock (size)
      __malloc_size_t size;
 {
   __ptr_t result;
@@ -514,6 +692,8 @@ morecore (size)
   if (result == NULL)
     return NULL;
 
+  PROTECT_MALLOC_STATE (0);
+
   /* Check if we need to grow the info table.  */
   if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize)
     {
@@ -540,7 +720,7 @@ morecore (size)
             `morecore_recursing' flag and return null.  */
          int save = errno;     /* Don't want to clobber errno with ENOMEM.  */
          morecore_recursing = 1;
-         newinfo = (malloc_info *) _realloc_internal
+         newinfo = (malloc_info *) _realloc_internal_nolock
            (_heapinfo, newsize * sizeof (malloc_info));
          morecore_recursing = 0;
          if (newinfo == NULL)
@@ -596,7 +776,8 @@ morecore (size)
       /* Reset _heaplimit so _free_internal never decides
         it can relocate or resize the info table.  */
       _heaplimit = 0;
-      _free_internal (oldinfo);
+      _free_internal_nolock (oldinfo);
+      PROTECT_MALLOC_STATE (0);
 
       /* The new heap limit includes the new table just allocated.  */
       _heaplimit = BLOCK ((char *) newinfo + heapsize * sizeof (malloc_info));
@@ -610,7 +791,7 @@ morecore (size)
 
 /* Allocate memory from the heap.  */
 __ptr_t
-_malloc_internal (size)
+_malloc_internal_nolock (size)
      __malloc_size_t size;
 {
   __ptr_t result;
@@ -630,6 +811,8 @@ _malloc_internal (size)
     return NULL;
 #endif
 
+  PROTECT_MALLOC_STATE (0);
+
   if (size < sizeof (struct list))
     size = sizeof (struct list);
 
@@ -676,9 +859,19 @@ _malloc_internal (size)
        {
          /* No free fragments of the desired size, so get a new block
             and break it into fragments, returning the first.  */
+#ifdef GC_MALLOC_CHECK
+         result = _malloc_internal_nolock (BLOCKSIZE);
+         PROTECT_MALLOC_STATE (0);
+#elif defined (USE_PTHREAD)
+         result = _malloc_internal_nolock (BLOCKSIZE);
+#else
          result = malloc (BLOCKSIZE);
+#endif
          if (result == NULL)
-           return NULL;
+           {
+             PROTECT_MALLOC_STATE (1);
+             goto out;
+           }
 
          /* Link all fragments but the first into the free list.  */
          next = (struct list *) ((char *) result + (1 << log));
@@ -741,9 +934,9 @@ _malloc_internal (size)
                  _heaplimit += wantblocks - lastblocks;
                  continue;
                }
-             result = morecore (wantblocks * BLOCKSIZE);
+             result = morecore_nolock (wantblocks * BLOCKSIZE);
              if (result == NULL)
-               return NULL;
+               goto out;
              block = BLOCK (result);
              /* Put the new block at the end of the free list.  */
              _heapinfo[block].free.size = wantblocks;
@@ -797,6 +990,21 @@ _malloc_internal (size)
        _heapinfo[block + blocks].busy.info.size = -blocks;
     }
 
+  PROTECT_MALLOC_STATE (1);
+ out:
+  return result;
+}
+
+__ptr_t
+_malloc_internal (size)
+     __malloc_size_t size;
+{
+  __ptr_t result;
+
+  LOCK ();
+  result = _malloc_internal_nolock (size);
+  UNLOCK ();
+
   return result;
 }
 
@@ -804,10 +1012,21 @@ __ptr_t
 malloc (size)
      __malloc_size_t size;
 {
+  __ptr_t (*hook) (__malloc_size_t);
+
   if (!__malloc_initialized && !__malloc_initialize ())
     return NULL;
 
-  return (__malloc_hook != NULL ? *__malloc_hook : _malloc_internal) (size);
+  /* Copy the value of __malloc_hook to an automatic variable in case
+     __malloc_hook is modified in another thread between its
+     NULL-check and the use.
+
+     Note: Strictly speaking, this is not a right solution.  We should
+     use mutexes to access non-read-only variables that are shared
+     among multiple threads.  We just leave it for compatibility with
+     glibc malloc (i.e., assignments to __malloc_hook) for now.  */
+  hook = __malloc_hook;
+  return (hook != NULL ? *hook : _malloc_internal) (size);
 }
 \f
 #ifndef _LIBC
@@ -843,19 +1062,19 @@ _realloc (ptr, size)
                  Written May 1989 by Mike Haertel.
 
 This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
+modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of the
 License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public
+License along with this library; see the file COPYING.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+Fifth Floor, Boston, MA 02110-1301, USA.
 
    The author may be reached (Email) at the address mike@ai.mit.edu,
    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
@@ -888,9 +1107,9 @@ void (*__free_hook) PP ((__ptr_t __ptr));
 struct alignlist *_aligned_blocks = NULL;
 
 /* Return memory to the heap.
-   Like `free' but don't call a __free_hook if there is one.  */
+   Like `_free_internal' but don't lock mutex.  */
 void
-_free_internal (ptr)
+_free_internal_nolock (ptr)
      __ptr_t ptr;
 {
   int type;
@@ -907,6 +1126,9 @@ _free_internal (ptr)
   if (ptr == NULL)
     return;
 
+  PROTECT_MALLOC_STATE (0);
+
+  LOCK_ALIGNED_BLOCKS ();
   for (l = _aligned_blocks; l != NULL; l = l->next)
     if (l->aligned == ptr)
       {
@@ -914,6 +1136,7 @@ _free_internal (ptr)
        ptr = l->exact;
        break;
       }
+  UNLOCK_ALIGNED_BLOCKS ();
 
   block = BLOCK (ptr);
 
@@ -1019,7 +1242,7 @@ _free_internal (ptr)
                 table's blocks to the system before we have copied them to
                 the new location.  */
              _heaplimit = 0;
-             _free_internal (_heapinfo);
+             _free_internal_nolock (_heapinfo);
              _heaplimit = oldlimit;
 
              /* Tell malloc to search from the beginning of the heap for
@@ -1027,8 +1250,9 @@ _free_internal (ptr)
              _heapindex = 0;
 
              /* Allocate new space for the info table and move its data.  */
-             newinfo = (malloc_info *) _malloc_internal (info_blocks
-                                                         * BLOCKSIZE);
+             newinfo = (malloc_info *) _malloc_internal_nolock (info_blocks
+                                                                * BLOCKSIZE);
+             PROTECT_MALLOC_STATE (0);
              memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE);
              _heapinfo = newinfo;
 
@@ -1090,7 +1314,11 @@ _free_internal (ptr)
          _chunks_free -= BLOCKSIZE >> type;
          _bytes_free -= BLOCKSIZE;
 
+#if defined (GC_MALLOC_CHECK) || defined (USE_PTHREAD)
+         _free_internal_nolock (ADDRESS (block));
+#else
          free (ADDRESS (block));
+#endif
        }
       else if (_heapinfo[block].busy.info.frag.nfree != 0)
        {
@@ -1123,15 +1351,31 @@ _free_internal (ptr)
        }
       break;
     }
+
+  PROTECT_MALLOC_STATE (1);
 }
 
-/* Return memory to the heap.  */
+/* Return memory to the heap.
+   Like `free' but don't call a __free_hook if there is one.  */
 void
+_free_internal (ptr)
+     __ptr_t ptr;
+{
+  LOCK ();
+  _free_internal_nolock (ptr);
+  UNLOCK ();
+}
+
+/* Return memory to the heap.  */
+
+FREE_RETURN_TYPE
 free (ptr)
      __ptr_t ptr;
 {
-  if (__free_hook != NULL)
-    (*__free_hook) (ptr);
+  void (*hook) (__ptr_t) = __free_hook;
+
+  if (hook != NULL)
+    (*hook) (ptr);
   else
     _free_internal (ptr);
 }
@@ -1152,19 +1396,19 @@ cfree (ptr)
                     Written May 1989 by Mike Haertel.
 
 This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
+modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of the
 License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public
+License along with this library; see the file COPYING.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+Fifth Floor, Boston, MA 02110-1301, USA.
 
    The author may be reached (Email) at the address mike@ai.mit.edu,
    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
@@ -1267,7 +1511,7 @@ __ptr_t (*__realloc_hook) PP ((__ptr_t __ptr, __malloc_size_t __size));
    new region.  This module has incestuous knowledge of the
    internals of both free and malloc. */
 __ptr_t
-_realloc_internal (ptr, size)
+_realloc_internal_nolock (ptr, size)
      __ptr_t ptr;
      __malloc_size_t size;
 {
@@ -1277,14 +1521,16 @@ _realloc_internal (ptr, size)
 
   if (size == 0)
     {
-      _free_internal (ptr);
-      return _malloc_internal (0);
+      _free_internal_nolock (ptr);
+      return _malloc_internal_nolock (0);
     }
   else if (ptr == NULL)
-    return _malloc_internal (size);
+    return _malloc_internal_nolock (size);
 
   block = BLOCK (ptr);
 
+  PROTECT_MALLOC_STATE (0);
+
   type = _heapinfo[block].busy.type;
   switch (type)
     {
@@ -1292,12 +1538,12 @@ _realloc_internal (ptr, size)
       /* Maybe reallocate a large block to a small fragment.  */
       if (size <= BLOCKSIZE / 2)
        {
-         result = _malloc_internal (size);
+         result = _malloc_internal_nolock (size);
          if (result != NULL)
            {
              memcpy (result, ptr, size);
-             _free_internal (ptr);
-             return result;
+             _free_internal_nolock (ptr);
+             goto out;
            }
        }
 
@@ -1316,7 +1562,7 @@ _realloc_internal (ptr, size)
             Now we will free this chunk; increment the statistics counter
             so it doesn't become wrong when _free_internal decrements it.  */
          ++_chunks_used;
-         _free_internal (ADDRESS (block + blocks));
+         _free_internal_nolock (ADDRESS (block + blocks));
          result = ptr;
        }
       else if (blocks == _heapinfo[block].busy.info.size)
@@ -1331,8 +1577,9 @@ _realloc_internal (ptr, size)
          /* Prevent free from actually returning memory to the system.  */
          oldlimit = _heaplimit;
          _heaplimit = 0;
-         _free_internal (ptr);
-         result = _malloc_internal (size);
+         _free_internal_nolock (ptr);
+         result = _malloc_internal_nolock (size);
+         PROTECT_MALLOC_STATE (0);
          if (_heaplimit == 0)
            _heaplimit = oldlimit;
          if (result == NULL)
@@ -1341,15 +1588,15 @@ _realloc_internal (ptr, size)
                 the thing we just freed.  Unfortunately it might
                 have been coalesced with its neighbors.  */
              if (_heapindex == block)
-               (void) _malloc_internal (blocks * BLOCKSIZE);
+               (void) _malloc_internal_nolock (blocks * BLOCKSIZE);
              else
                {
                  __ptr_t previous
-                   = _malloc_internal ((block - _heapindex) * BLOCKSIZE);
-                 (void) _malloc_internal (blocks * BLOCKSIZE);
-                 _free_internal (previous);
+                   = _malloc_internal_nolock ((block - _heapindex) * BLOCKSIZE);
+                 (void) _malloc_internal_nolock (blocks * BLOCKSIZE);
+                 _free_internal_nolock (previous);
                }
-             return NULL;
+             goto out;
            }
          if (ptr != result)
            memmove (result, ptr, blocks * BLOCKSIZE);
@@ -1367,15 +1614,31 @@ _realloc_internal (ptr, size)
        {
          /* The new size is different; allocate a new space,
             and copy the lesser of the new size and the old. */
-         result = _malloc_internal (size);
+         result = _malloc_internal_nolock (size);
          if (result == NULL)
-           return NULL;
+           goto out;
          memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type));
-         _free_internal (ptr);
+         _free_internal_nolock (ptr);
        }
       break;
     }
 
+  PROTECT_MALLOC_STATE (1);
+ out:
+  return result;
+}
+
+__ptr_t
+_realloc_internal (ptr, size)
+     __ptr_t ptr;
+     __malloc_size_t size;
+{
+  __ptr_t result;
+
+  LOCK();
+  result = _realloc_internal_nolock (ptr, size);
+  UNLOCK ();
+
   return result;
 }
 
@@ -1384,28 +1647,30 @@ realloc (ptr, size)
      __ptr_t ptr;
      __malloc_size_t size;
 {
+  __ptr_t (*hook) (__ptr_t, __malloc_size_t);
+
   if (!__malloc_initialized && !__malloc_initialize ())
     return NULL;
 
-  return (__realloc_hook != NULL ? *__realloc_hook : _realloc_internal)
-    (ptr, size);
+  hook = __realloc_hook;
+  return (hook != NULL ? *hook : _realloc_internal) (ptr, size);
 }
 /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
 
 This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
+modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of the
 License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public
+License along with this library; see the file COPYING.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+Fifth Floor, Boston, MA 02110-1301, USA.
 
    The author may be reached (Email) at the address mike@ai.mit.edu,
    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
@@ -1444,7 +1709,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with the GNU C Library; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+MA 02110-1301, USA.  */
 
 #ifndef        _MALLOC_INTERNAL
 #define        _MALLOC_INTERNAL
@@ -1474,7 +1740,14 @@ __ptr_t
 __default_morecore (increment)
      __malloc_ptrdiff_t increment;
 {
-  __ptr_t result = (__ptr_t) __sbrk (increment);
+  __ptr_t result;
+#if defined(CYGWIN)
+  if (!bss_sbrk_did_unexec)
+    {
+      return bss_sbrk (increment);
+    }
+#endif
+  result = (__ptr_t) __sbrk (increment);
   if (result == (__ptr_t) -1)
     return NULL;
   return result;
@@ -1482,19 +1755,19 @@ __default_morecore (increment)
 /* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
 
 This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
+modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of the
 License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
+You should have received a copy of the GNU General Public
+License along with this library; see the file COPYING.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #ifndef        _MALLOC_INTERNAL
 #define _MALLOC_INTERNAL
@@ -1508,7 +1781,8 @@ Cambridge, MA 02139, USA.  */
 
 #else
 
-__ptr_t (*__memalign_hook) PP ((size_t __size, size_t __alignment));
+__ptr_t (*__memalign_hook) PP ((__malloc_size_t __size,
+                               __malloc_size_t __alignment));
 
 __ptr_t
 memalign (alignment, size)
@@ -1517,9 +1791,10 @@ memalign (alignment, size)
 {
   __ptr_t result;
   unsigned long int adj, lastadj;
+  __ptr_t (*hook) (__malloc_size_t, __malloc_size_t) = __memalign_hook;
 
-  if (__memalign_hook)
-    return (*__memalign_hook) (alignment, size);
+  if (hook)
+    return (*hook) (alignment, size);
 
   /* Allocate a block with enough extra space to pad the block with up to
      (ALIGNMENT - 1) bytes if necessary.  */
@@ -1554,6 +1829,7 @@ memalign (alignment, size)
         of an allocated block.  */
 
       struct alignlist *l;
+      LOCK_ALIGNED_BLOCKS ();
       for (l = _aligned_blocks; l != NULL; l = l->next)
        if (l->aligned == NULL)
          /* This slot is free.  Use it.  */
@@ -1561,39 +1837,76 @@ memalign (alignment, size)
       if (l == NULL)
        {
          l = (struct alignlist *) malloc (sizeof (struct alignlist));
-         if (l == NULL)
+         if (l != NULL)
            {
-             free (result);
-             return NULL;
+             l->next = _aligned_blocks;
+             _aligned_blocks = l;
            }
-         l->next = _aligned_blocks;
-         _aligned_blocks = l;
        }
-      l->exact = result;
-      result = l->aligned = (char *) result + alignment - adj;
+      if (l != NULL)
+       {
+         l->exact = result;
+         result = l->aligned = (char *) result + alignment - adj;
+       }
+      UNLOCK_ALIGNED_BLOCKS ();
+      if (l == NULL)
+       {
+         free (result);
+         result = NULL;
+       }
     }
 
   return result;
 }
 
+#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;
+}
+
 #endif /* Not DJGPP v1 */
 /* Allocate memory on a page boundary.
    Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc.
 
 This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
+modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of the
 License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public
+License along with this library; see the file COPYING.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+Fifth Floor, Boston, MA 02110-1301, USA.
 
    The author may be reached (Email) at the address mike@ai.mit.edu,
    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
@@ -1640,3 +1953,245 @@ valloc (size)
 }
 
 #endif /* Not ELIDE_VALLOC.  */
+
+#ifdef GC_MCHECK
+
+/* Standard debugging hooks for `malloc'.
+   Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+   Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public
+License along with this library; see the file COPYING.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+Fifth Floor, Boston, MA 02110-1301, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifdef emacs
+#include <stdio.h>
+#else
+#ifndef        _MALLOC_INTERNAL
+#define        _MALLOC_INTERNAL
+#include <malloc.h>
+#include <stdio.h>
+#endif
+#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));
+
+/* Function to call when something awful happens.  */
+static void (*abortfunc) __P ((enum mcheck_status));
+
+/* Arbitrary magical numbers.  */
+#define MAGICWORD      0xfedabeeb
+#define MAGICFREE      0xd8675309
+#define MAGICBYTE      ((char) 0xd7)
+#define MALLOCFLOOD    ((char) 0x93)
+#define FREEFLOOD      ((char) 0x95)
+
+struct hdr
+  {
+    __malloc_size_t size;              /* Exact size requested by user.  */
+    unsigned long int magic;   /* Magic number to check header integrity.  */
+  };
+
+#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, val, size)
+     __ptr_t ptr;
+     int val;
+     __malloc_size_t size;
+{
+  char *cp = ptr;
+  while (size--)
+    *cp++ = val;
+}
+#endif
+
+static enum mcheck_status checkhdr __P ((const struct hdr *));
+static enum mcheck_status
+checkhdr (hdr)
+     const struct hdr *hdr;
+{
+  enum mcheck_status status;
+  switch (hdr->magic)
+    {
+    default:
+      status = MCHECK_HEAD;
+      break;
+    case MAGICFREE:
+      status = MCHECK_FREE;
+      break;
+    case MAGICWORD:
+      if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
+       status = MCHECK_TAIL;
+      else
+       status = MCHECK_OK;
+      break;
+    }
+  if (status != MCHECK_OK)
+    (*abortfunc) (status);
+  return status;
+}
+
+static void freehook __P ((__ptr_t));
+static void
+freehook (ptr)
+     __ptr_t ptr;
+{
+  struct hdr *hdr;
+
+  if (ptr)
+    {
+      hdr = ((struct hdr *) ptr) - 1;
+      checkhdr (hdr);
+      hdr->magic = MAGICFREE;
+      flood (ptr, FREEFLOOD, hdr->size);
+    }
+  else
+    hdr = NULL;
+
+  __free_hook = old_free_hook;
+  free (hdr);
+  __free_hook = freehook;
+}
+
+static __ptr_t mallochook __P ((__malloc_size_t));
+static __ptr_t
+mallochook (size)
+     __malloc_size_t size;
+{
+  struct hdr *hdr;
+
+  __malloc_hook = old_malloc_hook;
+  hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
+  __malloc_hook = mallochook;
+  if (hdr == NULL)
+    return NULL;
+
+  hdr->size = size;
+  hdr->magic = MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  flood ((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
+  return (__ptr_t) (hdr + 1);
+}
+
+static __ptr_t reallochook __P ((__ptr_t, __malloc_size_t));
+static __ptr_t
+reallochook (ptr, size)
+     __ptr_t ptr;
+     __malloc_size_t size;
+{
+  struct hdr *hdr = NULL;
+  __malloc_size_t osize = 0;
+
+  if (ptr)
+    {
+      hdr = ((struct hdr *) ptr) - 1;
+      osize = hdr->size;
+
+      checkhdr (hdr);
+      if (size < osize)
+       flood ((char *) ptr + size, FREEFLOOD, osize - size);
+    }
+
+  __free_hook = old_free_hook;
+  __malloc_hook = old_malloc_hook;
+  __realloc_hook = old_realloc_hook;
+  hdr = (struct hdr *) realloc ((__ptr_t) hdr, sizeof (struct hdr) + size + 1);
+  __free_hook = freehook;
+  __malloc_hook = mallochook;
+  __realloc_hook = reallochook;
+  if (hdr == NULL)
+    return NULL;
+
+  hdr->size = size;
+  hdr->magic = MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  if (size > osize)
+    flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
+  return (__ptr_t) (hdr + 1);
+}
+
+static void
+mabort (status)
+     enum mcheck_status status;
+{
+  const char *msg;
+  switch (status)
+    {
+    case MCHECK_OK:
+      msg = "memory is consistent, library is buggy";
+      break;
+    case MCHECK_HEAD:
+      msg = "memory clobbered before allocated block";
+      break;
+    case MCHECK_TAIL:
+      msg = "memory clobbered past end of allocated block";
+      break;
+    case MCHECK_FREE:
+      msg = "block freed twice";
+      break;
+    default:
+      msg = "bogus mcheck_status, library is buggy";
+      break;
+    }
+#ifdef __GNU_LIBRARY__
+  __libc_fatal (msg);
+#else
+  fprintf (stderr, "mcheck: %s\n", msg);
+  fflush (stderr);
+  abort ();
+#endif
+}
+
+static int mcheck_used = 0;
+
+int
+mcheck (func)
+     void (*func) __P ((enum mcheck_status));
+{
+  abortfunc = (func != NULL) ? func : &mabort;
+
+  /* These hooks may not be safely inserted if malloc is already in use.  */
+  if (!__malloc_initialized && !mcheck_used)
+    {
+      old_free_hook = __free_hook;
+      __free_hook = freehook;
+      old_malloc_hook = __malloc_hook;
+      __malloc_hook = mallochook;
+      old_realloc_hook = __realloc_hook;
+      __realloc_hook = reallochook;
+      mcheck_used = 1;
+    }
+
+  return mcheck_used ? 0 : -1;
+}
+
+enum mcheck_status
+mprobe (__ptr_t ptr)
+{
+  return mcheck_used ? checkhdr (ptr) : MCHECK_DISABLED;
+}
+
+#endif /* GC_MCHECK */
+
+/* arch-tag: 93dce5c0-f49a-41b5-86b1-f91c4169c02e
+   (do not change this comment) */