Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make H5VL multi-thread safe #6

Closed
wants to merge 78 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
17074be
Make registration of optional VOL ops locally threadsafe
mattjala Aug 8, 2024
02bc1e5
Make H5VL_t ref count atomic
mattjala Aug 8, 2024
c3463b0
Atomically initialize H5VL_t's nrefs
mattjala Aug 9, 2024
3b76b00
Add testing workflow
mattjala Aug 9, 2024
315fea7
Make H5VL_object_t ref count atomic
mattjala Aug 9, 2024
024b914
Reorder ref count operations
mattjala Aug 9, 2024
5343bec
Add additional const qualifiers for connector info
mattjala Aug 9, 2024
a868b5e
Make global VOL IDs atomic
mattjala Aug 13, 2024
9bbaa72
Implement threadsafe search for existing connector
mattjala Aug 16, 2024
4e78836
File open threadsafety
mattjala Aug 14, 2024
8ff311f
Use lock instead of atomic for native VOL ID
mattjala Aug 13, 2024
d997742
Properly initialize atomic variables
mattjala Aug 27, 2024
67ce26b
Acquire global lock before invoking H5T routines
mattjala Sep 3, 2024
d75886e
Add global lock to H5VLdyn_ops
mattjala Sep 10, 2024
6da755f
Fix app ref count error
mattjala Sep 10, 2024
57e3314
Acquire global lock if VOL conn not threadsafe
mattjala Sep 13, 2024
ea42186
Rework VOL_CONN_LOCK/UNLOCK
mattjala Sep 27, 2024
8df5f77
Add H5TSmutex_lock/unlock
mattjala Sep 23, 2024
8a4c7da
Refcount VOL wrap context atomically
mattjala Sep 25, 2024
e47c57a
Initialize properly when H5VL_NATIVE used early
mattjala Sep 26, 2024
6670314
MT VL Tests for conn/dyn op registration
mattjala Sep 10, 2024
ee1ccba
Add concurrent registration/op test
mattjala Sep 11, 2024
076f025
Add multi-threaded H5VL tests to CI
mattjala Sep 11, 2024
762710d
Concurrent registration by name/value tests
mattjala Sep 11, 2024
d50f735
Registration on file open failure test
mattjala Sep 12, 2024
4bf768a
Test VOL conn property copying
mattjala Sep 20, 2024
d10b13f
Test global mutex rel/acq from threadsafe VOL
mattjala Sep 20, 2024
d2df9b7
Add tests for H5TSmutex_lock/unlock()
mattjala Sep 23, 2024
4e57459
Test concurrent register/unregister and search
mattjala Sep 25, 2024
95ae276
Test H5VL_NATIVE as first library entrance
mattjala Sep 26, 2024
13de8f2
Sync H5TSmutex* signature and definitions
mattjala Sep 26, 2024
d676f33
Rename test VOL Connector
mattjala Sep 26, 2024
c75c1d7
Remove deprecated op from test VOL
mattjala Sep 26, 2024
471dfeb
Fix and test context state copy
mattjala Sep 26, 2024
f4a734e
Check arguments in get_wrap_ctx()
mattjala Sep 30, 2024
0bda396
Test H5VLget/free_wrap_ctx()
mattjala Sep 30, 2024
860c6f1
Test copying connector info
mattjala Sep 30, 2024
f8b2efa
Implement assert-based virtual locks on IDs
mattjala Oct 8, 2024
677128d
Implement multi-thread test VOL connector
mattjala Oct 15, 2024
fe3da50
Free vol obj memory if creation fails
mattjala Oct 16, 2024
8ec7cbf
Check VOL obj rc during free in threadsafe manner
mattjala Oct 16, 2024
d013a0e
Fix VOL name and test counts during API tests
mattjala Oct 16, 2024
1d1d71c
Fix duplicate VOL flag test initialization
mattjala Oct 16, 2024
b2d6d9d
Fix VOL_CONN_LOCK/UNLOCK
mattjala Oct 16, 2024
8f8c7a9
Implement Multi-Thread Test Passthrough VOL
mattjala Oct 21, 2024
bf8774f
Support default and repeat IDs in virtual locks
mattjala Oct 22, 2024
8b14385
Add test multi-thread connectors to CI
mattjala Oct 22, 2024
875a808
Silence multi-thread passthrough VOL warnings
mattjala Oct 22, 2024
2122755
Fix unset VOL name/info in singlethread API tests
mattjala Oct 22, 2024
369a34d
Remove global mutex from H5T VOL API calls
mattjala Oct 22, 2024
43fc556
Remove global mutex from most H5F API calls
mattjala Oct 22, 2024
938fb34
Remove global mutex from most H5G API calls
mattjala Oct 22, 2024
89f83f4
Remove global mutex from most H5D API calls
mattjala Oct 22, 2024
b6e3670
Remove global mutex from most H5A API calls
mattjala Oct 22, 2024
a01e7e9
Remove global mutex from most H5O API calls
mattjala Oct 22, 2024
060f59b
Remove global mutex from most H5A API calls
mattjala Oct 22, 2024
851ad68
Fix FUNC_ENTER macro in single-thread builds
mattjala Oct 22, 2024
82bb934
Disable free list check when using multithread
mattjala Oct 22, 2024
8e2ec05
Use test framework for MT VOL tests
mattjala Oct 29, 2024
e9b5d66
Obey TestExpress timeout in MT VL tests
mattjala Oct 29, 2024
9ef1168
Lower testexpress value in CI
mattjala Oct 30, 2024
f59e5ec
Remove global mutex from H5VL.c
mattjala Oct 30, 2024
347442c
Adding missing locks around ID releases
mattjala Oct 30, 2024
6dd8e51
Respect do not disturb flag in virtual locks
mattjala Oct 30, 2024
1bbd2e3
Test production and debug build in CI
mattjala Oct 30, 2024
936f724
Guard ID iteration in connector search
mattjala Oct 31, 2024
d918699
Fix incorrect lock counting in virtual locks
mattjala Oct 31, 2024
2e5ee13
Fix virtual lock miscounting with passthrough VOLs
mattjala Oct 31, 2024
97414c5
Remove API-test specific test macros
mattjala Nov 4, 2024
7aa639a
Integrate MT API tests with test framework
mattjala Nov 11, 2024
a42cb00
Remove special filename handling from MT Test VOL
mattjala Nov 11, 2024
40538cd
Remove inconsistent virtual lock usage
mattjala Nov 11, 2024
8b27d22
Remove global lock from passthrough VOL callbacks
mattjala Nov 11, 2024
ce6271e
API Test cleanup
mattjala Nov 11, 2024
7392528
Remove unused routines from thread test connector
mattjala Nov 12, 2024
beeb40c
Rename thread test connector -> MT VL Test connector
mattjala Nov 12, 2024
a1cc650
Rename mt test vol -> MT Native Wrapper VOL
mattjala Nov 12, 2024
0da9361
Rename mt test passthru VOL -> MT passthru wrapper VOL
mattjala Nov 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ on:
branches:
- '*'

