File tree 7 files changed +379
-75
lines changed
7 files changed +379
-75
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,29 @@ 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
+ ) ;
40
48
}
41
49
42
50
#[ cfg( not( all(
Original file line number Diff line number Diff line change @@ -341,15 +341,40 @@ 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( async {
353
+ let handle = handle;
354
+ handle. dump( ) . await
355
+ } ) . await
356
+ } ,
350
357
}
351
358
}
352
359
}
360
+
361
+ cfg_rt_multi_thread! {
362
+ /// Spawn a new thread and asynchronously await on its result.
363
+ async fn spawn_thread<F >( f: F ) -> <F as Future >:: Output
364
+ where
365
+ F : Future + Send + ' static ,
366
+ <F as Future >:: Output : Send + ' static
367
+ {
368
+ let ( tx, rx) = crate :: sync:: oneshot:: channel( ) ;
369
+ crate :: loom:: thread:: spawn( || {
370
+ let rt = crate :: runtime:: Builder :: new_current_thread( ) . build( ) . unwrap( ) ;
371
+ rt. block_on( async {
372
+ let _ = tx. send( f. await ) ;
373
+ } ) ;
374
+ } ) ;
375
+ rx. await . unwrap( )
376
+ }
377
+ }
353
378
}
354
379
355
380
/// 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 ) async 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 ) . await ;
105
+
106
+ let result = loop {
107
+ if let Some ( result) = trace_status. take_result( ) {
108
+ break result;
109
+ } else {
110
+ self . notify_all( ) ;
111
+ trace_status. result_ready. notified( ) . await ;
112
+ }
113
+ } ;
114
+
115
+ // Allow other queued dumps to proceed.
116
+ trace_status. end_trace_request( & self ) . await ;
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