1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-08 17:42:12 +03:00

(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.

This commit is contained in:
Ulrich Drepper
2004-12-22 20:10:10 +00:00
parent 0ecb606cb6
commit a334319f65
6215 changed files with 304673 additions and 494300 deletions

View File

@@ -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

View File

@@ -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 <wg@malloc.de>, 2001.
@@ -19,17 +18,13 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdbool.h>
/* $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 <stdbool.h>
/* 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 */
/*

View File

@@ -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 <wg@malloc.de>, 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<NFASTBINS; ++i)
main_arena.fastbins[i] = 0;
for (i=0; i<BINMAPSIZE; ++i)

View File

@@ -1,5 +1,5 @@
/* Malloc implementation for multiple threads without lock contention.
Copyright (C) 1996-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
/* Malloc implementation for multiple threads without lock contention.
Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Wolfram Gloger <wg@malloc.de>
and Doug Lea <dl@cs.oswego.edu>, 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 <stdio-common/_itoa.h>
#include <bits/wordsize.h>
#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] ?: "<unknown>", str, cp);
action & 4
? "%s\n" : "*** glibc detected *** %s: 0x%s ***\n",
str, cp);
}
else if (action & 2)
abort ();

View File

@@ -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 <features.h>
#include <stddef.h>
# define __malloc_ptr_t void *
#endif
/*
$Id$
`ptmalloc2', a malloc implementation for multiple threads without
lock contention, by Wolfram Gloger <wg@malloc.de>.
VERSION 2.7.0
This work is mainly derived from malloc-2.7.0 by Doug Lea
<dl@cs.oswego.edu>, 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 <stddef.h>
# 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 */

View File

@@ -24,25 +24,9 @@
# include <mcheck.h>
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
# include <libintl.h>
#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;

View File

@@ -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 <drepper@cygnus.com>, 1998.
@@ -18,13 +18,11 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <atomic.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -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 (&current_heap, len - old_len) + len - old_len;
atomic_max (&peak_heap, heap);
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. 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 ();
/* 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);
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;
}
/* 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;
}

View File

@@ -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 <drepper@gnu.org>, 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"

View File

@@ -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 <drepper@cygnus.com>, 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)
{

View File

@@ -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 <malloc.h>
#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 <stddef.h>
#include <stdlib.h>
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)

View File

@@ -40,18 +40,6 @@
# include <libio/iolibio.h>
# 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;

View File

@@ -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 <drepper@gnu.org>, 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 <drepper\@gnu.org>\n";

View File

@@ -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 <config.h>
@@ -52,38 +52,22 @@
# endif
#endif
#include <stddef.h>
#if defined _LIBC && defined USE_IN_LIBIO
# include <wchar.h>
#endif
#ifndef ELIDE_CODE
# if HAVE_INTTYPES_H
# include <inttypes.h>
# endif
# if HAVE_STDINT_H || defined _LIBC
# include <stdint.h>
# 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);
}

View File

@@ -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 <stddef.h>'s symbols. Otherwise, include <stddef.h>
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 <string.h>
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__ */

View File

@@ -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;
}

View File

@@ -1,51 +0,0 @@
/* Derived from the test case in
http://sourceware.org/bugzilla/show_bug.cgi?id=838. */
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
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"

View File

@@ -1,91 +0,0 @@
/* Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
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;
}

View File

@@ -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