diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2005-08-20 18:09:28 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2005-08-20 18:09:28 (GMT) |
commit | 96b3c145b7b8e033fff6504a5dbb88c78c42219b (patch) | |
tree | ffc018237d328eb5b4444d20eba7f52945d818d3 /src | |
parent | d29082f1659e2b5faa5fda61003b792cc5c9c4c7 (diff) | |
download | hdf5-96b3c145b7b8e033fff6504a5dbb88c78c42219b.zip hdf5-96b3c145b7b8e033fff6504a5dbb88c78c42219b.tar.gz hdf5-96b3c145b7b8e033fff6504a5dbb88c78c42219b.tar.bz2 |
[svn-r11282] Purpose:
New debugging feature
Description:
Add some code to track where memory from the internal free list allocator
is allocated within the library. It's not quite ready for "prime time" yet,
but it's close enough to be useful.
This is disabled by default and requires the H5FL_TRACK macro in
src/H5FLprivate.h to be uncommented to activate during debugging.
Platforms tested:
FreeBSD 4.11 (sleipnir)
Linux 2.4
Too minor to require full h5committest
Diffstat (limited to 'src')
-rw-r--r-- | src/H5CS.c | 117 | ||||
-rw-r--r-- | src/H5CSprivate.h | 5 | ||||
-rw-r--r-- | src/H5Distore.c | 3 | ||||
-rw-r--r-- | src/H5FL.c | 214 | ||||
-rw-r--r-- | src/H5FLprivate.h | 84 | ||||
-rw-r--r-- | src/H5FS.c | 117 | ||||
-rw-r--r-- | src/H5FSprivate.h | 5 | ||||
-rw-r--r-- | src/H5RS.c | 2 |
8 files changed, 457 insertions, 90 deletions
@@ -27,8 +27,9 @@ */ -#include "H5private.h" /* Generic Functions */ -#include "H5FSprivate.h" /* Private function stack routines */ +#include "H5private.h" /* Generic Functions */ +#include "H5FSprivate.h" /* Function stack */ +#include "H5MMprivate.h" /* Memory management */ #ifdef H5_HAVE_FUNCSTACK @@ -93,31 +94,30 @@ H5FS_get_stack(void) /*------------------------------------------------------------------------- - * Function: H5FS_print + * Function: H5FS_print_stack * - * Purpose: Prints the function stack in some default way. + * Purpose: Prints a function stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * THursday, February 6, 2003 + * Thursday, February 6, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t -H5FS_print(FILE *stream) +H5FS_print_stack(const H5FS_t *fstack, FILE *stream) { - H5FS_t *fstack = H5FS_get_my_stack (); /* Get the correct function stack */ const int indent = 2; /* Indention level */ int i; /* Local index ariable */ /* Don't push this function on the function stack... :-) */ - FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_print); + FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_print_stack); /* Sanity check */ - assert(fstack); + HDassert(fstack); /* Default to outputting information to stderr */ if (!stream) @@ -138,6 +138,37 @@ H5FS_print(FILE *stream) HDfprintf(stream, "%*s#%03d: Routine: %s\n", indent, "", i, fstack->slot[i]); FUNC_LEAVE_NOAPI_NOFS(SUCCEED); +} /* end H5FS_print_stack() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_print + * + * Purpose: Prints the default function stack in some default way. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, February 6, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_print(FILE *stream) +{ + H5FS_t *fstack = H5FS_get_my_stack (); /* Get the correct function stack */ + + /* Don't push this function on the function stack... :-) */ + FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_print); + + /* Sanity check */ + assert(fstack); + + H5FS_print_stack(fstack, stream); + + FUNC_LEAVE_NOAPI_NOFS(SUCCEED); } /* end H5FS_print() */ @@ -211,4 +242,72 @@ H5FS_pop(void) FUNC_LEAVE_NOAPI_NOFS(SUCCEED); } /* end H5FS_pop() */ + +/*------------------------------------------------------------------------- + * Function: H5FS_copy_stack + * + * Purpose: Makes a copy of the current stack + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 9, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_copy_stack(H5FS_t *new_stack) +{ + H5FS_t *old_stack = H5FS_get_my_stack (); + unsigned u; /* Local index variable */ + + /* Don't push this function on the function stack... :-) */ + FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_copy_stack); + + /* Sanity check */ + HDassert (old_stack); + + /* Copy old stack to new one, duplicating the strings */ + for(u = 0; u < old_stack->nused; u++) + new_stack->slot[u] = H5MM_strdup(old_stack->slot[u]); + new_stack->nused = old_stack->nused; + + FUNC_LEAVE_NOAPI_NOFS(SUCCEED); +} /* end H5FS_copy_stack() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_close_stack + * + * Purpose: Closes a copy of a stack + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 9, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_close_stack(H5FS_t *stack) +{ + unsigned u; /* Local index variable */ + + /* Don't push this function on the function stack... :-) */ + FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_close_stack); + + /* Sanity check */ + HDassert (stack); + + /* Free strings on stack */ + for(u = 0; u < stack->nused; u++) + stack->slot[u] = H5MM_xfree(stack->slot[u]); + + FUNC_LEAVE_NOAPI_NOFS(SUCCEED); +} /* end H5FS_close_stack() */ + #endif /* H5_HAVE_FUNCSTACK */ diff --git a/src/H5CSprivate.h b/src/H5CSprivate.h index 6dba575..d75bbec 100644 --- a/src/H5CSprivate.h +++ b/src/H5CSprivate.h @@ -29,12 +29,15 @@ /* A function stack */ typedef struct H5FS_t { - int nused; /*num slots currently used in stack */ + unsigned nused; /*num slots currently used in stack */ const char *slot[H5FS_NSLOTS]; /*array of function records */ } H5FS_t; H5_DLL herr_t H5FS_push (const char *func_name); H5_DLL herr_t H5FS_pop (void); H5_DLL herr_t H5FS_print (FILE *stream); +H5_DLL herr_t H5FS_print_stack (const H5FS_t *stack, FILE *stream); +H5_DLL herr_t H5FS_copy_stack (H5FS_t *stack); +H5_DLL herr_t H5FS_close_stack (H5FS_t *stack); #endif /* _H5FSprivate_H */ diff --git a/src/H5Distore.c b/src/H5Distore.c index 688b5d4..2a753f0 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -2388,8 +2388,7 @@ static void * H5D_istore_chunk_alloc(size_t size, const H5O_pline_t *pline) { void *ret_value=NULL; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_chunk_alloc) + FUNC_ENTER_NOAPI_NOINIT(H5D_istore_chunk_alloc) assert(size); assert(pline); @@ -97,6 +97,11 @@ typedef struct H5FL_blk_gc_list_t { /* The head of the list of PQs to garbage collect */ static H5FL_blk_gc_list_t H5FL_blk_gc_head={0,NULL}; +#ifdef H5FL_TRACK +/* Head of "outstanding allocations" list */ +static H5FL_track_t *H5FL_out_head_g = NULL; +#endif /* H5FL_TRACK */ + /* Forward declarations of local static functions */ static herr_t H5FL_reg_gc(void); static herr_t H5FL_reg_gc_list(H5FL_reg_head_t *head); @@ -157,7 +162,7 @@ H5FL_init_interface(void) static void * H5FL_malloc(size_t mem_size) { - void *ret_value=NULL; /* return value*/ + void *ret_value; /* return value*/ FUNC_ENTER_NOAPI(H5FL_malloc, NULL) @@ -215,6 +220,11 @@ H5FL_reg_init(H5FL_reg_head_t *head) /* Indicate that the free list is initialized */ head->init=1; + /* Make certain there's room for tracking information, if any */ +#ifdef H5FL_TRACK + head->size += sizeof(H5FL_track_t); +#endif /* H5FL_TRACK */ + /* Make certain that the space allocated is large enough to store a free list pointer (eventually) */ if(head->size<sizeof(void *)) head->size=sizeof(void *); @@ -242,7 +252,6 @@ done: void * H5FL_reg_free(H5FL_reg_head_t *head, void *obj) { - H5FL_reg_node_t *temp; /* Temp. ptr to the new free list node allocated */ void *ret_value=NULL; /* Return value */ FUNC_ENTER_NOAPI(H5FL_reg_free, NULL) @@ -251,6 +260,30 @@ H5FL_reg_free(H5FL_reg_head_t *head, void *obj) assert(head); assert(obj); +#ifdef H5FL_TRACK + { + H5FL_track_t *trk = obj = ((unsigned char *)obj) - sizeof(H5FL_track_t); + + /* Free tracking information about the allocation location */ + H5FS_close_stack(trk->stack); + trk->stack = H5MM_xfree(trk->stack); + trk->file = H5MM_xfree(trk->file); + trk->func = H5MM_xfree(trk->func); + + /* Remove from "outstanding allocations" list */ + if(trk == H5FL_out_head_g) { + H5FL_out_head_g = H5FL_out_head_g->next; + if(H5FL_out_head_g) + H5FL_out_head_g->prev = NULL; + } /* end if */ + else { + trk->prev->next = trk->next; + if(trk->next) + trk->next->prev = trk->prev; + } /* end else */ + } +#endif /* H5FL_TRACK */ + #ifdef H5FL_DEBUG HDmemset(obj,255,head->size); #endif /* H5FL_DEBUG */ @@ -258,14 +291,11 @@ H5FL_reg_free(H5FL_reg_head_t *head, void *obj) /* Make certain that the free list is initialized */ assert(head->init); - /* Alias the pointer to the block to free into a H5FL_reg_node_t node */ - temp=(H5FL_reg_node_t *)obj; - /* Link into the free list */ - temp->next=head->list; + ((H5FL_reg_node_t *)obj)->next=head->list; /* Point free list at the node freed */ - head->list=temp; + head->list=(H5FL_reg_node_t *)obj; /* Increment the number of blocks & memory on free list */ head->onlist++; @@ -306,7 +336,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_reg_malloc(H5FL_reg_head_t *head) +H5FL_reg_malloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS) { void *ret_value; /* Pointer to object to return */ @@ -334,7 +364,6 @@ H5FL_reg_malloc(H5FL_reg_head_t *head) /* Decrement the amount of global "regular" free list memory in use */ H5FL_reg_gc_head.mem_freed-=(head->size); - } /* end if */ /* Otherwise allocate a node */ else { @@ -345,6 +374,25 @@ H5FL_reg_malloc(H5FL_reg_head_t *head) head->allocated++; } /* end else */ +#ifdef H5FL_TRACK + /* Copy allocation location information */ + ((H5FL_track_t *)ret_value)->stack = H5MM_malloc(sizeof(H5FS_t)); + H5FS_copy_stack(((H5FL_track_t *)ret_value)->stack); + ((H5FL_track_t *)ret_value)->file = H5MM_strdup(call_file); + ((H5FL_track_t *)ret_value)->func = H5MM_strdup(call_func); + ((H5FL_track_t *)ret_value)->line = call_line; + + /* Add to "outstanding allocations" list */ + ((H5FL_track_t *)ret_value)->prev = NULL; + ((H5FL_track_t *)ret_value)->next = H5FL_out_head_g; + if(H5FL_out_head_g) + H5FL_out_head_g->prev = (H5FL_track_t *)ret_value; + H5FL_out_head_g = (H5FL_track_t *)ret_value; + + /* Adjust for allocation tracking information */ + ret_value = ((unsigned char *)ret_value) + sizeof(H5FL_track_t); +#endif /* H5FL_TRACK */ + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FL_reg_malloc() */ @@ -366,7 +414,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_reg_calloc(H5FL_reg_head_t *head) +H5FL_reg_calloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS) { void *ret_value; /* Pointer to object to return */ @@ -376,11 +424,12 @@ H5FL_reg_calloc(H5FL_reg_head_t *head) assert(head); /* Allocate the block */ - if (NULL==(ret_value = H5FL_reg_malloc(head))) + if (NULL==(ret_value = H5FL_reg_malloc(head H5FL_TRACK_INFO_INT))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Clear to zeros */ - HDmemset(ret_value,0,head->size); + /* (Accomodate tracking information, if present) */ + HDmemset(ret_value,0,head->size - H5FL_TRACK_SIZE); done: FUNC_LEAVE_NOAPI(ret_value) @@ -775,7 +824,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size) +H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS) { H5FL_blk_node_t *free_list; /* The free list of nodes of correct size */ H5FL_blk_list_t *temp; /* Temp. ptr to the new native list allocated */ @@ -799,12 +848,6 @@ H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size) temp=free_list->list; free_list->list=free_list->list->next; - /* Restore the size of the block */ - temp->size=size; /* Overwrites the 'next' field */ - - /* Return the pointer to the data portion */ - ret_value=((char *)temp)+sizeof(H5FL_blk_list_t); - /* Decrement the number of blocks & memory used on free list */ head->onlist--; head->list_mem-=size; @@ -816,18 +859,37 @@ H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size) /* No free list available, or there are no nodes on the list, allocate a new node to give to the user */ else { /* Allocate new node, with room for the page info header and the actual page data */ - if(NULL==(temp=H5FL_malloc(sizeof(H5FL_blk_list_t)+size))) + if(NULL==(temp=H5FL_malloc(sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE + size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for chunk") /* Increment the number of blocks allocated */ head->allocated++; + } /* end else */ - /* Initialize the block allocated */ - temp->size=size; + /* Initialize the block allocated */ + temp->size=size; - /* Set the return value to the block itself */ - ret_value=((char *)temp)+sizeof(H5FL_blk_list_t); - } /* end else */ + /* Set the return value to the block itself */ + ret_value=((char *)temp)+sizeof(H5FL_blk_list_t); + +#ifdef H5FL_TRACK + /* Copy allocation location information */ + ((H5FL_track_t *)ret_value)->stack = H5MM_malloc(sizeof(H5FS_t)); + H5FS_copy_stack(((H5FL_track_t *)ret_value)->stack); + ((H5FL_track_t *)ret_value)->file = H5MM_strdup(call_file); + ((H5FL_track_t *)ret_value)->func = H5MM_strdup(call_func); + ((H5FL_track_t *)ret_value)->line = call_line; + + /* Add to "outstanding allocations" list */ + ((H5FL_track_t *)ret_value)->prev = NULL; + ((H5FL_track_t *)ret_value)->next = H5FL_out_head_g; + if(H5FL_out_head_g) + H5FL_out_head_g->prev = (H5FL_track_t *)ret_value; + H5FL_out_head_g = (H5FL_track_t *)ret_value; + + /* Adjust for allocation tracking information */ + ret_value = ((unsigned char *)ret_value) + sizeof(H5FL_track_t); +#endif /* H5FL_TRACK */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -854,7 +916,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size) +H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS) { void *ret_value; /* Pointer to the block to return to the user */ @@ -865,7 +927,7 @@ H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size) assert(size); /* Allocate the block */ - if (NULL==(ret_value = H5FL_blk_malloc(head,size))) + if (NULL==(ret_value = H5FL_blk_malloc(head,size H5FL_TRACK_INFO_INT))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Clear the block to zeros */ @@ -908,16 +970,45 @@ H5FL_blk_free(H5FL_blk_head_t *head, void *block) assert(head); assert(block); +#ifdef H5FL_TRACK + { + H5FL_track_t *trk = block = ((unsigned char *)block) - sizeof(H5FL_track_t); + + /* Free tracking information about the allocation location */ + H5FS_close_stack(trk->stack); + trk->stack = H5MM_xfree(trk->stack); + trk->file = H5MM_xfree(trk->file); + trk->func = H5MM_xfree(trk->func); + + /* Remove from "outstanding allocations" list */ + if(trk == H5FL_out_head_g) { + H5FL_out_head_g = H5FL_out_head_g->next; + if(H5FL_out_head_g) + H5FL_out_head_g->prev = NULL; + } /* end if */ + else { + trk->prev->next = trk->next; + if(trk->next) + trk->next->prev = trk->prev; + } /* end else */ + } +#endif /* H5FL_TRACK */ + /* Get the pointer to the native block info header in front of the native block to free */ temp=(H5FL_blk_list_t *)((unsigned char *)block-sizeof(H5FL_blk_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */ /* Save the block's size for later */ free_size=temp->size; +#ifdef H5FL_DEBUG + HDmemset(temp,255,free_size + sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE); +#endif /* H5FL_DEBUG */ + /* check if there is a free list for native blocks of this size */ - if((free_list=H5FL_blk_find_list(&(head->head),temp->size))==NULL) { + if((free_list=H5FL_blk_find_list(&(head->head),free_size))==NULL) { /* No free list available, create a new list node and insert it to the queue */ - free_list=H5FL_blk_create_list(&(head->head),temp->size); + free_list=H5FL_blk_create_list(&(head->head),free_size); + HDassert(free_list); } /* end if */ /* Prepend the free'd native block to the front of the free list */ @@ -967,7 +1058,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size) +H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size H5FL_TRACK_PARAMS) { void *ret_value=NULL; /* Return value */ @@ -982,24 +1073,41 @@ H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size) H5FL_blk_list_t *temp; /* Temp. ptr to the new block node allocated */ /* Get the pointer to the chunk info header in front of the chunk to free */ - temp=(H5FL_blk_list_t *)((unsigned char *)block-sizeof(H5FL_blk_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */ + temp=(H5FL_blk_list_t *)((unsigned char *)block - (sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE)); /*lint !e826 Pointer-to-pointer cast is appropriate here */ /* check if we are actually changing the size of the buffer */ if(new_size!=temp->size) { size_t blk_size; /* Temporary block size */ - if((ret_value=H5FL_blk_malloc(head,new_size))==NULL) + if((ret_value=H5FL_blk_malloc(head,new_size H5FL_TRACK_INFO_INT))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for block") blk_size=MIN(new_size,temp->size); HDmemcpy(ret_value,block,blk_size); H5FL_blk_free(head,block); } /* end if */ - else + else { +#ifdef H5FL_TRACK + { + H5FL_track_t *trk = (H5FL_track_t *)(((unsigned char *)block) - sizeof(H5FL_track_t)); + + /* Release previous tracking information */ + H5FS_close_stack(trk->stack); + trk->file = H5MM_xfree(trk->file); + trk->func = H5MM_xfree(trk->func); + + /* Store new tracking information */ + H5FS_copy_stack(trk->stack); + trk->file = H5MM_strdup(call_file); + trk->func = H5MM_strdup(call_func); + trk->line = call_line; + } +#endif /* H5FL_TRACK */ ret_value=block; + } /* end if */ } /* end if */ /* Not re-allocating, just allocate a fresh block */ else - ret_value=H5FL_blk_malloc(head,new_size); + ret_value=H5FL_blk_malloc(head,new_size H5FL_TRACK_INFO_INT); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1753,7 +1861,7 @@ H5FL_seq_free(H5FL_seq_head_t *head, void *obj) *------------------------------------------------------------------------- */ void * -H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem) +H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS) { void *ret_value; /* Pointer to object to return */ @@ -1764,7 +1872,7 @@ H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem) assert(elem); /* Use block routine */ - ret_value=H5FL_blk_malloc(&(head->queue),head->size*elem); + ret_value=H5FL_blk_malloc(&(head->queue),head->size*elem H5FL_TRACK_INFO_INT); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1787,7 +1895,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_seq_calloc(H5FL_seq_head_t *head, size_t elem) +H5FL_seq_calloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS) { void *ret_value; /* Pointer to object to return */ @@ -1798,7 +1906,7 @@ H5FL_seq_calloc(H5FL_seq_head_t *head, size_t elem) assert(elem); /* Use block routine */ - ret_value=H5FL_blk_calloc(&(head->queue),head->size*elem); + ret_value=H5FL_blk_calloc(&(head->queue),head->size*elem H5FL_TRACK_INFO_INT); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1821,7 +1929,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_seq_realloc(H5FL_seq_head_t *head, void * obj, size_t new_elem) +H5FL_seq_realloc(H5FL_seq_head_t *head, void * obj, size_t new_elem H5FL_TRACK_PARAMS) { void *ret_value; /* Pointer to object to return */ @@ -1832,7 +1940,7 @@ H5FL_seq_realloc(H5FL_seq_head_t *head, void * obj, size_t new_elem) assert(new_elem); /* Use block routine */ - ret_value=H5FL_blk_realloc(&(head->queue),obj,head->size*new_elem); + ret_value=H5FL_blk_realloc(&(head->queue),obj,head->size*new_elem H5FL_TRACK_INFO_INT); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1933,7 +2041,7 @@ H5FL_fac_free(H5FL_fac_head_t *head, void *obj) *------------------------------------------------------------------------- */ void * -H5FL_fac_malloc(H5FL_fac_head_t *head) +H5FL_fac_malloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS) { void *ret_value; /* Pointer to object to return */ @@ -1943,7 +2051,7 @@ H5FL_fac_malloc(H5FL_fac_head_t *head) assert(head); /* Use block routine */ - ret_value=H5FL_blk_malloc(&(head->queue),head->size); + ret_value=H5FL_blk_malloc(&(head->queue),head->size H5FL_TRACK_INFO_INT); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1966,7 +2074,7 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_fac_calloc(H5FL_fac_head_t *head) +H5FL_fac_calloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS) { void *ret_value; /* Pointer to object to return */ @@ -1976,7 +2084,7 @@ H5FL_fac_calloc(H5FL_fac_head_t *head) assert(head); /* Use block routine */ - ret_value=H5FL_blk_calloc(&(head->queue),head->size); + ret_value=H5FL_blk_calloc(&(head->queue),head->size H5FL_TRACK_INFO_INT); done: FUNC_LEAVE_NOAPI(ret_value) @@ -2153,6 +2261,24 @@ H5FL_term_interface(void) ret_value=H5FL_reg_term()+H5FL_arr_term()+H5FL_blk_term(); +#ifdef H5FL_TRACK + /* If we haven't freed all the allocated memory, dump out the list now */ + if(ret_value > 0 && H5FL_out_head_g) { + H5FL_track_t *trk = H5FL_out_head_g; + + /* Dump information about all the outstanding allocations */ + while(trk != NULL) { + /* Print information about the outstanding block */ + HDfprintf(stderr,"%s: Outstanding allocation:\n", "H5FL_term_interface"); + HDfprintf(stderr,"\tFile: %s, Function: %s, Line: %d\n", trk->file, trk->func, trk->line); + H5FS_print_stack(trk->stack, stderr); + + /* Advance to next node */ + trk = trk->next; + } /* end while */ + } /* end if */ +#endif /* H5FL_TRACK */ + FUNC_LEAVE_NOAPI(ret_value) } diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h index b7b2030..325eef8 100644 --- a/src/H5FLprivate.h +++ b/src/H5FLprivate.h @@ -44,6 +44,44 @@ #define H5_NO_FAC_FREE_LISTS #endif /* H5_NO_FREE_LISTS */ +/* Macro to track location where block was allocated from */ +/* Uncomment next line to turn on tracking, but don't leave it on after + * debugging is done because of the extra overhead it imposes. + */ +/* NOTE: This hasn't been extended to all the free-list allocation routines + * yet. -QAK + */ +/* #define H5FL_TRACK */ +#ifdef H5FL_TRACK +/* Macro for inclusion in the free list allocation calls */ +#define H5FL_TRACK_INFO ,__FILE__, FUNC, __LINE__ + +/* Macro for inclusion in internal free list allocation calls */ +#define H5FL_TRACK_INFO_INT ,call_file, call_func, call_line + +/* Macro for inclusion in the free list allocation parameters */ +#define H5FL_TRACK_PARAMS ,const char *call_file, const char *call_func, int call_line + +/* Tracking information for each block */ +typedef struct H5FL_track_t { + H5FS_t *stack; /* Function stack */ + char *file; /* Name of file containing calling function */ + char *func; /* Name of calling function */ + int line; /* Line # within calling function */ + struct H5FL_track_t *next; /* Pointer to next tracking block */ + struct H5FL_track_t *prev; /* Pointer to previous tracking block */ +} H5FL_track_t; + +/* Macro for size of tracking information */ +#define H5FL_TRACK_SIZE sizeof(H5FL_track_t) + +#else /* H5FL_TRACK */ +#define H5FL_TRACK_INFO +#define H5FL_TRACK_INFO_INT +#define H5FL_TRACK_PARAMS +#define H5FL_TRACK_SIZE 0 +#endif /* H5FL_TRACK */ + /* * Private datatypes. */ @@ -55,9 +93,9 @@ typedef struct H5FL_reg_node_t { /* Data structure for free list of blocks */ typedef struct H5FL_reg_head_t { - unsigned init; /* Whether the free list has been initialized */ - unsigned allocated; /* Number of blocks allocated */ - unsigned onlist; /* Number of blocks on free list */ + unsigned init; /* Whether the free list has been initialized */ + unsigned allocated; /* Number of blocks allocated */ + unsigned onlist; /* Number of blocks on free list */ size_t list_mem; /* Amount of memory on free list */ const char *name; /* Name of the type */ size_t size; /* Size of the blocks in the list */ @@ -82,10 +120,10 @@ typedef struct H5FL_reg_head_t { #define H5FL_DEFINE_STATIC(t) static H5FL_DEFINE_COMMON(t) /* Allocate an object of type 't' */ -#define H5FL_MALLOC(t) H5FL_reg_malloc(&(H5FL_REG_NAME(t))) +#define H5FL_MALLOC(t) H5FL_reg_malloc(&(H5FL_REG_NAME(t)) H5FL_TRACK_INFO) /* Allocate an object of type 't' and clear it to all zeros */ -#define H5FL_CALLOC(t) H5FL_reg_calloc(&(H5FL_REG_NAME(t))) +#define H5FL_CALLOC(t) H5FL_reg_calloc(&(H5FL_REG_NAME(t)) H5FL_TRACK_INFO) /* Free an object of type 't' */ #define H5FL_FREE(t,obj) H5FL_reg_free(&(H5FL_REG_NAME(t)),obj) @@ -151,16 +189,16 @@ typedef struct H5FL_blk_head_t { #define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE_COMMON(t) /* Allocate an block of type 't' */ -#define H5FL_BLK_MALLOC(t,size) H5FL_blk_malloc(&(H5FL_BLK_NAME(t)),size) +#define H5FL_BLK_MALLOC(t,size) H5FL_blk_malloc(&(H5FL_BLK_NAME(t)),size H5FL_TRACK_INFO) /* Allocate an block of type 't' and clear it to zeros */ -#define H5FL_BLK_CALLOC(t,size) H5FL_blk_calloc(&(H5FL_BLK_NAME(t)),size) +#define H5FL_BLK_CALLOC(t,size) H5FL_blk_calloc(&(H5FL_BLK_NAME(t)),size H5FL_TRACK_INFO) /* Free a block of type 't' */ #define H5FL_BLK_FREE(t,blk) H5FL_blk_free(&(H5FL_BLK_NAME(t)),blk) /* Re-allocate a block of type 't' */ -#define H5FL_BLK_REALLOC(t,blk,new_size) H5FL_blk_realloc(&(H5FL_BLK_NAME(t)),blk,new_size) +#define H5FL_BLK_REALLOC(t,blk,new_size) H5FL_blk_realloc(&(H5FL_BLK_NAME(t)),blk,new_size H5FL_TRACK_INFO) /* Check if there is a free block available to re-use */ #define H5FL_BLK_AVAIL(t,size) H5FL_blk_free_block_avail(&(H5FL_BLK_NAME(t)),size) @@ -283,16 +321,16 @@ typedef struct H5FL_seq_head_t { #define H5FL_SEQ_DEFINE_STATIC(t) static H5FL_SEQ_DEFINE_COMMON(t) /* Allocate a sequence of type 't' */ -#define H5FL_SEQ_MALLOC(t,elem) H5FL_seq_malloc(&(H5FL_SEQ_NAME(t)),elem) +#define H5FL_SEQ_MALLOC(t,elem) H5FL_seq_malloc(&(H5FL_SEQ_NAME(t)),elem H5FL_TRACK_INFO) /* Allocate a sequence of type 't' and clear it to all zeros */ -#define H5FL_SEQ_CALLOC(t,elem) H5FL_seq_calloc(&(H5FL_SEQ_NAME(t)),elem) +#define H5FL_SEQ_CALLOC(t,elem) H5FL_seq_calloc(&(H5FL_SEQ_NAME(t)),elem H5FL_TRACK_INFO) /* Free a sequence of type 't' */ #define H5FL_SEQ_FREE(t,obj) H5FL_seq_free(&(H5FL_SEQ_NAME(t)),obj) /* Re-allocate a sequence of type 't' */ -#define H5FL_SEQ_REALLOC(t,obj,new_elem) H5FL_seq_realloc(&(H5FL_SEQ_NAME(t)),obj,new_elem) +#define H5FL_SEQ_REALLOC(t,obj,new_elem) H5FL_seq_realloc(&(H5FL_SEQ_NAME(t)),obj,new_elem H5FL_TRACK_INFO) #else /* H5_NO_SEQ_FREE_LISTS */ /* Common macro for H5FL_BLK_DEFINE & H5FL_BLK_DEFINE_STATIC */ @@ -322,10 +360,10 @@ typedef struct H5FL_fac_head_t { */ #ifndef H5_NO_FAC_FREE_LISTS /* Allocate a block from a factory */ -#define H5FL_FAC_MALLOC(t) H5FL_fac_malloc(t) +#define H5FL_FAC_MALLOC(t) H5FL_fac_malloc(t H5FL_TRACK_INFO) /* Allocate a block from a factory and clear it to all zeros */ -#define H5FL_FAC_CALLOC(t) H5FL_fac_calloc(t) +#define H5FL_FAC_CALLOC(t) H5FL_fac_calloc(t H5FL_TRACK_INFO) /* Return a block to a factory */ #define H5FL_FAC_FREE(t,obj) H5FL_fac_free(t,obj) @@ -339,25 +377,25 @@ typedef struct H5FL_fac_head_t { /* * Library prototypes. */ -H5_DLL void * H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size); -H5_DLL void * H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size); +H5_DLL void * H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS); +H5_DLL void * H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS); H5_DLL void * H5FL_blk_free(H5FL_blk_head_t *head, void *block); -H5_DLL void * H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size); +H5_DLL void * H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size H5FL_TRACK_PARAMS); H5_DLL htri_t H5FL_blk_free_block_avail(H5FL_blk_head_t *head, size_t size); -H5_DLL void * H5FL_reg_malloc(H5FL_reg_head_t *head); -H5_DLL void * H5FL_reg_calloc(H5FL_reg_head_t *head); +H5_DLL void * H5FL_reg_malloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS); +H5_DLL void * H5FL_reg_calloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS); H5_DLL void * H5FL_reg_free(H5FL_reg_head_t *head, void *obj); H5_DLL void * H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem); H5_DLL void * H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem); H5_DLL void * H5FL_arr_free(H5FL_arr_head_t *head, void *obj); H5_DLL void * H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem); -H5_DLL void * H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem); -H5_DLL void * H5FL_seq_calloc(H5FL_seq_head_t *head, size_t elem); +H5_DLL void * H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS); +H5_DLL void * H5FL_seq_calloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS); H5_DLL void * H5FL_seq_free(H5FL_seq_head_t *head, void *obj); -H5_DLL void * H5FL_seq_realloc(H5FL_seq_head_t *head, void *obj, size_t new_elem); +H5_DLL void * H5FL_seq_realloc(H5FL_seq_head_t *head, void *obj, size_t new_elem H5FL_TRACK_PARAMS); H5_DLL H5FL_fac_head_t *H5FL_fac_init(size_t size); -H5_DLL void * H5FL_fac_malloc(H5FL_fac_head_t *head); -H5_DLL void * H5FL_fac_calloc(H5FL_fac_head_t *head); +H5_DLL void * H5FL_fac_malloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS); +H5_DLL void * H5FL_fac_calloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS); H5_DLL void * H5FL_fac_free(H5FL_fac_head_t *head, void *obj); H5_DLL herr_t H5FL_fac_term(H5FL_fac_head_t *head); H5_DLL herr_t H5FL_garbage_coll(void); @@ -27,8 +27,9 @@ */ -#include "H5private.h" /* Generic Functions */ -#include "H5FSprivate.h" /* Private function stack routines */ +#include "H5private.h" /* Generic Functions */ +#include "H5FSprivate.h" /* Function stack */ +#include "H5MMprivate.h" /* Memory management */ #ifdef H5_HAVE_FUNCSTACK @@ -93,31 +94,30 @@ H5FS_get_stack(void) /*------------------------------------------------------------------------- - * Function: H5FS_print + * Function: H5FS_print_stack * - * Purpose: Prints the function stack in some default way. + * Purpose: Prints a function stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * THursday, February 6, 2003 + * Thursday, February 6, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t -H5FS_print(FILE *stream) +H5FS_print_stack(const H5FS_t *fstack, FILE *stream) { - H5FS_t *fstack = H5FS_get_my_stack (); /* Get the correct function stack */ const int indent = 2; /* Indention level */ int i; /* Local index ariable */ /* Don't push this function on the function stack... :-) */ - FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_print); + FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_print_stack); /* Sanity check */ - assert(fstack); + HDassert(fstack); /* Default to outputting information to stderr */ if (!stream) @@ -138,6 +138,37 @@ H5FS_print(FILE *stream) HDfprintf(stream, "%*s#%03d: Routine: %s\n", indent, "", i, fstack->slot[i]); FUNC_LEAVE_NOAPI_NOFS(SUCCEED); +} /* end H5FS_print_stack() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_print + * + * Purpose: Prints the default function stack in some default way. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, February 6, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_print(FILE *stream) +{ + H5FS_t *fstack = H5FS_get_my_stack (); /* Get the correct function stack */ + + /* Don't push this function on the function stack... :-) */ + FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_print); + + /* Sanity check */ + assert(fstack); + + H5FS_print_stack(fstack, stream); + + FUNC_LEAVE_NOAPI_NOFS(SUCCEED); } /* end H5FS_print() */ @@ -211,4 +242,72 @@ H5FS_pop(void) FUNC_LEAVE_NOAPI_NOFS(SUCCEED); } /* end H5FS_pop() */ + +/*------------------------------------------------------------------------- + * Function: H5FS_copy_stack + * + * Purpose: Makes a copy of the current stack + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 9, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_copy_stack(H5FS_t *new_stack) +{ + H5FS_t *old_stack = H5FS_get_my_stack (); + unsigned u; /* Local index variable */ + + /* Don't push this function on the function stack... :-) */ + FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_copy_stack); + + /* Sanity check */ + HDassert (old_stack); + + /* Copy old stack to new one, duplicating the strings */ + for(u = 0; u < old_stack->nused; u++) + new_stack->slot[u] = H5MM_strdup(old_stack->slot[u]); + new_stack->nused = old_stack->nused; + + FUNC_LEAVE_NOAPI_NOFS(SUCCEED); +} /* end H5FS_copy_stack() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_close_stack + * + * Purpose: Closes a copy of a stack + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 9, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_close_stack(H5FS_t *stack) +{ + unsigned u; /* Local index variable */ + + /* Don't push this function on the function stack... :-) */ + FUNC_ENTER_NOAPI_NOFUNC_NOFS(H5FS_close_stack); + + /* Sanity check */ + HDassert (stack); + + /* Free strings on stack */ + for(u = 0; u < stack->nused; u++) + stack->slot[u] = H5MM_xfree(stack->slot[u]); + + FUNC_LEAVE_NOAPI_NOFS(SUCCEED); +} /* end H5FS_close_stack() */ + #endif /* H5_HAVE_FUNCSTACK */ diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index 6dba575..d75bbec 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -29,12 +29,15 @@ /* A function stack */ typedef struct H5FS_t { - int nused; /*num slots currently used in stack */ + unsigned nused; /*num slots currently used in stack */ const char *slot[H5FS_NSLOTS]; /*array of function records */ } H5FS_t; H5_DLL herr_t H5FS_push (const char *func_name); H5_DLL herr_t H5FS_pop (void); H5_DLL herr_t H5FS_print (FILE *stream); +H5_DLL herr_t H5FS_print_stack (const H5FS_t *stack, FILE *stream); +H5_DLL herr_t H5FS_copy_stack (H5FS_t *stack); +H5_DLL herr_t H5FS_close_stack (H5FS_t *stack); #endif /* _H5FSprivate_H */ @@ -62,7 +62,7 @@ H5RS_xstrdup(const char *s) { char *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5RS_xstrdup); + FUNC_ENTER_NOAPI_NOINIT(H5RS_xstrdup); if (s) { ret_value = H5FL_BLK_MALLOC(str_buf,HDstrlen(s) + 1); |