From f3d528868431aab17280154185afcf2c6e5017a1 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 15 Dec 2020 21:54:44 -0500 Subject: [PATCH] Exclude `threads` test from rr tracing --- src/jlapi.c | 23 +++++++++++++++++++++++ src/jloptions.c | 6 ++++++ src/julia.h | 1 + src/julia_internal.h | 2 ++ src/partr.c | 6 +++--- test/threads.jl | 10 +++++----- 6 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/jlapi.c b/src/jlapi.c index f30e66cf57ccb..7565721902e2d 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -663,6 +663,17 @@ static void lock_low32(void) // Actual definition in `ast.c` void jl_lisp_prompt(void); +static void rr_detach_teleport(void) { +#ifdef _OS_LINUX_ +#define RR_CALL_BASE 1000 +#define SYS_rrcall_detach_teleport (RR_CALL_BASE + 9) + int err = syscall(SYS_rrcall_detach_teleport, 0, 0, 0, 0, 0, 0); + if (err < 0 || jl_running_under_rr(1)) { + jl_error("Failed to detach from rr session"); + } +#endif +} + JL_DLLEXPORT int repl_entrypoint(int argc, char *argv[]) { // no-op on Windows, note that the caller must have already converted @@ -678,7 +689,19 @@ JL_DLLEXPORT int repl_entrypoint(int argc, char *argv[]) memmove(&argv[1], &argv[2], (argc-2)*sizeof(void*)); argc--; } + char **orig_argv = argv; jl_parse_opts(&argc, (char***)&argv); + + // The parent process requested that we detach from the rr session. + // N.B.: In a perfect world, we would only do this for the portion of + // the execution where we actually need to exclude rr (e.g. because we're + // testing for the absence of a memory-model-dependent bug). + if (jl_options.rr_detach && jl_running_under_rr(0)) { + rr_detach_teleport(); + execv("/proc/self/exe", orig_argv); + jl_error("Failed to self-execute"); + } + julia_init(jl_options.image_file_specified ? JL_IMAGE_CWD : JL_IMAGE_JULIA_HOME); if (lisp_prompt) { jl_get_ptls_states()->world_age = jl_get_world_counter(); diff --git a/src/jloptions.c b/src/jloptions.c index da8c7a8560973..92affe7679098 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -75,6 +75,7 @@ jl_options_t jl_options = { 0, // quiet 0, // image_file_specified JL_OPTIONS_WARN_SCOPE_ON, // ambiguous scope warning 0, // image-codegen + 0, // rr-detach }; static const char usage[] = "julia [switches] -- [programfile] [args...]\n"; @@ -203,6 +204,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) opt_project, opt_bug_report, opt_image_codegen, + opt_rr_detach, }; static const char* const shortopts = "+vhqH:e:E:L:J:C:it:p:O:g:"; static const struct option longopts[] = { @@ -254,6 +256,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) { "bind-to", required_argument, 0, opt_bind_to }, { "lisp", no_argument, 0, 1 }, { "image-codegen", no_argument, 0, opt_image_codegen }, + { "rr-detach", no_argument, 0, opt_rr_detach }, { 0, 0, 0, 0 } }; @@ -655,6 +658,9 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) case opt_image_codegen: jl_options.image_codegen = 1; break; + case opt_rr_detach: + jl_options.rr_detach = 1; + break; default: jl_errorf("julia: unhandled option -- %c\n" "This is a bug, please report it.", c); diff --git a/src/julia.h b/src/julia.h index 66d32af6c4709..0087a624a1545 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1947,6 +1947,7 @@ typedef struct { int8_t image_file_specified; int8_t warn_scope; int8_t image_codegen; + int8_t rr_detach; } jl_options_t; extern JL_DLLEXPORT jl_options_t jl_options; diff --git a/src/julia_internal.h b/src/julia_internal.h index d5d64a244a3e3..c921cf91236b4 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -83,6 +83,8 @@ void JL_UV_LOCK(void); extern "C" { #endif +int jl_running_under_rr(int recheck); + //-------------------------------------------------- // timers // Returns time in nanosec diff --git a/src/partr.c b/src/partr.c index d12ee54207e59..a0dbf0f415a73 100644 --- a/src/partr.c +++ b/src/partr.c @@ -274,14 +274,14 @@ JL_DLLEXPORT int jl_enqueue_task(jl_task_t *task) } -static int running_under_rr(void) +int jl_running_under_rr(int recheck) { #ifdef _OS_LINUX_ #define RR_CALL_BASE 1000 #define SYS_rrcall_check_presence (RR_CALL_BASE + 8) static int checked_running_under_rr = 0; static int is_running_under_rr = 0; - if (!checked_running_under_rr) { + if (!checked_running_under_rr || recheck) { int ret = syscall(SYS_rrcall_check_presence, 0, 0, 0, 0, 0, 0); if (ret == -1) { // Should always be ENOSYS, but who knows what people do for @@ -311,7 +311,7 @@ static int sleep_check_after_threshold(uint64_t *start_cycles) * scheduling logic from switching to other threads. Just don't bother * trying to wait here */ - if (running_under_rr()) + if (jl_running_under_rr(0)) return 1; if (!(*start_cycles)) { *start_cycles = jl_hrtime(); diff --git a/test/threads.jl b/test/threads.jl index 6b4ff377f127d..f2f7e1a8f035a 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -2,7 +2,7 @@ using Test -let cmd = `$(Base.julia_cmd()) --depwarn=error --startup-file=no threads_exec.jl` +let cmd = `$(Base.julia_cmd()) --depwarn=error --rr-detach --startup-file=no threads_exec.jl` for test_nthreads in (1, 2, 4, 4) # run once to try single-threaded mode, then try a couple times to trigger bad races new_env = copy(ENV) new_env["JULIA_NUM_THREADS"] = string(test_nthreads) @@ -11,12 +11,12 @@ let cmd = `$(Base.julia_cmd()) --depwarn=error --startup-file=no threads_exec.jl end # issue #34415 - make sure external affinity settings work +const SYS_rrcall_check_presence = 1008 +running_under_rr() = 0 == ccall(:syscall, Int, + (Int, Int, Int, Int, Int, Int, Int), + SYS_rrcall_check_presence, 0, 0, 0, 0, 0, 0) if Sys.islinux() - const SYS_rrcall_check_presence = 1008 - running_under_rr() = 0 == ccall(:syscall, Int, - (Int, Int, Int, Int, Int, Int, Int), - SYS_rrcall_check_presence, 0, 0, 0, 0, 0, 0) if Sys.CPU_THREADS > 1 && Sys.which("taskset") !== nothing && !running_under_rr() run_with_affinity(spec) = readchomp(`taskset -c $spec $(Base.julia_cmd()) -e "run(\`taskset -p \$(getpid())\`)"`) @test endswith(run_with_affinity("1"), "2")