Skip to content

Commit

Permalink
threadsafe: Load preferences threadsafe
Browse files Browse the repository at this point in the history
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 gnuradio#440

Signed-off-by: Johannes Demel <[email protected]>
  • Loading branch information
jdemel committed Feb 21, 2021
1 parent cf44693 commit 4abcf5c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 7 deletions.
6 changes: 6 additions & 0 deletions include/volk/volk_prefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
43 changes: 43 additions & 0 deletions lib/volk_prefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#else
#include <unistd.h>
#endif
#include <stdatomic.h>
#include <volk/volk_prefs.h>

void volk_get_config_path(char* path, bool read)
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 3 additions & 7 deletions lib/volk_rank_archs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 4abcf5c

Please sign in to comment.