env:
HDF5TestExpress: 1

jobs:
build-and-test:
runs-on: ubuntu-latest
strategy:
matrix:
api_tests: ["--enable-api-tests", "--disable-api-tests"]
multi_thread: ["--enable-multithread --disable-hl", "--disable-multithread --enable-threadsafe --disable-hl", "--disable-multithread --disable-threadsafe"]
build_mode: ["production", "debug"]
fail-fast: false

steps:
Expand All @@ -25,22 +30,39 @@ jobs:
- name: Configure HDF5
working-directory: ${{github.workspace}}
run: |
autoreconf -if
./configure --enable-shared --enable-tests ${{ matrix.api_tests }}
sh ./autogen.sh
./configure --enable-shared --enable-tests ${{ matrix.multi_thread }} ${{ matrix.api_tests }} --enable-build-mode=${{ matrix.build_mode }}

- name: Build HDF5
working-directory: ${{github.workspace}}
run: |
make -j
make install


- name: API Tests
if: matrix.api_tests == '--enable-api-tests'
working-directory: ${{github.workspace}}
run: |
valgrind ./test/API/api_tests

- name: API Tests with multithread test VOL
if: matrix.api_tests == '--enable-api-tests' && matrix.multi_thread == '--enable-multithread --disable-hl'
working-directory: ${{github.workspace}}
env:
HDF5_PLUGIN_PATH: ${{github.workspace}}/test/.libs
HDF5_VOL_CONNECTOR: "mt_native_wrapper_vol_connector"
run: |
valgrind ./test/API/api_tests

