Skip to content

Commit

Permalink
Revert "Remove JULIA_ENABLE_THREADS feature flag (#32685)"
Browse files Browse the repository at this point in the history
This reverts commit a18ab97.
  • Loading branch information
vchuravy committed Dec 3, 2019
1 parent a7aba54 commit 8efb95c
Show file tree
Hide file tree
Showing 22 changed files with 242 additions and 39 deletions.
2 changes: 1 addition & 1 deletion Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,7 @@ endif

# Threads
ifneq ($(JULIA_THREADS), 0)
JCPPFLAGS += -DJULIA_NUM_THREADS=$(JULIA_THREADS)
JCPPFLAGS += -DJULIA_ENABLE_THREADING -DJULIA_NUM_THREADS=$(JULIA_THREADS)
endif

# Intel VTune Amplifier
Expand Down
3 changes: 3 additions & 0 deletions contrib/julia-config.jl
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ function cflags(doframework)
include = shell_escape(includeDir())
print(flags, " -I", include)
end
if threadingOn()
print(flags, " -DJULIA_ENABLE_THREADING=1")
end
if Sys.isunix()
print(flags, " -fPIC")
end
Expand Down
1 change: 1 addition & 0 deletions doc/src/manual/embedding.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ We start by opening Visual Studio and creating a new Console Application project
header file, add the following lines at the end:

```c
#define JULIA_ENABLE_THREADING
#include <julia.h>
```

Expand Down
20 changes: 20 additions & 0 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ NOINLINE uintptr_t gc_get_stack_ptr(void)

#define should_timeout() 0

#ifdef JULIA_ENABLE_THREADING
static void jl_gc_wait_for_the_world(void)
{
if (jl_n_threads > 1)
Expand All @@ -206,6 +207,11 @@ static void jl_gc_wait_for_the_world(void)
}
}
}
#else
static inline void jl_gc_wait_for_the_world(void)
{
}
#endif

// malloc wrappers, aligned allocation

