Skip to content

Commit

Permalink
Enable GC safepoint for non-threading build
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyichao committed May 5, 2016
1 parent c89632e commit ab2f0c1
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 56 deletions.
13 changes: 1 addition & 12 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1243,27 +1243,16 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
assert(!isVa);
assert(nargt == 0);
JL_GC_POP();
#ifdef JULIA_ENABLE_THREADING
#ifdef LLVM39
builder.CreateFence(AtomicOrdering::SequentiallyConsistent, SingleThread);
#else
builder.CreateFence(SequentiallyConsistent, SingleThread);
#endif
Value *addr;
if (imaging_mode) {
assert(ctx->signalPage);
addr = ctx->signalPage;
}
else {
addr = builder.CreateIntToPtr(
ConstantInt::get(T_size, (uintptr_t)jl_gc_signal_page), T_pint8);
}
builder.CreateLoad(addr, true);
builder.CreateLoad(ctx->signalPage, true);
#ifdef LLVM39
builder.CreateFence(AtomicOrdering::SequentiallyConsistent, SingleThread);
#else
builder.CreateFence(SequentiallyConsistent, SingleThread);
#endif
#endif
return ghostValue(jl_void_type);
}
Expand Down
15 changes: 9 additions & 6 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,10 @@ static GlobalVariable *jltls_states_var;
// Imaging mode only
static GlobalVariable *jltls_states_func_ptr = NULL;
static size_t jltls_states_func_idx = 0;
#endif
// Imaging mode only (non-imaging mode use pointer directly)
static GlobalVariable *jl_gc_signal_page_ptr = NULL;
static size_t jl_gc_signal_page_idx = 0;
#endif

// important functions
static Function *jlnew_func;
Expand Down Expand Up @@ -576,9 +577,7 @@ typedef struct {
std::vector<bool> inbounds;

CallInst *ptlsStates;
#ifdef JULIA_ENABLE_THREADING
Value *signalPage;
#endif

llvm::DIBuilder *dbuilder;
bool debug_enabled;
Expand Down Expand Up @@ -3431,12 +3430,14 @@ static void allocate_gc_frame(BasicBlock *b0, jl_codectx_t *ctx)
{
// allocate a placeholder gc instruction
ctx->ptlsStates = builder.CreateCall(prepare_call(jltls_states_func));
#ifdef JULIA_ENABLE_THREADING
if (imaging_mode) {
ctx->signalPage =
tbaa_decorate(tbaa_const, builder.CreateLoad(prepare_global(jl_gc_signal_page_ptr)));
}
#endif
else {
ctx->signalPage = builder.CreateIntToPtr(
ConstantInt::get(T_size, (uintptr_t)jl_gc_signal_page), T_pint8);
}
}

void jl_codegen_finalize_temp_arg(CallInst *ptlsStates, Type *T_pjlvalue,
Expand Down Expand Up @@ -5167,12 +5168,14 @@ static void init_julia_llvm_env(Module *m)
jl_emit_sysimg_slot(m, pfunctype, "jl_get_ptls_states.ptr",
(uintptr_t)jl_get_ptls_states_getter(),
jltls_states_func_idx);
}
#endif
if (imaging_mode) {
jl_gc_signal_page_ptr =
jl_emit_sysimg_slot(m, T_pint8, "jl_gc_signal_page.ptr",
(uintptr_t)jl_gc_signal_page,
jl_gc_signal_page_idx);
}
#endif

std::vector<Type*> args1(0);
args1.push_back(T_pint8);
Expand Down
2 changes: 1 addition & 1 deletion src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,10 @@ static int jl_load_sysimg_so(void)
"jl_ptls_states_getter_idx");
*sysimg_gvars[tls_getter_idx - 1] =
(jl_value_t*)jl_get_ptls_states_getter();
#endif
size_t signal_page_idx = *(size_t*)jl_dlsym(jl_sysimg_handle,
"jl_gc_signal_page_idx");
*sysimg_gvars[signal_page_idx - 1] = (jl_value_t*)jl_gc_signal_page;
#endif
const char *cpu_target = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target");
if (strcmp(cpu_target,jl_options.cpu_target) != 0)
jl_error("Julia and the system image were compiled for different architectures.\n"
Expand Down
42 changes: 21 additions & 21 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,9 +358,29 @@ NOINLINE static uintptr_t gc_get_stack_ptr(void)
// `jl_running_gc` to one on entering the GC and set it back afterward.
static volatile uint64_t jl_gc_running = 0;

#ifdef JULIA_ENABLE_THREADING
JL_DLLEXPORT volatile size_t *jl_gc_signal_page = NULL;

void jl_gc_signal_init(void)
{
// jl_page_size isn't available yet.
#ifdef _OS_WINDOWS_
jl_gc_signal_page = (size_t*)VirtualAlloc(NULL, jl_getpagesize(),
MEM_COMMIT, PAGE_READONLY);
#else
jl_gc_signal_page = (size_t*)mmap(0, jl_getpagesize(), PROT_READ,
MAP_NORESERVE | MAP_PRIVATE |
MAP_ANONYMOUS, -1, 0);
if (jl_gc_signal_page == MAP_FAILED)
jl_gc_signal_page = NULL;
#endif
if (jl_gc_signal_page == NULL) {
jl_printf(JL_STDERR, "could not allocate GC synchronization page\n");
gc_debug_critical_error();
abort();
}
}

#ifdef JULIA_ENABLE_THREADING
static void jl_wait_for_gc(void)
{
while (jl_gc_running) {
Expand All @@ -386,26 +406,6 @@ static void jl_gc_wait_for_the_world(void)
}
}

void jl_gc_signal_init(void)
{
// jl_page_size isn't available yet.
#ifdef _OS_WINDOWS_
jl_gc_signal_page = (size_t*)VirtualAlloc(NULL, jl_getpagesize(),
MEM_COMMIT, PAGE_READONLY);
#else
jl_gc_signal_page = (size_t*)mmap(0, jl_getpagesize(), PROT_READ,
MAP_NORESERVE | MAP_PRIVATE |
MAP_ANONYMOUS, -1, 0);
if (jl_gc_signal_page == MAP_FAILED)
jl_gc_signal_page = NULL;
#endif
if (jl_gc_signal_page == NULL) {
jl_printf(JL_STDERR, "could not allocate GC synchronization page\n");
gc_debug_critical_error();
abort();
}
}

static void jl_gc_signal_begin(void)
{
#ifdef __APPLE__
Expand Down
2 changes: 1 addition & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,8 @@ void _julia_init(JL_IMAGE_SEARCH rel)
#ifdef JULIA_ENABLE_THREADING
// Make sure we finalize the tls callback before starting any threads.
jl_get_ptls_states_getter();
jl_gc_signal_init();
#endif
jl_gc_signal_init();
libsupport_init();
jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.),
// best to call this first, since it also initializes libuv
Expand Down
4 changes: 1 addition & 3 deletions src/jitlayers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,6 @@ static void* jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit = NULL
#endif
}

