Skip to content

Commit 7ccc83e

Browse files
jpsamarootkf
andauthoredFeb 9, 2022
Add USDTs for the task runtime (JuliaLang#43453)
Co-authored-by: Takafumi Arakaki <[email protected]>
1 parent 0639d0d commit 7ccc83e

File tree

7 files changed

+320
-10
lines changed

7 files changed

+320
-10
lines changed
 

Diff for: ‎contrib/bpftrace/rt_all.bt

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env bpftrace
2+
3+
BEGIN
4+
{
5+
printf("Tracing Julia Task events... Hit Ctrl-C to end.\n");
6+
}
7+
8+
usdt:usr/lib/libjulia-internal.so:julia:rt__run__task
9+
{
10+
printf("Task running: %x\n", arg0);
11+
}
12+
13+
usdt:usr/lib/libjulia-internal.so:julia:rt__pause__task
14+
{
15+
printf("Task pausing: %x\n", arg0);
16+
}
17+
18+
usdt:usr/lib/libjulia-internal.so:julia:rt__new__task
19+
{
20+
printf("Task created: %x (Parent %x)\n", arg1, arg0);
21+
}
22+
23+
usdt:usr/lib/libjulia-internal.so:julia:rt__start__task
24+
{
25+
printf("Task started: %x\n", arg0);
26+
}
27+
28+
usdt:usr/lib/libjulia-internal.so:julia:rt__finish__task
29+
{
30+
printf("Task finished: %x\n", arg0);
31+
}
32+
33+
usdt:usr/lib/libjulia-internal.so:julia:rt__start__process__events
34+
{
35+
printf("Task processing libuv events: %x\n", arg0);
36+
}
37+
38+
usdt:usr/lib/libjulia-internal.so:julia:rt__finish__process__events
39+
{
40+
printf("Task processed libuv events: %x\n", arg0);
41+
}
42+
43+
usdt:usr/lib/libjulia-internal.so:julia:rt__taskq__insert
44+
{
45+
printf("Thread %x inserting task to multiq: %x\n", arg0, arg1);
46+
}
47+
48+
usdt:usr/lib/libjulia-internal.so:julia:rt__taskq__get
49+
{
50+
printf("Thread %x popped task from multiq: %x\n", arg0, arg1);
51+
}
52+
53+
usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__wake
54+
{
55+
printf("Thread waking: %x (was sleeping?: %d)\n", arg0, arg1);
56+
}
57+
58+
usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__wakeup
59+
{
60+
printf("Thread wakeup: %x\n", arg0);
61+
}
62+
63+
usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__sleep
64+
{
65+
printf("Thread trying to sleep: %x\n", arg0);
66+
}
67+
68+
usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__taskq__wake
69+
{
70+
printf("Thread waking due to non-empty task queue: %x\n", arg0);
71+
}
72+
73+
usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__task__wake
74+
{
75+
printf("Thread waking due to popped task: %x\n", arg0);
76+
}
77+
78+
usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__uv__wake
79+
{
80+
printf("Thread waking due to libuv: %x\n", arg0);
81+
}

Diff for: ‎doc/src/devdocs/probes.md

+158-2
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,37 @@ the probe handler.
9090
3. `julia:gc__mark__begin`: Beginning the mark phase
9191
4. `julia:gc__mark_end(scanned_bytes, perm_scanned)`: Mark phase ended
9292
5. `julia:gc__sweep_begin(full)`: Starting sweep
93-
6. `julia:gc__sweep_end()`: Sweep phase finished
93+
6. `julia:gc__sweep_end`: Sweep phase finished
9494
7. `julia:gc__end`: GC is finished, other threads continue work
9595
8. `julia:gc__finalizer`: Initial GC thread has finished running finalizers
9696

97-
#### GC stop-the-world latency
97+
### Task runtime probes
98+
99+
1. `julia:rt__run__task(task)`: Switching to task `task` on current thread.
100+
2. `julia:rt__pause__task(task)`: Switching from task `task` on current thread.
101+
3. `julia:rt__new__task(parent, child)`: Task `parent` created task `child` on current thread.
102+
4. `julia:rt__start__task(task)`: Task `task` started for the first time with a new stack.
103+
5. `julia:rt__finish__task(task)`: Task `task` finished and will no longer execute.
104+
6. `julia:rt__start__process__events(task)`: Task `task` started processing libuv events.
105+
7. `julia:rt__finish__process__events(task)`: Task `task` finished processing libuv events.
106+
107+
### Task queue probes
108+
109+
1. `julia:rt__taskq__insert(ptls, task)`: Thread `ptls` attempted to insert `task` into a PARTR multiq.
110+
2. `julia:rt__taskq__get(ptls, task)`: Thread `ptls` popped `task` from a PARTR multiq.
111+
112+
### Thread sleep/wake probes
113+
114+
1. `julia:rt__sleep__check__wake(ptls, old_state)`: Thread (PTLS `ptls`) waking up, previously in state `old_state`.
115+
2. `julia:rt__sleep__check__wakeup(ptls)`: Thread (PTLS `ptls`) woke itself up.
116+
3. `julia:rt__sleep__check__sleep(ptls)`: Thread (PTLS `ptls`) is attempting to sleep.
117+
4. `julia:rt__sleep__check__taskq__wake(ptls)`: Thread (PTLS `ptls`) fails to sleep due to tasks in PARTR multiq.
118+
5. `julia:rt__sleep__check__task__wake(ptls)`: Thread (PTLS `ptls`) fails to sleep due to tasks in Base workqueue.
119+
6. `julia:rt__sleep__check__uv__wake(ptls)`: Thread (PTLS `ptls`) fails to sleep due to libuv wakeup.
120+
121+
## Probe usage examples
122+
123+
### GC stop-the-world latency
98124

99125
An example `bpftrace` script is given in `contrib/gc_stop_the_world_latency.bt`
100126
and it creates a histogram of the latency for all threads to reach a safepoint.
@@ -143,6 +169,136 @@ Tracing Julia GC Stop-The-World Latency... Hit Ctrl-C to end.
143169

144170
We can see the latency distribution of the stop-the-world phase in the executed Julia process.
145171

172+
### Task spawn monitor
173+
174+
It's sometimes useful to know when a task is spawning other tasks. This is very
175+
easy to see with `rt__new__task`. The first argument to the probe, `parent`, is
176+
the existing task which is creating a new task. This means that if you know the
177+
address of the task you want to monitor, you can easily just look at the tasks
178+
that that specific task spawned. Let's see how to do this; first let's start a
179+
Julia session and get the PID and REPL's task address:
180+
181+
```
182+
> julia
183+
_
184+
_ _ _(_)_ | Documentation: https://docs.julialang.org
185+
(_) | (_) (_) |
186+
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
187+
| | | | | | |/ _` | |
188+
| | |_| | | | (_| | | Version 1.6.2 (2021-07-14)
189+
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
190+
|__/ |
191+
192+
1> getpid()
193+
997825
194+
195+
2> current_task()
196+
Task (runnable) @0x00007f524d088010
197+
```
198+
199+
Now we can start `bpftrace` and have it monitor `rt__new__task` for *only* this parent:
200+
201+
`sudo bpftrace -p 997825 -e 'usdt:usr/lib/libjulia-internal.so:julia:rt__new__task /arg0==0x00007f524d088010/{ printf("Task: %x\n", arg0); }'`
202+
203+
(Note that in the above, `arg0` is the first argument, `parent`).
204+
205+
And if we spawn a single task:
206+
207+
`@async 1+1`
208+
209+
we see this task being created:
210+
211+
`Task: 4d088010`
212+
213+
However, if we spawn a bunch of tasks from that newly-spawned task:
214+
215+
```julia
216+
@async for i in 1:10
217+
@async 1+1
218+
end
219+
```
220+
221+
we still only see one task from `bpftrace`:
222+
223+
`Task: 4d088010`
224+
225+
and it's still the same task we were monitoring! Of course, we can remove this
226+
filter to see *all* newly-created tasks just as easily:
227+
228+
`sudo bpftrace -p 997825 -e 'usdt:usr/lib/libjulia-internal.so:julia:rt__new__task { printf("Task: %x\n", arg0); }'`
229+
230+
```
231+
Task: 4d088010
232+
Task: 4dc4e290
233+
Task: 4dc4e290
234+
Task: 4dc4e290
235+
Task: 4dc4e290
236+
Task: 4dc4e290
237+
Task: 4dc4e290
238+
Task: 4dc4e290
239+
Task: 4dc4e290
240+
Task: 4dc4e290
241+
Task: 4dc4e290
242+
```
243+
244+
We can see our root task, and the newly-spawned task as the parent of the ten
245+
even newer tasks.
246+
247+
### Thundering herd detection
248+
249+
Task runtimes can often suffer from the "thundering herd" problem: when some
250+
work is added to a quiet task runtime, all threads may be woken up from their
251+
slumber, even if there isn't enough work for each thread to process. This can
252+
cause extra latency and CPU cycles while all threads awaken (and simultaneously
253+
go back to sleep, not finding any work to execute).
254+
255+
We can see this problem illustrated with `bpftrace` quite easily. First, in one terminal we start Julia with multiple threads (6 in this example), and get the PID of that process:
256+
257+
```
258+
> julia -t 6
259+
_
260+
_ _ _(_)_ | Documentation: https://docs.julialang.org
261+
(_) | (_) (_) |
262+
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
263+
| | | | | | |/ _` | |
264+
| | |_| | | | (_| | | Version 1.6.2 (2021-07-14)
265+
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
266+
|__/ |
267+
268+
1> getpid()
269+
997825
270+
```
271+
272+
And in another terminal we start `bpftrace` monitoring our process,
273+
specifically probing the `rt__sleep__check__wake` hook:
274+
275+
`sudo bpftrace -p 997825 -e 'usdt:usr/lib/libjulia-internal.so:julia:rt__sleep__check__wake { printf("Thread wake up! %x\n", arg0); }'`
276+
277+
Now, we create and execute a single task in Julia:
278+
279+
`Threads.@spawn 1+1`
280+
281+
And in `bpftrace` we see printed out something like:
282+
283+
```
284+
Thread wake up! 3f926100
285+
Thread wake up! 3ebd5140
286+
Thread wake up! 3f876130
287+
Thread wake up! 3e2711a0
288+
Thread wake up! 3e312190
289+
```
290+
291+
Even though we only spawned a single task (which only one thread could process
292+
at a time), we woke up all of our other threads! In the future, a smarter task
293+
runtime might only wake up a single thread (or none at all; the spawning thread
294+
could execute this task!), and we should see this behavior go away.
295+
296+
### Task Monitor with BPFnative.jl
297+
298+
BPFnative.jl is able to attach to USDT probe points just like `bpftrace`. There
299+
is a demo available for monitoring the task runtime, GC, and thread sleep/wake
300+
transitions [here](https://github.com/jpsamaroo/BPFnative.jl/blob/master/examples/task-runtime.jl).
301+
146302
## Notes on using `bpftrace`
147303

148304
An example probe in the bpftrace format looks like:

Diff for: ‎src/jl_uv.c

+2
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ JL_DLLEXPORT int jl_process_events(void)
205205
jl_gc_safepoint_(ct->ptls);
206206
if (loop && (jl_atomic_load_relaxed(&_threadedregion) || jl_atomic_load_relaxed(&ct->tid) == 0)) {
207207
if (jl_atomic_load_relaxed(&jl_uv_n_waiters) == 0 && jl_mutex_trylock(&jl_uv_mutex)) {
208+
JL_PROBE_RT_START_PROCESS_EVENTS(ct);
208209
loop->stop_flag = 0;
209210
int r = uv_run(loop, UV_RUN_NOWAIT);
211+
JL_PROBE_RT_FINISH_PROCESS_EVENTS(ct);
210212
JL_UV_UNLOCK();
211213
return r;
212214
}

Diff for: ‎src/julia_internal.h

+30
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,21 @@ uint16_t __gnu_f2h_ieee(float param) JL_NOTSAFEPOINT;
15431543
#define JL_PROBE_GC_SWEEP_END() do ; while (0)
15441544
#define JL_PROBE_GC_END() do ; while (0)
15451545
#define JL_PROBE_GC_FINALIZER() do ; while (0)
1546+
#define JL_PROBE_RT_RUN_TASK(task) do ; while (0)
1547+
#define JL_PROBE_RT_PAUSE_TASK(task) do ; while (0)
1548+
#define JL_PROBE_RT_NEW_TASK(parent, child) do ; while (0)
1549+
#define JL_PROBE_RT_START_TASK(task) do ; while (0)
1550+
#define JL_PROBE_RT_FINISH_TASK(task) do ; while (0)
1551+
#define JL_PROBE_RT_START_PROCESS_EVENTS(task) do ; while (0)
1552+
#define JL_PROBE_RT_FINISH_PROCESS_EVENTS(task) do ; while (0)
1553+
#define JL_PROBE_RT_TASKQ_INSERT(ptls, task) do ; while (0)
1554+
#define JL_PROBE_RT_TASKQ_GET(ptls, task) do ; while (0)
1555+
#define JL_PROBE_RT_SLEEP_CHECK_WAKE(other, old_state) do ; while (0)
1556+
#define JL_PROBE_RT_SLEEP_CHECK_WAKEUP(ptls) do ; while (0)
1557+
#define JL_PROBE_RT_SLEEP_CHECK_SLEEP(ptls) do ; while (0)
1558+
#define JL_PROBE_RT_SLEEP_CHECK_TASKQ_WAKE(ptls) do ; while (0)
1559+
#define JL_PROBE_RT_SLEEP_CHECK_TASK_WAKE(ptls) do ; while (0)
1560+
#define JL_PROBE_RT_SLEEP_CHECK_UV_WAKE(ptls) do ; while (0)
15461561

15471562
#define JL_PROBE_GC_BEGIN_ENABLED() (0)
15481563
#define JL_PROBE_GC_STOP_THE_WORLD_ENABLED() (0)
@@ -1552,6 +1567,21 @@ uint16_t __gnu_f2h_ieee(float param) JL_NOTSAFEPOINT;
15521567
#define JL_PROBE_GC_SWEEP_END_ENABLED() (0)
15531568
#define JL_PROBE_GC_END_ENABLED() (0)
15541569
#define JL_PROBE_GC_FINALIZER_ENABLED() (0)
1570+
#define JL_PROBE_RT_RUN_TASK_ENABLED() (0)
1571+
#define JL_PROBE_RT_PAUSE_TASK_ENABLED() (0)
1572+
#define JL_PROBE_RT_NEW_TASK_ENABLED() (0)
1573+
#define JL_PROBE_RT_START_TASK_ENABLED() (0)
1574+
#define JL_PROBE_RT_FINISH_TASK_ENABLED() (0)
1575+
#define JL_PROBE_RT_START_PROCESS_EVENTS_ENABLED() (0)
1576+
#define JL_PROBE_RT_FINISH_PROCESS_EVENTS_ENABLED() (0)
1577+
#define JL_PROBE_RT_TASKQ_INSERT_ENABLED() (0)
1578+
#define JL_PROBE_RT_TASKQ_GET_ENABLED() (0)
1579+
#define JL_PROBE_RT_SLEEP_CHECK_WAKE_ENABLED() (0)
1580+
#define JL_PROBE_RT_SLEEP_CHECK_WAKEUP_ENABLED() (0)
1581+
#define JL_PROBE_RT_SLEEP_CHECK_SLEEP_ENABLED() (0)
1582+
#define JL_PROBE_RT_SLEEP_CHECK_TASKQ_WAKE_ENABLED() (0)
1583+
#define JL_PROBE_RT_SLEEP_CHECK_TASK_WAKE_ENABLED() (0)
1584+
#define JL_PROBE_RT_SLEEP_CHECK_UV_WAKE_ENABLED() (0)
15551585
#endif
15561586

15571587
#endif

Diff for: ‎src/partr.c

+26-8
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,12 @@ void jl_threadfun(void *arg)
302302
// enqueue the specified task for execution
303303
JL_DLLEXPORT int jl_enqueue_task(jl_task_t *task)
304304
{
305+
char failed;
305306
if (multiq_insert(task, task->prio) == -1)
306-
return 1;
307-
return 0;
307+
failed = 1;
308+
failed = 0;
309+
JL_PROBE_RT_TASKQ_INSERT(jl_current_task->ptls, task);
310+
return failed;
308311
}
309312

310313

@@ -365,6 +368,7 @@ static int wake_thread(int16_t tid)
365368

366369
if (jl_atomic_load_relaxed(&other->sleep_check_state) == sleeping) {
367370
if (jl_atomic_cmpswap_relaxed(&other->sleep_check_state, &state, not_sleeping)) {
371+
JL_PROBE_RT_SLEEP_CHECK_WAKE(other, state);
368372
uv_mutex_lock(&sleep_locks[tid]);
369373
uv_cond_signal(&wake_signals[tid]);
370374
uv_mutex_unlock(&sleep_locks[tid]);
@@ -394,8 +398,10 @@ JL_DLLEXPORT void jl_wakeup_thread(int16_t tid)
394398
if (tid == self || tid == -1) {
395399
// we're already awake, but make sure we'll exit uv_run
396400
jl_ptls_t ptls = ct->ptls;
397-
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) == sleeping)
401+
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) == sleeping) {
398402
jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping);
403+
JL_PROBE_RT_SLEEP_CHECK_WAKEUP(ptls);
404+
}
399405
if (uvlock == ct)
400406
uv_stop(jl_global_event_loop());
401407
}
@@ -444,7 +450,10 @@ static jl_task_t *get_next_task(jl_value_t *trypoptask, jl_value_t *q)
444450
jl_set_task_tid(task, self);
445451
return task;
446452
}
447-
return multiq_deletemin();
453+
task = multiq_deletemin();
454+
if (task)
455+
JL_PROBE_RT_TASKQ_GET(jl_current_task->ptls, task);
456+
return task;
448457
}
449458

