diff options
Diffstat (limited to 'malloc')
-rw-r--r-- | malloc/malloc.c | 162 | ||||
-rw-r--r-- | malloc/malloc.h | 7 | ||||
-rw-r--r-- | malloc/thread-m.h | 36 |
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 |