summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Young <dyoung@hdfgroup.org>2019-08-28 17:58:08 (GMT)
committerDavid Young <dyoung@hdfgroup.org>2019-08-28 17:58:08 (GMT)
commite178ab0e11a6d4ac8f3541549b03cfff1456b38a (patch)
treededa52aa62bbdab198c95996999a408aa509950f /src
parent1f728439ddf4ac94d49ddd14fb72982b66b814fd (diff)
downloadhdf5-e178ab0e11a6d4ac8f3541549b03cfff1456b38a.zip
hdf5-e178ab0e11a6d4ac8f3541549b03cfff1456b38a.tar.gz
hdf5-e178ab0e11a6d4ac8f3541549b03cfff1456b38a.tar.bz2
Consolidate VFD SWMR variable declarations in a new header file,
H5FDvfd_swmr_private.h. Perform tick processing in FUNC_ENTER_API_NOCLEAR, where it was missing. Track the number of times the HDF5 library has been entered/exited through its public API. Only perform tick processing on the first entry and last exit. This stops us from performing tick processing in API calls invoked by application callbacks. Performing tick processing in nested API calls led to crashes. Note well: FUNC_LEAVE_API now performs tick processing even on an error exit! Previously, it did not. I'm not sure if the change is ok.
Diffstat (limited to 'src')
-rw-r--r--src/H5FDvfd_swmr_private.h25
-rw-r--r--src/H5Fint.c7
-rw-r--r--src/H5Fprivate.h2
-rw-r--r--src/H5private.h105
4 files changed, 76 insertions, 63 deletions
diff --git a/src/H5FDvfd_swmr_private.h b/src/H5FDvfd_swmr_private.h
new file mode 100644
index 0000000..54398dd
--- /dev/null
+++ b/src/H5FDvfd_swmr_private.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 The HDF Group. All rights reserved.
+ *
+ * This file is part of HDF5. The full HDF5 copyright notice, including
+ * terms governing use, modification, and redistribution, is contained in
+ * the COPYING file, which can be found at the root of the source code
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
+ * If you do not have access to either file, you may request a copy from
+ * help@hdfgroup.org.
+ */
+
+#ifndef _H5FDvfd_swmr_private_H
+#define _H5FDvfd_swmr_private_H
+
+/* Temporary globals for VFD SWMR */
+extern hbool_t vfd_swmr_g;
+extern unsigned int vfd_swmr_api_entries_g;
+extern hbool_t vfd_swmr_writer_g;
+extern uint64_t tick_num_g;
+extern struct timespec end_of_tick_g;
+
+H5_DLL herr_t H5F_vfd_swmr_writer_end_of_tick(void);
+H5_DLL herr_t H5F_vfd_swmr_reader_end_of_tick(void);
+
+#endif /* _H5FDvfd_swmr_private_H */
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 23213ac..a955892 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -141,6 +141,13 @@ static herr_t H5F__vfd_swmr_writer__wait_a_tick(H5F_t *f);
/* VFD SWMR globals */
H5F_t *vfd_swmr_file_g = NULL; /* Points to the file struct */
hbool_t vfd_swmr_g = FALSE; /* Is this a VFD SWMR configured file */
+unsigned int vfd_swmr_api_entries_g = 0;/* Times the library was entered
+ * and re-entered minus the times
+ * it was exited. We only perform
+ * the end-of-tick processing
+ * on the 0->1 and 1->0
+ * transitions.
+ */
hbool_t vfd_swmr_writer_g = FALSE; /* Is this the VFD SWMR writer */
uint64_t tick_num_g = 0; /* The current tick_num */
#if 1 /* clock_gettime() version */ /* JRM */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index cad92fa..f671635 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -881,8 +881,6 @@ H5_DLL herr_t H5F_debug(H5F_t *f, FILE * stream, int indent, int fwidth);
/* VFD SWMR */
H5_DLL herr_t H5F_vfd_swmr_writer__delay_write(H5F_t *f, uint64_t page,
uint64_t * delay_write_until_ptr);
-H5_DLL herr_t H5F_vfd_swmr_writer_end_of_tick(void);
-H5_DLL herr_t H5F_vfd_swmr_reader_end_of_tick(void);
H5_DLL herr_t H5F_update_vfd_swmr_metadata_file(H5F_t *f, uint32_t index_len, struct H5FD_vfd_swmr_idx_entry_t *index);
H5_DLL hbool_t H5F_use_vfd_swmr(const H5F_t *f);
H5_DLL haddr_t H5F_get_vfd_swmr_md_eoa(const H5F_t *f);
diff --git a/src/H5private.h b/src/H5private.h
index b64903b..f96188f 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -1953,15 +1953,7 @@ extern hbool_t H5_libterm_g; /* Is the library being shutdown? */
#define H5_INIT_GLOBAL (H5_libinit_g)
#define H5_TERM_GLOBAL (H5_libterm_g)
-/* Temporary globals for VFD SWMR */
-extern hbool_t vfd_swmr_g;
-extern hbool_t vfd_swmr_writer_g;
-extern uint64_t tick_num_g;
-#if 1 /* use clock_gettime() */ /* JRM */
-extern struct timespec end_of_tick_g;
-#else /* use gettimeofday() */ /* JRM */
-extern struct timeval end_of_tick_g;
-#endif /* use gettimeofday() */ /* JRM */
+#include "H5FDvfd_swmr_private.h"
#endif /* H5_HAVE_THREADSAFE */
@@ -2078,59 +2070,50 @@ H5_DLL herr_t H5CX_pop(void);
\
BEGIN_MPE_LOG
-#if 1 /* clock_gettime() version */ /* JRM */
-#define VFD_SWMR_TEST_FOR_END_OF_TICK(swmr_reader_exit, err) \
+/* NetBSD provides these comparison macros as part of a nifty set that
+ * performs addition and subtraction, too. We probably should bring in
+ * the whole set. -DCY
+ */
+#if !defined(timespeccmp)
+#define timespeccmp(__l, __r, __op) \
+ (((__l)->tv_sec == (__r)->tv_sec) \
+ ? ((__l)->tv_nsec __op (__r)->tv_nsec) \
+ : ((__l)->tv_sec __op (__r)->tv_sec))
+#endif /* !defined(timespeccmp) */
+
+#define VFD_SWMR_TEST_FOR_END_OF_TICK(entering, swmr_reader_exit, err) \
/* Initialize the library */ \
- if(vfd_swmr_g) { \
+ /* TBD assert that the API lock is held. The API lock */ \
+ /* synchronizes access to `vfd_swmr_api_entries_g` */ \
+ if (!entering && --vfd_swmr_api_entries_g > 0) { \
+ ; /* Do nothing: we are still in an API call. */ \
+ } else if (entering && vfd_swmr_api_entries_g++ > 0) { \
+ ; /* Do nothing: we are *re-*entering the API. */ \
+ } else if(err_occurred) { \
+ ; /* Do nothing: an error occurred. */ \
+ } else if(vfd_swmr_g) { \
struct timespec curr_time; \
- long curr_nsecs, end_nsecs; \
- if(HDclock_gettime(CLOCK_MONOTONIC, &curr_time) < 0) \
+ if(HDclock_gettime(CLOCK_MONOTONIC, &curr_time) < 0) { \
HGOTO_ERROR(H5E_FUNC, H5E_CANTGET, err, \
"can't get time via clock_gettime") \
- curr_nsecs = curr_time.tv_sec * 1000000000 + curr_time.tv_nsec; \
- end_nsecs = end_of_tick_g.tv_sec * 1000000000 + end_of_tick_g.tv_nsec;\
- if(curr_nsecs > end_nsecs) { \
- if(vfd_swmr_writer_g) { \
- if(H5F_vfd_swmr_writer_end_of_tick() < 0) \
- HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
- "end of tick error for VFD SWMR writer") \
- } \
- else if(!swmr_reader_exit) { \
- if(H5F_vfd_swmr_reader_end_of_tick() < 0) \
- HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
- "end of tick error for VFD SWMR reader") \
- } \
+ } else if(timespeccmp(&curr_time, &end_of_tick_g, <)) { \
+ ; /* Do nothing: it's not time, yet. */ \
+ } else if (vfd_swmr_writer_g) { \
+ if(H5F_vfd_swmr_writer_end_of_tick() < 0) \
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
+ "end of tick error for VFD SWMR writer") \
+ } else if(!swmr_reader_exit) { \
+ if(H5F_vfd_swmr_reader_end_of_tick() < 0) \
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
+ "end of tick error for VFD SWMR reader") \
} \
}
-#else /* gettimeofday() version */ /* JRM */
-#define VFD_SWMR_TEST_FOR_END_OF_TICK(swmr_reader_exit, err) \
- /* Initialize the library */ \
- if(vfd_swmr_g) { \
- struct timeval curr_time; \
- if(HDgettimeofday(&curr_time, NULL) < 0) \
- HGOTO_ERROR(H5E_FUNC, H5E_CANTGET, err, \
- "can't get time via gettimeofday()") \
- if((curr_time.tv_sec >= end_of_tick_g.tv_sec) && \
- (curr_time.tv_usec >= end_of_tick_g.tv_usec)) { \
- if(vfd_swmr_writer_g) { \
- if(H5F_vfd_swmr_writer_end_of_tick() < 0) \
- HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
- "end of tick error for VFD SWMR writer") \
- } \
- else if(!swmr_reader_exit) { \
- if(H5F_vfd_swmr_reader_end_of_tick() < 0) \
- HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
- "end of tick error for VFD SWMR reader") \
- } \
- } \
- }
-#endif /* gettimeofday() version */ /* JRM */
/* Use this macro for all "normal" API functions */
#define FUNC_ENTER_API(err) {{ \
FUNC_ENTER_API_COMMON \
FUNC_ENTER_API_INIT(err); \
- VFD_SWMR_TEST_FOR_END_OF_TICK(FALSE, err); \
+ VFD_SWMR_TEST_FOR_END_OF_TICK(true, false, err); \
/* Clear thread error stack entering public functions */ \
H5E_clear_stack(NULL); \
{
@@ -2142,6 +2125,7 @@ H5_DLL herr_t H5CX_pop(void);
#define FUNC_ENTER_API_NOCLEAR(err) {{ \
FUNC_ENTER_API_COMMON \
FUNC_ENTER_API_INIT(err); \
+ VFD_SWMR_TEST_FOR_END_OF_TICK(true, false, err); \
{
/*
@@ -2332,16 +2316,15 @@ H5_DLL herr_t H5CX_pop(void);
FINISH_MPE_LOG \
H5TRACE_RETURN(ret_value);
-#define FUNC_LEAVE_API(ret_value) \
- if(!err_occurred) \
- VFD_SWMR_TEST_FOR_END_OF_TICK(!vfd_swmr_writer_g, ret_value); \
- FUNC_LEAVE_API_COMMON(ret_value); \
- (void)H5CX_pop(); \
- H5_POP_FUNC \
- if(err_occurred) \
- (void)H5E_dump_api_stack(TRUE); \
- FUNC_LEAVE_API_THREADSAFE \
- return(ret_value); \
+#define FUNC_LEAVE_API(ret_value) \
+ VFD_SWMR_TEST_FOR_END_OF_TICK(false, !vfd_swmr_writer_g, ret_value); \
+ FUNC_LEAVE_API_COMMON(ret_value); \
+ (void)H5CX_pop(); \
+ H5_POP_FUNC \
+ if(err_occurred) \
+ (void)H5E_dump_api_stack(TRUE); \
+ FUNC_LEAVE_API_THREADSAFE \
+ return(ret_value); \
}} /*end scope from beginning of FUNC_ENTER*/
/* Use this macro to match the FUNC_ENTER_API_NOINIT macro */