Skip to content

Commit 49da56e

Browse files
authored
Simplify code for managing pthreads/workers in JS. NFC (#17492)
We no longer need to track each pthread as a JS object, we can just map pthread pointer to workers, and have each worker contain reverse mapping to its current pthread_ptr.
1 parent d947b50 commit 49da56e

File tree

4 files changed

+36
-43
lines changed

4 files changed

+36
-43
lines changed

src/library_pthread.js

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ var LibraryPThread = {
5151
// Contains all Workers that are currently hosting an active pthread.
5252
runningWorkers: [],
5353
tlsInitFunctions: [],
54+
// Maps pthread_t pointers to the workers on which they are running. For
55+
// the reverse mapping, each worker has a `pthread_ptr` when its running a
56+
// pthread.
57+
pthreads: {},
5458
#if PTHREADS_DEBUG
5559
nextWorkerID: 1,
5660
debugInit: function() {
@@ -114,8 +118,6 @@ var LibraryPThread = {
114118
noExitRuntime = false;
115119
#endif
116120
},
117-
// Maps pthread_t to pthread info objects
118-
pthreads: {},
119121

120122
#if PTHREADS_PROFILING
121123
getThreadName: function(pthreadPtr) {
@@ -158,9 +160,9 @@ var LibraryPThread = {
158160
err('terminateAllThreads');
159161
#endif
160162
for (var t in PThread.pthreads) {
161-
var pthread = PThread.pthreads[t];
162-
if (pthread && pthread.worker) {
163-
PThread.returnWorkerToPool(pthread.worker);
163+
var worker = PThread.pthreads[t];
164+
if (worker) {
165+
PThread.returnWorkerToPool(worker);
164166
}
165167
}
166168

@@ -175,7 +177,7 @@ var LibraryPThread = {
175177
var worker = PThread.unusedWorkers[i];
176178
#if ASSERTIONS
177179
// This Worker should not be hosting a pthread at this time.
178-
assert(!worker.pthread);
180+
assert(!worker.pthread_ptr);
179181
#endif
180182
worker.terminate();
181183
}
@@ -188,7 +190,7 @@ var LibraryPThread = {
188190
// queued pthread_create which looks at the global data structures we are
189191
// modifying). To achieve that, defer the free() til the very end, when
190192
// we are all done.
191-
var pthread_ptr = worker.pthread.threadInfoStruct;
193+
var pthread_ptr = worker.pthread_ptr;
192194
delete PThread.pthreads[pthread_ptr];
193195
// Note: worker is intentionally not terminated so the pool can
194196
// dynamically grow.
@@ -197,7 +199,7 @@ var LibraryPThread = {
197199
// Not a running Worker anymore
198200
// Detach the worker from the pthread object, and return it to the
199201
// worker pool as an unused worker.
200-
worker.pthread = undefined;
202+
worker.pthread_ptr = 0;
201203

202204
// Finally, free the underlying (and now-unused) pthread structure in
203205
// linear memory.
@@ -237,13 +239,13 @@ var LibraryPThread = {
237239
// HTML5 DOM events handlers such as
238240
// emscripten_set_mousemove_callback()), so keep track in a globally
239241
// accessible variable about the thread that initiated the proxying.
240-
if (worker.pthread) PThread.currentProxiedOperationCallerThread = worker.pthread.threadInfoStruct;
242+
if (worker.pthread_ptr) PThread.currentProxiedOperationCallerThread = worker.pthread_ptr;
241243

242244
// If this message is intended to a recipient that is not the main thread, forward it to the target thread.
243245
if (d['targetThread'] && d['targetThread'] != _pthread_self()) {
244-
var thread = PThread.pthreads[d.targetThread];
245-
if (thread) {
246-
thread.worker.postMessage(d, d['transferList']);
246+
var targetWorker = PThread.pthreads[d.targetThread];
247+
if (targetWorker) {
248+
targetWorker.postMessage(d, d['transferList']);
247249
} else {
248250
err('Internal error! Worker sent a message "' + cmd + '" to target pthread ' + d['targetThread'] + ', but that thread no longer exists!');
249251
}
@@ -295,11 +297,8 @@ var LibraryPThread = {
295297
worker.onerror = (e) => {
296298
var message = 'worker sent an error!';
297299
#if ASSERTIONS
298-
if (worker.pthread) {
299-
var pthread_ptr = worker.pthread.threadInfoStruct;
300-
if (pthread_ptr) {
301-
message = 'Pthread ' + ptrToString(pthread_ptr) + ' sent an error!';
302-
}
300+
if (worker.pthread_ptr) {
301+
message = 'Pthread ' + ptrToString(worker.pthread_ptr) + ' sent an error!';
303302
}
304303
#endif
305304
err(message + ' ' + e.filename + ':' + e.lineno + ': ' + e.message);
@@ -444,14 +443,14 @@ var LibraryPThread = {
444443
assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! killThread() can only ever be called from main application thread!');
445444
assert(pthread_ptr, 'Internal Error! Null pthread_ptr in killThread!');
446445
#endif
447-
var pthread = PThread.pthreads[pthread_ptr];
446+
var worker = PThread.pthreads[pthread_ptr];
448447
delete PThread.pthreads[pthread_ptr];
449-
pthread.worker.terminate();
448+
worker.terminate();
450449
__emscripten_thread_free_data(pthread_ptr);
451450
// The worker was completely nuked (not just the pthread execution it was hosting), so remove it from running workers
452451
// but don't put it back to the pool.
453-
PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker), 1); // Not a running Worker anymore.
454-
pthread.worker.pthread = undefined;
452+
PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker), 1); // Not a running Worker anymore.
453+
worker.pthread_ptr = 0;
455454
},
456455

457456
__emscripten_thread_cleanup: function(thread) {
@@ -469,9 +468,8 @@ var LibraryPThread = {
469468
assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! cleanupThread() can only ever be called from main application thread!');
470469
assert(pthread_ptr, 'Internal Error! Null pthread_ptr in cleanupThread!');
471470
#endif
472-
var pthread = PThread.pthreads[pthread_ptr];
473-
assert(pthread);
474-
var worker = pthread.worker;
471+
var worker = PThread.pthreads[pthread_ptr];
472+
assert(worker);
475473
PThread.returnWorkerToPool(worker);
476474
},
477475

@@ -522,8 +520,8 @@ var LibraryPThread = {
522520
assert(!ENVIRONMENT_IS_PTHREAD, 'Internal Error! cancelThread() can only ever be called from main application thread!');
523521
assert(pthread_ptr, 'Internal Error! Null pthread_ptr in cancelThread!');
524522
#endif
525-
var pthread = PThread.pthreads[pthread_ptr];
526-
pthread.worker.postMessage({ 'cmd': 'cancel' });
523+
var worker = PThread.pthreads[pthread_ptr];
524+
worker.postMessage({ 'cmd': 'cancel' });
527525
},
528526

529527
$spawnThread: function(threadParams) {
@@ -538,24 +536,20 @@ var LibraryPThread = {
538536
return {{{ cDefine('EAGAIN') }}};
539537
}
540538
#if ASSERTIONS
541-
assert(!worker.pthread, 'Internal error!');
539+
assert(!worker.pthread_ptr, 'Internal error!');
542540
#endif
543541

544542
PThread.runningWorkers.push(worker);
545543

546-
// Create a pthread info object to represent this thread.
547-
var pthread = PThread.pthreads[threadParams.pthread_ptr] = {
548-
worker: worker,
549-
// Info area for this thread in Emscripten HEAP (shared)
550-
threadInfoStruct: threadParams.pthread_ptr
551-
};
544+
// Add to pthreads map
545+
PThread.pthreads[threadParams.pthread_ptr] = worker;
552546

553-
worker.pthread = pthread;
547+
worker.pthread_ptr = threadParams.pthread_ptr;
554548
var msg = {
555549
'cmd': 'run',
556550
'start_routine': threadParams.startRoutine,
557551
'arg': threadParams.arg,
558-
'threadInfoStruct': threadParams.pthread_ptr,
552+
'pthread_ptr': threadParams.pthread_ptr,
559553
};
560554
#if OFFSCREENCANVAS_SUPPORT
561555
// Note that we do not need to quote these names because they are only used
@@ -1017,8 +1011,7 @@ var LibraryPThread = {
10171011
} else if (ENVIRONMENT_IS_PTHREAD) {
10181012
postMessage({'targetThread' : targetThreadId, 'cmd' : 'processProxyingQueue', 'queue' : queue});
10191013
} else {
1020-
var pthread = PThread.pthreads[targetThreadId];
1021-
var worker = pthread && pthread.worker;
1014+
var worker = PThread.pthreads[targetThreadId];
10221015
if (!worker) {
10231016
#if ASSERTIONS
10241017
err('Cannot send message to thread with ID ' + targetThreadId + ', unknown thread ID!');

src/threadprofiler.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var emscriptenThreadProfiler = {
3535

3636
var threads = [mainThread];
3737
for (var i in PThread.pthreads) {
38-
threads.push(PThread.pthreads[i].threadInfoStruct);
38+
threads.push(PThread.pthreads[i].pthread_ptr);
3939
}
4040
for (var i = 0; i < threads.length; ++i) {
4141
var threadPtr = threads[i];
@@ -62,7 +62,7 @@ var emscriptenThreadProfiler = {
6262

6363
var threads = [mainThread];
6464
for (var i in PThread.pthreads) {
65-
threads.push(PThread.pthreads[i].threadInfoStruct);
65+
threads.push(PThread.pthreads[i].pthread_ptr);
6666
}
6767

6868
for (var i = 0; i < threads.length; ++i) {

src/worker.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,11 @@ self.onmessage = (e) => {
200200
// (+/- 0.1msecs in testing).
201201
Module['__performance_now_clock_drift'] = performance.now() - e.data.time;
202202

203-
// Pass the thread address inside the asm.js scope to store it for fast access that avoids the need for a FFI out.
204-
Module['__emscripten_thread_init'](e.data.threadInfoStruct, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0, /*canBlock=*/1);
203+
// Pass the thread address to wasm to store it for fast access.
204+
Module['__emscripten_thread_init'](e.data.pthread_ptr, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0, /*canBlock=*/1);
205205

206206
#if ASSERTIONS
207-
assert(e.data.threadInfoStruct);
207+
assert(e.data.pthread_ptr);
208208
#endif
209209
// Also call inside JS module to set up the stack frame for this pthread in JS module scope
210210
Module['establishStackSpace']();
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
16000
1+
15892

0 commit comments

Comments
 (0)