@@ -112,33 +112,29 @@ void emscripten_thread_sleep(double msecs) {
112
112
double now = emscripten_get_now ();
113
113
double target = now + msecs ;
114
114
115
- __pthread_testcancel (); // pthreads spec: sleep is a cancellation point, so must test if this
116
- // thread is cancelled during the sleep.
117
- emscripten_current_thread_process_queued_calls ();
118
-
119
115
// If we have less than this many msecs left to wait, busy spin that instead.
120
- const double minimumTimeSliceToSleep = 0.1 ;
116
+ const double minTimeSliceToSleep = 0.1 ;
121
117
122
- // main thread may need to run proxied calls, so sleep in very small slices to be responsive.
118
+ // Main browser thread may need to run proxied calls, so sleep in very small slices to be responsive.
123
119
const double maxMsecsSliceToSleep = emscripten_is_main_browser_thread () ? 1 : 100 ;
124
120
125
121
emscripten_conditional_set_current_thread_status (
126
122
EM_THREAD_STATUS_RUNNING , EM_THREAD_STATUS_SLEEPING );
127
- now = emscripten_get_now ();
128
- while (now < target ) {
123
+
124
+ double msecsToSleep ;
125
+ do {
129
126
// Keep processing the main loop of the calling thread.
130
127
__pthread_testcancel (); // pthreads spec: sleep is a cancellation point, so must test if this
131
128
// thread is cancelled during the sleep.
132
129
emscripten_current_thread_process_queued_calls ();
133
130
134
- now = emscripten_get_now ();
135
- double msecsToSleep = target - now ;
136
- if (msecsToSleep > maxMsecsSliceToSleep )
137
- msecsToSleep = maxMsecsSliceToSleep ;
138
- if (msecsToSleep >= minimumTimeSliceToSleep )
139
- emscripten_futex_wait (& dummyZeroAddress , 0 , msecsToSleep );
140
- now = emscripten_get_now ();
141
- };
131
+ msecsToSleep = target - emscripten_get_now ();
132
+ if (msecsToSleep < minTimeSliceToSleep )
133
+ continue ;
134
+
135
+ __builtin_wasm_memory_atomic_wait32 ((int * )& dummyZeroAddress , 0 ,
136
+ (msecsToSleep > maxMsecsSliceToSleep ? maxMsecsSliceToSleep : msecsToSleep ) * /*NSEC_PER_MSEC*/ 1000000 );
137
+ } while (msecsToSleep > 0 );
142
138
143
139
emscripten_conditional_set_current_thread_status (
144
140
EM_THREAD_STATUS_SLEEPING , EM_THREAD_STATUS_RUNNING );
@@ -336,7 +332,7 @@ static void _do_call(em_queued_call* q) {
336
332
} else {
337
333
// The caller owns this call object, it is listening to it and will free it up.
338
334
q -> operationDone = 1 ;
339
- emscripten_futex_wake ( & q -> operationDone , INT_MAX );
335
+ __builtin_wasm_memory_atomic_notify (( int * ) & q -> operationDone , -1 );
340
336
}
341
337
}
342
338
@@ -390,25 +386,27 @@ static CallQueue* GetOrAllocateQueue(
390
386
return q ;
391
387
}
392
388
389
+ // TODO(kleisauke): All paths call this with timeoutMSecs == INFINITY, perhaps drop this param?
393
390
EMSCRIPTEN_RESULT emscripten_wait_for_call_v (em_queued_call * call , double timeoutMSecs ) {
391
+ int done = emscripten_atomic_load_u32 (& call -> operationDone );
392
+ if (done ) return EMSCRIPTEN_RESULT_SUCCESS ;
393
+
394
+ int waitIndefinitely = isinf (timeoutMSecs );
395
+
396
+ emscripten_set_current_thread_status (EM_THREAD_STATUS_WAITPROXY );
397
+
398
+ double timeoutUntilTime = emscripten_get_now () + timeoutMSecs ;
394
399
int r ;
400
+ do {
401
+ r = __builtin_wasm_memory_atomic_wait32 ((int * )& call -> operationDone , 0 ,
402
+ waitIndefinitely ? -1 : (timeoutMSecs * /*NSEC_PER_MSEC*/ 1000000 ));
395
403
396
- int done = emscripten_atomic_load_u32 (& call -> operationDone );
397
- if (!done ) {
398
- double now = emscripten_get_now ();
399
- double waitEndTime = now + timeoutMSecs ;
400
- emscripten_set_current_thread_status (EM_THREAD_STATUS_WAITPROXY );
401
- while (!done && now < waitEndTime ) {
402
- r = emscripten_futex_wait (& call -> operationDone , 0 , waitEndTime - now );
403
- done = emscripten_atomic_load_u32 (& call -> operationDone );
404
- now = emscripten_get_now ();
405
- }
406
- emscripten_set_current_thread_status (EM_THREAD_STATUS_RUNNING );
407
- }
408
- if (done )
409
- return EMSCRIPTEN_RESULT_SUCCESS ;
410
- else
411
- return EMSCRIPTEN_RESULT_TIMED_OUT ;
404
+ timeoutMSecs = timeoutUntilTime - emscripten_get_now ();
405
+ } while (r == /*ETIMEDOUT*/ 2 && timeoutMSecs > 0 );
406
+
407
+ emscripten_set_current_thread_status (EM_THREAD_STATUS_RUNNING );
408
+
409
+ return r == 0 ? EMSCRIPTEN_RESULT_SUCCESS : EMSCRIPTEN_RESULT_TIMED_OUT ;
412
410
}
413
411
414
412
EMSCRIPTEN_RESULT emscripten_wait_for_call_i (
@@ -470,7 +468,7 @@ int _emscripten_do_dispatch_to_thread(
470
468
// If queue of the main browser thread is full, then we wait. (never drop messages for the main
471
469
// browser thread)
472
470
if (target_thread == emscripten_main_browser_thread_id ()) {
473
- emscripten_futex_wait (( void * )& q -> call_queue_head , head , INFINITY );
471
+ __builtin_wasm_memory_atomic_wait32 (( int * )& q -> call_queue_head , head , -1 );
474
472
pthread_mutex_lock (& call_queue_lock );
475
473
head = emscripten_atomic_load_u32 ((void * )& q -> call_queue_head );
476
474
tail = emscripten_atomic_load_u32 ((void * )& q -> call_queue_tail );
@@ -680,7 +678,7 @@ void emscripten_current_thread_process_queued_calls() {
680
678
pthread_mutex_unlock (& call_queue_lock );
681
679
682
680
// If the queue was full and we had waiters pending to get to put data to queue, wake them up.
683
- emscripten_futex_wake (( void * )& q -> call_queue_head , 0x7FFFFFFF );
681
+ __builtin_wasm_memory_atomic_notify (( int * )& q -> call_queue_head , -1 );
684
682
685
683
if (emscripten_is_main_browser_thread ())
686
684
bool_main_thread_inside_nested_process_queued_calls = 0 ;
0 commit comments