Skip to content

Commit 534a208

Browse files
committed
fixes
1 parent 36be7cd commit 534a208

File tree

4 files changed

+28
-20
lines changed

4 files changed

+28
-20
lines changed

src/library_pthread.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ var LibraryPThread = {
99
$PThread__deps: ['$registerPthreadPtr',
1010
'$ERRNO_CODES', 'emscripten_futex_wake', '$killThread',
1111
'$cancelThread', '$cleanupThread',
12-
'_main_thread_futex_wait_address'
1312
#if USE_ASAN || USE_LSAN
1413
, '$withBuiltinMalloc'
1514
#endif
@@ -28,6 +27,9 @@ var LibraryPThread = {
2827
runningWorkers: [],
2928
// Points to a pthread_t structure in the Emscripten main heap, allocated on demand if/when first needed.
3029
// mainThreadBlock: undefined,
30+
// Stores the memory address that the main thread is waiting on, if any. If
31+
// the main thread is waiting, we wake it up before waking up any workers.
32+
// mainThreadFutex: undefined,
3133
initMainThreadBlock: function() {
3234
#if ASSERTIONS
3335
assert(!ENVIRONMENT_IS_PTHREAD);
@@ -69,7 +71,7 @@ var LibraryPThread = {
6971
Atomics.store(HEAPU32, (PThread.mainThreadBlock + {{{ C_STRUCTS.pthread.tid }}} ) >> 2, PThread.mainThreadBlock); // Main thread ID.
7072
Atomics.store(HEAPU32, (PThread.mainThreadBlock + {{{ C_STRUCTS.pthread.pid }}} ) >> 2, {{{ PROCINFO.pid }}}); // Process ID.
7173

72-
__main_thread_futex_wait_address = _malloc(4);
74+
PThread.mainThreadFutex = _malloc(4);
7375

7476
#if PTHREADS_PROFILING
7577
PThread.createProfilerBlock(PThread.mainThreadBlock);
@@ -87,6 +89,8 @@ var LibraryPThread = {
8789
_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);
8890
},
8991
initWorker: function() {
92+
PThread.mainThreadFutex = Module['mainThreadFutex'];
93+
9094
#if USE_CLOSURE_COMPILER
9195
// worker.js is not compiled together with us, and must access certain
9296
// things.
@@ -394,6 +398,7 @@ var LibraryPThread = {
394398
// object in Module['mainScriptUrlOrBlob'], or a URL to it, so that pthread Workers can
395399
// independently load up the same main application file.
396400
'urlOrBlob': Module['mainScriptUrlOrBlob'] || _scriptDir,
401+
'mainThreadFutex': PThread.mainThreadFutex,
397402
#if WASM2JS
398403
// the polyfill WebAssembly.Memory instance has function properties,
399404
// which will fail in postMessage, so just send a custom object with the
@@ -1106,11 +1111,8 @@ var LibraryPThread = {
11061111
return 0;
11071112
},
11081113

1109-
// Stores the memory address that the main thread is waiting on, if any.
1110-
_main_thread_futex_wait_address: '0',
1111-
11121114
// Returns 0 on success, or one of the values -ETIMEDOUT, -EWOULDBLOCK or -EINVAL on error.
1113-
emscripten_futex_wait__deps: ['_main_thread_futex_wait_address', 'emscripten_main_thread_process_queued_calls'],
1115+
emscripten_futex_wait__deps: ['emscripten_main_thread_process_queued_calls'],
11141116
emscripten_futex_wait: function(addr, val, timeout) {
11151117
if (addr <= 0 || addr > HEAP8.length || addr&3 != 0) return -{{{ cDefine('EINVAL') }}};
11161118
if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_WORKER) {
@@ -1136,10 +1138,13 @@ var LibraryPThread = {
11361138
#if PTHREADS_PROFILING
11371139
PThread.setThreadStatusConditional(_pthread_self(), {{{ cDefine('EM_THREAD_STATUS_RUNNING') }}}, {{{ cDefine('EM_THREAD_STATUS_WAITFUTEX') }}});
11381140
#endif
1139-
11401141
// Register globally which address the main thread is simulating to be waiting on. When zero, main thread is not waiting on anything,
1141-
// and on nonzero, the contents of address pointed by __main_thread_futex_wait_address tell which address the main thread is simulating its wait on.
1142-
Atomics.store(HEAP32, __main_thread_futex_wait_address >> 2, addr);
1142+
// and on nonzero, the contents of address pointed by PThread.mainThreadFutex tell which address the main thread is simulating its wait on.
1143+
var old = Atomics.exchange(HEAP32, PThread.mainThreadFutex >> 2, addr);
1144+
#if ASSERTIONS
1145+
assert(PThread.mainThreadFutex > 0);
1146+
assert(old == 0); // we must not have been waiting before.
1147+
#endif
11431148
var ourWaitAddress = addr; // We may recursively re-enter this function while processing queued calls, in which case we'll do a spurious wakeup of the older wait operation.
11441149
while (addr == ourWaitAddress) {
11451150
tNow = performance.now();
@@ -1150,7 +1155,7 @@ var LibraryPThread = {
11501155
return -{{{ cDefine('ETIMEDOUT') }}};
11511156
}
11521157
_emscripten_main_thread_process_queued_calls(); // We are performing a blocking loop here, so must pump any pthreads if they want to perform operations that are proxied.
1153-
addr = Atomics.load(HEAP32, __main_thread_futex_wait_address >> 2); // Look for a worker thread waking us up.
1158+
addr = Atomics.load(HEAP32, PThread.mainThreadFutex >> 2); // Look for a worker thread waking us up.
11541159
}
11551160
#if PTHREADS_PROFILING
11561161
PThread.setThreadStatusConditional(_pthread_self(), {{{ cDefine('EM_THREAD_STATUS_RUNNING') }}}, {{{ cDefine('EM_THREAD_STATUS_WAITFUTEX') }}});
@@ -1161,7 +1166,6 @@ var LibraryPThread = {
11611166

11621167
// Returns the number of threads (>= 0) woken up, or the value -EINVAL on error.
11631168
// Pass count == INT_MAX to wake up all threads.
1164-
emscripten_futex_wake__deps: ['_main_thread_futex_wait_address'],
11651169
emscripten_futex_wake: function(addr, count) {
11661170
if (addr <= 0 || addr > HEAP8.length || addr&3 != 0 || count < 0) return -{{{ cDefine('EINVAL') }}};
11671171
if (count == 0) return 0;
@@ -1172,10 +1176,13 @@ var LibraryPThread = {
11721176
// See if main thread is waiting on this address? If so, wake it up by resetting its wake location to zero.
11731177
// Note that this is not a fair procedure, since we always wake main thread first before any workers, so
11741178
// this scheme does not adhere to real queue-based waiting.
1175-
var mainThreadWaitAddress = Atomics.load(HEAP32, __main_thread_futex_wait_address >> 2);
1179+
#if ASSERTIONS
1180+
assert(PThread.mainThreadFutex > 0);
1181+
#endif
1182+
var mainThreadWaitAddress = Atomics.load(HEAP32, PThread.mainThreadFutex >> 2);
11761183
var mainThreadWoken = 0;
11771184
if (mainThreadWaitAddress == addr) {
1178-
var loadedAddr = Atomics.compareExchange(HEAP32, __main_thread_futex_wait_address >> 2, mainThreadWaitAddress, 0);
1185+
var loadedAddr = Atomics.compareExchange(HEAP32, PThread.mainThreadFutex >> 2, mainThreadWaitAddress, 0);
11791186
if (loadedAddr == mainThreadWaitAddress) {
11801187
--count;
11811188
mainThreadWoken = 1;

src/worker.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ this.onmessage = function(e) {
7676
#if !MINIMAL_RUNTIME
7777
Module['DYNAMIC_BASE'] = e.data.DYNAMIC_BASE;
7878
#endif
79+
Module['mainThreadFutex'] = e.data.mainThreadFutex;
7980

8081
// Module and memory were sent from main thread
8182
#if MINIMAL_RUNTIME

tests/pthread/test_pthread_proxy_hammer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ random_device::operator()()
5151

5252
int main() {
5353
int total = 0;
54-
for (int i = 0; i < 1024; i++) {
54+
for (int i = 0; i < ITERATIONS; i++) {
5555
// printf causes proxying
5656
printf("%d %d\n", i, total);
5757
for (int j = 0; j < 1024; j++) {

tests/test_browser.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4912,16 +4912,16 @@ def test_zzz_zzz_4GB_fail(self):
49124912
self.emcc_args += ['-O2', '-s', 'ALLOW_MEMORY_GROWTH', '-s', 'MAXIMUM_MEMORY=4GB', '-s', 'ABORTING_MALLOC=0']
49134913
self.do_run_in_out_file_test('tests', 'browser', 'test_4GB_fail.cpp', js_engines=[V8_ENGINE])
49144914

4915-
@unittest.skip("only run this manually, to test for race conditions")
49164915
@requires_threads
49174916
def test_manual_pthread_proxy_hammer(self):
4918-
# the specific symptom of the hangs that were fixed is that the test hangs
4919-
# at some point, using 0% CPU. often that occured in 0-200 iterations out
4920-
# of the 1024 the test runs by default, but this can vary by machine and
4921-
# browser...
4917+
# the specific symptom of the hang that was fixed is that the test hangs
4918+
# at some point, using 0% CPU. often that occured in 0-200 iterations, but
4919+
# to make the test fast it runs a lower number. increase "ITERATIONS" when
4920+
# bisecting.
49224921
self.btest(path_from_root('tests', 'pthread', 'test_pthread_proxy_hammer.cpp'),
49234922
expected='0',
4924-
args=['-s', 'USE_PTHREADS=1', '-O2', '-s', 'PROXY_TO_PTHREAD'],
4923+
args=['-s', 'USE_PTHREADS=1', '-O2', '-s', 'PROXY_TO_PTHREAD',
4924+
'-DITERATIONS=1024'],
49254925
timeout=10000,
49264926
# don't run this with the default extra_tries value, as this is
49274927
# *meant* to notice something random, a race condition.

0 commit comments

Comments
 (0)