File tree Expand file tree Collapse file tree
src/runtime/scheduler/multi_thread Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -782,7 +782,13 @@ impl Context {
782782 }
783783
784784 pub ( crate ) fn defer ( & self , waker : & Waker ) {
785- self . defer . defer ( waker) ;
785+ if self . core . borrow ( ) . is_none ( ) {
786+ // If there is no core, then the worker is currently in a block_in_place. In this case,
787+ // we cannot use the defer queue as we aren't really in the current runtime.
788+ waker. wake_by_ref ( ) ;
789+ } else {
790+ self . defer . defer ( waker) ;
791+ }
786792 }
787793
788794 #[ allow( dead_code) ]
Original file line number Diff line number Diff line change @@ -126,6 +126,17 @@ fn unbounded_mpsc_channel() {
126126 } )
127127}
128128
129+ #[ test]
130+ fn yield_in_block_in_place ( ) {
131+ test_with_runtimes ( || {
132+ Handle :: current ( ) . block_on ( async {
133+ tokio:: task:: block_in_place ( || {
134+ Handle :: current ( ) . block_on ( tokio:: task:: yield_now ( ) ) ;
135+ } ) ;
136+ } ) ;
137+ } )
138+ }
139+
129140#[ cfg( not( target_os = "wasi" ) ) ] // Wasi doesn't support file operations or bind
130141rt_test ! {
131142 use tokio:: fs;
Original file line number Diff line number Diff line change @@ -647,6 +647,51 @@ fn test_nested_block_in_place_with_block_on_between() {
647647 }
648648}
649649
650+ #[ test]
651+ fn yield_now_in_block_in_place ( ) {
652+ let rt = runtime:: Builder :: new_multi_thread ( )
653+ . worker_threads ( 1 )
654+ . build ( )
655+ . unwrap ( ) ;
656+
657+ rt. block_on ( async {
658+ tokio:: spawn ( async {
659+ tokio:: task:: block_in_place ( || {
660+ tokio:: runtime:: Handle :: current ( ) . block_on ( tokio:: task:: yield_now ( ) ) ;
661+ } )
662+ } )
663+ . await
664+ . unwrap ( )
665+ } )
666+ }
667+
668+ #[ test]
669+ fn mutex_in_block_in_place ( ) {
670+ const BUDGET : usize = 128 ;
671+
672+ let rt = runtime:: Builder :: new_multi_thread ( )
673+ . worker_threads ( 1 )
674+ . build ( )
675+ . unwrap ( ) ;
676+
677+ rt. block_on ( async {
678+ let lock = tokio:: sync:: Mutex :: new ( 0 ) ;
679+
680+ tokio:: spawn ( async move {
681+ tokio:: task:: block_in_place ( || {
682+ tokio:: runtime:: Handle :: current ( ) . block_on ( async move {
683+ for i in 0 ..( BUDGET + 1 ) {
684+ let mut guard = lock. lock ( ) . await ;
685+ * guard = i;
686+ }
687+ } ) ;
688+ } )
689+ } )
690+ . await
691+ . unwrap ( ) ;
692+ } )
693+ }
694+
650695// Testing the tuning logic is tricky as it is inherently timing based, and more
651696// of a heuristic than an exact behavior. This test checks that the interval
652697// changes over time based on load factors. There are no assertions, completion
You can’t perform that action at this time.
0 commit comments