From 393bddc46d2b0a4741d515ff0341b24cd2900cff Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 21 Nov 2015 10:40:19 -0500 Subject: [PATCH] WIP: threading without LLVM patch --- Make.inc | 8 ++++---- src/cgutils.cpp | 21 +++++++++++++++++++-- src/codegen.cpp | 44 +++++++++++++++++++++++++------------------- src/gc.c | 2 +- src/julia.h | 39 +++++++++++++++++++++++---------------- src/julia_internal.h | 2 +- src/task.c | 11 +++-------- src/threading.c | 19 ++++++++++++++++++- src/threading.h | 3 +-- 9 files changed, 95 insertions(+), 54 deletions(-) diff --git a/Make.inc b/Make.inc index d0fd4bcbe2d90..8f8d67ed5ca8d 100644 --- a/Make.inc +++ b/Make.inc @@ -276,10 +276,10 @@ DISABLE_ASSERTIONS := -DNDEBUG endif # Threads -ifeq ($(JULIA_THREADS), 1) -LLVM_VER := svn -LLVM_GIT_URL_LLVM := https://github.com/JuliaLang/llvm.git -b jn/tls37 -endif +# ifeq ($(JULIA_THREADS), 1) +# LLVM_VER := svn +# LLVM_GIT_URL_LLVM := https://github.com/JuliaLang/llvm.git -b jn/tls37 +# endif # Compiler specific stuff diff --git a/src/cgutils.cpp b/src/cgutils.cpp index b83a130acb156..425ea381f452c 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -2124,12 +2124,29 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg } } +static Value *emit_ptls_states() +{ +#ifndef JULIA_ENABLE_THREADING + return builder.CreateBitCast(prepare_global(jltls_states_var), T_ppint8); +#else + return builder.CreateCall(prepare_call(jltls_states_func)); +#endif +} + static Value *emit_pgcstack() { - return prepare_global(jlpgcstack_var); + Value * addr = emit_nthptr_addr( + emit_ptls_states(), + (ssize_t)(offsetof(jl_tls_states_t, pgcstack) / sizeof(void*))); + return builder.CreateBitCast(addr, PointerType::get(T_ppjlvalue, 0), + "jl_pgcstack"); } static Value *emit_exc_in_transit() { - return prepare_global(jlexc_var); + Value * addr = emit_nthptr_addr( + emit_ptls_states(), + (ssize_t)(offsetof(jl_tls_states_t, + exception_in_transit) / sizeof(void*))); + return builder.CreateBitCast(addr, T_ppjlvalue, "jl_exception_in_transit"); } diff --git a/src/codegen.cpp b/src/codegen.cpp index 8844b8273a4d2..cc066521e08c2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -447,8 +447,6 @@ static GlobalVariable *jlemptytuple_var; #ifdef JL_NEED_FLOATTEMP_VAR static GlobalVariable *jlfloattemp_var; #endif -static GlobalVariable *jlpgcstack_var; -static GlobalVariable *jlexc_var; static GlobalVariable *jldiverr_var; static GlobalVariable *jlundeferr_var; static GlobalVariable *jldomerr_var; @@ -467,6 +465,12 @@ extern JITMemoryManager* createJITMemoryManagerWin(); extern RTDyldMemoryManager* createRTDyldMemoryManagerOSX(); #endif +#ifndef JULIA_ENABLE_THREADING +static GlobalVariable *jltls_states_var; +#else +static Function *jltls_states_func; +#endif + // important functions static Function *jlnew_func; static Function *jlthrow_func; @@ -5574,23 +5578,6 @@ static void init_julia_llvm_env(Module *m) "jl_array_t"); jl_parray_llvmt = PointerType::get(jl_array_llvmt,0); -#ifdef JULIA_ENABLE_THREADING -#define JL_THREAD_MODEL ,GlobalValue::GeneralDynamicTLSModel -#else -#define JL_THREAD_MODEL -#endif - jlpgcstack_var = - new GlobalVariable(*m, T_ppjlvalue, - false, GlobalVariable::ExternalLinkage, - NULL, "jl_pgcstack", NULL JL_THREAD_MODEL); - add_named_global(jlpgcstack_var, jl_dlsym(jl_dl_handle, "jl_pgcstack")); - - jlexc_var = - new GlobalVariable(*m, T_pjlvalue, - false, GlobalVariable::ExternalLinkage, - NULL, "jl_exception_in_transit", NULL JL_THREAD_MODEL); - add_named_global(jlexc_var, jl_dlsym(jl_dl_handle, "jl_exception_in_transit")); - global_to_llvm("__stack_chk_guard", (void*)&__stack_chk_guard, m); Function *jl__stack_chk_fail = Function::Create(FunctionType::get(T_void, false), @@ -5640,6 +5627,25 @@ static void init_julia_llvm_env(Module *m) "jl_float_temp")); #endif +#ifndef JULIA_ENABLE_THREADING + jltls_states_var = + new GlobalVariable(*m, ArrayType::get(T_int8, sizeof(jl_tls_states_t)), + false, GlobalVariable::ExternalLinkage, + NULL, "jl_tls_states"); + add_named_global(jltls_states_var, (void*)&jl_tls_states); +#else + jltls_states_func = Function::Create(FunctionType::get(T_ppint8, false), + Function::ExternalLinkage, + "jl_get_ptls_states", m); + jltls_states_func->setAttributes( + jltls_states_func->getAttributes() + .addAttribute(jltls_states_func->getContext(), + AttributeSet::FunctionIndex, Attribute::ReadNone) + .addAttribute(jltls_states_func->getContext(), + AttributeSet::FunctionIndex, Attribute::NoUnwind)); + add_named_global(jltls_states_func, (void*)&jl_get_ptls_states); +#endif + std::vector args1(0); args1.push_back(T_pint8); jlerror_func = diff --git a/src/gc.c b/src/gc.c index 7ad24c86481c2..643e3ddc54198 100644 --- a/src/gc.c +++ b/src/gc.c @@ -251,7 +251,7 @@ typedef struct { // In the single-threaded version, they are essentially noops, but nonetheless // serve to check that the thread context macros are being used. #ifdef JULIA_ENABLE_THREADING -static JL_THREAD jl_thread_heap_t *jl_thread_heap; +#define jl_thread_heap (*(jl_thread_heap_t**)&(jl_get_ptls_states()->heap)) #define FOR_EACH_HEAP() \ for (jl_each_heap_index_t __current_heap_idx = {jl_n_threads, NULL}; \ --current_heap_index >= 0 && \ diff --git a/src/julia.h b/src/julia.h index 921e2aacc8c74..7e1ff46101be1 100644 --- a/src/julia.h +++ b/src/julia.h @@ -64,17 +64,6 @@ extern "C" { // JULIA_ENABLE_THREADING is switched on in Make.inc if JULIA_THREADS is // set (in Make.user) -#ifndef JULIA_ENABLE_THREADING -// Definition for compiling non-thread-safe Julia. -# define JL_THREAD -#elif !defined(_OS_WINDOWS_) -// Definition for compiling Julia on platforms with GCC __thread. -# define JL_THREAD __thread -#else -// Definition for compiling Julia on Windows -# define JL_THREAD __declspec(thread) -#endif - DLLEXPORT int16_t jl_threadid(void); DLLEXPORT void *jl_threadgroup(void); DLLEXPORT void jl_cpu_pause(void); @@ -585,7 +574,7 @@ typedef struct _jl_gcframe_t { // jl_value_t *x=NULL, *y=NULL; JL_GC_PUSH2(&x, &y); // x = f(); y = g(); foo(x, y) -extern DLLEXPORT JL_THREAD jl_gcframe_t *jl_pgcstack; +#define jl_pgcstack (jl_get_ptls_states()->pgcstack) #define JL_GC_PUSH1(arg1) \ void *__gc_stkf[] = {(void*)3, jl_pgcstack, arg1}; \ @@ -1485,10 +1474,10 @@ typedef struct { jl_value_t * volatile *ptask_arg_in_transit; } jl_thread_task_state_t; -extern DLLEXPORT JL_THREAD jl_task_t * volatile jl_current_task; -extern DLLEXPORT JL_THREAD jl_task_t *jl_root_task; -extern DLLEXPORT JL_THREAD jl_value_t *jl_exception_in_transit; -extern DLLEXPORT JL_THREAD jl_value_t * volatile jl_task_arg_in_transit; +#define jl_current_task (jl_get_ptls_states()->current_task) +#define jl_root_task (jl_get_ptls_states()->root_task) +#define jl_exception_in_transit (jl_get_ptls_states()->exception_in_transit) +#define jl_task_arg_in_transit (jl_get_ptls_states()->task_arg_in_transit) DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize); DLLEXPORT jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg); @@ -1496,6 +1485,24 @@ DLLEXPORT void NORETURN jl_throw(jl_value_t *e); DLLEXPORT void NORETURN jl_rethrow(void); DLLEXPORT void NORETURN jl_rethrow_other(jl_value_t *e); +typedef struct _jl_tls_states_t { + jl_gcframe_t *pgcstack; + jl_value_t *exception_in_transit; + void *heap; + jl_task_t *volatile current_task; + jl_task_t *root_task; + jl_value_t *volatile task_arg_in_transit; + void *stackbase; + jl_jmp_buf *volatile jmp_target; + jl_jmp_buf base_ctx; // base context of stack + int16_t tid; +} jl_tls_states_t; +DLLEXPORT JL_CONST_FUNC jl_tls_states_t *(jl_get_ptls_states)(void); +#ifndef JULIA_ENABLE_THREADING +extern DLLEXPORT jl_tls_states_t jl_tls_states; +#define jl_get_ptls_states() (&jl_tls_states) +#endif + STATIC_INLINE void jl_eh_restore_state(jl_handler_t *eh) { JL_SIGATOMIC_BEGIN(); diff --git a/src/julia_internal.h b/src/julia_internal.h index 0a6a6af69c171..08d5df42ad51d 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -146,7 +146,7 @@ void jl_init_serializer(void); void _julia_init(JL_IMAGE_SEARCH rel); #ifdef COPY_STACKS -extern JL_THREAD void *jl_stackbase; +#define jl_stackbase (jl_get_ptls_states()->stackbase) #endif void jl_set_stackbase(char *__stk); diff --git a/src/task.c b/src/task.c index fbad9ec93b416..035816a4f0dac 100644 --- a/src/task.c +++ b/src/task.c @@ -138,21 +138,17 @@ static jl_sym_t *runnable_sym; extern size_t jl_page_size; jl_datatype_t *jl_task_type; -DLLEXPORT JL_THREAD jl_task_t * volatile jl_current_task; -JL_THREAD jl_task_t *jl_root_task; -DLLEXPORT JL_THREAD jl_value_t *jl_exception_in_transit; -DLLEXPORT JL_THREAD jl_gcframe_t *jl_pgcstack = NULL; +#define jl_root_task (jl_get_ptls_states()->root_task) #ifdef COPY_STACKS -static JL_THREAD jl_jmp_buf * volatile jl_jmp_target; +#define jl_jmp_target (jl_get_ptls_states()->jmp_target) #if (defined(_CPU_X86_64_) || defined(_CPU_X86_)) && !defined(_COMPILER_MICROSOFT_) #define ASM_COPY_STACKS #endif -JL_THREAD void *jl_stackbase; #ifndef ASM_COPY_STACKS -static JL_THREAD jl_jmp_buf jl_base_ctx; // base context of stack +#define jl_base_ctx (jl_get_ptls_states()->base_ctx) #endif static void NOINLINE save_stack(jl_task_t *t) @@ -359,7 +355,6 @@ static void ctx_switch(jl_task_t *t, jl_jmp_buf *where) //JL_SIGATOMIC_END(); } -JL_THREAD jl_value_t * volatile jl_task_arg_in_transit; extern int jl_in_gc; DLLEXPORT jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg) { diff --git a/src/threading.c b/src/threading.c index e70c352e84b4f..2c778a6b8a470 100644 --- a/src/threading.c +++ b/src/threading.c @@ -34,8 +34,25 @@ extern "C" { #include "threadgroup.h" #include "threading.h" +#ifdef JULIA_ENABLE_THREADING +# if !defined(_COMPILER_MICROSOFT_) +// Definition for compiling Julia on platforms with GCC __thread. +# define JL_THREAD __thread +# else +// Definition for compiling Julia on Windows +# define JL_THREAD __declspec(thread) +# endif +JL_THREAD jl_tls_states_t jl_tls_states; +#else +DLLEXPORT jl_tls_states_t jl_tls_states; +#endif + +DLLEXPORT JL_CONST_FUNC jl_tls_states_t *(jl_get_ptls_states)(void) +{ + return &jl_tls_states; +} + // thread ID -JL_THREAD int16_t ti_tid = 0; DLLEXPORT int jl_n_threads; // # threads we're actually using DLLEXPORT int jl_max_threads; // # threads possible jl_thread_task_state_t *jl_all_task_states; diff --git a/src/threading.h b/src/threading.h index 8b1b803bab636..b5c3938c55251 100644 --- a/src/threading.h +++ b/src/threading.h @@ -14,7 +14,7 @@ extern "C" { #define PROFILE_JL_THREADING 1 // thread ID -extern JL_THREAD int16_t ti_tid; +#define ti_tid (jl_get_ptls_states()->tid) extern jl_thread_task_state_t *jl_all_task_states; extern DLLEXPORT int jl_n_threads; // # threads we're actually using @@ -69,4 +69,3 @@ jl_value_t *ti_runthread(jl_function_t *f, jl_svec_t *args, size_t nargs); #endif #endif /* THREADING_H */ -