- name: API Tests with passthrough multithread test VOL
if: matrix.api_tests == '--enable-api-tests' && matrix.multi_thread == '--enable-multithread --disable-hl'
working-directory: ${{github.workspace}}
env:
HDF5_PLUGIN_PATH: ${{github.workspace}}/test/.libs
HDF5_VOL_CONNECTOR: "mt_native_wrapper_passthru_vol_connector under_vol=0\\;under_info={}"
run: |
valgrind ./test/API/api_tests

- name: Test HDF5
working-directory: ${{github.workspace}}
run: |
make check
make check
11 changes: 10 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2043,6 +2043,7 @@ AC_SUBST([MULTITHREAD])
## Default is no multithread
MULTITHREAD=no


AC_MSG_CHECKING([for multithread configure option])
AC_ARG_ENABLE([multithread],
[AS_HELP_STRING([--enable-multithread],
Expand Down Expand Up @@ -2114,7 +2115,6 @@ esac

if test "X$MULTITHREAD" = "Xyes"; then
AC_DEFINE([HAVE_MULTITHREAD], [1], [Define if we have multithread support])

## ----------------------------------------------------------------------
## Is the Pthreads library present? It has a header file `pthread.h' and
## a library `-lpthread' and their locations might be specified with the
Expand Down Expand Up @@ -2245,6 +2245,15 @@ if test "X$MULTITHREAD" = "Xyes"; then
esac
fi

AC_SUBST([VIRTUAL_LOCK])
VIRTUAL_LOCK=NO

if test "X$MULTITHREAD" = "Xyes" -a "X$BUILD_MODE" = "Xdebug"; then
AC_DEFINE([HAVE_VIRTUAL_LOCK], [1], [Define if we enable the virtual lock])
else
AC_DEFINE([HAVE_VIRTUAL_LOCK], [0], [Define if we enable the virtual lock])
fi

## ----------------------------------------------------------------------
## Check for MONOTONIC_TIMER support (used in clock_gettime). This has
## to be done after any POSIX defines to ensure that the test gets
Expand Down
71 changes: 43 additions & 28 deletions src/H5.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,15 +544,15 @@ H5dont_atexit(void)
{
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_API_NOINIT_NOERR_NOFS
FUNC_ENTER_API_NOINIT_NOERR_NOFS()
H5TRACE0("e", "");

if (H5_dont_atexit_g)
ret_value = FAIL;
else
H5_dont_atexit_g = TRUE;

FUNC_LEAVE_API_NOFS(ret_value)
FUNC_LEAVE_API_NOFS(ret_value, H5I_INVALID_HID)
} /* end H5dont_atexit() */

/*-------------------------------------------------------------------------
Expand All @@ -577,15 +577,15 @@ H5garbage_collect(void)
{
herr_t ret_value = SUCCEED;

FUNC_ENTER_API(FAIL)
FUNC_ENTER_API(FAIL, H5I_INVALID_HID)
H5TRACE0("e", "");

/* Call the garbage collection routines in the library */
if (H5FL_garbage_coll() < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "can't garbage collect objects");

done:
FUNC_LEAVE_API(ret_value)
FUNC_LEAVE_API(ret_value, H5I_INVALID_HID)
} /* end H5garbage_collect() */

/*-------------------------------------------------------------------------
Expand Down Expand Up @@ -621,7 +621,7 @@ H5set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_lim,
{
herr_t ret_value = SUCCEED;

FUNC_ENTER_API(FAIL)
FUNC_ENTER_API(FAIL, H5I_INVALID_HID)
H5TRACE6("e", "IsIsIsIsIsIs", reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim, blk_global_lim,
blk_list_lim);

Expand All @@ -631,7 +631,7 @@ H5set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_lim,
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSET, FAIL, "can't set garbage collection limits");

done:
FUNC_LEAVE_API(ret_value)
FUNC_LEAVE_API(ret_value, H5I_INVALID_HID)
} /* end H5set_free_list_limits() */

/*-------------------------------------------------------------------------
Expand Down Expand Up @@ -659,15 +659,15 @@ H5get_free_list_sizes(size_t *reg_size /*out*/, size_t *arr_size /*out*/, size_t
{
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_API(FAIL)
FUNC_ENTER_API(FAIL, H5I_INVALID_HID)
H5TRACE4("e", "xxxx", 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)
FUNC_LEAVE_API(ret_value, H5I_INVALID_HID)
} /* end H5get_free_list_sizes() */

/*-------------------------------------------------------------------------
Expand Down Expand Up @@ -819,7 +819,7 @@ H5get_libversion(unsigned *majnum /*out*/, unsigned *minnum /*out*/, unsigned *r
{
herr_t ret_value = SUCCEED;

FUNC_ENTER_API(FAIL)
FUNC_ENTER_API(FAIL, H5I_INVALID_HID)
H5TRACE3("e", "xxx", majnum, minnum, relnum);

/* Set the version information */
Expand All @@ -831,7 +831,7 @@ H5get_libversion(unsigned *majnum /*out*/, unsigned *minnum /*out*/, unsigned *r
*relnum = H5_VERS_RELEASE;

done:
FUNC_LEAVE_API(ret_value)
FUNC_LEAVE_API(ret_value, H5I_INVALID_HID)
} /* end H5get_libversion() */

/*-------------------------------------------------------------------------
Expand Down Expand Up @@ -882,7 +882,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
static const char *release_mismatch_warning = RELEASE_MISMATCH_WARNING;
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_API_NOINIT_NOERR_NOFS
FUNC_ENTER_API_NOINIT_NOERR_NOFS()
H5TRACE3("e", "IuIuIu", majnum, minnum, relnum);

/* Don't check again, if we already have */
Expand Down Expand Up @@ -1008,7 +1008,7 @@ H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
}

done:
FUNC_LEAVE_API_NOFS(ret_value)
FUNC_LEAVE_API_NOFS(ret_value, H5I_INVALID_HID)
} /* end H5check_version() */

/*-------------------------------------------------------------------------
Expand All @@ -1028,13 +1028,13 @@ H5open(void)
{
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_API_NOPUSH(FAIL)
FUNC_ENTER_API_NOPUSH(FAIL, H5I_INVALID_HID)
/*NO TRACE*/

/* all work is done by FUNC_ENTER() */

done:
FUNC_LEAVE_API_NOPUSH(ret_value)
FUNC_LEAVE_API_NOPUSH(ret_value, H5I_INVALID_HID)
} /* end H5open() */

