diff options
-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 | ||||
-rw-r--r-- | test/trefstr.c | 1 |
9 files changed, 458 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); diff --git a/test/trefstr.c b/test/trefstr.c index 8073c3f..eca4aaf 100644 --- a/test/trefstr.c +++ b/test/trefstr.c @@ -289,6 +289,7 @@ test_refstr_wrap(void) static void test_refstr_own(void) { + static const char *FUNC = "test_refstr_own"; H5RS_str_t *rs; /* Ref-counted string created */ char *s; /* Pointer to string to transfer */ const char *t; /* Temporary pointers to string */ |