From 3e3d08d4ad3b06709d8eb93e78aa36081c51c522 Mon Sep 17 00:00:00 2001 From: Johannes Demel Date: Sun, 21 Feb 2021 15:49:16 +0100 Subject: [PATCH] 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 96b7f1c11..bf7f8a359 100644 --- a/include/volk/volk_prefs.h +++ b/include/volk/volk_prefs.h @@ -13,6 +13,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 8934bf7d4..6bceac6d5 100644 --- a/lib/volk_prefs.c +++ b/lib/volk_prefs.c @@ -9,6 +9,7 @@ #else #include #endif +#include #include void volk_get_config_path(char* path, bool read) @@ -63,6 +64,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 7cf3fd713..7a98a2cc6 100644 --- a/lib/volk_rank_archs.c +++ b/lib/volk_rank_archs.c @@ -53,13 +53,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.