@@ -252,106 +252,115 @@ var LibraryPThread = {
252
252
Module [ 'print' ] ( 'Preallocating ' + numWorkers + ' workers for a pthread spawn pool.' ) ;
253
253
254
254
var numWorkersLoaded = 0 ;
255
+ var pthreadMainJs = 'pthread-main.js' ;
256
+ // Allow HTML module to configure the location where the 'pthread-main.js' file will be loaded from,
257
+ // either via Module.locateFile() function, or via Module.pthreadMainPrefixURL string. If neither
258
+ // of these are passed, then the default URL 'pthread-main.js' relative to the main html file is loaded.
259
+ if ( typeof Module [ 'locateFile' ] === 'function' ) pthreadMainJs = Module [ 'locateFile' ] ( pthreadMainJs ) ;
260
+ else if ( Module [ 'pthreadMainPrefixURL' ] ) pthreadMainJs = Module [ 'pthreadMainPrefixURL' ] + pthreadMainJs ;
261
+
255
262
for ( var i = 0 ; i < numWorkers ; ++ i ) {
256
- var pthreadMainJs = 'pthread-main.js' ;
257
- // Allow HTML module to configure the location where the 'pthread-main.js' file will be loaded from,
258
- // either via Module.locateFile() function, or via Module.pthreadMainPrefixURL string. If neither
259
- // of these are passed, then the default URL 'pthread-main.js' relative to the main html file is loaded.
260
- if ( typeof Module [ 'locateFile' ] === 'function' ) pthreadMainJs = Module [ 'locateFile' ] ( pthreadMainJs ) ;
261
- else if ( Module [ 'pthreadMainPrefixURL' ] ) pthreadMainJs = Module [ 'pthreadMainPrefixURL' ] + pthreadMainJs ;
262
263
var worker = new Worker ( pthreadMainJs ) ;
263
264
264
- worker . onmessage = function ( e ) {
265
- var d = e . data ;
266
- // TODO: Move the proxied call mechanism into a queue inside heap.
267
- if ( d . proxiedCall ) {
268
- var returnValue ;
269
- var funcTable = ( d . func >= 0 ) ? proxiedFunctionTable : ASM_CONSTS ;
270
- var funcIdx = ( d . func >= 0 ) ? d . func : ( - 1 - d . func ) ;
271
- PThread . currentProxiedOperationCallerThread = worker . pthread . threadInfoStruct ; // Sometimes we need to backproxy events to the calling thread (e.g. HTML5 DOM events handlers such as emscripten_set_mousemove_callback()), so keep track in a globally accessible variable about the thread that initiated the proxying.
272
- switch ( d . proxiedCall & 31 ) {
273
- case 1 : returnValue = funcTable [ funcIdx ] ( ) ; break ;
274
- case 2 : returnValue = funcTable [ funcIdx ] ( d . p0 ) ; break ;
275
- case 3 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 ) ; break ;
276
- case 4 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 ) ; break ;
277
- case 5 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 ) ; break ;
278
- case 6 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 ) ; break ;
279
- case 7 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 , d . p5 ) ; break ;
280
- case 8 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 , d . p5 , d . p6 ) ; break ;
281
- case 9 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 , d . p5 , d . p6 , d . p7 ) ; break ;
282
- case 10 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 , d . p5 , d . p6 , d . p7 , d . p8 ) ; break ;
283
- default :
284
- if ( d . proxiedCall ) {
285
- Module [ 'printErr' ] ( "worker sent an unknown proxied call idx " + d . proxiedCall ) ;
286
- console . error ( e . data ) ;
287
- }
288
- break ;
289
- }
290
- if ( d . returnValue ) {
291
- if ( d . proxiedCall < 32 ) HEAP32 [ d . returnValue >> 2 ] = returnValue ;
292
- else HEAPF64 [ d . returnValue >> 3 ] = returnValue ;
265
+ ( function ( worker ) {
266
+ worker . onmessage = function ( e ) {
267
+ var d = e . data ;
268
+ // TODO: Move the proxied call mechanism into a queue inside heap.
269
+ if ( d . proxiedCall ) {
270
+ var returnValue ;
271
+ var funcTable = ( d . func >= 0 ) ? proxiedFunctionTable : ASM_CONSTS ;
272
+ var funcIdx = ( d . func >= 0 ) ? d . func : ( - 1 - d . func ) ;
273
+ PThread . currentProxiedOperationCallerThread = worker . pthread . threadInfoStruct ; // Sometimes we need to backproxy events to the calling thread (e.g. HTML5 DOM events handlers such as emscripten_set_mousemove_callback()), so keep track in a globally accessible variable about the thread that initiated the proxying.
274
+ switch ( d . proxiedCall & 31 ) {
275
+ case 1 : returnValue = funcTable [ funcIdx ] ( ) ; break ;
276
+ case 2 : returnValue = funcTable [ funcIdx ] ( d . p0 ) ; break ;
277
+ case 3 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 ) ; break ;
278
+ case 4 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 ) ; break ;
279
+ case 5 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 ) ; break ;
280
+ case 6 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 ) ; break ;
281
+ case 7 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 , d . p5 ) ; break ;
282
+ case 8 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 , d . p5 , d . p6 ) ; break ;
283
+ case 9 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 , d . p5 , d . p6 , d . p7 ) ; break ;
284
+ case 10 : returnValue = funcTable [ funcIdx ] ( d . p0 , d . p1 , d . p2 , d . p3 , d . p4 , d . p5 , d . p6 , d . p7 , d . p8 ) ; break ;
285
+ default :
286
+ if ( d . proxiedCall ) {
287
+ Module [ 'printErr' ] ( "worker sent an unknown proxied call idx " + d . proxiedCall ) ;
288
+ console . error ( e . data ) ;
289
+ }
290
+ break ;
291
+ }
292
+ if ( d . returnValue ) {
293
+ if ( d . proxiedCall < 32 ) HEAP32 [ d . returnValue >> 2 ] = returnValue ;
294
+ else HEAPF64 [ d . returnValue >> 3 ] = returnValue ;
295
+ }
296
+ var waitAddress = d . waitAddress ;
297
+ if ( waitAddress ) {
298
+ Atomics . store ( HEAP32 , waitAddress >> 2 , 1 ) ;
299
+ Atomics . wake ( HEAP32 , waitAddress >> 2 , 1 ) ;
300
+ }
301
+ return ;
293
302
}
294
- var waitAddress = d . waitAddress ;
295
- if ( waitAddress ) {
296
- Atomics . store ( HEAP32 , waitAddress >> 2 , 1 ) ;
297
- Atomics . wake ( HEAP32 , waitAddress >> 2 , 1 ) ;
303
+
304
+ // If this message is intended to a recipient that is not the main thread, forward it to the target thread.
305
+ if ( d . targetThread && d . targetThread != _pthread_self ( ) ) {
306
+ var thread = PThread . pthreads [ d . targetThread ] ;
307
+ if ( thread ) {
308
+ thread . worker . postMessage ( e . data , d . transferList ) ;
309
+ } else {
310
+ console . error ( 'Internal error! Worker sent a message "' + d . cmd + '" to target pthread ' + d . targetThread + ', but that thread no longer exists!' ) ;
311
+ }
312
+ return ;
298
313
}
299
- return ;
300
- }
301
314
302
- // If this message is intended to a recipient that is not the main thread, forward it to the target thread.
303
- if ( d . targetThread && d . targetThread != _pthread_self ( ) ) {
304
- var thread = PThread . pthreads [ d . targetThread ] ;
305
- if ( thread ) {
306
- thread . worker . postMessage ( e . data , d . transferList ) ;
315
+ if ( d . cmd === 'processQueuedMainThreadWork' ) {
316
+ // TODO: Must post message to main Emscripten thread in PROXY_TO_WORKER mode.
317
+ _emscripten_main_thread_process_queued_calls ( ) ;
318
+ } else if ( d . cmd === 'spawnThread' ) {
319
+ __spawn_thread ( e . data ) ;
320
+ } else if ( d . cmd === 'cleanupThread' ) {
321
+ __cleanup_thread ( d . thread ) ;
322
+ } else if ( d . cmd === 'killThread' ) {
323
+ __kill_thread ( d . thread ) ;
324
+ } else if ( d . cmd === 'cancelThread' ) {
325
+ __cancel_thread ( d . thread ) ;
326
+ } else if ( d . cmd === 'loaded' ) {
327
+ worker . loaded = true ;
328
+ // If this Worker is already pending to start running a thread, launch the thread now
329
+ if ( worker . runPthread ) {
330
+ worker . runPthread ( ) ;
331
+ delete worker . runPthread ;
332
+ }
333
+ ++ numWorkersLoaded ;
334
+ if ( numWorkersLoaded === numWorkers && onFinishedLoading ) {
335
+ onFinishedLoading ( ) ;
336
+ }
337
+ } else if ( d . cmd === 'print' ) {
338
+ Module [ 'print' ] ( 'Thread ' + d . threadId + ': ' + d . text ) ;
339
+ } else if ( d . cmd === 'printErr' ) {
340
+ Module [ 'printErr' ] ( 'Thread ' + d . threadId + ': ' + d . text ) ;
341
+ } else if ( d . cmd === 'alert' ) {
342
+ alert ( 'Thread ' + d . threadId + ': ' + d . text ) ;
343
+ } else if ( d . cmd === 'exit' ) {
344
+ // currently no-op
345
+ } else if ( d . cmd === 'cancelDone' ) {
346
+ PThread . freeThreadData ( worker . pthread ) ;
347
+ worker . pthread = undefined ; // Detach the worker from the pthread object, and return it to the worker pool as an unused worker.
348
+ PThread . unusedWorkerPool . push ( worker ) ;
349
+ // TODO: Free if detached.
350
+ PThread . runningWorkers . splice ( PThread . runningWorkers . indexOf ( worker . pthread ) , 1 ) ; // Not a running Worker anymore.
351
+ } else if ( d . cmd === 'objectTransfer' ) {
352
+ PThread . receiveObjectTransfer ( e . data ) ;
353
+ } else if ( e . data . target === 'setimmediate' ) {
354
+ worker . postMessage ( e . data ) ; // Worker wants to postMessage() to itself to implement setImmediate() emulation.
307
355
} else {
308
- console . error ( 'Internal error! Worker sent a message "' + d . cmd + '" to target pthread ' + d . targetThread + ', but that thread no longer exists!' ) ;
356
+ Module [ 'printErr' ] ( "worker sent an unknown command " + d . cmd ) ;
309
357
}
310
- return ;
311
- }
358
+ } ;
312
359
313
- if ( d . cmd === 'processQueuedMainThreadWork' ) {
314
- // TODO: Must post message to main Emscripten thread in PROXY_TO_WORKER mode.
315
- _emscripten_main_thread_process_queued_calls ( ) ;
316
- } else if ( d . cmd === 'spawnThread' ) {
317
- __spawn_thread ( e . data ) ;
318
- } else if ( d . cmd === 'cleanupThread' ) {
319
- __cleanup_thread ( d . thread ) ;
320
- } else if ( d . cmd === 'killThread' ) {
321
- __kill_thread ( d . thread ) ;
322
- } else if ( d . cmd === 'cancelThread' ) {
323
- __cancel_thread ( d . thread ) ;
324
- } else if ( d . cmd === 'loaded' ) {
325
- ++ numWorkersLoaded ;
326
- if ( numWorkersLoaded === numWorkers && onFinishedLoading ) {
327
- onFinishedLoading ( ) ;
328
- }
329
- } else if ( d . cmd === 'print' ) {
330
- Module [ 'print' ] ( 'Thread ' + d . threadId + ': ' + d . text ) ;
331
- } else if ( d . cmd === 'printErr' ) {
332
- Module [ 'printErr' ] ( 'Thread ' + d . threadId + ': ' + d . text ) ;
333
- } else if ( d . cmd === 'alert' ) {
334
- alert ( 'Thread ' + d . threadId + ': ' + d . text ) ;
335
- } else if ( d . cmd === 'exit' ) {
336
- // currently no-op
337
- } else if ( d . cmd === 'cancelDone' ) {
338
- PThread . freeThreadData ( worker . pthread ) ;
339
- worker . pthread = undefined ; // Detach the worker from the pthread object, and return it to the worker pool as an unused worker.
340
- PThread . unusedWorkerPool . push ( worker ) ;
341
- // TODO: Free if detached.
342
- PThread . runningWorkers . splice ( PThread . runningWorkers . indexOf ( worker . pthread ) , 1 ) ; // Not a running Worker anymore.
343
- } else if ( d . cmd === 'objectTransfer' ) {
344
- PThread . receiveObjectTransfer ( e . data ) ;
345
- } else if ( e . data . target === 'setimmediate' ) {
346
- worker . postMessage ( e . data ) ; // Worker wants to postMessage() to itself to implement setImmediate() emulation.
347
- } else {
348
- Module [ 'printErr' ] ( "worker sent an unknown command " + d . cmd ) ;
349
- }
350
- } ;
351
-
352
- worker . onerror = function ( e ) {
353
- Module [ 'printErr' ] ( 'pthread sent an error! ' + e . filename + ':' + e . lineno + ': ' + e . message ) ;
354
- } ;
360
+ worker . onerror = function ( e ) {
361
+ Module [ 'printErr' ] ( 'pthread sent an error! ' + e . filename + ':' + e . lineno + ': ' + e . message ) ;
362
+ } ;
363
+ } ( worker ) ) ;
355
364
356
365
// Allocate tempDoublePtr for the worker. This is done here on the worker's behalf, since we may need to do this statically
357
366
// if the runtime has not been loaded yet, etc. - so we just use getMemory, which is main-thread only.
@@ -477,22 +486,29 @@ var LibraryPThread = {
477
486
#endif
478
487
479
488
worker . pthread = pthread ;
480
-
481
- // Ask the worker to start executing its pthread entry point function.
482
- worker . postMessage ( {
483
- cmd : 'run' ,
484
- start_routine : threadParams . startRoutine ,
485
- arg : threadParams . arg ,
486
- threadInfoStruct : threadParams . pthread_ptr ,
487
- selfThreadId : threadParams . pthread_ptr , // TODO: Remove this since thread ID is now the same as the thread address.
488
- parentThreadId : threadParams . parent_pthread_ptr ,
489
- stackBase : threadParams . stackBase ,
490
- stackSize : threadParams . stackSize ,
489
+ var msg = {
490
+ cmd : 'run' ,
491
+ start_routine : threadParams . startRoutine ,
492
+ arg : threadParams . arg ,
493
+ threadInfoStruct : threadParams . pthread_ptr ,
494
+ selfThreadId : threadParams . pthread_ptr , // TODO: Remove this since thread ID is now the same as the thread address.
495
+ parentThreadId : threadParams . parent_pthread_ptr ,
496
+ stackBase : threadParams . stackBase ,
497
+ stackSize : threadParams . stackSize ,
491
498
#if OFFSCREENCANVAS_SUPPORT
492
- moduleCanvasId : threadParams . moduleCanvasId ,
493
- offscreenCanvases : threadParams . offscreenCanvases ,
499
+ moduleCanvasId : threadParams . moduleCanvasId ,
500
+ offscreenCanvases : threadParams . offscreenCanvases ,
494
501
#endif
495
- } , threadParams . transferList ) ;
502
+ } ;
503
+ worker . runPthread = function ( ) {
504
+ // Ask the worker to start executing its pthread entry point function.
505
+ msg . time = performance . now ( ) ;
506
+ worker . postMessage ( msg , threadParams . transferList ) ;
507
+ } ;
508
+ if ( worker . loaded ) {
509
+ worker . runPthread ( ) ;
510
+ delete worker . runPthread ;
511
+ }
496
512
} ,
497
513
498
514
#if USE_PTHREADS
0 commit comments