From e355e5926a19c88e8d44b3291816a099c82997c3 Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Sun, 21 Feb 2021 15:49:16 +0100 Subject: [PATCH 1/3] threadsafe: Load preferences threadsafe Instead of static variables in a function, we store preferences in a struct and use an `atomic_int` to prevent any more than one thread from loading preferences. Fixes #440 Signed-off-by: Johannes Demel --- include/volk/volk_prefs.h | 6 ++++++ lib/volk_prefs.c | 43 +++++++++++++++++++++++++++++++++++++++ lib/volk_rank_archs.c | 10 +++------ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/include/volk/volk_prefs.h b/include/volk/volk_prefs.h index 3aa8bc54e..d12317996 100644 --- a/include/volk/volk_prefs.h +++ b/include/volk/volk_prefs.h @@ -22,6 +22,12 @@ typedef struct volk_arch_pref { char impl_u[128]; // best unaligned impl } volk_arch_pref_t; + +VOLK_API void volk_initialize_preferences(); +VOLK_API void volk_free_preferences(); +VOLK_API const size_t volk_get_num_arch_prefs(); +VOLK_API const volk_arch_pref_t* volk_get_arch_prefs(); + //////////////////////////////////////////////////////////////////////// // get path to volk_config profiling info; second arguments specifies // if config file should be tested on existence for reading. diff --git a/lib/volk_prefs.c b/lib/volk_prefs.c index 2ff989e33..5ca0ddfee 100644 --- a/lib/volk_prefs.c +++ b/lib/volk_prefs.c @@ -18,6 +18,7 @@ #else #include #endif +#include #include void volk_get_config_path(char* path, bool read) @@ -72,6 +73,48 @@ void volk_get_config_path(char* path, bool read) return; } + +static struct volk_preferences { + volk_arch_pref_t* volk_arch_prefs; + size_t n_arch_prefs; + atomic_int initialized; + +} volk_preferences; + + +void volk_initialize_preferences() +{ + if (!atomic_fetch_and(&volk_preferences.initialized, 1)) { + volk_preferences.n_arch_prefs = + volk_load_preferences(&volk_preferences.volk_arch_prefs); + } +} + + +void volk_free_preferences() +{ + if (volk_preferences.initialized) { + free(volk_preferences.volk_arch_prefs); + volk_preferences.n_arch_prefs = 0; + volk_preferences.initialized = 0; + } +} + + +const size_t volk_get_num_arch_prefs() +{ + volk_initialize_preferences(); + return volk_preferences.n_arch_prefs; +} + + +const volk_arch_pref_t* volk_get_arch_prefs() +{ + volk_initialize_preferences(); + return volk_preferences.volk_arch_prefs; +} + + size_t volk_load_preferences(volk_arch_pref_t** prefs_res) { FILE* config_file; diff --git a/lib/volk_rank_archs.c b/lib/volk_rank_archs.c index 750fe54b7..f5521268e 100644 --- a/lib/volk_rank_archs.c +++ b/lib/volk_rank_archs.c @@ -41,13 +41,9 @@ int volk_rank_archs(const char* kern_name, // name of the kernel to rank ) { size_t i; - static volk_arch_pref_t* volk_arch_prefs; - static size_t n_arch_prefs = 0; - static int prefs_loaded = 0; - if (!prefs_loaded) { - n_arch_prefs = volk_load_preferences(&volk_arch_prefs); - prefs_loaded = 1; - } + + const volk_arch_pref_t* volk_arch_prefs = volk_get_arch_prefs(); + const size_t n_arch_prefs = volk_get_num_arch_prefs(); // If we've defined VOLK_GENERIC to be anything, always return the // 'generic' kernel. Used in GR's QA code. From 608a66b867d8c4ceb9df269b1e04f3e39af9f2ec Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Thu, 4 Mar 2021 22:14:48 +0100 Subject: [PATCH 2/3] prefs: Introduce mutex for thread-safety We initialize a mutex with `call_once` and then use this mutex to protect the init and deinit portion of our struct handlers. Signed-off-by: Johannes Demel --- lib/CMakeLists.txt | 1 + lib/volk_prefs.c | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a27be22b4..4b9b0c990 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -560,6 +560,7 @@ if(ORC_FOUND) endif() if(NOT MSVC) target_link_libraries(volk PUBLIC m) + target_link_libraries(volk PRIVATE pthread) endif() set_target_properties(volk PROPERTIES VERSION ${VERSION}) set_target_properties(volk PROPERTIES SOVERSION ${SOVERSION}) diff --git a/lib/volk_prefs.c b/lib/volk_prefs.c index 5ca0ddfee..733b6f25b 100644 --- a/lib/volk_prefs.c +++ b/lib/volk_prefs.c @@ -18,7 +18,7 @@ #else #include #endif -#include +#include #include void volk_get_config_path(char* path, bool read) @@ -77,27 +77,44 @@ void volk_get_config_path(char* path, bool read) static struct volk_preferences { volk_arch_pref_t* volk_arch_prefs; size_t n_arch_prefs; - atomic_int initialized; + int initialized; + mtx_t mutex; } volk_preferences; +void init_struct_mutex(void) +{ + if (mtx_init(&volk_preferences.mutex, mtx_plain) != thrd_success) { + printf("\n mutex init failed\n"); + } +} + +static once_flag mutex_init_once_flag = ONCE_FLAG_INIT; +void initialize_mutex() { call_once(&mutex_init_once_flag, init_struct_mutex); } void volk_initialize_preferences() { - if (!atomic_fetch_and(&volk_preferences.initialized, 1)) { + initialize_mutex(); + mtx_lock(&volk_preferences.mutex); + if (!volk_preferences.initialized) { volk_preferences.n_arch_prefs = volk_load_preferences(&volk_preferences.volk_arch_prefs); + volk_preferences.initialized = 1; } + mtx_unlock(&volk_preferences.mutex); } void volk_free_preferences() { + initialize_mutex(); + mtx_lock(&volk_preferences.mutex); if (volk_preferences.initialized) { free(volk_preferences.volk_arch_prefs); volk_preferences.n_arch_prefs = 0; volk_preferences.initialized = 0; } + mtx_unlock(&volk_preferences.mutex); } From 1391989ad1455ffcca29a3a9cce97a2d760d5d6f Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Thu, 4 Mar 2021 22:35:54 +0100 Subject: [PATCH 3/3] prefs: Use threads if available Signed-off-by: Johannes Demel --- lib/volk_prefs.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/volk_prefs.c b/lib/volk_prefs.c index 733b6f25b..47c1aebff 100644 --- a/lib/volk_prefs.c +++ b/lib/volk_prefs.c @@ -18,7 +18,9 @@ #else #include #endif +#ifndef __STDC_NO_THREADS__ #include +#endif #include void volk_get_config_path(char* path, bool read) @@ -78,10 +80,12 @@ static struct volk_preferences { volk_arch_pref_t* volk_arch_prefs; size_t n_arch_prefs; int initialized; +#ifndef __STDC_NO_THREADS__ mtx_t mutex; - +#endif } volk_preferences; +#ifndef __STDC_NO_THREADS__ void init_struct_mutex(void) { if (mtx_init(&volk_preferences.mutex, mtx_plain) != thrd_success) { @@ -91,30 +95,39 @@ void init_struct_mutex(void) static once_flag mutex_init_once_flag = ONCE_FLAG_INIT; void initialize_mutex() { call_once(&mutex_init_once_flag, init_struct_mutex); } +#endif void volk_initialize_preferences() { +#ifndef __STDC_NO_THREADS__ initialize_mutex(); mtx_lock(&volk_preferences.mutex); +#endif if (!volk_preferences.initialized) { volk_preferences.n_arch_prefs = volk_load_preferences(&volk_preferences.volk_arch_prefs); volk_preferences.initialized = 1; } +#ifndef __STDC_NO_THREADS__ mtx_unlock(&volk_preferences.mutex); +#endif } void volk_free_preferences() { +#ifndef __STDC_NO_THREADS__ initialize_mutex(); mtx_lock(&volk_preferences.mutex); +#endif if (volk_preferences.initialized) { free(volk_preferences.volk_arch_prefs); volk_preferences.n_arch_prefs = 0; volk_preferences.initialized = 0; } +#ifndef __STDC_NO_THREADS__ mtx_unlock(&volk_preferences.mutex); +#endif }