summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5CS.c117
-rw-r--r--src/H5CSprivate.h5
-rw-r--r--src/H5Distore.c3
-rw-r--r--src/H5FL.c214
-rw-r--r--src/H5FLprivate.h84
-rw-r--r--src/H5FS.c117
-rw-r--r--src/H5FSprivate.h5
-rw-r--r--src/H5RS.c2
-rw-r--r--test/trefstr.c1
9 files changed, 458 insertions, 90 deletions
diff --git a/src/H5CS.c b/src/H5CS.c
index 63928dd..83c4020 100644
--- a/src/H5CS.c
+++ b/src/H5CS.c
@@ -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);
diff --git a/src/H5FL.c b/src/H5FL.c
index cc9edb5..1165a36 100644
--- a/src/H5FL.c
+++ b/src/H5FL.c
@@ -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);
diff --git a/src/H5FS.c b/src/H5FS.c
index 63928dd..83c4020 100644
--- a/src/H5FS.c
+++ b/src/H5FS.c
@@ -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 */
diff --git a/src/H5RS.c b/src/H5RS.c
index 96d31b3..7d5bbfe 100644
--- a/src/H5RS.c
+++ b/src/H5RS.c
@@ -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 */