8
8
#include <errno.h>
9
9
#include <math.h>
10
10
#include <emscripten/threading.h>
11
- #include <stdbool.h>
12
11
#include <stdlib.h>
13
12
#include <stdio.h>
14
13
#include "atomic.h"
@@ -28,13 +27,13 @@ static int futex_wait_busy(volatile void *addr, uint32_t val, double timeout) {
28
27
// nonzero, the contents of the address pointed by __emscripten_main_thread_futex
29
28
// tell which address the main thread is simulating its wait on.
30
29
// We need to be careful of recursion here: If we wait on a futex, and
31
- // then call _emscripten_main_thread_process_queued_calls () below, that
32
- // will call code that takes the proxying mutex - which can once more
33
- // reach this code in a nested call. To avoid interference between the
34
- // two (there is just a single __emscripten_main_thread_futex at a time), unmark
35
- // ourselves before calling the potentially-recursive call. See below for
36
- // how we handle the case of our futex being notified during the time in
37
- // between when we are not set as the value of __emscripten_main_thread_futex.
30
+ // then call _emscripten_yield () below, that will call code that takes the
31
+ // proxying mutex - which can once more reach this code in a nested call. To
32
+ // avoid interference between the two (there is just a single
33
+ // __emscripten_main_thread_futex at a time), unmark ourselves before calling
34
+ // the potentially-recursive call. See below for how we handle the case of our
35
+ // futex being notified during the time in between when we are not set as the
36
+ // value of __emscripten_main_thread_futex.
38
37
void * last_addr = a_cas_p (& _emscripten_main_thread_futex , 0 , (void * )addr );
39
38
// We must not have already been waiting.
40
39
assert (last_addr == 0 );
@@ -62,13 +61,13 @@ static int futex_wait_busy(volatile void *addr, uint32_t val, double timeout) {
62
61
// We were told to stop waiting, so stop.
63
62
break ;
64
63
}
65
- emscripten_main_thread_process_queued_calls ();
64
+ _emscripten_yield ();
66
65
67
66
// Check the value, as if we were starting the futex all over again.
68
67
// This handles the following case:
69
68
//
70
69
// * wait on futex A
71
- // * recurse into emscripten_main_thread_process_queued_calls (),
70
+ // * recurse into _emscripten_yield (),
72
71
// which waits on futex B. that sets the __emscripten_main_thread_futex address to
73
72
// futex B, and there is no longer any mention of futex A.
74
73
// * a worker is done with futex A. it checks __emscripten_main_thread_futex but does
@@ -83,7 +82,7 @@ static int futex_wait_busy(volatile void *addr, uint32_t val, double timeout) {
83
82
// That case motivates the design here. Given that, checking the memory
84
83
// address is also necessary for other reasons: we unset and re-set our
85
84
// address in __emscripten_main_thread_futex around calls to
86
- // emscripten_main_thread_process_queued_calls (), and a worker could
85
+ // _emscripten_yield (), and a worker could
87
86
// attempt to wake us up right before/after such times.
88
87
//
89
88
// Note that checking the memory value of the futex is valid to do: we
@@ -92,11 +91,11 @@ static int futex_wait_busy(volatile void *addr, uint32_t val, double timeout) {
92
91
// later time when there is no need to block. The only "odd" thing is
93
92
// that we may have caused side effects in that "delay" time. But the
94
93
// only side effects we can have are to call
95
- // emscripten_main_thread_process_queued_calls (). That is always ok to
94
+ // _emscripten_yield (). That is always ok to
96
95
// do on the main thread (it's why it is ok for us to call it in the
97
96
// middle of this function, and elsewhere). So if we check the value
98
97
// here and return, it's the same is if what happened on the main thread
99
- // was the same as calling emscripten_main_thread_process_queued_calls ()
98
+ // was the same as calling _emscripten_yield ()
100
99
// a few times before calling emscripten_futex_wait().
101
100
if (__c11_atomic_load ((_Atomic uintptr_t * )addr , __ATOMIC_SEQ_CST ) != val ) {
102
101
return - EWOULDBLOCK ;
@@ -109,32 +108,12 @@ static int futex_wait_busy(volatile void *addr, uint32_t val, double timeout) {
109
108
return 0 ;
110
109
}
111
110
112
- static _Atomic bool thread_crashed = false;
113
-
114
- void _emscripten_thread_crashed () {
115
- thread_crashed = true;
116
- }
117
-
118
111
int emscripten_futex_wait (volatile void * addr , uint32_t val , double max_wait_ms ) {
119
112
if ((((intptr_t )addr )& 3 ) != 0 ) {
120
113
return - EINVAL ;
121
114
}
122
115
123
- if (emscripten_is_main_runtime_thread ()) {
124
- // When a secondary thread crashes, we need to be able to interrupt the main
125
- // thread even if it's in a blocking/looping on a mutex. We want to avoid
126
- // using the normal proxying mechanism to send this message since it can
127
- // allocate (or otherwise itself crash) so use a low level atomic primitive
128
- // for this signal.
129
- if (thread_crashed ) {
130
- // Return the event loop so we can handle the message from the crashed
131
- // thread.
132
- emscripten_unwind_to_js_event_loop ();
133
- }
134
-
135
- // Assist other threads by executing proxied operations that are effectively singlethreaded.
136
- emscripten_main_thread_process_queued_calls ();
137
- }
116
+ _emscripten_yield ();
138
117
139
118
int ret ;
140
119
emscripten_conditional_set_current_thread_status (EM_THREAD_STATUS_RUNNING , EM_THREAD_STATUS_WAITFUTEX );
0 commit comments