diff options
Diffstat (limited to 'src/H5MM.c')
-rw-r--r-- | src/H5MM.c | 408 |
1 files changed, 7 insertions, 401 deletions
@@ -13,8 +13,6 @@ /*------------------------------------------------------------------------- * * Created: H5MM.c - * Jul 10 1997 - * Robb Matzke * * Purpose: Memory management functions * @@ -35,45 +33,14 @@ /****************/ /* Local Macros */ /****************/ -#if defined H5_MEMORY_ALLOC_SANITY_CHECK -#define H5MM_SIG_SIZE 4 -#define H5MM_HEAD_GUARD_SIZE 8 -#define H5MM_TAIL_GUARD_SIZE 8 -#define H5MM_BLOCK_FROM_BUF(mem) \ - ((H5MM_block_t *)((void *)((unsigned char *)mem - (offsetof(H5MM_block_t, b) + H5MM_HEAD_GUARD_SIZE)))) -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ /******************/ /* Local Typedefs */ /******************/ -#if defined H5_MEMORY_ALLOC_SANITY_CHECK -/* Memory allocation "block", wrapped around each allocation */ -struct H5MM_block_t; /* Forward declaration for typedef */ -typedef struct H5MM_block_t { - unsigned char - sig[H5MM_SIG_SIZE]; /* Signature for the block, to indicate it was allocated with H5MM* interface */ - struct H5MM_block_t *next; /* Pointer to next block in the list of allocated blocks */ - struct H5MM_block_t *prev; /* Pointer to previous block in the list of allocated blocks */ - union { - struct { - size_t size; /* Size of allocated block */ - hbool_t in_use; /* Whether the block is in use or is free */ - } info; - double _align; /* Align following buffer (b) to double boundary (unused) */ - } u; - unsigned char b[]; /* Buffer for caller (includes header and footer) */ -} H5MM_block_t; -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ - /********************/ /* Local Prototypes */ /********************/ -#if defined H5_MEMORY_ALLOC_SANITY_CHECK -static hbool_t H5MM__is_our_block(void *mem); -static void H5MM__sanity_check_block(const H5MM_block_t *block); -static void H5MM__sanity_check(void *mem); -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ /*********************/ /* Package Variables */ @@ -87,152 +54,6 @@ static void H5MM__sanity_check(void *mem); /* Local Variables */ /*******************/ -#if defined H5_MEMORY_ALLOC_SANITY_CHECK -/* Constant strings for block signature, head & tail guards */ -static const char H5MM_block_signature_s[H5MM_SIG_SIZE] = {'H', '5', 'M', 'M'}; -static const char H5MM_block_head_guard_s[H5MM_HEAD_GUARD_SIZE] = {'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F'}; -static const char H5MM_block_tail_guard_s[H5MM_TAIL_GUARD_SIZE] = {'B', 'E', 'E', 'F', 'D', 'E', 'A', 'D'}; - -/* Flag to indicate the the interface has been initialized */ -static hbool_t H5MM_init_s = FALSE; - -/* Head of the list of allocated blocks */ -static H5MM_block_t H5MM_block_head_s; - -/* Statistics about block allocations */ -static unsigned long long H5MM_total_alloc_bytes_s = 0; -static size_t H5MM_curr_alloc_bytes_s = 0; -static size_t H5MM_peak_alloc_bytes_s = 0; -static size_t H5MM_max_block_size_s = 0; -static size_t H5MM_total_alloc_blocks_count_s = 0; -static size_t H5MM_curr_alloc_blocks_count_s = 0; -static size_t H5MM_peak_alloc_blocks_count_s = 0; -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ - -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - -/*------------------------------------------------------------------------- - * Function: H5MM__is_our_block - * - * Purpose: Try to determine if a memory buffer has been allocated through - * the H5MM* interface, instead of the system's malloc() routines. - * - * Return: Success: TRUE/FALSE - * Failure: (Can't fail) - * - * Programmer: Quincey Koziol - * Dec 30 2015 - * - *------------------------------------------------------------------------- - */ -static hbool_t -H5MM__is_our_block(void *mem) -{ - H5MM_block_t *block = H5MM_BLOCK_FROM_BUF(mem); - - return (0 == HDmemcmp(block->sig, H5MM_block_signature_s, H5MM_SIG_SIZE)); -} - -/*------------------------------------------------------------------------- - * Function: H5MM__sanity_check_block - * - * Purpose: Check a block wrapper around a buffer to validate it. - * - * Return: N/A (void) - * - * Programmer: Quincey Koziol - * Dec 30 2015 - * - *------------------------------------------------------------------------- - */ -static void -H5MM__sanity_check_block(const H5MM_block_t *block) -{ - HDassert(block->u.info.size > 0); - HDassert(block->u.info.in_use); - /* Check for head & tail guards, if not head of linked list */ - if (block->u.info.size != SIZE_MAX) { - HDassert(0 == HDmemcmp(block->b, H5MM_block_head_guard_s, H5MM_HEAD_GUARD_SIZE)); - HDassert(0 == HDmemcmp(block->b + H5MM_HEAD_GUARD_SIZE + block->u.info.size, H5MM_block_tail_guard_s, - H5MM_TAIL_GUARD_SIZE)); - } -} - -/*------------------------------------------------------------------------- - * Function: H5MM__sanity_check - * - * Purpose: Check a buffer to validate it (just calls - * H5MM__sanity_check_block after finding block for buffer) - * - * Return: N/A (void) - * - * Programmer: Quincey Koziol - * Dec 30 2015 - * - *------------------------------------------------------------------------- - */ -static void -H5MM__sanity_check(void *mem) -{ - H5MM_block_t *block = H5MM_BLOCK_FROM_BUF(mem); - - H5MM__sanity_check_block(block); -} - -/*------------------------------------------------------------------------- - * Function: H5MM_sanity_check_all - * - * Purpose: Sanity check all current memory allocations. - * - * Return: N/A (void) - * - * Programmer: Quincey Koziol - * Jan 5 2016 - * - *------------------------------------------------------------------------- - */ -void -H5MM_sanity_check_all(void) -{ - H5MM_block_t *curr = NULL; - - curr = H5MM_block_head_s.next; - while (curr != &H5MM_block_head_s) { - H5MM__sanity_check_block(curr); - curr = curr->next; - } /* end while */ -} /* end H5MM_sanity_check_all() */ - -/*------------------------------------------------------------------------- - * Function: H5MM_final_sanity_check - * - * Purpose: Final sanity checks on memory allocation. - * - * Return: N/A (void) - * - * Programmer: Quincey Koziol - * Jan 1 2016 - * - *------------------------------------------------------------------------- - */ -void -H5MM_final_sanity_check(void) -{ - HDassert(0 == H5MM_curr_alloc_bytes_s); - HDassert(0 == H5MM_curr_alloc_blocks_count_s); - HDassert(H5MM_block_head_s.next == &H5MM_block_head_s); - 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 = %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); -#endif /* H5MM_PRINT_MEMORY_STATS */ -} -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ - /*------------------------------------------------------------------------- * Function: H5MM_malloc * @@ -246,10 +67,6 @@ H5MM_final_sanity_check(void) * * Return: Success: Pointer to new memory * Failure: NULL - * - * Programmer: Quincey Koziol - * Nov 8 2003 - * *------------------------------------------------------------------------- */ void * @@ -260,60 +77,7 @@ H5MM_malloc(size_t size) /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOERR -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - /* Initialize block list head singleton */ - if (!H5MM_init_s) { - H5MM_memcpy(H5MM_block_head_s.sig, H5MM_block_signature_s, H5MM_SIG_SIZE); - H5MM_block_head_s.next = &H5MM_block_head_s; - H5MM_block_head_s.prev = &H5MM_block_head_s; - H5MM_block_head_s.u.info.size = SIZE_MAX; - H5MM_block_head_s.u.info.in_use = TRUE; - - H5MM_init_s = TRUE; - } /* end if */ -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ - - if (size) { -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - H5MM_block_t *block; - size_t alloc_size = sizeof(H5MM_block_t) + size + H5MM_HEAD_GUARD_SIZE + H5MM_TAIL_GUARD_SIZE; - - if (NULL != (block = (H5MM_block_t *)HDmalloc(alloc_size))) { - /* Set up block */ - H5MM_memcpy(block->sig, H5MM_block_signature_s, H5MM_SIG_SIZE); - block->next = H5MM_block_head_s.next; - H5MM_block_head_s.next = block; - block->next->prev = block; - block->prev = &H5MM_block_head_s; - block->u.info.size = size; - block->u.info.in_use = TRUE; - H5MM_memcpy(block->b, H5MM_block_head_guard_s, H5MM_HEAD_GUARD_SIZE); - H5MM_memcpy(block->b + H5MM_HEAD_GUARD_SIZE + size, H5MM_block_tail_guard_s, - H5MM_TAIL_GUARD_SIZE); - - /* Update statistics */ - H5MM_total_alloc_bytes_s += size; - H5MM_curr_alloc_bytes_s += size; - if (H5MM_curr_alloc_bytes_s > H5MM_peak_alloc_bytes_s) - H5MM_peak_alloc_bytes_s = H5MM_curr_alloc_bytes_s; - if (size > H5MM_max_block_size_s) - H5MM_max_block_size_s = size; - H5MM_total_alloc_blocks_count_s++; - H5MM_curr_alloc_blocks_count_s++; - if (H5MM_curr_alloc_blocks_count_s > H5MM_peak_alloc_blocks_count_s) - H5MM_peak_alloc_blocks_count_s = H5MM_curr_alloc_blocks_count_s; - - /* Set buffer to return */ - ret_value = block->b + H5MM_HEAD_GUARD_SIZE; - } /* end if */ - else - ret_value = NULL; -#else /* H5_MEMORY_ALLOC_SANITY_CHECK */ - ret_value = HDmalloc(size); -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ - } /* end if */ - else - ret_value = NULL; + ret_value = HDmalloc(size); FUNC_LEAVE_NOAPI(ret_value) } /* end H5MM_malloc() */ @@ -330,13 +94,8 @@ H5MM_malloc(size_t size) * considered an error condition since allocations of zero * bytes usually indicate problems. * - * * Return: Success: Pointer to new memory * Failure: NULL - * - * Programmer: Quincey Koziol - * Nov 8 2003 - * *------------------------------------------------------------------------- */ void * @@ -347,16 +106,7 @@ H5MM_calloc(size_t size) /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOERR - if (size) { -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - if (NULL != (ret_value = H5MM_malloc(size))) - HDmemset(ret_value, 0, size); -#else /* H5_MEMORY_ALLOC_SANITY_CHECK */ - ret_value = HDcalloc((size_t)1, size); -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ - } /* end if */ - else - ret_value = NULL; + ret_value = HDcalloc(1, size); FUNC_LEAVE_NOAPI(ret_value) } /* end H5MM_calloc() */ @@ -377,10 +127,6 @@ H5MM_calloc(size_t size) * Return: Success: Ptr to new memory if size > 0 * NULL if size is zero * Failure: NULL (input buffer is unchanged on failure) - * - * Programmer: Robb Matzke - * Jul 10 1997 - * *------------------------------------------------------------------------- */ void * @@ -395,35 +141,12 @@ H5MM_realloc(void *mem, size_t size) /* Not defined in the standard, return NULL */ ret_value = NULL; else { -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - if (size > 0) { - if (mem) { - if (H5MM__is_our_block(mem)) { - H5MM_block_t *block = H5MM_BLOCK_FROM_BUF(mem); - size_t old_size = block->u.info.size; - - H5MM__sanity_check(mem); - - ret_value = H5MM_malloc(size); - H5MM_memcpy(ret_value, mem, MIN(size, old_size)); - H5MM_xfree(mem); - } /* end if */ - else - ret_value = HDrealloc(mem, size); - } - else - ret_value = H5MM_malloc(size); - } - else - ret_value = H5MM_xfree(mem); -#else /* H5_MEMORY_ALLOC_SANITY_CHECK */ ret_value = HDrealloc(mem, size); /* Some platforms do not return NULL if size is zero. */ if (0 == size) ret_value = NULL; -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ - } /* end else */ + } FUNC_LEAVE_NOAPI(ret_value) } /* end H5MM_realloc() */ @@ -436,9 +159,6 @@ H5MM_realloc(void *mem, size_t size) * * Return: Success: Pointer to a new string (NULL if s is NULL). * Failure: NULL - * - * Programmer: Robb Matzke - * Jul 10 1997 *------------------------------------------------------------------------- */ char * @@ -448,18 +168,9 @@ H5MM_xstrdup(const char *s) FUNC_ENTER_NOAPI(NULL) -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - if (s) { - if (NULL == (ret_value = (char *)H5MM_malloc(HDstrlen(s) + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - HDstrcpy(ret_value, s); - } -#else if (s) if (NULL == (ret_value = HDstrdup(s))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "string duplication failed") -#endif - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5MM_xstrdup() */ @@ -475,9 +186,6 @@ done: * * Return: Success: Pointer to a new string * Failure: NULL - * - * Programmer: Robb Matzke - * Jul 10 1997 *------------------------------------------------------------------------- */ char * @@ -489,14 +197,8 @@ H5MM_strdup(const char *s) if (!s) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "NULL string not allowed") -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - if (NULL == (ret_value = (char *)H5MM_malloc(HDstrlen(s) + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - HDstrcpy(ret_value, s); -#else if (NULL == (ret_value = HDstrdup(s))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "string duplication failed") -#endif done: FUNC_LEAVE_NOAPI(ret_value) @@ -521,9 +223,6 @@ done: char * H5MM_strndup(const char *s, size_t n) { -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - size_t len; -#endif char *ret_value = NULL; FUNC_ENTER_NOAPI(NULL) @@ -531,19 +230,8 @@ H5MM_strndup(const char *s, size_t n) if (!s) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "NULL string not allowed") -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - for (len = 0; len < n && s[len] != '\0'; len++) - ; - - if (NULL == (ret_value = H5MM_malloc(len + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - H5MM_memcpy(ret_value, s, len); - ret_value[len] = '\0'; -#else if (NULL == (ret_value = HDstrndup(s, n))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "string duplication failed") -#endif done: FUNC_LEAVE_NOAPI(ret_value) @@ -552,18 +240,13 @@ done: /*------------------------------------------------------------------------- * Function: H5MM_xfree * - * Purpose: Just like free(3) except null pointers are allowed as - * arguments, and the return value (always NULL) can be - * assigned to the pointer whose memory was just freed: + * Purpose: Just like free(3) except the return value (always NULL) can + * be assigned to the pointer whose memory was just freed: * - * thing = H5MM_xfree (thing); + * thing = H5MM_xfree(thing); * * Return: Success: NULL * Failure: never fails - * - * Programmer: Robb Matzke - * Jul 10 1997 - * *------------------------------------------------------------------------- */ void * @@ -572,37 +255,7 @@ H5MM_xfree(void *mem) /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOERR - if (mem) { -#if defined H5_MEMORY_ALLOC_SANITY_CHECK - if (H5MM__is_our_block(mem)) { - H5MM_block_t *block = H5MM_BLOCK_FROM_BUF(mem); - - /* Run sanity checks on this block and its neighbors */ - H5MM__sanity_check(mem); - H5MM__sanity_check_block(block->next); - H5MM__sanity_check_block(block->prev); - - /* Update statistics */ - H5MM_curr_alloc_bytes_s -= block->u.info.size; - H5MM_curr_alloc_blocks_count_s--; - - /* Reset block info */ - HDmemset(block->sig, 0, H5MM_SIG_SIZE); - block->next->prev = block->prev; - block->prev->next = block->next; - block->next = NULL; - block->prev = NULL; - block->u.info.in_use = FALSE; - - /* Free the block (finally!) */ - HDfree(block); - } - else - HDfree(mem); -#else /* H5_MEMORY_ALLOC_SANITY_CHECK */ - HDfree(mem); -#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */ - } /* end if */ + HDfree(mem); FUNC_LEAVE_NOAPI(NULL) } /* end H5MM_xfree() */ @@ -616,7 +269,6 @@ H5MM_xfree(void *mem) * * Return: Success: NULL * Failure: never fails - * *------------------------------------------------------------------------- */ void * @@ -639,10 +291,6 @@ H5MM_xfree_const(const void *mem) * * Return: Success: pointer to dest * Failure: NULL - * - * Programmer: Dana Robinson - * Spring 2019 - * *------------------------------------------------------------------------- */ void * @@ -665,45 +313,3 @@ H5MM_memcpy(void *dest, const void *src, size_t n) FUNC_LEAVE_NOAPI(ret) } /* 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() */ |