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