Skip to content

Multithreading 6/N: Proxy calls to JavaScript functions from pthreads to main browser thread#5531

Merged
juj merged 5 commits intoemscripten-core:incomingfrom
juj:proxy_to_main_thread
Sep 22, 2017
Merged

Multithreading 6/N: Proxy calls to JavaScript functions from pthreads to main browser thread#5531
juj merged 5 commits intoemscripten-core:incomingfrom
juj:proxy_to_main_thread

Conversation

@juj
Copy link
Collaborator

@juj juj commented Aug 26, 2017

This PR implements a mechanism where JavaScript library functions can be attributed with foo__proxy: 'mode', where mode is one of 'main', 'async', 'main_gl' or 'async_gl'. This allows a pthread running in a web worker to either synchronously or asynchronously call out to JavaScript on the main browser thread.

The _gl variants decide proxying based on the currently active WebGL context for the calling thread. If the calling thread owns the GL context, then the call is not proxied. If the calling thread instead has activated a proxied context that is owned by the main browser thread, then the call is proxied. (This machinery is expanded on along with tests in a later PR)

This PR requires #5527 to land first in order to work.

var returnValue;
var funcTable = (e.data.func >= 0) ? proxiedFunctionTable : ASM_CONSTS;
var funcIdx = (e.data.func >= 0) ? e.data.func : (-1 - e.data.func);
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I have an exception : worker.pthread is undefined, when a proxy call is lanch but the worker terminate and is clean.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance you'd be able to make a small test case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I test to reproduce it in a small test case but for now, i'm not able. I will continue to try.

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the 4 proxying modes documented? the names suggest what they do, but I'm not 100% sure.

src/jsifier.js Outdated

// This is ad-hoc numbering scheme to map signatures to IDs, and must agree with call handler in src/library_pthread.js.
// Once proxied function calls no longer go through postMessage()s but instead in the heap, this will need to change, since int vs float will matter.
var functionCallOrdinal = sig.length + (sizeofReturn == 8 ? 20 : 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is magical about 8 and 20?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sizeOfReturn being 8 equals the case of a double, and the ID 20 is where functions with double return type start. The comment refers to the matching IDs at src/library_pthread.js: https://github.com/kripken/emscripten/pull/5531/files#diff-db41bea94577c2dd9b0eef0308b06cf9R272

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed sizeOfReturn == 8 test to sig[0] == 'd' to be more self-documenting.

@juj
Copy link
Collaborator Author

juj commented Sep 7, 2017

I'll need to write a full set of documentation about the updated pthreads support. I'd like to defer that to once these PRs land, so that I can write a coherent update of the current doc page at http://kripken.github.io/emscripten-site/docs/porting/pthreads.html

@juj juj force-pushed the proxy_to_main_thread branch 2 times, most recently from 4b8ddf2 to 6945de2 Compare September 8, 2017 08:50
src/jsifier.js Outdated

// This is ad-hoc numbering scheme to map signatures to IDs, and must agree with call handler in src/library_pthread.js.
// Once proxied function calls no longer go through postMessage()s but instead in the heap, this will need to change, since int vs float will matter.
var functionCallOrdinal = sig.length + (sig[0] == 'd' ? 20 : 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i still think the 20 is bad - couldn't that become invalid if we change memory layout? or am i missing something?

at minimum lets put a big comment with XXX FIXME on this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The number 20 is more like a magic ID, it only needs to match in this spot in src/jsifier.js and then in src/pthread-main.js (in https://github.com/kripken/emscripten/pull/5531/files#diff-db41bea94577c2dd9b0eef0308b06cf9R272). There is nothing about the memory layout itself that would interact with this. Only limit to number 20 is if there's a function that needs proxying that would take in more than 20 input parameters, then we'd have to bump up the number.

Basically this is turning all these signature strings 'vii', 'viii', 'iii', 'dii' into ID numbers, so that the receiving code knows what kind of function signature it should be calling.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, so it just cares about the # of params and whether the return value is float? maybe add a comment with that?

also, how about storing 20 in a const, and also asserting that the sig.length is shorter than it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestions, improved this. Also while reading, found a yet unimplemented case in handling there, fixed that, and also changed the number from 20 to 32 to be more programmer-friendly :)

@kripken
Copy link
Member

kripken commented Sep 11, 2017

Bigger docs later sounds ok, but just for reviewing this PR, I could use some short explanations :)

@juj juj force-pushed the proxy_to_main_thread branch from 6945de2 to 7a2f474 Compare September 13, 2017 09:39
@juj
Copy link
Collaborator Author

juj commented Sep 13, 2017

Edited the PR to remove the main_gl and async_gl proxying modes for now. This is because I'm looking at redoing the WebGL proxying via a more efficient method, by creating a WebGL thread. Depending on how that goes, I'll look at reintroducing main_gl and async_gl, whichever makes more sense.

@juj
Copy link
Collaborator Author

juj commented Sep 13, 2017

Bigger docs later sounds ok, but just for reviewing this PR, I could use some short explanations :)

The main proxying mode queues the function call on the main browser thread, and the calling thread then synchronously waits for the function call to finish on the main thread, and gets the return value back.

The async proxying mode queues the function call on the main browser thread, but immediately continues to execute code without waiting for the function call to happen, or the return value, if the function had any.

@kripken
Copy link
Member

kripken commented Sep 13, 2017

I see, thanks. Why not call it sync and async, then, instead of main and async?

@juj juj force-pushed the proxy_to_main_thread branch from 7a2f474 to cca54d2 Compare September 22, 2017 09:31
@juj
Copy link
Collaborator Author

juj commented Sep 22, 2017

I see, thanks. Why not call it sync and async, then, instead of main and async?

Hmm, yeah, I first started with main, and then added main_async, and then thought that's too long, and shortened it to async. But sync and async sound like better, I'll change to that.

@juj juj force-pushed the proxy_to_main_thread branch from cca54d2 to 244d10d Compare September 22, 2017 09:39
@juj
Copy link
Collaborator Author

juj commented Sep 22, 2017

Updated the PR, how does it look now?

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with one style nit

src/jsifier.js Outdated

function sizeofType(t) {
switch(t) {
case 'd':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please do case bodies on same line, or {,}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check

@juj juj merged commit 5bcb75e into emscripten-core:incoming Sep 22, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants