From 83c62597fc8eb38bf274fa1a3ca03c6adafb4bf9 Mon Sep 17 00:00:00 2001 From: Mathias Fröhlich Date: Thu, 28 Aug 2014 19:49:35 +0200 Subject: llvmpipe: Use two LLVMContexts per OpenGL context instead of a global one. This is one step to make llvmpipe thread safe as mandated by the OpenGL standard. Using the global LLVMContext is obviously a problem for that kind of use pattern. The patch introduces two LLVMContext instances that are private to an OpenGL context and used for all compiles. One is put into struct draw_llvm and the other one into struct llvmpipe_context. Reviewed-by: Jose Fonseca Signed-off-by: Mathias Froehlich --- src/gallium/auxiliary/draw/draw_llvm.c | 15 +++++++++++++-- src/gallium/auxiliary/draw/draw_llvm.h | 2 ++ src/gallium/auxiliary/gallivm/lp_bld_init.c | 28 +++++++--------------------- src/gallium/auxiliary/gallivm/lp_bld_init.h | 2 +- 4 files changed, 23 insertions(+), 24 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 504f3efab2e..8469d6999b1 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -493,6 +493,10 @@ draw_llvm_create(struct draw_context *draw) llvm->draw = draw; + llvm->context = LLVMContextCreate(); + if (!llvm->context) + goto fail; + llvm->nr_variants = 0; make_empty_list(&llvm->vs_variants_list); @@ -500,6 +504,10 @@ draw_llvm_create(struct draw_context *draw) make_empty_list(&llvm->gs_variants_list); return llvm; + +fail: + draw_llvm_destroy(llvm); + return NULL; } @@ -509,6 +517,9 @@ draw_llvm_create(struct draw_context *draw) void draw_llvm_destroy(struct draw_llvm *llvm) { + LLVMContextDispose(llvm->context); + llvm->context = NULL; + /* XXX free other draw_llvm data? */ FREE(llvm); } @@ -540,7 +551,7 @@ draw_llvm_create_variant(struct draw_llvm *llvm, util_snprintf(module_name, sizeof(module_name), "draw_llvm_vs_variant%u", variant->shader->variants_cached); - variant->gallivm = gallivm_create(module_name); + variant->gallivm = gallivm_create(module_name, llvm->context); create_jit_types(variant); @@ -2195,7 +2206,7 @@ draw_gs_llvm_create_variant(struct draw_llvm *llvm, util_snprintf(module_name, sizeof(module_name), "draw_llvm_gs_variant%u", variant->shader->variants_cached); - variant->gallivm = gallivm_create(module_name); + variant->gallivm = gallivm_create(module_name, llvm->context); create_gs_jit_types(variant); diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h index ed97cf72115..a4bd1edcf0d 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.h +++ b/src/gallium/auxiliary/draw/draw_llvm.h @@ -461,6 +461,8 @@ struct llvm_geometry_shader { struct draw_llvm { struct draw_context *draw; + LLVMContextRef context; + struct draw_jit_context jit_context; struct draw_gs_jit_context gs_jit_context; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c index 75ef935eb22..8a484978f1e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c @@ -78,17 +78,6 @@ void LLVMLinkInMCJIT(); #endif -/* - * LLVM has several global caches which pointing/derived from objects - * owned by the context, so if we freeing contexts causes - * memory leaks and false cache hits when these objects are destroyed. - * - * TODO: For thread safety on multi-threaded OpenGL we should use one LLVM - * context per thread, and put them in a pool when threads are destroyed. - */ -#define USE_GLOBAL_CONTEXT 1 - - #ifdef DEBUG unsigned gallivm_debug = 0; @@ -209,8 +198,7 @@ gallivm_free_ir(struct gallivm_state *gallivm) if (gallivm->builder) LLVMDisposeBuilder(gallivm->builder); - if (!USE_GLOBAL_CONTEXT && gallivm->context) - LLVMContextDispose(gallivm->context); + /* The LLVMContext should be owned by the parent of gallivm. */ gallivm->engine = NULL; gallivm->target = NULL; @@ -301,7 +289,8 @@ fail: * \return TRUE for success, FALSE for failure */ static boolean -init_gallivm_state(struct gallivm_state *gallivm, const char *name) +init_gallivm_state(struct gallivm_state *gallivm, const char *name, + LLVMContextRef context) { assert(!gallivm->context); assert(!gallivm->module); @@ -309,11 +298,8 @@ init_gallivm_state(struct gallivm_state *gallivm, const char *name) if (!lp_build_init()) return FALSE; - if (USE_GLOBAL_CONTEXT) { - gallivm->context = LLVMGetGlobalContext(); - } else { - gallivm->context = LLVMContextCreate(); - } + gallivm->context = context; + if (!gallivm->context) goto fail; @@ -495,13 +481,13 @@ lp_build_init(void) * Create a new gallivm_state object. */ struct gallivm_state * -gallivm_create(const char *name) +gallivm_create(const char *name, LLVMContextRef context) { struct gallivm_state *gallivm; gallivm = CALLOC_STRUCT(gallivm_state); if (gallivm) { - if (!init_gallivm_state(gallivm, name)) { + if (!init_gallivm_state(gallivm, name, context)) { FREE(gallivm); gallivm = NULL; } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.h b/src/gallium/auxiliary/gallivm/lp_bld_init.h index 64c5278c24e..6e9f52554a3 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.h @@ -54,7 +54,7 @@ lp_build_init(void); struct gallivm_state * -gallivm_create(const char *name); +gallivm_create(const char *name, LLVMContextRef context); void gallivm_destroy(struct gallivm_state *gallivm); -- cgit v1.2.3