Skip to content

WIP: save registers of tasks that were active right before GC on a ucontext_t for conservative scanning #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
16 changes: 16 additions & 0 deletions src/gc-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -968,3 +968,19 @@ static int gc_logging_enabled = 0;
JL_DLLEXPORT void jl_enable_gc_logging(int enable) {
gc_logging_enabled = enable;
}

JL_DLLEXPORT void jl_save_context_for_conservative_scanning(jl_ptls_t ptls, void *ctx)
{
#ifdef GC_SAVE_CONTEXT_FOR_CONSERVATIVE_SCANNING
if (ctx == NULL) {
// Save the context for the thread as it was running at the time of the call
int r = getcontext(&ptls->ctx_at_the_time_gc_started);
if (r == -1) {
jl_safe_printf("Failed to save context for conservative scanning\n");
abort();
}
return;
}
memcpy(&ptls->ctx_at_the_time_gc_started, ctx, sizeof(ucontext_t));
#endif
}
1 change: 1 addition & 0 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2716,6 +2716,7 @@ size_t jl_maxrss(void);
// Only one thread should be running in this function
static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
{
jl_save_context_for_conservative_scanning(ptls, NULL);
combine_thread_gc_counts(&gc_num);

jl_gc_markqueue_t *mq = &ptls->mark_queue;
Expand Down
6 changes: 6 additions & 0 deletions src/julia_gcext.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ JL_DLLEXPORT void jl_active_task_stack(jl_task_t *task,
char **active_start, char **active_end,
char **total_start, char **total_end);

// Save the context of a task for conservative scanning.
// Requires `GC_SAVE_CONTEXT_FOR_CONSERVATIVE_SCANNING` to be defined.
// If ctx is NULL, the registers of the thread at the moment of the call are saved, else
// the registers of the context ctx are saved into the `ctx_at_the_time_gc_started` field of Julia's TLS.
JL_DLLEXPORT void jl_save_context_for_conservative_scanning(jl_ptls_t ptls, void *ctx);

#ifdef __cplusplus
}
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/julia_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@ typedef struct _jl_tls_states_t {
size_t malloc_sz_since_last_poll;
#endif

#ifdef GC_SAVE_CONTEXT_FOR_CONSERVATIVE_SCANNING
ucontext_t ctx_at_the_time_gc_started;
#endif

JULIA_DEBUG_SLEEPWAKE(
uint64_t uv_run_enter;
uint64_t uv_run_leave;
Expand Down
7 changes: 7 additions & 0 deletions src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@
// GC_SMALL_PAGE allocates objects in 4k pages
// #define GC_SMALL_PAGE

// GC_SAVE_CONTEXT_FOR_CONSERVATIVE_SCANNING saves the context of the tasks that
// were running right before GC started so that they can be used for conservative
// scanning. Currently only available on x86_64 Linux.
#define GC_SAVE_CONTEXT_FOR_CONSERVATIVE_SCANNING
#if !defined(x86_64) || !defined(_OS_LINUX_)
#undef GC_SAVE_CONTEXT_FOR_CONSERVATIVE_SCANNING
#endif

// method dispatch profiling --------------------------------------------------

Expand Down
1 change: 1 addition & 0 deletions src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ 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)) {
jl_save_context_for_conservative_scanning(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