Skip to content

Commit 4473f92

Browse files
authored
Integrate Tokio v1.46.1 task spawn locations (#2)
Tokio PRs tokio-rs/tokio#7417 and tokio-rs/tokio#7440 add the source code locations at which a task was spawned to the `TaskMeta` structure provided to the runtime task hook callbacks. These will give us the ability to associate task IDs (which identify a task at runtime) with a source code location in the instrumented program, which is going to make everything a lot easier. This PR picks up those changes and updates the minimum Tokio dependency to 1.46.1. Closes #1
1 parent 8db1775 commit 4473f92

File tree

5 files changed

+54
-18
lines changed

5 files changed

+54
-18
lines changed

Cargo.lock

Lines changed: 27 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ license = "MIT OR Apache-2.0"
99

1010
[dependencies]
1111
thiserror = "2.0.12"
12-
tokio = { version = "1.45.1", features = ["rt"] }
12+
tokio = { version = "1.46.1", features = ["rt"] }
1313
usdt = "0.5.0"
1414

1515
[dev-dependencies.tokio]
16-
version = "1.45.1"
16+
version = "1.46.1"
1717
features = ["rt", "rt-multi-thread", "time", "signal", "macros"]
1818

1919
[lints.rust]

examples/count-spawns.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#!/usr/sbin/dtrace -s
12
/*
23
* When a task is spawned, count the stack that spawned it.
34
*/

examples/pollstats.d

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
#!/usr/sbin/dtrace -s
12
/*
23
* This script profiles the following:
34
* - distribution of poll durations across all tasks
45
* - distribution of total duration for which a task exists
56
* - distribution of total duration for which a task was actively being polled
67
*/
78

8-
99
tokio$1:::task-spawn
1010
{
1111
task_poll_times[arg0] = 0;
@@ -21,13 +21,13 @@ tokio$1:::task-poll-end
2121
/self->poll_start_ts/
2222
{
2323
duration = timestamp - self->poll_start_ts;
24-
@durations["task poll duration"] = quantize(duration);
24+
@durations["task poll duration", copyinstr(arg1), arg2, arg3] = quantize(duration);
2525
task_poll_times[arg0] += duration;
2626
self->poll_start_ts = 0;
2727
}
2828

2929
tokio$1:::task-terminate
3030
{
31-
@durations["task total lifetime"] = quantize(timestamp - task_spawn_times[arg0]);
32-
@durations["task active time"] = quantize(task_poll_times[arg0]);
31+
@durations["task total lifetime", copyinstr(arg1), arg2, arg3] = quantize(timestamp - task_spawn_times[arg0]);
32+
@durations["task active time", copyinstr(arg1), arg2, arg3] = quantize(task_poll_times[arg0]);
3333
}

src/lib.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -409,22 +409,22 @@ pub mod hooks {
409409

410410
/// Hook function to be used in [`tokio::runtime::Builder::on_task_spawn`].
411411
pub fn on_task_spawn(meta: &TaskMeta<'_>) {
412-
probes::task__spawn!(|| meta_to_id(meta));
412+
probes::task__spawn!(|| unpack_meta(meta));
413413
}
414414

415415
/// Hook function to be used in [`tokio::runtime::Builder::on_before_task_poll`].
416416
pub fn on_before_task_poll(meta: &TaskMeta<'_>) {
417-
probes::task__poll__start!(|| meta_to_id(meta));
417+
probes::task__poll__start!(|| unpack_meta(meta));
418418
}
419419

420420
/// Hook function to be used in [`tokio::runtime::Builder::on_after_task_poll`].
421421
pub fn on_after_task_poll(meta: &TaskMeta<'_>) {
422-
probes::task__poll__end!(|| meta_to_id(meta));
422+
probes::task__poll__end!(|| unpack_meta(meta));
423423
}
424424

425425
/// Hook function to be used in [`tokio::runtime::Builder::on_task_terminate`].
426426
pub fn on_task_terminate(meta: &TaskMeta<'_>) {
427-
probes::task__terminate!(|| meta_to_id(meta));
427+
probes::task__terminate!(|| unpack_meta(meta));
428428
}
429429

430430
/// Hook function to be used in [`tokio::runtime::Builder::on_thread_start`].
@@ -448,26 +448,36 @@ pub mod hooks {
448448
}
449449

450450
#[inline]
451-
fn meta_to_id(meta: &TaskMeta<'_>) -> u64 {
451+
fn unpack_meta(meta: &TaskMeta<'_>) -> (u64, String, u32, u32) {
452+
let id = id_to_u64(meta.id());
453+
let location = meta.spawned_at();
454+
let file = location.file().to_string();
455+
let line = location.line();
456+
let col = location.column();
457+
(id, file, line, col)
458+
}
459+
460+
#[inline]
461+
fn id_to_u64(id: tokio::task::Id) -> u64 {
452462
unsafe {
453463
// SAFETY: Based on training and experience, I know that a
454464
// `tokio::task::Id` is represented as a single `NonZeroU64`.
455465
union TrustMeOnThis {
456466
id: tokio::task::Id,
457467
int: NonZeroU64,
458468
}
459-
TrustMeOnThis { id: meta.id() }.int.get()
469+
TrustMeOnThis { id }.int.get()
460470
}
461471
}
462472
}
463473

464474
#[usdt::provider(provider = "tokio")]
465475
#[allow(non_snake_case)]
466476
mod probes {
467-
fn task__spawn(task_id: u64) {}
468-
fn task__poll__start(task_id: u64) {}
469-
fn task__poll__end(task_id: u64) {}
470-
fn task__terminate(task_id: u64) {}
477+
fn task__spawn(task_id: u64, file: String, line: u32, col: u32) {}
478+
fn task__poll__start(task_id: u64, file: String, line: u32, col: u32) {}
479+
fn task__poll__end(task_id: u64, file: String, line: u32, col: u32) {}
480+
fn task__terminate(task_id: u64, file: String, line: u32, col: u32) {}
471481

472482
fn worker__thread__start() {}
473483
fn worker__thread__stop() {}

0 commit comments

Comments
 (0)