File tree 7 files changed +372
-76
lines changed
7 files changed +372
-76
lines changed Original file line number Diff line number Diff line change 6
6
target_os = "linux" ,
7
7
any( target_arch = "aarch64" , target_arch = "x86" , target_arch = "x86_64" )
8
8
) ) ]
9
- #[ tokio:: main( flavor = "current_thread" ) ]
9
+ #[ tokio:: main]
10
10
async fn main ( ) {
11
11
use std:: hint:: black_box;
12
12
@@ -22,21 +22,30 @@ async fn main() {
22
22
23
23
#[ inline( never) ]
24
24
async fn c ( ) {
25
- black_box ( tokio:: task:: yield_now ( ) ) . await
25
+ loop {
26
+ tokio:: task:: yield_now ( ) . await ;
27
+ }
26
28
}
27
29
28
- tokio :: spawn ( a ( ) ) ;
29
- tokio:: spawn ( b ( ) ) ;
30
- tokio :: spawn ( c ( ) ) ;
30
+ async fn dump ( ) {
31
+ let handle = tokio:: runtime :: Handle :: current ( ) ;
32
+ let dump = handle . dump ( ) . await ;
31
33
32
- let handle = tokio:: runtime:: Handle :: current ( ) ;
33
- let dump = handle. dump ( ) ;
34
-
35
- for ( i, task) in dump. tasks ( ) . iter ( ) . enumerate ( ) {
36
- let trace = task. trace ( ) ;
37
- println ! ( "task {i} trace:" ) ;
38
- println ! ( "{trace}" ) ;
34
+ for ( i, task) in dump. tasks ( ) . iter ( ) . enumerate ( ) {
35
+ let trace = task. trace ( ) ;
36
+ println ! ( "task {i} trace:" ) ;
37
+ println ! ( "{trace}\n " ) ;
38
+ }
39
39
}
40
+
41
+ tokio:: select!(
42
+ biased;
43
+ _ = tokio:: spawn( a( ) ) => { } ,
44
+ _ = tokio:: spawn( b( ) ) => { } ,
45
+ _ = tokio:: spawn( c( ) ) => { } ,
46
+ _ = dump( ) => { } ,
47
+ ) ;
48
+
40
49
}
41
50
42
51
#[ cfg( not( all(
Original file line number Diff line number Diff line change @@ -341,15 +341,37 @@ cfg_metrics! {
341
341
cfg_taskdump ! {
342
342
impl Handle {
343
343
/// Capture a snapshot of this runtime's state.
344
- pub fn dump( & self ) -> crate :: runtime:: Dump {
344
+ pub async fn dump( & self ) -> crate :: runtime:: Dump {
345
345
match & self . inner {
346
346
scheduler:: Handle :: CurrentThread ( handle) => handle. dump( ) ,
347
347
#[ cfg( all( feature = "rt-multi-thread" , not( tokio_wasi) ) ) ]
348
- scheduler:: Handle :: MultiThread ( _) =>
349
- unimplemented!( "taskdumps are unsupported on the multi-thread runtime" ) ,
348
+ scheduler:: Handle :: MultiThread ( handle) => {
349
+ // perform the trace in a separate thread so that the
350
+ // trace itself does not appear in the taskdump.
351
+ let handle = handle. clone( ) ;
352
+ spawn_thread( || {
353
+ let handle = handle;
354
+ handle. dump( )
355
+ } ) . await
356
+ } ,
350
357
}
351
358
}
352
359
}
360
+
361
+ /// Spawn a new thread and asynchronously await on its result.
362
+ async fn spawn_thread<F , T >( f: F ) -> T
363
+ where
364
+ F : FnOnce ( ) -> T + Send + ' static ,
365
+ T : Send + ' static
366
+ {
367
+ let ( tx, rx) = crate :: sync:: oneshot:: channel( ) ;
368
+ crate :: loom:: thread:: spawn( || {
369
+ if tx. send( f( ) ) . is_err( ) {
370
+ unreachable!( "send failed" ) ;
371
+ }
372
+ } ) ;
373
+ rx. await . unwrap( )
374
+ }
353
375
}
354
376
355
377
/// Error returned by `try_current` when no Runtime has been started
Original file line number Diff line number Diff line change @@ -95,6 +95,31 @@ cfg_metrics! {
95
95
}
96
96
}
97
97
98
+ cfg_taskdump ! {
99
+ impl Handle {
100
+ pub ( crate ) fn dump( & self ) -> crate :: runtime:: Dump {
101
+ let trace_status = & self . shared. trace_status;
102
+
103
+ // If a dump is in progress, block.
104
+ trace_status. start_trace_request( & self ) ;
105
+
106
+ let result = loop {
107
+ if let Some ( result) = trace_status. take_result( ) {
108
+ break result;
109
+ } else {
110
+ self . notify_all( ) ;
111
+ crate :: loom:: thread:: yield_now( ) ;
112
+ }
113
+ } ;
114
+
115
+ // Allow other queued dumps to proceed.
116
+ trace_status. end_trace_request( & self ) ;
117
+
118
+ result
119
+ }
120
+ }
121
+ }
122
+
98
123
impl fmt:: Debug for Handle {
99
124
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
100
125
fmt. debug_struct ( "multi_thread::Handle { ... }" ) . finish ( )
You can’t perform that action at this time.
0 commit comments