summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDana Robinson <derobins@hdfgroup.org>2020-07-08 21:24:55 (GMT)
committerDana Robinson <derobins@hdfgroup.org>2020-07-08 21:24:55 (GMT)
commit185ec14f360efb80eb4638cc3745834a141280e1 (patch)
tree1355143d703d710f6c1a9fc43f120c1b89f9db7f
parent50ef7ff9962051c767aae7ad229b558b7586c59b (diff)
downloadhdf5-185ec14f360efb80eb4638cc3745834a141280e1.zip
hdf5-185ec14f360efb80eb4638cc3745834a141280e1.tar.gz
hdf5-185ec14f360efb80eb4638cc3745834a141280e1.tar.bz2
Normalization of H5MM and H5FL with develop. Adds the new
stats calls.
-rw-r--r--src/H5.c81
-rw-r--r--src/H5FL.c490
-rw-r--r--src/H5FLprivate.h20
-rw-r--r--src/H5MM.c52
-rw-r--r--src/H5MMprivate.h1
-rw-r--r--src/H5private.h5
-rw-r--r--src/H5public.h16
7 files changed, 445 insertions, 220 deletions
diff --git a/src/H5.c b/src/H5.c
index ed09c7c..03fe535 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -547,6 +547,87 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5get_free_list_sizes
+ *
+ * Purpose: Gets the current size of the different kinds of free lists that
+ * the library uses to manage memory. The free list sizes can be set with
+ * H5set_free_list_limits and garbage collected with H5garbage_collect.
+ * These lists are global for the entire library.
+ *
+ * Parameters:
+ * size_t *reg_size; OUT: The current size of all "regular" free list memory used
+ * size_t *arr_size; OUT: The current size of all "array" free list memory used
+ * size_t *blk_size; OUT: The current size of all "block" free list memory used
+ * size_t *fac_size; OUT: The current size of all "factory" free list memory used
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, March 6, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5get_free_list_sizes(size_t *reg_size, size_t *arr_size, size_t *blk_size,
+ size_t *fac_size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "*z*z*z*z", reg_size, arr_size, blk_size, fac_size);
+
+ /* Call the free list function to actually get the sizes */
+ if(H5FL_get_free_list_sizes(reg_size, arr_size, blk_size, fac_size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get garbage collection sizes")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5get_free_list_sizes() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5get_alloc_stats
+ *
+ * Purpose: Gets the memory allocation statistics for the library, if the
+ * --enable-memory-alloc-sanity-check option was given when building the
+ * library. Applications can check whether this option was enabled by
+ * detecting if the 'H5_MEMORY_ALLOC_SANITY_CHECK' macro is defined. This
+ * option is enabled by default for debug builds of the library and
+ * disabled by default for non-debug builds. If the option is not enabled,
+ * all the values returned with be 0. These statistics are global for the
+ * entire library, but don't include allocations from chunked dataset I/O
+ * filters or non-native VOL connectors.
+ *
+ * Parameters:
+ * H5_alloc_stats_t *stats; OUT: Memory allocation statistics
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, March 7, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5get_alloc_stats(H5_alloc_stats_t *stats)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "*x", stats);
+
+ /* Call the internal allocation stat routine to get the values */
+ if(H5MM_get_alloc_stats(stats) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get allocation stats")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5get_alloc_stats() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5_debug_mask
*
* Purpose: Set runtime debugging flags according to the string S. The
diff --git a/src/H5FL.c b/src/H5FL.c
index a662713..66d27fb 100644
--- a/src/H5FL.c
+++ b/src/H5FL.c
@@ -130,17 +130,23 @@ static H5FL_track_t *H5FL_out_head_g = NULL;
#endif /* H5FL_TRACK */
/* Forward declarations of local static functions */
+static void * H5FL__malloc(size_t mem_size);
+static herr_t H5FL__reg_init(H5FL_reg_head_t *head);
static herr_t H5FL__reg_gc(void);
static herr_t H5FL__reg_gc_list(H5FL_reg_head_t *head);
static int H5FL__reg_term(void);
-static herr_t H5FL__arr_gc(void);
-static herr_t H5FL__arr_gc_list(H5FL_arr_head_t *head);
-static int H5FL__arr_term(void);
-static herr_t H5FL__blk_gc(void);
+static H5FL_blk_node_t *H5FL__blk_find_list(H5FL_blk_node_t **head, size_t size);
+static H5FL_blk_node_t *H5FL__blk_create_list(H5FL_blk_node_t **head, size_t size);
+static herr_t H5FL__blk_init(H5FL_blk_head_t *head);
static herr_t H5FL__blk_gc_list(H5FL_blk_head_t *head);
+static herr_t H5FL__blk_gc(void);
static int H5FL__blk_term(void);
-static herr_t H5FL__fac_gc(void);
+static herr_t H5FL__arr_init(H5FL_arr_head_t *head);
+static herr_t H5FL__arr_gc_list(H5FL_arr_head_t *head);
+static herr_t H5FL__arr_gc(void);
+static int H5FL__arr_term(void);
static herr_t H5FL__fac_gc_list(H5FL_fac_head_t *head);
+static herr_t H5FL__fac_gc(void);
static int H5FL__fac_term_all(void);
/* Declare a free list to manage the H5FL_blk_node_t struct */
@@ -217,7 +223,7 @@ H5FL_term_package(void)
/*-------------------------------------------------------------------------
- * Function: H5FL_malloc
+ * Function: H5FL__malloc
*
* Purpose: Attempt to allocate space using malloc. If malloc fails, garbage
* collect and try again. If malloc fails again, then return NULL.
@@ -228,16 +234,14 @@ H5FL_term_package(void)
* Programmer: Quincey Koziol
* Tuesday, August 1, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static void *
-H5FL_malloc(size_t mem_size)
+H5FL__malloc(size_t mem_size)
{
void *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Attempt to allocate the memory requested */
if(NULL==(ret_value=H5MM_malloc(mem_size))) {
@@ -252,11 +256,11 @@ H5FL_malloc(size_t mem_size)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FL_malloc() */
+} /* end H5FL__malloc() */
/*-------------------------------------------------------------------------
- * Function: H5FL_reg_init
+ * Function: H5FL__reg_init
*
* Purpose: Initialize a free list for a certain type. Right now, this just
* adds the free list to the list of things to garbage collect.
@@ -267,17 +271,15 @@ done:
* Programmer: Quincey Koziol
* Friday, March 24, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FL_reg_init(H5FL_reg_head_t *head)
+H5FL__reg_init(H5FL_reg_head_t *head)
{
H5FL_reg_gc_node_t *new_node; /* Pointer to the node for the new list to garbage collect */
herr_t ret_value=SUCCEED; /* return value*/
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Allocate a new garbage collection node */
if(NULL == (new_node = (H5FL_reg_gc_node_t *)H5MM_malloc(sizeof(H5FL_reg_gc_node_t))))
@@ -304,7 +306,7 @@ H5FL_reg_init(H5FL_reg_head_t *head)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FL_reg_init() */
+} /* end H5FL__reg_init() */
/*-------------------------------------------------------------------------
@@ -317,8 +319,6 @@ done:
* Programmer: Quincey Koziol
* Friday, March 24, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -403,8 +403,6 @@ done:
* Programmer: Quincey Koziol
* Friday, March 24, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -419,7 +417,7 @@ H5FL_reg_malloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS)
/* Make certain the list is initialized first */
if(!head->init)
- if(H5FL_reg_init(head)<0)
+ if(H5FL__reg_init(head) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't initialize 'regular' blocks")
/* Check for nodes available on the free list first */
@@ -438,7 +436,7 @@ H5FL_reg_malloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS)
} /* end if */
/* Otherwise allocate a node */
else {
- if (NULL==(ret_value = H5FL_malloc(head->size)))
+ if(NULL == (ret_value = H5FL__malloc(head->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Increment the number of blocks allocated in list */
@@ -480,8 +478,6 @@ done:
* Programmer: Quincey Koziol
* Monday, December 23, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -524,35 +520,34 @@ static herr_t
H5FL__reg_gc_list(H5FL_reg_head_t *head)
{
H5FL_reg_node_t *free_list; /* Pointer to nodes in free list being garbage collected */
- size_t total_mem; /* Total memory used on list */
FUNC_ENTER_STATIC_NOERR
- /* Calculate the total memory used on this list */
- total_mem = head->onlist * head->size;
-
/* For each free list being garbage collected, walk through the nodes and free them */
free_list = head->list;
while(free_list != NULL) {
- void *tmp; /* Temporary node pointer */
+ H5FL_reg_node_t *tmp; /* Temporary node pointer */
+ /* Get the pointer to the next node */
tmp = free_list->next;
- /* Decrement the count of nodes allocated and free the node */
- head->allocated--;
-
+ /* Free the block */
H5MM_free(free_list);
- free_list = (H5FL_reg_node_t *)tmp;
+ /* Advance to the next node */
+ free_list = tmp;
} /* end while */
+ /* Decrement the count of nodes allocated and free the node */
+ head->allocated -= head->onlist;
+
+ /* Decrement global count of free memory on "regular" lists */
+ H5FL_reg_gc_head.mem_freed -= (head->onlist * head->size);
+
/* Indicate no free nodes on the free list */
head->list = NULL;
head->onlist = 0;
- /* Decrement global count of free memory on "regular" lists */
- H5FL_reg_gc_head.mem_freed -= total_mem;
-
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FL__reg_gc_list() */
@@ -568,10 +563,6 @@ H5FL__reg_gc_list(H5FL_reg_head_t *head)
* Programmer: Quincey Koziol
* Friday, March 24, 2000
*
- * Modifications:
- * Broke into two parts, one for looping over all the free lists and
- * another for freeing each list - QAK 7/25/00
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -670,7 +661,7 @@ HDprintf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_reg_gc_head.f
/*-------------------------------------------------------------------------
- * Function: H5FL_blk_find_list
+ * Function: H5FL__blk_find_list
*
* Purpose: Finds the free list for blocks of a given size. Also moves that
* free list node to the head of the priority queue (if it isn't there
@@ -684,16 +675,14 @@ HDprintf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_reg_gc_head.f
* Programmer: Quincey Koziol
* Thursday, March 23, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static H5FL_blk_node_t *
-H5FL_blk_find_list(H5FL_blk_node_t **head, size_t size)
+H5FL__blk_find_list(H5FL_blk_node_t **head, size_t size)
{
H5FL_blk_node_t *temp = NULL; /* Temp. pointer to node in the native list */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Find the correct free list */
temp=*head;
@@ -729,11 +718,11 @@ H5FL_blk_find_list(H5FL_blk_node_t **head, size_t size)
} /* end if */
FUNC_LEAVE_NOAPI(temp)
-} /* end H5FL_blk_find_list() */
+} /* end H5FL__blk_find_list() */
/*-------------------------------------------------------------------------
- * Function: H5FL_blk_create_list
+ * Function: H5FL__blk_create_list
*
* Purpose: Creates a new free list for blocks of the given size at the
* head of the priority queue.
@@ -745,47 +734,38 @@ H5FL_blk_find_list(H5FL_blk_node_t **head, size_t size)
* Programmer: Quincey Koziol
* Thursday, March 23, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static H5FL_blk_node_t *
-H5FL_blk_create_list(H5FL_blk_node_t **head, size_t size)
+H5FL__blk_create_list(H5FL_blk_node_t **head, size_t size)
{
- H5FL_blk_node_t *temp; /* Temp. pointer to node in the list */
H5FL_blk_node_t *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Allocate room for the new free list node */
- if(NULL==(temp=H5FL_MALLOC(H5FL_blk_node_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for chunk info")
+ if(NULL == (ret_value = H5FL_CALLOC(H5FL_blk_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "memory allocation failed for chunk info")
/* Set the correct values for the new free list */
- temp->size=size;
- temp->list=NULL;
+ ret_value->size = size;
/* Attach to head of priority queue */
- if(*head==NULL) {
- *head=temp;
- temp->next=temp->prev=NULL;
- } /* end if */
+ if(NULL == *head)
+ *head = ret_value;
else {
- temp->next=*head;
- (*head)->prev=temp;
- temp->prev=NULL;
- *head=temp;
+ ret_value->next = *head;
+ (*head)->prev = ret_value;
+ *head = ret_value;
} /* end else */
- ret_value=temp;
-
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FL_blk_create_list() */
+} /* end H5FL__blk_create_list() */
/*-------------------------------------------------------------------------
- * Function: H5FL_blk_init
+ * Function: H5FL__blk_init
*
* Purpose: Initialize a priority queue of a certain type. Right now, this just
* adds the PQ to the list of things to garbage collect.
@@ -796,17 +776,15 @@ done:
* Programmer: Quincey Koziol
* Saturday, March 25, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FL_blk_init(H5FL_blk_head_t *head)
+H5FL__blk_init(H5FL_blk_head_t *head)
{
H5FL_blk_gc_node_t *new_node; /* Pointer to the node for the new list to garbage collect */
herr_t ret_value=SUCCEED; /* return value*/
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Allocate a new garbage collection node */
if(NULL == (new_node = (H5FL_blk_gc_node_t *)H5MM_malloc(sizeof(H5FL_blk_gc_node_t))))
@@ -824,7 +802,7 @@ H5FL_blk_init(H5FL_blk_head_t *head)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FL_blk_init() */
+} /* end H5FL__blk_init() */
/*-------------------------------------------------------------------------
@@ -839,8 +817,6 @@ done:
* Programmer: Quincey Koziol
* Monday, December 16, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
htri_t
@@ -856,10 +832,11 @@ H5FL_blk_free_block_avail(H5FL_blk_head_t *head, size_t size)
/* check if there is a free list for blocks of this size */
/* and if there are any blocks available on the list */
- if((free_list = H5FL_blk_find_list(&(head->head), size)) != NULL && free_list->list != NULL)
+ if((free_list = H5FL__blk_find_list(&(head->head), size)) != NULL && free_list->list != NULL)
ret_value = TRUE;
else
ret_value = FALSE;
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FL_blk_free_block_avail() */
@@ -878,8 +855,6 @@ H5FL_blk_free_block_avail(H5FL_blk_head_t *head, size_t size)
* Programmer: Quincey Koziol
* Thursday, March 23, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -897,31 +872,40 @@ H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS)
/* Make certain the list is initialized first */
if(!head->init)
- if(H5FL_blk_init(head)<0)
+ if(H5FL__blk_init(head) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't initialize 'block' list")
/* check if there is a free list for blocks of this size */
/* and if there are any blocks available on the list */
- if((free_list=H5FL_blk_find_list(&(head->head),size))!=NULL && free_list->list!=NULL) {
+ if(NULL != (free_list = H5FL__blk_find_list(&(head->head), size)) && NULL != free_list->list) {
/* Remove the first node from the free list */
temp=free_list->list;
free_list->list=free_list->list->next;
/* Decrement the number of blocks & memory used on free list */
+ free_list->onlist--;
head->onlist--;
head->list_mem-=size;
/* Decrement the amount of global "block" free list memory in use */
H5FL_blk_gc_head.mem_freed-=size;
-
} /* end if */
/* No free list available, or there are no nodes on the list, allocate a new node to give to the user */
else {
+ /* Check if there was no free list for native blocks of this size */
+ if(NULL == free_list)
+ /* Create a new list node and insert it to the queue */
+ free_list = H5FL__blk_create_list(&(head->head), size);
+ HDassert(free_list);
+
/* Allocate new node, with room for the page info header and the actual page data */
- if(NULL == (temp = (H5FL_blk_list_t *)H5FL_malloc(sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE + size)))
+ if(NULL == (temp = (H5FL_blk_list_t *)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 */
+ /* Increment the number of blocks of this size */
+ free_list->allocated++;
+
+ /* Increment the total number of blocks allocated */
head->allocated++;
} /* end else */
@@ -970,8 +954,6 @@ done:
* Programmer: Quincey Koziol
* Monday, December 23, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1011,8 +993,6 @@ done:
* Programmer: Quincey Koziol
* Thursday, March 23, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1055,7 +1035,7 @@ H5FL_blk_free(H5FL_blk_head_t *head, void *block)
#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 */
+ temp = (H5FL_blk_list_t *)((void *)((unsigned char *)block - (sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE))); /*lint !e826 Pointer-to-pointer cast is appropriate here */
/* Save the block's size for later */
free_size=temp->size;
@@ -1064,20 +1044,18 @@ H5FL_blk_free(H5FL_blk_head_t *head, void *block)
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),free_size))==NULL) {
+ /* Check if there is a free list for native blocks of this size */
+ if(NULL == (free_list = H5FL__blk_find_list(&(head->head), free_size)))
/* No free list available, create a new list node and insert it to the queue */
- free_list=H5FL_blk_create_list(&(head->head),free_size);
- HDassert(free_list);
- } /* end if */
+ free_list = H5FL__blk_create_list(&(head->head), free_size);
+ HDassert(free_list);
/* Prepend the free'd native block to the front of the free list */
- if(free_list!=NULL) {
- temp->next=free_list->list; /* Overwrites the size field in union */
- free_list->list=temp;
- } /* end if */
+ temp->next = free_list->list; /* Note: Overwrites the size field in union */
+ free_list->list = temp;
/* Increment the number of blocks on free list */
+ free_list->onlist++;
head->onlist++;
head->list_mem += free_size;
@@ -1113,8 +1091,6 @@ done:
* Programmer: Quincey Koziol
* Thursday, March 23, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1133,7 +1109,7 @@ H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size H5FL_TRACK_
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) + H5FL_TRACK_SIZE)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
+ temp = (H5FL_blk_list_t *)((void *)((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) {
@@ -1191,44 +1167,70 @@ done:
static herr_t
H5FL__blk_gc_list(H5FL_blk_head_t *head)
{
+ H5FL_blk_node_t *blk_head; /* Temp. ptr to the free list page node */
+
FUNC_ENTER_STATIC_NOERR
/* Loop through all the nodes in the block free list queue */
- while(head->head != NULL) {
- H5FL_blk_list_t *list; /* The free list of native nodes of a particular size */
- void *temp; /* Temp. ptr to the free list page node */
+ blk_head = head->head;
+ while(blk_head != NULL) {
+ H5FL_blk_node_t *blk_next; /* Temp. ptr to the next free list node */
+ H5FL_blk_list_t *list; /* The free list of native nodes of a particular size */
- temp = head->head->next;
+ /* Sanity check */
+ HDassert((blk_head->onlist && blk_head->list) || (0 == blk_head->onlist && NULL == blk_head->list));
/* Loop through all the blocks in the free list, freeing them */
- list = head->head->list;
+ list = blk_head->list;
while(list != NULL) {
- void *next; /* Temp. ptr to the free list list node */
+ H5FL_blk_list_t *next; /* Temp. ptr to the free list list node */
+ /* Get the pointer to the next node */
next = list->next;
- /* Decrement the number of blocks & memory allocated from this PQ */
- head->allocated--;
- head->list_mem -= head->head->size;
-
- /* Decrement global count of free memory on "block" lists */
- H5FL_blk_gc_head.mem_freed -= head->head->size;
-
/* Free the block */
H5MM_free(list);
- list = (H5FL_blk_list_t *)next;
+ /* Advance to the next node */
+ list = next;
} /* end while */
- /* Free the free list node */
- head->head = H5FL_FREE(H5FL_blk_node_t, head->head);
+ /* Decrement the number of blocks allocated from this list */
+ blk_head->allocated -= blk_head->onlist;
+ head->allocated -= blk_head->onlist;
+
+ /* Decrement count of free memory on this "block" list */
+ head->list_mem -= (blk_head->onlist * blk_head->size);
+
+ /* Decrement global count of free memory on "block" lists */
+ H5FL_blk_gc_head.mem_freed -= (blk_head->onlist * blk_head->size);
+
+ /* Indicate no free nodes on the free list */
+ blk_head->list = NULL;
+ blk_head->onlist = 0;
- /* Advance to the next free list */
- head->head = (H5FL_blk_node_t *)temp;
+ /* Get pointer to next node */
+ blk_next = blk_head->next;
+
+ /* Check for list completely unused now */
+ if(0 == blk_head->allocated) {
+ /* Patch this node out of the PQ */
+ if(head->head == blk_head)
+ head->head = blk_head->next;
+ if(blk_head->prev)
+ blk_head->prev->next = blk_head->next;
+ if(blk_head->next)
+ blk_head->next->prev = blk_head->prev;
+
+ /* Free the free list node */
+ H5FL_FREE(H5FL_blk_node_t, blk_head);
+ } /* end if */
+
+ /* Advance to the next node */
+ blk_head = blk_next;
} /* end while */
/* Indicate no free nodes on the free list */
- head->head = NULL;
head->onlist = 0;
/* Double check that all the memory on this list is recycled */
@@ -1257,7 +1259,7 @@ H5FL__blk_gc(void)
H5FL_blk_gc_node_t *gc_node; /* Pointer into the list of things to garbage collect */
herr_t ret_value = SUCCEED; /* return value*/
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Walk through all the free lists, free()'ing the nodes */
gc_node = H5FL_blk_gc_head.first;
@@ -1341,7 +1343,7 @@ HDprintf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_blk_gc_head.f
/*-------------------------------------------------------------------------
- * Function: H5FL_arr_init
+ * Function: H5FL__arr_init
*
* Purpose: Initialize a free list for a arrays of certain type. Right now,
* this just adds the free list to the list of things to garbage collect.
@@ -1352,18 +1354,16 @@ HDprintf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_blk_gc_head.f
* Programmer: Quincey Koziol
* Saturday, March 25, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FL_arr_init(H5FL_arr_head_t *head)
+H5FL__arr_init(H5FL_arr_head_t *head)
{
H5FL_gc_arr_node_t *new_node; /* Pointer to the node for the new list to garbage collect */
size_t u; /* Local index variable */
herr_t ret_value=SUCCEED; /* return value*/
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Allocate a new garbage collection node */
if(NULL == (new_node = (H5FL_gc_arr_node_t *)H5MM_malloc(sizeof(H5FL_gc_arr_node_t))))
@@ -1389,7 +1389,7 @@ H5FL_arr_init(H5FL_arr_head_t *head)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FL_arr_init() */
+} /* end H5FL__arr_init() */
/*-------------------------------------------------------------------------
@@ -1403,8 +1403,6 @@ done:
* Programmer: Quincey Koziol
* Friday, March 24, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1430,7 +1428,7 @@ H5FL_arr_free(H5FL_arr_head_t *head, void *obj)
HDassert(head->init);
/* Get the pointer to the info header in front of the block to free */
- temp=(H5FL_arr_list_t *)((unsigned char *)obj-sizeof(H5FL_arr_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
+ temp = (H5FL_arr_list_t *)((void *)((unsigned char *)obj - sizeof(H5FL_arr_list_t))); /*lint !e826 Pointer-to-pointer cast is appropriate here */
/* Get the number of elements */
free_nelem=temp->nelem;
@@ -1481,8 +1479,6 @@ done:
* Programmer: Quincey Koziol
* Saturday, March 25, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1500,7 +1496,7 @@ H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem)
/* Make certain the list is initialized first */
if(!head->init)
- if(H5FL_arr_init(head)<0)
+ if(H5FL__arr_init(head) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't initialize 'array' blocks")
/* Sanity check that the number of elements is supported */
@@ -1527,10 +1523,13 @@ H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem)
} /* end if */
/* Otherwise allocate a node */
else {
- if(NULL == (new_obj = (H5FL_arr_list_t *)H5FL_malloc(sizeof(H5FL_arr_list_t)+mem_size)))
+ if(NULL == (new_obj = (H5FL_arr_list_t *)H5FL__malloc(sizeof(H5FL_arr_list_t)+mem_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Increment the number of blocks allocated in list */
+ /* Increment the number of blocks of this size */
+ head->list_arr[elem].allocated++;
+
+ /* Increment the number of blocks allocated in list, of all sizes */
head->allocated++;
} /* end else */
@@ -1556,8 +1555,6 @@ done:
* Programmer: Quincey Koziol
* Monday, December 23, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1594,8 +1591,6 @@ done:
* Programmer: Quincey Koziol
* Saturday, March 25, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1619,7 +1614,7 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void * obj, size_t new_elem)
HDassert((int)new_elem <= head->maxelem);
/* Get the pointer to the info header in front of the block to free */
- temp = (H5FL_arr_list_t *)((unsigned char *)obj - sizeof(H5FL_arr_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
+ temp = (H5FL_arr_list_t *)((void *)((unsigned char *)obj - sizeof(H5FL_arr_list_t))); /*lint !e826 Pointer-to-pointer cast is appropriate here */
/* Check if the size is really changing */
if(temp->nelem != new_elem) {
@@ -1667,34 +1662,35 @@ H5FL__arr_gc_list(H5FL_arr_head_t *head)
for(u = 0; u < (unsigned)head->maxelem; u++) {
if(head->list_arr[u].onlist > 0) {
H5FL_arr_list_t *arr_free_list; /* Pointer to nodes in free list being garbage collected */
- size_t total_mem; /* Total memory used on list */
-
- /* Calculate the total memory used on this list */
- total_mem = head->list_arr[u].onlist * head->list_arr[u].size;
/* For each free list being garbage collected, walk through the nodes and free them */
arr_free_list = head->list_arr[u].list;
while(arr_free_list != NULL) {
- void *tmp; /* Temporary node pointer */
+ H5FL_arr_list_t *tmp; /* Temporary node pointer */
+ /* Get the pointer to the next node */
tmp = arr_free_list->next;
- /* Decrement the count of nodes allocated and free the node */
- head->allocated--;
+ /* Free the node */
H5MM_free(arr_free_list);
- arr_free_list = (H5FL_arr_list_t *)tmp;
+ /* Advance to the next node */
+ arr_free_list = tmp;
} /* end while */
- /* Indicate no free nodes on the free list */
- head->list_arr[u].list = NULL;
- head->list_arr[u].onlist = 0;
+ /* Decrement the count of nodes allocated */
+ head->list_arr[u].allocated -= head->list_arr[u].onlist;
+ head->allocated -= head->list_arr[u].onlist;
/* Decrement count of free memory on this "array" list */
- head->list_mem -= total_mem;
+ head->list_mem -= (head->list_arr[u].onlist * head->list_arr[u].size);
/* Decrement global count of free memory on "array" lists */
- H5FL_arr_gc_head.mem_freed -= total_mem;
+ H5FL_arr_gc_head.mem_freed -= (head->list_arr[u].onlist * head->list_arr[u].size);
+
+ /* Indicate no free nodes on the free list */
+ head->list_arr[u].list = NULL;
+ head->list_arr[u].onlist = 0;
} /* end if */
} /* end for */
@@ -1820,8 +1816,6 @@ HDprintf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_arr_gc_head.f
* Programmer: Quincey Koziol
* Saturday, April 3, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1856,8 +1850,6 @@ H5FL_seq_free(H5FL_seq_head_t *head, void *obj)
* Programmer: Quincey Koziol
* Saturday, April 3, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1889,8 +1881,6 @@ H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS)
* Programmer: Quincey Koziol
* Saturday, April 3, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1922,8 +1912,6 @@ H5FL_seq_calloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS)
* Programmer: Quincey Koziol
* Saturday, April 3, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -1955,11 +1943,6 @@ H5FL_seq_realloc(H5FL_seq_head_t *head, void * obj, size_t new_elem H5FL_TRACK_P
* Programmer: Quincey Koziol
* Wednesday, February 2, 2005
*
- * Modifications:
- * Neil Fortner
- * Friday, December 19, 2008
- * Totally rewritten to support new factory implementation
- *
*-------------------------------------------------------------------------
*/
H5FL_fac_head_t *
@@ -2032,11 +2015,6 @@ done:
* Programmer: Quincey Koziol
* Wednesday, February 2, 2005
*
- * Modifications:
- * Neil Fortner
- * Friday, December 19, 2008
- * Totally rewritten to support new factory implementation
- *
*-------------------------------------------------------------------------
*/
void *
@@ -2120,11 +2098,6 @@ done:
* Programmer: Quincey Koziol
* Wednesday, February 2, 2005
*
- * Modifications:
- * Neil Fortner
- * Friday, December 19, 2008
- * Totally rewritten to support new factory implementation
- *
*-------------------------------------------------------------------------
*/
void *
@@ -2155,7 +2128,7 @@ H5FL_fac_malloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS)
} /* end if */
/* Otherwise allocate a node */
else {
- if (NULL==(ret_value = H5FL_malloc(head->size)))
+ if(NULL == (ret_value = H5FL__malloc(head->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Increment the number of blocks allocated in list */
@@ -2197,11 +2170,6 @@ done:
* Programmer: Quincey Koziol
* Wednesday, February 2, 2005
*
- * Modifications:
- * Neil Fortner
- * Friday, December 19, 2008
- * Totally rewritten to support new factory implementation
- *
*-------------------------------------------------------------------------
*/
void *
@@ -2245,35 +2213,34 @@ static herr_t
H5FL__fac_gc_list(H5FL_fac_head_t *head)
{
H5FL_fac_node_t *free_list; /* Pointer to nodes in free list being garbage collected */
- size_t total_mem; /* Total memory used on list */
FUNC_ENTER_STATIC_NOERR
- /* Calculate the total memory used on this list */
- total_mem = head->onlist * head->size;
-
/* For each free list being garbage collected, walk through the nodes and free them */
free_list = head->list;
while(free_list != NULL) {
- void *tmp; /* Temporary node pointer */
+ H5FL_fac_node_t *tmp; /* Temporary node pointer */
+ /* Get the pointer to the next node */
tmp = free_list->next;
- /* Decrement the count of nodes allocated and free the node */
- head->allocated--;
-
+ /* Free the block */
H5MM_free(free_list);
- free_list = (H5FL_fac_node_t *)tmp;
+ /* Advance to the next node */
+ free_list = tmp;
} /* end while */
+ /* Decrement the count of nodes allocated and free the node */
+ head->allocated -= head->onlist;
+
+ /* Decrement global count of free memory on "factory" lists */
+ H5FL_fac_gc_head.mem_freed -= (head->onlist * head->size);
+
/* Indicate no free nodes on the free list */
head->list = NULL;
head->onlist = 0;
- /* Decrement global count of free memory on "factory" lists */
- H5FL_fac_gc_head.mem_freed -= total_mem;
-
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FL__fac_gc_list() */
@@ -2329,11 +2296,6 @@ done:
* Programmer: Quincey Koziol
* Wednesday, February 2, 2005
*
- * Modifications:
- * Neil Fortner
- * Friday, December 19, 2008
- * Totally rewritten to support new factory implementation
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -2438,8 +2400,6 @@ HDprintf("%s: head->size = %d, head->allocated = %d\n", FUNC, (int)H5FL_fac_gc_h
* Programmer: Quincey Koziol
* Friday, March 24, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -2495,10 +2455,6 @@ done:
* Programmer: Quincey Koziol
* Wednesday, August 2, 2000
*
- * Modifications: Neil Fortner
- * Wednesday, April 8, 2009
- * Added support for factory free lists
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -2531,3 +2487,127 @@ H5FL_set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_l
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FL_set_free_list_limits() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FL_get_free_list_sizes
+ *
+ * Purpose: Gets the current size of the different kinds of free lists.
+ * These lists are global for the entire library. The size returned
+ * included nodes that are freed and awaiting garbage collection /
+ * reallocation.
+ *
+ * Parameters:
+ * size_t *reg_size; OUT: The current size of all "regular" free list memory used
+ * size_t *arr_size; OUT: The current size of all "array" free list memory used
+ * size_t *blk_size; OUT: The current size of all "block" free list memory used
+ * size_t *fac_size; OUT: The current size of all "factory" free list memory used
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, March 6, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FL_get_free_list_sizes(size_t *reg_size, size_t *arr_size, size_t *blk_size,
+ size_t *fac_size)
+{
+ FUNC_ENTER_NOAPI_NOERR
+
+ /* Retrieve the amount of "regular" memory used */
+ if(reg_size) {
+ H5FL_reg_gc_node_t *gc_node; /* Pointer into the list of lists */
+
+ /* Walk through all the free lists, counting the amount of memory */
+ *reg_size = 0;
+ gc_node = H5FL_reg_gc_head.first;
+ while(gc_node != NULL) {
+ H5FL_reg_head_t *reg_list = gc_node->list; /* Head of list */
+
+ /* Sanity check */
+ HDassert(reg_list->init);
+
+ /* Add the amount of memory for this list */
+ *reg_size += (reg_list->size * reg_list->allocated);
+
+ /* Go on to the next free list */
+ gc_node = gc_node->next;
+ } /* end while */
+ } /* end if */
+
+ /* Retrieve the amount of "array" memory used */
+ if(arr_size) {
+ H5FL_gc_arr_node_t *gc_arr_node; /* Pointer into the list of things to garbage collect */
+
+ /* Walk through all the free lists, counting the amount of memory */
+ *arr_size = 0;
+ gc_arr_node = H5FL_arr_gc_head.first;
+ while(gc_arr_node != NULL) {
+ H5FL_arr_head_t *head = gc_arr_node->list; /* Head of array list elements */
+
+ /* Sanity check */
+ HDassert(head->init);
+
+ /* Check for any allocated elements in this list */
+ if(head->allocated > 0) {
+ unsigned u;
+
+ /* Walk through the free lists for array sizes */
+ for(u = 0; u < (unsigned)head->maxelem; u++)
+ /* Add the amount of memory for this size */
+ *arr_size += head->list_arr[u].allocated * head->list_arr[u].size;
+ } /* end if */
+
+ /* Go on to the next free list */
+ gc_arr_node = gc_arr_node->next;
+ } /* end while */
+ } /* end if */
+
+ /* Retrieve the amount of "block" memory used */
+ if(blk_size) {
+ H5FL_blk_gc_node_t *gc_blk_node; /* Pointer into the list of things */
+
+ /* Walk through all the free lists */
+ gc_blk_node = H5FL_blk_gc_head.first;
+ *blk_size = 0;
+ while(gc_blk_node != NULL) {
+ H5FL_blk_node_t *blk_head; /* Temp. ptr to the free list block node */
+
+ /* Loop through all the nodes in the block free list queue */
+ blk_head = gc_blk_node->pq->head;
+ while(blk_head != NULL) {
+ /* Add size of blocks on this list */
+ *blk_size += (blk_head->allocated * blk_head->size);
+
+ /* Get pointer to next node */
+ blk_head = blk_head->next;
+ } /* end while */
+
+ /* Go on to the next free list */
+ gc_blk_node = gc_blk_node->next;
+ } /* end while */
+ } /* end if */
+
+ /* Retrieve the amount of "factory" memory used */
+ if(fac_size) {
+ H5FL_fac_gc_node_t *gc_fac_node; /* Pointer into the list of things to garbage collect */
+
+ /* Walk through all the free lists */
+ gc_fac_node = H5FL_fac_gc_head.first;
+ *fac_size = 0;
+ while(gc_fac_node != NULL) {
+ H5FL_fac_head_t *fac_head = gc_fac_node->list; /* Head node for factory list */
+
+ /* Add size of blocks on this list */
+ *fac_size += (fac_head->allocated * fac_head->size);
+
+ /* Go on to the next free list to garbage collect */
+ gc_fac_node = gc_fac_node->next;
+ } /* end while */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FL_get_free_list_sizes() */
+
diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h
index 4aa44f9..94a51e5 100644
--- a/src/H5FLprivate.h
+++ b/src/H5FLprivate.h
@@ -157,6 +157,8 @@ typedef union H5FL_blk_list_t {
/* Data structure for priority queue node of block free lists */
typedef struct H5FL_blk_node_t {
size_t size; /* Size of the blocks in the list */
+ unsigned allocated; /* Number of blocks of this size allocated */
+ unsigned onlist; /* Number of blocks on free list */
H5FL_blk_list_t *list; /* List of free blocks */
struct H5FL_blk_node_t *next; /* Pointer to next free list in queue */
struct H5FL_blk_node_t *prev; /* Pointer to previous free list in queue */
@@ -165,9 +167,9 @@ typedef struct H5FL_blk_node_t {
/* Data structure for priority queue of native block free lists */
typedef struct H5FL_blk_head_t {
hbool_t 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 in block on free list */
+ unsigned allocated; /* Total number of blocks allocated */
+ unsigned onlist; /* Total number of blocks on free list */
+ size_t list_mem; /* Total amount of memory in blocks on free list */
const char *name; /* Name of the type */
H5FL_blk_node_t *head; /* Pointer to first free list in queue */
} H5FL_blk_head_t;
@@ -189,10 +191,10 @@ typedef struct H5FL_blk_head_t {
/* Declare a static free list to manage objects of type 't' */
#define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE_COMMON(t)
-/* Allocate an block of type 't' */
+/* Allocate a block of type 't' */
#define H5FL_BLK_MALLOC(t,size) (uint8_t *)H5FL_blk_malloc(&(H5FL_BLK_NAME(t)),size H5FL_TRACK_INFO)
-/* Allocate an block of type 't' and clear it to zeros */
+/* Allocate a block of type 't' and clear it to zeros */
#define H5FL_BLK_CALLOC(t,size) (uint8_t *)H5FL_blk_calloc(&(H5FL_BLK_NAME(t)),size H5FL_TRACK_INFO)
/* Free a block of type 't' */
@@ -228,7 +230,9 @@ typedef union H5FL_arr_list_t {
/* Data structure for each size of array element */
typedef struct H5FL_arr_node_t {
- size_t size; /* Size of the blocks in the list */
+ size_t size; /* Size of the blocks in the list (in bytes) */
+ /* (Note: base_size + <# of elem> * elem_size) */
+ unsigned allocated; /* Number of blocks allocated of this element size */
unsigned onlist; /* Number of blocks on free list */
H5FL_arr_list_t *list; /* List of free blocks */
} H5FL_arr_node_t;
@@ -236,7 +240,7 @@ typedef struct H5FL_arr_node_t {
/* Data structure for free list of array blocks */
typedef struct H5FL_arr_head_t {
hbool_t init; /* Whether the free list has been initialized */
- unsigned allocated; /* Number of blocks allocated */
+ unsigned allocated; /* Total number of blocks allocated */
size_t list_mem; /* Amount of memory in block on free list */
const char *name; /* Name of the type */
int maxelem; /* Maximum number of elements in an array */
@@ -423,6 +427,8 @@ H5_DLL herr_t H5FL_garbage_coll(void);
H5_DLL herr_t H5FL_set_free_list_limits(int reg_global_lim, int reg_list_lim,
int arr_global_lim, int arr_list_lim, int blk_global_lim, int blk_list_lim,
int fac_global_lim, int fac_list_lim);
+H5_DLL herr_t H5FL_get_free_list_sizes(size_t *reg_size, size_t *arr_size,
+ size_t *blk_size, size_t *fac_size);
H5_DLL int H5FL_term_interface(void);
#endif
diff --git a/src/H5MM.c b/src/H5MM.c
index 7eb1023..cceac4f 100644
--- a/src/H5MM.c
+++ b/src/H5MM.c
@@ -154,7 +154,7 @@ H5MM__is_our_block(void *mem)
*
*-------------------------------------------------------------------------
*/
-H5_ATTR_PURE static void
+static void
H5MM__sanity_check_block(const H5MM_block_t *block)
{
HDassert(block->u.info.size > 0);
@@ -180,7 +180,7 @@ H5MM__sanity_check_block(const H5MM_block_t *block)
*
*-------------------------------------------------------------------------
*/
-H5_ATTR_PURE static void
+static void
H5MM__sanity_check(void *mem)
{
H5MM_block_t *block = H5MM_BLOCK_FROM_BUF(mem);
@@ -201,7 +201,7 @@ H5MM__sanity_check(void *mem)
*
*-------------------------------------------------------------------------
*/
-H5_ATTR_PURE void
+void
H5MM_sanity_check_all(void)
{
H5MM_block_t *curr = NULL;
@@ -226,7 +226,7 @@ H5MM_sanity_check_all(void)
*
*-------------------------------------------------------------------------
*/
-H5_ATTR_PURE void
+void
H5MM_final_sanity_check(void)
{
HDassert(0 == H5MM_curr_alloc_bytes_s);
@@ -235,7 +235,7 @@ H5MM_final_sanity_check(void)
HDassert(H5MM_block_head_s.prev == &H5MM_block_head_s);
#ifdef H5MM_PRINT_MEMORY_STATS
HDfprintf(stderr, "%s: H5MM_total_alloc_bytes_s = %llu\n", __func__, H5MM_total_alloc_bytes_s);
- HDfprintf(stderr, "%s: H5MM_peak_alloc_bytes_s = %llu\n", __func__, H5MM_peak_alloc_bytes_s);
+ HDfprintf(stderr, "%s: H5MM_peak_alloc_bytes_s = %zu\n", __func__, H5MM_peak_alloc_bytes_s);
HDfprintf(stderr, "%s: H5MM_max_block_size_s = %zu\n", __func__, H5MM_max_block_size_s);
HDfprintf(stderr, "%s: H5MM_total_alloc_blocks_count_s = %zu\n", __func__, H5MM_total_alloc_blocks_count_s);
HDfprintf(stderr, "%s: H5MM_peak_alloc_blocks_count_s = %zu\n", __func__, H5MM_peak_alloc_blocks_count_s);
@@ -625,4 +625,46 @@ H5MM_memcpy(void *dest, const void *src, size_t n)
} /* end H5MM_memcpy() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5MM_get_alloc_stats
+ *
+ * Purpose: Gets the memory allocation statistics for the library, if the
+ * H5_MEMORY_ALLOC_SANITY_CHECK macro is defined. If the macro is not
+ * defined, zeros are returned. These statistics are global for the
+ * entire library.
+ *
+ * Parameters:
+ * H5_alloc_stats_t *stats; OUT: Memory allocation statistics
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, March 7, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MM_get_alloc_stats(H5_alloc_stats_t *stats)
+{
+ FUNC_ENTER_NOAPI_NOERR
+
+#if defined H5_MEMORY_ALLOC_SANITY_CHECK
+ if(stats) {
+ stats->total_alloc_bytes = H5MM_total_alloc_bytes_s;
+ stats->curr_alloc_bytes = H5MM_curr_alloc_bytes_s;
+ stats->peak_alloc_bytes = H5MM_peak_alloc_bytes_s;
+ stats->max_block_size = H5MM_max_block_size_s;
+ stats->total_alloc_blocks_count = H5MM_total_alloc_blocks_count_s;
+ stats->curr_alloc_blocks_count = H5MM_curr_alloc_blocks_count_s;
+ stats->peak_alloc_blocks_count = H5MM_peak_alloc_blocks_count_s;
+ } /* end if */
+#else /* H5_MEMORY_ALLOC_SANITY_CHECK */
+ if(stats)
+ HDmemset(stats, 0, sizeof(H5_alloc_stats_t));
+#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5MM_get_alloc_stats() */
diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h
index 240b931..0787eb2 100644
--- a/src/H5MMprivate.h
+++ b/src/H5MMprivate.h
@@ -47,6 +47,7 @@ H5_DLL char *H5MM_strdup(const char *s);
H5_DLL void *H5MM_xfree(void *mem);
H5_DLL void *H5MM_xfree_const(const void *mem);
H5_DLL void *H5MM_memcpy(void *dest, const void *src, size_t n);
+H5_DLL herr_t H5MM_get_alloc_stats(H5_alloc_stats_t *stats);
#if defined H5_MEMORY_ALLOC_SANITY_CHECK
H5_DLL void H5MM_sanity_check_all(void);
H5_DLL void H5MM_final_sanity_check(void);
diff --git a/src/H5private.h b/src/H5private.h
index c628fcf..5b1c4db 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -1951,12 +1951,11 @@ H5_DLL double H5_trace(const double *calltime, const char *func, const char *typ
/* global library version information string */
extern char H5_lib_vers_info_g[];
+#include "H5TSprivate.h"
+
/* Lock headers */
#ifdef H5_HAVE_THREADSAFE
-/* Include required thread-safety header */
-#include "H5TSprivate.h"
-
/* replacement structure for original global variable */
typedef struct H5_api_struct {
H5TS_mutex_t init_lock; /* API entrance mutex */
diff --git a/src/H5public.h b/src/H5public.h
index fe4e33c..871c360 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -328,6 +328,19 @@ typedef struct H5_ih_info_t {
hsize_t heap_size;
} H5_ih_info_t;
+/*
+ * Allocation statistics info struct
+ */
+typedef struct H5_alloc_stats_t {
+ unsigned long long total_alloc_bytes; /* Running count of total # of bytes allocated */
+ size_t curr_alloc_bytes; /* Current # of bytes allocated */
+ size_t peak_alloc_bytes; /* Peak # of bytes allocated */
+ size_t max_block_size; /* Largest block allocated */
+ size_t total_alloc_blocks_count; /* Running count of total # of blocks allocated */
+ size_t curr_alloc_blocks_count; /* Current # of blocks allocated */
+ size_t peak_alloc_blocks_count; /* Peak # of blocks allocated */
+} H5_alloc_stats_t;
+
/* Functions in H5.c */
H5_DLL herr_t H5open(void);
H5_DLL herr_t H5close(void);
@@ -336,6 +349,9 @@ H5_DLL herr_t H5garbage_collect(void);
H5_DLL herr_t H5set_free_list_limits (int reg_global_lim, int reg_list_lim,
int arr_global_lim, int arr_list_lim, int blk_global_lim,
int blk_list_lim);
+H5_DLL herr_t H5get_free_list_sizes(size_t *reg_size, size_t *arr_size,
+ size_t *blk_size, size_t *fac_size);
+H5_DLL herr_t H5get_alloc_stats(H5_alloc_stats_t *stats);
H5_DLL herr_t H5get_libversion(unsigned *majnum, unsigned *minnum,
unsigned *relnum);
H5_DLL herr_t H5check_version(unsigned majnum, unsigned minnum,