mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 12:30:06 +00:00
Reformat malloc to gnu style.
This commit is contained in:
parent
9a3c6a6ff6
commit
6c8dbf00f5
34
ChangeLog
34
ChangeLog
@ -1,3 +1,37 @@
|
||||
2013-01-02 Ondřej Bílka <neleai@seznam.cz>
|
||||
|
||||
* malloc/arena.c (malloc_atfork, free_atfork, ptmalloc_lock_all,
|
||||
ptmalloc_unlock_all, ptmalloc_unlock_all2, next_env_entry,
|
||||
__failing_morecore, ptmalloc_init, dump_heap, new_heap, grow_heap,
|
||||
heap_trim, _int_new_arena, get_free_list, reused_arena, arena_get2):
|
||||
Convert to GNU style.
|
||||
* malloc/hooks.c (memalign_hook_ini, __malloc_check_init,
|
||||
mem2mem_check, mem2chunk_check, top_check, realloc_check,
|
||||
memalign_check, __malloc_set_state): Likewise.
|
||||
* malloc/mallocbug.c (main): Likewise.
|
||||
* malloc/malloc.c (__malloc_assert, malloc_init_state, free_perturb,
|
||||
do_check_malloced_chunk, do_check_malloc_state, sysmalloc, systrim,
|
||||
mremap_chunk, __libc_malloc, __libc_free, __libc_realloc, _mid_memalign,
|
||||
_int_malloc, malloc_consolidate, _int_realloc, _int_memalign, mtrim,
|
||||
musable, __libc_mallopt, __posix_memalign, malloc_info): Likewise.
|
||||
* malloc/malloc.h: Likewise.
|
||||
* malloc/mcheck.c (checkhdr, unlink_blk, link_blk, freehook, mallochook,
|
||||
memalignhook, reallochook, mabort): Likewise.
|
||||
* malloc/mcheck.h: Likewise.
|
||||
* malloc/memusage.c (update_data, me, malloc, realloc, calloc, free, mmap,
|
||||
mmap64, mremap, munmap, dest): Likewise.
|
||||
* malloc/memusagestat.c (main, parse_opt, more_help): Likewise.
|
||||
* malloc/morecore.c (__default_morecore): Likewise.
|
||||
* malloc/mtrace.c (tr_break, lock_and_info, mtrace): Likewise.
|
||||
* malloc/obstack.c (_obstack_begin, _obstack_newchunk,
|
||||
_obstack_allocated_p, obstack_free, _obstack_memory_used,
|
||||
print_and_abort): Likewise.
|
||||
* malloc/obstack.h: Likewise.
|
||||
* malloc/set-freeres.c (__libc_freeres): Likewise.
|
||||
* malloc/tst-mallocstate.c (main): Likewise.
|
||||
* malloc/tst-mtrace.c (main): Likewise.
|
||||
* malloc/tst-realloc.c (do_test): Likewise.
|
||||
|
||||
2013-01-02 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
[BZ #16366]
|
||||
|
785
malloc/arena.c
785
malloc/arena.c
File diff suppressed because it is too large
Load Diff
642
malloc/hooks.c
642
malloc/hooks.c
@ -24,29 +24,29 @@
|
||||
/* Hooks for debugging versions. The initial hooks just call the
|
||||
initialization routine, then do the normal work. */
|
||||
|
||||
static void*
|
||||
malloc_hook_ini(size_t sz, const void *caller)
|
||||
static void *
|
||||
malloc_hook_ini (size_t sz, const void *caller)
|
||||
{
|
||||
__malloc_hook = NULL;
|
||||
ptmalloc_init();
|
||||
return __libc_malloc(sz);
|
||||
ptmalloc_init ();
|
||||
return __libc_malloc (sz);
|
||||
}
|
||||
|
||||
static void*
|
||||
realloc_hook_ini(void* ptr, size_t sz, const void *caller)
|
||||
static void *
|
||||
realloc_hook_ini (void *ptr, size_t sz, const void *caller)
|
||||
{
|
||||
__malloc_hook = NULL;
|
||||
__realloc_hook = NULL;
|
||||
ptmalloc_init();
|
||||
return __libc_realloc(ptr, sz);
|
||||
ptmalloc_init ();
|
||||
return __libc_realloc (ptr, sz);
|
||||
}
|
||||
|
||||
static void*
|
||||
memalign_hook_ini(size_t alignment, size_t sz, const void *caller)
|
||||
static void *
|
||||
memalign_hook_ini (size_t alignment, size_t sz, const void *caller)
|
||||
{
|
||||
__memalign_hook = NULL;
|
||||
ptmalloc_init();
|
||||
return __libc_memalign(alignment, sz);
|
||||
ptmalloc_init ();
|
||||
return __libc_memalign (alignment, sz);
|
||||
}
|
||||
|
||||
/* Whether we are using malloc checking. */
|
||||
@ -71,10 +71,11 @@ static int disallow_malloc_check;
|
||||
void
|
||||
__malloc_check_init (void)
|
||||
{
|
||||
if (disallow_malloc_check) {
|
||||
disallow_malloc_check = 0;
|
||||
return;
|
||||
}
|
||||
if (disallow_malloc_check)
|
||||
{
|
||||
disallow_malloc_check = 0;
|
||||
return;
|
||||
}
|
||||
using_malloc_checking = 1;
|
||||
__malloc_hook = malloc_check;
|
||||
__free_hook = free_check;
|
||||
@ -87,7 +88,7 @@ __malloc_check_init (void)
|
||||
overruns. The goal here is to avoid obscure crashes due to invalid
|
||||
usage, unlike in the MALLOC_DEBUG code. */
|
||||
|
||||
#define MAGICBYTE(p) ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF )
|
||||
#define MAGICBYTE(p) ((((size_t) p >> 3) ^ ((size_t) p >> 11)) & 0xFF)
|
||||
|
||||
/* Visualize the chunk as being partitioned into blocks of 256 bytes from the
|
||||
highest address of the chunk, downwards. The beginning of each block tells
|
||||
@ -96,53 +97,58 @@ __malloc_check_init (void)
|
||||
must reach it with this iteration, otherwise we have witnessed a memory
|
||||
corruption. */
|
||||
static size_t
|
||||
malloc_check_get_size(mchunkptr p)
|
||||
malloc_check_get_size (mchunkptr p)
|
||||
{
|
||||
size_t size;
|
||||
unsigned char c;
|
||||
unsigned char magic = MAGICBYTE(p);
|
||||
unsigned char magic = MAGICBYTE (p);
|
||||
|
||||
assert(using_malloc_checking == 1);
|
||||
assert (using_malloc_checking == 1);
|
||||
|
||||
for (size = chunksize(p) - 1 + (chunk_is_mmapped(p) ? 0 : SIZE_SZ);
|
||||
(c = ((unsigned char*)p)[size]) != magic;
|
||||
size -= c) {
|
||||
if(c<=0 || size<(c+2*SIZE_SZ)) {
|
||||
malloc_printerr(check_action, "malloc_check_get_size: memory corruption",
|
||||
chunk2mem(p));
|
||||
return 0;
|
||||
for (size = chunksize (p) - 1 + (chunk_is_mmapped (p) ? 0 : SIZE_SZ);
|
||||
(c = ((unsigned char *) p)[size]) != magic;
|
||||
size -= c)
|
||||
{
|
||||
if (c <= 0 || size < (c + 2 * SIZE_SZ))
|
||||
{
|
||||
malloc_printerr (check_action, "malloc_check_get_size: memory corruption",
|
||||
chunk2mem (p));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* chunk2mem size. */
|
||||
return size - 2*SIZE_SZ;
|
||||
return size - 2 * SIZE_SZ;
|
||||
}
|
||||
|
||||
/* Instrument a chunk with overrun detector byte(s) and convert it
|
||||
into a user pointer with requested size sz. */
|
||||
|
||||
static void*
|
||||
static void *
|
||||
internal_function
|
||||
mem2mem_check(void *ptr, size_t sz)
|
||||
mem2mem_check (void *ptr, size_t sz)
|
||||
{
|
||||
mchunkptr p;
|
||||
unsigned char* m_ptr = ptr;
|
||||
unsigned char *m_ptr = ptr;
|
||||
size_t i;
|
||||
|
||||
if (!ptr)
|
||||
return ptr;
|
||||
p = mem2chunk(ptr);
|
||||
for(i = chunksize(p) - (chunk_is_mmapped(p) ? 2*SIZE_SZ+1 : SIZE_SZ+1);
|
||||
i > sz;
|
||||
i -= 0xFF) {
|
||||
if(i-sz < 0x100) {
|
||||
m_ptr[i] = (unsigned char)(i-sz);
|
||||
break;
|
||||
|
||||
p = mem2chunk (ptr);
|
||||
for (i = chunksize (p) - (chunk_is_mmapped (p) ? 2 * SIZE_SZ + 1 : SIZE_SZ + 1);
|
||||
i > sz;
|
||||
i -= 0xFF)
|
||||
{
|
||||
if (i - sz < 0x100)
|
||||
{
|
||||
m_ptr[i] = (unsigned char) (i - sz);
|
||||
break;
|
||||
}
|
||||
m_ptr[i] = 0xFF;
|
||||
}
|
||||
m_ptr[i] = 0xFF;
|
||||
}
|
||||
m_ptr[sz] = MAGICBYTE(p);
|
||||
return (void*)m_ptr;
|
||||
m_ptr[sz] = MAGICBYTE (p);
|
||||
return (void *) m_ptr;
|
||||
}
|
||||
|
||||
/* Convert a pointer to be free()d or realloc()ed to a valid chunk
|
||||
@ -150,53 +156,64 @@ mem2mem_check(void *ptr, size_t sz)
|
||||
|
||||
static mchunkptr
|
||||
internal_function
|
||||
mem2chunk_check(void* mem, unsigned char **magic_p)
|
||||
mem2chunk_check (void *mem, unsigned char **magic_p)
|
||||
{
|
||||
mchunkptr p;
|
||||
INTERNAL_SIZE_T sz, c;
|
||||
unsigned char magic;
|
||||
|
||||
if(!aligned_OK(mem)) return NULL;
|
||||
p = mem2chunk(mem);
|
||||
if (!chunk_is_mmapped(p)) {
|
||||
/* Must be a chunk in conventional heap memory. */
|
||||
int contig = contiguous(&main_arena);
|
||||
sz = chunksize(p);
|
||||
if((contig &&
|
||||
((char*)p<mp_.sbrk_base ||
|
||||
((char*)p + sz)>=(mp_.sbrk_base+main_arena.system_mem) )) ||
|
||||
sz<MINSIZE || sz&MALLOC_ALIGN_MASK || !inuse(p) ||
|
||||
( !prev_inuse(p) && (p->prev_size&MALLOC_ALIGN_MASK ||
|
||||
(contig && (char*)prev_chunk(p)<mp_.sbrk_base) ||
|
||||
next_chunk(prev_chunk(p))!=p) ))
|
||||
return NULL;
|
||||
magic = MAGICBYTE(p);
|
||||
for(sz += SIZE_SZ-1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
|
||||
if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
|
||||
}
|
||||
} else {
|
||||
unsigned long offset, page_mask = GLRO(dl_pagesize)-1;
|
||||
if (!aligned_OK (mem))
|
||||
return NULL;
|
||||
|
||||
/* mmap()ed chunks have MALLOC_ALIGNMENT or higher power-of-two
|
||||
alignment relative to the beginning of a page. Check this
|
||||
first. */
|
||||
offset = (unsigned long)mem & page_mask;
|
||||
if((offset!=MALLOC_ALIGNMENT && offset!=0 && offset!=0x10 &&
|
||||
offset!=0x20 && offset!=0x40 && offset!=0x80 && offset!=0x100 &&
|
||||
offset!=0x200 && offset!=0x400 && offset!=0x800 && offset!=0x1000 &&
|
||||
offset<0x2000) ||
|
||||
!chunk_is_mmapped(p) || (p->size & PREV_INUSE) ||
|
||||
( (((unsigned long)p - p->prev_size) & page_mask) != 0 ) ||
|
||||
( (sz = chunksize(p)), ((p->prev_size + sz) & page_mask) != 0 ) )
|
||||
return NULL;
|
||||
magic = MAGICBYTE(p);
|
||||
for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
|
||||
if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
|
||||
p = mem2chunk (mem);
|
||||
if (!chunk_is_mmapped (p))
|
||||
{
|
||||
/* Must be a chunk in conventional heap memory. */
|
||||
int contig = contiguous (&main_arena);
|
||||
sz = chunksize (p);
|
||||
if ((contig &&
|
||||
((char *) p < mp_.sbrk_base ||
|
||||
((char *) p + sz) >= (mp_.sbrk_base + main_arena.system_mem))) ||
|
||||
sz < MINSIZE || sz & MALLOC_ALIGN_MASK || !inuse (p) ||
|
||||
(!prev_inuse (p) && (p->prev_size & MALLOC_ALIGN_MASK ||
|
||||
(contig && (char *) prev_chunk (p) < mp_.sbrk_base) ||
|
||||
next_chunk (prev_chunk (p)) != p)))
|
||||
return NULL;
|
||||
|
||||
magic = MAGICBYTE (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 = GLRO (dl_pagesize) - 1;
|
||||
|
||||
/* mmap()ed chunks have MALLOC_ALIGNMENT or higher power-of-two
|
||||
alignment relative to the beginning of a page. Check this
|
||||
first. */
|
||||
offset = (unsigned long) mem & page_mask;
|
||||
if ((offset != MALLOC_ALIGNMENT && offset != 0 && offset != 0x10 &&
|
||||
offset != 0x20 && offset != 0x40 && offset != 0x80 && offset != 0x100 &&
|
||||
offset != 0x200 && offset != 0x400 && offset != 0x800 && offset != 0x1000 &&
|
||||
offset < 0x2000) ||
|
||||
!chunk_is_mmapped (p) || (p->size & PREV_INUSE) ||
|
||||
((((unsigned long) p - p->prev_size) & page_mask) != 0) ||
|
||||
((sz = chunksize (p)), ((p->prev_size + sz) & page_mask) != 0))
|
||||
return NULL;
|
||||
|
||||
magic = MAGICBYTE (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;
|
||||
if (magic_p)
|
||||
*magic_p = (unsigned char *)p + sz;
|
||||
*magic_p = (unsigned char *) p + sz;
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -205,32 +222,32 @@ mem2chunk_check(void* mem, unsigned char **magic_p)
|
||||
|
||||
static int
|
||||
internal_function
|
||||
top_check(void)
|
||||
top_check (void)
|
||||
{
|
||||
mchunkptr t = top(&main_arena);
|
||||
char* brk, * new_brk;
|
||||
mchunkptr t = top (&main_arena);
|
||||
char *brk, *new_brk;
|
||||
INTERNAL_SIZE_T front_misalign, sbrk_size;
|
||||
unsigned long pagesz = GLRO(dl_pagesize);
|
||||
unsigned long pagesz = GLRO (dl_pagesize);
|
||||
|
||||
if (t == initial_top(&main_arena) ||
|
||||
(!chunk_is_mmapped(t) &&
|
||||
chunksize(t)>=MINSIZE &&
|
||||
prev_inuse(t) &&
|
||||
(!contiguous(&main_arena) ||
|
||||
(char*)t + chunksize(t) == mp_.sbrk_base + main_arena.system_mem)))
|
||||
if (t == initial_top (&main_arena) ||
|
||||
(!chunk_is_mmapped (t) &&
|
||||
chunksize (t) >= MINSIZE &&
|
||||
prev_inuse (t) &&
|
||||
(!contiguous (&main_arena) ||
|
||||
(char *) t + chunksize (t) == mp_.sbrk_base + main_arena.system_mem)))
|
||||
return 0;
|
||||
|
||||
malloc_printerr (check_action, "malloc: top chunk is corrupt", t);
|
||||
|
||||
/* Try to set up a new top chunk. */
|
||||
brk = MORECORE(0);
|
||||
front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK;
|
||||
brk = MORECORE (0);
|
||||
front_misalign = (unsigned long) chunk2mem (brk) & MALLOC_ALIGN_MASK;
|
||||
if (front_misalign > 0)
|
||||
front_misalign = MALLOC_ALIGNMENT - front_misalign;
|
||||
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))
|
||||
sbrk_size += pagesz - ((unsigned long) (brk + sbrk_size) & (pagesz - 1));
|
||||
new_brk = (char *) (MORECORE (sbrk_size));
|
||||
if (new_brk == (char *) (MORECORE_FAILURE))
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
return -1;
|
||||
@ -238,128 +255,148 @@ top_check(void)
|
||||
/* Call the `morecore' hook if necessary. */
|
||||
void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
|
||||
if (hook)
|
||||
(*hook) ();
|
||||
(*hook)();
|
||||
main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size;
|
||||
|
||||
top(&main_arena) = (mchunkptr)(brk + front_misalign);
|
||||
set_head(top(&main_arena), (sbrk_size - front_misalign) | PREV_INUSE);
|
||||
top (&main_arena) = (mchunkptr) (brk + front_misalign);
|
||||
set_head (top (&main_arena), (sbrk_size - front_misalign) | PREV_INUSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void*
|
||||
malloc_check(size_t sz, const void *caller)
|
||||
static void *
|
||||
malloc_check (size_t sz, const void *caller)
|
||||
{
|
||||
void *victim;
|
||||
|
||||
if (sz+1 == 0) {
|
||||
__set_errno (ENOMEM);
|
||||
return NULL;
|
||||
}
|
||||
if (sz + 1 == 0)
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
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);
|
||||
return mem2mem_check(victim, sz);
|
||||
(void) mutex_lock (&main_arena.mutex);
|
||||
victim = (top_check () >= 0) ? _int_malloc (&main_arena, sz + 1) : NULL;
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
return mem2mem_check (victim, sz);
|
||||
}
|
||||
|
||||
static void
|
||||
free_check(void* mem, const void *caller)
|
||||
free_check (void *mem, const void *caller)
|
||||
{
|
||||
mchunkptr p;
|
||||
|
||||
if(!mem) return;
|
||||
(void)mutex_lock(&main_arena.mutex);
|
||||
p = mem2chunk_check(mem, NULL);
|
||||
if(!p) {
|
||||
(void)mutex_unlock(&main_arena.mutex);
|
||||
if (!mem)
|
||||
return;
|
||||
|
||||
malloc_printerr(check_action, "free(): invalid pointer", mem);
|
||||
return;
|
||||
}
|
||||
if (chunk_is_mmapped(p)) {
|
||||
(void)mutex_unlock(&main_arena.mutex);
|
||||
munmap_chunk(p);
|
||||
return;
|
||||
}
|
||||
_int_free(&main_arena, p, 1);
|
||||
(void)mutex_unlock(&main_arena.mutex);
|
||||
(void) mutex_lock (&main_arena.mutex);
|
||||
p = mem2chunk_check (mem, NULL);
|
||||
if (!p)
|
||||
{
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
|
||||
malloc_printerr (check_action, "free(): invalid pointer", mem);
|
||||
return;
|
||||
}
|
||||
if (chunk_is_mmapped (p))
|
||||
{
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
munmap_chunk (p);
|
||||
return;
|
||||
}
|
||||
_int_free (&main_arena, p, 1);
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
}
|
||||
|
||||
static void*
|
||||
realloc_check(void* oldmem, size_t bytes, const void *caller)
|
||||
static void *
|
||||
realloc_check (void *oldmem, size_t bytes, const void *caller)
|
||||
{
|
||||
INTERNAL_SIZE_T nb;
|
||||
void* newmem = 0;
|
||||
void *newmem = 0;
|
||||
unsigned char *magic_p;
|
||||
|
||||
if (bytes+1 == 0) {
|
||||
__set_errno (ENOMEM);
|
||||
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);
|
||||
const mchunkptr oldp = mem2chunk_check(oldmem, &magic_p);
|
||||
(void)mutex_unlock(&main_arena.mutex);
|
||||
if(!oldp) {
|
||||
malloc_printerr(check_action, "realloc(): invalid pointer", oldmem);
|
||||
return malloc_check(bytes, NULL);
|
||||
}
|
||||
const INTERNAL_SIZE_T oldsize = chunksize(oldp);
|
||||
|
||||
checked_request2size(bytes+1, nb);
|
||||
(void)mutex_lock(&main_arena.mutex);
|
||||
|
||||
if (chunk_is_mmapped(oldp)) {
|
||||
#if HAVE_MREMAP
|
||||
mchunkptr newp = mremap_chunk(oldp, nb);
|
||||
if(newp)
|
||||
newmem = chunk2mem(newp);
|
||||
else
|
||||
#endif
|
||||
if (bytes + 1 == 0)
|
||||
{
|
||||
/* Note the extra SIZE_SZ overhead. */
|
||||
if(oldsize - SIZE_SZ >= nb)
|
||||
newmem = oldmem; /* do nothing */
|
||||
else {
|
||||
/* Must alloc, copy, free. */
|
||||
if (top_check() >= 0)
|
||||
newmem = _int_malloc(&main_arena, bytes+1);
|
||||
if (newmem) {
|
||||
memcpy(newmem, oldmem, oldsize - 2*SIZE_SZ);
|
||||
munmap_chunk(oldp);
|
||||
}
|
||||
__set_errno (ENOMEM);
|
||||
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);
|
||||
const mchunkptr oldp = mem2chunk_check (oldmem, &magic_p);
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
if (!oldp)
|
||||
{
|
||||
malloc_printerr (check_action, "realloc(): invalid pointer", oldmem);
|
||||
return malloc_check (bytes, NULL);
|
||||
}
|
||||
const INTERNAL_SIZE_T oldsize = chunksize (oldp);
|
||||
|
||||
checked_request2size (bytes + 1, nb);
|
||||
(void) mutex_lock (&main_arena.mutex);
|
||||
|
||||
if (chunk_is_mmapped (oldp))
|
||||
{
|
||||
#if HAVE_MREMAP
|
||||
mchunkptr newp = mremap_chunk (oldp, nb);
|
||||
if (newp)
|
||||
newmem = chunk2mem (newp);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Note the extra SIZE_SZ overhead. */
|
||||
if (oldsize - SIZE_SZ >= nb)
|
||||
newmem = oldmem; /* do nothing */
|
||||
else
|
||||
{
|
||||
/* Must alloc, copy, free. */
|
||||
if (top_check () >= 0)
|
||||
newmem = _int_malloc (&main_arena, bytes + 1);
|
||||
if (newmem)
|
||||
{
|
||||
memcpy (newmem, oldmem, oldsize - 2 * SIZE_SZ);
|
||||
munmap_chunk (oldp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (top_check() >= 0) {
|
||||
INTERNAL_SIZE_T nb;
|
||||
checked_request2size(bytes + 1, nb);
|
||||
newmem = _int_realloc(&main_arena, oldp, oldsize, nb);
|
||||
else
|
||||
{
|
||||
if (top_check () >= 0)
|
||||
{
|
||||
INTERNAL_SIZE_T nb;
|
||||
checked_request2size (bytes + 1, nb);
|
||||
newmem = _int_realloc (&main_arena, oldp, oldsize, nb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
if (newmem == NULL)
|
||||
*magic_p ^= 0xFF;
|
||||
|
||||
(void)mutex_unlock(&main_arena.mutex);
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
|
||||
return mem2mem_check(newmem, bytes);
|
||||
return mem2mem_check (newmem, bytes);
|
||||
}
|
||||
|
||||
static void*
|
||||
memalign_check(size_t alignment, size_t bytes, const void *caller)
|
||||
static void *
|
||||
memalign_check (size_t alignment, size_t bytes, const void *caller)
|
||||
{
|
||||
void* mem;
|
||||
void *mem;
|
||||
|
||||
if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL);
|
||||
if (alignment < MINSIZE) alignment = MINSIZE;
|
||||
if (alignment <= MALLOC_ALIGNMENT)
|
||||
return malloc_check (bytes, NULL);
|
||||
|
||||
if (alignment < MINSIZE)
|
||||
alignment = MINSIZE;
|
||||
|
||||
/* If the alignment is greater than SIZE_MAX / 2 + 1 it cannot be a
|
||||
power of 2 and will cause overflow in the check below. */
|
||||
@ -377,17 +414,19 @@ memalign_check(size_t alignment, size_t bytes, const void *caller)
|
||||
}
|
||||
|
||||
/* Make sure alignment is power of 2. */
|
||||
if (!powerof2(alignment)) {
|
||||
size_t a = MALLOC_ALIGNMENT * 2;
|
||||
while (a < alignment) a <<= 1;
|
||||
alignment = a;
|
||||
}
|
||||
if (!powerof2 (alignment))
|
||||
{
|
||||
size_t a = MALLOC_ALIGNMENT * 2;
|
||||
while (a < alignment)
|
||||
a <<= 1;
|
||||
alignment = a;
|
||||
}
|
||||
|
||||
(void)mutex_lock(&main_arena.mutex);
|
||||
mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) :
|
||||
NULL;
|
||||
(void)mutex_unlock(&main_arena.mutex);
|
||||
return mem2mem_check(mem, bytes);
|
||||
(void) mutex_lock (&main_arena.mutex);
|
||||
mem = (top_check () >= 0) ? _int_memalign (&main_arena, alignment, bytes + 1) :
|
||||
NULL;
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
return mem2mem_check (mem, bytes);
|
||||
}
|
||||
|
||||
|
||||
@ -408,59 +447,63 @@ memalign_check(size_t alignment, size_t bytes, const void *caller)
|
||||
then the hooks are reset to 0. */
|
||||
|
||||
#define MALLOC_STATE_MAGIC 0x444c4541l
|
||||
#define MALLOC_STATE_VERSION (0*0x100l + 4l) /* major*0x100 + minor */
|
||||
#define MALLOC_STATE_VERSION (0 * 0x100l + 4l) /* major*0x100 + minor */
|
||||
|
||||
struct malloc_save_state {
|
||||
long magic;
|
||||
long version;
|
||||
mbinptr av[NBINS * 2 + 2];
|
||||
char* sbrk_base;
|
||||
int sbrked_mem_bytes;
|
||||
struct malloc_save_state
|
||||
{
|
||||
long magic;
|
||||
long version;
|
||||
mbinptr av[NBINS * 2 + 2];
|
||||
char *sbrk_base;
|
||||
int sbrked_mem_bytes;
|
||||
unsigned long trim_threshold;
|
||||
unsigned long top_pad;
|
||||
unsigned int n_mmaps_max;
|
||||
unsigned int n_mmaps_max;
|
||||
unsigned long mmap_threshold;
|
||||
int check_action;
|
||||
int check_action;
|
||||
unsigned long max_sbrked_mem;
|
||||
unsigned long max_total_mem;
|
||||
unsigned int n_mmaps;
|
||||
unsigned int max_n_mmaps;
|
||||
unsigned int n_mmaps;
|
||||
unsigned int max_n_mmaps;
|
||||
unsigned long mmapped_mem;
|
||||
unsigned long max_mmapped_mem;
|
||||
int using_malloc_checking;
|
||||
int using_malloc_checking;
|
||||
unsigned long max_fast;
|
||||
unsigned long arena_test;
|
||||
unsigned long arena_max;
|
||||
unsigned long narenas;
|
||||
};
|
||||
|
||||
void*
|
||||
__malloc_get_state(void)
|
||||
void *
|
||||
__malloc_get_state (void)
|
||||
{
|
||||
struct malloc_save_state* ms;
|
||||
struct malloc_save_state *ms;
|
||||
int i;
|
||||
mbinptr b;
|
||||
|
||||
ms = (struct malloc_save_state*)__libc_malloc(sizeof(*ms));
|
||||
ms = (struct malloc_save_state *) __libc_malloc (sizeof (*ms));
|
||||
if (!ms)
|
||||
return 0;
|
||||
(void)mutex_lock(&main_arena.mutex);
|
||||
malloc_consolidate(&main_arena);
|
||||
|
||||
(void) mutex_lock (&main_arena.mutex);
|
||||
malloc_consolidate (&main_arena);
|
||||
ms->magic = MALLOC_STATE_MAGIC;
|
||||
ms->version = MALLOC_STATE_VERSION;
|
||||
ms->av[0] = 0;
|
||||
ms->av[1] = 0; /* used to be binblocks, now no longer used */
|
||||
ms->av[2] = top(&main_arena);
|
||||
ms->av[2] = top (&main_arena);
|
||||
ms->av[3] = 0; /* used to be undefined */
|
||||
for(i=1; i<NBINS; i++) {
|
||||
b = bin_at(&main_arena, i);
|
||||
if(first(b) == b)
|
||||
ms->av[2*i+2] = ms->av[2*i+3] = 0; /* empty bin */
|
||||
else {
|
||||
ms->av[2*i+2] = first(b);
|
||||
ms->av[2*i+3] = last(b);
|
||||
for (i = 1; i < NBINS; i++)
|
||||
{
|
||||
b = bin_at (&main_arena, i);
|
||||
if (first (b) == b)
|
||||
ms->av[2 * i + 2] = ms->av[2 * i + 3] = 0; /* empty bin */
|
||||
else
|
||||
{
|
||||
ms->av[2 * i + 2] = first (b);
|
||||
ms->av[2 * i + 3] = last (b);
|
||||
}
|
||||
}
|
||||
}
|
||||
ms->sbrk_base = mp_.sbrk_base;
|
||||
ms->sbrked_mem_bytes = main_arena.system_mem;
|
||||
ms->trim_threshold = mp_.trim_threshold;
|
||||
@ -475,78 +518,92 @@ __malloc_get_state(void)
|
||||
ms->mmapped_mem = mp_.mmapped_mem;
|
||||
ms->max_mmapped_mem = mp_.max_mmapped_mem;
|
||||
ms->using_malloc_checking = using_malloc_checking;
|
||||
ms->max_fast = get_max_fast();
|
||||
ms->max_fast = get_max_fast ();
|
||||
ms->arena_test = mp_.arena_test;
|
||||
ms->arena_max = mp_.arena_max;
|
||||
ms->narenas = narenas;
|
||||
(void)mutex_unlock(&main_arena.mutex);
|
||||
return (void*)ms;
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
return (void *) ms;
|
||||
}
|
||||
|
||||
int
|
||||
__malloc_set_state(void* msptr)
|
||||
__malloc_set_state (void *msptr)
|
||||
{
|
||||
struct malloc_save_state* ms = (struct malloc_save_state*)msptr;
|
||||
struct malloc_save_state *ms = (struct malloc_save_state *) msptr;
|
||||
size_t i;
|
||||
mbinptr b;
|
||||
|
||||
disallow_malloc_check = 1;
|
||||
ptmalloc_init();
|
||||
if(ms->magic != MALLOC_STATE_MAGIC) return -1;
|
||||
ptmalloc_init ();
|
||||
if (ms->magic != MALLOC_STATE_MAGIC)
|
||||
return -1;
|
||||
|
||||
/* Must fail if the major version is too high. */
|
||||
if((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl)) return -2;
|
||||
(void)mutex_lock(&main_arena.mutex);
|
||||
if ((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl))
|
||||
return -2;
|
||||
|
||||
(void) mutex_lock (&main_arena.mutex);
|
||||
/* There are no fastchunks. */
|
||||
clear_fastchunks(&main_arena);
|
||||
clear_fastchunks (&main_arena);
|
||||
if (ms->version >= 4)
|
||||
set_max_fast(ms->max_fast);
|
||||
set_max_fast (ms->max_fast);
|
||||
else
|
||||
set_max_fast(64); /* 64 used to be the value we always used. */
|
||||
for (i=0; i<NFASTBINS; ++i)
|
||||
set_max_fast (64); /* 64 used to be the value we always used. */
|
||||
for (i = 0; i < NFASTBINS; ++i)
|
||||
fastbin (&main_arena, i) = 0;
|
||||
for (i=0; i<BINMAPSIZE; ++i)
|
||||
for (i = 0; i < BINMAPSIZE; ++i)
|
||||
main_arena.binmap[i] = 0;
|
||||
top(&main_arena) = ms->av[2];
|
||||
top (&main_arena) = ms->av[2];
|
||||
main_arena.last_remainder = 0;
|
||||
for(i=1; i<NBINS; i++) {
|
||||
b = bin_at(&main_arena, i);
|
||||
if(ms->av[2*i+2] == 0) {
|
||||
assert(ms->av[2*i+3] == 0);
|
||||
first(b) = last(b) = b;
|
||||
} else {
|
||||
if(ms->version >= 3 &&
|
||||
(i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i &&
|
||||
largebin_index(chunksize(ms->av[2*i+3]))==i))) {
|
||||
first(b) = ms->av[2*i+2];
|
||||
last(b) = ms->av[2*i+3];
|
||||
/* Make sure the links to the bins within the heap are correct. */
|
||||
first(b)->bk = b;
|
||||
last(b)->fd = b;
|
||||
/* Set bit in binblocks. */
|
||||
mark_bin(&main_arena, i);
|
||||
} else {
|
||||
/* Oops, index computation from chunksize must have changed.
|
||||
Link the whole list into unsorted_chunks. */
|
||||
first(b) = last(b) = b;
|
||||
b = unsorted_chunks(&main_arena);
|
||||
ms->av[2*i+2]->bk = b;
|
||||
ms->av[2*i+3]->fd = b->fd;
|
||||
b->fd->bk = ms->av[2*i+3];
|
||||
b->fd = ms->av[2*i+2];
|
||||
}
|
||||
for (i = 1; i < NBINS; i++)
|
||||
{
|
||||
b = bin_at (&main_arena, i);
|
||||
if (ms->av[2 * i + 2] == 0)
|
||||
{
|
||||
assert (ms->av[2 * i + 3] == 0);
|
||||
first (b) = last (b) = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ms->version >= 3 &&
|
||||
(i < NSMALLBINS || (largebin_index (chunksize (ms->av[2 * i + 2])) == i &&
|
||||
largebin_index (chunksize (ms->av[2 * i + 3])) == i)))
|
||||
{
|
||||
first (b) = ms->av[2 * i + 2];
|
||||
last (b) = ms->av[2 * i + 3];
|
||||
/* Make sure the links to the bins within the heap are correct. */
|
||||
first (b)->bk = b;
|
||||
last (b)->fd = b;
|
||||
/* Set bit in binblocks. */
|
||||
mark_bin (&main_arena, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Oops, index computation from chunksize must have changed.
|
||||
Link the whole list into unsorted_chunks. */
|
||||
first (b) = last (b) = b;
|
||||
b = unsorted_chunks (&main_arena);
|
||||
ms->av[2 * i + 2]->bk = b;
|
||||
ms->av[2 * i + 3]->fd = b->fd;
|
||||
b->fd->bk = ms->av[2 * i + 3];
|
||||
b->fd = ms->av[2 * i + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ms->version < 3) {
|
||||
/* Clear fd_nextsize and bk_nextsize fields. */
|
||||
b = unsorted_chunks(&main_arena)->fd;
|
||||
while (b != unsorted_chunks(&main_arena)) {
|
||||
if (!in_smallbin_range(chunksize(b))) {
|
||||
b->fd_nextsize = NULL;
|
||||
b->bk_nextsize = NULL;
|
||||
}
|
||||
b = b->fd;
|
||||
if (ms->version < 3)
|
||||
{
|
||||
/* Clear fd_nextsize and bk_nextsize fields. */
|
||||
b = unsorted_chunks (&main_arena)->fd;
|
||||
while (b != unsorted_chunks (&main_arena))
|
||||
{
|
||||
if (!in_smallbin_range (chunksize (b)))
|
||||
{
|
||||
b->fd_nextsize = NULL;
|
||||
b->bk_nextsize = NULL;
|
||||
}
|
||||
b = b->fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
mp_.sbrk_base = ms->sbrk_base;
|
||||
main_arena.system_mem = ms->sbrked_mem_bytes;
|
||||
mp_.trim_threshold = ms->trim_threshold;
|
||||
@ -560,28 +617,31 @@ __malloc_set_state(void* msptr)
|
||||
mp_.mmapped_mem = ms->mmapped_mem;
|
||||
mp_.max_mmapped_mem = ms->max_mmapped_mem;
|
||||
/* add version-dependent code here */
|
||||
if (ms->version >= 1) {
|
||||
/* Check whether it is safe to enable malloc checking, or whether
|
||||
it is necessary to disable it. */
|
||||
if (ms->using_malloc_checking && !using_malloc_checking &&
|
||||
!disallow_malloc_check)
|
||||
__malloc_check_init ();
|
||||
else if (!ms->using_malloc_checking && using_malloc_checking) {
|
||||
__malloc_hook = NULL;
|
||||
__free_hook = NULL;
|
||||
__realloc_hook = NULL;
|
||||
__memalign_hook = NULL;
|
||||
using_malloc_checking = 0;
|
||||
if (ms->version >= 1)
|
||||
{
|
||||
/* Check whether it is safe to enable malloc checking, or whether
|
||||
it is necessary to disable it. */
|
||||
if (ms->using_malloc_checking && !using_malloc_checking &&
|
||||
!disallow_malloc_check)
|
||||
__malloc_check_init ();
|
||||
else if (!ms->using_malloc_checking && using_malloc_checking)
|
||||
{
|
||||
__malloc_hook = NULL;
|
||||
__free_hook = NULL;
|
||||
__realloc_hook = NULL;
|
||||
__memalign_hook = NULL;
|
||||
using_malloc_checking = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ms->version >= 4) {
|
||||
mp_.arena_test = ms->arena_test;
|
||||
mp_.arena_max = ms->arena_max;
|
||||
narenas = ms->narenas;
|
||||
}
|
||||
check_malloc_state(&main_arena);
|
||||
if (ms->version >= 4)
|
||||
{
|
||||
mp_.arena_test = ms->arena_test;
|
||||
mp_.arena_max = ms->arena_max;
|
||||
narenas = ms->narenas;
|
||||
}
|
||||
check_malloc_state (&main_arena);
|
||||
|
||||
(void)mutex_unlock(&main_arena.mutex);
|
||||
(void) mutex_unlock (&main_arena.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
4027
malloc/malloc.c
4027
malloc/malloc.c
File diff suppressed because it is too large
Load Diff
@ -39,7 +39,7 @@ extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur;
|
||||
|
||||
/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
|
||||
extern void *calloc (size_t __nmemb, size_t __size)
|
||||
__THROW __attribute_malloc__ __wur;
|
||||
__THROW __attribute_malloc__ __wur;
|
||||
|
||||
/* Re-allocate the previously allocated block in __ptr, making the new
|
||||
block SIZE bytes long. */
|
||||
@ -47,7 +47,7 @@ extern void *calloc (size_t __nmemb, size_t __size)
|
||||
the same pointer that was passed to it, aliasing needs to be allowed
|
||||
between objects pointed by the old and new pointers. */
|
||||
extern void *realloc (void *__ptr, size_t __size)
|
||||
__THROW __attribute_warn_unused_result__;
|
||||
__THROW __attribute_warn_unused_result__;
|
||||
|
||||
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
|
||||
extern void free (void *__ptr) __THROW;
|
||||
@ -57,14 +57,14 @@ extern void cfree (void *__ptr) __THROW;
|
||||
|
||||
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
|
||||
extern void *memalign (size_t __alignment, size_t __size)
|
||||
__THROW __attribute_malloc__ __wur;
|
||||
__THROW __attribute_malloc__ __wur;
|
||||
|
||||
/* Allocate SIZE bytes on a page boundary. */
|
||||
extern void *valloc (size_t __size) __THROW __attribute_malloc__ __wur;
|
||||
|
||||
/* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up
|
||||
__size to nearest pagesize. */
|
||||
extern void * pvalloc (size_t __size) __THROW __attribute_malloc__ __wur;
|
||||
extern void *pvalloc (size_t __size) __THROW __attribute_malloc__ __wur;
|
||||
|
||||
/* Underlying allocation function; successive calls should return
|
||||
contiguous pieces of memory. */
|
||||
@ -72,7 +72,7 @@ extern void *(*__morecore) (ptrdiff_t __size);
|
||||
|
||||
/* Default value of `__morecore'. */
|
||||
extern void *__default_morecore (ptrdiff_t __size)
|
||||
__THROW __attribute_malloc__;
|
||||
__THROW __attribute_malloc__;
|
||||
|
||||
/* SVID2/XPG mallinfo structure */
|
||||
|
||||
@ -95,16 +95,16 @@ extern struct mallinfo mallinfo (void) __THROW;
|
||||
|
||||
/* SVID2/XPG mallopt options */
|
||||
#ifndef M_MXFAST
|
||||
# define M_MXFAST 1 /* maximum request size for "fastbins" */
|
||||
# define M_MXFAST 1 /* maximum request size for "fastbins" */
|
||||
#endif
|
||||
#ifndef M_NLBLKS
|
||||
# define M_NLBLKS 2 /* UNUSED in this malloc */
|
||||
# define M_NLBLKS 2 /* UNUSED in this malloc */
|
||||
#endif
|
||||
#ifndef M_GRAIN
|
||||
# define M_GRAIN 3 /* UNUSED in this malloc */
|
||||
# define M_GRAIN 3 /* UNUSED in this malloc */
|
||||
#endif
|
||||
#ifndef M_KEEP
|
||||
# define M_KEEP 4 /* UNUSED in this malloc */
|
||||
# define M_KEEP 4 /* UNUSED in this malloc */
|
||||
#endif
|
||||
|
||||
/* mallopt options that actually do something */
|
||||
@ -113,9 +113,9 @@ extern struct mallinfo mallinfo (void) __THROW;
|
||||
#define M_MMAP_THRESHOLD -3
|
||||
#define M_MMAP_MAX -4
|
||||
#define M_CHECK_ACTION -5
|
||||
#define M_PERTURB -6
|
||||
#define M_ARENA_TEST -7
|
||||
#define M_ARENA_MAX -8
|
||||
#define M_PERTURB -6
|
||||
#define M_ARENA_TEST -7
|
||||
#define M_ARENA_MAX -8
|
||||
|
||||
/* General SVID/XPG interface to tunable parameters. */
|
||||
extern int mallopt (int __param, int __val) __THROW;
|
||||
@ -145,22 +145,22 @@ extern int malloc_set_state (void *__ptr) __THROW;
|
||||
the application provides the preferred way to set up the hook
|
||||
pointers. */
|
||||
extern void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void)
|
||||
__MALLOC_DEPRECATED;
|
||||
__MALLOC_DEPRECATED;
|
||||
/* Hooks for debugging and user-defined versions. */
|
||||
extern void (*__MALLOC_HOOK_VOLATILE __free_hook) (void *__ptr,
|
||||
const void *)
|
||||
__MALLOC_DEPRECATED;
|
||||
extern void *(*__MALLOC_HOOK_VOLATILE __malloc_hook) (size_t __size,
|
||||
const void *)
|
||||
__MALLOC_DEPRECATED;
|
||||
extern void *(*__MALLOC_HOOK_VOLATILE __realloc_hook) (void *__ptr,
|
||||
size_t __size,
|
||||
const void *)
|
||||
__MALLOC_DEPRECATED;
|
||||
extern void *(*__MALLOC_HOOK_VOLATILE __memalign_hook) (size_t __alignment,
|
||||
size_t __size,
|
||||
const void *)
|
||||
__MALLOC_DEPRECATED;
|
||||
const void *)
|
||||
__MALLOC_DEPRECATED;
|
||||
extern void *(*__MALLOC_HOOK_VOLATILE __malloc_hook)(size_t __size,
|
||||
const void *)
|
||||
__MALLOC_DEPRECATED;
|
||||
extern void *(*__MALLOC_HOOK_VOLATILE __realloc_hook)(void *__ptr,
|
||||
size_t __size,
|
||||
const void *)
|
||||
__MALLOC_DEPRECATED;
|
||||
extern void *(*__MALLOC_HOOK_VOLATILE __memalign_hook)(size_t __alignment,
|
||||
size_t __size,
|
||||
const void *)
|
||||
__MALLOC_DEPRECATED;
|
||||
extern void (*__MALLOC_HOOK_VOLATILE __after_morecore_hook) (void);
|
||||
|
||||
/* Activate a standard set of debugging hooks. */
|
||||
@ -168,5 +168,4 @@ extern void __malloc_check_init (void) __THROW __MALLOC_DEPRECATED;
|
||||
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* malloc.h */
|
||||
|
@ -22,14 +22,14 @@ main (int argc, char *argv[])
|
||||
size_t i;
|
||||
|
||||
/* Here's what memory is supposed to look like (hex):
|
||||
size contents
|
||||
3000 original_info_table, later fill_info_table1
|
||||
size contents
|
||||
3000 original_info_table, later fill_info_table1
|
||||
3fa000 dummy0
|
||||
3fa000 dummy1
|
||||
6000 info_table_2
|
||||
3000 over_top
|
||||
6000 info_table_2
|
||||
3000 over_top
|
||||
|
||||
*/
|
||||
*/
|
||||
/* mem: original_info_table */
|
||||
dummy0 = malloc (0x3fa000);
|
||||
/* mem: original_info_table, dummy0 */
|
||||
@ -54,15 +54,15 @@ main (int argc, char *argv[])
|
||||
for (i = 0; i < over_top_size; ++i)
|
||||
if (over_top[i] != 0)
|
||||
{
|
||||
printf ("FAIL: malloc expands info table\n");
|
||||
return 0;
|
||||
printf ("FAIL: malloc expands info table\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < over_top_dup_size; ++i)
|
||||
if (over_top_dup[i] != 1)
|
||||
{
|
||||
printf ("FAIL: malloc expands info table\n");
|
||||
return 0;
|
||||
printf ("FAIL: malloc expands info table\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf ("PASS: malloc expands info table\n");
|
||||
|
@ -17,7 +17,7 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _MALLOC_INTERNAL
|
||||
#ifndef _MALLOC_INTERNAL
|
||||
# define _MALLOC_INTERNAL
|
||||
# include <malloc.h>
|
||||
# include <mcheck.h>
|
||||
@ -28,32 +28,32 @@
|
||||
#endif
|
||||
|
||||
/* Old hook values. */
|
||||
static void (*old_free_hook) (__ptr_t ptr, const __ptr_t);
|
||||
static void (*old_free_hook)(__ptr_t ptr, const __ptr_t);
|
||||
static __ptr_t (*old_malloc_hook) (size_t size, const __ptr_t);
|
||||
static __ptr_t (*old_memalign_hook) (size_t alignment, size_t size,
|
||||
const __ptr_t);
|
||||
const __ptr_t);
|
||||
static __ptr_t (*old_realloc_hook) (__ptr_t ptr, size_t size,
|
||||
const __ptr_t);
|
||||
const __ptr_t);
|
||||
|
||||
/* Function to call when something awful happens. */
|
||||
static void (*abortfunc) (enum mcheck_status);
|
||||
|
||||
/* Arbitrary magical numbers. */
|
||||
#define MAGICWORD 0xfedabeeb
|
||||
#define MAGICFREE 0xd8675309
|
||||
#define MAGICBYTE ((char) 0xd7)
|
||||
#define MALLOCFLOOD ((char) 0x93)
|
||||
#define FREEFLOOD ((char) 0x95)
|
||||
#define MAGICWORD 0xfedabeeb
|
||||
#define MAGICFREE 0xd8675309
|
||||
#define MAGICBYTE ((char) 0xd7)
|
||||
#define MALLOCFLOOD ((char) 0x93)
|
||||
#define FREEFLOOD ((char) 0x95)
|
||||
|
||||
struct hdr
|
||||
{
|
||||
size_t size; /* Exact size requested by user. */
|
||||
unsigned long int magic; /* Magic number to check header integrity. */
|
||||
struct hdr *prev;
|
||||
struct hdr *next;
|
||||
__ptr_t block; /* Real block allocated, for memalign. */
|
||||
unsigned long int magic2; /* Extra, keeps us doubleword aligned. */
|
||||
};
|
||||
{
|
||||
size_t size; /* Exact size requested by user. */
|
||||
unsigned long int magic; /* Magic number to check header integrity. */
|
||||
struct hdr *prev;
|
||||
struct hdr *next;
|
||||
__ptr_t block; /* Real block allocated, for memalign. */
|
||||
unsigned long int magic2; /* Extra, keeps us doubleword aligned. */
|
||||
};
|
||||
|
||||
/* This is the beginning of the list of all memory blocks allocated.
|
||||
It is only constructed if the pedantic testing is requested. */
|
||||
@ -69,11 +69,10 @@ static int pedantic;
|
||||
# define flood memset
|
||||
#else
|
||||
static void flood (__ptr_t, int, size_t);
|
||||
static void
|
||||
flood (ptr, val, size)
|
||||
__ptr_t ptr;
|
||||
int val;
|
||||
size_t size;
|
||||
static void flood (ptr, val, size)
|
||||
__ptr_t ptr;
|
||||
int val;
|
||||
size_t size;
|
||||
{
|
||||
char *cp = ptr;
|
||||
while (size--)
|
||||
@ -101,11 +100,11 @@ checkhdr (const struct hdr *hdr)
|
||||
break;
|
||||
case MAGICWORD:
|
||||
if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
|
||||
status = MCHECK_TAIL;
|
||||
status = MCHECK_TAIL;
|
||||
else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD)
|
||||
status = MCHECK_HEAD;
|
||||
status = MCHECK_HEAD;
|
||||
else
|
||||
status = MCHECK_OK;
|
||||
status = MCHECK_OK;
|
||||
break;
|
||||
}
|
||||
if (status != MCHECK_OK)
|
||||
@ -148,13 +147,13 @@ unlink_blk (struct hdr *ptr)
|
||||
{
|
||||
ptr->next->prev = ptr->prev;
|
||||
ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev
|
||||
+ (uintptr_t) ptr->next->next);
|
||||
+ (uintptr_t) ptr->next->next);
|
||||
}
|
||||
if (ptr->prev != NULL)
|
||||
{
|
||||
ptr->prev->next = ptr->next;
|
||||
ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev
|
||||
+ (uintptr_t) ptr->prev->next);
|
||||
+ (uintptr_t) ptr->prev->next);
|
||||
}
|
||||
else
|
||||
root = ptr->next;
|
||||
@ -173,7 +172,7 @@ link_blk (struct hdr *hdr)
|
||||
{
|
||||
hdr->next->prev = hdr;
|
||||
hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr
|
||||
+ (uintptr_t) hdr->next->next);
|
||||
+ (uintptr_t) hdr->next->next);
|
||||
}
|
||||
}
|
||||
static void
|
||||
@ -194,7 +193,7 @@ freehook (__ptr_t ptr, const __ptr_t caller)
|
||||
}
|
||||
__free_hook = old_free_hook;
|
||||
if (old_free_hook != NULL)
|
||||
(*old_free_hook) (ptr, caller);
|
||||
(*old_free_hook)(ptr, caller);
|
||||
else
|
||||
free (ptr);
|
||||
__free_hook = freehook;
|
||||
@ -216,8 +215,8 @@ mallochook (size_t size, const __ptr_t caller)
|
||||
|
||||
__malloc_hook = old_malloc_hook;
|
||||
if (old_malloc_hook != NULL)
|
||||
hdr = (struct hdr *) (*old_malloc_hook) (sizeof (struct hdr) + size + 1,
|
||||
caller);
|
||||
hdr = (struct hdr *) (*old_malloc_hook)(sizeof (struct hdr) + size + 1,
|
||||
caller);
|
||||
else
|
||||
hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
|
||||
__malloc_hook = mallochook;
|
||||
@ -235,7 +234,7 @@ mallochook (size_t size, const __ptr_t caller)
|
||||
|
||||
static __ptr_t
|
||||
memalignhook (size_t alignment, size_t size,
|
||||
const __ptr_t caller)
|
||||
const __ptr_t caller)
|
||||
{
|
||||
struct hdr *hdr;
|
||||
size_t slop;
|
||||
@ -244,7 +243,7 @@ memalignhook (size_t alignment, size_t size,
|
||||
if (pedantic)
|
||||
mcheck_check_all ();
|
||||
|
||||
slop = (sizeof *hdr + alignment - 1) & -alignment;
|
||||
slop = (sizeof *hdr + alignment - 1) & - alignment;
|
||||
|
||||
if (size > ~((size_t) 0) - (slop + 1))
|
||||
{
|
||||
@ -254,7 +253,7 @@ memalignhook (size_t alignment, size_t size,
|
||||
|
||||
__memalign_hook = old_memalign_hook;
|
||||
if (old_memalign_hook != NULL)
|
||||
block = (*old_memalign_hook) (alignment, slop + size + 1, caller);
|
||||
block = (*old_memalign_hook)(alignment, slop + size + 1, caller);
|
||||
else
|
||||
block = memalign (alignment, slop + size + 1);
|
||||
__memalign_hook = memalignhook;
|
||||
@ -301,7 +300,7 @@ reallochook (__ptr_t ptr, size_t size, const __ptr_t caller)
|
||||
checkhdr (hdr);
|
||||
unlink_blk (hdr);
|
||||
if (size < osize)
|
||||
flood ((char *) ptr + size, FREEFLOOD, osize - size);
|
||||
flood ((char *) ptr + size, FREEFLOOD, osize - size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -313,12 +312,12 @@ reallochook (__ptr_t ptr, size_t size, const __ptr_t caller)
|
||||
__memalign_hook = old_memalign_hook;
|
||||
__realloc_hook = old_realloc_hook;
|
||||
if (old_realloc_hook != NULL)
|
||||
hdr = (struct hdr *) (*old_realloc_hook) ((__ptr_t) hdr,
|
||||
sizeof (struct hdr) + size + 1,
|
||||
caller);
|
||||
hdr = (struct hdr *) (*old_realloc_hook)((__ptr_t) hdr,
|
||||
sizeof (struct hdr) + size + 1,
|
||||
caller);
|
||||
else
|
||||
hdr = (struct hdr *) realloc ((__ptr_t) hdr,
|
||||
sizeof (struct hdr) + size + 1);
|
||||
sizeof (struct hdr) + size + 1);
|
||||
__free_hook = freehook;
|
||||
__malloc_hook = mallochook;
|
||||
__memalign_hook = memalignhook;
|
||||
@ -344,19 +343,19 @@ mabort (enum mcheck_status status)
|
||||
switch (status)
|
||||
{
|
||||
case MCHECK_OK:
|
||||
msg = _("memory is consistent, library is buggy\n");
|
||||
msg = _ ("memory is consistent, library is buggy\n");
|
||||
break;
|
||||
case MCHECK_HEAD:
|
||||
msg = _("memory clobbered before allocated block\n");
|
||||
msg = _ ("memory clobbered before allocated block\n");
|
||||
break;
|
||||
case MCHECK_TAIL:
|
||||
msg = _("memory clobbered past end of allocated block\n");
|
||||
msg = _ ("memory clobbered past end of allocated block\n");
|
||||
break;
|
||||
case MCHECK_FREE:
|
||||
msg = _("block freed twice\n");
|
||||
msg = _ ("block freed twice\n");
|
||||
break;
|
||||
default:
|
||||
msg = _("bogus mcheck_status, library is buggy\n");
|
||||
msg = _ ("bogus mcheck_status, library is buggy\n");
|
||||
break;
|
||||
}
|
||||
#ifdef _LIBC
|
||||
@ -370,11 +369,10 @@ mabort (enum mcheck_status status)
|
||||
|
||||
/* Memory barrier so that GCC does not optimize out the argument. */
|
||||
#define malloc_opt_barrier(x) \
|
||||
({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
|
||||
({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
|
||||
|
||||
int
|
||||
mcheck (func)
|
||||
void (*func) (enum mcheck_status);
|
||||
int mcheck (func)
|
||||
void (*func)(enum mcheck_status);
|
||||
{
|
||||
abortfunc = (func != NULL) ? func : &mabort;
|
||||
|
||||
@ -404,9 +402,8 @@ mcheck (func)
|
||||
libc_hidden_def (mcheck)
|
||||
#endif
|
||||
|
||||
int
|
||||
mcheck_pedantic (func)
|
||||
void (*func) (enum mcheck_status);
|
||||
int mcheck_pedantic (func)
|
||||
void (*func)(enum mcheck_status);
|
||||
{
|
||||
int res = mcheck (func);
|
||||
if (res == 0)
|
||||
|
@ -16,7 +16,7 @@
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _MCHECK_H
|
||||
#define _MCHECK_H 1
|
||||
#define _MCHECK_H 1
|
||||
|
||||
#include <features.h>
|
||||
|
||||
@ -25,24 +25,24 @@ __BEGIN_DECLS
|
||||
/* Return values for `mprobe': these are the kinds of inconsistencies that
|
||||
`mcheck' enables detection of. */
|
||||
enum mcheck_status
|
||||
{
|
||||
MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */
|
||||
MCHECK_OK, /* Block is fine. */
|
||||
MCHECK_FREE, /* Block freed twice. */
|
||||
MCHECK_HEAD, /* Memory before the block was clobbered. */
|
||||
MCHECK_TAIL /* Memory after the block was clobbered. */
|
||||
};
|
||||
{
|
||||
MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */
|
||||
MCHECK_OK, /* Block is fine. */
|
||||
MCHECK_FREE, /* Block freed twice. */
|
||||
MCHECK_HEAD, /* Memory before the block was clobbered. */
|
||||
MCHECK_TAIL /* Memory after the block was clobbered. */
|
||||
};
|
||||
|
||||
|
||||
/* Activate a standard collection of debugging hooks. This must be called
|
||||
before `malloc' is ever called. ABORTFUNC is called with an error code
|
||||
(see enum above) when an inconsistency is detected. If ABORTFUNC is
|
||||
null, the standard function prints on stderr and then calls `abort'. */
|
||||
extern int mcheck (void (*__abortfunc) (enum mcheck_status)) __THROW;
|
||||
extern int mcheck (void (*__abortfunc)(enum mcheck_status)) __THROW;
|
||||
|
||||
/* Similar to `mcheck' but performs checks for all block whenever one of
|
||||
the memory handling functions is called. This can be very slow. */
|
||||
extern int mcheck_pedantic (void (*__abortfunc) (enum mcheck_status)) __THROW;
|
||||
extern int mcheck_pedantic (void (*__abortfunc)(enum mcheck_status)) __THROW;
|
||||
|
||||
/* Force check of all blocks now. */
|
||||
extern void mcheck_check_all (void);
|
||||
@ -57,5 +57,4 @@ extern void mtrace (void) __THROW;
|
||||
extern void muntrace (void) __THROW;
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* mcheck.h */
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
/* Pointer to the real functions. These are determined used `dlsym'
|
||||
when really needed. */
|
||||
static void *(*mallocp) (size_t);
|
||||
static void *(*mallocp)(size_t);
|
||||
static void *(*reallocp) (void *, size_t);
|
||||
static void *(*callocp) (size_t, size_t);
|
||||
static void (*freep) (void *);
|
||||
@ -89,11 +89,11 @@ static memusage_size_t peak_use[3];
|
||||
static __thread uintptr_t start_sp;
|
||||
|
||||
/* A few macros to make the source more readable. */
|
||||
#define peak_heap peak_use[0]
|
||||
#define peak_stack peak_use[1]
|
||||
#define peak_total peak_use[2]
|
||||
#define peak_heap peak_use[0]
|
||||
#define peak_stack peak_use[1]
|
||||
#define peak_total peak_use[2]
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 32768
|
||||
#define DEFAULT_BUFFER_SIZE 32768
|
||||
static size_t buffer_size;
|
||||
|
||||
static int fd = -1;
|
||||
@ -164,16 +164,16 @@ update_data (struct header *result, size_t len, size_t old_len)
|
||||
{
|
||||
uatomic32_t idx = catomic_exchange_and_add (&buffer_cnt, 1);
|
||||
if (idx + 1 >= 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. */
|
||||
uatomic32_t reset = (idx + 1) % (2 * buffer_size);
|
||||
catomic_compare_and_exchange_val_acq (&buffer_cnt, reset, idx + 1);
|
||||
if (idx >= 2 * buffer_size)
|
||||
idx = reset - 1;
|
||||
}
|
||||
{
|
||||
/* 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. */
|
||||
uatomic32_t reset = (idx + 1) % (2 * buffer_size);
|
||||
catomic_compare_and_exchange_val_acq (&buffer_cnt, reset, idx + 1);
|
||||
if (idx >= 2 * buffer_size)
|
||||
idx = reset - 1;
|
||||
}
|
||||
assert (idx < 2 * DEFAULT_BUFFER_SIZE);
|
||||
|
||||
buffer[idx].heap = current_heap;
|
||||
@ -182,9 +182,9 @@ update_data (struct header *result, size_t len, size_t old_len)
|
||||
|
||||
/* Write out buffer if it is full. */
|
||||
if (idx + 1 == buffer_size)
|
||||
write (fd, buffer, buffer_size * sizeof (struct entry));
|
||||
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));
|
||||
write (fd, &buffer[buffer_size], buffer_size * sizeof (struct entry));
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,19 +221,19 @@ me (void)
|
||||
size_t prog_len = strlen (__progname);
|
||||
|
||||
initialized = -1;
|
||||
mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc");
|
||||
reallocp = (void *(*) (void *, size_t)) dlsym (RTLD_NEXT, "realloc");
|
||||
callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT, "calloc");
|
||||
freep = (void (*) (void *)) dlsym (RTLD_NEXT, "free");
|
||||
mallocp = (void *(*)(size_t))dlsym (RTLD_NEXT, "malloc");
|
||||
reallocp = (void *(*)(void *, size_t))dlsym (RTLD_NEXT, "realloc");
|
||||
callocp = (void *(*)(size_t, size_t))dlsym (RTLD_NEXT, "calloc");
|
||||
freep = (void (*)(void *))dlsym (RTLD_NEXT, "free");
|
||||
|
||||
mmapp = (void *(*) (void *, size_t, int, int, int, off_t)) dlsym (RTLD_NEXT,
|
||||
"mmap");
|
||||
mmapp = (void *(*)(void *, size_t, int, int, int, off_t))dlsym (RTLD_NEXT,
|
||||
"mmap");
|
||||
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");
|
||||
munmapp = (int (*) (void *, size_t)) dlsym (RTLD_NEXT, "munmap");
|
||||
(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");
|
||||
munmapp = (int (*)(void *, size_t))dlsym (RTLD_NEXT, "munmap");
|
||||
initialized = 1;
|
||||
|
||||
if (env != NULL)
|
||||
@ -241,8 +241,8 @@ me (void)
|
||||
/* Check for program name. */
|
||||
size_t len = strlen (env);
|
||||
if (len > prog_len || strcmp (env, &__progname[prog_len - len]) != 0
|
||||
|| (prog_len != len && __progname[prog_len - len - 1] != '/'))
|
||||
not_me = true;
|
||||
|| (prog_len != len && __progname[prog_len - len - 1] != '/'))
|
||||
not_me = true;
|
||||
}
|
||||
|
||||
/* Only open the file if it's really us. */
|
||||
@ -251,62 +251,62 @@ me (void)
|
||||
const char *outname;
|
||||
|
||||
if (!start_sp)
|
||||
start_sp = GETSP ();
|
||||
start_sp = GETSP ();
|
||||
|
||||
outname = getenv ("MEMUSAGE_OUTPUT");
|
||||
if (outname != NULL && outname[0] != '\0'
|
||||
&& (access (outname, R_OK | W_OK) == 0 || errno == ENOENT))
|
||||
{
|
||||
fd = creat64 (outname, 0666);
|
||||
&& (access (outname, R_OK | W_OK) == 0 || errno == ENOENT))
|
||||
{
|
||||
fd = creat64 (outname, 0666);
|
||||
|
||||
if (fd == -1)
|
||||
/* Don't do anything in future calls if we cannot write to
|
||||
the output file. */
|
||||
not_me = true;
|
||||
else
|
||||
{
|
||||
/* Write the first entry. */
|
||||
first.heap = 0;
|
||||
first.stack = 0;
|
||||
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));
|
||||
if (fd == -1)
|
||||
/* Don't do anything in future calls if we cannot write to
|
||||
the output file. */
|
||||
not_me = true;
|
||||
else
|
||||
{
|
||||
/* Write the first entry. */
|
||||
first.heap = 0;
|
||||
first.stack = 0;
|
||||
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. */
|
||||
buffer_size = DEFAULT_BUFFER_SIZE;
|
||||
if (getenv ("MEMUSAGE_BUFFER_SIZE") != NULL)
|
||||
{
|
||||
buffer_size = atoi (getenv ("MEMUSAGE_BUFFER_SIZE"));
|
||||
if (buffer_size == 0 || buffer_size > DEFAULT_BUFFER_SIZE)
|
||||
buffer_size = DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
/* Determine the buffer size. We use the default if the
|
||||
environment variable is not present. */
|
||||
buffer_size = DEFAULT_BUFFER_SIZE;
|
||||
if (getenv ("MEMUSAGE_BUFFER_SIZE") != NULL)
|
||||
{
|
||||
buffer_size = atoi (getenv ("MEMUSAGE_BUFFER_SIZE"));
|
||||
if (buffer_size == 0 || buffer_size > DEFAULT_BUFFER_SIZE)
|
||||
buffer_size = DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/* Possibly enable timer-based stack pointer retrieval. */
|
||||
if (getenv ("MEMUSAGE_NO_TIMER") == NULL)
|
||||
{
|
||||
struct sigaction act;
|
||||
/* Possibly enable timer-based stack pointer retrieval. */
|
||||
if (getenv ("MEMUSAGE_NO_TIMER") == NULL)
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = (sighandler_t) &int_handler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigfillset (&act.sa_mask);
|
||||
act.sa_handler = (sighandler_t) &int_handler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigfillset (&act.sa_mask);
|
||||
|
||||
if (sigaction (SIGPROF, &act, NULL) >= 0)
|
||||
{
|
||||
struct itimerval timer;
|
||||
if (sigaction (SIGPROF, &act, NULL) >= 0)
|
||||
{
|
||||
struct itimerval timer;
|
||||
|
||||
timer.it_value.tv_sec = 0;
|
||||
timer.it_value.tv_usec = 1;
|
||||
timer.it_interval = timer.it_value;
|
||||
setitimer (ITIMER_PROF, &timer, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timer.it_value.tv_sec = 0;
|
||||
timer.it_value.tv_usec = 1;
|
||||
timer.it_interval = timer.it_value;
|
||||
setitimer (ITIMER_PROF, &timer, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!not_me && getenv ("MEMUSAGE_TRACE_MMAP") != NULL)
|
||||
trace_mmap = true;
|
||||
trace_mmap = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,7 +317,7 @@ __attribute__ ((constructor))
|
||||
init (void)
|
||||
{
|
||||
start_sp = GETSP ();
|
||||
if (! initialized)
|
||||
if (!initialized)
|
||||
me ();
|
||||
}
|
||||
|
||||
@ -333,13 +333,14 @@ malloc (size_t len)
|
||||
if (__builtin_expect (initialized <= 0, 0))
|
||||
{
|
||||
if (initialized == -1)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
me ();
|
||||
}
|
||||
|
||||
/* If this is not the correct program just use the normal function. */
|
||||
if (not_me)
|
||||
return (*mallocp) (len);
|
||||
return (*mallocp)(len);
|
||||
|
||||
/* Keep track of number of calls. */
|
||||
catomic_increment (&calls[idx_malloc]);
|
||||
@ -356,7 +357,7 @@ malloc (size_t len)
|
||||
catomic_increment (&calls_total);
|
||||
|
||||
/* Do the real work. */
|
||||
result = (struct header *) (*mallocp) (len + sizeof (struct header));
|
||||
result = (struct header *) (*mallocp)(len + sizeof (struct header));
|
||||
if (result == NULL)
|
||||
{
|
||||
catomic_increment (&failed[idx_malloc]);
|
||||
@ -384,13 +385,14 @@ realloc (void *old, size_t len)
|
||||
if (__builtin_expect (initialized <= 0, 0))
|
||||
{
|
||||
if (initialized == -1)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
me ();
|
||||
}
|
||||
|
||||
/* If this is not the correct program just use the normal function. */
|
||||
if (not_me)
|
||||
return (*reallocp) (old, len);
|
||||
return (*reallocp)(old, len);
|
||||
|
||||
if (old == NULL)
|
||||
{
|
||||
@ -402,8 +404,9 @@ realloc (void *old, size_t len)
|
||||
{
|
||||
real = ((struct header *) old) - 1;
|
||||
if (real->magic != MAGIC)
|
||||
/* This is no memory allocated here. */
|
||||
return (*reallocp) (old, len);
|
||||
/* This is no memory allocated here. */
|
||||
return (*reallocp)(old, len);
|
||||
|
||||
old_len = real->length;
|
||||
}
|
||||
|
||||
@ -442,7 +445,7 @@ realloc (void *old, size_t len)
|
||||
catomic_increment (&calls_total);
|
||||
|
||||
/* Do the real work. */
|
||||
result = (struct header *) (*reallocp) (real, len + sizeof (struct header));
|
||||
result = (struct header *) (*reallocp)(real, len + sizeof (struct header));
|
||||
if (result == NULL)
|
||||
{
|
||||
catomic_increment (&failed[idx_realloc]);
|
||||
@ -476,13 +479,14 @@ calloc (size_t n, size_t len)
|
||||
if (__builtin_expect (initialized <= 0, 0))
|
||||
{
|
||||
if (initialized == -1)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
me ();
|
||||
}
|
||||
|
||||
/* If this is not the correct program just use the normal function. */
|
||||
if (not_me)
|
||||
return (*callocp) (n, len);
|
||||
return (*callocp)(n, len);
|
||||
|
||||
/* Keep track of number of calls. */
|
||||
catomic_increment (&calls[idx_calloc]);
|
||||
@ -499,7 +503,7 @@ calloc (size_t n, size_t len)
|
||||
++calls_total;
|
||||
|
||||
/* Do the real work. */
|
||||
result = (struct header *) (*mallocp) (size + sizeof (struct header));
|
||||
result = (struct header *) (*mallocp)(size + sizeof (struct header));
|
||||
if (result == NULL)
|
||||
{
|
||||
catomic_increment (&failed[idx_calloc]);
|
||||
@ -525,7 +529,8 @@ free (void *ptr)
|
||||
if (__builtin_expect (initialized <= 0, 0))
|
||||
{
|
||||
if (initialized == -1)
|
||||
return;
|
||||
return;
|
||||
|
||||
me ();
|
||||
}
|
||||
|
||||
@ -576,17 +581,18 @@ mmap (void *start, size_t len, int prot, int flags, int fd, off_t offset)
|
||||
if (__builtin_expect (initialized <= 0, 0))
|
||||
{
|
||||
if (initialized == -1)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
me ();
|
||||
}
|
||||
|
||||
/* Always get a block. We don't need extra memory. */
|
||||
result = (*mmapp) (start, len, prot, flags, fd, offset);
|
||||
result = (*mmapp)(start, len, prot, flags, fd, offset);
|
||||
|
||||
if (!not_me && trace_mmap)
|
||||
{
|
||||
int idx = (flags & MAP_ANON
|
||||
? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r);
|
||||
? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r);
|
||||
|
||||
/* Keep track of number of calls. */
|
||||
catomic_increment (&calls[idx]);
|
||||
@ -596,20 +602,20 @@ mmap (void *start, size_t len, int prot, int flags, int fd, off_t offset)
|
||||
catomic_add (&grand_total, len);
|
||||
/* Remember the size of the request. */
|
||||
if (len < 65536)
|
||||
catomic_increment (&histogram[len / 16]);
|
||||
catomic_increment (&histogram[len / 16]);
|
||||
else
|
||||
catomic_increment (&large);
|
||||
catomic_increment (&large);
|
||||
/* Total number of calls of any of the functions. */
|
||||
catomic_increment (&calls_total);
|
||||
|
||||
/* Check for failures. */
|
||||
if (result == NULL)
|
||||
catomic_increment (&failed[idx]);
|
||||
catomic_increment (&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
|
||||
the size is not tracked. */
|
||||
update_data (NULL, len, 0);
|
||||
/* Update the allocation data and write out the records if
|
||||
necessary. Note the first parameter is NULL which means
|
||||
the size is not tracked. */
|
||||
update_data (NULL, len, 0);
|
||||
}
|
||||
|
||||
/* Return the pointer to the user buffer. */
|
||||
@ -628,17 +634,18 @@ mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset)
|
||||
if (__builtin_expect (initialized <= 0, 0))
|
||||
{
|
||||
if (initialized == -1)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
me ();
|
||||
}
|
||||
|
||||
/* Always get a block. We don't need extra memory. */
|
||||
result = (*mmap64p) (start, len, prot, flags, fd, offset);
|
||||
result = (*mmap64p)(start, len, prot, flags, fd, offset);
|
||||
|
||||
if (!not_me && trace_mmap)
|
||||
{
|
||||
int idx = (flags & MAP_ANON
|
||||
? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r);
|
||||
? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r);
|
||||
|
||||
/* Keep track of number of calls. */
|
||||
catomic_increment (&calls[idx]);
|
||||
@ -648,20 +655,20 @@ mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset)
|
||||
catomic_add (&grand_total, len);
|
||||
/* Remember the size of the request. */
|
||||
if (len < 65536)
|
||||
catomic_increment (&histogram[len / 16]);
|
||||
catomic_increment (&histogram[len / 16]);
|
||||
else
|
||||
catomic_increment (&large);
|
||||
catomic_increment (&large);
|
||||
/* Total number of calls of any of the functions. */
|
||||
catomic_increment (&calls_total);
|
||||
|
||||
/* Check for failures. */
|
||||
if (result == NULL)
|
||||
catomic_increment (&failed[idx]);
|
||||
catomic_increment (&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
|
||||
the size is not tracked. */
|
||||
update_data (NULL, len, 0);
|
||||
/* Update the allocation data and write out the records if
|
||||
necessary. Note the first parameter is NULL which means
|
||||
the size is not tracked. */
|
||||
update_data (NULL, len, 0);
|
||||
}
|
||||
|
||||
/* Return the pointer to the user buffer. */
|
||||
@ -672,7 +679,7 @@ mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset)
|
||||
/* `mremap' replacement. We do not have to keep track of the size since
|
||||
`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;
|
||||
@ -685,49 +692,50 @@ mremap (void *start, size_t old_len, size_t len, int flags, ...)
|
||||
if (__builtin_expect (initialized <= 0, 0))
|
||||
{
|
||||
if (initialized == -1)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
me ();
|
||||
}
|
||||
|
||||
/* 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, newaddr);
|
||||
|
||||
if (!not_me && trace_mmap)
|
||||
{
|
||||
/* Keep track of number of calls. */
|
||||
catomic_increment (&calls[idx_mremap]);
|
||||
if (len > old_len)
|
||||
{
|
||||
/* Keep track of total memory consumption for `malloc'. */
|
||||
catomic_add (&total[idx_mremap], len - old_len);
|
||||
/* Keep track of total memory requirement. */
|
||||
catomic_add (&grand_total, len - old_len);
|
||||
}
|
||||
{
|
||||
/* Keep track of total memory consumption for `malloc'. */
|
||||
catomic_add (&total[idx_mremap], len - old_len);
|
||||
/* Keep track of total memory requirement. */
|
||||
catomic_add (&grand_total, len - old_len);
|
||||
}
|
||||
/* Remember the size of the request. */
|
||||
if (len < 65536)
|
||||
catomic_increment (&histogram[len / 16]);
|
||||
catomic_increment (&histogram[len / 16]);
|
||||
else
|
||||
catomic_increment (&large);
|
||||
catomic_increment (&large);
|
||||
/* Total number of calls of any of the functions. */
|
||||
catomic_increment (&calls_total);
|
||||
|
||||
/* Check for failures. */
|
||||
if (result == NULL)
|
||||
catomic_increment (&failed[idx_mremap]);
|
||||
catomic_increment (&failed[idx_mremap]);
|
||||
else
|
||||
{
|
||||
/* Record whether the reduction/increase happened in place. */
|
||||
if (start == result)
|
||||
catomic_increment (&inplace_mremap);
|
||||
/* Was the buffer increased? */
|
||||
if (old_len > len)
|
||||
catomic_increment (&decreasing_mremap);
|
||||
{
|
||||
/* Record whether the reduction/increase happened in place. */
|
||||
if (start == result)
|
||||
catomic_increment (&inplace_mremap);
|
||||
/* Was the buffer increased? */
|
||||
if (old_len > len)
|
||||
catomic_increment (&decreasing_mremap);
|
||||
|
||||
/* Update the allocation data and write out the records if
|
||||
necessary. Note the first parameter is NULL which means
|
||||
the size is not tracked. */
|
||||
update_data (NULL, len, old_len);
|
||||
}
|
||||
/* Update the allocation data and write out the records if
|
||||
necessary. Note the first parameter is NULL which means
|
||||
the size is not tracked. */
|
||||
update_data (NULL, len, old_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the pointer to the user buffer. */
|
||||
@ -745,12 +753,13 @@ munmap (void *start, size_t len)
|
||||
if (__builtin_expect (initialized <= 0, 0))
|
||||
{
|
||||
if (initialized == -1)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
me ();
|
||||
}
|
||||
|
||||
/* Do the real work. */
|
||||
result = (*munmapp) (start, len);
|
||||
result = (*munmapp)(start, len);
|
||||
|
||||
if (!not_me && trace_mmap)
|
||||
{
|
||||
@ -758,16 +767,16 @@ munmap (void *start, size_t len)
|
||||
catomic_increment (&calls[idx_munmap]);
|
||||
|
||||
if (__builtin_expect (result == 0, 1))
|
||||
{
|
||||
/* Keep track of total memory freed using `free'. */
|
||||
catomic_add (&total[idx_munmap], len);
|
||||
{
|
||||
/* Keep track of total memory freed using `free'. */
|
||||
catomic_add (&total[idx_munmap], len);
|
||||
|
||||
/* Update the allocation data and write out the records if
|
||||
necessary. */
|
||||
update_data (NULL, 0, len);
|
||||
}
|
||||
/* Update the allocation data and write out the records if
|
||||
necessary. */
|
||||
update_data (NULL, 0, len);
|
||||
}
|
||||
else
|
||||
catomic_increment (&failed[idx_munmap]);
|
||||
catomic_increment (&failed[idx_munmap]);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -785,6 +794,7 @@ dest (void)
|
||||
/* If we haven't done anything here just return. */
|
||||
if (not_me)
|
||||
return;
|
||||
|
||||
/* If we should call any of the memory functions don't do any profiling. */
|
||||
not_me = true;
|
||||
|
||||
@ -793,13 +803,13 @@ dest (void)
|
||||
{
|
||||
/* Write the partially filled buffer. */
|
||||
if (buffer_cnt > buffer_size)
|
||||
write (fd, buffer + buffer_size,
|
||||
(buffer_cnt - buffer_size) * sizeof (struct entry));
|
||||
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. */
|
||||
here when we opened the file. */
|
||||
lseek (fd, 0, SEEK_SET);
|
||||
/* Write out a record containing the total size. */
|
||||
first.stack = peak_total;
|
||||
@ -824,25 +834,25 @@ dest (void)
|
||||
\e[00;34mrealloc|\e[0m %10lu %12llu %s%12lu\e[00;00m (nomove:%ld, dec:%ld, free:%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,
|
||||
(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]);
|
||||
(unsigned long long int) 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]);
|
||||
|
||||
if (trace_mmap)
|
||||
fprintf (stderr, "\
|
||||
@ -851,28 +861,28 @@ dest (void)
|
||||
\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 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]);
|
||||
(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]);
|
||||
|
||||
/* Write out a histoogram of the sizes of the allocations. */
|
||||
fprintf (stderr, "\e[01;32mHistogram for block sizes:\e[0;0m\n");
|
||||
@ -887,20 +897,20 @@ dest (void)
|
||||
/* Only write out the nonzero entries. */
|
||||
if (histogram[cnt / 16] != 0)
|
||||
{
|
||||
percent = (histogram[cnt / 16] * 100) / calls_total;
|
||||
fprintf (stderr, "%5d-%-5d%12lu ", cnt, cnt + 15,
|
||||
(unsigned long int) histogram[cnt / 16]);
|
||||
if (percent == 0)
|
||||
fputs (" <1% \e[41;37m", stderr);
|
||||
else
|
||||
fprintf (stderr, "%3d%% \e[41;37m", percent);
|
||||
percent = (histogram[cnt / 16] * 100) / calls_total;
|
||||
fprintf (stderr, "%5d-%-5d%12lu ", cnt, cnt + 15,
|
||||
(unsigned long int) histogram[cnt / 16]);
|
||||
if (percent == 0)
|
||||
fputs (" <1% \e[41;37m", stderr);
|
||||
else
|
||||
fprintf (stderr, "%3d%% \e[41;37m", percent);
|
||||
|
||||
/* Draw a bar with a length corresponding to the current
|
||||
/* Draw a bar with a length corresponding to the current
|
||||
percentage. */
|
||||
percent = (histogram[cnt / 16] * 50) / maxcalls;
|
||||
while (percent-- > 0)
|
||||
fputc ('=', stderr);
|
||||
fputs ("\e[0;0m\n", stderr);
|
||||
percent = (histogram[cnt / 16] * 50) / maxcalls;
|
||||
while (percent-- > 0)
|
||||
fputc ('=', stderr);
|
||||
fputs ("\e[0;0m\n", stderr);
|
||||
}
|
||||
|
||||
if (large != 0)
|
||||
@ -908,9 +918,9 @@ dest (void)
|
||||
percent = (large * 100) / calls_total;
|
||||
fprintf (stderr, " large %12lu ", (unsigned long int) large);
|
||||
if (percent == 0)
|
||||
fputs (" <1% \e[41;37m", stderr);
|
||||
fputs (" <1% \e[41;37m", stderr);
|
||||
else
|
||||
fprintf (stderr, "%3d%% \e[41;37m", percent);
|
||||
fprintf (stderr, "%3d%% \e[41;37m", percent);
|
||||
percent = (large * 50) / maxcalls;
|
||||
while (percent-- > 0)
|
||||
fputc ('=', stderr);
|
||||
|
@ -53,24 +53,24 @@
|
||||
/* Definitions of arguments for argp functions. */
|
||||
static const struct argp_option options[] =
|
||||
{
|
||||
{ "output", 'o', N_("FILE"), 0, N_("Name output file") },
|
||||
{ "string", 's', N_("STRING"), 0, N_("Title string used in output graphic") },
|
||||
{ "time", 't', NULL, 0, N_("\
|
||||
{ "output", 'o', N_ ("FILE"), 0, N_ ("Name output file") },
|
||||
{ "string", 's', N_ ("STRING"), 0, N_ ("Title string used in output graphic") },
|
||||
{ "time", 't', NULL, 0, N_ (" \
|
||||
Generate output linear to time (default is linear to number of function calls)\
|
||||
") },
|
||||
{ "total", 'T', NULL, 0,
|
||||
N_("Also draw graph for total memory consumption") },
|
||||
{ "x-size", 'x', N_("VALUE"), 0,
|
||||
N_("Make output graphic VALUE pixels wide") },
|
||||
{ "y-size", 'y', "VALUE", 0, N_("Make output graphic VALUE pixels high") },
|
||||
N_ ("Also draw graph for total memory consumption") },
|
||||
{ "x-size", 'x', N_ ("VALUE"), 0,
|
||||
N_ ("Make output graphic VALUE pixels wide") },
|
||||
{ "y-size", 'y', "VALUE", 0, N_ ("Make output graphic VALUE pixels high") },
|
||||
{ NULL, 0, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
/* Short description of program. */
|
||||
static const char doc[] = N_("Generate graphic from memory profiling data");
|
||||
static const char doc[] = N_ ("Generate graphic from memory profiling data");
|
||||
|
||||
/* Strings for arguments in help texts. */
|
||||
static const char args_doc[] = N_("DATAFILE [OUTFILE]");
|
||||
static const char args_doc[] = N_ ("DATAFILE [OUTFILE]");
|
||||
|
||||
/* Prototype for option handler. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state);
|
||||
@ -152,7 +152,7 @@ main (int argc, char *argv[])
|
||||
if (remaining >= argc || remaining + 2 < argc)
|
||||
{
|
||||
argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
|
||||
program_invocation_short_name);
|
||||
program_invocation_short_name);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -197,21 +197,21 @@ main (int argc, char *argv[])
|
||||
if (maxsize_heap == 0 && maxsize_stack == 0)
|
||||
{
|
||||
/* The program aborted before memusage was able to write the
|
||||
information about the maximum heap and stack use. Repair
|
||||
the file now. */
|
||||
information about the maximum heap and stack use. Repair
|
||||
the file now. */
|
||||
struct entry next;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (read (fd, &next, sizeof (next)) == 0)
|
||||
break;
|
||||
if (next.heap > maxsize_heap)
|
||||
maxsize_heap = next.heap;
|
||||
if (next.stack > maxsize_stack)
|
||||
maxsize_stack = next.stack;
|
||||
if (maxsize_heap + maxsize_stack > maxsize_total)
|
||||
maxsize_total = maxsize_heap + maxsize_stack;
|
||||
}
|
||||
{
|
||||
if (read (fd, &next, sizeof (next)) == 0)
|
||||
break;
|
||||
if (next.heap > maxsize_heap)
|
||||
maxsize_heap = next.heap;
|
||||
if (next.stack > maxsize_stack)
|
||||
maxsize_stack = next.stack;
|
||||
if (maxsize_heap + maxsize_stack > maxsize_total)
|
||||
maxsize_total = maxsize_heap + maxsize_stack;
|
||||
}
|
||||
|
||||
headent[0].stack = maxsize_total;
|
||||
headent[1].heap = maxsize_heap;
|
||||
@ -227,7 +227,7 @@ main (int argc, char *argv[])
|
||||
if (also_total)
|
||||
{
|
||||
/* We use one scale and since we also draw the total amount of
|
||||
memory used we have to adapt the maximum. */
|
||||
memory used we have to adapt the maximum. */
|
||||
maxsize_heap = maxsize_total;
|
||||
maxsize_stack = maxsize_total;
|
||||
}
|
||||
@ -292,145 +292,145 @@ main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
gdImageString (im_out, gdFontSmall, 38, ysize - 14, (unsigned char *) "0",
|
||||
blue);
|
||||
blue);
|
||||
snprintf (buf, sizeof (buf), heap_format, 0);
|
||||
gdImageString (im_out, gdFontSmall, maxsize_heap < 1024 ? 32 : 26,
|
||||
ysize - 26, (unsigned char *) buf, red);
|
||||
ysize - 26, (unsigned char *) buf, red);
|
||||
snprintf (buf, sizeof (buf), stack_format, 0);
|
||||
gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26,
|
||||
(unsigned char *) buf, green);
|
||||
(unsigned char *) buf, green);
|
||||
|
||||
if (string != NULL)
|
||||
gdImageString (im_out, gdFontLarge, (xsize - strlen (string) * 8) / 2,
|
||||
2, (unsigned char *) string, green);
|
||||
2, (unsigned char *) string, green);
|
||||
|
||||
gdImageStringUp (im_out, gdFontSmall, 1, ysize / 2 - 10,
|
||||
(unsigned char *) "allocated", red);
|
||||
(unsigned char *) "allocated", red);
|
||||
gdImageStringUp (im_out, gdFontSmall, 11, ysize / 2 - 10,
|
||||
(unsigned char *) "memory", red);
|
||||
(unsigned char *) "memory", red);
|
||||
|
||||
gdImageStringUp (im_out, gdFontSmall, xsize - 39, ysize / 2 - 10,
|
||||
(unsigned char *) "used", green);
|
||||
(unsigned char *) "used", green);
|
||||
gdImageStringUp (im_out, gdFontSmall, xsize - 27, ysize / 2 - 10,
|
||||
(unsigned char *) "stack", green);
|
||||
(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);
|
||||
(unsigned char *) buf, red);
|
||||
snprintf (buf, sizeof (buf), stack_format, maxsize_stack / stack_scale);
|
||||
gdImageString (im_out, gdFontSmall, xsize - 37, 14,
|
||||
(unsigned char *) buf, green);
|
||||
(unsigned char *) buf, green);
|
||||
|
||||
for (line = 1; line <= 3; ++line)
|
||||
{
|
||||
if (maxsize_heap > 0)
|
||||
{
|
||||
cnt = (((ysize - 40) * (maxsize_heap / 4 * line / heap_scale))
|
||||
/ (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 / heap_scale);
|
||||
gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6,
|
||||
ysize - 26 - cnt, (unsigned char *) buf, red);
|
||||
}
|
||||
{
|
||||
cnt = (((ysize - 40) * (maxsize_heap / 4 * line / heap_scale))
|
||||
/ (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 / heap_scale);
|
||||
gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6,
|
||||
ysize - 26 - cnt, (unsigned char *) buf, red);
|
||||
}
|
||||
else
|
||||
cnt = 0;
|
||||
cnt = 0;
|
||||
|
||||
if (maxsize_stack > 0)
|
||||
cnt2 = (((ysize - 40) * (maxsize_stack / 4 * line / stack_scale))
|
||||
/ (maxsize_stack / stack_scale));
|
||||
cnt2 = (((ysize - 40) * (maxsize_stack / 4 * line / stack_scale))
|
||||
/ (maxsize_stack / stack_scale));
|
||||
else
|
||||
cnt2 = 0;
|
||||
cnt2 = 0;
|
||||
|
||||
if (cnt != cnt2)
|
||||
gdImageDashedLine (im_out, 40, ysize - 20 - cnt2, xsize - 40,
|
||||
ysize - 20 - cnt2, green);
|
||||
gdImageDashedLine (im_out, 40, ysize - 20 - cnt2, xsize - 40,
|
||||
ysize - 20 - cnt2, green);
|
||||
snprintf (buf, sizeof (buf), stack_format, maxsize_stack / 4 * line /
|
||||
stack_scale);
|
||||
stack_scale);
|
||||
gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26 - cnt2,
|
||||
(unsigned char *) buf, green);
|
||||
(unsigned char *) buf, green);
|
||||
}
|
||||
|
||||
snprintf (buf, sizeof (buf), "%llu", (unsigned long long) total);
|
||||
gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14,
|
||||
(unsigned char *) buf, blue);
|
||||
(unsigned char *) buf, blue);
|
||||
|
||||
if (!time_based)
|
||||
{
|
||||
uint64_t previously = start_time;
|
||||
|
||||
gdImageString (im_out, gdFontSmall, 40 + (xsize - 32 * 6 - 80) / 2,
|
||||
ysize - 12,
|
||||
(unsigned char *) "# memory handling function calls",
|
||||
blue);
|
||||
ysize - 12,
|
||||
(unsigned char *) "# memory handling function calls",
|
||||
blue);
|
||||
|
||||
|
||||
last_stack = last_heap = last_total = ysize - 20;
|
||||
for (cnt = 1; cnt <= total; ++cnt)
|
||||
{
|
||||
struct entry entry;
|
||||
size_t new[2];
|
||||
uint64_t now;
|
||||
{
|
||||
struct entry entry;
|
||||
size_t new[2];
|
||||
uint64_t now;
|
||||
|
||||
read (fd, &entry, sizeof (entry));
|
||||
read (fd, &entry, sizeof (entry));
|
||||
|
||||
now = ((uint64_t) entry.time_high) << 32 | entry.time_low;
|
||||
now = ((uint64_t) entry.time_high) << 32 | entry.time_low;
|
||||
|
||||
if ((((previously - start_time) * 100) / total_time) % 10 < 5)
|
||||
gdImageFilledRectangle (im_out,
|
||||
40 + ((cnt - 1) * (xsize - 80)) / total,
|
||||
ysize - 19,
|
||||
39 + (cnt * (xsize - 80)) / total,
|
||||
ysize - 14, yellow);
|
||||
previously = now;
|
||||
if ((((previously - start_time) * 100) / total_time) % 10 < 5)
|
||||
gdImageFilledRectangle (im_out,
|
||||
40 + ((cnt - 1) * (xsize - 80)) / total,
|
||||
ysize - 19,
|
||||
39 + (cnt * (xsize - 80)) / total,
|
||||
ysize - 14, yellow);
|
||||
previously = now;
|
||||
|
||||
if (also_total && maxsize_heap > 0)
|
||||
{
|
||||
size_t new3;
|
||||
if (also_total && maxsize_heap > 0)
|
||||
{
|
||||
size_t new3;
|
||||
|
||||
new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40))
|
||||
* (entry.heap + entry.stack))
|
||||
/ maxsize_heap);
|
||||
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
|
||||
last_total,
|
||||
40 + ((xsize - 80) * cnt) / total, new3,
|
||||
black);
|
||||
last_total = new3;
|
||||
}
|
||||
new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40))
|
||||
* (entry.heap + entry.stack))
|
||||
/ maxsize_heap);
|
||||
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
|
||||
last_total,
|
||||
40 + ((xsize - 80) * cnt) / total, new3,
|
||||
black);
|
||||
last_total = new3;
|
||||
}
|
||||
|
||||
if (maxsize_heap > 0)
|
||||
{
|
||||
new[0] = ((ysize - 20)
|
||||
- ((((unsigned long long int) (ysize - 40))
|
||||
* entry.heap) / maxsize_heap));
|
||||
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
|
||||
last_heap, 40 + ((xsize - 80) * cnt) / total,
|
||||
new[0], red);
|
||||
last_heap = new[0];
|
||||
}
|
||||
if (maxsize_heap > 0)
|
||||
{
|
||||
new[0] = ((ysize - 20)
|
||||
- ((((unsigned long long int) (ysize - 40))
|
||||
* entry.heap) / maxsize_heap));
|
||||
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
|
||||
last_heap, 40 + ((xsize - 80) * cnt) / total,
|
||||
new[0], red);
|
||||
last_heap = new[0];
|
||||
}
|
||||
|
||||
if (maxsize_stack > 0)
|
||||
{
|
||||
new[1] = ((ysize - 20)
|
||||
- ((((unsigned long long int) (ysize - 40))
|
||||
* entry.stack) / maxsize_stack));
|
||||
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
|
||||
last_stack, 40 + ((xsize - 80) * cnt) / total,
|
||||
new[1], green);
|
||||
last_stack = new[1];
|
||||
}
|
||||
}
|
||||
if (maxsize_stack > 0)
|
||||
{
|
||||
new[1] = ((ysize - 20)
|
||||
- ((((unsigned long long int) (ysize - 40))
|
||||
* entry.stack) / maxsize_stack));
|
||||
gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
|
||||
last_stack, 40 + ((xsize - 80) * cnt) / total,
|
||||
new[1], green);
|
||||
last_stack = new[1];
|
||||
}
|
||||
}
|
||||
|
||||
cnt = 0;
|
||||
while (cnt < total)
|
||||
{
|
||||
gdImageLine (im_out, 40 + ((xsize - 80) * cnt) / total, ysize - 20,
|
||||
40 + ((xsize - 80) * cnt) / total, ysize - 15, blue);
|
||||
cnt += MAX (1, total / 20);
|
||||
}
|
||||
{
|
||||
gdImageLine (im_out, 40 + ((xsize - 80) * cnt) / total, ysize - 20,
|
||||
40 + ((xsize - 80) * cnt) / total, ysize - 15, blue);
|
||||
cnt += MAX (1, total / 20);
|
||||
}
|
||||
gdImageLine (im_out, xsize - 40, ysize - 20, xsize - 40, ysize - 15,
|
||||
blue);
|
||||
blue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -438,67 +438,67 @@ main (int argc, char *argv[])
|
||||
size_t last_xpos = 40;
|
||||
|
||||
gdImageString (im_out, gdFontSmall, 40 + (xsize - 39 * 6 - 80) / 2,
|
||||
ysize - 12,
|
||||
(unsigned char *) "\
|
||||
ysize - 12,
|
||||
(unsigned char *) " \
|
||||
# memory handling function calls / time", blue);
|
||||
|
||||
for (cnt = 0; cnt < 20; cnt += 2)
|
||||
gdImageFilledRectangle (im_out,
|
||||
40 + (cnt * (xsize - 80)) / 20, ysize - 19,
|
||||
39 + ((cnt + 1) * (xsize - 80)) / 20,
|
||||
ysize - 14, yellow);
|
||||
gdImageFilledRectangle (im_out,
|
||||
40 + (cnt * (xsize - 80)) / 20, ysize - 19,
|
||||
39 + ((cnt + 1) * (xsize - 80)) / 20,
|
||||
ysize - 14, yellow);
|
||||
|
||||
last_stack = last_heap = last_total = ysize - 20;
|
||||
for (cnt = 1; cnt <= total; ++cnt)
|
||||
{
|
||||
struct entry entry;
|
||||
size_t new[2];
|
||||
size_t xpos;
|
||||
uint64_t now;
|
||||
{
|
||||
struct entry entry;
|
||||
size_t new[2];
|
||||
size_t xpos;
|
||||
uint64_t now;
|
||||
|
||||
read (fd, &entry, sizeof (entry));
|
||||
read (fd, &entry, sizeof (entry));
|
||||
|
||||
now = ((uint64_t) entry.time_high) << 32 | entry.time_low;
|
||||
xpos = 40 + ((xsize - 80) * (now - start_time)) / total_time;
|
||||
now = ((uint64_t) entry.time_high) << 32 | entry.time_low;
|
||||
xpos = 40 + ((xsize - 80) * (now - start_time)) / total_time;
|
||||
|
||||
if (cnt == next_tick)
|
||||
{
|
||||
gdImageLine (im_out, xpos, ysize - 20, xpos, ysize - 15, blue);
|
||||
next_tick += MAX (1, total / 20);
|
||||
}
|
||||
if (cnt == next_tick)
|
||||
{
|
||||
gdImageLine (im_out, xpos, ysize - 20, xpos, ysize - 15, blue);
|
||||
next_tick += MAX (1, total / 20);
|
||||
}
|
||||
|
||||
if (also_total && maxsize_heap > 0)
|
||||
{
|
||||
size_t new3;
|
||||
if (also_total && maxsize_heap > 0)
|
||||
{
|
||||
size_t new3;
|
||||
|
||||
new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40))
|
||||
* (entry.heap + entry.stack))
|
||||
/ maxsize_heap);
|
||||
gdImageLine (im_out, last_xpos, last_total, xpos, new3, black);
|
||||
last_total = new3;
|
||||
}
|
||||
new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40))
|
||||
* (entry.heap + entry.stack))
|
||||
/ maxsize_heap);
|
||||
gdImageLine (im_out, last_xpos, last_total, xpos, new3, black);
|
||||
last_total = new3;
|
||||
}
|
||||
|
||||
if (maxsize_heap > 0)
|
||||
{
|
||||
new[0] = ((ysize - 20)
|
||||
- ((((unsigned long long int) (ysize - 40))
|
||||
* entry.heap) / maxsize_heap));
|
||||
gdImageLine (im_out, last_xpos, last_heap, xpos, new[0], red);
|
||||
last_heap = new[0];
|
||||
}
|
||||
if (maxsize_heap > 0)
|
||||
{
|
||||
new[0] = ((ysize - 20)
|
||||
- ((((unsigned long long int) (ysize - 40))
|
||||
* entry.heap) / maxsize_heap));
|
||||
gdImageLine (im_out, last_xpos, last_heap, xpos, new[0], red);
|
||||
last_heap = new[0];
|
||||
}
|
||||
|
||||
if (maxsize_stack > 0)
|
||||
{
|
||||
new[1] = ((ysize - 20)
|
||||
- ((((unsigned long long int) (ysize - 40))
|
||||
* entry.stack) / maxsize_stack));
|
||||
gdImageLine (im_out, last_xpos, last_stack, xpos, new[1],
|
||||
green);
|
||||
last_stack = new[1];
|
||||
}
|
||||
if (maxsize_stack > 0)
|
||||
{
|
||||
new[1] = ((ysize - 20)
|
||||
- ((((unsigned long long int) (ysize - 40))
|
||||
* entry.stack) / maxsize_stack));
|
||||
gdImageLine (im_out, last_xpos, last_stack, xpos, new[1],
|
||||
green);
|
||||
last_stack = new[1];
|
||||
}
|
||||
|
||||
last_xpos = xpos;
|
||||
}
|
||||
last_xpos = xpos;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out the result. */
|
||||
@ -537,12 +537,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
case 'x':
|
||||
xsize = atoi (arg);
|
||||
if (xsize == 0)
|
||||
xsize = XSIZE;
|
||||
xsize = XSIZE;
|
||||
break;
|
||||
case 'y':
|
||||
ysize = atoi (arg);
|
||||
if (ysize == 0)
|
||||
ysize = XSIZE;
|
||||
ysize = XSIZE;
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
@ -563,8 +563,10 @@ more_help (int key, const char *text, void *input)
|
||||
if (asprintf (&tp, gettext ("\
|
||||
For bug reporting instructions, please see:\n\
|
||||
%s.\n"), REPORT_BUGS_TO) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return tp;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -15,27 +15,27 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _MALLOC_INTERNAL
|
||||
#define _MALLOC_INTERNAL
|
||||
#include <malloc.h>
|
||||
#ifndef _MALLOC_INTERNAL
|
||||
# define _MALLOC_INTERNAL
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifndef __GNU_LIBRARY__
|
||||
#define __sbrk sbrk
|
||||
#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>
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
extern void *__sbrk (ptrdiff_t increment) __THROW;
|
||||
libc_hidden_proto (__sbrk)
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
/* Allocate INCREMENT more bytes of data space,
|
||||
@ -47,6 +47,7 @@ __default_morecore (ptrdiff_t increment)
|
||||
void *result = (void *) __sbrk (increment);
|
||||
if (result == (void *) -1)
|
||||
return NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
libc_hidden_def (__default_morecore)
|
||||
|
179
malloc/mtrace.c
179
malloc/mtrace.c
@ -1,8 +1,8 @@
|
||||
/* More debugging hooks for `malloc'.
|
||||
Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written April 2, 1991 by John Gilmore of Cygnus Support.
|
||||
Based on mcheck.c by Mike Haertel.
|
||||
Written April 2, 1991 by John Gilmore of Cygnus Support.
|
||||
Based on mcheck.c by Mike Haertel.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -18,11 +18,11 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _MALLOC_INTERNAL
|
||||
#define _MALLOC_INTERNAL
|
||||
#include <malloc.h>
|
||||
#include <mcheck.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#ifndef _MALLOC_INTERNAL
|
||||
# define _MALLOC_INTERNAL
|
||||
# include <malloc.h>
|
||||
# include <mcheck.h>
|
||||
# include <bits/libc-lock.h>
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h>
|
||||
@ -48,7 +48,7 @@
|
||||
#define TRACE_BUFFER_SIZE 512
|
||||
|
||||
static FILE *mallstream;
|
||||
static const char mallenv[]= "MALLOC_TRACE";
|
||||
static const char mallenv[] = "MALLOC_TRACE";
|
||||
static char *malloc_trace_buffer;
|
||||
|
||||
__libc_lock_define_initialized (static, lock);
|
||||
@ -60,9 +60,9 @@ __ptr_t mallwatch;
|
||||
static void (*tr_old_free_hook) (__ptr_t ptr, const __ptr_t);
|
||||
static __ptr_t (*tr_old_malloc_hook) (size_t size, const __ptr_t);
|
||||
static __ptr_t (*tr_old_realloc_hook) (__ptr_t ptr, size_t size,
|
||||
const __ptr_t);
|
||||
const __ptr_t);
|
||||
static __ptr_t (*tr_old_memalign_hook) (size_t __alignment, size_t __size,
|
||||
const __ptr_t);
|
||||
const __ptr_t);
|
||||
|
||||
/* This function is called when the block being alloc'd, realloc'd, or
|
||||
freed has an address matching the variable "mallwatch". In a debugger,
|
||||
@ -79,39 +79,38 @@ libc_hidden_def (tr_break)
|
||||
|
||||
static void tr_where (const __ptr_t, Dl_info *) __THROW internal_function;
|
||||
static void
|
||||
internal_function
|
||||
tr_where (caller, info)
|
||||
const __ptr_t caller;
|
||||
Dl_info *info;
|
||||
internal_function tr_where (caller, info)
|
||||
const __ptr_t caller;
|
||||
Dl_info *info;
|
||||
{
|
||||
if (caller != NULL)
|
||||
{
|
||||
if (info != NULL)
|
||||
{
|
||||
char *buf = (char *) "";
|
||||
if (info->dli_sname != NULL)
|
||||
{
|
||||
size_t len = strlen (info->dli_sname);
|
||||
buf = alloca (len + 6 + 2 * sizeof (void *));
|
||||
{
|
||||
char *buf = (char *) "";
|
||||
if (info->dli_sname != NULL)
|
||||
{
|
||||
size_t len = strlen (info->dli_sname);
|
||||
buf = alloca (len + 6 + 2 * sizeof (void *));
|
||||
|
||||
buf[0] = '(';
|
||||
__stpcpy (_fitoa (caller >= (const __ptr_t) info->dli_saddr
|
||||
? caller - (const __ptr_t) info->dli_saddr
|
||||
: (const __ptr_t) info->dli_saddr - caller,
|
||||
__stpcpy (__mempcpy (buf + 1, info->dli_sname,
|
||||
len),
|
||||
caller >= (__ptr_t) info->dli_saddr
|
||||
? "+0x" : "-0x"),
|
||||
16, 0),
|
||||
")");
|
||||
}
|
||||
buf[0] = '(';
|
||||
__stpcpy (_fitoa (caller >= (const __ptr_t) info->dli_saddr
|
||||
? caller - (const __ptr_t) info->dli_saddr
|
||||
: (const __ptr_t) info->dli_saddr - caller,
|
||||
__stpcpy (__mempcpy (buf + 1, info->dli_sname,
|
||||
len),
|
||||
caller >= (__ptr_t) info->dli_saddr
|
||||
? "+0x" : "-0x"),
|
||||
16, 0),
|
||||
")");
|
||||
}
|
||||
|
||||
fprintf (mallstream, "@ %s%s%s[%p] ",
|
||||
info->dli_fname ?: "", info->dli_fname ? ":" : "",
|
||||
buf, caller);
|
||||
}
|
||||
fprintf (mallstream, "@ %s%s%s[%p] ",
|
||||
info->dli_fname ? : "", info->dli_fname ? ":" : "",
|
||||
buf, caller);
|
||||
}
|
||||
else
|
||||
fprintf (mallstream, "@ [%p] ", caller);
|
||||
fprintf (mallstream, "@ [%p] ", caller);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,10 +130,9 @@ lock_and_info (const __ptr_t caller, Dl_info *mem)
|
||||
|
||||
|
||||
static void tr_freehook (__ptr_t, const __ptr_t) __THROW;
|
||||
static void
|
||||
tr_freehook (ptr, caller)
|
||||
__ptr_t ptr;
|
||||
const __ptr_t caller;
|
||||
static void tr_freehook (ptr, caller)
|
||||
__ptr_t ptr;
|
||||
const __ptr_t caller;
|
||||
{
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
@ -152,7 +150,7 @@ tr_freehook (ptr, caller)
|
||||
}
|
||||
__free_hook = tr_old_free_hook;
|
||||
if (tr_old_free_hook != NULL)
|
||||
(*tr_old_free_hook) (ptr, caller);
|
||||
(*tr_old_free_hook)(ptr, caller);
|
||||
else
|
||||
free (ptr);
|
||||
__free_hook = tr_freehook;
|
||||
@ -160,10 +158,9 @@ tr_freehook (ptr, caller)
|
||||
}
|
||||
|
||||
static __ptr_t tr_mallochook (size_t, const __ptr_t) __THROW;
|
||||
static __ptr_t
|
||||
tr_mallochook (size, caller)
|
||||
size_t size;
|
||||
const __ptr_t caller;
|
||||
static __ptr_t tr_mallochook (size, caller)
|
||||
size_t size;
|
||||
const __ptr_t caller;
|
||||
{
|
||||
__ptr_t hdr;
|
||||
|
||||
@ -172,7 +169,7 @@ tr_mallochook (size, caller)
|
||||
|
||||
__malloc_hook = tr_old_malloc_hook;
|
||||
if (tr_old_malloc_hook != NULL)
|
||||
hdr = (__ptr_t) (*tr_old_malloc_hook) (size, caller);
|
||||
hdr = (__ptr_t) (*tr_old_malloc_hook)(size, caller);
|
||||
else
|
||||
hdr = (__ptr_t) malloc (size);
|
||||
__malloc_hook = tr_mallochook;
|
||||
@ -190,12 +187,11 @@ tr_mallochook (size, caller)
|
||||
}
|
||||
|
||||
static __ptr_t tr_reallochook (__ptr_t, size_t, const __ptr_t)
|
||||
__THROW;
|
||||
static __ptr_t
|
||||
tr_reallochook (ptr, size, caller)
|
||||
__ptr_t ptr;
|
||||
size_t size;
|
||||
const __ptr_t caller;
|
||||
__THROW;
|
||||
static __ptr_t tr_reallochook (ptr, size, caller)
|
||||
__ptr_t ptr;
|
||||
size_t size;
|
||||
const __ptr_t caller;
|
||||
{
|
||||
__ptr_t hdr;
|
||||
|
||||
@ -209,7 +205,7 @@ tr_reallochook (ptr, size, caller)
|
||||
__malloc_hook = tr_old_malloc_hook;
|
||||
__realloc_hook = tr_old_realloc_hook;
|
||||
if (tr_old_realloc_hook != NULL)
|
||||
hdr = (__ptr_t) (*tr_old_realloc_hook) (ptr, size, caller);
|
||||
hdr = (__ptr_t) (*tr_old_realloc_hook)(ptr, size, caller);
|
||||
else
|
||||
hdr = (__ptr_t) realloc (ptr, size);
|
||||
__free_hook = tr_freehook;
|
||||
@ -220,10 +216,10 @@ tr_reallochook (ptr, size, caller)
|
||||
if (hdr == NULL)
|
||||
{
|
||||
if (size != 0)
|
||||
/* Failed realloc. */
|
||||
fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
|
||||
/* Failed realloc. */
|
||||
fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
|
||||
else
|
||||
fprintf (mallstream, "- %p\n", ptr);
|
||||
fprintf (mallstream, "- %p\n", ptr);
|
||||
}
|
||||
else if (ptr == NULL)
|
||||
fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
|
||||
@ -243,11 +239,10 @@ tr_reallochook (ptr, size, caller)
|
||||
}
|
||||
|
||||
static __ptr_t tr_memalignhook (size_t, size_t,
|
||||
const __ptr_t) __THROW;
|
||||
static __ptr_t
|
||||
tr_memalignhook (alignment, size, caller)
|
||||
size_t alignment, size;
|
||||
const __ptr_t caller;
|
||||
const __ptr_t) __THROW;
|
||||
static __ptr_t tr_memalignhook (alignment, size, caller)
|
||||
size_t alignment, size;
|
||||
const __ptr_t caller;
|
||||
{
|
||||
__ptr_t hdr;
|
||||
|
||||
@ -257,7 +252,7 @@ tr_memalignhook (alignment, size, caller)
|
||||
__memalign_hook = tr_old_memalign_hook;
|
||||
__malloc_hook = tr_old_malloc_hook;
|
||||
if (tr_old_memalign_hook != NULL)
|
||||
hdr = (__ptr_t) (*tr_old_memalign_hook) (alignment, size, caller);
|
||||
hdr = (__ptr_t) (*tr_old_memalign_hook)(alignment, size, caller);
|
||||
else
|
||||
hdr = (__ptr_t) memalign (alignment, size);
|
||||
__memalign_hook = tr_memalignhook;
|
||||
@ -321,44 +316,44 @@ mtrace (void)
|
||||
{
|
||||
char *mtb = malloc (TRACE_BUFFER_SIZE);
|
||||
if (mtb == NULL)
|
||||
return;
|
||||
return;
|
||||
|
||||
mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce");
|
||||
if (mallstream != NULL)
|
||||
{
|
||||
{
|
||||
#ifndef __ASSUME_O_CLOEXEC
|
||||
/* Make sure we close the file descriptor on exec. */
|
||||
int flags = __fcntl (fileno (mallstream), F_GETFD, 0);
|
||||
if (flags >= 0)
|
||||
{
|
||||
flags |= FD_CLOEXEC;
|
||||
__fcntl (fileno (mallstream), F_SETFD, flags);
|
||||
}
|
||||
/* Make sure we close the file descriptor on exec. */
|
||||
int flags = __fcntl (fileno (mallstream), F_GETFD, 0);
|
||||
if (flags >= 0)
|
||||
{
|
||||
flags |= FD_CLOEXEC;
|
||||
__fcntl (fileno (mallstream), F_SETFD, flags);
|
||||
}
|
||||
#endif
|
||||
/* Be sure it doesn't malloc its buffer! */
|
||||
malloc_trace_buffer = mtb;
|
||||
setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
|
||||
fprintf (mallstream, "= Start\n");
|
||||
tr_old_free_hook = __free_hook;
|
||||
__free_hook = tr_freehook;
|
||||
tr_old_malloc_hook = __malloc_hook;
|
||||
__malloc_hook = tr_mallochook;
|
||||
tr_old_realloc_hook = __realloc_hook;
|
||||
__realloc_hook = tr_reallochook;
|
||||
tr_old_memalign_hook = __memalign_hook;
|
||||
__memalign_hook = tr_memalignhook;
|
||||
/* Be sure it doesn't malloc its buffer! */
|
||||
malloc_trace_buffer = mtb;
|
||||
setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
|
||||
fprintf (mallstream, "= Start\n");
|
||||
tr_old_free_hook = __free_hook;
|
||||
__free_hook = tr_freehook;
|
||||
tr_old_malloc_hook = __malloc_hook;
|
||||
__malloc_hook = tr_mallochook;
|
||||
tr_old_realloc_hook = __realloc_hook;
|
||||
__realloc_hook = tr_reallochook;
|
||||
tr_old_memalign_hook = __memalign_hook;
|
||||
__memalign_hook = tr_memalignhook;
|
||||
#ifdef _LIBC
|
||||
if (!added_atexit_handler)
|
||||
{
|
||||
extern void *__dso_handle __attribute__ ((__weak__));
|
||||
added_atexit_handler = 1;
|
||||
__cxa_atexit ((void (*) (void *)) release_libc_mem, NULL,
|
||||
&__dso_handle ? __dso_handle : NULL);
|
||||
}
|
||||
if (!added_atexit_handler)
|
||||
{
|
||||
extern void *__dso_handle __attribute__ ((__weak__));
|
||||
added_atexit_handler = 1;
|
||||
__cxa_atexit ((void (*)(void *))release_libc_mem, NULL,
|
||||
&__dso_handle ? __dso_handle : NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
free (mtb);
|
||||
free (mtb);
|
||||
}
|
||||
}
|
||||
|
||||
|
145
malloc/obstack.c
145
malloc/obstack.c
@ -42,7 +42,7 @@
|
||||
program understand `configure --with-gnu-libc' and omit the object
|
||||
files, it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
|
||||
#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
|
||||
#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
|
||||
# include <gnu-versions.h>
|
||||
# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
|
||||
@ -78,10 +78,10 @@ struct fooalign
|
||||
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)
|
||||
};
|
||||
{
|
||||
DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
|
||||
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;
|
||||
@ -127,19 +127,19 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
|
||||
do not allow (expr) ? void : void. */
|
||||
|
||||
# define CALL_CHUNKFUN(h, size) \
|
||||
(((h) -> use_extra_arg) \
|
||||
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
|
||||
: (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
|
||||
(((h)->use_extra_arg) \
|
||||
? (*(h)->chunkfun)((h)->extra_arg, (size)) \
|
||||
: (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
|
||||
|
||||
# define CALL_FREEFUN(h, old_chunk) \
|
||||
do { \
|
||||
if ((h) -> use_extra_arg) \
|
||||
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
|
||||
else \
|
||||
(*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
|
||||
} while (0)
|
||||
if ((h)->use_extra_arg) \
|
||||
(*(h)->freefun)((h)->extra_arg, (old_chunk)); \
|
||||
else \
|
||||
(*(void (*)(void *))(h)->freefun)((old_chunk)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
|
||||
Objects start on multiples of ALIGNMENT (0 means use default).
|
||||
CHUNKFUN is the function to use to allocate chunks,
|
||||
@ -150,44 +150,44 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
|
||||
|
||||
int
|
||||
_obstack_begin (struct obstack *h,
|
||||
int size, int alignment,
|
||||
void *(*chunkfun) (long),
|
||||
void (*freefun) (void *))
|
||||
int size, int alignment,
|
||||
void *(*chunkfun)(long),
|
||||
void (*freefun)(void *))
|
||||
{
|
||||
struct _obstack_chunk *chunk; /* points to new chunk */
|
||||
|
||||
if (alignment == 0)
|
||||
alignment = DEFAULT_ALIGNMENT;
|
||||
if (size == 0)
|
||||
/* Default size is what GNU malloc can fit in a 4096-byte block. */
|
||||
/* Default size is what GNU malloc can fit in a 4096-byte block. */
|
||||
{
|
||||
/* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
|
||||
Use the values for range checking, because if range checking is off,
|
||||
the extra bytes won't be missed terribly, but if range checking is on
|
||||
and we used a larger request, a whole extra 4096 bytes would be
|
||||
allocated.
|
||||
Use the values for range checking, because if range checking is off,
|
||||
the extra bytes won't be missed terribly, but if range checking is on
|
||||
and we used a larger request, a whole extra 4096 bytes would be
|
||||
allocated.
|
||||
|
||||
These number are irrelevant to the new GNU malloc. I suspect it is
|
||||
less sensitive to the size of the request. */
|
||||
These number are irrelevant to the new GNU malloc. I suspect it is
|
||||
less sensitive to the size of the request. */
|
||||
int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
|
||||
+ 4 + DEFAULT_ROUNDING - 1)
|
||||
& ~(DEFAULT_ROUNDING - 1));
|
||||
+ 4 + DEFAULT_ROUNDING - 1)
|
||||
& ~(DEFAULT_ROUNDING - 1));
|
||||
size = 4096 - extra;
|
||||
}
|
||||
|
||||
h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
|
||||
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
|
||||
h->chunkfun = (struct _obstack_chunk * (*)(void *, long))chunkfun;
|
||||
h->freefun = (void (*)(void *, struct _obstack_chunk *))freefun;
|
||||
h->chunk_size = size;
|
||||
h->alignment_mask = alignment - 1;
|
||||
h->use_extra_arg = 0;
|
||||
|
||||
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
|
||||
chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
|
||||
if (!chunk)
|
||||
(*obstack_alloc_failed_handler) ();
|
||||
(*obstack_alloc_failed_handler)();
|
||||
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
|
||||
alignment - 1);
|
||||
alignment - 1);
|
||||
h->chunk_limit = chunk->limit
|
||||
= (char *) chunk + h->chunk_size;
|
||||
= (char *) chunk + h->chunk_size;
|
||||
chunk->prev = 0;
|
||||
/* The initial chunk now contains no empty object. */
|
||||
h->maybe_empty_object = 0;
|
||||
@ -197,45 +197,45 @@ _obstack_begin (struct obstack *h,
|
||||
|
||||
int
|
||||
_obstack_begin_1 (struct obstack *h, int size, int alignment,
|
||||
void *(*chunkfun) (void *, long),
|
||||
void (*freefun) (void *, void *),
|
||||
void *arg)
|
||||
void *(*chunkfun)(void *, long),
|
||||
void (*freefun)(void *, void *),
|
||||
void *arg)
|
||||
{
|
||||
struct _obstack_chunk *chunk; /* points to new chunk */
|
||||
|
||||
if (alignment == 0)
|
||||
alignment = DEFAULT_ALIGNMENT;
|
||||
if (size == 0)
|
||||
/* Default size is what GNU malloc can fit in a 4096-byte block. */
|
||||
/* Default size is what GNU malloc can fit in a 4096-byte block. */
|
||||
{
|
||||
/* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
|
||||
Use the values for range checking, because if range checking is off,
|
||||
the extra bytes won't be missed terribly, but if range checking is on
|
||||
and we used a larger request, a whole extra 4096 bytes would be
|
||||
allocated.
|
||||
Use the values for range checking, because if range checking is off,
|
||||
the extra bytes won't be missed terribly, but if range checking is on
|
||||
and we used a larger request, a whole extra 4096 bytes would be
|
||||
allocated.
|
||||
|
||||
These number are irrelevant to the new GNU malloc. I suspect it is
|
||||
less sensitive to the size of the request. */
|
||||
These number are irrelevant to the new GNU malloc. I suspect it is
|
||||
less sensitive to the size of the request. */
|
||||
int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
|
||||
+ 4 + DEFAULT_ROUNDING - 1)
|
||||
& ~(DEFAULT_ROUNDING - 1));
|
||||
+ 4 + DEFAULT_ROUNDING - 1)
|
||||
& ~(DEFAULT_ROUNDING - 1));
|
||||
size = 4096 - extra;
|
||||
}
|
||||
|
||||
h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
|
||||
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
|
||||
h->chunkfun = (struct _obstack_chunk * (*)(void *, long))chunkfun;
|
||||
h->freefun = (void (*)(void *, struct _obstack_chunk *))freefun;
|
||||
h->chunk_size = size;
|
||||
h->alignment_mask = alignment - 1;
|
||||
h->extra_arg = arg;
|
||||
h->use_extra_arg = 1;
|
||||
|
||||
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
|
||||
chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
|
||||
if (!chunk)
|
||||
(*obstack_alloc_failed_handler) ();
|
||||
(*obstack_alloc_failed_handler)();
|
||||
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
|
||||
alignment - 1);
|
||||
alignment - 1);
|
||||
h->chunk_limit = chunk->limit
|
||||
= (char *) chunk + h->chunk_size;
|
||||
= (char *) chunk + h->chunk_size;
|
||||
chunk->prev = 0;
|
||||
/* The initial chunk now contains no empty object. */
|
||||
h->maybe_empty_object = 0;
|
||||
@ -254,7 +254,7 @@ _obstack_newchunk (struct obstack *h, int length)
|
||||
{
|
||||
struct _obstack_chunk *old_chunk = h->chunk;
|
||||
struct _obstack_chunk *new_chunk;
|
||||
long new_size;
|
||||
long new_size;
|
||||
long obj_size = h->next_free - h->object_base;
|
||||
long i;
|
||||
long already;
|
||||
@ -268,7 +268,7 @@ _obstack_newchunk (struct obstack *h, int length)
|
||||
/* Allocate and initialize the new chunk. */
|
||||
new_chunk = CALL_CHUNKFUN (h, new_size);
|
||||
if (!new_chunk)
|
||||
(*obstack_alloc_failed_handler) ();
|
||||
(*obstack_alloc_failed_handler)();
|
||||
h->chunk = new_chunk;
|
||||
new_chunk->prev = old_chunk;
|
||||
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
|
||||
@ -283,12 +283,12 @@ _obstack_newchunk (struct obstack *h, int length)
|
||||
if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
|
||||
{
|
||||
for (i = obj_size / sizeof (COPYING_UNIT) - 1;
|
||||
i >= 0; i--)
|
||||
((COPYING_UNIT *)object_base)[i]
|
||||
= ((COPYING_UNIT *)h->object_base)[i];
|
||||
i >= 0; i--)
|
||||
((COPYING_UNIT *) object_base)[i]
|
||||
= ((COPYING_UNIT *) h->object_base)[i];
|
||||
/* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
|
||||
but that can cross a page boundary on a machine
|
||||
which does not do strict alignment for COPYING_UNITS. */
|
||||
but that can cross a page boundary on a machine
|
||||
which does not do strict alignment for COPYING_UNITS. */
|
||||
already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
|
||||
}
|
||||
else
|
||||
@ -300,10 +300,10 @@ _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
|
||||
if (!h->maybe_empty_object
|
||||
&& (h->object_base
|
||||
== __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
|
||||
h->alignment_mask)))
|
||||
== __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
|
||||
h->alignment_mask)))
|
||||
{
|
||||
new_chunk->prev = old_chunk->prev;
|
||||
CALL_FREEFUN (h, old_chunk);
|
||||
@ -329,8 +329,8 @@ int _obstack_allocated_p (struct obstack *h, void *obj);
|
||||
int
|
||||
_obstack_allocated_p (struct obstack *h, void *obj)
|
||||
{
|
||||
struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
|
||||
struct _obstack_chunk *plp; /* point to previous chunk if any */
|
||||
struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
|
||||
struct _obstack_chunk *plp; /* point to previous chunk if any */
|
||||
|
||||
lp = (h)->chunk;
|
||||
/* We use >= rather than > since the object cannot be exactly at
|
||||
@ -343,7 +343,7 @@ _obstack_allocated_p (struct obstack *h, void *obj)
|
||||
}
|
||||
return lp != 0;
|
||||
}
|
||||
|
||||
|
||||
/* Free objects in obstack H, including OBJ and everything allocate
|
||||
more recently than OBJ. If OBJ is zero, free everything in H. */
|
||||
|
||||
@ -352,8 +352,8 @@ _obstack_allocated_p (struct obstack *h, void *obj)
|
||||
void
|
||||
obstack_free (struct obstack *h, void *obj)
|
||||
{
|
||||
struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
|
||||
struct _obstack_chunk *plp; /* point to previous chunk if any */
|
||||
struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
|
||||
struct _obstack_chunk *plp; /* point to previous chunk if any */
|
||||
|
||||
lp = h->chunk;
|
||||
/* We use >= because there cannot be an object at the beginning of a chunk.
|
||||
@ -365,7 +365,7 @@ obstack_free (struct obstack *h, void *obj)
|
||||
CALL_FREEFUN (h, lp);
|
||||
lp = plp;
|
||||
/* If we switch chunks, we can't tell whether the new current
|
||||
chunk contains an empty object, so assume that it may. */
|
||||
chunk contains an empty object, so assume that it may. */
|
||||
h->maybe_empty_object = 1;
|
||||
}
|
||||
if (lp)
|
||||
@ -384,11 +384,11 @@ obstack_free (struct obstack *h, void *obj)
|
||||
called by non-GCC compilers. */
|
||||
strong_alias (obstack_free, _obstack_free)
|
||||
# endif
|
||||
|
||||
|
||||
int
|
||||
_obstack_memory_used (struct obstack *h)
|
||||
{
|
||||
struct _obstack_chunk* lp;
|
||||
struct _obstack_chunk *lp;
|
||||
int nbytes = 0;
|
||||
|
||||
for (lp = h->chunk; lp != 0; lp = lp->prev)
|
||||
@ -397,7 +397,7 @@ _obstack_memory_used (struct obstack *h)
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
|
||||
/* Define the error handler. */
|
||||
# ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
@ -429,11 +429,10 @@ print_and_abort (void)
|
||||
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"));
|
||||
(void) __fxprintf (NULL, "%s\n", _ ("memory exhausted"));
|
||||
# else
|
||||
fprintf (stderr, "%s\n", _("memory exhausted"));
|
||||
fprintf (stderr, "%s\n", _ ("memory exhausted"));
|
||||
# endif
|
||||
exit (obstack_exit_failure);
|
||||
}
|
||||
|
||||
#endif /* !ELIDE_CODE */
|
||||
#endif /* !ELIDE_CODE */
|
||||
|
608
malloc/obstack.h
608
malloc/obstack.h
@ -18,85 +18,85 @@
|
||||
|
||||
/* Summary:
|
||||
|
||||
All the apparent functions defined here are macros. The idea
|
||||
is that you would use these pre-tested macros to solve a
|
||||
very specific set of problems, and they would run fast.
|
||||
Caution: no side-effects in arguments please!! They may be
|
||||
evaluated MANY times!!
|
||||
All the apparent functions defined here are macros. The idea
|
||||
is that you would use these pre-tested macros to solve a
|
||||
very specific set of problems, and they would run fast.
|
||||
Caution: no side-effects in arguments please!! They may be
|
||||
evaluated MANY times!!
|
||||
|
||||
These macros operate a stack of objects. Each object starts life
|
||||
small, and may grow to maturity. (Consider building a word syllable
|
||||
by syllable.) An object can move while it is growing. Once it has
|
||||
been "finished" it never changes address again. So the "top of the
|
||||
stack" is typically an immature growing object, while the rest of the
|
||||
stack is of mature, fixed size and fixed address objects.
|
||||
These macros operate a stack of objects. Each object starts life
|
||||
small, and may grow to maturity. (Consider building a word syllable
|
||||
by syllable.) An object can move while it is growing. Once it has
|
||||
been "finished" it never changes address again. So the "top of the
|
||||
stack" is typically an immature growing object, while the rest of the
|
||||
stack is of mature, fixed size and fixed address objects.
|
||||
|
||||
These routines grab large chunks of memory, using a function you
|
||||
supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
|
||||
by calling `obstack_chunk_free'. You must define them and declare
|
||||
them before using any obstack macros.
|
||||
These routines grab large chunks of memory, using a function you
|
||||
supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
|
||||
by calling `obstack_chunk_free'. You must define them and declare
|
||||
them before using any obstack macros.
|
||||
|
||||
Each independent stack is represented by a `struct obstack'.
|
||||
Each of the obstack macros expects a pointer to such a structure
|
||||
as the first argument.
|
||||
Each independent stack is represented by a `struct obstack'.
|
||||
Each of the obstack macros expects a pointer to such a structure
|
||||
as the first argument.
|
||||
|
||||
One motivation for this package is the problem of growing char strings
|
||||
in symbol tables. Unless you are "fascist pig with a read-only mind"
|
||||
--Gosper's immortal quote from HAKMEM item 154, out of context--you
|
||||
would not like to put any arbitrary upper limit on the length of your
|
||||
symbols.
|
||||
One motivation for this package is the problem of growing char strings
|
||||
in symbol tables. Unless you are "fascist pig with a read-only mind"
|
||||
--Gosper's immortal quote from HAKMEM item 154, out of context--you
|
||||
would not like to put any arbitrary upper limit on the length of your
|
||||
symbols.
|
||||
|
||||
In practice this often means you will build many short symbols and a
|
||||
few long symbols. At the time you are reading a symbol you don't know
|
||||
how long it is. One traditional method is to read a symbol into a
|
||||
buffer, realloc()ating the buffer every time you try to read a symbol
|
||||
that is longer than the buffer. This is beaut, but you still will
|
||||
want to copy the symbol from the buffer to a more permanent
|
||||
symbol-table entry say about half the time.
|
||||
In practice this often means you will build many short symbols and a
|
||||
few long symbols. At the time you are reading a symbol you don't know
|
||||
how long it is. One traditional method is to read a symbol into a
|
||||
buffer, realloc()ating the buffer every time you try to read a symbol
|
||||
that is longer than the buffer. This is beaut, but you still will
|
||||
want to copy the symbol from the buffer to a more permanent
|
||||
symbol-table entry say about half the time.
|
||||
|
||||
With obstacks, you can work differently. Use one obstack for all symbol
|
||||
names. As you read a symbol, grow the name in the obstack gradually.
|
||||
When the name is complete, finalize it. Then, if the symbol exists already,
|
||||
free the newly read name.
|
||||
With obstacks, you can work differently. Use one obstack for all symbol
|
||||
names. As you read a symbol, grow the name in the obstack gradually.
|
||||
When the name is complete, finalize it. Then, if the symbol exists already,
|
||||
free the newly read name.
|
||||
|
||||
The way we do this is to take a large chunk, allocating memory from
|
||||
low addresses. When you want to build a symbol in the chunk you just
|
||||
add chars above the current "high water mark" in the chunk. When you
|
||||
have finished adding chars, because you got to the end of the symbol,
|
||||
you know how long the chars are, and you can create a new object.
|
||||
Mostly the chars will not burst over the highest address of the chunk,
|
||||
because you would typically expect a chunk to be (say) 100 times as
|
||||
long as an average object.
|
||||
The way we do this is to take a large chunk, allocating memory from
|
||||
low addresses. When you want to build a symbol in the chunk you just
|
||||
add chars above the current "high water mark" in the chunk. When you
|
||||
have finished adding chars, because you got to the end of the symbol,
|
||||
you know how long the chars are, and you can create a new object.
|
||||
Mostly the chars will not burst over the highest address of the chunk,
|
||||
because you would typically expect a chunk to be (say) 100 times as
|
||||
long as an average object.
|
||||
|
||||
In case that isn't clear, when we have enough chars to make up
|
||||
the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
|
||||
so we just point to it where it lies. No moving of chars is
|
||||
needed and this is the second win: potentially long strings need
|
||||
never be explicitly shuffled. Once an object is formed, it does not
|
||||
change its address during its lifetime.
|
||||
In case that isn't clear, when we have enough chars to make up
|
||||
the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
|
||||
so we just point to it where it lies. No moving of chars is
|
||||
needed and this is the second win: potentially long strings need
|
||||
never be explicitly shuffled. Once an object is formed, it does not
|
||||
change its address during its lifetime.
|
||||
|
||||
When the chars burst over a chunk boundary, we allocate a larger
|
||||
chunk, and then copy the partly formed object from the end of the old
|
||||
chunk to the beginning of the new larger chunk. We then carry on
|
||||
accreting characters to the end of the object as we normally would.
|
||||
When the chars burst over a chunk boundary, we allocate a larger
|
||||
chunk, and then copy the partly formed object from the end of the old
|
||||
chunk to the beginning of the new larger chunk. We then carry on
|
||||
accreting characters to the end of the object as we normally would.
|
||||
|
||||
A special macro is provided to add a single char at a time to a
|
||||
growing object. This allows the use of register variables, which
|
||||
break the ordinary 'growth' macro.
|
||||
A special macro is provided to add a single char at a time to a
|
||||
growing object. This allows the use of register variables, which
|
||||
break the ordinary 'growth' macro.
|
||||
|
||||
Summary:
|
||||
We allocate large chunks.
|
||||
We carve out one object at a time from the current chunk.
|
||||
Once carved, an object never moves.
|
||||
We are free to append data of any size to the currently
|
||||
growing object.
|
||||
Exactly one object is growing in an obstack at any one time.
|
||||
You can run one obstack per control block.
|
||||
You may have as many control blocks as you dare.
|
||||
Because of the way we do it, you can `unwind' an obstack
|
||||
back to a previous state. (You may remove objects much
|
||||
as you would with a stack.)
|
||||
*/
|
||||
Summary:
|
||||
We allocate large chunks.
|
||||
We carve out one object at a time from the current chunk.
|
||||
Once carved, an object never moves.
|
||||
We are free to append data of any size to the currently
|
||||
growing object.
|
||||
Exactly one object is growing in an obstack at any one time.
|
||||
You can run one obstack per control block.
|
||||
You may have as many control blocks as you dare.
|
||||
Because of the way we do it, you can `unwind' an obstack
|
||||
back to a previous state. (You may remove objects much
|
||||
as you would with a stack.)
|
||||
*/
|
||||
|
||||
|
||||
/* Don't do the contents of this file more than once. */
|
||||
@ -107,7 +107,7 @@ Summary:
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* We need the type of a pointer subtraction. 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>
|
||||
@ -124,7 +124,7 @@ extern "C" {
|
||||
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)))
|
||||
#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,
|
||||
@ -133,61 +133,61 @@ extern "C" {
|
||||
relative to B. Otherwise, use the faster strategy of computing the
|
||||
alignment relative to 0. */
|
||||
|
||||
#define __PTR_ALIGN(B, P, A) \
|
||||
#define __PTR_ALIGN(B, P, A) \
|
||||
__BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
|
||||
P, A)
|
||||
P, A)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct _obstack_chunk /* Lives at front of each chunk. */
|
||||
struct _obstack_chunk /* Lives at front of each chunk. */
|
||||
{
|
||||
char *limit; /* 1 past end of this chunk */
|
||||
struct _obstack_chunk *prev; /* address of prior chunk or NULL */
|
||||
char contents[4]; /* objects begin here */
|
||||
char *limit; /* 1 past end of this chunk */
|
||||
struct _obstack_chunk *prev; /* address of prior chunk or NULL */
|
||||
char contents[4]; /* objects begin here */
|
||||
};
|
||||
|
||||
struct obstack /* control current object in current chunk */
|
||||
struct obstack /* control current object in current chunk */
|
||||
{
|
||||
long chunk_size; /* preferred size to allocate chunks in */
|
||||
struct _obstack_chunk *chunk; /* address of current struct obstack_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 */
|
||||
long chunk_size; /* preferred size to allocate chunks in */
|
||||
struct _obstack_chunk *chunk; /* address of current struct obstack_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. */
|
||||
int alignment_mask; /* Mask of alignment for each object. */
|
||||
} 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,
|
||||
but having prototypes here quiets -Wstrict-prototypes. */
|
||||
struct _obstack_chunk *(*chunkfun) (void *, long);
|
||||
void (*freefun) (void *, struct _obstack_chunk *);
|
||||
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
|
||||
unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
|
||||
unsigned maybe_empty_object:1;/* There is a possibility that the current
|
||||
chunk contains a zero-length object. This
|
||||
prevents freeing the chunk if we allocate
|
||||
a bigger chunk to replace it. */
|
||||
unsigned alloc_failed:1; /* No longer used, as we now call the failed
|
||||
handler on error, but retained for binary
|
||||
compatibility. */
|
||||
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
|
||||
unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
|
||||
unsigned maybe_empty_object : 1; /* There is a possibility that the current
|
||||
chunk contains a zero-length object. This
|
||||
prevents freeing the chunk if we allocate
|
||||
a bigger chunk to replace it. */
|
||||
unsigned alloc_failed : 1; /* No longer used, as we now call the failed
|
||||
handler on error, but retained for binary
|
||||
compatibility. */
|
||||
};
|
||||
|
||||
/* Declare the external functions we use; they are in obstack.c. */
|
||||
|
||||
extern void _obstack_newchunk (struct obstack *, int);
|
||||
extern int _obstack_begin (struct obstack *, int, int,
|
||||
void *(*) (long), void (*) (void *));
|
||||
void *(*)(long), void (*)(void *));
|
||||
extern int _obstack_begin_1 (struct obstack *, int, int,
|
||||
void *(*) (void *, long),
|
||||
void (*) (void *, void *), void *);
|
||||
void *(*)(void *, long),
|
||||
void (*)(void *, void *), void *);
|
||||
extern int _obstack_memory_used (struct obstack *);
|
||||
|
||||
void obstack_free (struct obstack *__obstack, void *__glibc_block);
|
||||
|
||||
|
||||
|
||||
/* Error handler called when `obstack_chunk_alloc' failed to allocate
|
||||
more memory. This can be set to a user defined function which
|
||||
should either abort gracefully or use longjump - but shouldn't
|
||||
@ -196,7 +196,7 @@ extern void (*obstack_alloc_failed_handler) (void);
|
||||
|
||||
/* Exit value used when `print_and_abort' is used. */
|
||||
extern int obstack_exit_failure;
|
||||
|
||||
|
||||
/* Pointer to beginning of object being allocated or to be allocated next.
|
||||
Note that this might not be the final address of the object
|
||||
because a new chunk might be needed to hold the final size. */
|
||||
@ -209,45 +209,45 @@ extern int obstack_exit_failure;
|
||||
|
||||
/* Pointer to next byte not yet allocated in current chunk. */
|
||||
|
||||
#define obstack_next_free(h) ((h)->next_free)
|
||||
#define obstack_next_free(h) ((h)->next_free)
|
||||
|
||||
/* Mask specifying low bits that should be clear in address of an object. */
|
||||
|
||||
#define obstack_alignment_mask(h) ((h)->alignment_mask)
|
||||
|
||||
/* To prevent prototype warnings provide complete argument list. */
|
||||
#define obstack_init(h) \
|
||||
_obstack_begin ((h), 0, 0, \
|
||||
(void *(*) (long)) obstack_chunk_alloc, \
|
||||
(void (*) (void *)) obstack_chunk_free)
|
||||
#define obstack_init(h) \
|
||||
_obstack_begin ((h), 0, 0, \
|
||||
(void *(*)(long))obstack_chunk_alloc, \
|
||||
(void (*)(void *))obstack_chunk_free)
|
||||
|
||||
#define obstack_begin(h, size) \
|
||||
_obstack_begin ((h), (size), 0, \
|
||||
(void *(*) (long)) obstack_chunk_alloc, \
|
||||
(void (*) (void *)) obstack_chunk_free)
|
||||
#define obstack_begin(h, size) \
|
||||
_obstack_begin ((h), (size), 0, \
|
||||
(void *(*)(long))obstack_chunk_alloc, \
|
||||
(void (*)(void *))obstack_chunk_free)
|
||||
|
||||
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
|
||||
_obstack_begin ((h), (size), (alignment), \
|
||||
(void *(*) (long)) (chunkfun), \
|
||||
(void (*) (void *)) (freefun))
|
||||
_obstack_begin ((h), (size), (alignment), \
|
||||
(void *(*)(long))(chunkfun), \
|
||||
(void (*)(void *))(freefun))
|
||||
|
||||
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
|
||||
_obstack_begin_1 ((h), (size), (alignment), \
|
||||
(void *(*) (void *, long)) (chunkfun), \
|
||||
(void (*) (void *, void *)) (freefun), (arg))
|
||||
_obstack_begin_1 ((h), (size), (alignment), \
|
||||
(void *(*)(void *, long))(chunkfun), \
|
||||
(void (*)(void *, void *))(freefun), (arg))
|
||||
|
||||
#define obstack_chunkfun(h, newchunkfun) \
|
||||
((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
|
||||
((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
|
||||
|
||||
#define obstack_freefun(h, newfreefun) \
|
||||
((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
|
||||
((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
|
||||
|
||||
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar))
|
||||
#define obstack_1grow_fast(h, achar) (*((h)->next_free)++ = (achar))
|
||||
|
||||
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
|
||||
#define obstack_blank_fast(h, n) ((h)->next_free += (n))
|
||||
|
||||
#define obstack_memory_used(h) _obstack_memory_used (h)
|
||||
|
||||
|
||||
#if defined __GNUC__
|
||||
/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
|
||||
does not implement __extension__. But that compiler doesn't define
|
||||
@ -261,158 +261,158 @@ extern int obstack_exit_failure;
|
||||
without using a global variable.
|
||||
Also, we can avoid using the `temp' slot, to make faster code. */
|
||||
|
||||
# define obstack_object_size(OBSTACK) \
|
||||
__extension__ \
|
||||
({ struct obstack const *__o = (OBSTACK); \
|
||||
(unsigned) (__o->next_free - __o->object_base); })
|
||||
# define obstack_object_size(OBSTACK) \
|
||||
__extension__ \
|
||||
({ struct obstack const *__o = (OBSTACK); \
|
||||
(unsigned) (__o->next_free - __o->object_base); })
|
||||
|
||||
# define obstack_room(OBSTACK) \
|
||||
__extension__ \
|
||||
({ struct obstack const *__o = (OBSTACK); \
|
||||
(unsigned) (__o->chunk_limit - __o->next_free); })
|
||||
# define obstack_room(OBSTACK) \
|
||||
__extension__ \
|
||||
({ struct obstack const *__o = (OBSTACK); \
|
||||
(unsigned) (__o->chunk_limit - __o->next_free); })
|
||||
|
||||
# define obstack_make_room(OBSTACK,length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
int __len = (length); \
|
||||
if (__o->chunk_limit - __o->next_free < __len) \
|
||||
_obstack_newchunk (__o, __len); \
|
||||
(void) 0; })
|
||||
# define obstack_make_room(OBSTACK, length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
int __len = (length); \
|
||||
if (__o->chunk_limit - __o->next_free < __len) \
|
||||
_obstack_newchunk (__o, __len); \
|
||||
(void) 0; })
|
||||
|
||||
# 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)); })
|
||||
# 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)); })
|
||||
|
||||
# define obstack_grow(OBSTACK,where,length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
int __len = (length); \
|
||||
if (__o->next_free + __len > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, __len); \
|
||||
memcpy (__o->next_free, where, __len); \
|
||||
__o->next_free += __len; \
|
||||
(void) 0; })
|
||||
# define obstack_grow(OBSTACK, where, length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
int __len = (length); \
|
||||
if (__o->next_free + __len > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, __len); \
|
||||
memcpy (__o->next_free, where, __len); \
|
||||
__o->next_free += __len; \
|
||||
(void) 0; })
|
||||
|
||||
# define obstack_grow0(OBSTACK,where,length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
int __len = (length); \
|
||||
if (__o->next_free + __len + 1 > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, __len + 1); \
|
||||
memcpy (__o->next_free, where, __len); \
|
||||
__o->next_free += __len; \
|
||||
*(__o->next_free)++ = 0; \
|
||||
(void) 0; })
|
||||
# define obstack_grow0(OBSTACK, where, length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
int __len = (length); \
|
||||
if (__o->next_free + __len + 1 > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, __len + 1); \
|
||||
memcpy (__o->next_free, where, __len); \
|
||||
__o->next_free += __len; \
|
||||
*(__o->next_free)++ = 0; \
|
||||
(void) 0; })
|
||||
|
||||
# define obstack_1grow(OBSTACK,datum) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
if (__o->next_free + 1 > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, 1); \
|
||||
obstack_1grow_fast (__o, datum); \
|
||||
(void) 0; })
|
||||
# define obstack_1grow(OBSTACK, datum) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
if (__o->next_free + 1 > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, 1); \
|
||||
obstack_1grow_fast (__o, datum); \
|
||||
(void) 0; })
|
||||
|
||||
/* These assume that the obstack alignment is good enough for pointers
|
||||
or ints, and that the data added so far to the current object
|
||||
shares that much alignment. */
|
||||
|
||||
# define obstack_ptr_grow(OBSTACK,datum) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, sizeof (void *)); \
|
||||
obstack_ptr_grow_fast (__o, datum); }) \
|
||||
# define obstack_ptr_grow(OBSTACK, datum) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, sizeof (void *)); \
|
||||
obstack_ptr_grow_fast (__o, datum); }) \
|
||||
|
||||
# define obstack_int_grow(OBSTACK,datum) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
if (__o->next_free + sizeof (int) > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, sizeof (int)); \
|
||||
obstack_int_grow_fast (__o, datum); })
|
||||
# define obstack_int_grow(OBSTACK, datum) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
if (__o->next_free + sizeof (int) > __o->chunk_limit) \
|
||||
_obstack_newchunk (__o, sizeof (int)); \
|
||||
obstack_int_grow_fast (__o, datum); })
|
||||
|
||||
# define obstack_ptr_grow_fast(OBSTACK,aptr) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o1 = (OBSTACK); \
|
||||
*(const void **) __o1->next_free = (aptr); \
|
||||
__o1->next_free += sizeof (const void *); \
|
||||
(void) 0; })
|
||||
# define obstack_ptr_grow_fast(OBSTACK, aptr) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o1 = (OBSTACK); \
|
||||
*(const void **) __o1->next_free = (aptr); \
|
||||
__o1->next_free += sizeof (const void *); \
|
||||
(void) 0; })
|
||||
|
||||
# define obstack_int_grow_fast(OBSTACK,aint) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o1 = (OBSTACK); \
|
||||
*(int *) __o1->next_free = (aint); \
|
||||
__o1->next_free += sizeof (int); \
|
||||
(void) 0; })
|
||||
# define obstack_int_grow_fast(OBSTACK, aint) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o1 = (OBSTACK); \
|
||||
*(int *) __o1->next_free = (aint); \
|
||||
__o1->next_free += sizeof (int); \
|
||||
(void) 0; })
|
||||
|
||||
# define obstack_blank(OBSTACK,length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
int __len = (length); \
|
||||
if (__o->chunk_limit - __o->next_free < __len) \
|
||||
_obstack_newchunk (__o, __len); \
|
||||
obstack_blank_fast (__o, __len); \
|
||||
(void) 0; })
|
||||
# define obstack_blank(OBSTACK, length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
int __len = (length); \
|
||||
if (__o->chunk_limit - __o->next_free < __len) \
|
||||
_obstack_newchunk (__o, __len); \
|
||||
obstack_blank_fast (__o, __len); \
|
||||
(void) 0; })
|
||||
|
||||
# define obstack_alloc(OBSTACK,length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__h = (OBSTACK); \
|
||||
obstack_blank (__h, (length)); \
|
||||
obstack_finish (__h); })
|
||||
# define obstack_alloc(OBSTACK, length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__h = (OBSTACK); \
|
||||
obstack_blank (__h, (length)); \
|
||||
obstack_finish (__h); })
|
||||
|
||||
# define obstack_copy(OBSTACK,where,length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__h = (OBSTACK); \
|
||||
obstack_grow (__h, (where), (length)); \
|
||||
obstack_finish (__h); })
|
||||
# define obstack_copy(OBSTACK, where, length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__h = (OBSTACK); \
|
||||
obstack_grow (__h, (where), (length)); \
|
||||
obstack_finish (__h); })
|
||||
|
||||
# define obstack_copy0(OBSTACK,where,length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__h = (OBSTACK); \
|
||||
obstack_grow0 (__h, (where), (length)); \
|
||||
obstack_finish (__h); })
|
||||
# define obstack_copy0(OBSTACK, where, length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__h = (OBSTACK); \
|
||||
obstack_grow0 (__h, (where), (length)); \
|
||||
obstack_finish (__h); })
|
||||
|
||||
/* The local variable is named __o1 to avoid a name conflict
|
||||
when obstack_blank is called. */
|
||||
# define obstack_finish(OBSTACK) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o1 = (OBSTACK); \
|
||||
void *__value = (void *) __o1->object_base; \
|
||||
if (__o1->next_free == __value) \
|
||||
__o1->maybe_empty_object = 1; \
|
||||
__o1->next_free \
|
||||
= __PTR_ALIGN (__o1->object_base, __o1->next_free, \
|
||||
__o1->alignment_mask); \
|
||||
if (__o1->next_free - (char *)__o1->chunk \
|
||||
> __o1->chunk_limit - (char *)__o1->chunk) \
|
||||
__o1->next_free = __o1->chunk_limit; \
|
||||
__o1->object_base = __o1->next_free; \
|
||||
__value; })
|
||||
# define obstack_finish(OBSTACK) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o1 = (OBSTACK); \
|
||||
void *__value = (void *) __o1->object_base; \
|
||||
if (__o1->next_free == __value) \
|
||||
__o1->maybe_empty_object = 1; \
|
||||
__o1->next_free \
|
||||
= __PTR_ALIGN (__o1->object_base, __o1->next_free, \
|
||||
__o1->alignment_mask); \
|
||||
if (__o1->next_free - (char *) __o1->chunk \
|
||||
> __o1->chunk_limit - (char *) __o1->chunk) \
|
||||
__o1->next_free = __o1->chunk_limit; \
|
||||
__o1->object_base = __o1->next_free; \
|
||||
__value; })
|
||||
|
||||
# define obstack_free(OBSTACK, OBJ) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
void *__obj = (OBJ); \
|
||||
if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \
|
||||
__o->next_free = __o->object_base = (char *) __obj; \
|
||||
else (obstack_free) (__o, __obj); })
|
||||
|
||||
# define obstack_free(OBSTACK, OBJ) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
void *__obj = (OBJ); \
|
||||
if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
|
||||
__o->next_free = __o->object_base = (char *)__obj; \
|
||||
else (obstack_free) (__o, __obj); })
|
||||
|
||||
#else /* not __GNUC__ */
|
||||
|
||||
# define obstack_object_size(h) \
|
||||
(unsigned) ((h)->next_free - (h)->object_base)
|
||||
(unsigned) ((h)->next_free - (h)->object_base)
|
||||
|
||||
# define obstack_room(h) \
|
||||
(unsigned) ((h)->chunk_limit - (h)->next_free)
|
||||
# define obstack_room(h) \
|
||||
(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 == __PTR_ALIGN ((char *) (h)->chunk, \
|
||||
(h)->chunk->contents, \
|
||||
(h)->alignment_mask))
|
||||
|
||||
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
|
||||
so that we can avoid having void expressions
|
||||
@ -420,88 +420,86 @@ __extension__ \
|
||||
Casting the third operand to void was tried before,
|
||||
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) \
|
||||
# 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))
|
||||
|
||||
# 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)
|
||||
# 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)
|
||||
|
||||
# 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)->next_free)++ = 0)
|
||||
# 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)->next_free)++ = 0)
|
||||
|
||||
# define obstack_1grow(h,datum) \
|
||||
( (((h)->next_free + 1 > (h)->chunk_limit) \
|
||||
? (_obstack_newchunk ((h), 1), 0) : 0), \
|
||||
obstack_1grow_fast (h, datum))
|
||||
# define obstack_1grow(h, datum) \
|
||||
((((h)->next_free + 1 > (h)->chunk_limit) \
|
||||
? (_obstack_newchunk ((h), 1), 0) : 0), \
|
||||
obstack_1grow_fast (h, datum))
|
||||
|
||||
# define obstack_ptr_grow(h,datum) \
|
||||
( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
|
||||
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
|
||||
obstack_ptr_grow_fast (h, datum))
|
||||
# define obstack_ptr_grow(h, datum) \
|
||||
((((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
|
||||
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
|
||||
obstack_ptr_grow_fast (h, datum))
|
||||
|
||||
# define obstack_int_grow(h,datum) \
|
||||
( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
|
||||
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
|
||||
obstack_int_grow_fast (h, datum))
|
||||
# define obstack_int_grow(h, datum) \
|
||||
((((h)->next_free + sizeof (int) > (h)->chunk_limit) \
|
||||
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
|
||||
obstack_int_grow_fast (h, datum))
|
||||
|
||||
# define obstack_ptr_grow_fast(h,aptr) \
|
||||
# define obstack_ptr_grow_fast(h, aptr) \
|
||||
(((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
|
||||
|
||||
# define obstack_int_grow_fast(h,aint) \
|
||||
# define obstack_int_grow_fast(h, aint) \
|
||||
(((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
|
||||
|
||||
# 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))
|
||||
# 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))
|
||||
|
||||
# define obstack_alloc(h,length) \
|
||||
(obstack_blank ((h), (length)), obstack_finish ((h)))
|
||||
# define obstack_alloc(h, length) \
|
||||
(obstack_blank ((h), (length)), obstack_finish ((h)))
|
||||
|
||||
# define obstack_copy(h,where,length) \
|
||||
(obstack_grow ((h), (where), (length)), obstack_finish ((h)))
|
||||
# define obstack_copy(h, where, length) \
|
||||
(obstack_grow ((h), (where), (length)), obstack_finish ((h)))
|
||||
|
||||
# define obstack_copy0(h,where,length) \
|
||||
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
|
||||
# define obstack_copy0(h, where, length) \
|
||||
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
|
||||
|
||||
# define obstack_finish(h) \
|
||||
( ((h)->next_free == (h)->object_base \
|
||||
? (((h)->maybe_empty_object = 1), 0) \
|
||||
: 0), \
|
||||
(h)->temp.tempptr = (h)->object_base, \
|
||||
(h)->next_free \
|
||||
= __PTR_ALIGN ((h)->object_base, (h)->next_free, \
|
||||
(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)
|
||||
# define obstack_finish(h) \
|
||||
(((h)->next_free == (h)->object_base \
|
||||
? (((h)->maybe_empty_object = 1), 0) \
|
||||
: 0), \
|
||||
(h)->temp.tempptr = (h)->object_base, \
|
||||
(h)->next_free \
|
||||
= __PTR_ALIGN ((h)->object_base, (h)->next_free, \
|
||||
(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)
|
||||
|
||||
# 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)->next_free = (h)->object_base \
|
||||
= (h)->temp.tempint + (char *) (h)->chunk), 0) \
|
||||
# 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)->next_free = (h)->object_base \
|
||||
= (h)->temp.tempint + (char *) (h)->chunk), 0) \
|
||||
: ((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0)))
|
||||
|
||||
#endif /* not __GNUC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* C++ */
|
||||
} /* C++ */
|
||||
#endif
|
||||
|
||||
#endif /* obstack.h */
|
||||
|
@ -33,17 +33,17 @@ __libc_freeres (void)
|
||||
protect for multiple executions since these are fatal. */
|
||||
static long int already_called;
|
||||
|
||||
if (! atomic_compare_and_exchange_bool_acq (&already_called, 1, 0))
|
||||
if (!atomic_compare_and_exchange_bool_acq (&already_called, 1, 0))
|
||||
{
|
||||
void * const *p;
|
||||
void *const *p;
|
||||
|
||||
_IO_cleanup ();
|
||||
|
||||
RUN_HOOK (__libc_subfreeres, ());
|
||||
|
||||
for (p = symbol_set_first_element (__libc_freeres_ptrs);
|
||||
! symbol_set_end_p (__libc_freeres_ptrs, p); ++p)
|
||||
free (*p);
|
||||
!symbol_set_end_p (__libc_freeres_ptrs, p); ++p)
|
||||
free (*p);
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__libc_freeres)
|
||||
|
@ -48,19 +48,19 @@ main (void)
|
||||
|
||||
free (malloc (10));
|
||||
|
||||
for (i=0; i<100; ++i)
|
||||
for (i = 0; i < 100; ++i)
|
||||
{
|
||||
save_state = malloc_get_state ();
|
||||
if (save_state == NULL)
|
||||
{
|
||||
merror ("malloc_get_state () failed.");
|
||||
break;
|
||||
}
|
||||
{
|
||||
merror ("malloc_get_state () failed.");
|
||||
break;
|
||||
}
|
||||
/*free (malloc (10)); This could change the top chunk! */
|
||||
malloc_set_state (save_state);
|
||||
p1 = realloc (p1, i*4 + 4);
|
||||
p1 = realloc (p1, i * 4 + 4);
|
||||
if (p1 == NULL)
|
||||
merror ("realloc (i*4) failed.");
|
||||
merror ("realloc (i*4) failed.");
|
||||
free (save_state);
|
||||
}
|
||||
|
||||
|
@ -55,20 +55,20 @@ main (void)
|
||||
ssize_t n = getline (&line, &linelen, fp);
|
||||
|
||||
if (n < 0)
|
||||
break;
|
||||
break;
|
||||
|
||||
if (n == 0)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
copy = strdup (line);
|
||||
if (copy == NULL)
|
||||
abort ();
|
||||
abort ();
|
||||
|
||||
p = (char **) tsearch (copy, &root,
|
||||
(int (*) (const void *, const void *)) strcmp);
|
||||
(int (*)(const void *, const void *))strcmp);
|
||||
if (*p != copy)
|
||||
/* This line wasn't added. */
|
||||
free (copy);
|
||||
/* This line wasn't added. */
|
||||
free (copy);
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
|
@ -79,11 +79,11 @@ do_test (void)
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
if (c[i] != 0)
|
||||
ok = 0;
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (ok == 0)
|
||||
merror ("first 20 bytes were not cleared");
|
||||
merror ("first 20 bytes were not cleared");
|
||||
|
||||
free (p);
|
||||
|
||||
@ -104,11 +104,11 @@ do_test (void)
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
if (c[i] != 0xff)
|
||||
ok = 0;
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (ok == 0)
|
||||
merror ("first 16 bytes were not correct");
|
||||
merror ("first 16 bytes were not correct");
|
||||
|
||||
/* Check failed realloc leaves original untouched (C89). */
|
||||
c = realloc (p, -1);
|
||||
@ -121,11 +121,11 @@ do_test (void)
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
if (c[i] != 0xff)
|
||||
ok = 0;
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (ok == 0)
|
||||
merror ("first 16 bytes were not correct after failed realloc");
|
||||
merror ("first 16 bytes were not correct after failed realloc");
|
||||
|
||||
/* realloc (p, 0) frees p (C89) and returns NULL (glibc). */
|
||||
p = realloc (p, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user