26
26
future:: Future ,
27
27
marker:: PhantomData ,
28
28
mem:: { self , MaybeUninit } ,
29
+ ops:: Range ,
29
30
pin:: { pin, Pin } ,
30
31
ptr:: { self , NonNull } ,
31
32
sync:: { Arc , Mutex } ,
@@ -323,6 +324,23 @@ impl<T: Copy> Drop for Reset<T> {
323
324
}
324
325
}
325
326
327
+ #[ derive( Clone , Copy ) ]
328
+ struct PollContext {
329
+ future_context : * mut Context < ' static > ,
330
+ guard_range_start : * mut u8 ,
331
+ guard_range_end : * mut u8 ,
332
+ }
333
+
334
+ impl Default for PollContext {
335
+ fn default ( ) -> PollContext {
336
+ PollContext {
337
+ future_context : core:: ptr:: null_mut ( ) ,
338
+ guard_range_start : core:: ptr:: null_mut ( ) ,
339
+ guard_range_end : core:: ptr:: null_mut ( ) ,
340
+ }
341
+ }
342
+ }
343
+
326
344
struct AsyncState {
327
345
current_suspend : UnsafeCell <
328
346
* mut Suspend <
@@ -331,7 +349,7 @@ struct AsyncState {
331
349
( Option < * mut dyn VMStore > , Result < ( ) > ) ,
332
350
> ,
333
351
> ,
334
- current_poll_cx : UnsafeCell < * mut Context < ' static > > ,
352
+ current_poll_cx : UnsafeCell < PollContext > ,
335
353
}
336
354
337
355
unsafe impl Send for AsyncState { }
@@ -344,26 +362,35 @@ pub(crate) struct AsyncCx {
344
362
( Option < * mut dyn VMStore > , Result < ( ) > ) ,
345
363
> ,
346
364
current_stack_limit : * mut usize ,
347
- current_poll_cx : * mut * mut Context < ' static > ,
365
+ current_poll_cx : * mut PollContext ,
348
366
track_pkey_context_switch : bool ,
349
367
}
350
368
351
369
impl AsyncCx {
352
370
pub ( crate ) fn new < T > ( store : & mut StoreContextMut < T > ) -> Self {
353
- Self {
354
- current_suspend : store. concurrent_state ( ) . async_state . current_suspend . get ( ) ,
355
- current_stack_limit : store. 0 . runtime_limits ( ) . stack_limit . get ( ) ,
356
- current_poll_cx : store. concurrent_state ( ) . async_state . current_poll_cx . get ( ) ,
357
- track_pkey_context_switch : store. has_pkey ( ) ,
371
+ Self :: try_new ( store) . unwrap ( )
372
+ }
373
+
374
+ pub ( crate ) fn try_new < T > ( store : & mut StoreContextMut < T > ) -> Option < Self > {
375
+ let current_poll_cx = store. concurrent_state ( ) . async_state . current_poll_cx . get ( ) ;
376
+ if unsafe { ( * current_poll_cx) . future_context . is_null ( ) } {
377
+ None
378
+ } else {
379
+ Some ( Self {
380
+ current_suspend : store. concurrent_state ( ) . async_state . current_suspend . get ( ) ,
381
+ current_stack_limit : store. 0 . runtime_limits ( ) . stack_limit . get ( ) ,
382
+ current_poll_cx,
383
+ track_pkey_context_switch : store. has_pkey ( ) ,
384
+ } )
358
385
}
359
386
}
360
387
361
388
unsafe fn poll < U > ( & self , mut future : Pin < & mut ( dyn Future < Output = U > + Send ) > ) -> Poll < U > {
362
389
let poll_cx = * self . current_poll_cx ;
363
390
let _reset = Reset ( self . current_poll_cx , poll_cx) ;
364
- * self . current_poll_cx = ptr :: null_mut ( ) ;
365
- assert ! ( !poll_cx. is_null( ) ) ;
366
- future. as_mut ( ) . poll ( & mut * poll_cx)
391
+ * self . current_poll_cx = PollContext :: default ( ) ;
392
+ assert ! ( !poll_cx. future_context . is_null( ) ) ;
393
+ future. as_mut ( ) . poll ( & mut * poll_cx. future_context )
367
394
}
368
395
369
396
pub ( crate ) unsafe fn block_on < ' a , T , U > (
@@ -420,6 +447,13 @@ pub struct ConcurrentState<T> {
420
447
_phantom : PhantomData < T > ,
421
448
}
422
449
450
+ impl < T > ConcurrentState < T > {
451
+ pub ( crate ) fn async_guard_range ( & self ) -> Range < * mut u8 > {
452
+ let context = unsafe { * self . async_state . current_poll_cx . get ( ) } ;
453
+ context. guard_range_start ..context. guard_range_end
454
+ }
455
+ }
456
+
423
457
impl < T > Default for ConcurrentState < T > {
424
458
fn default ( ) -> Self {
425
459
Self {
@@ -428,7 +462,7 @@ impl<T> Default for ConcurrentState<T> {
428
462
futures : ReadyChunks :: new ( FuturesUnordered :: new ( ) , 1024 ) ,
429
463
async_state : AsyncState {
430
464
current_suspend : UnsafeCell :: new ( ptr:: null_mut ( ) ) ,
431
- current_poll_cx : UnsafeCell :: new ( ptr :: null_mut ( ) ) ,
465
+ current_poll_cx : UnsafeCell :: new ( PollContext :: default ( ) ) ,
432
466
} ,
433
467
instance_states : HashMap :: new ( ) ,
434
468
yielding : HashSet :: new ( ) ,
@@ -622,7 +656,7 @@ pub(crate) fn poll_and_block<'a, T, R: Send + Sync + 'static>(
622
656
623
657
pub ( crate ) async fn on_fiber < ' a , R : Send + Sync + ' static , T : Send > (
624
658
mut store : StoreContextMut < ' a , T > ,
625
- instance : RuntimeComponentInstanceIndex ,
659
+ instance : Option < RuntimeComponentInstanceIndex > ,
626
660
func : impl FnOnce ( & mut StoreContextMut < T > ) -> R + Send ,
627
661
) -> Result < ( R , StoreContextMut < ' a , T > ) > {
628
662
let result = Arc :: new ( Mutex :: new ( None ) ) ;
@@ -634,7 +668,21 @@ pub(crate) async fn on_fiber<'a, R: Send + Sync + 'static, T: Send>(
634
668
}
635
669
} ) ?;
636
670
637
- store = poll_fn ( store, move |_, mut store| {
671
+ let guard_range = fiber
672
+ . fiber
673
+ . as_ref ( )
674
+ . unwrap ( )
675
+ . stack ( )
676
+ . guard_range ( )
677
+ . map ( |r| {
678
+ (
679
+ NonNull :: new ( r. start ) . map ( SendSyncPtr :: new) ,
680
+ NonNull :: new ( r. end ) . map ( SendSyncPtr :: new) ,
681
+ )
682
+ } )
683
+ . unwrap_or ( ( None , None ) ) ;
684
+
685
+ store = poll_fn ( store, guard_range, move |_, mut store| {
638
686
match resume_fiber ( & mut fiber, store. take ( ) , Ok ( ( ) ) ) {
639
687
Ok ( Ok ( ( store, result) ) ) => Ok ( result. map ( |( ) | store) ) ,
640
688
Ok ( Err ( s) ) => Err ( s) ,
@@ -761,36 +809,40 @@ fn resume_stackful<'a, T>(
761
809
match resume_fiber ( & mut fiber, Some ( store) , Ok ( ( ) ) ) ? {
762
810
Ok ( ( mut store, result) ) => {
763
811
result?;
764
- store = maybe_resume_next_task ( store, fiber. instance ) ?;
765
- for ( event, call, _) in mem:: take (
766
- & mut store
767
- . concurrent_state ( )
768
- . table
769
- . get_mut ( guest_task)
770
- . with_context ( || format ! ( "bad handle: {}" , guest_task. rep( ) ) ) ?
771
- . events ,
772
- ) {
773
- if event == events:: EVENT_CALL_DONE {
774
- log:: trace!( "resume_stackful will delete call {}" , call. rep( ) ) ;
775
- call. delete_all_from ( store. as_context_mut ( ) ) ?;
776
- }
777
- }
778
- match & store. concurrent_state ( ) . table . get ( guest_task) ?. caller {
779
- Caller :: Host ( _) => {
780
- log:: trace!( "resume_stackful will delete task {}" , guest_task. rep( ) ) ;
781
- AnyTask :: Guest ( guest_task) . delete_all_from ( store. as_context_mut ( ) ) ?;
782
- Ok ( store)
812
+ if let Some ( instance) = fiber. instance {
813
+ store = maybe_resume_next_task ( store, instance) ?;
814
+ for ( event, call, _) in mem:: take (
815
+ & mut store
816
+ . concurrent_state ( )
817
+ . table
818
+ . get_mut ( guest_task)
819
+ . with_context ( || format ! ( "bad handle: {}" , guest_task. rep( ) ) ) ?
820
+ . events ,
821
+ ) {
822
+ if event == events:: EVENT_CALL_DONE {
823
+ log:: trace!( "resume_stackful will delete call {}" , call. rep( ) ) ;
824
+ call. delete_all_from ( store. as_context_mut ( ) ) ?;
825
+ }
783
826
}
784
- Caller :: Guest { task, .. } => {
785
- let task = * task;
786
- maybe_send_event (
787
- store,
788
- task,
789
- events:: EVENT_CALL_DONE ,
790
- AnyTask :: Guest ( guest_task) ,
791
- 0 ,
792
- )
827
+ match & store. concurrent_state ( ) . table . get ( guest_task) ?. caller {
828
+ Caller :: Host ( _) => {
829
+ log:: trace!( "resume_stackful will delete task {}" , guest_task. rep( ) ) ;
830
+ AnyTask :: Guest ( guest_task) . delete_all_from ( store. as_context_mut ( ) ) ?;
831
+ Ok ( store)
832
+ }
833
+ Caller :: Guest { task, .. } => {
834
+ let task = * task;
835
+ maybe_send_event (
836
+ store,
837
+ task,
838
+ events:: EVENT_CALL_DONE ,
839
+ AnyTask :: Guest ( guest_task) ,
840
+ 0 ,
841
+ )
842
+ }
793
843
}
844
+ } else {
845
+ Ok ( store)
794
846
}
795
847
}
796
848
Err ( new_store) => {
@@ -1029,7 +1081,7 @@ struct StoreFiber<'a> {
1029
1081
( Option < * mut dyn VMStore > , Result < ( ) > ) ,
1030
1082
> ,
1031
1083
stack_limit : * mut usize ,
1032
- instance : RuntimeComponentInstanceIndex ,
1084
+ instance : Option < RuntimeComponentInstanceIndex > ,
1033
1085
}
1034
1086
1035
1087
impl < ' a > Drop for StoreFiber < ' a > {
@@ -1054,7 +1106,7 @@ unsafe impl<'a> Sync for StoreFiber<'a> {}
1054
1106
1055
1107
fn make_fiber < ' a , T > (
1056
1108
store : & mut StoreContextMut < T > ,
1057
- instance : RuntimeComponentInstanceIndex ,
1109
+ instance : Option < RuntimeComponentInstanceIndex > ,
1058
1110
fun : impl FnOnce ( StoreContextMut < T > ) -> Result < ( ) > + ' a ,
1059
1111
) -> Result < StoreFiber < ' a > > {
1060
1112
let engine = store. engine ( ) . clone ( ) ;
@@ -1118,9 +1170,11 @@ unsafe fn resume_fiber_raw<'a>(
1118
1170
fn poll_ready < ' a , T > ( mut store : StoreContextMut < ' a , T > ) -> Result < StoreContextMut < ' a , T > > {
1119
1171
unsafe {
1120
1172
let cx = * store. concurrent_state ( ) . async_state . current_poll_cx . get ( ) ;
1121
- assert ! ( !cx. is_null( ) ) ;
1122
- while let Poll :: Ready ( Some ( ready) ) =
1123
- store. concurrent_state ( ) . futures . poll_next_unpin ( & mut * cx)
1173
+ assert ! ( !cx. future_context. is_null( ) ) ;
1174
+ while let Poll :: Ready ( Some ( ready) ) = store
1175
+ . concurrent_state ( )
1176
+ . futures
1177
+ . poll_next_unpin ( & mut * cx. future_context )
1124
1178
{
1125
1179
match handle_ready ( store, ready) {
1126
1180
Ok ( s) => {
@@ -1691,7 +1745,7 @@ fn do_start_call<'a, T>(
1691
1745
cx
1692
1746
}
1693
1747
} else {
1694
- let mut fiber = make_fiber ( & mut cx, callee_instance, move |mut cx| {
1748
+ let mut fiber = make_fiber ( & mut cx, Some ( callee_instance) , move |mut cx| {
1695
1749
if !async_ {
1696
1750
cx. concurrent_state ( )
1697
1751
. instance_states
@@ -2017,12 +2071,12 @@ pub(crate) async fn poll_until<'a, T: Send, U>(
2017
2071
. await ;
2018
2072
2019
2073
if ready. is_some ( ) {
2020
- store = poll_fn ( store, move |_, mut store| {
2074
+ store = poll_fn ( store, ( None , None ) , move |_, mut store| {
2021
2075
Ok ( handle_ready ( store. take ( ) . unwrap ( ) , ready. take ( ) . unwrap ( ) ) )
2022
2076
} )
2023
2077
. await ?;
2024
2078
} else {
2025
- let ( s, resumed) = poll_fn ( store, move |_, mut store| {
2079
+ let ( s, resumed) = poll_fn ( store, ( None , None ) , move |_, mut store| {
2026
2080
Ok ( unyield ( store. take ( ) . unwrap ( ) ) )
2027
2081
} )
2028
2082
. await ?;
@@ -2039,7 +2093,7 @@ pub(crate) async fn poll_until<'a, T: Send, U>(
2039
2093
Either :: Left ( ( None , future_again) ) => break Ok ( ( store, future_again. await ) ) ,
2040
2094
Either :: Left ( ( Some ( ready) , future_again) ) => {
2041
2095
let mut ready = Some ( ready) ;
2042
- store = poll_fn ( store, move |_, mut store| {
2096
+ store = poll_fn ( store, ( None , None ) , move |_, mut store| {
2043
2097
Ok ( handle_ready ( store. take ( ) . unwrap ( ) , ready. take ( ) . unwrap ( ) ) )
2044
2098
} )
2045
2099
. await ?;
@@ -2052,13 +2106,14 @@ pub(crate) async fn poll_until<'a, T: Send, U>(
2052
2106
2053
2107
async fn poll_fn < ' a , T , R > (
2054
2108
mut store : StoreContextMut < ' a , T > ,
2109
+ guard_range : ( Option < SendSyncPtr < u8 > > , Option < SendSyncPtr < u8 > > ) ,
2055
2110
mut fun : impl FnMut (
2056
2111
& mut Context ,
2057
2112
Option < StoreContextMut < ' a , T > > ,
2058
2113
) -> Result < R , Option < StoreContextMut < ' a , T > > > ,
2059
2114
) -> R {
2060
2115
#[ derive( Clone , Copy ) ]
2061
- struct PollCx ( * mut * mut Context < ' static > ) ;
2116
+ struct PollCx ( * mut PollContext ) ;
2062
2117
2063
2118
unsafe impl Send for PollCx { }
2064
2119
@@ -2068,7 +2123,13 @@ async fn poll_fn<'a, T, R>(
2068
2123
2069
2124
move |cx| unsafe {
2070
2125
let _reset = Reset ( poll_cx. 0 , * poll_cx. 0 ) ;
2071
- * poll_cx. 0 = mem:: transmute :: < & mut Context < ' _ > , * mut Context < ' static > > ( cx) ;
2126
+ let guard_range_start = guard_range. 0 . map ( |v| v. as_ptr ( ) ) . unwrap_or ( ptr:: null_mut ( ) ) ;
2127
+ let guard_range_end = guard_range. 1 . map ( |v| v. as_ptr ( ) ) . unwrap_or ( ptr:: null_mut ( ) ) ;
2128
+ * poll_cx. 0 = PollContext {
2129
+ future_context : mem:: transmute :: < & mut Context < ' _ > , * mut Context < ' static > > ( cx) ,
2130
+ guard_range_start,
2131
+ guard_range_end,
2132
+ } ;
2072
2133
#[ allow( dropping_copy_types) ]
2073
2134
drop ( poll_cx) ;
2074
2135
0 commit comments