about summary refs log tree commit diff
path: root/malloc
diff options
context:
space:
mode:
Diffstat (limited to 'malloc')
-rw-r--r--malloc/malloc.c162
-rw-r--r--malloc/malloc.h7
-rw-r--r--malloc/thread-m.h36
3 files changed, 193 insertions, 12 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 0380527f64..6b4fc72b20 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -19,7 +19,7 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-/* V2.6.4-pt2 Sat Dec 14 1996
+/* V2.6.4-pt3 Thu Feb 20 1997
 
   This work is mainly derived from malloc-2.6.4 by Doug Lea
   <dl@cs.oswego.edu>, which is available from:
@@ -874,6 +874,8 @@ extern Void_t*     sbrk();
 #define mALLOC_STATs    __malloc_stats
 #define mALLOC_USABLE_SIZe __malloc_usable_size
 #define mALLOC_TRIm     __malloc_trim
+#define mALLOC_GET_STATe __malloc_get_state
+#define mALLOC_SET_STATe __malloc_set_state
 
 #else
 
@@ -889,6 +891,8 @@ extern Void_t*     sbrk();
 #define mALLOC_STATs    malloc_stats
 #define mALLOC_USABLE_SIZe malloc_usable_size
 #define mALLOC_TRIm     malloc_trim
+#define mALLOC_GET_STATe malloc_get_state
+#define mALLOC_SET_STATe malloc_set_state
 
 #endif
 
@@ -912,7 +916,11 @@ size_t  mALLOC_USABLE_SIZe(Void_t*);
 void    mALLOC_STATs(void);
 int     mALLOPt(int, int);
 struct mallinfo mALLINFo(void);
-#else
+Void_t* mALLOC_GET_STATe(void);
+int     mALLOC_SET_STATe(Void_t*);
+
+#else /* !__STD_C */
+
 #ifndef _LIBC
 void    ptmalloc_init();
 #endif
@@ -929,7 +937,10 @@ size_t  mALLOC_USABLE_SIZe();
 void    mALLOC_STATs();
 int     mALLOPt();
 struct mallinfo mALLINFo();
-#endif
+Void_t* mALLOC_GET_STATe();
+int     mALLOC_SET_STATe();
+
+#endif /* __STD_C */
 
 
 #ifdef __cplusplus
@@ -3775,6 +3786,144 @@ int mALLOPt(param_number, value) int param_number; int value;
 
 
 
