X-Git-Url: http://git.csclub.uwaterloo.ca/?p=kopensolaris-gnu%2Fglibc.git;a=blobdiff_plain;f=malloc%2Fhooks.c;h=1e01b73afde89be6edf35e18182c5f31149e9da7;hp=28629eff80c56d9915a5e4ad4a04e1c950987edd;hb=4b69b20a6f55e974e80e2eff97f0c79257673d5e;hpb=917f0ee00246953a5268070f11683ce17d233354 diff --git a/malloc/hooks.c b/malloc/hooks.c index 28629eff80..1e01b73afd 100644 --- a/malloc/hooks.c +++ b/malloc/hooks.c @@ -1,33 +1,23 @@ /* Malloc implementation for multiple threads without lock contention. - Copyright (C) 2001 Free Software Foundation, Inc. + Copyright (C) 2001-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Wolfram Gloger , 2001. The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id$ */ - -#ifndef weak_variable -#define weak_variable /**/ -#endif - -#ifndef DEFAULT_CHECK_ACTION -#define DEFAULT_CHECK_ACTION 1 -#endif - /* What to do if the standard debugging hooks are in place and a corrupt pointer is detected: do nothing (0), print an error message (1), or call abort() (2). */ @@ -75,22 +65,6 @@ memalign_hook_ini(alignment, sz, caller) return public_mEMALIGn(alignment, sz); } -void weak_variable (*__malloc_initialize_hook) __MALLOC_P ((void)) = NULL; -void weak_variable (*__free_hook) __MALLOC_P ((__malloc_ptr_t __ptr, - const __malloc_ptr_t)) = NULL; -__malloc_ptr_t weak_variable (*__malloc_hook) - __MALLOC_P ((size_t __size, const __malloc_ptr_t)) = malloc_hook_ini; -__malloc_ptr_t weak_variable (*__realloc_hook) - __MALLOC_P ((__malloc_ptr_t __ptr, size_t __size, const __malloc_ptr_t)) - = realloc_hook_ini; -__malloc_ptr_t weak_variable (*__memalign_hook) - __MALLOC_P ((size_t __alignment, size_t __size, const __malloc_ptr_t)) - = memalign_hook_ini; -void weak_variable (*__after_morecore_hook) __MALLOC_P ((void)) = NULL; - - -static int check_action = DEFAULT_CHECK_ACTION; - /* Whether we are using malloc checking. */ static int using_malloc_checking; @@ -123,7 +97,7 @@ __malloc_check_init() __realloc_hook = realloc_check; __memalign_hook = memalign_check; if(check_action & 1) - fprintf(stderr, "malloc: using debugging hooks\n"); + malloc_printerr (5, "malloc: using debugging hooks", NULL); } /* A simple, standard set of debugging hooks. Overhead is `only' one @@ -170,33 +144,33 @@ mem2mem_check(ptr, sz) Void_t *ptr; size_t sz; static mchunkptr internal_function #if __STD_C -mem2chunk_check(Void_t* mem) +mem2chunk_check(Void_t* mem, unsigned char **magic_p) #else -mem2chunk_check(mem) Void_t* mem; +mem2chunk_check(mem, magic_p) Void_t* mem; unsigned char **magic_p; #endif { mchunkptr p; INTERNAL_SIZE_T sz, c; unsigned char magic; + if(!aligned_OK(mem)) return NULL; p = mem2chunk(mem); - if(!aligned_OK(p)) return NULL; - if( (char*)p>=mp_.sbrk_base && - (char*)p<(mp_.sbrk_base+main_arena.system_mem) ) { + if (!chunk_is_mmapped(p)) { /* Must be a chunk in conventional heap memory. */ - if(chunk_is_mmapped(p) || - ( (sz = chunksize(p)), - ((char*)p + sz)>=(mp_.sbrk_base+main_arena.system_mem) ) || + int contig = contiguous(&main_arena); + sz = chunksize(p); + if((contig && + ((char*)p=(mp_.sbrk_base+main_arena.system_mem) )) || szprev_size&MALLOC_ALIGN_MASK || - (long)prev_chunk(p)<(long)mp_.sbrk_base || + (contig && (char*)prev_chunk(p)=MINSIZE && + prev_inuse(t) && + (!contiguous(&main_arena) || + (char*)t + chunksize(t) == mp_.sbrk_base + main_arena.system_mem))) + return 0; - if(check_action & 1) - fprintf(stderr, "malloc: top chunk is corrupt\n"); - if(check_action & 2) - abort(); + malloc_printerr (check_action, "malloc: top chunk is corrupt", t); /* Try to set up a new top chunk. */ brk = MORECORE(0); @@ -253,7 +231,11 @@ top_check() sbrk_size = front_misalign + mp_.top_pad + MINSIZE; sbrk_size += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1)); new_brk = (char*)(MORECORE (sbrk_size)); - if (new_brk == (char*)(MORECORE_FAILURE)) return -1; + if (new_brk == (char*)(MORECORE_FAILURE)) + { + MALLOC_FAILURE_ACTION; + return -1; + } /* Call the `morecore' hook if necessary. */ if (__after_morecore_hook) (*__after_morecore_hook) (); @@ -274,6 +256,11 @@ malloc_check(sz, caller) size_t sz; const Void_t *caller; { Void_t *victim; + if (sz+1 == 0) { + MALLOC_FAILURE_ACTION; + return NULL; + } + (void)mutex_lock(&main_arena.mutex); victim = (top_check() >= 0) ? _int_malloc(&main_arena, sz+1) : NULL; (void)mutex_unlock(&main_arena.mutex); @@ -291,13 +278,11 @@ free_check(mem, caller) Void_t* mem; const Void_t *caller; if(!mem) return; (void)mutex_lock(&main_arena.mutex); - p = mem2chunk_check(mem); + p = mem2chunk_check(mem, NULL); if(!p) { (void)mutex_unlock(&main_arena.mutex); - if(check_action & 1) - fprintf(stderr, "free(): invalid pointer %p!\n", mem); - if(check_action & 2) - abort(); + + malloc_printerr(check_action, "free(): invalid pointer", mem); return; } #if HAVE_MMAP @@ -322,19 +307,25 @@ realloc_check(oldmem, bytes, caller) Void_t* oldmem; size_t bytes; const Void_t *caller; #endif { - mchunkptr oldp, newp = 0; + mchunkptr oldp; INTERNAL_SIZE_T nb, oldsize; Void_t* newmem = 0; + unsigned char *magic_p; + if (bytes+1 == 0) { + MALLOC_FAILURE_ACTION; + return NULL; + } if (oldmem == 0) return malloc_check(bytes, NULL); + if (bytes == 0) { + free_check (oldmem, NULL); + return NULL; + } (void)mutex_lock(&main_arena.mutex); - oldp = mem2chunk_check(oldmem); + oldp = mem2chunk_check(oldmem, &magic_p); (void)mutex_unlock(&main_arena.mutex); if(!oldp) { - if(check_action & 1) - fprintf(stderr, "realloc(): invalid pointer %p!\n", oldmem); - if(check_action & 2) - abort(); + malloc_printerr(check_action, "realloc(): invalid pointer", oldmem); return malloc_check(bytes, NULL); } oldsize = chunksize(oldp); @@ -345,9 +336,12 @@ realloc_check(oldmem, bytes, caller) #if HAVE_MMAP if (chunk_is_mmapped(oldp)) { #if HAVE_MREMAP - newp = mremap_chunk(oldp, nb); - if(!newp) { + 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 */ @@ -360,9 +354,7 @@ realloc_check(oldmem, bytes, caller) munmap_chunk(oldp); } } -#if HAVE_MREMAP } -#endif } else { #endif /* HAVE_MMAP */ if (top_check() >= 0) @@ -382,6 +374,12 @@ realloc_check(oldmem, bytes, caller) #if HAVE_MMAP } #endif + + /* mem2chunk_check changed the magic byte in the old chunk. + If newmem is NULL, then the old chunk will still be used though, + so we need to invert that change here. */ + if (newmem == NULL) *magic_p ^= 0xFF; + (void)mutex_unlock(&main_arena.mutex); return mem2mem_check(newmem, bytes); @@ -401,6 +399,10 @@ memalign_check(alignment, bytes, caller) if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL); if (alignment < MINSIZE) alignment = MINSIZE; + if (bytes+1 == 0) { + MALLOC_FAILURE_ACTION; + return NULL; + } checked_request2size(bytes+1, nb); (void)mutex_lock(&main_arena.mutex); mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) : @@ -411,6 +413,17 @@ memalign_check(alignment, bytes, caller) #ifndef NO_THREADS +# ifdef _LIBC +# if USE___THREAD || !defined SHARED + /* These routines are never needed in this configuration. */ +# define NO_STARTER +# endif +# endif + +# ifdef NO_STARTER +# undef NO_STARTER +# else + /* The following hooks are used when the global initialization in ptmalloc_init() hasn't completed yet. */ @@ -428,6 +441,20 @@ malloc_starter(sz, caller) size_t sz; const Void_t *caller; return victim ? BOUNDED_N(victim, sz) : 0; } +static Void_t* +#if __STD_C +memalign_starter(size_t align, size_t sz, const Void_t *caller) +#else +memalign_starter(align, sz, caller) size_t align, sz; const Void_t *caller; +#endif +{ + Void_t* victim; + + victim = _int_memalign(&main_arena, align, sz); + + return victim ? BOUNDED_N(victim, sz) : 0; +} + static void #if __STD_C free_starter(Void_t* mem, const Void_t *caller) @@ -448,6 +475,7 @@ free_starter(mem, caller) Void_t* mem; const Void_t *caller; _int_free(&main_arena, mem); } +# endif /* !defiend NO_STARTER */ #endif /* NO_THREADS */ @@ -468,7 +496,7 @@ free_starter(mem, caller) Void_t* mem; const Void_t *caller; then the hooks are reset to 0. */ #define MALLOC_STATE_MAGIC 0x444c4541l -#define MALLOC_STATE_VERSION (0*0x100l + 2l) /* major*0x100 + minor */ +#define MALLOC_STATE_VERSION (0*0x100l + 3l) /* major*0x100 + minor */ struct malloc_save_state { long magic; @@ -526,7 +554,7 @@ public_gET_STATe(void) ms->check_action = check_action; ms->max_sbrked_mem = main_arena.max_system_mem; #ifdef NO_THREADS - ms->max_total_mem = max_total_mem; + ms->max_total_mem = mp_.max_total_mem; #else ms->max_total_mem = 0; #endif @@ -543,7 +571,7 @@ int public_sET_STATe(Void_t* msptr) { struct malloc_save_state* ms = (struct malloc_save_state*)msptr; - int i; + size_t i; mbinptr b; disallow_malloc_check = 1; @@ -554,7 +582,7 @@ public_sET_STATe(Void_t* msptr) (void)mutex_lock(&main_arena.mutex); /* There are no fastchunks. */ clear_fastchunks(&main_arena); - set_max_fast(&main_arena, DEFAULT_MXFAST); + set_max_fast(DEFAULT_MXFAST); for (i=0; iav[2*i+3] == 0); first(b) = last(b) = b; } else { - if(iav[2*i+2]))==i && - largebin_index(chunksize(ms->av[2*i+3]))==i)) { + if(ms->version >= 3 && + (iav[2*i+2]))==i && + largebin_index(chunksize(ms->av[2*i+3]))==i))) { first(b) = ms->av[2*i+2]; last(b) = ms->av[2*i+3]; /* Make sure the links to the bins within the heap are correct. */ @@ -588,6 +617,17 @@ public_sET_STATe(Void_t* msptr) } } } + if (ms->version < 3) { + /* Clear fd_nextsize and bk_nextsize fields. */ + b = unsorted_chunks(&main_arena)->fd; + while (b != unsorted_chunks(&main_arena)) { + if (!in_smallbin_range(chunksize(b))) { + b->fd_nextsize = NULL; + b->bk_nextsize = NULL; + } + b = b->fd; + } + } mp_.sbrk_base = ms->sbrk_base; main_arena.system_mem = ms->sbrked_mem_bytes; mp_.trim_threshold = ms->trim_threshold;