Skip to content

Commit 58ebb04

Browse files
committed
Move emscripten_futex_wake to native code. NFC
1 parent ad282f9 commit 58ebb04

9 files changed

+63
-40
lines changed

src/library_pthread.js

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -951,42 +951,6 @@ var LibraryPThread = {
951951
return 0;
952952
},
953953

954-
// Returns the number of threads (>= 0) woken up, or the value -EINVAL on error.
955-
// Pass count == INT_MAX to wake up all threads.
956-
emscripten_futex_wake: function(addr, count) {
957-
if (addr <= 0 || addr > HEAP8.length || addr&3 != 0 || count < 0) return -{{{ cDefine('EINVAL') }}};
958-
if (count == 0) return 0;
959-
// Waking (at least) INT_MAX waiters is defined to mean wake all callers.
960-
// For Atomics.notify() API Infinity is to be passed in that case.
961-
if (count >= {{{ cDefine('INT_MAX') }}}) count = Infinity;
962-
963-
// See if main thread is waiting on this address? If so, wake it up by resetting its wake location to zero.
964-
// Note that this is not a fair procedure, since we always wake main thread first before any workers, so
965-
// this scheme does not adhere to real queue-based waiting.
966-
var mainThreadWaitAddress = Atomics.load(HEAP32, __emscripten_main_thread_futex >> 2);
967-
var mainThreadWoken = 0;
968-
if (mainThreadWaitAddress == addr) {
969-
#if ASSERTIONS
970-
// We only use __emscripten_main_thread_futex on the main browser thread, where we
971-
// cannot block while we wait. Therefore we should only see it set from
972-
// other threads, and not on the main thread itself. In other words, the
973-
// main thread must never try to wake itself up!
974-
assert(!ENVIRONMENT_IS_WEB);
975-
#endif
976-
var loadedAddr = Atomics.compareExchange(HEAP32, __emscripten_main_thread_futex >> 2, mainThreadWaitAddress, 0);
977-
if (loadedAddr == mainThreadWaitAddress) {
978-
--count;
979-
mainThreadWoken = 1;
980-
if (count <= 0) return 1;
981-
}
982-
}
983-
984-
// Wake any workers waiting on this address.
985-
var ret = Atomics.notify(HEAP32, addr >> 2, count);
986-
if (ret >= 0) return ret + mainThreadWoken;
987-
throw 'Atomics.notify returned an unexpected value ' + ret;
988-
},
989-
990954
__atomic_is_lock_free: function(size, ptr) {
991955
return size <= 4 && (size & (size-1)) == 0 && (ptr&(size-1)) == 0;
992956
},
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2021 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <assert.h>
9+
#include <errno.h>
10+
#include <limits.h>
11+
#include <stdatomic.h>
12+
#include <emscripten/threading.h>
13+
14+
int _emscripten_thread_supports_atomics_wait(void);
15+
extern void* _Atomic _emscripten_main_thread_futex;
16+
17+
18+
// Returns the number of threads (>= 0) woken up, or the value -EINVAL on error.
19+
// Pass count == INT_MAX to wake up all threads.
20+
int emscripten_futex_wake(volatile void *addr, int count) {
21+
if ((((intptr_t)addr) & 3) != 0 || count < 0) {
22+
return -EINVAL;
23+
}
24+
if (count == 0) {
25+
return 0;
26+
}
27+
28+
// See if main thread is waiting on this address? If so, wake it up by resetting its wake location to zero.
29+
// Note that this is not a fair procedure, since we always wake main thread first before any workers, so
30+
// this scheme does not adhere to real queue-based waiting.
31+
int main_thread_woken = 0;
32+
if (_emscripten_main_thread_futex == addr) {
33+
// We only use __emscripten_main_thread_futex on the main browser thread,
34+
// where we cannot block while we wait. Therefore we should only see it set
35+
// from other threads, and not on the main thread itself. In other words,
36+
// the main thread must never try to wake itself up!
37+
assert(!_emscripten_thread_supports_atomics_wait());
38+
void* expected = (void*)addr;
39+
if (atomic_compare_exchange_strong(&_emscripten_main_thread_futex, &expected, 0)) {
40+
--count;
41+
main_thread_woken = 1;
42+
if (count <= 0) {
43+
return 1;
44+
}
45+
}
46+
}
47+
48+
// Waking INT_MAX waiters is defined to mean wake all callers.
49+
// With __builtin_wasm_memory_atomic_notify wake all is signified by -1.
50+
if (count == INT_MAX) {
51+
count = -1;
52+
}
53+
54+
// Wake any workers waiting on this address.
55+
int ret = __builtin_wasm_memory_atomic_notify((int*)addr, count);
56+
assert(ret >= 0);
57+
return ret + main_thread_woken;
58+
}

tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.exports

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ H
99
I
1010
J
1111
K
12+
p
1213
q
1314
r
1415
s

tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.funcs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ $emscripten_async_run_in_main_thread
3333
$emscripten_current_thread_process_queued_calls
3434
$emscripten_dispatch_to_thread_
3535
$emscripten_futex_wait
36+
$emscripten_futex_wake
3637
$emscripten_main_thread_process_queued_calls
3738
$emscripten_proxy_main
3839
$emscripten_run_in_main_runtime_thread_js

tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.imports

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,3 @@ a.l
1313
a.m
1414
a.n
1515
a.o
16-
a.p
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
49696
1+
49055

tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.sent

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,3 @@ l
1313
m
1414
n
1515
o
16-
p
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
16846
1+
16950

tools/system_libs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ def get_files(self):
828828
'emscripten_proxy_main.c',
829829
'emscripten_thread_state.S',
830830
'emscripten_futex_wait.c',
831+
'emscripten_futex_wake.c',
831832
])
832833
else:
833834
ignore += ['thread']

0 commit comments

Comments
 (0)