Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/gc-interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ JL_DLLEXPORT int gc_is_collector_thread(int tid) JL_NOTSAFEPOINT;
JL_DLLEXPORT unsigned char jl_gc_pin_object(void* obj);
// Returns the version of which GC implementation is being used according to the list of supported GCs
JL_DLLEXPORT const char* jl_active_gc_impl(void);
// Notifies the GC that the given thread is about to yield for a GC. ctx is the ucontext for the thread
// if it is already fetched by the caller, otherwise it is NULL.
JL_DLLEXPORT void jl_gc_notify_thread_yield(jl_ptls_t ptls, void* ctx);

// TODO: The preserve hook functions may be temporary. We should see the performance impact of the change.

Expand Down
15 changes: 15 additions & 0 deletions src/gc-mmtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ JL_DLLEXPORT void jl_mmtk_prepare_to_collect(void)
gc_num.total_time_to_safepoint += duration;

if (!jl_atomic_load_acquire(&jl_gc_disable_counter)) {
// This thread will yield.
jl_gc_notify_thread_yield(ptls, NULL);
JL_LOCK_NOGC(&finalizers_lock); // all the other threads are stopped, so this does not make sense, right? otherwise, failing that, this seems like plausibly a deadlock
#ifndef __clang_gcanalyzer__
mmtk_block_thread_for_gc();
Expand Down Expand Up @@ -303,6 +305,19 @@ JL_DLLEXPORT unsigned char jl_gc_pin_object(void* obj) {
return mmtk_pin_object(obj);
}

JL_DLLEXPORT void jl_gc_notify_thread_yield(jl_ptls_t ptls, void* ctx) {
if (ctx == NULL) {
// Save the context for the thread as it was running at the time of the call
int r = getcontext(&ptls->gc_tls.ctx_at_the_time_gc_started);
if (r == -1) {
jl_safe_printf("Failed to save context for conservative scanning\n");
abort();
}
return;
}
memcpy(&ptls->gc_tls.ctx_at_the_time_gc_started, ctx, sizeof(ucontext_t));
}

// ========================================================================= //
// GC Statistics
// ========================================================================= //
Expand Down
9 changes: 9 additions & 0 deletions src/gc-stock.c
Original file line number Diff line number Diff line change
Expand Up @@ -3361,6 +3361,11 @@ JL_DLLEXPORT void jl_gc_collect(jl_gc_collection_t collection)
gc_cblist_pre_gc, (collection));

if (!jl_atomic_load_acquire(&jl_gc_disable_counter)) {
// This thread will yield.
// jl_gc_notify_thread_yield does nothing for the stock GC at the point, but it may be non empty in the future,
// and this is a place where we should call jl_gc_notify_thread_yield.
// TODO: This call can be removed if requested.
jl_gc_notify_thread_yield(ptls, NULL);
JL_LOCK_NOGC(&finalizers_lock); // all the other threads are stopped, so this does not make sense, right? otherwise, failing that, this seems like plausibly a deadlock
#ifndef __clang_gcanalyzer__
if (_jl_gc_collect(ptls, collection)) {
Expand Down Expand Up @@ -4022,6 +4027,10 @@ JL_DLLEXPORT const char* jl_active_gc_impl(void) {
return "";
}

JL_DLLEXPORT void jl_gc_notify_thread_yield(jl_ptls_t ptls, void* ctx) {
// Do nothing before a thread yields
}

#ifdef __cplusplus
}
#endif
1 change: 1 addition & 0 deletions src/gc-tls-mmtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ extern "C" {
typedef struct {
MMTkMutatorContext mmtk_mutator;
size_t malloc_sz_since_last_poll;
ucontext_t ctx_at_the_time_gc_started;
} jl_gc_tls_states_t;

#ifdef __cplusplus
Expand Down
2 changes: 2 additions & 0 deletions src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,8 @@ JL_NO_ASAN static void segv_handler(int sig, siginfo_t *info, void *context)
return;
}
if (sig == SIGSEGV && info->si_code == SEGV_ACCERR && jl_addr_is_safepoint((uintptr_t)info->si_addr) && !is_write_fault(context)) {
// TODO: We should do the same for other platforms
jl_gc_notify_thread_yield(ct->ptls, context);
jl_set_gc_and_wait();
// Do not raise sigint on worker thread
if (jl_atomic_load_relaxed(&ct->tid) != 0)
Expand Down
Loading