/*-------------------------------------------------------------------------
Expand All @@ -1053,7 +1053,7 @@ H5atclose(H5_atclose_func_t func, void *ctx)
H5_atclose_node_t *new_atclose; /* New 'atclose' node */
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_API(FAIL)
FUNC_ENTER_API(FAIL, H5I_INVALID_HID)
H5TRACE2("e", "Hc*x", func, ctx);

/* Check arguments */
Expand All @@ -1073,7 +1073,7 @@ H5atclose(H5_atclose_func_t func, void *ctx)
H5_atclose_head = new_atclose;

done:
FUNC_LEAVE_API(ret_value)
FUNC_LEAVE_API(ret_value, H5I_INVALID_HID)
} /* end H5atclose() */

/*-------------------------------------------------------------------------
Expand All @@ -1093,12 +1093,12 @@ H5close(void)
* whole library just to release it all right away. It is safe to call
* this function for an uninitialized library.
*/
FUNC_ENTER_API_NOINIT_NOERR_NOFS
FUNC_ENTER_API_NOINIT_NOERR_NOFS()
H5TRACE0("e", "");

H5_term_library();

FUNC_LEAVE_API_NOFS(SUCCEED)
FUNC_LEAVE_API_NOFS(SUCCEED, H5I_INVALID_HID)
} /* end H5close() */

