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 adding two new functions: gallivm_llvm_init_begin() which locks a mutex guarding the TargetRegistry and initializes the gallivm targets, and gallivm_llvm_init_end() which unlocks the mutex. Drivers and state trackers should use this sequence to correctly initialize the LLVM targets they use: gallivm_init_llvm_begin(); LLVMInitializeFooTarget(); gallivm_init_llvm_end(); CC: "10.6 11.0" <mesa-sta...@lists.freedesktop.org> --- src/gallium/auxiliary/gallivm/lp_bld_misc.cpp | 68 ++++++++++++++++++++++++--- src/gallium/auxiliary/gallivm/lp_bld_misc.h | 5 ++ 2 files changed, 66 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..8bf833e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp +++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp @@ -81,6 +81,7 @@ # pragma pop_macro("DEBUG") #endif +#include "os/os_thread.h" #include "pipe/p_config.h" #include "util/u_debug.h" #include "util/u_cpu_detect.h" @@ -101,6 +102,64 @@ public: static LLVMEnsureMultithreaded lLVMEnsureMultithreaded; +struct LLVMRegistryLock { +private: + pipe_mutex mutex; + +public: + LLVMRegistryLock() + { + pipe_mutex_init(mutex); + } + + void lock() + { + pipe_mutex_lock(mutex); + } + + void unlock() + { + pipe_mutex_unlock(mutex); + } +}; + +static LLVMRegistryLock gallivm_llvm_registry_lock; + +} + +/** + * The llvm target registry is not thread-safe, so drivers and state-trackers + * that want to initialize targets should use the gallivm_init_llvm_begin() and + * gallivm_init_llvm_end() functions to safely initialize targets. For example: + * + * gallivm_init_llvm_begin(); + * LLVMInitializeFooTarget(); + * gallivm_init_llvm_end(); + * + * LLVM targets should be initialized before the driver tries to access the + * registry. + */ +extern "C" void +gallivm_init_llvm_begin(void) +{ + static int init = 0; + gallivm_llvm_registry_lock.lock(); + if (!init) { + // 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(); + init = 1; + } +} + +extern "C" void +gallivm_init_llvm_end(void) +{ + gallivm_llvm_registry_lock.unlock(); } extern "C" void @@ -115,13 +174,8 @@ 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_begin(); + gallivm_init_llvm_end(); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.h b/src/gallium/auxiliary/gallivm/lp_bld_misc.h index 36923aa..f87bb24 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_misc.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.h @@ -41,6 +41,11 @@ extern "C" { struct lp_generated_code; +extern void +gallivm_init_llvm_begin(void); + +extern void +gallivm_init_llvm_end(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