+/* Get/set state: malloc_get_state() records the current state of all
+   malloc variables (_except_ for the actual heap contents and `hook'
+   function pointers) in a system dependent, opaque data structure.
+   This data structure is dynamically allocated and can be free()d
+   after use.  malloc_set_state() restores the state of all malloc
+   variables to the previously obtained state.  This is especially
+   useful when using this malloc as part of a shared library, and when
+   the heap contents are saved/restored via some other method.  The
+   primary example for this is GNU Emacs with its `dumping' procedure.
+   `Hook' function pointers are never saved or restored by these
+   functions. */
+
+#define MALLOC_STATE_MAGIC   0x444c4541l
+#define MALLOC_STATE_VERSION (0*0x100l + 0l) /* major*0x100 + minor */
+
+struct malloc_state {
+  long          magic;
+  long          version;
+  mbinptr       av[NAV * 2 + 2];
+  char*         sbrk_base;
+  int           sbrked_mem_bytes;
+  unsigned long trim_threshold;
+  unsigned long top_pad;
+  unsigned int  n_mmaps_max;
+  unsigned long mmap_threshold;
+  int           check_action;
+  unsigned long max_sbrked_mem;
+  unsigned long max_total_mem;
+  unsigned int  n_mmaps;
+  unsigned int  max_n_mmaps;
+  unsigned long mmapped_mem;
+  unsigned long max_mmapped_mem;
+};
+
+Void_t*
+mALLOC_GET_STATe()
+{
+  mchunkptr victim;
+  struct malloc_state* ms;
+  int i;
+  mbinptr b;
+
+  ptmalloc_init();
+  (void)mutex_lock(&main_arena.mutex);
+  victim = chunk_alloc(&main_arena, request2size(sizeof(*ms)));
+  if(!victim) {
+    (void)mutex_unlock(&main_arena.mutex);
+    return 0;
+  }
+  ms = (struct malloc_state*)chunk2mem(victim);
+  ms->magic = MALLOC_STATE_MAGIC;
+  ms->version = MALLOC_STATE_VERSION;
+  ms->av[0] = main_arena.av[0];
+  ms->av[1] = main_arena.av[1];
+  for(i=0; i<NAV; i++) {
+    b = bin_at(&main_arena, i);
+    if(first(b) == b)
+      ms->av[2*i+2] = ms->av[2*i+3] = 0; /* empty bin (or initial top) */
+    else {
+      ms->av[2*i+2] = first(b);
+      ms->av[2*i+3] = last(b);
+    }
+  }
+  ms->sbrk_base = sbrk_base;
+  ms->sbrked_mem_bytes = sbrked_mem;
+  ms->trim_threshold = trim_threshold;
+  ms->top_pad = top_pad;
+  ms->n_mmaps_max = n_mmaps_max;
+  ms->mmap_threshold = mmap_threshold;
+  ms->check_action = check_action;
+  ms->max_sbrked_mem = max_sbrked_mem;
+#ifdef NO_THREADS
+  ms->max_total_mem = max_total_mem;
+#else
+  ms->max_total_mem = 0;
+#endif
+  ms->n_mmaps = n_mmaps;
+  ms->max_n_mmaps = max_n_mmaps;
+  ms->mmapped_mem = mmapped_mem;
+  ms->max_mmapped_mem = max_mmapped_mem;
+  (void)mutex_unlock(&main_arena.mutex);
+  return (Void_t*)ms;
+}
+
+int
+#if __STD_C
+mALLOC_SET_STATe(Void_t* msptr)
+#else
+mALLOC_SET_STATe(msptr) Void_t* msptr;
+#endif
+{
+  struct malloc_state* ms = (struct malloc_state*)msptr;
+  int i;
+  mbinptr b;
+
+  ptmalloc_init();
+  if(ms->magic != MALLOC_STATE_MAGIC) return -1;
+  /* Must fail if the major version is too high. */
+  if((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl)) return -2;
+  (void)mutex_lock(&main_arena.mutex);
+  main_arena.av[0] = ms->av[0];
+  main_arena.av[1] = ms->av[1];
+  for(i=0; i<NAV; i++) {
+    b = bin_at(&main_arena, i);
+    if(ms->av[2*i+2] == 0)
+      first(b) = last(b) = b;
+    else {
+      first(b) = ms->av[2*i+2];
+      last(b) = ms->av[2*i+3];
+      if(i > 0) {
+        /* Make sure the links to the `av'-bins in the heap are correct. */
+        first(b)->bk = b;
+        last(b)->fd = b;
+      }
+    }
+  }
+  sbrk_base = ms->sbrk_base;
+  sbrked_mem = ms->sbrked_mem_bytes;
+  trim_threshold = ms->trim_threshold;
+  top_pad = ms->top_pad;
+  n_mmaps_max = ms->n_mmaps_max;
+  mmap_threshold = ms->mmap_threshold;
+  check_action = ms->check_action;
+  max_sbrked_mem = ms->max_sbrked_mem;
+#ifdef NO_THREADS
+  max_total_mem = ms->max_total_mem;
+#endif
+  n_mmaps = ms->n_mmaps;
+  max_n_mmaps = ms->max_n_mmaps;
+  mmapped_mem = ms->mmapped_mem;
+  max_mmapped_mem = ms->max_mmapped_mem;
+  /* add version-dependent code here */
+  (void)mutex_unlock(&main_arena.mutex);
+  return 0;
+}
+
+
+
 #if defined(_LIBC) || defined(MALLOC_HOOKS)
 
 /* A simple, standard set of debugging hooks.  Overhead is `only' one
@@ -4048,12 +4197,19 @@ weak_alias (__libc_mallopt, __mallopt) weak_alias (__libc_mallopt, mallopt)
 weak_alias (__malloc_stats, malloc_stats)
 weak_alias (__malloc_usable_size, malloc_usable_size)
 weak_alias (__malloc_trim, malloc_trim)
+weak_alias (__malloc_get_state, malloc_get_state)
+weak_alias (__malloc_set_state, malloc_set_state)
 #endif
 
 /*
 
 History:
 
+    V2.6.4-pt3 Thu Feb 20 1997 Wolfram Gloger (wmglo@dent.med.uni-muenchen.de)
+      * Added malloc_get/set_state() (mainly for use in GNU emacs),
+        using interface from Marcus Daniels
+      * All parameters are now adjustable via environment variables
+
     V2.6.4-pt2 Sat Dec 14 1996 Wolfram Gloger (wmglo@dent.med.uni-muenchen.de)
       * Added debugging hooks
       * Fixed possible deadlock in realloc() when out of memory
diff --git a/malloc/malloc.h b/malloc/malloc.h
index b27d06252c..53b9d1b206 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -171,6 +171,13 @@ extern size_t malloc_usable_size __MALLOC_P ((__malloc_ptr_t __ptr));
 /* Prints brief summary statistics on stderr. */
 extern void malloc_stats __MALLOC_P ((void));
 