450459
static int may_sleep(jl_ptls_t ptls) JL_NOTSAFEPOINT
@@ -482,24 +491,31 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q)
482491
// acquire sleep-check lock
483492
jl_atomic_store_relaxed(&ptls->sleep_check_state, sleeping);
484493
jl_fence(); // [^store_buffering_1]
494+
JL_PROBE_RT_SLEEP_CHECK_SLEEP(ptls);
485495
if (!multiq_check_empty()) { // uses relaxed loads
486-
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping)
496+
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) {
487497
jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); // let other threads know they don't need to wake us
498+
JL_PROBE_RT_SLEEP_CHECK_TASKQ_WAKE(ptls);
499+
}
488500
continue;
489501
}
490502
task = get_next_task(trypoptask, q); // note: this should not yield
491503
if (ptls != ct->ptls) {
492504
// sigh, a yield was detected, so let's go ahead and handle it anyway by starting over
493505
ptls = ct->ptls;
494-
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping)
506+
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) {
495507
jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); // let other threads know they don't need to wake us
508+
JL_PROBE_RT_SLEEP_CHECK_TASK_WAKE(ptls);
509+
}
496510
if (task)
497511
return task;
498512
continue;
499513
}
500514
if (task) {
501-
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping)
515+
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) {
502516
jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); // let other threads know they don't need to wake us
517+
JL_PROBE_RT_SLEEP_CHECK_TASK_WAKE(ptls);
518+
}
503519
return task;
504520
}
505521