Expand Down Expand Up @@ -1135,7 +1141,9 @@ JL_DLLEXPORT jl_value_t *jl_gc_pool_alloc(jl_ptls_t ptls, int pool_offset,
// to workaround a llvm bug.
// Ref https://llvm.org/bugs/show_bug.cgi?id=27190
jl_gc_pool_t *p = (jl_gc_pool_t*)((char*)ptls + pool_offset);
#ifdef JULIA_ENABLE_THREADING
assert(ptls->gc_state == 0);
#endif
#ifdef MEMDEBUG
return jl_gc_big_alloc(ptls, osize);
#endif
Expand Down Expand Up @@ -1490,6 +1498,12 @@ JL_DLLEXPORT void jl_gc_queue_root(jl_value_t *ptr)
{
jl_ptls_t ptls = jl_get_ptls_states();
jl_taggedvalue_t *o = jl_astaggedvalue(ptr);
#ifndef JULIA_ENABLE_THREADING
// Disable this assert since it can happen with multithreading (same
// with the ones in gc_queue_binding) when two threads are writing
// to the same object.
assert(o->bits.gc == GC_OLD_MARKED);
#endif
// The modification of the `gc_bits` is not atomic but it
// should be safe here since GC is not allowed to run here and we only
// write GC_OLD to the GC bits outside GC. This could cause
Expand All @@ -1503,6 +1517,10 @@ void gc_queue_binding(jl_binding_t *bnd)
{
jl_ptls_t ptls = jl_get_ptls_states();
jl_taggedvalue_t *buf = jl_astaggedvalue(bnd);
#ifndef JULIA_ENABLE_THREADING
// Will fail for multithreading. See `jl_gc_queue_root`
assert(buf->bits.gc == GC_OLD_MARKED);
#endif
buf->bits.gc = GC_MARKED;
arraylist_push(&ptls->heap.rem_bindings, bnd);
}
Expand Down Expand Up @@ -2520,7 +2538,9 @@ static void mark_roots(jl_gc_mark_cache_t *gc_cache, jl_gc_mark_sp_t *sp)
gc_mark_queue_obj(gc_cache, sp, jl_main_module);

// tasks
#ifdef JULIA_ENABLE_THREADING
jl_gc_mark_enqueued_tasks(gc_cache, sp);
#endif

// invisible builtin values
if (jl_an_empty_vec_any != NULL)
Expand Down
24 changes: 15 additions & 9 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,20 @@ void jl_init_stack_limits(int ismaster, void **stack_lo, void **stack_hi)
#ifdef _OS_WINDOWS_
(void)ismaster;
// https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
# ifdef _P64
#ifdef _P64
*stack_hi = (void**)__readgsqword(0x08); // Stack Base / Bottom of stack (high address)
*stack_lo = (void**)__readgsqword(0x10); // Stack Limit / Ceiling of stack (low address)
# else // !_P64
#else
*stack_hi = (void**)__readfsdword(0x04); // Stack Base / Bottom of stack (high address)
*stack_lo = (void**)__readfsdword(0x08); // Stack Limit / Ceiling of stack (low address)
# endif // _P64
#else // !_OS_WINDOWS_
#endif
#else
# ifdef JULIA_ENABLE_THREADING
// Only use pthread_*_np functions to get stack address for non-master
// threads since it seems to return bogus values for master thread on Linux
// and possibly OSX.
if (!ismaster) {
# if defined(_OS_LINUX_)
# if defined(_OS_LINUX_)
pthread_attr_t attr;
pthread_getattr_np(pthread_self(), &attr);
void *stackaddr;
Expand All @@ -88,7 +89,7 @@ void jl_init_stack_limits(int ismaster, void **stack_lo, void **stack_hi)
*stack_lo = (void*)stackaddr;
*stack_hi = (void*)&stacksize;
return;
# elif defined(_OS_DARWIN_)
# elif defined(_OS_DARWIN_)
extern void *pthread_get_stackaddr_np(pthread_t thread);
extern size_t pthread_get_stacksize_np(pthread_t thread);
pthread_t thread = pthread_self();
Expand All @@ -97,7 +98,7 @@ void jl_init_stack_limits(int ismaster, void **stack_lo, void **stack_hi)
*stack_lo = (void*)stackaddr;
*stack_hi = (void*)&stacksize;
return;
# elif defined(_OS_FREEBSD_)
# elif defined(_OS_FREEBSD_)
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_get_np(pthread_self(), &attr);
Expand All @@ -108,10 +109,13 @@ void jl_init_stack_limits(int ismaster, void **stack_lo, void **stack_hi)
*stack_lo = (void*)stackaddr;
*stack_hi = (void*)&stacksize;
return;
# else
# else
# warning "Getting precise stack size for thread is not supported."
# endif
# endif
}
# else
(void)ismaster;
# endif
struct rlimit rl;
getrlimit(RLIMIT_STACK, &rl);
size_t stacksize = rl.rlim_cur;
Expand Down Expand Up @@ -626,8 +630,10 @@ static void jl_set_io_wait(int v)
void _julia_init(JL_IMAGE_SEARCH rel)
{
jl_init_timing();
#ifdef JULIA_ENABLE_THREADING
// Make sure we finalize the tls callback before starting any threads.
jl_get_ptls_states_getter();
#endif
jl_ptls_t ptls = jl_get_ptls_states();
(void)ptls; assert(ptls); // make sure early that we have initialized ptls
jl_safepoint_init();
Expand Down
9 changes: 7 additions & 2 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1540,11 +1540,12 @@ typedef enum {
JL_IMAGE_JULIA_HOME = 1,
//JL_IMAGE_LIBJULIA = 2,
} JL_IMAGE_SEARCH;
#ifdef JULIA_ENABLE_THREADING
// this helps turn threading compilation mismatches into linker errors
#define julia_init julia_init__threading
#define jl_init jl_init__threading
#define jl_init_with_image jl_init_with_image__threading

#endif
JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel);
JL_DLLEXPORT void jl_init(void);
JL_DLLEXPORT void jl_init_with_image(const char *julia_bindir,
Expand Down Expand Up @@ -1680,7 +1681,9 @@ typedef struct _jl_handler_t {
jl_gcframe_t *gcstack;
struct _jl_handler_t *prev;
int8_t gc_state;
#ifdef JULIA_ENABLE_THREADING
size_t locks_len;
#endif
sig_atomic_t defer_signal;
int finalizers_inhibited;
jl_timing_block_t *timing_stack;
Expand Down Expand Up @@ -1722,8 +1725,10 @@ typedef struct _jl_task_t {
int16_t tid;
/* for the multiqueue */
int16_t prio;
#ifdef JULIA_ENABLE_THREADING
// This is statically initialized when the task is not holding any locks
arraylist_t locks;
#endif
jl_timing_block_t *timing_stack;
} jl_task_t;

Expand Down Expand Up @@ -2037,7 +2042,7 @@ typedef struct {
extern JL_DLLEXPORT jl_cgparams_t jl_default_cgparams;
extern JL_DLLEXPORT int jl_default_debug_info_kind;

#if !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_)
#if defined(JULIA_ENABLE_THREADING) && !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_)
#define JULIA_DEFINE_FAST_TLS() \
JL_DLLEXPORT JL_CONST_FUNC jl_ptls_t jl_get_ptls_states_static(void) \
{ \
Expand Down
5 changes: 3 additions & 2 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ void jl_safepoint_defer_sigint(void);
int jl_safepoint_consume_sigint(void);
void jl_wake_libuv(void);

#if !defined(__clang_analyzer__)
#if defined(JULIA_ENABLE_THREADING) && !defined(__clang_analyzer__)
jl_get_ptls_states_func jl_get_ptls_states_getter(void);
static inline void jl_set_gc_and_wait(void)
{
Expand Down Expand Up @@ -971,7 +971,8 @@ extern jl_mutex_t typecache_lock;
extern jl_mutex_t codegen_lock;
extern jl_mutex_t safepoint_lock;

#if defined(__APPLE__)
#if defined(__APPLE__) && defined(JULIA_ENABLE_THREADING)
// -- gc.c -- //
void jl_mach_gc_end(void);
#endif

Expand Down
14 changes: 14 additions & 0 deletions src/julia_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
// Nonetheless, we define JL_THREAD and use it to give advanced notice to
// maintainers of what eventual threading support will change.

// JULIA_ENABLE_THREADING is switched on in Make.inc if JULIA_THREADS is
// set (in Make.user)

// Options for task switching algorithm (in order of preference):
// JL_HAVE_ASM -- mostly setjmp
// JL_HAVE_ASYNCIFY -- task switching based on the binaryen asyncify transform
Expand Down Expand Up @@ -272,6 +275,16 @@ void jl_sigint_safepoint(jl_ptls_t tls) JL_NOTSAFEPOINT;
(void)safepoint_load; \
} while (0)
#endif
#ifndef JULIA_ENABLE_THREADING
#define jl_gc_state(ptls) ((int8_t)0)
STATIC_INLINE int8_t jl_gc_state_set(jl_ptls_t ptls, int8_t state,
int8_t old_state)
{
(void)ptls;
(void)state;
return old_state;
}
#else // ifndef JULIA_ENABLE_THREADING
// Make sure jl_gc_state() is always a rvalue
#define jl_gc_state(ptls) ((int8_t)ptls->gc_state)
STATIC_INLINE int8_t jl_gc_state_set(jl_ptls_t ptls, int8_t state,
Expand All @@ -284,6 +297,7 @@ STATIC_INLINE int8_t jl_gc_state_set(jl_ptls_t ptls, int8_t state,
jl_gc_safepoint_(ptls);
return old_state;
}
#endif // ifndef JULIA_ENABLE_THREADING
STATIC_INLINE int8_t jl_gc_state_save_and_set(jl_ptls_t ptls,
int8_t state)
{
Expand Down
22 changes: 20 additions & 2 deletions src/llvm-ptls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/MDBuilder.h>

#include <llvm/IR/InlineAsm.h>
#include <llvm/Transforms/Utils/BasicBlockUtils.h>
#if defined(JULIA_ENABLE_THREADING)
# include <llvm/IR/InlineAsm.h>
# include <llvm/Transforms/Utils/BasicBlockUtils.h>
#endif

#include "julia.h"
#include "julia_internal.h"
Expand Down Expand Up @@ -59,16 +61,21 @@ struct LowerPTLS: public ModulePass {
Type *T_int8;
Type *T_size;
PointerType *T_pint8;
#ifdef JULIA_ENABLE_THREADING
GlobalVariable *ptls_slot{nullptr};
GlobalVariable *ptls_offset{nullptr};
void set_ptls_attrs(CallInst *ptlsStates) const;
Instruction *emit_ptls_tp(Value *offset, Instruction *insertBefore) const;
template<typename T> T *add_comdat(T *G) const;
GlobalVariable *create_aliased_global(Type *T, StringRef name) const;
#else
GlobalVariable *static_tls;
#endif
void fix_ptls_use(CallInst *ptlsStates);
bool runOnModule(Module &M) override;
};

#ifdef JULIA_ENABLE_THREADING
void LowerPTLS::set_ptls_attrs(CallInst *ptlsStates) const
{
ptlsStates->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
Expand Down Expand Up @@ -175,6 +182,7 @@ inline T *LowerPTLS::add_comdat(T *G) const
#endif
return G;
}
#endif

void LowerPTLS::fix_ptls_use(CallInst *ptlsStates)
{
Expand All @@ -183,6 +191,7 @@ void LowerPTLS::fix_ptls_use(CallInst *ptlsStates)
return;
}

#ifdef JULIA_ENABLE_THREADING
if (imaging_mode) {
if (jl_tls_elf_support) {
// if (offset != 0)
Expand Down Expand Up @@ -236,6 +245,10 @@ void LowerPTLS::fix_ptls_use(CallInst *ptlsStates)
ptlsStates->setCalledFunction(ptlsStates->getFunctionType(), ConstantExpr::getIntToPtr(val, T_ptls_getter));
set_ptls_attrs(ptlsStates);
}
#else
ptlsStates->replaceAllUsesWith(static_tls);
ptlsStates->eraseFromParent();
#endif
}

bool LowerPTLS::runOnModule(Module &_M)
Expand All @@ -255,10 +268,15 @@ bool LowerPTLS::runOnModule(Module &_M)
T_int8 = Type::getInt8Ty(*ctx);
T_size = sizeof(size_t) == 8 ? Type::getInt64Ty(*ctx) : Type::getInt32Ty(*ctx);
T_pint8 = T_int8->getPointerTo();
#ifdef JULIA_ENABLE_THREADING
if (imaging_mode) {
ptls_slot = create_aliased_global(T_ptls_getter, "jl_get_ptls_states_slot");
ptls_offset = create_aliased_global(T_size, "jl_tls_offset");
}
#else
static_tls = new GlobalVariable(*M, T_ppjlvalue, false, GlobalVariable::ExternalLinkage,
NULL, "jl_tls_states");
#endif

for (auto it = ptls_getter->user_begin(); it != ptls_getter->user_end();) {
auto call = cast<CallInst>(*it);
Expand Down
30 changes: 30 additions & 0 deletions src/locks.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static inline void jl_mutex_lock_nogc(jl_mutex_t *lock) JL_NOTSAFEPOINT
#endif
}

#ifdef JULIA_ENABLE_THREADING
static inline void jl_lock_frame_push(jl_mutex_t *lock)
{
jl_ptls_t ptls = jl_get_ptls_states();
Expand All @@ -74,6 +75,15 @@ static inline void jl_lock_frame_pop(void)
ptls->current_task->locks.len--;
}
}
#else
static inline void jl_lock_frame_push(jl_mutex_t *lock)
{
(void)lock;
}
static inline void jl_lock_frame_pop(void)
{
}
#endif // ifndef JULIA_ENABLE_THREADING

#define JL_SIGATOMIC_BEGIN() do { \
jl_get_ptls_states()->defer_signal++; \
Expand Down Expand Up @@ -171,11 +181,31 @@ static inline void jl_mutex_init(jl_mutex_t *lock) JL_NOTSAFEPOINT
lock->count = 0;
}

#ifdef JULIA_ENABLE_THREADING
#define JL_MUTEX_INIT(m) jl_mutex_init(m)
#define JL_LOCK(m) jl_mutex_lock(m)
#define JL_UNLOCK(m) jl_mutex_unlock(m)
#define JL_LOCK_NOGC(m) jl_mutex_lock_nogc(m)
#define JL_UNLOCK_NOGC(m) jl_mutex_unlock_nogc(m)
#else // JULIA_ENABLE_THREADING
static inline void jl_mutex_check_type(jl_mutex_t *m) JL_NOTSAFEPOINT
{
(void)m;
}
#define JL_MUTEX_INIT(m) jl_mutex_check_type(m)
#define JL_LOCK(m) do { \
JL_SIGATOMIC_BEGIN(); \
jl_gc_enable_finalizers(jl_get_ptls_states(), 0); \
jl_mutex_check_type(m); \
} while (0)
#define JL_UNLOCK(m) do { \
jl_gc_enable_finalizers(jl_get_ptls_states(), 1); \
jl_mutex_check_type(m); \
JL_SIGATOMIC_END(); \
} while (0)
#define JL_LOCK_NOGC(m) jl_mutex_check_type(m)
#define JL_UNLOCK_NOGC(m) jl_mutex_check_type(m)
#endif // JULIA_ENABLE_THREADING

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 8efb95c

Please sign in to comment.