From d488bd0bba7832eaf40e2820fb5dbbc00429b209 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Mon, 15 Jul 2024 19:00:21 -0500 Subject: [PATCH] Move global variable initialization code out of H5TS header Signed-off-by: Quincey Koziol --- src/H5FL.c | 22 ++++++++++---------- src/H5FLprivate.h | 6 +++--- src/H5TSprivate.h | 49 -------------------------------------------- src/H5private.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 63 deletions(-) diff --git a/src/H5FL.c b/src/H5FL.c index caa6c3921ba..de9935a389e 100644 --- a/src/H5FL.c +++ b/src/H5FL.c @@ -437,7 +437,7 @@ H5FL_reg_free(H5FL_reg_head_t *head, void *obj) assert(obj); /* Make certain that the free list is initialized */ - assert(H5TS_IS_GLOBAL_INIT(head)); + assert(H5_GLOBAL_IS_INIT(head)); #ifdef H5_HAVE_CONCURRENCY /* Acquire the mutex protecting this list */ @@ -503,7 +503,7 @@ H5FL_reg_malloc(H5FL_reg_head_t *head) assert(head); /* Make certain the list is initialized first */ - H5TS_INIT_GLOBAL(head, H5FL__reg_init, H5E_RESOURCE, H5E_CANTINIT, NULL, + H5_GLOBAL_INIT(head, H5FL__reg_init, H5E_RESOURCE, H5E_CANTINIT, NULL, "can't initialize 'regular' blocks"); #ifdef H5_HAVE_CONCURRENCY @@ -772,7 +772,7 @@ H5FL__reg_term(void) #endif /* H5_HAVE_CONCURRENCY */ /* Reset the "initialized" flag, in case we restart this list */ - H5TS_SET_GLOBAL_INIT(H5FL_reg_gc_head.first->list, false); + H5_GLOBAL_SET_INIT(H5FL_reg_gc_head.first->list, false); /* Free the node from the garbage collection list */ H5MM_xfree(H5FL_reg_gc_head.first); @@ -1027,7 +1027,7 @@ H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size) assert(size); /* Make certain the list is initialized first */ - H5TS_INIT_GLOBAL(head, H5FL__blk_init, H5E_RESOURCE, H5E_CANTINIT, NULL, "can't initialize 'block' list"); + H5_GLOBAL_INIT(head, H5FL__blk_init, H5E_RESOURCE, H5E_CANTINIT, NULL, "can't initialize 'block' list"); #ifdef H5_HAVE_CONCURRENCY /* Acquire the mutex protecting this list */ @@ -1191,7 +1191,7 @@ H5FL_blk_free(H5FL_blk_head_t *head, void *block) free_size = temp->size; /* Make certain that the free list is initialized */ - assert(H5TS_IS_GLOBAL_INIT(head)); + assert(H5_GLOBAL_IS_INIT(head)); #ifdef H5_HAVE_CONCURRENCY /* Acquire the mutex protecting this list */ @@ -1512,7 +1512,7 @@ H5FL__blk_term(void) #endif /* H5_HAVE_CONCURRENCY */ /* Reset the "initialized" flag, in case we restart this list */ - H5TS_SET_GLOBAL_INIT(H5FL_blk_gc_head.first->pq, false); + H5_GLOBAL_SET_INIT(H5FL_blk_gc_head.first->pq, false); /* Free the node from the garbage collection list */ H5MM_free(H5FL_blk_gc_head.first); @@ -1633,7 +1633,7 @@ H5FL_arr_free(H5FL_arr_head_t *head, void *obj) assert(head); /* Make certain that the free list is initialized */ - assert(H5TS_IS_GLOBAL_INIT(head)); + assert(H5_GLOBAL_IS_INIT(head)); #ifdef H5_HAVE_CONCURRENCY /* Acquire the mutex protecting this list */ @@ -1712,7 +1712,7 @@ H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem) assert(elem); /* Make certain the list is initialized first */ - H5TS_INIT_GLOBAL(head, H5FL__arr_init, H5E_RESOURCE, H5E_CANTINIT, NULL, + H5_GLOBAL_INIT(head, H5FL__arr_init, H5E_RESOURCE, H5E_CANTINIT, NULL, "can't initialize 'array' blocks"); #ifdef H5_HAVE_CONCURRENCY @@ -2069,7 +2069,7 @@ H5FL__arr_term(void) #endif /* H5_HAVE_CONCURRENCY */ /* Reset the "initialized" flag, in case we restart this list */ - H5TS_SET_GLOBAL_INIT(H5FL_arr_gc_head.first->list, false); + H5_GLOBAL_SET_INIT(H5FL_arr_gc_head.first->list, false); /* Free the node from the garbage collection list */ H5MM_free(H5FL_arr_gc_head.first); @@ -2860,7 +2860,7 @@ H5FL_get_free_list_sizes(size_t *reg_size, size_t *arr_size, size_t *blk_size, s H5FL_reg_head_t *reg_list = gc_node->list; /* Head of list */ /* Sanity check */ - assert(H5TS_IS_GLOBAL_INIT(reg_list)); + assert(H5_GLOBAL_IS_INIT(reg_list)); /* Add the amount of memory for this list */ *reg_size += (reg_list->size * reg_list->allocated); @@ -2894,7 +2894,7 @@ H5FL_get_free_list_sizes(size_t *reg_size, size_t *arr_size, size_t *blk_size, s H5FL_arr_head_t *head = gc_arr_node->list; /* Head of array list elements */ /* Sanity check */ - assert(H5TS_IS_GLOBAL_INIT(head)); + assert(H5_GLOBAL_IS_INIT(head)); /* Check for any allocated elements in this list */ if (head->allocated > 0) { diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h index 97dace7575b..b34f0603824 100644 --- a/src/H5FLprivate.h +++ b/src/H5FLprivate.h @@ -47,7 +47,7 @@ typedef struct H5FL_reg_node_t { /* Data structure for free list of blocks */ typedef struct H5FL_reg_head_t { - H5TS_dclp_t dlcp_info; /* Information for init */ + H5_global_t dlcp_info; /* Information for init */ /* (MUST be first field in structure) */ #ifdef H5_HAVE_CONCURRENCY H5TS_dlftt_mutex_t mutex; /* Guard access to this free list */ @@ -122,7 +122,7 @@ typedef struct H5FL_blk_node_t { /* Data structure for priority queue of native block free lists */ typedef struct H5FL_blk_head_t { - H5TS_dclp_t dlcp_info; /* Information for init */ + H5_global_t dlcp_info; /* Information for init */ /* (MUST be first field in structure) */ #ifdef H5_HAVE_CONCURRENCY H5TS_dlftt_mutex_t mutex; /* Guard access to this free list */ @@ -199,7 +199,7 @@ typedef struct H5FL_arr_node_t { /* Data structure for free list of array blocks */ typedef struct H5FL_arr_head_t { - H5TS_dclp_t dlcp_info; /* Information for init */ + H5_global_t dlcp_info; /* Information for init */ /* (MUST be first field in structure) */ #ifdef H5_HAVE_CONCURRENCY H5TS_dlftt_mutex_t mutex; /* Guard access to this free list */ diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h index 96a383a0a24..222c48adbba 100644 --- a/src/H5TSprivate.h +++ b/src/H5TSprivate.h @@ -306,55 +306,6 @@ typedef struct H5TS_dlftt_mutex_t { unsigned dlftt; } H5TS_dlftt_mutex_t; -/* Mechanism for implementing Double-checked Locking Protocol (DCLP) for global - * variables with deferred initialization (i.e. not at library init time. - * FYI: https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/ - */ -typedef struct H5TS_dclp_t { - bool init; /* Whether the global has been initialized */ -} H5TS_dclp_t; - -/* Safely call an initialization routine for a global variable. This is invoked - * from a single thread while blocking other threads from using the global until - * initialization is completed. - * - * Note that this currently assumes that the global variable is a struct - * containing a field of type H5TS_dclp_t as its first field. - */ -#ifdef H5_HAVE_CONCURRENCY -#define H5TS_INIT_GLOBAL(v, f, maj, min, err_ret, ...) \ - do { \ - if (H5_UNLIKELY(!((H5TS_dclp_t *)(v))->init)) { \ - if (H5_UNLIKELY(H5TS_dlftt_mutex_acquire(&H5TS_bootstrap_mtx_g) < 0)) \ - HGOTO_ERROR((maj), H5E_CANTLOCK, (err_ret), "can't acquire global bootstrap mutex"); \ - if (!((H5TS_dclp_t *)(v))->init) { \ - /* Invoke the init function */ \ - if (H5_UNLIKELY((f)(v) < 0)) \ - HGOTO_ERROR((maj), (min), (err_ret), __VA_ARGS__); \ - \ - /* Indicate that the free list is initialized */ \ - H5TS_SET_GLOBAL_INIT(v, true); \ - } \ - if (H5_UNLIKELY(H5TS_dlftt_mutex_release(&H5TS_bootstrap_mtx_g) < 0)) \ - HGOTO_ERROR((maj), H5E_CANTUNLOCK, (err_ret), "can't release global bootstrap mutex"); \ - } \ - } while (0) -#else /* H5_HAVE_CONCURRENCY */ -#define H5TS_INIT_GLOBAL(v, f, maj, min, err_ret, ...) \ - do { \ - if (H5_UNLIKELY(!((H5TS_dclp_t *)(v))->init)) { \ - /* Invoke the init function */ \ - if (H5_UNLIKELY((f)(v) < 0)) \ - HGOTO_ERROR((maj), (min), (err_ret), __VA_ARGS__); \ - \ - /* Indicate that the free list is initialized */ \ - H5TS_SET_GLOBAL_INIT(v, true); \ - } \ - } while (0) -#endif /* H5_HAVE_CONCURRENCY */ -#define H5TS_IS_GLOBAL_INIT(v) (((H5TS_dclp_t *)(v))->init) -#define H5TS_SET_GLOBAL_INIT(v, x) ((H5TS_dclp_t *)(v))->init = (x) - /*****************************/ /* Library-private Variables */ /*****************************/ diff --git a/src/H5private.h b/src/H5private.h index a97197db672..4ed6117b4e1 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1666,6 +1666,58 @@ H5_DLL herr_t H5CX_pop(bool update_dxpl_props); #define HDcompile_assert(e) do { typedef struct { unsigned int b: (e); } x; } while(0) */ +/* Safely call an initialization routine for a global variable. + * + * Note that this currently assumes that the global variable is a struct + * containing a field of type H5_global_t as its first field. + */ +typedef struct H5_global_t { + bool init; /* Whether the global has been initialized */ +} H5_global_t; + +#ifdef H5_HAVE_CONCURRENCY + +/* Mechanism for implementing double-checked locking protocol (DCLP) for global + * variables with deferred initialization (i.e. not at library init time). + * + * This is invoked from a single thread while blocking other threads from + * using the global until initialization is completed. + * + * FYI: https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/ + */ +#define H5_GLOBAL_INIT(v, f, maj, min, err_ret, ...) \ + do { \ + if (H5_UNLIKELY(!((H5_global_t *)(v))->init)) { \ + if (H5_UNLIKELY(H5TS_dlftt_mutex_acquire(&H5TS_bootstrap_mtx_g) < 0)) \ + HGOTO_ERROR((maj), H5E_CANTLOCK, (err_ret), "can't acquire global bootstrap mutex"); \ + if (!((H5_global_t *)(v))->init) { \ + /* Invoke the init function */ \ + if (H5_UNLIKELY((f)(v) < 0)) \ + HGOTO_ERROR((maj), (min), (err_ret), __VA_ARGS__); \ + \ + /* Indicate that the free list is initialized */ \ + H5_GLOBAL_SET_INIT(v, true); \ + } \ + if (H5_UNLIKELY(H5TS_dlftt_mutex_release(&H5TS_bootstrap_mtx_g) < 0)) \ + HGOTO_ERROR((maj), H5E_CANTUNLOCK, (err_ret), "can't release global bootstrap mutex"); \ + } \ + } while (0) +#else /* H5_HAVE_CONCURRENCY */ +#define H5_GLOBAL_INIT(v, f, maj, min, err_ret, ...) \ + do { \ + if (H5_UNLIKELY(!((H5_global_t *)(v))->init)) { \ + /* Invoke the init function */ \ + if (H5_UNLIKELY((f)(v) < 0)) \ + HGOTO_ERROR((maj), (min), (err_ret), __VA_ARGS__); \ + \ + /* Indicate that the free list is initialized */ \ + H5_GLOBAL_SET_INIT(v, true); \ + } \ + } while (0) +#endif /* H5_HAVE_CONCURRENCY */ +#define H5_GLOBAL_IS_INIT(v) (((H5_global_t *)(v))->init) +#define H5_GLOBAL_SET_INIT(v, x) ((H5_global_t *)(v))->init = (x) + /* Private typedefs */ /* Union for const/non-const pointer for use by functions that manipulate