@@ -554,8 +570,10 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q)
554570
if (!jl_atomic_load_relaxed(&_threadedregion) && active && ptls->tid == 0) {
555571
// thread 0 is the only thread permitted to run the event loop
556572
// so it needs to stay alive, just spin-looping if necessary
557-
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping)
573+
if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) {
558574
jl_atomic_store_relaxed(&ptls->sleep_check_state, not_sleeping); // let other threads know they don't need to wake us
575+
JL_PROBE_RT_SLEEP_CHECK_UV_WAKE(ptls);
576+
}
559577
start_cycles = 0;
560578
continue;
561579
}

Diff for: ‎src/task.c

+7
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ static _Atomic(jl_function_t*) task_done_hook_func JL_GLOBALLY_ROOTED = NULL;
229229
void JL_NORETURN jl_finish_task(jl_task_t *t)
230230
{
231231
jl_task_t *ct = jl_current_task;
232+
JL_PROBE_RT_FINISH_TASK(ct);
232233
JL_SIGATOMIC_BEGIN();
233234
if (jl_atomic_load_relaxed(&t->_isexception))
234235
jl_atomic_store_release(&t->_state, JL_TASK_STATE_FAILED);
@@ -532,6 +533,8 @@ JL_DLLEXPORT void jl_switch(void)
532533
if (!jl_set_task_tid(t, jl_atomic_load_relaxed(&ct->tid))) // manually yielding to a task
533534
jl_error("cannot switch to task running on another thread");
534535

536+
JL_PROBE_RT_PAUSE_TASK(ct);
537+
535538
// Store old values on the stack and reset
536539
sig_atomic_t defer_signal = ptls->defer_signal;
537540
int8_t gc_state = jl_gc_unsafe_enter(ptls);
@@ -579,6 +582,8 @@ JL_DLLEXPORT void jl_switch(void)
579582
ptls->defer_signal = defer_signal;
580583
if (other_defer_signal && !defer_signal)
581584
jl_sigint_safepoint(ptls);
585+
586+
JL_PROBE_RT_RUN_TASK(ct);
582587
}
583588

