From 76cfd6f1da3748effb480e4f1151910af59fb88a Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Thu, 24 Sep 2015 15:57:02 +0000 Subject: gallivm: Allow drivers and state trackers to initialize gallivm LLVM targets v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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(). Reviewed-by: Marek Olšák Reviewed-by: Mathias Fröhlich Reviewed-by: Emil Velikov CC: "10.6 11.0" --- 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(-) (limited to 'src/gallium/auxiliary/gallivm') diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp index 5e25819ac55..72fab8ccf06 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 36923aa423f..86d2f86ac45 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); -- cgit v1.2.3