#ifdef JULIA_ENABLE_THREADING // only used in the threading build
// Emit a slot in the system image to be filled at sysimg init time.
// Returns the global var. Fill `idx` with 1-base index in the sysimg gv.
// Use as an optimization for runtime constant addresses to have one less
Expand Down Expand Up @@ -840,7 +839,6 @@ static GlobalVariable *jl_emit_sysimg_slot(Module *m, Type *typ, const char *nam
idx = jl_sysimg_gvars.size();
return gv;
}
#endif

static void* jl_get_global(GlobalVariable *gv)
{
Expand Down Expand Up @@ -915,13 +913,13 @@ static void jl_gen_llvm_globaldata(llvm::Module *mod, ValueToValueMapTy &VMap,
GlobalVariable::ExternalLinkage,
ConstantInt::get(T_size, jltls_states_func_idx),
"jl_ptls_states_getter_idx"));
#endif
addComdat(new GlobalVariable(*mod,
T_size,
true,
GlobalVariable::ExternalLinkage,
ConstantInt::get(T_size, jl_gc_signal_page_idx),
"jl_gc_signal_page_idx"));
#endif

Constant *feature_string = ConstantDataArray::getString(jl_LLVMContext, jl_options.cpu_target);
addComdat(new GlobalVariable(*mod,
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ void jl_set_base_ctx(char *__stk);
void jl_init_threading(void);
void jl_start_threads(void);
void jl_shutdown_threading(void);
void jl_gc_signal_init(void);
#ifdef JULIA_ENABLE_THREADING
jl_get_ptls_states_func jl_get_ptls_states_getter(void);
void jl_gc_signal_init(void);
void jl_gc_signal_wait(void);
#endif

Expand Down
21 changes: 10 additions & 11 deletions src/julia_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,20 @@ JL_DLLEXPORT void (jl_cpu_wake)(void);

// Accessing the tls variables, gc safepoint and gc states
JL_DLLEXPORT JL_CONST_FUNC jl_tls_states_t *(jl_get_ptls_states)(void);
JL_DLLEXPORT extern volatile size_t *jl_gc_signal_page;
// This triggers a SegFault when we are in GC
// Assign it to a variable to make sure the compiler emit the load
// and to avoid Clang warning for -Wunused-volatile-lvalue
#define jl_gc_safepoint() do { \
jl_signal_fence(); \
size_t safepoint_load = *jl_gc_signal_page; \
jl_signal_fence(); \
(void)safepoint_load; \
} while (0)
#ifndef JULIA_ENABLE_THREADING
extern JL_DLLEXPORT jl_tls_states_t jl_tls_states;
#define jl_get_ptls_states() (&jl_tls_states)
#define jl_gc_state() ((int8_t)0)
#define jl_gc_safepoint() do {} while (0)
STATIC_INLINE int8_t jl_gc_state_set(int8_t state, int8_t old_state)
{
(void)state;
Expand All @@ -300,16 +309,6 @@ typedef jl_tls_states_t *(*jl_get_ptls_states_func)(void);
JL_DLLEXPORT void jl_set_ptls_states_getter(jl_get_ptls_states_func f);
// Make sure jl_gc_state() is always a rvalue
#define jl_gc_state() ((int8_t)(jl_get_ptls_states()->gc_state))
JL_DLLEXPORT extern volatile size_t *jl_gc_signal_page;
// This triggers a SegFault when we are in GC
// Assign it to a variable to make sure the compiler emit the load
// and to avoid Clang warning for -Wunused-volatile-lvalue
#define jl_gc_safepoint() do { \
jl_signal_fence(); \
size_t safepoint_load = *jl_gc_signal_page; \
jl_signal_fence(); \
(void)safepoint_load; \
} while (0)
STATIC_INLINE int8_t jl_gc_state_set(int8_t state, int8_t old_state)
{
jl_get_ptls_states()->gc_state = state;
Expand Down

0 comments on commit ab2f0c1

Please sign in to comment.