[Mesa-dev] [PATCH] r600g-llvm: Crude fix for a race in initialization of the llvm backend
Tom Stellard
thomas.stellard at amd.com
Wed Aug 15 06:35:53 PDT 2012
cc'ing the list this time.
On Wed, Aug 15, 2012 at 07:51:46AM +0200, Mathias Fröhlich wrote:
>
> Hi,
>
> This change adds application global locking around compiling an r600 llvm
> shader. This fixes a race condition/crash that I observe when shaders are
> concurrently compiled from different contexts in different threads.
> The fix is crude as it just guards the whole compile with a global mutex, but
> up to now I did not have enough time to understand the real reason that must
> be somewhere in the way r600g initializes the llvm backend. And since we have
> a pending public release we will better have a curde fix than a known bug.
> Better solutions welcome!
>
> I will post a piglit test in the next minutes that exercises this problem with
> a high probability at least here on my test machine.
>
> Please review
>
> Mathias
This is likely caused by the fact that the same LLVM Context is used
for all threads. Take a look at the comment starting at
src/gallium/auxilary/gallivm/lp_bld_init.c:314
You should be able to reproduce this error on llvmpipe as well.
Creating a new LLVM Context for each thread should fix this.
-Tom
> From 6501efdb1ef9f52b584a709c4d24e095b67fc91d Mon Sep 17 00:00:00 2001
> Message-Id: <6501efdb1ef9f52b584a709c4d24e095b67fc91d.1345008604.git.Mathias.Froehlich at gmx.net>
> From: =?UTF-8?q?Mathias=20Fr=C3=B6hlich?= <Mathias.Froehlich at gmx.net>
> Date: Fri, 10 Aug 2012 22:20:06 +0200
> Subject: [PATCH] radeon_llvm: Introduce global lock on llvm.
>
> No clue what is really racing here, but this fixes
> sporadic crashes running osgviewer with multiple
> windows together with the r600 llvm shader compiler.
>
> Signed-off-by: Mathias Froehlich <Mathias.Froehlich at web.de>
> ---
> src/gallium/drivers/radeon/radeon_llvm.h | 10 ++++++++
> src/gallium/drivers/radeon/radeon_llvm_emit.cpp | 14 +++++++++--
> .../drivers/radeon/radeon_setup_tgsi_llvm.c | 28 ++++++++++++++++++++++
> 3 files changed, 50 insertions(+), 2 deletions(-)
>
> diff --git a/src/gallium/drivers/radeon/radeon_llvm.h b/src/gallium/drivers/radeon/radeon_llvm.h
> index 7a32bb0..d1b6d17 100644
> --- a/src/gallium/drivers/radeon/radeon_llvm.h
> +++ b/src/gallium/drivers/radeon/radeon_llvm.h
> @@ -142,6 +142,16 @@ static inline LLVMValueRef bitcast(
> return value;
> }
>
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +void radeon_llvm_lock(void);
> +void radeon_llvm_unlock(void);
> +
> +#ifdef __cplusplus
> +}
> +#endif
>
> void radeon_llvm_context_init(struct radeon_llvm_context * ctx);
>
> diff --git a/src/gallium/drivers/radeon/radeon_llvm_emit.cpp b/src/gallium/drivers/radeon/radeon_llvm_emit.cpp
> index 89130b3..39b4640 100644
> --- a/src/gallium/drivers/radeon/radeon_llvm_emit.cpp
> +++ b/src/gallium/drivers/radeon/radeon_llvm_emit.cpp
> @@ -48,15 +48,19 @@
>
> using namespace llvm;
>
> -#ifndef EXTERNAL_LLVM
> extern "C" {
>
> +#ifndef EXTERNAL_LLVM
> void LLVMInitializeAMDGPUTargetMC(void);
> void LLVMInitializeAMDGPUTarget(void);
> void LLVMInitializeAMDGPUTargetInfo(void);
> -}
> #endif
>
> +void radeon_llvm_lock();
> +void radeon_llvm_unlock();
> +
> +}
> +
> /**
> * Compile an LLVM module to machine code.
> *
> @@ -68,6 +72,8 @@ radeon_llvm_compile(LLVMModuleRef M, unsigned char ** bytes,
> unsigned * byte_count, const char * gpu_family,
> unsigned dump) {
>
> + radeon_llvm_lock();
> +
> Triple AMDGPUTriple(sys::getDefaultTargetTriple());
>
> #ifdef EXTERNAL_LLVM
> @@ -82,6 +88,7 @@ radeon_llvm_compile(LLVMModuleRef M, unsigned char ** bytes,
> std::string err;
> const Target * AMDGPUTarget = TargetRegistry::lookupTarget("r600", err);
> if(!AMDGPUTarget) {
> + radeon_llvm_unlock();
> fprintf(stderr, "Can't find target: %s\n", err.c_str());
> return 1;
> }
> @@ -119,6 +126,7 @@ radeon_llvm_compile(LLVMModuleRef M, unsigned char ** bytes,
> /* Optional extra paramater true / false to disable verify */
> if (AMDGPUTargetMachine.addPassesToEmitFile(PM, out, TargetMachine::CGFT_AssemblyFile,
> true)){
> + radeon_llvm_unlock();
> fprintf(stderr, "AddingPasses failed.\n");
> return 1;
> }
> @@ -131,5 +139,7 @@ radeon_llvm_compile(LLVMModuleRef M, unsigned char ** bytes,
> memcpy(*bytes, data.c_str(), data.length() * sizeof(unsigned char));
> *byte_count = data.length();
>
> + radeon_llvm_unlock();
> +
> return 0;
> }
> diff --git a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c b/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> index 641d277..95dd419 100644
> --- a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> +++ b/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> @@ -36,10 +36,26 @@
> #include "util/u_math.h"
> #include "util/u_memory.h"
> #include "util/u_debug.h"
> +#include "os/os_thread.h"
>
> #include <llvm-c/Core.h>
> #include <llvm-c/Transforms/Scalar.h>
>
> +/** llvm with its magnitudes of global variables and factories
> + * appears not to be thread safe. Until then, we sadly need a mutex.
> + */
> +pipe_static_mutex(llvm_mutex);
> +
> +void radeon_llvm_lock()
> +{
> + pipe_mutex_lock(llvm_mutex);
> +}
> +
> +void radeon_llvm_unlock()
> +{
> + pipe_mutex_unlock(llvm_mutex);
> +}
> +
> static struct radeon_llvm_loop * get_current_loop(struct radeon_llvm_context * ctx)
> {
> return ctx->loop_depth > 0 ? ctx->loop + (ctx->loop_depth - 1) : NULL;
> @@ -989,6 +1005,8 @@ void radeon_llvm_context_init(struct radeon_llvm_context * ctx)
> LLVMTypeRef main_fn_type;
> LLVMBasicBlockRef main_fn_body;
>
> + radeon_llvm_lock();
> +
> /* Initialize the gallivm object:
> * We are only using the module, context, and builder fields of this struct.
> * This should be enough for us to be able to pass our gallivm struct to the
> @@ -1166,11 +1184,16 @@ void radeon_llvm_context_init(struct radeon_llvm_context * ctx)
>
> bld_base->rsq_action.emit = build_tgsi_intrinsic_nomem;
> bld_base->rsq_action.intr_name = "llvm.AMDGPU.rsq";
> +
> + radeon_llvm_unlock();
> }
>
> void radeon_llvm_finalize_module(struct radeon_llvm_context * ctx)
> {
> struct gallivm_state * gallivm = ctx->soa.bld_base.base.gallivm;
> +
> + radeon_llvm_lock();
> +
> /* End the main function with Return*/
> LLVMBuildRetVoid(gallivm->builder);
>
> @@ -1191,10 +1214,15 @@ void radeon_llvm_finalize_module(struct radeon_llvm_context * ctx)
> LLVMDisposeBuilder(gallivm->builder);
> LLVMDisposePassManager(gallivm->passmgr);
>
> + radeon_llvm_unlock();
> }
>
> void radeon_llvm_dispose(struct radeon_llvm_context * ctx)
> {
> + radeon_llvm_lock();
> +
> LLVMDisposeModule(ctx->soa.bld_base.base.gallivm->module);
> LLVMContextDispose(ctx->soa.bld_base.base.gallivm->context);
> +
> + radeon_llvm_unlock();
> }
> --
> 1.7.11.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list