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:
@@ -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
|
||||
|
179
malloc/arena.c
179
malloc/arena.c
@@ -1,6 +1,5 @@
|
||||
/* Malloc implementation for multiple threads without lock contention.
|
||||
Copyright (C) 2001,2002,2003,2004,2005,2006,2007
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Wolfram Gloger <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 */
|
||||
|
||||
/*
|
||||
|
@@ -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)
|
||||
|
374
malloc/malloc.c
374
malloc/malloc.c
@@ -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 ();
|
||||
|
144
malloc/malloc.h
144
malloc/malloc.h
@@ -1,5 +1,5 @@
|
||||
/* Prototypes and definition for malloc implementation.
|
||||
Copyright (C) 1996,97,99,2000,2002-2004,2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996,97,99,2000,2002,2003,2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -20,16 +20,59 @@
|
||||
#ifndef _MALLOC_H
|
||||
#define _MALLOC_H 1
|
||||
|
||||
#ifdef _LIBC
|
||||
#include <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 */
|
||||
|
@@ -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;
|
||||
|
@@ -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 (¤t_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;
|
||||
}
|
||||
|
@@ -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"
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
@@ -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;
|
||||
|
||||
|
@@ -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";
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
114
malloc/obstack.h
114
malloc/obstack.h
@@ -1,7 +1,7 @@
|
||||
/* obstack.h - object stack macros
|
||||
Copyright (C) 1988-1994,1996-1999,2003,2004,2005
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Copyright (C) 1988-1994,1996-1999,2003,2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library. Its master source is NOT part of
|
||||
the C library, however. The master source lives in /gd/gnu/lib.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@@ -15,8 +15,8 @@
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Summary:
|
||||
|
||||
@@ -110,7 +110,19 @@ Summary:
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
|
||||
/* We use subtraction of (char *) 0 instead of casting to int
|
||||
because on word-addressable machines a simple cast to int
|
||||
may ignore the byte-within-word field of the pointer. */
|
||||
|
||||
#ifndef __PTR_TO_INT
|
||||
# define __PTR_TO_INT(P) ((P) - (char *) 0)
|
||||
#endif
|
||||
|
||||
#ifndef __INT_TO_PTR
|
||||
# define __INT_TO_PTR(P) ((P) + (char *) 0)
|
||||
#endif
|
||||
|
||||
/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is
|
||||
defined, as with GNU C, use that; that way we don't pollute the
|
||||
namespace with <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__ */
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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"
|
@@ -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;
|
||||
}
|
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user