584589
JL_DLLEXPORT void jl_switchto(jl_task_t **pt)
@@ -753,6 +758,7 @@ JL_DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, jl_value_t *completion
753758
{
754759
jl_task_t *ct = jl_current_task;
755760
jl_task_t *t = (jl_task_t*)jl_gc_alloc(ct->ptls, sizeof(jl_task_t), jl_task_type);
761+
JL_PROBE_RT_NEW_TASK(ct, t);
756762
t->copy_stack = 0;
757763
if (ssize == 0) {
758764
// stack size unspecified; use default
@@ -908,6 +914,7 @@ CFI_NORETURN
908914
#endif
909915

910916
ct->started = 1;
917+
JL_PROBE_RT_START_TASK(ct);
911918
if (jl_atomic_load_relaxed(&ct->_isexception)) {
912919
record_backtrace(ptls, 0);
913920
jl_push_excstack(&ct->excstack, ct->result,

Diff for: ‎src/uprobes.d

+16
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@ provider julia {
99
probe gc__sweep__end();
1010
probe gc__end();
1111
probe gc__finalizer();
12+
13+
probe rt__run__task(jl_task_t *task);
14+
probe rt__pause__task(jl_task_t *task);
15+
probe rt__new__task(jl_task_t *parent, jl_task_t *child);
16+
probe rt__start__task(jl_task_t *task);
17+
probe rt__finish__task(jl_task_t *task);
18+
probe rt__start__process__events(jl_task_t *task);
19+
probe rt__finish__process__events(jl_task_t *task);
20+
probe rt__taskq__insert(jl_ptls_t ptls, jl_task_t *task);
21+
probe rt__taskq__get(jl_ptls_t ptls, jl_task_t *task);
22+
probe rt__sleep__check__wake(jl_ptls_t other, int8_t old_state);
23+
probe rt__sleep__check__wakeup(jl_ptls_t ptls);
24+
probe rt__sleep__check__sleep(jl_ptls_t ptls);
25+
probe rt__sleep__check__taskq__wake(jl_ptls_t ptls);
26+
probe rt__sleep__check__task__wake(jl_ptls_t ptls);
27+
probe rt__sleep__check__uv__wake(jl_ptls_t ptls);
1228
};
1329

1430
#pragma D attributes Evolving/Evolving/Common provider julia provider

0 commit comments

Comments
 (0)
Please sign in to comment.