+/* Record the state of all malloc variables in an opaque data structure. */
+extern __malloc_ptr_t malloc_get_state __MALLOC_P ((void));
+
+/* Restore the state of all malloc variables from data obtained with
+   malloc_get_state(). */
+extern int malloc_set_state __MALLOC_P ((__malloc_ptr_t __ptr));
+
 #if defined(__GLIBC__) || defined(MALLOC_HOOKS)
 
 /* Hooks for debugging versions. */
diff --git a/malloc/thread-m.h b/malloc/thread-m.h
index 10da26ba32..8307f256ff 100644
--- a/malloc/thread-m.h
+++ b/malloc/thread-m.h
@@ -1,6 +1,6 @@
 /* Basic platform-independent macro definitions for mutexes and
    thread-specific data.
-   Copyright (C) 1996 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Wolfram Gloger <wmglo@dent.med.uni-muenchen.de>, 1996.
 
@@ -66,19 +66,37 @@ static Void_t *malloc_key_data;
    (__pthread_mutex_unlock != NULL ? __pthread_mutex_unlock (m) : 0)
 
 #elif defined(MUTEX_INITIALIZER)
+/* Assume hurd, with cthreads */
 
-typedef thread_t thread_id;
+/* Cthreads `mutex_t' is a pointer to a mutex, and malloc wants just the
+   mutex itself.  */
+#undef mutex_t
+#define mutex_t struct mutex
 
-/* mutex */
-typedef mutex_t	mutex_t;
+#undef mutex_lock
+#define mutex_lock(m) (__mutex_lock(m), 0)
+
+#undef mutex_unlock
+#define mutex_unlock(m) (__mutex_unlock(m), 0)
+
+#define mutex_trylock(m) (!__mutex_trylock(m))
+
+#include <hurd/threadvar.h>
 
 /* thread specific data */
-typedef pthread_key_t tsd_key_t;
+typedef int tsd_key_t;
+
+static int tsd_keys_alloced = 0;
+
+#define tsd_key_create(key, destr) \
+  (assert (tsd_keys_alloced == 0), tsd_keys_alloced++)
+#define tsd_setspecific(key, data) \
+  (*__hurd_threadvar_location (_HURD_THREADVAR_MALLOC) = (unsigned long)(data))
+#define tsd_getspecific(key, vptr) \
+  ((vptr) = (void *)*__hurd_threadvar_location (_HURD_THREADVAR_MALLOC))
 
-#define mutex_init(m)		__mutex_init (m)
-#define mutex_lock(m)		__mutex_lock (m)
-#define mutex_trylock(m)	__mutex_trylock (m)
-#define mutex_unlock(m)		__mutex_unlock (m)
+/* No we're *not* using pthreads.  */
+#define __pthread_initialize ((void (*)(void))0)
 
 #else