/*-------------------------------------------------------------------------
Expand Down Expand Up @@ -1131,7 +1131,7 @@ H5allocate_memory(size_t size, hbool_t clear)
{
void *ret_value = NULL;

FUNC_ENTER_API_NOINIT
FUNC_ENTER_API_NOINIT()
H5TRACE2("*x", "zb", size, clear);

if (0 == size)
Expand All @@ -1142,7 +1142,7 @@ H5allocate_memory(size_t size, hbool_t clear)
else
ret_value = H5MM_malloc(size);

FUNC_LEAVE_API_NOINIT(ret_value)
FUNC_LEAVE_API_NOINIT(ret_value, H5I_INVALID_HID)
} /* end H5allocate_memory() */

/*-------------------------------------------------------------------------
Expand Down Expand Up @@ -1174,12 +1174,12 @@ H5resize_memory(void *mem, size_t size)
{
void *ret_value = NULL;

FUNC_ENTER_API_NOINIT
FUNC_ENTER_API_NOINIT()
H5TRACE2("*x", "*xz", mem, size);

ret_value = H5MM_realloc(mem, size);

FUNC_LEAVE_API_NOINIT(ret_value)
FUNC_LEAVE_API_NOINIT(ret_value, H5I_INVALID_HID)
} /* end H5resize_memory() */

/*-------------------------------------------------------------------------
Expand All @@ -1197,13 +1197,13 @@ H5resize_memory(void *mem, size_t size)
herr_t
H5free_memory(void *mem)
{
FUNC_ENTER_API_NOINIT
FUNC_ENTER_API_NOINIT()
H5TRACE1("e", "*x", mem);

/* At this time, it is impossible for this to fail. */
H5MM_xfree(mem);

FUNC_LEAVE_API_NOINIT(SUCCEED)
FUNC_LEAVE_API_NOINIT(SUCCEED, H5I_INVALID_HID)
} /* end H5free_memory() */

/*-------------------------------------------------------------------------
Expand All @@ -1221,7 +1221,7 @@ H5is_library_threadsafe(hbool_t *is_ts /*out*/)
{
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_API_NOINIT
FUNC_ENTER_API_NOINIT()
H5TRACE1("e", "x", is_ts);

if (is_ts) {
Expand All @@ -1234,7 +1234,7 @@ H5is_library_threadsafe(hbool_t *is_ts /*out*/)
else
ret_value = FAIL;

FUNC_LEAVE_API_NOINIT(ret_value)
FUNC_LEAVE_API_NOINIT(ret_value, H5I_INVALID_HID)
} /* end H5is_library_threadsafe() */

/*-------------------------------------------------------------------------
Expand All @@ -1256,7 +1256,7 @@ H5is_library_terminating(hbool_t *is_terminating /*out*/)
{
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_API_NOINIT
FUNC_ENTER_API_NOINIT()
H5TRACE1("e", "x", is_terminating);

assert(is_terminating);
Expand All @@ -1266,7 +1266,7 @@ H5is_library_terminating(hbool_t *is_terminating /*out*/)
else
ret_value = FAIL;

FUNC_LEAVE_API_NOINIT(ret_value)
FUNC_LEAVE_API_NOINIT(ret_value, H5I_INVALID_HID)
} /* end H5is_library_terminating() */

#if defined(H5_HAVE_THREADSAFE) && defined(H5_BUILT_AS_DYNAMIC_LIB) && defined(H5_HAVE_WIN32_API) && \
Expand Down Expand Up @@ -1328,3 +1328,18 @@ DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
return fOkay;
}
#endif /* H5_HAVE_WIN32_API && H5_BUILT_AS_DYNAMIC_LIB && H5_HAVE_WIN_THREADS && H5_HAVE_THREADSAFE*/

#if defined(H5_HAVE_THREADSAFE) || defined(H5_HAVE_MULTITHREAD)
// TODO
bool H5_varname_is_id(const char *varname) {
const char *suffix = "_id";
size_t len_var = strlen(varname);
size_t len_suffix = strlen(suffix);

if (len_var < len_suffix) {
return false;
}

return strcmp(varname + len_var - len_suffix, suffix) == 0;
}
#endif
Loading
Loading