-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Move emscripten_futex_wake to native code. NFC #15766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
58ebb04 to
d181bf5
Compare
|
Some tests (e.g. Which is curious, I tried to solve that with this simplification: 15766.patchdiff --git a/system/lib/pthread/emscripten_futex_wake.c b/system/lib/pthread/emscripten_futex_wake.c
index ac3a42eba..6e87bd5ed 100644
--- a/system/lib/pthread/emscripten_futex_wake.c
+++ b/system/lib/pthread/emscripten_futex_wake.c
@@ -8,12 +8,14 @@
#include <assert.h>
#include <errno.h>
#include <limits.h>
-#include <stdatomic.h>
+#include <atomic.h>
#include <emscripten/threading.h>
int _emscripten_thread_supports_atomics_wait(void);
-extern void* _Atomic _emscripten_main_thread_futex;
+// Stores the memory address that the main thread is waiting on, if any. If
+// the main thread is waiting, we wake it up before waking up any workers.
+EMSCRIPTEN_KEEPALIVE void *volatile _emscripten_main_thread_futex;
// Returns the number of threads (>= 0) woken up, or the value -EINVAL on error.
// Pass count == INT_MAX to wake up all threads.
@@ -29,19 +31,16 @@ int emscripten_futex_wake(volatile void *addr, int count) {
// Note that this is not a fair procedure, since we always wake main thread first before any workers, so
// this scheme does not adhere to real queue-based waiting.
int main_thread_woken = 0;
- if (_emscripten_main_thread_futex == addr) {
+ if (a_cas_p(&_emscripten_main_thread_futex, (void *)addr, 0) == addr) {
// We only use __emscripten_main_thread_futex on the main browser thread,
// where we cannot block while we wait. Therefore we should only see it set
// from other threads, and not on the main thread itself. In other words,
// the main thread must never try to wake itself up!
assert(!_emscripten_thread_supports_atomics_wait());
- void* expected = (void*)addr;
- if (atomic_compare_exchange_strong(&_emscripten_main_thread_futex, &expected, 0)) {
- --count;
- main_thread_woken = 1;
- if (count <= 0) {
- return 1;
- }
+ --count;
+ main_thread_woken = 1;
+ if (count <= 0) {
+ return 1;
}
}
diff --git a/system/lib/pthread/library_pthread.c b/system/lib/pthread/library_pthread.c
index 3d5051f04..612e697d7 100644
--- a/system/lib/pthread/library_pthread.c
+++ b/system/lib/pthread/library_pthread.c
@@ -831,10 +831,6 @@ int emscripten_dispatch_to_thread_async_(pthread_t target_thread,
return ret;
}
-// Stores the memory address that the main thread is waiting on, if any. If
-// the main thread is waiting, we wake it up before waking up any workers.
-EMSCRIPTEN_KEEPALIVE void* _emscripten_main_thread_futex;
-
void __emscripten_init_main_thread_js(void* tb);
static void *dummy_tsd[1] = { 0 };To no avail (same assertion failure). |
2aa6eb4 to
9a8451d
Compare
|
Ah, it looks like I had the condition in the assert the wrong way around.. |
|
I like your simplification though! I will apply that.. |
9a8451d to
8000992
Compare
8000992 to
fefc22b
Compare
|
I ran the whole of |
| // from other threads (that should always support waiting), and not on the | ||
| // main thread itself. In other words, the main thread must never try to | ||
| // wake itself up! | ||
| assert(_emscripten_thread_supports_atomics_wait()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At some point we might want to audit our code to try to make it work correctly from audio worklets, which also can't block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.. this mechanism assumes only one (busy-looping) main thread I think, so it would need to be revisited.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I came across the audioworklet issue:
SimpleSequencer.js:1 Uncaught RuntimeError: Aborted(Assertion failed: _emscripten_thread_supports_atomics_wait(), at:
/home/jonathan/emsdk/upstream/emscripten/system/lib/pthread/emscripten_futex_wake.c,40,emscripten_futex_wake)
at abort (SimpleSequencer.js:1:23555)
at ___assert_fail (SimpleSequencer.js:1:92185)
at emscripten_futex_wake (SimpleSequencer.wasm:0x5fcc66)
at __wake (SimpleSequencer.wasm:0x5fc80b)
at __pthread_mutex_unlock (SimpleSequencer.wasm:0x6041a7)
at sys_unlock (SimpleSequencer.wasm:0x4b4743)
at ofxPd::audioOut(float*, int, int) (SimpleSequencer.wasm:0x43abb3)
at ofxOfelia::audioOut(ofSoundBuffer&) (SimpleSequencer.wasm:0x691b3)
at std::__2::__function::__func<std::__2::__bind<void (ofBaseSoundInput::*)(ofSoundBuffer&), ofBaseSoundInput*&, std::__2::placeholders::__ph<1> const&>, std::__2::allocator<std::__2::__bind<void (ofBaseSoundInput::*)(ofSoundBuffer&), ofBaseSoundInput*&, std::__2::placeholders::__ph<1> const&>>, void (ofSoundBuffer&)>::operator()(ofSoundBuffer&) (SimpleSequencer.wasm:0x63b62)
at ofxEmscriptenSoundStream::audio_cb(int, int, int, void*) (SimpleSequencer.wasm:0x637e0)
It would be absolutely great, if this gets fixed. Because the app I am using with Emscripten seems to rely on that. And I am a bit lost with fixing it by myself.
This is great example of why moving stuff into native code can save on overall size: jssize: 49696 -> 48861 = -775 wasm size: 16846 -> 16928 = +82
This is great example of why moving stuff into native code can save on overall size:
jssize: 49696 -> 48861 = -775
wasm size: 16846 -> 16928 = +82