llvmpipe: Make a llvmpipe OpenGL context thread safe.
authorMathias Fröhlich <Mathias.Froehlich@gmx.net>
Sun, 13 Jul 2014 10:49:41 +0000 (12:49 +0200)
committerMathias Fröhlich <Mathias.Froehlich@gmx.net>
Tue, 30 Sep 2014 18:51:02 +0000 (20:51 +0200)
This fixes the remaining problem with the recently introduced
global jit memory manager. This change again uses a memory manager
that is local to gallivm_state. This implementation still frees
the majority of the memory immediately after compilation.
Only the generated code is deferred until this code is no longer used.

This change and the previous one using private LLVMContext instances
I can now safely run several independent OpenGL contexts driven
by llvmpipe from different threads.

v3: Rebase on llvm-3.6 compile fixes.

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Signed-off-by: Mathias Froehlich <Mathias.Froehlich@web.de>
src/gallium/auxiliary/gallivm/lp_bld_init.c
src/gallium/auxiliary/gallivm/lp_bld_init.h
src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
src/gallium/auxiliary/gallivm/lp_bld_misc.h

index 8a484978f1e1be6b932c19641c9bc0a576872938..4e4aecb102cfac89e9b8fe175281d89a90e9311a 100644 (file)
@@ -219,6 +219,10 @@ gallivm_free_code(struct gallivm_state *gallivm)
    assert(!gallivm->engine);
    lp_free_generated_code(gallivm->code);
    gallivm->code = NULL;
+#if HAVE_LLVM < 0x0306
+   LLVMDisposeMCJITMemoryManager(gallivm->memorymgr);
+   gallivm->memorymgr = NULL;
+#endif
 }
 
 
@@ -240,6 +244,7 @@ init_gallivm_engine(struct gallivm_state *gallivm)
       ret = lp_build_create_jit_compiler_for_module(&gallivm->engine,
                                                     &gallivm->code,
                                                     gallivm->module,
+                                                    gallivm->memorymgr,
                                                     (unsigned) optlevel,
                                                     USE_MCJIT,
                                                     &error);
@@ -312,6 +317,14 @@ init_gallivm_state(struct gallivm_state *gallivm, const char *name,
    if (!gallivm->builder)
       goto fail;
 
+#if HAVE_LLVM < 0x0306
+   gallivm->memorymgr = lp_get_default_memory_manager();
+   if (!gallivm->memorymgr)
+      goto fail;
+#else
+   gallivm->memorymgr = 0;
+#endif
+
    /* FIXME: MC-JIT only allows compiling one module at a time, and it must be
     * complete when MC-JIT is created. So defer the MC-JIT engine creation for
     * now.
index 6e9f52554a3d0e989ba3a4f4b163e44b569acb23..9e50f88931d07469f15266e12600381bda7d37bd 100644 (file)
@@ -44,6 +44,7 @@ struct gallivm_state
    LLVMPassManagerRef passmgr;
    LLVMContextRef context;
    LLVMBuilderRef builder;
+   LLVMMCJITMemoryManagerRef memorymgr;
    struct lp_generated_code *code;
    unsigned compiled;
 };
index 06d29bcceeb8b24624657addc5474489c535aaf0..c173ab657b95f67a699ef5746aaf5ba22a30fad9 100644 (file)
@@ -322,15 +322,15 @@ class DelegatingJITMemoryManager : public llvm::JITMemoryManager {
  */
 class ShaderMemoryManager : public DelegatingJITMemoryManager {
 
-   static llvm::JITMemoryManager *TheMM;
-   static unsigned NumUsers;
+   llvm::JITMemoryManager *TheMM;
 
    struct GeneratedCode {
       typedef std::vector<void *> Vec;
       Vec FunctionBody, ExceptionTable;
+      llvm::JITMemoryManager *TheMM;
 
-      GeneratedCode() {
-         ++NumUsers;
+      GeneratedCode(llvm::JITMemoryManager *MM) {
+         TheMM = MM;
       }
 
       ~GeneratedCode() {
@@ -347,27 +347,20 @@ class ShaderMemoryManager : public DelegatingJITMemoryManager {
         for ( i = ExceptionTable.begin(); i != ExceptionTable.end(); ++i )
            TheMM->deallocateExceptionTable(*i);
 #endif
-         --NumUsers;
-         if (NumUsers == 0) {
-            delete TheMM;
-            TheMM = 0;
-         }
       }
    };
 
    GeneratedCode *code;
 
    llvm::JITMemoryManager *mgr() const {
-      if (!TheMM) {
-         TheMM = CreateDefaultMemManager();
-      }
       return TheMM;
    }
 
    public:
 
-      ShaderMemoryManager() {
-         code = new GeneratedCode;
+      ShaderMemoryManager(llvm::JITMemoryManager* MM) {
+         TheMM = MM;
+         code = new GeneratedCode(MM);
       }
 
       virtual ~ShaderMemoryManager() {
@@ -398,9 +391,6 @@ class ShaderMemoryManager : public DelegatingJITMemoryManager {
       }
 };
 
-llvm::JITMemoryManager *ShaderMemoryManager::TheMM = 0;
-unsigned ShaderMemoryManager::NumUsers = 0;
-
 #endif
 
 /**
@@ -418,6 +408,7 @@ LLVMBool
 lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
                                         lp_generated_code **OutCode,
                                         LLVMModuleRef M,
+                                        LLVMMCJITMemoryManagerRef CMM,
                                         unsigned OptLevel,
                                         int useMCJIT,
                                         char **OutError)
@@ -510,7 +501,8 @@ lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
    builder.setMCPU(MCPU);
 #endif
 
-   ShaderMemoryManager *MM = new ShaderMemoryManager();
+   llvm::JITMemoryManager* JMM = reinterpret_cast<llvm::JITMemoryManager*>(CMM);
+   ShaderMemoryManager *MM = new ShaderMemoryManager(JMM);
    *OutCode = MM->getGeneratedCode();
 
    builder.setJITMemoryManager(MM);
@@ -549,3 +541,16 @@ lp_free_generated_code(struct lp_generated_code *code)
    ShaderMemoryManager::freeGeneratedCode(code);
 #endif
 }
+
+extern "C"
+LLVMMCJITMemoryManagerRef
+lp_get_default_memory_manager()
+{
+#if HAVE_LLVM < 0x0306
+   llvm::JITMemoryManager *mm;
+   mm = llvm::JITMemoryManager::CreateDefaultMemManager();
+   return reinterpret_cast<LLVMMCJITMemoryManagerRef>(mm);
+#else
+   return 0;
+#endif
+}
index 64d2a04190f0b52df421184861b8c061048475b5..40d3e797b4a0caac3fd155e467be80be1ae40533 100644 (file)
@@ -54,6 +54,7 @@ extern int
 lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
                                         struct lp_generated_code **OutCode,
                                         LLVMModuleRef M,
+                                        LLVMMCJITMemoryManagerRef MM,
                                         unsigned OptLevel,
                                         int useMCJIT,
                                         char **OutError);
@@ -61,6 +62,8 @@ lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT,
 extern void
 lp_free_generated_code(struct lp_generated_code *code);
 
+extern LLVMMCJITMemoryManagerRef
+lp_get_default_memory_manager();
 
 #ifdef __cplusplus
 }