Skip to content

Commit

Permalink
Move global variable initialization code out of H5TS header
Browse files Browse the repository at this point in the history
Signed-off-by: Quincey Koziol <[email protected]>
  • Loading branch information
qkoziol committed Jul 16, 2024
1 parent 11f1a0d commit d488bd0
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 63 deletions.
22 changes: 11 additions & 11 deletions src/H5FL.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions src/H5FLprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down
49 changes: 0 additions & 49 deletions src/H5TSprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
/*****************************/
Expand Down
52 changes: 52 additions & 0 deletions src/H5private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit d488bd0

Please sign in to comment.