Drivers and state trackers that use LLVM for generating code, must register the targets they use with LLVM's global TargetRegistry. The TargetRegistry is not thread-safe, so all targets must be added to the registry before it can be queried for target information.
When drivers and state trackers initialize their own targets, they need a way to force gallivm to initialize its targets at the same time. Otherwise, there can be a race condition in some multi-threaded applications (e.g. glx-multihreaded-shader-compile in piglit), when one thread creates a context for a driver that uses LLVM (e.g. radeonsi) and another thread creates a gallivm context (glxContextCreate does this). The race happens when the driver thread initializes its LLVM targets and then starts using the registry before the gallivm thread has a chance to register its targets. This patch allows users to force gallivm to register its targets by calling the gallivm_init_llvm_targets() function. v2: - Use call_once and remove mutexes and static initializations. - Replace gallivm_init_llvm_{begin,end}() with gallivm_init_llvm_targets(). CC: "10.6 11.0" <mesa-sta...@lists.freedesktop.org> --- src/gallium/auxiliary/gallivm/lp_bld_misc.cpp | 37 ++++++++++++++++++++++----- src/gallium/auxiliary/gallivm/lp_bld_misc.h | 2 ++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp index 5e25819..72fab8c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp +++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp @@ -81,6 +81,8 @@ # pragma pop_macro("DEBUG") #endif +#include "c11/threads.h" +#include "os/os_thread.h" #include "pipe/p_config.h" #include "util/u_debug.h" #include "util/u_cpu_detect.h" @@ -103,6 +105,33 @@ static LLVMEnsureMultithreaded lLVMEnsureMultithreaded; } +static once_flag init_native_targets_once_flag; + +static void init_native_targets() +{ + // If we have a native target, initialize it to ensure it is linked in and + // usable by the JIT. + llvm::InitializeNativeTarget(); + + llvm::InitializeNativeTargetAsmPrinter(); + + llvm::InitializeNativeTargetDisassembler(); +} + +/** + * The llvm target registry is not thread-safe, so drivers and state-trackers + * that want to initialize targets should use the gallivm_init_llvm_targets() + * function to safely initialize targets. + * + * LLVM targets should be initialized before the driver or state-tracker tries + * to access the registry. + */ +extern "C" void +gallivm_init_llvm_targets(void) +{ + call_once(&init_native_targets_once_flag, init_native_targets); +} + extern "C" void lp_set_target_options(void) { @@ -115,13 +144,7 @@ lp_set_target_options(void) llvm::DisablePrettyStackTrace = true; #endif - // If we have a native target, initialize it to ensure it is linked in and - // usable by the JIT. - llvm::InitializeNativeTarget(); - - llvm::InitializeNativeTargetAsmPrinter(); - - llvm::InitializeNativeTargetDisassembler(); + gallivm_init_llvm_targets(); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.h b/src/gallium/auxiliary/gallivm/lp_bld_misc.h index 36923aa..86d2f86 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_misc.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.h @@ -41,6 +41,8 @@ extern "C" { struct lp_generated_code; +extern void +gallivm_init_llvm_targets(void); extern void lp_set_target_options(void); -- 2.0.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev