From a334319f6530564d22e775935d9c91663623a1b4 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 22 Dec 2004 20:10:10 +0000 Subject: (CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4. --- malloc/Makefile | 16 +-- malloc/arena.c | 179 ++++++++--------------- malloc/hooks.c | 49 ++----- malloc/malloc.c | 374 +++++++++--------------------------------------- malloc/malloc.h | 142 +++++++++++++----- malloc/mcheck.c | 30 +--- malloc/memusage.c | 325 ++++++++++++++++------------------------- malloc/memusage.sh | 28 ++-- malloc/memusagestat.c | 51 ++++--- malloc/morecore.c | 54 ------- malloc/mtrace.c | 20 +-- malloc/mtrace.pl | 4 +- malloc/obstack.c | 71 ++++----- malloc/obstack.h | 114 +++++++-------- malloc/tst-malloc.c | 12 +- malloc/tst-mallocfork.c | 51 ------- malloc/tst-mcheck.c | 91 ------------ malloc/tst-mtrace.sh | 5 +- 18 files changed, 507 insertions(+), 1109 deletions(-) delete mode 100644 malloc/morecore.c delete mode 100644 malloc/tst-mallocfork.c delete mode 100644 malloc/tst-mcheck.c (limited to 'malloc') diff --git a/malloc/Makefile b/malloc/Makefile index c39eae5474..0512c49839 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -1,5 +1,4 @@ -# Copyright (C) 1991-1999, 2000, 2001, 2002, 2003, 2005, 2006 -# Free Software Foundation, Inc. +# Copyright (C) 1991-1999,2000,2001,2002,2003 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -27,7 +26,7 @@ all: dist-headers := malloc.h headers := $(dist-headers) obstack.h mcheck.h tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ - tst-mallocstate tst-mcheck tst-mallocfork + tst-mallocstate test-srcs = tst-mtrace distribute = thread-m.h mtrace.pl mcheck-init.c stackinfo.h memusage.h \ @@ -79,7 +78,6 @@ endif ifneq ($(cross-compiling),yes) # If the gd library is available we build the `memusagestat' program. ifneq ($(LIBGD),no) -others: $(objpfx)memusage install-bin = memusagestat install-bin-script += memusage generated += memusagestat memusage @@ -103,8 +101,6 @@ $(objpfx)memusagestat: $(memusagestat-modules:%=$(objpfx)%.o) include ../Rules -CFLAGS-mcheck-init.c = $(PIC-ccflag) - $(objpfx)libmcheck.a: $(objpfx)mcheck-init.o -rm -f $@ $(patsubst %/,cd % &&,$(objpfx)) \ @@ -122,13 +118,9 @@ endif endif endif -tst-mcheck-ENV = MALLOC_CHECK_=3 - # Uncomment this for test releases. For public releases it is too expensive. #CPPFLAGS-malloc.o += -DMALLOC_DEBUG=1 -sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,') - $(objpfx)mtrace: mtrace.pl rm -f $@.new sed -e 's|@PERL@|$(PERL)|' -e 's|@XXX@|$(address-width)|' \ @@ -138,12 +130,12 @@ $(objpfx)mtrace: mtrace.pl $(objpfx)memusage: memusage.sh rm -f $@.new sed -e 's|@BASH@|$(BASH)|' -e 's|@VERSION@|$(version)|' \ - -e 's|@SLIBDIR@|$(sLIBdir)|' -e 's|@BINDIR@|$(bindir)|' $^ > $@.new \ + -e 's|@SLIBDIR@|$(slibdir)|' -e 's|@BINDIR@|$(bindir)|' $^ > $@.new \ && rm -f $@ && mv $@.new $@ && chmod +x $@ # The implementation uses `dlsym' -$(objpfx)libmemusage.so: $(common-objpfx)dlfcn/libdl.so $(elfobjdir)/ld.so +$(objpfx)libmemusage.so: $(common-objpfx)dlfcn/libdl.so # Extra dependencies $(foreach o,$(all-object-suffixes),$(objpfx)malloc$(o)): arena.c hooks.c diff --git a/malloc/arena.c b/malloc/arena.c index 0dcb7cb9f8..026f2c7822 100644 --- a/malloc/arena.c +++ b/malloc/arena.c @@ -1,6 +1,5 @@ /* Malloc implementation for multiple threads without lock contention. - Copyright (C) 2001,2002,2003,2004,2005,2006,2007 - Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Wolfram Gloger , 2001. @@ -19,17 +18,13 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +/* $Id$ */ /* Compile-time constants. */ #define HEAP_MIN_SIZE (32*1024) #ifndef HEAP_MAX_SIZE -# ifdef DEFAULT_MMAP_THRESHOLD_MAX -# define HEAP_MAX_SIZE (2 * DEFAULT_MMAP_THRESHOLD_MAX) -# else -# define HEAP_MAX_SIZE (1024*1024) /* must be a power of two */ -# endif +#define HEAP_MAX_SIZE (1024*1024) /* must be a power of two */ #endif /* HEAP_MIN_SIZE and HEAP_MAX_SIZE limit the size of mmap()ed heaps @@ -60,20 +55,9 @@ typedef struct _heap_info { mstate ar_ptr; /* Arena for this heap. */ struct _heap_info *prev; /* Previous heap. */ size_t size; /* Current size in bytes. */ - size_t mprotect_size; /* Size in bytes that has been mprotected - PROT_READ|PROT_WRITE. */ - /* Make sure the following data is properly aligned, particularly - that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of - MALLOC_ALIGNMENT. */ - char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK]; + size_t pad; /* Make sure the following data is properly aligned. */ } heap_info; -/* Get a compile-time error if the heap_info padding is not correct - to make alignment work as expected in sYSMALLOc. */ -extern int sanity_check_heap_info_alignment[(sizeof (heap_info) - + 2 * SIZE_SZ) % MALLOC_ALIGNMENT - ? -1 : 1]; - /* Thread specific data */ static tsd_key_t arena_key; @@ -224,10 +208,6 @@ free_atfork(Void_t* mem, const Void_t *caller) (void)mutex_unlock(&ar_ptr->mutex); } - -/* Counter for number of times the list is locked by the same thread. */ -static unsigned int atfork_recursive_cntr; - /* The following two functions are registered via thread_atfork() to make sure that the mutexes remain in a consistent state in the fork()ed version of a thread. Also adapt the malloc and free hooks @@ -241,18 +221,7 @@ ptmalloc_lock_all (void) if(__malloc_initialized < 1) return; - if (mutex_trylock(&list_lock)) - { - Void_t *my_arena; - tsd_getspecific(arena_key, my_arena); - if (my_arena == ATFORK_ARENA_PTR) - /* This is the same thread which already locks the global list. - Just bump the counter. */ - goto out; - - /* This thread has to wait its turn. */ - (void)mutex_lock(&list_lock); - } + (void)mutex_lock(&list_lock); for(ar_ptr = &main_arena;;) { (void)mutex_lock(&ar_ptr->mutex); ar_ptr = ar_ptr->next; @@ -265,8 +234,6 @@ ptmalloc_lock_all (void) /* Only the current thread may perform malloc/free calls now. */ tsd_getspecific(arena_key, save_arena); tsd_setspecific(arena_key, ATFORK_ARENA_PTR); - out: - ++atfork_recursive_cntr; } static void @@ -276,8 +243,6 @@ ptmalloc_unlock_all (void) if(__malloc_initialized < 1) return; - if (--atfork_recursive_cntr != 0) - return; tsd_setspecific(arena_key, save_arena); __malloc_hook = save_malloc_hook; __free_hook = save_free_hook; @@ -291,7 +256,7 @@ ptmalloc_unlock_all (void) #ifdef __linux__ -/* In NPTL, unlocking a mutex in the child process after a +/* In LinuxThreads, unlocking a mutex in the child process after a fork() is currently unsafe, whereas re-initializing it is safe and does not leak resources. Therefore, a special atfork handler is installed for the child. */ @@ -314,7 +279,6 @@ ptmalloc_unlock_all2 (void) if(ar_ptr == &main_arena) break; } mutex_init(&list_lock); - atfork_recursive_cntr = 0; } #else @@ -389,6 +353,8 @@ libc_hidden_proto (_dl_open_hook); # endif # if defined SHARED && defined USE_TLS && !USE___THREAD +# include + /* This is called by __pthread_initialize_minimal when it needs to use malloc to set up the TLS state. We cannot do the full work of ptmalloc_init (below) until __pthread_initialize_minimal has finished, @@ -516,13 +482,8 @@ ptmalloc_init (void) s = &envline[7]; break; case 8: - if (! secure) - { - if (memcmp (envline, "TOP_PAD_", 8) == 0) - mALLOPt(M_TOP_PAD, atoi(&envline[9])); - else if (memcmp (envline, "PERTURB_", 8) == 0) - mALLOPt(M_PERTURB, atoi(&envline[9])); - } + if (! secure && memcmp (envline, "TOP_PAD_", 8) == 0) + mALLOPt(M_TOP_PAD, atoi(&envline[9])); break; case 9: if (! secure && memcmp (envline, "MMAP_MAX_", 9) == 0) @@ -549,8 +510,6 @@ ptmalloc_init (void) mALLOPt(M_TRIM_THRESHOLD, atoi(s)); if((s = getenv("MALLOC_TOP_PAD_"))) mALLOPt(M_TOP_PAD, atoi(s)); - if((s = getenv("MALLOC_PERTURB_"))) - mALLOPt(M_PERTURB, atoi(s)); if((s = getenv("MALLOC_MMAP_THRESHOLD_"))) mALLOPt(M_MMAP_THRESHOLD, atoi(s)); if((s = getenv("MALLOC_MMAP_MAX_"))) @@ -558,8 +517,8 @@ ptmalloc_init (void) } s = getenv("MALLOC_CHECK_"); #endif - if(s && s[0]) { - mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0')); + if(s) { + if(s[0]) mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0')); if (check_action != 0) __malloc_check_init(); } @@ -695,7 +654,6 @@ new_heap(size, top_pad) size_t size, top_pad; } h = (heap_info *)p2; h->size = size; - h->mprotect_size = size; THREAD_STAT(stat_n_heaps++); return h; } @@ -716,36 +674,19 @@ grow_heap(h, diff) heap_info *h; long diff; if(diff >= 0) { diff = (diff + page_mask) & ~page_mask; new_size = (long)h->size + diff; - if((unsigned long) new_size > (unsigned long) HEAP_MAX_SIZE) + if(new_size > HEAP_MAX_SIZE) return -1; - if((unsigned long) new_size > h->mprotect_size) { - if (mprotect((char *)h + h->mprotect_size, - (unsigned long) new_size - h->mprotect_size, - PROT_READ|PROT_WRITE) != 0) - return -2; - h->mprotect_size = new_size; - } + if(mprotect((char *)h + h->size, diff, PROT_READ|PROT_WRITE) != 0) + return -2; } else { new_size = (long)h->size + diff; if(new_size < (long)sizeof(*h)) return -1; /* Try to re-map the extra heap space freshly to save memory, and make it inaccessible. */ -#ifdef _LIBC - if (__builtin_expect (__libc_enable_secure, 0)) -#else - if (1) -#endif - { - if((char *)MMAP((char *)h + new_size, -diff, PROT_NONE, - MAP_PRIVATE|MAP_FIXED) == (char *) MAP_FAILED) - return -2; - h->mprotect_size = new_size; - } -#ifdef _LIBC - else - madvise ((char *)h + new_size, -diff, MADV_DONTNEED); -#endif + if((char *)MMAP((char *)h + new_size, -diff, PROT_NONE, + MAP_PRIVATE|MAP_FIXED) == (char *) MAP_FAILED) + return -2; /*fprintf(stderr, "shrink %p %08lx\n", h, new_size);*/ } h->size = new_size; @@ -818,48 +759,6 @@ heap_trim(heap, pad) heap_info *heap; size_t pad; return 1; } -/* Create a new arena with initial size "size". */ - -static mstate -_int_new_arena(size_t size) -{ - mstate a; - heap_info *h; - char *ptr; - unsigned long misalign; - - h = new_heap(size + (sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT), - mp_.top_pad); - if(!h) { - /* Maybe size is too large to fit in a single heap. So, just try - to create a minimally-sized arena and let _int_malloc() attempt - to deal with the large request via mmap_chunk(). */ - h = new_heap(sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT, mp_.top_pad); - if(!h) - return 0; - } - a = h->ar_ptr = (mstate)(h+1); - malloc_init_state(a); - /*a->next = NULL;*/ - a->system_mem = a->max_system_mem = h->size; - arena_mem += h->size; -#ifdef NO_THREADS - if((unsigned long)(mp_.mmapped_mem + arena_mem + main_arena.system_mem) > - mp_.max_total_mem) - mp_.max_total_mem = mp_.mmapped_mem + arena_mem + main_arena.system_mem; -#endif - - /* Set up the top chunk, with proper alignment. */ - ptr = (char *)(a + 1); - misalign = (unsigned long)chunk2mem(ptr) & MALLOC_ALIGN_MASK; - if (misalign > 0) - ptr += MALLOC_ALIGNMENT - misalign; - top(a) = (mchunkptr)ptr; - set_head(top(a), (((char*)h + h->size) - ptr) | PREV_INUSE); - - return a; -} - static mstate internal_function #if __STD_C @@ -930,6 +829,48 @@ arena_get2(a_tsd, size) mstate a_tsd; size_t size; return a; } +/* Create a new arena with initial size "size". */ + +mstate +_int_new_arena(size_t size) +{ + mstate a; + heap_info *h; + char *ptr; + unsigned long misalign; + + h = new_heap(size + (sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT), + mp_.top_pad); + if(!h) { + /* Maybe size is too large to fit in a single heap. So, just try + to create a minimally-sized arena and let _int_malloc() attempt + to deal with the large request via mmap_chunk(). */ + h = new_heap(sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT, mp_.top_pad); + if(!h) + return 0; + } + a = h->ar_ptr = (mstate)(h+1); + malloc_init_state(a); + /*a->next = NULL;*/ + a->system_mem = a->max_system_mem = h->size; + arena_mem += h->size; +#ifdef NO_THREADS + if((unsigned long)(mp_.mmapped_mem + arena_mem + main_arena.system_mem) > + mp_.max_total_mem) + mp_.max_total_mem = mp_.mmapped_mem + arena_mem + main_arena.system_mem; +#endif + + /* Set up the top chunk, with proper alignment. */ + ptr = (char *)(a + 1); + misalign = (unsigned long)chunk2mem(ptr) & MALLOC_ALIGN_MASK; + if (misalign > 0) + ptr += MALLOC_ALIGNMENT - misalign; + top(a) = (mchunkptr)ptr; + set_head(top(a), (((char*)h + h->size) - ptr) | PREV_INUSE); + + return a; +} + #endif /* USE_ARENAS */ /* diff --git a/malloc/hooks.c b/malloc/hooks.c index 708f0faf83..a5c97f3133 100644 --- a/malloc/hooks.c +++ b/malloc/hooks.c @@ -1,5 +1,5 @@ /* Malloc implementation for multiple threads without lock contention. - Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Wolfram Gloger , 2001. @@ -18,6 +18,8 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id$ */ + /* What to do if the standard debugging hooks are in place and a corrupt pointer is detected: do nothing (0), print an error message (1), or call abort() (2). */ @@ -144,9 +146,9 @@ mem2mem_check(ptr, sz) Void_t *ptr; size_t sz; static mchunkptr internal_function #if __STD_C -mem2chunk_check(Void_t* mem, unsigned char **magic_p) +mem2chunk_check(Void_t* mem) #else -mem2chunk_check(mem, magic_p) Void_t* mem; unsigned char **magic_p; +mem2chunk_check(mem) Void_t* mem; #endif { mchunkptr p; @@ -171,6 +173,7 @@ mem2chunk_check(mem, magic_p) Void_t* mem; unsigned char **magic_p; for(sz += SIZE_SZ-1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) { if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL; } + ((unsigned char*)p)[sz] ^= 0xFF; } else { unsigned long offset, page_mask = malloc_getpagesize-1; @@ -190,10 +193,8 @@ mem2chunk_check(mem, magic_p) Void_t* mem; unsigned char **magic_p; for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) { if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL; } + ((unsigned char*)p)[sz] ^= 0xFF; } - ((unsigned char*)p)[sz] ^= 0xFF; - if (magic_p) - *magic_p = (unsigned char *)p + sz; return p; } @@ -231,11 +232,7 @@ top_check() sbrk_size = front_misalign + mp_.top_pad + MINSIZE; sbrk_size += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1)); new_brk = (char*)(MORECORE (sbrk_size)); - if (new_brk == (char*)(MORECORE_FAILURE)) - { - MALLOC_FAILURE_ACTION; - return -1; - } + if (new_brk == (char*)(MORECORE_FAILURE)) return -1; /* Call the `morecore' hook if necessary. */ if (__after_morecore_hook) (*__after_morecore_hook) (); @@ -256,11 +253,6 @@ malloc_check(sz, caller) size_t sz; const Void_t *caller; { Void_t *victim; - if (sz+1 == 0) { - MALLOC_FAILURE_ACTION; - return NULL; - } - (void)mutex_lock(&main_arena.mutex); victim = (top_check() >= 0) ? _int_malloc(&main_arena, sz+1) : NULL; (void)mutex_unlock(&main_arena.mutex); @@ -278,7 +270,7 @@ free_check(mem, caller) Void_t* mem; const Void_t *caller; if(!mem) return; (void)mutex_lock(&main_arena.mutex); - p = mem2chunk_check(mem, NULL); + p = mem2chunk_check(mem); if(!p) { (void)mutex_unlock(&main_arena.mutex); @@ -310,19 +302,10 @@ realloc_check(oldmem, bytes, caller) mchunkptr oldp; INTERNAL_SIZE_T nb, oldsize; Void_t* newmem = 0; - unsigned char *magic_p; - if (bytes+1 == 0) { - MALLOC_FAILURE_ACTION; - return NULL; - } if (oldmem == 0) return malloc_check(bytes, NULL); - if (bytes == 0) { - free_check (oldmem, NULL); - return NULL; - } (void)mutex_lock(&main_arena.mutex); - oldp = mem2chunk_check(oldmem, &magic_p); + oldp = mem2chunk_check(oldmem); (void)mutex_unlock(&main_arena.mutex); if(!oldp) { malloc_printerr(check_action, "realloc(): invalid pointer", oldmem); @@ -374,12 +357,6 @@ realloc_check(oldmem, bytes, caller) #if HAVE_MMAP } #endif - - /* mem2chunk_check changed the magic byte in the old chunk. - If newmem is NULL, then the old chunk will still be used though, - so we need to invert that change here. */ - if (newmem == NULL) *magic_p ^= 0xFF; - (void)mutex_unlock(&main_arena.mutex); return mem2mem_check(newmem, bytes); @@ -399,10 +376,6 @@ memalign_check(alignment, bytes, caller) if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL); if (alignment < MINSIZE) alignment = MINSIZE; - if (bytes+1 == 0) { - MALLOC_FAILURE_ACTION; - return NULL; - } checked_request2size(bytes+1, nb); (void)mutex_lock(&main_arena.mutex); mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) : @@ -582,7 +555,7 @@ public_sET_STATe(Void_t* msptr) (void)mutex_lock(&main_arena.mutex); /* There are no fastchunks. */ clear_fastchunks(&main_arena); - set_max_fast(DEFAULT_MXFAST); + set_max_fast(&main_arena, DEFAULT_MXFAST); for (i=0; i and Doug Lea , 2001. @@ -24,6 +24,7 @@ Doug Lea and adapted to multiple threads/arenas by Wolfram Gloger. * Version ptmalloc2-20011215 + $Id$ based on: VERSION 2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) @@ -188,8 +189,7 @@ Changing default word sizes: INTERNAL_SIZE_T size_t - MALLOC_ALIGNMENT MAX (2 * sizeof(INTERNAL_SIZE_T), - __alignof__ (long double)) + MALLOC_ALIGNMENT 2 * sizeof(INTERNAL_SIZE_T) Configuration and functionality options: @@ -259,7 +259,6 @@ #ifdef _LIBC #include -#include #endif #ifdef __cplusplus @@ -382,15 +381,6 @@ extern "C" { #ifndef MALLOC_ALIGNMENT -/* XXX This is the correct definition. It differs from 2*SIZE_SZ only on - powerpc32. For the time being, changing this is causing more - compatibility problems due to malloc_get_state/malloc_set_state than - will returning blocks not adequately aligned for long double objects - under -mlong-double-128. - -#define MALLOC_ALIGNMENT (2 * SIZE_SZ < __alignof__ (long double) \ - ? __alignof__ (long double) : 2 * SIZE_SZ) -*/ #define MALLOC_ALIGNMENT (2 * SIZE_SZ) #endif @@ -1016,7 +1006,6 @@ struct mallinfo public_mALLINFo(void); struct mallinfo public_mALLINFo(); #endif -#ifndef _LIBC /* independent_calloc(size_t n_elements, size_t element_size, Void_t* chunks[]); @@ -1140,8 +1129,6 @@ Void_t** public_iCOMALLOc(size_t, size_t*, Void_t**); Void_t** public_iCOMALLOc(); #endif -#endif /* _LIBC */ - /* pvalloc(size_t n); @@ -1415,27 +1402,6 @@ int __posix_memalign(void **, size_t, size_t); #define DEFAULT_TOP_PAD (0) #endif -/* - MMAP_THRESHOLD_MAX and _MIN are the bounds on the dynamically - adjusted MMAP_THRESHOLD. -*/ - -#ifndef DEFAULT_MMAP_THRESHOLD_MIN -#define DEFAULT_MMAP_THRESHOLD_MIN (128 * 1024) -#endif - -#ifndef DEFAULT_MMAP_THRESHOLD_MAX - /* For 32-bit platforms we cannot increase the maximum mmap - threshold much because it is also the minimum value for the - maximum heap size and its alignment. Going above 512k (i.e., 1M - for new heaps) wastes too much address space. */ -# if __WORDSIZE == 32 -# define DEFAULT_MMAP_THRESHOLD_MAX (512 * 1024) -# else -# define DEFAULT_MMAP_THRESHOLD_MAX (4 * 1024 * 1024 * sizeof(long)) -# endif -#endif - /* M_MMAP_THRESHOLD is the request size threshold for using mmap() to service a request. Requests of at least this size that cannot @@ -1475,63 +1441,12 @@ int __posix_memalign(void **, size_t, size_t); "large" chunks, but the value of "large" varies across systems. The default is an empirically derived value that works well in most systems. - - - Update in 2006: - The above was written in 2001. Since then the world has changed a lot. - Memory got bigger. Applications got bigger. The virtual address space - layout in 32 bit linux changed. - - In the new situation, brk() and mmap space is shared and there are no - artificial limits on brk size imposed by the kernel. What is more, - applications have started using transient allocations larger than the - 128Kb as was imagined in 2001. - - The price for mmap is also high now; each time glibc mmaps from the - kernel, the kernel is forced to zero out the memory it gives to the - application. Zeroing memory is expensive and eats a lot of cache and - memory bandwidth. This has nothing to do with the efficiency of the - virtual memory system, by doing mmap the kernel just has no choice but - to zero. - - In 2001, the kernel had a maximum size for brk() which was about 800 - megabytes on 32 bit x86, at that point brk() would hit the first - mmaped shared libaries and couldn't expand anymore. With current 2.6 - kernels, the VA space layout is different and brk() and mmap - both can span the entire heap at will. - - Rather than using a static threshold for the brk/mmap tradeoff, - we are now using a simple dynamic one. The goal is still to avoid - fragmentation. The old goals we kept are - 1) try to get the long lived large allocations to use mmap() - 2) really large allocations should always use mmap() - and we're adding now: - 3) transient allocations should use brk() to avoid forcing the kernel - having to zero memory over and over again - - The implementation works with a sliding threshold, which is by default - limited to go between 128Kb and 32Mb (64Mb for 64 bitmachines) and starts - out at 128Kb as per the 2001 default. - - This allows us to satisfy requirement 1) under the assumption that long - lived allocations are made early in the process' lifespan, before it has - started doing dynamic allocations of the same size (which will - increase the threshold). - - The upperbound on the threshold satisfies requirement 2) - - The threshold goes up in value when the application frees memory that was - allocated with the mmap allocator. The idea is that once the application - starts freeing memory of a certain size, it's highly probable that this is - a size the application uses for transient allocations. This estimator - is there to satisfy the new third requirement. - */ #define M_MMAP_THRESHOLD -3 #ifndef DEFAULT_MMAP_THRESHOLD -#define DEFAULT_MMAP_THRESHOLD DEFAULT_MMAP_THRESHOLD_MIN +#define DEFAULT_MMAP_THRESHOLD (128 * 1024) #endif /* @@ -1592,10 +1507,8 @@ Void_t* _int_memalign(mstate, size_t, size_t); Void_t* _int_valloc(mstate, size_t); static Void_t* _int_pvalloc(mstate, size_t); /*static Void_t* cALLOc(size_t, size_t);*/ -#ifndef _LIBC static Void_t** _int_icalloc(mstate, size_t, size_t, Void_t**); static Void_t** _int_icomalloc(mstate, size_t, size_t*, Void_t**); -#endif static int mTRIm(size_t); static size_t mUSABLe(Void_t*); static void mSTATs(void); @@ -1808,7 +1721,7 @@ struct malloc_chunk { mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | User data starts here... . . . - . (malloc_usable_size() bytes) . + . (malloc_usable_space() bytes) . . | nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Size of chunk | @@ -1890,11 +1803,7 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /* Check if m has acceptable alignment */ -#define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0) - -#define misaligned_chunk(p) \ - ((uintptr_t)(MALLOC_ALIGNMENT == 2 * SIZE_SZ ? (p) : chunk2mem (p)) \ - & MALLOC_ALIGN_MASK) +#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0) /* @@ -2061,9 +1970,7 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ typedef struct malloc_chunk* mbinptr; /* addressing -- note that bin_at(0) does not exist */ -#define bin_at(m, i) \ - (mbinptr) (((char *) &((m)->bins[((i) - 1) * 2])) \ - - offsetof (struct malloc_chunk, fd)) +#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - (SIZE_SZ<<1))) /* analog of ++bin */ #define next_bin(b) ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1))) @@ -2245,9 +2152,9 @@ typedef struct malloc_chunk* mfastbinptr; #define FASTCHUNKS_BIT (1U) -#define have_fastchunks(M) (((M)->flags & FASTCHUNKS_BIT) == 0) -#define clear_fastchunks(M) ((M)->flags |= FASTCHUNKS_BIT) -#define set_fastchunks(M) ((M)->flags &= ~FASTCHUNKS_BIT) +#define have_fastchunks(M) (((M)->max_fast & FASTCHUNKS_BIT) == 0) +#define clear_fastchunks(M) ((M)->max_fast |= FASTCHUNKS_BIT) +#define set_fastchunks(M) ((M)->max_fast &= ~FASTCHUNKS_BIT) /* NONCONTIGUOUS_BIT indicates that MORECORE does not return contiguous @@ -2260,10 +2167,10 @@ typedef struct malloc_chunk* mfastbinptr; #define NONCONTIGUOUS_BIT (2U) -#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0) -#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0) -#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT) -#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT) +#define contiguous(M) (((M)->max_fast & NONCONTIGUOUS_BIT) == 0) +#define noncontiguous(M) (((M)->max_fast & NONCONTIGUOUS_BIT) != 0) +#define set_noncontiguous(M) ((M)->max_fast |= NONCONTIGUOUS_BIT) +#define set_contiguous(M) ((M)->max_fast &= ~NONCONTIGUOUS_BIT) /* Set value of max_fast. @@ -2272,9 +2179,10 @@ typedef struct malloc_chunk* mfastbinptr; Setting the value clears fastchunk bit but preserves noncontiguous bit. */ -#define set_max_fast(s) \ - global_max_fast = ((s) == 0)? SMALLBIN_WIDTH: request2size(s) -#define get_max_fast() global_max_fast +#define set_max_fast(M, s) \ + (M)->max_fast = (((s) == 0)? SMALLBIN_WIDTH: request2size(s)) | \ + FASTCHUNKS_BIT | \ + ((M)->max_fast & NONCONTIGUOUS_BIT) /* @@ -2284,15 +2192,16 @@ typedef struct malloc_chunk* mfastbinptr; struct malloc_state { /* Serialize access. */ mutex_t mutex; - - /* Flags (formerly in max_fast). */ - int flags; + // Should we have padding to move the mutex to its own cache line? #if THREAD_STATS /* Statistics for locking. Only used if THREAD_STATS is defined. */ long stat_lock_direct, stat_lock_loop, stat_lock_wait; #endif + /* The maximum chunk size to be eligible for fastbin */ + INTERNAL_SIZE_T max_fast; /* low 2 bits used as flags */ + /* Fastbins */ mfastbinptr fastbins[NFASTBINS]; @@ -2303,7 +2212,7 @@ struct malloc_state { mchunkptr last_remainder; /* Normal bins packed as described above */ - mchunkptr bins[NBINS * 2 - 2]; + mchunkptr bins[NBINS * 2]; /* Bitmap of bins */ unsigned int binmap[BINMAPSIZE]; @@ -2326,10 +2235,6 @@ struct malloc_par { int n_mmaps; int n_mmaps_max; int max_n_mmaps; - /* the mmap_threshold is dynamic, until the user sets - it manually, at which point we need to disable any - dynamic behavior. */ - int no_dyn_threshold; /* Cache malloc_getpagesize */ unsigned int pagesize; @@ -2357,10 +2262,6 @@ static struct malloc_state main_arena; static struct malloc_par mp_; - -/* Maximum size of memory handled in fastbins. */ -static INTERNAL_SIZE_T global_max_fast; - /* Initialize a malloc_state struct. @@ -2390,9 +2291,8 @@ static void malloc_init_state(av) mstate av; if (av != &main_arena) #endif set_noncontiguous(av); - if (av == &main_arena) - set_max_fast(DEFAULT_MXFAST); - av->flags |= FASTCHUNKS_BIT; + + set_max_fast(av, DEFAULT_MXFAST); av->top = initial_top(av); } @@ -2405,9 +2305,7 @@ static void malloc_init_state(av) mstate av; static Void_t* sYSMALLOc(INTERNAL_SIZE_T, mstate); static int sYSTRIm(size_t, mstate); static void malloc_consolidate(mstate); -#ifndef _LIBC static Void_t** iALLOc(mstate, size_t, size_t*, int, Void_t**); -#endif #else static Void_t* sYSMALLOc(); static int sYSTRIm(); @@ -2461,14 +2359,6 @@ void weak_variable (*__after_morecore_hook) (void) = NULL; static int check_action = DEFAULT_CHECK_ACTION; -/* ------------------ Testing support ----------------------------------*/ - -static int perturb_byte; - -#define alloc_perturb(p, n) memset (p, (perturb_byte ^ 0xff) & 0xff, n) -#define free_perturb(p, n) memset (p, perturb_byte & 0xff, n) - - /* ------------------- Support for multiple arenas -------------------- */ #include "arena.c" @@ -2734,9 +2624,9 @@ static void do_check_malloc_state(mstate av) /* properties of fastbins */ /* max_fast is in allowed range */ - assert((get_max_fast () & ~1) <= request2size(MAX_FAST_SIZE)); + assert((av->max_fast & ~1) <= request2size(MAX_FAST_SIZE)); - max_fast_bin = fastbin_index(get_max_fast ()); + max_fast_bin = fastbin_index(av->max_fast); for (i = 0; i < NFASTBINS; ++i) { p = av->fastbins[i]; @@ -2862,7 +2752,6 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; unsigned long sum; /* for updating stats */ size_t pagemask = mp_.pagesize - 1; - bool tried_mmap = false; #if HAVE_MMAP @@ -2879,14 +2768,12 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; char* mm; /* return value from mmap call*/ - try_mmap: /* Round up size to nearest page. For mmapped chunks, the overhead is one SIZE_SZ unit larger than for normal chunks, because there is no following chunk whose prev_size field could be used. */ size = (nb + SIZE_SZ + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; - tried_mmap = true; /* Don't try if size wraps around 0 */ if ((unsigned long)(size) > (unsigned long)(nb)) { @@ -2970,8 +2857,7 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; /* First try to extend the current heap. */ old_heap = heap_for_ptr(old_top); old_heap_size = old_heap->size; - if ((long) (MINSIZE + nb - old_size) > 0 - && grow_heap(old_heap, MINSIZE + nb - old_size) == 0) { + if (grow_heap(old_heap, MINSIZE + nb - old_size) == 0) { av->system_mem += old_heap->size - old_heap_size; arena_mem += old_heap->size - old_heap_size; #if 0 @@ -3011,9 +2897,6 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; set_foot(old_top, (old_size + 2*SIZE_SZ)); } } - else if (!tried_mmap) - /* We can at least try to use to mmap memory. */ - goto try_mmap; } else { /* av == main_arena */ @@ -3367,31 +3250,19 @@ munmap_chunk(p) mchunkptr p; #endif { INTERNAL_SIZE_T size = chunksize(p); + int ret; assert (chunk_is_mmapped(p)); #if 0 assert(! ((char*)p >= mp_.sbrk_base && (char*)p < mp_.sbrk_base + mp_.sbrked_mem)); assert((mp_.n_mmaps > 0)); #endif - - uintptr_t block = (uintptr_t) p - p->prev_size; - size_t total_size = p->prev_size + size; - /* Unfortunately we have to do the compilers job by hand here. Normally - we would test BLOCK and TOTAL-SIZE separately for compliance with the - page size. But gcc does not recognize the optimization possibility - (in the moment at least) so we combine the two values into one before - the bit test. */ - if (__builtin_expect (((block | total_size) & (mp_.pagesize - 1)) != 0, 0)) - { - malloc_printerr (check_action, "munmap_chunk(): invalid pointer", - chunk2mem (p)); - return; - } + assert(((p->prev_size + size) & (mp_.pagesize-1)) == 0); mp_.n_mmaps--; - mp_.mmapped_mem -= total_size; + mp_.mmapped_mem -= (size + p->prev_size); - int ret __attribute__ ((unused)) = munmap((char *)block, total_size); + ret = munmap((char *)p - p->prev_size, size + p->prev_size); /* munmap returns non-zero on failure */ assert(ret == 0); @@ -3514,14 +3385,6 @@ public_fREe(Void_t* mem) #if HAVE_MMAP if (chunk_is_mmapped(p)) /* release mmapped memory. */ { - /* see if the dynamic brk/mmap threshold needs adjusting */ - if (!mp_.no_dyn_threshold - && p->size > mp_.mmap_threshold - && p->size <= DEFAULT_MMAP_THRESHOLD_MAX) - { - mp_.mmap_threshold = chunksize (p); - mp_.trim_threshold = 2 * mp_.mmap_threshold; - } munmap_chunk(p); return; } @@ -3576,7 +3439,7 @@ public_rEALLOc(Void_t* oldmem, size_t bytes) Therefore we can exclude some size values which might appear here by accident or by "design" from some intruder. */ if (__builtin_expect ((uintptr_t) oldp > (uintptr_t) -oldsize, 0) - || __builtin_expect (misaligned_chunk (oldp), 0)) + || __builtin_expect ((uintptr_t) oldp & MALLOC_ALIGN_MASK, 0)) { malloc_printerr (check_action, "realloc(): invalid pointer", oldmem); return NULL; @@ -3626,29 +3489,6 @@ public_rEALLOc(Void_t* oldmem, size_t bytes) (void)mutex_unlock(&ar_ptr->mutex); assert(!newp || chunk_is_mmapped(mem2chunk(newp)) || ar_ptr == arena_for_chunk(mem2chunk(newp))); - - if (newp == NULL) - { - /* Try harder to allocate memory in other arenas. */ - newp = public_mALLOc(bytes); - if (newp != NULL) - { - MALLOC_COPY (newp, oldmem, oldsize - 2 * SIZE_SZ); -#if THREAD_STATS - if(!mutex_trylock(&ar_ptr->mutex)) - ++(ar_ptr->stat_lock_direct); - else { - (void)mutex_lock(&ar_ptr->mutex); - ++(ar_ptr->stat_lock_wait); - } -#else - (void)mutex_lock(&ar_ptr->mutex); -#endif - _int_free(ar_ptr, oldmem); - (void)mutex_unlock(&ar_ptr->mutex); - } - } - return newp; } #ifdef libc_hidden_def @@ -3836,18 +3676,14 @@ public_cALLOc(size_t n, size_t elem_size) /* Two optional cases in which clearing not necessary */ #if HAVE_MMAP - if (chunk_is_mmapped (p)) - { - if (__builtin_expect (perturb_byte, 0)) - MALLOC_ZERO (mem, sz); - return mem; - } + if (chunk_is_mmapped(p)) + return mem; #endif csz = chunksize(p); #if MORECORE_CLEARS - if (perturb_byte == 0 && (p == oldtop && csz > oldtopsize)) { + if (p == oldtop && csz > oldtopsize) { /* clear only the bytes from non-freshly-sbrked memory */ csz = oldtopsize; } @@ -3885,8 +3721,6 @@ public_cALLOc(size_t n, size_t elem_size) return mem; } -#ifndef _LIBC - Void_t** public_iCALLOc(size_t n, size_t elem_size, Void_t** chunks) { @@ -3917,6 +3751,8 @@ public_iCOMALLOc(size_t n, size_t sizes[], Void_t** chunks) return m; } +#ifndef _LIBC + void public_cFREe(Void_t* m) { @@ -3930,8 +3766,6 @@ public_mTRIm(size_t s) { int result; - if(__malloc_initialized < 0) - ptmalloc_init (); (void)mutex_lock(&main_arena.mutex); result = mTRIm(s); (void)mutex_unlock(&main_arena.mutex); @@ -4016,7 +3850,7 @@ _int_malloc(mstate av, size_t bytes) can try it without checking, which saves some time on this fast path. */ - if ((unsigned long)(nb) <= (unsigned long)(get_max_fast ())) { + if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) { long int idx = fastbin_index(nb); fb = &(av->fastbins[idx]); if ( (victim = *fb) != 0) { @@ -4025,10 +3859,7 @@ _int_malloc(mstate av, size_t bytes) chunk2mem (victim)); *fb = victim->fd; check_remalloced_chunk(av, victim, nb); - void *p = chunk2mem(victim); - if (__builtin_expect (perturb_byte, 0)) - alloc_perturb (p, bytes); - return p; + return chunk2mem(victim); } } @@ -4056,10 +3887,7 @@ _int_malloc(mstate av, size_t bytes) if (av != &main_arena) victim->size |= NON_MAIN_ARENA; check_malloced_chunk(av, victim, nb); - void *p = chunk2mem(victim); - if (__builtin_expect (perturb_byte, 0)) - alloc_perturb (p, bytes); - return p; + return chunk2mem(victim); } } } @@ -4096,8 +3924,6 @@ _int_malloc(mstate av, size_t bytes) for(;;) { - int iters = 0; - bool any_larger = false; while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) { bck = victim->bk; if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0) @@ -4132,10 +3958,7 @@ _int_malloc(mstate av, size_t bytes) set_foot(remainder, remainder_size); check_malloced_chunk(av, victim, nb); - void *p = chunk2mem(victim); - if (__builtin_expect (perturb_byte, 0)) - alloc_perturb (p, bytes); - return p; + return chunk2mem(victim); } /* remove from unsorted list */ @@ -4149,10 +3972,7 @@ _int_malloc(mstate av, size_t bytes) if (av != &main_arena) victim->size |= NON_MAIN_ARENA; check_malloced_chunk(av, victim, nb); - void *p = chunk2mem(victim); - if (__builtin_expect (perturb_byte, 0)) - alloc_perturb (p, bytes); - return p; + return chunk2mem(victim); } /* place chunk in bin */ @@ -4193,12 +4013,6 @@ _int_malloc(mstate av, size_t bytes) victim->fd = fwd; fwd->bk = victim; bck->fd = victim; - - if (size >= nb + MINSIZE) - any_larger = true; -#define MAX_ITERS 10000 - if (++iters >= MAX_ITERS) - break; } /* @@ -4227,28 +4041,21 @@ _int_malloc(mstate av, size_t bytes) set_inuse_bit_at_offset(victim, size); if (av != &main_arena) victim->size |= NON_MAIN_ARENA; + check_malloced_chunk(av, victim, nb); + return chunk2mem(victim); } /* Split */ else { remainder = chunk_at_offset(victim, nb); - /* We cannot assume the unsorted list is empty and therefore - have to perform a complete insert here. */ - bck = unsorted_chunks(av); - fwd = bck->fd; - remainder->bk = bck; - remainder->fd = fwd; - bck->fd = remainder; - fwd->bk = remainder; + unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; + remainder->bk = remainder->fd = unsorted_chunks(av); set_head(victim, nb | PREV_INUSE | (av != &main_arena ? NON_MAIN_ARENA : 0)); set_head(remainder, remainder_size | PREV_INUSE); set_foot(remainder, remainder_size); + check_malloced_chunk(av, victim, nb); + return chunk2mem(victim); } - check_malloced_chunk(av, victim, nb); - void *p = chunk2mem(victim); - if (__builtin_expect (perturb_byte, 0)) - alloc_perturb (p, bytes); - return p; } } @@ -4317,21 +4124,16 @@ _int_malloc(mstate av, size_t bytes) set_inuse_bit_at_offset(victim, size); if (av != &main_arena) victim->size |= NON_MAIN_ARENA; + check_malloced_chunk(av, victim, nb); + return chunk2mem(victim); } /* Split */ else { remainder = chunk_at_offset(victim, nb); - /* We cannot assume the unsorted list is empty and therefore - have to perform a complete insert here. */ - bck = unsorted_chunks(av); - fwd = bck->fd; - remainder->bk = bck; - remainder->fd = fwd; - bck->fd = remainder; - fwd->bk = remainder; - + unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; + remainder->bk = remainder->fd = unsorted_chunks(av); /* advertise as last remainder */ if (in_smallbin_range(nb)) av->last_remainder = remainder; @@ -4340,12 +4142,9 @@ _int_malloc(mstate av, size_t bytes) (av != &main_arena ? NON_MAIN_ARENA : 0)); set_head(remainder, remainder_size | PREV_INUSE); set_foot(remainder, remainder_size); + check_malloced_chunk(av, victim, nb); + return chunk2mem(victim); } - check_malloced_chunk(av, victim, nb); - void *p = chunk2mem(victim); - if (__builtin_expect (perturb_byte, 0)) - alloc_perturb (p, bytes); - return p; } } @@ -4377,10 +4176,7 @@ _int_malloc(mstate av, size_t bytes) set_head(remainder, remainder_size | PREV_INUSE); check_malloced_chunk(av, victim, nb); - void *p = chunk2mem(victim); - if (__builtin_expect (perturb_byte, 0)) - alloc_perturb (p, bytes); - return p; + return chunk2mem(victim); } /* @@ -4398,12 +4194,8 @@ _int_malloc(mstate av, size_t bytes) /* Otherwise, relay to handle system-dependent cases */ - else { - void *p = sYSMALLOc(nb, av); - if (__builtin_expect (perturb_byte, 0)) - alloc_perturb (p, bytes); - return p; - } + else + return sYSMALLOc(nb, av); } } @@ -4434,19 +4226,13 @@ _int_free(mstate av, Void_t* mem) Therefore we can exclude some size values which might appear here by accident or by "design" from some intruder. */ if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0) - || __builtin_expect (misaligned_chunk (p), 0)) + || __builtin_expect ((uintptr_t) p & MALLOC_ALIGN_MASK, 0)) { errstr = "free(): invalid pointer"; errout: malloc_printerr (check_action, errstr, mem); return; } - /* We know that each chunk is at least MINSIZE bytes in size. */ - if (__builtin_expect (size < MINSIZE, 0)) - { - errstr = "free(): invalid size"; - goto errout; - } check_inuse_chunk(av, p); @@ -4455,7 +4241,7 @@ _int_free(mstate av, Void_t* mem) and used quickly in malloc. */ - if ((unsigned long)(size) <= (unsigned long)(get_max_fast ()) + if ((unsigned long)(size) <= (unsigned long)(av->max_fast) #if TRIM_FASTBINS /* @@ -4483,10 +4269,6 @@ _int_free(mstate av, Void_t* mem) errstr = "double free or corruption (fasttop)"; goto errout; } - - if (__builtin_expect (perturb_byte, 0)) - free_perturb (mem, size - SIZE_SZ); - p->fd = *fb; *fb = p; } @@ -4528,9 +4310,6 @@ _int_free(mstate av, Void_t* mem) goto errout; } - if (__builtin_expect (perturb_byte, 0)) - free_perturb (mem, size - SIZE_SZ); - /* consolidate backward */ if (!prev_inuse(p)) { prevsize = p->prev_size; @@ -4671,7 +4450,7 @@ static void malloc_consolidate(av) mstate av; yet been initialized, in which case do so below */ - if (get_max_fast () != 0) { + if (av->max_fast != 0) { clear_fastchunks(av); unsorted_bin = unsorted_chunks(av); @@ -4684,7 +4463,7 @@ static void malloc_consolidate(av) mstate av; reused anyway. */ - maxfb = &(av->fastbins[fastbin_index(get_max_fast ())]); + maxfb = &(av->fastbins[fastbin_index(av->max_fast)]); fb = &(av->fastbins[0]); do { if ( (p = *fb) != 0) { @@ -4780,7 +4559,7 @@ _int_realloc(mstate av, Void_t* oldmem, size_t bytes) oldsize = chunksize(oldp); /* Simple tests for old block integrity. */ - if (__builtin_expect (misaligned_chunk (oldp), 0)) + if (__builtin_expect ((uintptr_t) oldp & MALLOC_ALIGN_MASK, 0)) { errstr = "realloc(): invalid pointer"; errout: @@ -4790,7 +4569,7 @@ _int_realloc(mstate av, Void_t* oldmem, size_t bytes) if (__builtin_expect (oldp->size <= 2 * SIZE_SZ, 0) || __builtin_expect (oldsize >= av->system_mem, 0)) { - errstr = "realloc(): invalid old size"; + errstr = "realloc(): invalid size"; goto errout; } @@ -5147,7 +4926,6 @@ Void_t* cALLOc(n_elements, elem_size) size_t n_elements; size_t elem_size; } #endif /* 0 */ -#ifndef _LIBC /* ------------------------- independent_calloc ------------------------- */ @@ -5311,7 +5089,6 @@ mstate av; size_t n_elements; size_t* sizes; int opts; Void_t* chunks[]; return marray; } -#endif /* _LIBC */ /* @@ -5548,7 +5325,7 @@ int mALLOPt(param_number, value) int param_number; int value; switch(param_number) { case M_MXFAST: if (value >= 0 && value <= MAX_FAST_SIZE) { - set_max_fast(value); + set_max_fast(av, value); } else res = 0; @@ -5556,12 +5333,10 @@ int mALLOPt(param_number, value) int param_number; int value; case M_TRIM_THRESHOLD: mp_.trim_threshold = value; - mp_.no_dyn_threshold = 1; break; case M_TOP_PAD: mp_.top_pad = value; - mp_.no_dyn_threshold = 1; break; case M_MMAP_THRESHOLD: @@ -5572,7 +5347,6 @@ int mALLOPt(param_number, value) int param_number; int value; else #endif mp_.mmap_threshold = value; - mp_.no_dyn_threshold = 1; break; case M_MMAP_MAX: @@ -5582,16 +5356,11 @@ int mALLOPt(param_number, value) int param_number; int value; else #endif mp_.n_mmaps_max = value; - mp_.no_dyn_threshold = 1; break; case M_CHECK_ACTION: check_action = value; break; - - case M_PERTURB: - perturb_byte = value; - break; } (void)mutex_unlock(&av->mutex); return res; @@ -5739,14 +5508,10 @@ int mALLOPt(param_number, value) int param_number; int value; /* Helper code. */ -extern char **__libc_argv attribute_hidden; - static void malloc_printerr(int action, const char *str, void *ptr) { - if ((action & 5) == 5) - __libc_message (action & 2, "%s\n", str); - else if (action & 1) + if (action & 1) { char buf[2 * sizeof (uintptr_t) + 1]; @@ -5756,8 +5521,9 @@ malloc_printerr(int action, const char *str, void *ptr) *--cp = '0'; __libc_message (action & 2, - "*** glibc detected *** %s: %s: 0x%s ***\n", - __libc_argv[0] ?: "", str, cp); + action & 4 + ? "%s\n" : "*** glibc detected *** %s: 0x%s ***\n", + str, cp); } else if (action & 2) abort (); diff --git a/malloc/malloc.h b/malloc/malloc.h index 1340aa15bc..753539e7b0 100644 --- a/malloc/malloc.h +++ b/malloc/malloc.h @@ -1,5 +1,5 @@ /* Prototypes and definition for malloc implementation. - Copyright (C) 1996,97,99,2000,2002-2004,2005 Free Software Foundation, Inc. + Copyright (C) 1996,97,99,2000,2002,2003,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -20,16 +20,59 @@ #ifndef _MALLOC_H #define _MALLOC_H 1 +#ifdef _LIBC #include -#include +#endif + +/* + $Id$ + `ptmalloc2', a malloc implementation for multiple threads without + lock contention, by Wolfram Gloger . + + VERSION 2.7.0 + + This work is mainly derived from malloc-2.7.0 by Doug Lea + , which is available from: + + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + + This trimmed-down header file only provides function prototypes and + the exported data structures. For more detailed function + descriptions and compile-time options, see the source file + `malloc.c'. +*/ + +#if defined(__STDC__) || defined (__cplusplus) +# include # define __malloc_ptr_t void * +#else +# undef size_t +# define size_t unsigned int +# undef ptrdiff_t +# define ptrdiff_t int +# define __malloc_ptr_t char * +#endif +#ifdef _LIBC /* Used by GNU libc internals. */ -#define __malloc_size_t size_t -#define __malloc_ptrdiff_t ptrdiff_t +# define __malloc_size_t size_t +# define __malloc_ptrdiff_t ptrdiff_t +#elif !defined __attribute_malloc__ +# define __attribute_malloc__ +#endif #ifdef __GNUC__ +/* GCC can always grok prototypes. For C++ programs we add throw() + to help it optimize the function calls. But this works only with + gcc 2.8.x and egcs. */ +# ifndef __THROW +# if defined __cplusplus && (__GNUC__ >= 3 || __GNUC_MINOR__ >= 8) +# define __THROW throw () +# else +# define __THROW +# endif +# endif # define __MALLOC_P(args) args __THROW /* This macro will be used for functions which might take C++ callback functions. */ @@ -37,51 +80,78 @@ #else /* Not GCC. */ -# define __MALLOC_P(args) args -# define __MALLOC_PMT(args) args +# define __THROW + +# if (defined __STDC__ && __STDC__) || defined __cplusplus + +# define __MALLOC_P(args) args +# define __MALLOC_PMT(args) args + +# ifndef __const +# define __const const +# endif + +# else /* Not ANSI C or C++. */ + +# define __MALLOC_P(args) () /* No prototypes. */ +# define __MALLOC_PMT(args) () + +# ifndef __const +# define __const +# endif + +# endif /* ANSI C or C++. */ #endif /* GCC. */ +#ifndef NULL +# ifdef __cplusplus +# define NULL 0 +# else +# define NULL ((__malloc_ptr_t) 0) +# endif +#endif -__BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif /* Allocate SIZE bytes of memory. */ -extern void *malloc __MALLOC_P ((size_t __size)) __attribute_malloc__ __wur; +extern __malloc_ptr_t malloc __MALLOC_P ((size_t __size)) __attribute_malloc__; /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ -extern void *calloc __MALLOC_P ((size_t __nmemb, size_t __size)) - __attribute_malloc__ __wur; +extern __malloc_ptr_t calloc __MALLOC_P ((size_t __nmemb, size_t __size)) + __attribute_malloc__; /* Re-allocate the previously allocated block in __ptr, making the new block SIZE bytes long. */ -extern void *realloc __MALLOC_P ((void *__ptr, size_t __size)) - __attribute_malloc__ __attribute_warn_unused_result__; +extern __malloc_ptr_t realloc __MALLOC_P ((__malloc_ptr_t __ptr, + size_t __size)) + __attribute_malloc__; /* Free a block allocated by `malloc', `realloc' or `calloc'. */ -extern void free __MALLOC_P ((void *__ptr)); +extern void free __MALLOC_P ((__malloc_ptr_t __ptr)); /* Free a block allocated by `calloc'. */ -extern void cfree __MALLOC_P ((void *__ptr)); +extern void cfree __MALLOC_P ((__malloc_ptr_t __ptr)); /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ -extern void *memalign __MALLOC_P ((size_t __alignment, size_t __size)) - __attribute_malloc__ __wur; +extern __malloc_ptr_t memalign __MALLOC_P ((size_t __alignment, size_t __size)); /* Allocate SIZE bytes on a page boundary. */ -extern void *valloc __MALLOC_P ((size_t __size)) - __attribute_malloc__ __wur; +extern __malloc_ptr_t valloc __MALLOC_P ((size_t __size)) __attribute_malloc__; /* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up __size to nearest pagesize. */ -extern void * pvalloc __MALLOC_P ((size_t __size)) - __attribute_malloc__ __wur; +extern __malloc_ptr_t pvalloc __MALLOC_P ((size_t __size)) + __attribute_malloc__; /* Underlying allocation function; successive calls should return contiguous pieces of memory. */ -extern void *(*__morecore) __MALLOC_PMT ((ptrdiff_t __size)); +extern __malloc_ptr_t (*__morecore) __MALLOC_PMT ((ptrdiff_t __size)); /* Default value of `__morecore'. */ -extern void *__default_morecore __MALLOC_P ((ptrdiff_t __size)) +extern __malloc_ptr_t __default_morecore __MALLOC_P ((ptrdiff_t __size)) __attribute_malloc__; /* SVID2/XPG mallinfo structure */ @@ -122,7 +192,6 @@ extern struct mallinfo mallinfo __MALLOC_P ((void)); #define M_MMAP_THRESHOLD -3 #define M_MMAP_MAX -4 #define M_CHECK_ACTION -5 -#define M_PERTURB -6 /* General SVID/XPG interface to tunable parameters. */ extern int mallopt __MALLOC_P ((int __param, int __val)); @@ -133,38 +202,41 @@ extern int malloc_trim __MALLOC_P ((size_t __pad)); /* Report the number of usable allocated bytes associated with allocated chunk __ptr. */ -extern size_t malloc_usable_size __MALLOC_P ((void *__ptr)); +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 void *malloc_get_state __MALLOC_P ((void)); +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 ((void *__ptr)); +extern int malloc_set_state __MALLOC_P ((__malloc_ptr_t __ptr)); /* Called once when malloc is initialized; redefining this variable in the application provides the preferred way to set up the hook pointers. */ extern void (*__malloc_initialize_hook) __MALLOC_PMT ((void)); /* Hooks for debugging and user-defined versions. */ -extern void (*__free_hook) __MALLOC_PMT ((void *__ptr, +extern void (*__free_hook) __MALLOC_PMT ((__malloc_ptr_t __ptr, __const __malloc_ptr_t)); -extern void *(*__malloc_hook) __MALLOC_PMT ((size_t __size, - __const __malloc_ptr_t)); -extern void *(*__realloc_hook) __MALLOC_PMT ((void *__ptr, size_t __size, - __const __malloc_ptr_t)); -extern void *(*__memalign_hook) __MALLOC_PMT ((size_t __alignment, - size_t __size, - __const __malloc_ptr_t)); +extern __malloc_ptr_t (*__malloc_hook) __MALLOC_PMT ((size_t __size, + __const __malloc_ptr_t)); +extern __malloc_ptr_t (*__realloc_hook) __MALLOC_PMT ((__malloc_ptr_t __ptr, + size_t __size, + __const __malloc_ptr_t)); +extern __malloc_ptr_t (*__memalign_hook) __MALLOC_PMT ((size_t __alignment, + size_t __size, + __const __malloc_ptr_t)); extern void (*__after_morecore_hook) __MALLOC_PMT ((void)); /* Activate a standard set of debugging hooks. */ extern void __malloc_check_init __MALLOC_P ((void)); -__END_DECLS +#ifdef __cplusplus +} /* end of extern "C" */ +#endif #endif /* malloc.h */ diff --git a/malloc/mcheck.c b/malloc/mcheck.c index 9f88843445..02379d219d 100644 --- a/malloc/mcheck.c +++ b/malloc/mcheck.c @@ -24,25 +24,9 @@ # include # include # include -# include # include #endif -#ifdef _LIBC -extern __typeof (malloc) __libc_malloc; -extern __typeof (free) __libc_free; -extern __typeof (realloc) __libc_realloc; -libc_hidden_proto (__libc_malloc) -libc_hidden_proto (__libc_realloc) -libc_hidden_proto (__libc_free) -libc_hidden_proto (__libc_memalign) -#else -# define __libc_malloc(sz) malloc (sz) -# define __libc_free(ptr) free (ptr) -# define __libc_realloc(ptr, sz) realloc (ptr, sz) -# define __libc_memalign(al, sz) memalign (al, sz) -#endif - /* Old hook values. */ static void (*old_free_hook) (__ptr_t ptr, __const __ptr_t); static __ptr_t (*old_malloc_hook) (__malloc_size_t size, const __ptr_t); @@ -213,7 +197,7 @@ freehook (__ptr_t ptr, const __ptr_t caller) if (old_free_hook != NULL) (*old_free_hook) (ptr, caller); else - __libc_free (ptr); + free (ptr); __free_hook = freehook; } @@ -230,7 +214,7 @@ mallochook (__malloc_size_t size, const __ptr_t caller) hdr = (struct hdr *) (*old_malloc_hook) (sizeof (struct hdr) + size + 1, caller); else - hdr = (struct hdr *) __libc_malloc (sizeof (struct hdr) + size + 1); + hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1); __malloc_hook = mallochook; if (hdr == NULL) return NULL; @@ -261,7 +245,7 @@ memalignhook (__malloc_size_t alignment, __malloc_size_t size, if (old_memalign_hook != NULL) block = (*old_memalign_hook) (alignment, slop + size + 1, caller); else - block = __libc_memalign (alignment, slop + size + 1); + block = memalign (alignment, slop + size + 1); __memalign_hook = memalignhook; if (block == NULL) return NULL; @@ -310,8 +294,8 @@ reallochook (__ptr_t ptr, __malloc_size_t size, const __ptr_t caller) sizeof (struct hdr) + size + 1, caller); else - hdr = (struct hdr *) __libc_realloc ((__ptr_t) hdr, - sizeof (struct hdr) + size + 1); + hdr = (struct hdr *) realloc ((__ptr_t) hdr, + sizeof (struct hdr) + size + 1); __free_hook = freehook; __malloc_hook = mallochook; __memalign_hook = memalignhook; @@ -371,8 +355,8 @@ mcheck (func) if (__malloc_initialized <= 0 && !mcheck_used) { /* We call malloc() once here to ensure it is initialized. */ - void *p = __libc_malloc (0); - __libc_free (p); + void *p = malloc (0); + free (p); old_free_hook = __free_hook; __free_hook = freehook; diff --git a/malloc/memusage.c b/malloc/memusage.c index 16fa09060a..b552ec37b0 100644 --- a/malloc/memusage.c +++ b/malloc/memusage.c @@ -1,5 +1,5 @@ /* Profile heap and stack memory usage of running program. - Copyright (C) 1998-2002, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. @@ -18,13 +18,11 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include #include #include #include #include #include -#include #include #include #include @@ -45,7 +43,7 @@ static void (*freep) (void *); static void *(*mmapp) (void *, size_t, int, int, int, off_t); static void *(*mmap64p) (void *, size_t, int, int, int, off64_t); static int (*munmapp) (void *, size_t); -static void *(*mremapp) (void *, size_t, size_t, int, void *); +static void *(*mremapp) (void *, size_t, size_t, int); enum { @@ -71,23 +69,24 @@ struct header #define MAGIC 0xfeedbeaf -static memusage_cntr_t calls[idx_last]; -static memusage_cntr_t failed[idx_last]; -static memusage_size_t total[idx_last]; -static memusage_size_t grand_total; -static memusage_cntr_t histogram[65536 / 16]; -static memusage_cntr_t large; -static memusage_cntr_t calls_total; -static memusage_cntr_t inplace; -static memusage_cntr_t decreasing; -static memusage_cntr_t realloc_free; -static memusage_cntr_t inplace_mremap; -static memusage_cntr_t decreasing_mremap; -static memusage_size_t current_heap; -static memusage_size_t peak_use[3]; -static __thread uintptr_t start_sp; +static unsigned long int calls[idx_last]; +static unsigned long int failed[idx_last]; +static unsigned long long int total[idx_last]; +static unsigned long long int grand_total; +static unsigned long int histogram[65536 / 16]; +static unsigned long int large; +static unsigned long int calls_total; +static unsigned long int inplace; +static unsigned long int decreasing; +static unsigned long int inplace_mremap; +static unsigned long int decreasing_mremap; +static long int current_use[2]; +static long int peak_use[3]; +static uintptr_t start_sp; /* A few macros to make the source more readable. */ +#define current_heap current_use[0] +#define current_stack current_use[1] #define peak_heap peak_use[0] #define peak_stack peak_use[1] #define peak_total peak_use[2] @@ -104,14 +103,14 @@ extern const char *__progname; struct entry { - uint64_t heap; - uint64_t stack; + size_t heap; + size_t stack; uint32_t time_low; uint32_t time_high; }; -static struct entry buffer[2 * DEFAULT_BUFFER_SIZE]; -static uatomic32_t buffer_cnt; +static struct entry buffer[DEFAULT_BUFFER_SIZE]; +static size_t buffer_cnt; static struct entry first; @@ -119,6 +118,8 @@ static struct entry first; static void update_data (struct header *result, size_t len, size_t old_len) { + long int total_use; + if (result != NULL) { /* Record the information we need and mark the block using a @@ -128,60 +129,38 @@ update_data (struct header *result, size_t len, size_t old_len) } /* Compute current heap usage and compare it with the maximum value. */ - memusage_size_t heap - = atomic_exchange_and_add (¤t_heap, len - old_len) + len - old_len; - atomic_max (&peak_heap, heap); - - /* Compute current stack usage and compare it with the maximum - value. The base stack pointer might not be set if this is not - the main thread and it is the first call to any of these - functions. */ - if (__builtin_expect (!start_sp, 0)) - start_sp = GETSP (); - - uintptr_t sp = GETSP (); + current_heap += len - old_len; + if (current_heap > peak_heap) + peak_heap = current_heap; + + /* Compute current stack usage and compare it with the maximum value. */ #ifdef STACK_GROWS_UPWARD - /* This can happen in threads where we didn't catch the thread's - stack early enough. */ - if (__builtin_expect (sp < start_sp, 0)) - start_sp = sp; - size_t current_stack = sp - start_sp; + current_stack = GETSP () - start_sp; #else - /* This can happen in threads where we didn't catch the thread's - stack early enough. */ - if (__builtin_expect (sp > start_sp, 0)) - start_sp = sp; - size_t current_stack = start_sp - sp; + current_stack = start_sp - GETSP (); #endif - atomic_max (&peak_stack, current_stack); + if (current_stack > peak_stack) + peak_stack = current_stack; /* Add up heap and stack usage and compare it with the maximum value. */ - atomic_max (&peak_total, heap + current_stack); + total_use = current_heap + current_stack; + if (total_use > peak_total) + peak_total = total_use; /* Store the value only if we are writing to a file. */ if (fd != -1) { - uatomic32_t idx = atomic_exchange_and_add (&buffer_cnt, 1); - if (idx >= 2 * buffer_size) - { - /* We try to reset the counter to the correct range. If - this fails because of another thread increasing the - counter it does not matter since that thread will take - care of the correction. */ - unsigned int reset = idx - 2 * buffer_size; - atomic_compare_and_exchange_val_acq (&buffer_size, reset, idx); - idx = reset; - } - - buffer[idx].heap = current_heap; - buffer[idx].stack = current_stack; - GETTIME (buffer[idx].time_low, buffer[idx].time_high); + buffer[buffer_cnt].heap = current_heap; + buffer[buffer_cnt].stack = current_stack; + GETTIME (buffer[buffer_cnt].time_low, buffer[buffer_cnt].time_high); + ++buffer_cnt; /* Write out buffer if it is full. */ - if (idx + 1 == buffer_size) - write (fd, buffer, buffer_size * sizeof (struct entry)); - else if (idx + 1 == 2 * buffer_size) - write (fd, &buffer[buffer_size], buffer_size * sizeof (struct entry)); + if (buffer_cnt == buffer_size) + { + write (fd, buffer, buffer_cnt * sizeof (struct entry)); + buffer_cnt = 0; + } } } @@ -228,8 +207,8 @@ me (void) mmap64p = (void *(*) (void *, size_t, int, int, int, off64_t)) dlsym (RTLD_NEXT, "mmap64"); - mremapp = (void *(*) (void *, size_t, size_t, int, void *)) dlsym (RTLD_NEXT, - "mremap"); + mremapp = (void *(*) (void *, size_t, size_t, int)) dlsym (RTLD_NEXT, + "mremap"); munmapp = (int (*) (void *, size_t)) dlsym (RTLD_NEXT, "munmap"); initialized = 1; @@ -268,7 +247,6 @@ me (void) GETTIME (first.time_low, first.time_high); /* Write it two times since we need the starting and end time. */ write (fd, &first, sizeof (first)); - write (fd, &first, sizeof (first)); /* Determine the buffer size. We use the default if the environment variable is not present. */ @@ -339,24 +317,24 @@ malloc (size_t len) return (*mallocp) (len); /* Keep track of number of calls. */ - atomic_increment (&calls[idx_malloc]); + ++calls[idx_malloc]; /* Keep track of total memory consumption for `malloc'. */ - atomic_add (&total[idx_malloc], len); + total[idx_malloc] += len; /* Keep track of total memory requirement. */ - atomic_add (&grand_total, len); + grand_total += len; /* Remember the size of the request. */ if (len < 65536) - atomic_increment (&histogram[len / 16]); + ++histogram[len / 16]; else - atomic_increment (&large); + ++large; /* Total number of calls of any of the functions. */ - atomic_increment (&calls_total); + ++calls_total; /* Do the real work. */ result = (struct header *) (*mallocp) (len + sizeof (struct header)); if (result == NULL) { - atomic_increment (&failed[idx_malloc]); + ++failed[idx_malloc]; return NULL; } @@ -405,53 +383,36 @@ realloc (void *old, size_t len) } /* Keep track of number of calls. */ - atomic_increment (&calls[idx_realloc]); + ++calls[idx_realloc]; if (len > old_len) { /* Keep track of total memory consumption for `realloc'. */ - atomic_add (&total[idx_realloc], len - old_len); + total[idx_realloc] += len - old_len; /* Keep track of total memory requirement. */ - atomic_add (&grand_total, len - old_len); - } - - if (len == 0 && old != NULL) - { - /* Special case. */ - atomic_increment (&realloc_free); - /* Keep track of total memory freed using `free'. */ - atomic_add (&total[idx_free], real->length); - - /* Update the allocation data and write out the records if necessary. */ - update_data (NULL, 0, old_len); - - /* Do the real work. */ - (*freep) (real); - - return NULL; + grand_total += len - old_len; } - /* Remember the size of the request. */ if (len < 65536) - atomic_increment (&histogram[len / 16]); + ++histogram[len / 16]; else - atomic_increment (&large); + ++large; /* Total number of calls of any of the functions. */ - atomic_increment (&calls_total); + ++calls_total; /* Do the real work. */ result = (struct header *) (*reallocp) (real, len + sizeof (struct header)); if (result == NULL) { - atomic_increment (&failed[idx_realloc]); + ++failed[idx_realloc]; return NULL; } /* Record whether the reduction/increase happened in place. */ if (real == result) - atomic_increment (&inplace); + ++inplace; /* Was the buffer increased? */ if (old_len > len) - atomic_increment (&decreasing); + ++decreasing; /* Update the allocation data and write out the records if necessary. */ update_data (result, len, old_len); @@ -482,16 +443,16 @@ calloc (size_t n, size_t len) return (*callocp) (n, len); /* Keep track of number of calls. */ - atomic_increment (&calls[idx_calloc]); + ++calls[idx_calloc]; /* Keep track of total memory consumption for `calloc'. */ - atomic_add (&total[idx_calloc], size); + total[idx_calloc] += size; /* Keep track of total memory requirement. */ - atomic_add (&grand_total, size); + grand_total += size; /* Remember the size of the request. */ if (size < 65536) - atomic_increment (&histogram[size / 16]); + ++histogram[size / 16]; else - atomic_increment (&large); + ++large; /* Total number of calls of any of the functions. */ ++calls_total; @@ -499,7 +460,7 @@ calloc (size_t n, size_t len) result = (struct header *) (*mallocp) (size + sizeof (struct header)); if (result == NULL) { - atomic_increment (&failed[idx_calloc]); + ++failed[idx_calloc]; return NULL; } @@ -536,7 +497,7 @@ free (void *ptr) /* `free (NULL)' has no effect. */ if (ptr == NULL) { - atomic_increment (&calls[idx_free]); + ++calls[idx_free]; return; } @@ -550,9 +511,9 @@ free (void *ptr) } /* Keep track of number of calls. */ - atomic_increment (&calls[idx_free]); + ++calls[idx_free]; /* Keep track of total memory freed using `free'. */ - atomic_add (&total[idx_free], real->length); + total[idx_free] += real->length; /* Update the allocation data and write out the records if necessary. */ update_data (NULL, 0, real->length); @@ -586,22 +547,22 @@ mmap (void *start, size_t len, int prot, int flags, int fd, off_t offset) ? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r); /* Keep track of number of calls. */ - atomic_increment (&calls[idx]); + ++calls[idx]; /* Keep track of total memory consumption for `malloc'. */ - atomic_add (&total[idx], len); + total[idx] += len; /* Keep track of total memory requirement. */ - atomic_add (&grand_total, len); + grand_total += len; /* Remember the size of the request. */ if (len < 65536) - atomic_increment (&histogram[len / 16]); + ++histogram[len / 16]; else - atomic_increment (&large); + ++large; /* Total number of calls of any of the functions. */ - atomic_increment (&calls_total); + ++calls_total; /* Check for failures. */ if (result == NULL) - atomic_increment (&failed[idx]); + ++failed[idx]; else if (idx == idx_mmap_w) /* Update the allocation data and write out the records if necessary. Note the first parameter is NULL which means @@ -638,22 +599,22 @@ mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset) ? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r); /* Keep track of number of calls. */ - atomic_increment (&calls[idx]); + ++calls[idx]; /* Keep track of total memory consumption for `malloc'. */ - atomic_add (&total[idx], len); + total[idx] += len; /* Keep track of total memory requirement. */ - atomic_add (&grand_total, len); + grand_total += len; /* Remember the size of the request. */ if (len < 65536) - atomic_increment (&histogram[len / 16]); + ++histogram[len / 16]; else - atomic_increment (&large); + ++large; /* Total number of calls of any of the functions. */ - atomic_increment (&calls_total); + ++calls_total; /* Check for failures. */ if (result == NULL) - atomic_increment (&failed[idx]); + ++failed[idx]; else if (idx == idx_mmap_w) /* Update the allocation data and write out the records if necessary. Note the first parameter is NULL which means @@ -669,14 +630,9 @@ mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset) /* `mmap' replacement. We do not have to keep track of the sizesince `munmap' will get it as a parameter. */ void * -mremap (void *start, size_t old_len, size_t len, int flags, ...) +mremap (void *start, size_t old_len, size_t len, int flags) { void *result = NULL; - va_list ap; - - va_start (ap, flags); - void *newaddr = (flags & MREMAP_FIXED) ? va_arg (ap, void *) : NULL; - va_end (ap); /* Determine real implementation if not already happened. */ if (__builtin_expect (initialized <= 0, 0)) @@ -687,38 +643,38 @@ mremap (void *start, size_t old_len, size_t len, int flags, ...) } /* Always get a block. We don't need extra memory. */ - result = (*mremapp) (start, old_len, len, flags, newaddr); + result = (*mremapp) (start, old_len, len, flags); if (!not_me && trace_mmap) { /* Keep track of number of calls. */ - atomic_increment (&calls[idx_mremap]); + ++calls[idx_mremap]; if (len > old_len) { /* Keep track of total memory consumption for `malloc'. */ - atomic_add (&total[idx_mremap], len - old_len); + total[idx_mremap] += len - old_len; /* Keep track of total memory requirement. */ - atomic_add (&grand_total, len - old_len); + grand_total += len - old_len; } /* Remember the size of the request. */ if (len < 65536) - atomic_increment (&histogram[len / 16]); + ++histogram[len / 16]; else - atomic_increment (&large); + ++large; /* Total number of calls of any of the functions. */ - atomic_increment (&calls_total); + ++calls_total; /* Check for failures. */ if (result == NULL) - atomic_increment (&failed[idx_mremap]); + ++failed[idx_mremap]; else { /* Record whether the reduction/increase happened in place. */ if (start == result) - atomic_increment (&inplace_mremap); + ++inplace_mremap; /* Was the buffer increased? */ if (old_len > len) - atomic_increment (&decreasing_mremap); + ++decreasing_mremap; /* Update the allocation data and write out the records if necessary. Note the first parameter is NULL which means @@ -752,19 +708,19 @@ munmap (void *start, size_t len) if (!not_me && trace_mmap) { /* Keep track of number of calls. */ - atomic_increment (&calls[idx_munmap]); + ++calls[idx_munmap]; if (__builtin_expect (result == 0, 1)) { /* Keep track of total memory freed using `free'. */ - atomic_add (&total[idx_munmap], len); + total[idx_munmap] += len; /* Update the allocation data and write out the records if necessary. */ update_data (NULL, 0, len); } else - atomic_increment (&failed[idx_munmap]); + ++failed[idx_munmap]; } return result; @@ -789,12 +745,7 @@ dest (void) if (fd != -1) { /* Write the partially filled buffer. */ - if (buffer_cnt > buffer_size) - write (fd, buffer + buffer_size, - (buffer_cnt - buffer_size) * sizeof (struct entry)); - else - write (fd, buffer, buffer_cnt * sizeof (struct entry)); - + write (fd, buffer, buffer_cnt * sizeof (struct entry)); /* Go back to the beginning of the file. We allocated two records here when we opened the file. */ lseek (fd, 0, SEEK_SET); @@ -818,58 +769,38 @@ dest (void) \e[01;32mMemory usage summary:\e[0;0m heap total: %llu, heap peak: %lu, stack peak: %lu\n\ \e[04;34m total calls total memory failed calls\e[0m\n\ \e[00;34m malloc|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\ -\e[00;34mrealloc|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove:%ld, dec:%ld, free:%ld)\n\ +\e[00;34mrealloc|\e[0m %10lu %12llu %s%12lu\e[00;00m (in place: %ld, dec: %ld)\n\ \e[00;34m calloc|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\ \e[00;34m free|\e[0m %10lu %12llu\n", - (unsigned long long int) grand_total, (unsigned long int) peak_heap, + grand_total, (unsigned long int) peak_heap, (unsigned long int) peak_stack, - (unsigned long int) calls[idx_malloc], - (unsigned long long int) total[idx_malloc], - failed[idx_malloc] ? "\e[01;41m" : "", - (unsigned long int) failed[idx_malloc], - (unsigned long int) calls[idx_realloc], - (unsigned long long int) total[idx_realloc], - failed[idx_realloc] ? "\e[01;41m" : "", - (unsigned long int) failed[idx_realloc], - (unsigned long int) inplace, - (unsigned long int) decreasing, - (unsigned long int) realloc_free, - (unsigned long int) calls[idx_calloc], - (unsigned long long int) total[idx_calloc], - failed[idx_calloc] ? "\e[01;41m" : "", - (unsigned long int) failed[idx_calloc], - (unsigned long int) calls[idx_free], - (unsigned long long int) total[idx_free]); + calls[idx_malloc], total[idx_malloc], + failed[idx_malloc] ? "\e[01;41m" : "", failed[idx_malloc], + calls[idx_realloc], total[idx_realloc], + failed[idx_realloc] ? "\e[01;41m" : "", failed[idx_realloc], + inplace, decreasing, + calls[idx_calloc], total[idx_calloc], + failed[idx_calloc] ? "\e[01;41m" : "", failed[idx_calloc], + calls[idx_free], total[idx_free]); if (trace_mmap) fprintf (stderr, "\ \e[00;34mmmap(r)|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\ \e[00;34mmmap(w)|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\ \e[00;34mmmap(a)|\e[0m %10lu %12llu %s%12lu\e[00;00m\n\ -\e[00;34m mremap|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove: %ld, dec:%ld)\n\ +\e[00;34m mremap|\e[0m %10lu %12llu %s%12lu\e[00;00m (in place: %ld, dec: %ld)\n\ \e[00;34m munmap|\e[0m %10lu %12llu %s%12lu\e[00;00m\n", - (unsigned long int) calls[idx_mmap_r], - (unsigned long long int) total[idx_mmap_r], - failed[idx_mmap_r] ? "\e[01;41m" : "", - (unsigned long int) failed[idx_mmap_r], - (unsigned long int) calls[idx_mmap_w], - (unsigned long long int) total[idx_mmap_w], - failed[idx_mmap_w] ? "\e[01;41m" : "", - (unsigned long int) failed[idx_mmap_w], - (unsigned long int) calls[idx_mmap_a], - (unsigned long long int) total[idx_mmap_a], - failed[idx_mmap_a] ? "\e[01;41m" : "", - (unsigned long int) failed[idx_mmap_a], - (unsigned long int) calls[idx_mremap], - (unsigned long long int) total[idx_mremap], - failed[idx_mremap] ? "\e[01;41m" : "", - (unsigned long int) failed[idx_mremap], - (unsigned long int) inplace_mremap, - (unsigned long int) decreasing_mremap, - (unsigned long int) calls[idx_munmap], - (unsigned long long int) total[idx_munmap], - failed[idx_munmap] ? "\e[01;41m" : "", - (unsigned long int) failed[idx_munmap]); + calls[idx_mmap_r], total[idx_mmap_r], + failed[idx_mmap_r] ? "\e[01;41m" : "", failed[idx_mmap_r], + calls[idx_mmap_w], total[idx_mmap_w], + failed[idx_mmap_w] ? "\e[01;41m" : "", failed[idx_mmap_w], + calls[idx_mmap_a], total[idx_mmap_a], + failed[idx_mmap_a] ? "\e[01;41m" : "", failed[idx_mmap_a], + calls[idx_mremap], total[idx_mremap], + failed[idx_mremap] ? "\e[01;41m" : "", failed[idx_mremap], + inplace_mremap, decreasing_mremap, + calls[idx_munmap], total[idx_munmap], + failed[idx_munmap] ? "\e[01;41m" : "", failed[idx_munmap]); /* Write out a histoogram of the sizes of the allocations. */ fprintf (stderr, "\e[01;32mHistogram for block sizes:\e[0;0m\n"); @@ -886,7 +817,7 @@ dest (void) { percent = (histogram[cnt / 16] * 100) / calls_total; fprintf (stderr, "%5d-%-5d%12lu ", cnt, cnt + 15, - (unsigned long int) histogram[cnt / 16]); + histogram[cnt / 16]); if (percent == 0) fputs (" <1% \e[41;37m", stderr); else @@ -903,7 +834,7 @@ dest (void) if (large != 0) { percent = (large * 100) / calls_total; - fprintf (stderr, " large %12lu ", (unsigned long int) large); + fprintf (stderr, " large %12lu ", large); if (percent == 0) fputs (" <1% \e[41;37m", stderr); else @@ -913,10 +844,4 @@ dest (void) fputc ('=', stderr); fputs ("\e[0;0m\n", stderr); } - - /* Any following malloc/free etc. calls should generate statistics again, - because otherwise freeing something that has been malloced before - this destructor (including struct header in front of it) wouldn't - be properly freed. */ - not_me = false; } diff --git a/malloc/memusage.sh b/malloc/memusage.sh index 47f8cc22ff..be8f755a20 100755 --- a/malloc/memusage.sh +++ b/malloc/memusage.sh @@ -1,5 +1,5 @@ #! @BASH@ -# Copyright (C) 1999-2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper , 1999. @@ -18,8 +18,8 @@ # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. -memusageso='@SLIBDIR@/libmemusage.so' -memusagestat='@BINDIR@/memusagestat' +memusageso=@SLIBDIR@/libmemusage.so +memusagestat=@BINDIR@/memusagestat TEXTDOMAIN=libc # Print usage message. @@ -71,21 +71,12 @@ do_version() { printf $"Copyright (C) %s Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -" "2006" +" "2004" printf $"Written by %s. " "Ulrich Drepper" exit 0 } -# These variables are local -buffer= -data= -memusagestat_args= -notimer= -png= -progname= -tracemmap= - # Process arguments. But stop as soon as the program name is found. while test $# -gt 0; do case "$1" in @@ -222,8 +213,15 @@ datafile= if test -n "$data"; then datafile="$data" elif test -n "$png"; then - datafile=$(mktemp -t memusage.XXXXXX) || exit - trap 'rm -f "$datafile"; exit 1' HUP INT QUIT TERM PIPE + datafile=$(mktemp ${TMPDIR:-/tmp}/memusage.XXXXXX 2> /dev/null) + if test $? -ne 0; then + # Lame, but if there is no `mktemp' program the user cannot expect more. + if test "$RANDOM" != "$RANDOM"; then + datafile=${TMPDIR:-/tmp}/memusage.$RANDOM + else + datafile=${TMPDIR:-/tmp}/memusage.$$ + fi + fi fi if test -n "$datafile"; then add_env="$add_env MEMUSAGE_OUTPUT=$datafile" diff --git a/malloc/memusagestat.c b/malloc/memusagestat.c index 8a74ec8dcf..b1cad9b251 100644 --- a/malloc/memusagestat.c +++ b/malloc/memusagestat.c @@ -1,20 +1,22 @@ /* Generate graphic from memory profiling data. - Copyright (C) 1998, 1999, 2000, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #define _FILE_OFFSET_BITS 64 @@ -81,8 +83,8 @@ static struct argp argp = struct entry { - uint64_t heap; - uint64_t stack; + size_t heap; + size_t stack; uint32_t time_low; uint32_t time_high; }; @@ -277,16 +279,16 @@ main (int argc, char *argv[]) gdImageString (im_out, gdFontSmall, 38, ysize - 14, (unsigned char *) "0", blue); - snprintf (buf, sizeof (buf), heap_format, 0); + snprintf(buf, sizeof (buf), heap_format, 0); gdImageString (im_out, gdFontSmall, maxsize_heap < 1024 ? 32 : 26, - ysize - 26, (unsigned char *) buf, red); - snprintf (buf, sizeof (buf), stack_format, 0); + ysize - 26, buf, red); + snprintf(buf, sizeof (buf), stack_format, 0); gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26, - (unsigned char *) buf, green); + buf, green); if (string != NULL) gdImageString (im_out, gdFontLarge, (xsize - strlen (string) * 8) / 2, - 2, (unsigned char *) string, green); + 2, (char *) string, green); gdImageStringUp (im_out, gdFontSmall, 1, ysize / 2 - 10, (unsigned char *) "allocated", red); @@ -299,11 +301,9 @@ main (int argc, char *argv[]) (unsigned char *) "stack", green); snprintf (buf, sizeof (buf), heap_format, maxsize_heap / heap_scale); - gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14, - (unsigned char *) buf, red); + gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14, buf, red); snprintf (buf, sizeof (buf), stack_format, maxsize_stack / stack_scale); - gdImageString (im_out, gdFontSmall, xsize - 37, 14, - (unsigned char *) buf, green); + gdImageString (im_out, gdFontSmall, xsize - 37, 14, buf, green); for (line = 1; line <= 3; ++line) { @@ -311,10 +311,10 @@ main (int argc, char *argv[]) (maxsize_heap / heap_scale); gdImageDashedLine (im_out, 40, ysize - 20 - cnt, xsize - 40, ysize - 20 - cnt, red); - snprintf (buf, sizeof (buf), heap_format, maxsize_heap / 4 * line / + snprintf (buf, sizeof (buf), heap_format, maxsize_heap / 4 * line / heap_scale); gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, - ysize - 26 - cnt, (unsigned char *) buf, red); + ysize - 26 - cnt, buf, red); cnt2 = ((ysize - 40) * (maxsize_stack / 4 * line / stack_scale)) / (maxsize_stack / stack_scale); @@ -324,12 +324,11 @@ main (int argc, char *argv[]) snprintf (buf, sizeof (buf), stack_format, maxsize_stack / 4 * line / stack_scale); gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26 - cnt2, - (unsigned char *) buf, green); + buf, green); } snprintf (buf, sizeof (buf), "%llu", (unsigned long long) total); - gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14, - (unsigned char *) buf, blue); + gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14, buf, blue); if (!time_based) { diff --git a/malloc/morecore.c b/malloc/morecore.c deleted file mode 100644 index 0a66ef5a85..0000000000 --- a/malloc/morecore.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 1991,92,93,94,95,97,2002,2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _MALLOC_INTERNAL -#define _MALLOC_INTERNAL -#include -#endif - -#ifndef __GNU_LIBRARY__ -#define __sbrk sbrk -#endif - -#ifdef __GNU_LIBRARY__ -/* It is best not to declare this and cast its result on foreign operating - systems with potentially hostile include files. */ - -#include -#include -extern __malloc_ptr_t __sbrk (ptrdiff_t increment) __THROW; -libc_hidden_proto (__sbrk) -#endif - -#ifndef NULL -#define NULL 0 -#endif - -/* Allocate INCREMENT more bytes of data space, - and return the start of data space, or NULL on errors. - If INCREMENT is negative, shrink data space. */ -__malloc_ptr_t -__default_morecore (increment) - __malloc_ptrdiff_t increment; -{ - __malloc_ptr_t result = (__malloc_ptr_t) __sbrk (increment); - if (result == (__malloc_ptr_t) -1) - return NULL; - return result; -} -libc_hidden_def (__default_morecore) diff --git a/malloc/mtrace.c b/malloc/mtrace.c index 139ebc8153..1a9522b09d 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -40,18 +40,6 @@ # include # define setvbuf(s, b, f, l) INTUSE(_IO_setvbuf) (s, b, f, l) # define fwrite(buf, size, count, fp) _IO_fwrite (buf, size, count, fp) -extern __typeof (malloc) __libc_malloc; -extern __typeof (free) __libc_free; -extern __typeof (realloc) __libc_realloc; -libc_hidden_proto (__libc_malloc) -libc_hidden_proto (__libc_realloc) -libc_hidden_proto (__libc_free) -libc_hidden_proto (__libc_memalign) -#else -# define __libc_malloc(sz) malloc (sz) -# define __libc_free(ptr) free (ptr) -# define __libc_realloc(ptr, sz) realloc (ptr, sz) -# define __libc_memalign(al, sz) memalign (al, sz) #endif #ifndef attribute_hidden @@ -166,7 +154,7 @@ tr_freehook (ptr, caller) if (tr_old_free_hook != NULL) (*tr_old_free_hook) (ptr, caller); else - __libc_free (ptr); + free (ptr); __free_hook = tr_freehook; __libc_lock_unlock (lock); } @@ -185,7 +173,7 @@ tr_mallochook (size, caller) if (tr_old_malloc_hook != NULL) hdr = (__ptr_t) (*tr_old_malloc_hook) (size, caller); else - hdr = (__ptr_t) __libc_malloc (size); + hdr = (__ptr_t) malloc (size); __malloc_hook = tr_mallochook; tr_where (caller); @@ -221,7 +209,7 @@ tr_reallochook (ptr, size, caller) if (tr_old_realloc_hook != NULL) hdr = (__ptr_t) (*tr_old_realloc_hook) (ptr, size, caller); else - hdr = (__ptr_t) __libc_realloc (ptr, size); + hdr = (__ptr_t) realloc (ptr, size); __free_hook = tr_freehook; __malloc_hook = tr_mallochook; __realloc_hook = tr_reallochook; @@ -263,7 +251,7 @@ tr_memalignhook (alignment, size, caller) if (tr_old_memalign_hook != NULL) hdr = (__ptr_t) (*tr_old_memalign_hook) (alignment, size, caller); else - hdr = (__ptr_t) __libc_memalign (alignment, size); + hdr = (__ptr_t) memalign (alignment, size); __memalign_hook = tr_memalignhook; __malloc_hook = tr_mallochook; diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl index 8a0fbc7e95..1640fa652d 100644 --- a/malloc/mtrace.pl +++ b/malloc/mtrace.pl @@ -1,7 +1,7 @@ #! @PERL@ eval "exec @PERL@ -S $0 $*" if 0; -# Copyright (C) 1997-2004, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 1997-2002, 2003, 2004 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper , 1997. # Based on the mtrace.awk script. @@ -45,7 +45,7 @@ arglist: while (@ARGV) { $ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" || $ARGV[0] eq "--versio" || $ARGV[0] eq "--version") { print "mtrace (GNU $PACKAGE) $VERSION\n"; - print "Copyright (C) 2006 Free Software Foundation, Inc.\n"; + print "Copyright (C) 2004 Free Software Foundation, Inc.\n"; print "This is free software; see the source for copying conditions. There is NO\n"; print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"; print "Written by Ulrich Drepper \n"; diff --git a/malloc/obstack.c b/malloc/obstack.c index 75440d9c79..fddda3ec5b 100644 --- a/malloc/obstack.c +++ b/malloc/obstack.c @@ -1,7 +1,8 @@ /* obstack.c - subroutines used implicitly by object stack macros - Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. - This file is part of the GNU C Library. + Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, + 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,9 +16,8 @@ You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ - + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #ifdef HAVE_CONFIG_H # include @@ -52,38 +52,22 @@ # endif #endif -#include +#if defined _LIBC && defined USE_IN_LIBIO +# include +#endif #ifndef ELIDE_CODE -# if HAVE_INTTYPES_H -# include -# endif -# if HAVE_STDINT_H || defined _LIBC -# include -# endif - /* Determine default alignment. */ -union fooround -{ - uintmax_t i; - long double d; - void *p; -}; -struct fooalign -{ - char c; - union fooround u; -}; +struct fooalign {char x; double d;}; +# define DEFAULT_ALIGNMENT \ + ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0)) /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. But in fact it might be less smart and round addresses to as much as DEFAULT_ROUNDING. So we prepare for it to do that. */ -enum - { - DEFAULT_ALIGNMENT = offsetof (struct fooalign, u), - DEFAULT_ROUNDING = sizeof (union fooround) - }; +union fooround {long x; double d;}; +# define DEFAULT_ROUNDING (sizeof (union fooround)) /* When we copy a long block of data, this is the unit to do it with. On some machines, copying successive ints does not work; @@ -159,7 +143,7 @@ _obstack_begin (struct obstack *h, register struct _obstack_chunk *chunk; /* points to new chunk */ if (alignment == 0) - alignment = DEFAULT_ALIGNMENT; + alignment = (int) DEFAULT_ALIGNMENT; if (size == 0) /* Default size is what GNU malloc can fit in a 4096-byte block. */ { @@ -186,8 +170,7 @@ _obstack_begin (struct obstack *h, chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); if (!chunk) (*obstack_alloc_failed_handler) (); - h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, - alignment - 1); + h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; @@ -206,7 +189,7 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment, register struct _obstack_chunk *chunk; /* points to new chunk */ if (alignment == 0) - alignment = DEFAULT_ALIGNMENT; + alignment = (int) DEFAULT_ALIGNMENT; if (size == 0) /* Default size is what GNU malloc can fit in a 4096-byte block. */ { @@ -234,8 +217,7 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment, chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); if (!chunk) (*obstack_alloc_failed_handler) (); - h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, - alignment - 1); + h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; @@ -277,7 +259,8 @@ _obstack_newchunk (struct obstack *h, int length) /* Compute an aligned object_base in the new chunk */ object_base = - __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask); + __INT_TO_PTR ((__PTR_TO_INT (new_chunk->contents) + h->alignment_mask) + & ~ (h->alignment_mask)); /* Move the existing object to the new chunk. Word at a time is fast and is safe if the object @@ -302,10 +285,7 @@ _obstack_newchunk (struct obstack *h, int length) /* If the object just copied was the only data in OLD_CHUNK, free that chunk and remove it from the chain. But not if that chunk might contain an empty object. */ - if (! h->maybe_empty_object - && (h->object_base - == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, - h->alignment_mask))) + if (h->object_base == old_chunk->contents && ! h->maybe_empty_object) { new_chunk->prev = old_chunk->prev; CALL_FREEFUN (h, old_chunk); @@ -430,11 +410,12 @@ print_and_abort (void) happen because the "memory exhausted" message appears in other places like this and the translation should be reused instead of creating a very similar string which requires a separate translation. */ -# ifdef _LIBC - (void) __fxprintf (NULL, "%s\n", _("memory exhausted")); -# else - fprintf (stderr, "%s\n", _("memory exhausted")); +# if defined _LIBC && defined USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s\n", _("memory exhausted")); + else # endif + fprintf (stderr, "%s\n", _("memory exhausted")); exit (obstack_exit_failure); } diff --git a/malloc/obstack.h b/malloc/obstack.h index 206fe55050..d18ef40b6e 100644 --- a/malloc/obstack.h +++ b/malloc/obstack.h @@ -1,7 +1,7 @@ /* obstack.h - object stack macros - Copyright (C) 1988-1994,1996-1999,2003,2004,2005 - Free Software Foundation, Inc. - This file is part of the GNU C Library. + Copyright (C) 1988-1994,1996-1999,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,8 +15,8 @@ You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ /* Summary: @@ -110,7 +110,19 @@ Summary: extern "C" { #endif -/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is +/* We use subtraction of (char *) 0 instead of casting to int + because on word-addressable machines a simple cast to int + may ignore the byte-within-word field of the pointer. */ + +#ifndef __PTR_TO_INT +# define __PTR_TO_INT(P) ((P) - (char *) 0) +#endif + +#ifndef __INT_TO_PTR +# define __INT_TO_PTR(P) ((P) + (char *) 0) +#endif + +/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is defined, as with GNU C, use that; that way we don't pollute the namespace with 's symbols. Otherwise, include and use ptrdiff_t. */ @@ -122,23 +134,6 @@ extern "C" { # define PTR_INT_TYPE ptrdiff_t #endif -/* If B is the base of an object addressed by P, return the result of - aligning P to the next multiple of A + 1. B and P must be of type - char *. A + 1 must be a power of 2. */ - -#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) - -/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case - where pointers can be converted to integers, aligned as integers, - and converted back again. If PTR_INT_TYPE is narrower than a - pointer (e.g., the AS/400), play it safe and compute the alignment - relative to B. Otherwise, use the faster strategy of computing the - alignment relative to 0. */ - -#define __PTR_ALIGN(B, P, A) \ - __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \ - P, A) - #include struct _obstack_chunk /* Lives at front of each chunk. */ @@ -155,11 +150,7 @@ struct obstack /* control current object in current chunk */ char *object_base; /* address of object we are building */ char *next_free; /* where to add next char to current object */ char *chunk_limit; /* address of char after current chunk */ - union - { - PTR_INT_TYPE tempint; - void *tempptr; - } temp; /* Temporary for some macros. */ + PTR_INT_TYPE temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ /* These prototypes vary based on `use_extra_arg', and we use casts to the prototypeless function type in all assignments, @@ -284,10 +275,7 @@ __extension__ \ # define obstack_empty_p(OBSTACK) \ __extension__ \ ({ struct obstack const *__o = (OBSTACK); \ - (__o->chunk->prev == 0 \ - && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ - __o->chunk->contents, \ - __o->alignment_mask)); }) + (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); }) # define obstack_grow(OBSTACK,where,length) \ __extension__ \ @@ -386,8 +374,8 @@ __extension__ \ if (__o1->next_free == __value) \ __o1->maybe_empty_object = 1; \ __o1->next_free \ - = __PTR_ALIGN (__o1->object_base, __o1->next_free, \ - __o1->alignment_mask); \ + = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ + & ~ (__o1->alignment_mask)); \ if (__o1->next_free - (char *)__o1->chunk \ > __o1->chunk_limit - (char *)__o1->chunk) \ __o1->next_free = __o1->chunk_limit; \ @@ -411,10 +399,7 @@ __extension__ \ (unsigned) ((h)->chunk_limit - (h)->next_free) # define obstack_empty_p(h) \ - ((h)->chunk->prev == 0 \ - && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ - (h)->chunk->contents, \ - (h)->alignment_mask)) + ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0) /* Note that the call to _obstack_newchunk is enclosed in (..., 0) so that we can avoid having void expressions @@ -423,23 +408,23 @@ __extension__ \ but some compilers won't accept it. */ # define obstack_make_room(h,length) \ -( (h)->temp.tempint = (length), \ - (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0)) +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0)) # define obstack_grow(h,where,length) \ -( (h)->temp.tempint = (length), \ - (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ - memcpy ((h)->next_free, where, (h)->temp.tempint), \ - (h)->next_free += (h)->temp.tempint) +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp), \ + (h)->next_free += (h)->temp) # define obstack_grow0(h,where,length) \ -( (h)->temp.tempint = (length), \ - (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \ - memcpy ((h)->next_free, where, (h)->temp.tempint), \ - (h)->next_free += (h)->temp.tempint, \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp), \ + (h)->next_free += (h)->temp, \ *((h)->next_free)++ = 0) # define obstack_1grow(h,datum) \ @@ -461,13 +446,13 @@ __extension__ \ (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr)) # define obstack_int_grow_fast(h,aint) \ - (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint)) + (((int *) ((h)->next_free += sizeof (int)))[-1] = (aptr)) # define obstack_blank(h,length) \ -( (h)->temp.tempint = (length), \ - (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \ - ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ - obstack_blank_fast (h, (h)->temp.tempint)) +( (h)->temp = (length), \ + (((h)->chunk_limit - (h)->next_free < (h)->temp) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ + obstack_blank_fast (h, (h)->temp)) # define obstack_alloc(h,length) \ (obstack_blank ((h), (length)), obstack_finish ((h))) @@ -482,23 +467,22 @@ __extension__ \ ( ((h)->next_free == (h)->object_base \ ? (((h)->maybe_empty_object = 1), 0) \ : 0), \ - (h)->temp.tempptr = (h)->object_base, \ + (h)->temp = __PTR_TO_INT ((h)->object_base), \ (h)->next_free \ - = __PTR_ALIGN ((h)->object_base, (h)->next_free, \ - (h)->alignment_mask), \ + = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ + & ~ ((h)->alignment_mask)), \ (((h)->next_free - (char *) (h)->chunk \ > (h)->chunk_limit - (char *) (h)->chunk) \ ? ((h)->next_free = (h)->chunk_limit) : 0), \ (h)->object_base = (h)->next_free, \ - (h)->temp.tempptr) + (void *) __INT_TO_PTR ((h)->temp)) # define obstack_free(h,obj) \ -( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \ - ((((h)->temp.tempint > 0 \ - && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \ +( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ + (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ? (int) ((h)->next_free = (h)->object_base \ - = (h)->temp.tempint + (char *) (h)->chunk) \ - : (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0))) + = (h)->temp + (char *) (h)->chunk) \ + : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) #endif /* not __GNUC__ or not __STDC__ */ diff --git a/malloc/tst-malloc.c b/malloc/tst-malloc.c index 81d279236c..d555ae46ef 100644 --- a/malloc/tst-malloc.c +++ b/malloc/tst-malloc.c @@ -33,7 +33,7 @@ merror (const char *msg) int main (void) { - void *p, *q; + void *p; int save; errno = 0; @@ -64,15 +64,5 @@ main (void) if (p != NULL) merror ("realloc (p, 0) failed."); - p = malloc (513 * 1024); - if (p == NULL) - merror ("malloc (513K) failed."); - - q = malloc (-512 * 1024); - if (q != NULL) - merror ("malloc (-512K) succeeded."); - - free (p); - return errors != 0; } diff --git a/malloc/tst-mallocfork.c b/malloc/tst-mallocfork.c deleted file mode 100644 index f90ce94887..0000000000 --- a/malloc/tst-mallocfork.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Derived from the test case in - http://sourceware.org/bugzilla/show_bug.cgi?id=838. */ -#include -#include -#include -#include -#include -#include -#include - -static void -sig_handler (int signum) -{ - pid_t child = fork (); - if (child == 0) - exit (0); - TEMP_FAILURE_RETRY (waitpid (child, NULL, 0)); -} - -static int -do_test (void) -{ - pid_t parent = getpid (); - - struct sigaction action = { .sa_handler = sig_handler }; - sigemptyset (&action.sa_mask); - - malloc (sizeof (int)); - - if (sigaction (SIGALRM, &action, NULL) != 0) - { - puts ("sigaction failed"); - return 1; - } - - /* Create a child that sends the signal to be caught. */ - pid_t child = fork (); - if (child == 0) - { - if (kill (parent, SIGALRM) == -1) - perror ("kill"); - exit (0); - } - - TEMP_FAILURE_RETRY (waitpid (child, NULL, 0)); - - return 0; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" diff --git a/malloc/tst-mcheck.c b/malloc/tst-mcheck.c deleted file mode 100644 index 16784912a9..0000000000 --- a/malloc/tst-mcheck.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek , 2005. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include - -static int errors = 0; - -static void -merror (const char *msg) -{ - ++errors; - printf ("Error: %s\n", msg); -} - -int -main (void) -{ - void *p, *q; - - errno = 0; - - p = malloc (-1); - - if (p != NULL) - merror ("malloc (-1) succeeded."); - else if (errno != ENOMEM) - merror ("errno is not set correctly."); - - p = malloc (10); - if (p == NULL) - merror ("malloc (10) failed."); - - p = realloc (p, 0); - if (p != NULL) - merror ("realloc (p, 0) failed."); - - p = malloc (0); - if (p == NULL) - merror ("malloc (0) failed."); - - p = realloc (p, 0); - if (p != NULL) - merror ("realloc (p, 0) failed."); - - q = malloc (256); - if (q == NULL) - merror ("malloc (256) failed."); - - p = malloc (512); - if (p == NULL) - merror ("malloc (512) failed."); - - if (realloc (p, -256) != NULL) - merror ("realloc (p, -256) succeeded."); - else if (errno != ENOMEM) - merror ("errno is not set correctly."); - - free (p); - - p = malloc (512); - if (p == NULL) - merror ("malloc (512) failed."); - - if (realloc (p, -1) != NULL) - merror ("realloc (p, -1) succeeded."); - else if (errno != ENOMEM) - merror ("errno is not set correctly."); - - free (p); - free (q); - - return errors != 0; -} diff --git a/malloc/tst-mtrace.sh b/malloc/tst-mtrace.sh index 771689a273..d4fee2a357 100755 --- a/malloc/tst-mtrace.sh +++ b/malloc/tst-mtrace.sh @@ -1,6 +1,6 @@ #! /bin/sh # Testing the mtrace function. -# Copyright (C) 2000, 2005 Free Software Foundation, Inc. +# Copyright (C) 2000 Free Software Foundation, Inc. # This file is part of the GNU C Library. # @@ -30,7 +30,8 @@ ${common_objpfx}elf/ld.so --library-path $common_objpfx \ ${common_objpfx}malloc/tst-mtrace || status=1 if test $status -eq 0 && test -f ${common_objpfx}malloc/mtrace; then - ${common_objpfx}malloc/mtrace ${common_objpfx}malloc/tst-mtrace.leak \ + ${common_objpfx}malloc/mtrace ${common_objpfx}malloc/tst-mtrace \ + ${common_objpfx}malloc/tst-mtrace.leak \ > ${common_objpfx}malloc/tst-mtrace.out|| status=1 fi -- cgit 1.4.1