Mesa (master): gallivm: Allow drivers and state trackers to initialize gallivm LLVM targets v2

Tom Stellard tstellar at kemper.freedesktop.org
Sat Oct 3 01:03:47 UTC 2015


Module: Mesa
Branch: master
Commit: 76cfd6f1da3748effb480e4f1151910af59fb88a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=76cfd6f1da3748effb480e4f1151910af59fb88a

Author: Tom Stellard <thomas.stellard at amd.com>
Date:   Thu Sep 24 15:57:02 2015 +0000

gallivm: Allow drivers and state trackers to initialize gallivm LLVM targets v2

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 <marek.olsak at amd.com>
Reviewed-by: Mathias Fröhlich <Mathias.Froehlich at web.de>
Reviewed-by: Emil Velikov <emil.l.velikov at gmail.com>

CC: "10.6 11.0" <mesa-stable at lists.freedesktop.org>

---

 src/gallium/auxiliary/gallivm/lp_bld_misc.cpp |   37 ++++++++++++++++++++-----
 src/gallium/auxiliary/gallivm/lp_bld_misc.h   |    2 ++
 src/gallium/targets/opencl/Makefile.am        |    3 +-
 3 files changed, 34 insertions(+), 8 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);
diff --git a/src/gallium/targets/opencl/Makefile.am b/src/gallium/targets/opencl/Makefile.am
index 4ab706e..c78b268 100644
--- a/src/gallium/targets/opencl/Makefile.am
+++ b/src/gallium/targets/opencl/Makefile.am
@@ -35,7 +35,8 @@ lib at OPENCL_LIBNAME@_la_LIBADD = \
 	-lclangEdit \
 	-lclangLex \
 	-lclangBasic \
-	$(LLVM_LIBS)
+	$(LLVM_LIBS) \
+	$(PTHREAD_LIBS)
 
 nodist_EXTRA_lib at OPENCL_LIBNAME@_la_SOURCES = dummy.cpp
 lib at OPENCL_LIBNAME@_la_SOURCES =




More information about the mesa-commit mailing list