llvmpipe: Make a llvmpipe OpenGL context thread safe.

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>
This commit is contained in:
Mathias Fröhlich 2014-07-13 12:49:41 +02:00
parent 83c62597fc
commit d90ff351f3
4 changed files with 40 additions and 18 deletions

View 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.

View File

@ -44,6 +44,7 @@ struct gallivm_state
LLVMPassManagerRef passmgr;
LLVMContextRef context;
LLVMBuilderRef builder;
LLVMMCJITMemoryManagerRef memorymgr;
struct lp_generated_code *code;
unsigned compiled;
};

View 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
}

View 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
}