@@ -893,7 +893,7 @@ basket_type_name(enum ractor_basket_type type)
893
893
894
894
//
895
895
896
- #else // win32
896
+ #else // win32 + wasm
897
897
898
898
static void
899
899
ractor_cond_wait (rb_ractor_t * r , rb_thread_t * th )
@@ -903,7 +903,10 @@ ractor_cond_wait(rb_ractor_t *r, rb_thread_t *th)
903
903
VM_ASSERT (locked_by && locked_by != Qnil );
904
904
r -> sync .locked_by = Qnil ;
905
905
#endif
906
- rb_native_cond_wait (& th -> sched .ractor_action_wakeup_cond , & r -> sync .lock );
906
+ th -> status = THREAD_STOPPED_FOREVER ;
907
+ while (th -> status == THREAD_STOPPED_FOREVER ) {
908
+ rb_native_cond_wait (& th -> sched .ractor_action_wakeup_cond , & r -> sync .lock );
909
+ }
907
910
908
911
#if RACTOR_CHECK_MODE > 0
909
912
r -> sync .locked_by = locked_by ;
@@ -943,15 +946,14 @@ rb_ractor_sched_wait(rb_execution_context_t *ec, rb_ractor_t *cr, rb_unblock_fun
943
946
static void
944
947
rb_ractor_sched_wakeup (rb_ractor_t * r , rb_thread_t * th )
945
948
{
946
- RACTOR_LOCK ( r );
947
- {
949
+ if ( th -> status == THREAD_STOPPED_FOREVER ) {
950
+ th -> status = THREAD_RUNNABLE ;
948
951
rb_native_cond_signal (& th -> sched .ractor_action_wakeup_cond );
949
952
}
950
- RACTOR_UNLOCK (r );
951
953
}
952
954
#endif
953
955
954
- // Wake up all ractors that are currently blocked on `rp`
956
+ // TODO: wake up all threads on r that are currently blocked on `rp`, not all threads on r
955
957
static void
956
958
ractor_wakeup_all (const struct ractor_port * rp , enum ractor_wakeup_status wakeup_status )
957
959
{
@@ -960,40 +962,21 @@ ractor_wakeup_all(const struct ractor_port *rp, enum ractor_wakeup_status wakeup
960
962
961
963
RUBY_DEBUG_LOG ("r:%u wakeup:%s" , rb_ractor_id (r ), wakeup_status_str (wakeup_status ));
962
964
963
- struct ractor_waiter * waiter ;
964
- struct ractor_waiter * * waiters_on_port = NULL ;
965
- int num_waiters = 0 ;
966
965
RACTOR_LOCK (r );
967
- {
968
- if (!ccan_list_empty (& r -> sync .waiters )) {
969
- ccan_list_for_each (& r -> sync .waiters , waiter , node ) {
970
- if (waiter -> wakeup_status == wakeup_none && (!waiter -> port || ractor_port_id (waiter -> port ) == ractor_port_id (rp ))) {
971
- num_waiters ++ ;
972
- }
973
- }
974
- if (num_waiters > 0 ) {
975
- waiters_on_port = ALLOC_N (struct ractor_waiter * , num_waiters );
976
- int i = 0 ;
977
- ccan_list_for_each (& r -> sync .waiters , waiter , node ) {
978
- if (waiter -> wakeup_status == wakeup_none && (!waiter -> port || ractor_port_id (waiter -> port ) == ractor_port_id (rp ))) {
979
- waiter -> wakeup_status = wakeup_status ;
980
- waiters_on_port [i ++ ] = waiter ;
981
- }
982
- }
983
- for (int i = 0 ; i < num_waiters ; i ++ ) {
984
- ccan_list_del (& waiters_on_port [i ]-> node );
985
- }
986
- }
966
+ while (1 ) {
967
+ struct ractor_waiter * waiter = ccan_list_pop (& r -> sync .waiters , struct ractor_waiter , node );
968
+
969
+ if (waiter ) {
970
+ VM_ASSERT (waiter -> wakeup_status == wakeup_none );
971
+
972
+ waiter -> wakeup_status = wakeup_status ;
973
+ rb_ractor_sched_wakeup (r , waiter -> th );
974
+ }
975
+ else {
976
+ break ;
987
977
}
988
978
}
989
979
RACTOR_UNLOCK (r );
990
-
991
- for (int i = 0 ; i < num_waiters ; i ++ ) {
992
- waiter = waiters_on_port [i ];
993
- RUBY_ASSERT (!waiter -> port || ractor_port_id (waiter -> port ) == ractor_port_id (rp ));
994
- rb_ractor_sched_wakeup (r , waiter -> th );
995
- }
996
- if (waiters_on_port ) ruby_xfree (waiters_on_port );
997
980
}
998
981
999
982
static void
@@ -1010,22 +993,18 @@ ubf_ractor_wait(void *ptr)
1010
993
1011
994
rb_native_mutex_unlock (& th -> interrupt_lock );
1012
995
{
1013
- bool should_wake = false;
1014
996
RACTOR_LOCK (r );
1015
997
{
1016
998
if (waiter -> wakeup_status == wakeup_none ) {
1017
999
RUBY_DEBUG_LOG ("waiter:%p" , (void * )waiter );
1018
1000
1019
1001
waiter -> wakeup_status = wakeup_by_interrupt ;
1020
1002
ccan_list_del (& waiter -> node );
1021
- should_wake = true ;
1003
+ rb_ractor_sched_wakeup ( r , th ) ;
1022
1004
}
1023
1005
}
1024
1006
RACTOR_UNLOCK (r );
1025
1007
1026
- if (should_wake ) {
1027
- rb_ractor_sched_wakeup (r , th );
1028
- }
1029
1008
}
1030
1009
rb_native_mutex_lock (& th -> interrupt_lock );
1031
1010
}
@@ -1104,7 +1083,7 @@ ractor_check_received(rb_ractor_t *cr, struct ractor_queue *messages)
1104
1083
return received ;
1105
1084
}
1106
1085
1107
- // The port can be NULL when you're waiting on any ractor to wake you up, such as with `Ractor.select(*ractors)`
1086
+ // The port `rp` can be NULL when you're waiting on multiple ractors to wake you up, such as with `Ractor.select(*ractors)`
1108
1087
static void
1109
1088
ractor_wait_receive (rb_execution_context_t * ec , rb_ractor_t * cr , const struct ractor_port * rp )
1110
1089
{
@@ -1114,7 +1093,7 @@ ractor_wait_receive(rb_execution_context_t *ec, rb_ractor_t *cr, const struct ra
1114
1093
RACTOR_LOCK_SELF (cr );
1115
1094
{
1116
1095
if (ractor_check_received (cr , & messages )) {
1117
- deliverred = true;
1096
+ deliverred = true; // any message was delivered, not necessarily to this port
1118
1097
}
1119
1098
else {
1120
1099
ractor_wait (ec , cr , rp );
@@ -1432,7 +1411,7 @@ ractor_selector__wait(rb_execution_context_t *ec, VALUE selector)
1432
1411
return rb_ary_new_from_args (2 , data .rpv , data .v );
1433
1412
}
1434
1413
1435
- ractor_wait_receive (ec , cr , NULL ); // wait on any ractor port
1414
+ ractor_wait_receive (ec , cr , NULL ); // wait on any ractor port. TODO: should only wait on a group of ports
1436
1415
}
1437
1416
}
1438
1417
0 commit comments