-
-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Add USDTs for the task runtime #43453
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
Changes from 8 commits
c5833bf
1e0ad56
7047c66
5eb9bac
3414f1c
27b9160
5b9974f
3ca21ab
1818cdc
ff2f913
77d54ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| #!/usr/bin/env bpftrace | ||
|
|
||
| BEGIN | ||
| { | ||
| printf("Tracing Julia Task events... Hit Ctrl-C to end.\n"); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__run__task | ||
| { | ||
| printf("Task running: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__pause__task | ||
| { | ||
| printf("Task pausing: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__new__task | ||
| { | ||
| printf("Task created: %x (Parent %x)\n", arg1, arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__finish__task | ||
| { | ||
| printf("Task finished: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__start__process__events | ||
| { | ||
| printf("Task processing libuv events: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__finish__process__events | ||
| { | ||
| printf("Task processed libuv events: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__wake | ||
| { | ||
| printf("Thread waking: %x (was sleeping?: %d)\n", arg0, arg1); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__wakeup | ||
| { | ||
| printf("Thread wakeup: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__sleep | ||
| { | ||
| printf("Thread trying to sleep: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__taskq__wake | ||
| { | ||
| printf("Thread waking due to non-empty task queue: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__task__wake | ||
| { | ||
| printf("Thread waking due to popped task: %x\n", arg0); | ||
| } | ||
|
|
||
| usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__uv__wake | ||
| { | ||
| printf("Thread waking due to libuv: %x\n", arg0); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -365,6 +365,7 @@ static int wake_thread(int16_t tid) | |
|
|
||
| if (jl_atomic_load_relaxed(&other->sleep_check_state) == sleeping) { | ||
| if (jl_atomic_cmpswap_relaxed(&other->sleep_check_state, &state, not_sleeping)) { | ||
| JL_PROBE_RT_SLEEP_CHECK_WAKE(other, state); | ||
| uv_mutex_lock(&sleep_locks[tid]); | ||
| uv_cond_signal(&wake_signals[tid]); | ||
| uv_mutex_unlock(&sleep_locks[tid]); | ||
|
|
@@ -394,8 +395,10 @@ JL_DLLEXPORT void jl_wakeup_thread(int16_t tid) | |
| if (tid == self || tid == -1) { | ||
| // we're already awake, but make sure we'll exit uv_run | ||
| jl_ptls_t ptls = ct->ptls; | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) == sleeping) | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) == sleeping) { | ||
| jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); | ||
| JL_PROBE_RT_SLEEP_CHECK_WAKEUP(ptls); | ||
| } | ||
| if (uvlock == ct) | ||
| uv_stop(jl_global_event_loop()); | ||
| } | ||
|
|
@@ -482,24 +485,31 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q) | |
| // acquire sleep-check lock | ||
| jl_atomic_store_relaxed(&ptls->sleep_check_state, sleeping); | ||
| jl_fence(); // [^store_buffering_1] | ||
| JL_PROBE_RT_SLEEP_CHECK_SLEEP(ptls); | ||
| if (!multiq_check_empty()) { // uses relaxed loads | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) { | ||
| jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); // let other threads know they don't need to wake us | ||
| JL_PROBE_RT_SLEEP_CHECK_TASKQ_WAKE(ptls); | ||
| } | ||
| continue; | ||
| } | ||
| task = get_next_task(trypoptask, q); // note: this should not yield | ||
| if (ptls != ct->ptls) { | ||
| // sigh, a yield was detected, so let's go ahead and handle it anyway by starting over | ||
| ptls = ct->ptls; | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) { | ||
| jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); // let other threads know they don't need to wake us | ||
| JL_PROBE_RT_SLEEP_CHECK_TASK_WAKE(ptls); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kpamnany should this get its own probe? It was introduced during a rebase, so I just copy-pasta'd the probe from below.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, in general, every state transition should get its own probe so that we can distinguish them. I'm not actually sure what's going on here in particular though so I'm not sure what to call this probe. Maybe
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most of these transitions are the same, the code structure just makes them copy the same structure frequently. In particular, all events between a given pair of fences (or locks) are indistinguishable. In practice, that also means |
||
| } | ||
| if (task) | ||
| return task; | ||
| continue; | ||
| } | ||
| if (task) { | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) { | ||
| jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); // let other threads know they don't need to wake us | ||
| JL_PROBE_RT_SLEEP_CHECK_TASK_WAKE(ptls); | ||
| } | ||
| return task; | ||
| } | ||
|
|
||
|
|
@@ -554,8 +564,10 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q) | |
| if (!jl_atomic_load_relaxed(&_threadedregion) && active && ptls->tid == 0) { | ||
| // thread 0 is the only thread permitted to run the event loop | ||
| // so it needs to stay alive, just spin-looping if necessary | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) | ||
| if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) { | ||
| jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); // let other threads know they don't need to wake us | ||
| JL_PROBE_RT_SLEEP_CHECK_UV_WAKE(ptls); | ||
| } | ||
| start_cycles = 0; | ||
| continue; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.