-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Fix the setup of the stack pointer in wasm backend+threads mode, It should point to the top of the stack, not the bottom. #8811
Conversation
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.
Thanks @vargaz! Please add yourself to AUTHORS.
The CI errors look random, although oddly there are a bunch of pthreads ones. I re-ran that part of the CI to see.
@@ -44,7 +44,7 @@ int pthread_attr_getstack(const pthread_attr_t *restrict a, void **restrict addr | |||
// return EINVAL; | |||
|
|||
*size = a->_a_stacksize + DEFAULT_STACK_SIZE; | |||
*addr = (void *)(a->_a_stackaddr - *size); | |||
*addr = (void *)(a->_a_stackaddr); | |||
return 0; |
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 don't understand this change, but then I don't understand the code from before either I think :)
This change is for both fastcomp and the wasm backend, it seems, since it's not ifdef'd? So was this always wrong?
@juj you know this code the best, what do you think?
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'm confused. The base musl implementation does the same thing:
https://github.com/kraj/musl/blob/cbf41860664b2f408653cc2169b454a293096ccf/src/thread/pthread_attr_get.c#L38-L45
and the pthread_attr_getstack doco says:
The base (lowest addressable byte) of the storage shall be addr
So maybe I'm wrong, but the the current behaviour looks right?
What bug is this trying to fix?
This change does look wrong to me. In musl convention for the Second, musl has an internal meaning for the The function Perhaps the root issue for stack base vs stack end is somewhere else? The original implementation of |
To double-check, what is the convention of |
Yes, in the wasm backend, the stack grows down, so stackRestore () needs to be called with the top address. t->stack is initialized from threadParams.stackBase: https://github.com/emscripten-core/emscripten/blob/incoming/src/library_pthread.js#L436 |
Changed it so pthread_t.stack points to the stack top in the wasm backend, so pthread_attr_getstack() remains the same. |
Interestingly, this looks like it may fix #8718! The CI failure on
That check is here. It doesn't look obviously wrong to me - |
STACK_MAX is the highest address, from library_pthread.js: $establishStackSpaceInJsModule: function(stackBase, stackMax) { |
Hmm, then that code may be wrong. We set up the stack as something like
So max is the maximum the stack can be incremented to (the lowest address, if the stack increments down). Sounds like we need to update a few places in the code to get this right. Let me know if that turns out complicated and if I can help. |
Another location is in worker.js:
|
Do these places need an ifdef #WASM_BACKEND ? |
It's possible, yeah, that we need to ifdef in places like that. But I'm not sure - I don't have it all in my head what the various stack variables all mean. If you get stuck let me know - I can find time to do a larger refactoring of this code. But I'm hoping it's simple enough to fix this, and we don't need that. |
Made a try.
Not sure whenever to use #ifdef WASM or #ifdef WASM_BACKEND. |
For the wasm backend, |
src/worker.js
Outdated
#if ASSERTIONS | ||
assert(threadInfoStruct); | ||
assert(selfThreadId); | ||
assert(parentThreadId); | ||
assert(STACK_BASE != 0); | ||
assert(STACK_MAX > STACK_BASE); |
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.
how about keeping this assertion for fastcomp, and checking the other direction for the wasm backend?
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.
Done.
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 don't see this change - was it reverted perhaps?
@@ -1169,8 +1171,15 @@ var LibraryPThread = { | |||
|
|||
#if MODULARIZE | |||
$establishStackSpaceInJsModule: function(stackBase, stackMax) { |
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.
To avoid confusion, how about renaming these params lowAddr, highAddr
? Or stackLow, stackhigh
?
I think we should do the same type of renaming in the rest of library_pthread.js
and worker.js
, where these terms appear. That is, I think it's risky and confusing to have STACK_BASE
mean one thing (the initial location of the stack) but stackBase
mean another thing (the lowest address of the stack). On fastcomp they were the same, but on the wasm backend the direction change means we are using the same words for very different things...
Instead, I suggest we can keep the meanings of "base" (initial position), "top" (current position), "max" (position we should not increment past). And for terms like lowest address and highest address, which we need in the pthreads code (e.g. since we malloc to get the lowest address), we should use lowAddr/highAddr or stackLow/stackHigh (I don't have a strong feeling between those pairs). What do you think?
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.
stackBase always means the lowest address everywhere i think, only make needs to be renamed.
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'd suggest renaming STACK_TOP to SP or STACK_POINTER, and STACK_MAX to STACK_LIMIT. stackBase/stackMax could then be used to refer to the lowest/highest address. Would that work ?
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.
stackBase always means the lowest address everywhere i think, only make needs to be renamed.
I don't think that's true for STACK_BASE
. Here is what hello world gets:
var STATIC_BASE = 1024,
STACK_BASE = 5246688,
STACKTOP = STACK_BASE,
STACK_MAX = 3808,
DYNAMIC_BASE = 5246688,
DYNAMICTOP_PTR = 3776;
STACK_BASE
is the initial value of the stack pointer, which for the wasm backend is the highest address. And as mentioned above I think it's important we keep STACK_BASE
and stackBase
consistent.
I'd suggest renaming STACK_TOP to SP or STACK_POINTER, and STACK_MAX to STACK_LIMIT. stackBase/stackMax could then be used to refer to the lowest/highest address. Would that work ?
I'm not picky about the names, but I slightly worry about expanding this PR to such a larger renaming - I think it will end up a nontrivial amount of work. In particular we may want to do the same for DYNAMIC_*
and STATIC_*
for consistency as they all use the same naming convention now. Another issue is that we hope to get rid of fastcomp eventually - it won't happen soon, but once it does, we'll just have one direction for the stack, so all this will become easier to refactor. So I'd prefer to leave a larger refactoring to a later PR (by you, if you're interested, of course).
However, if you'd rather do it here, then that sounds ok too. Those names sound generally ok. I like that LIMIT makes sense regardless of the direction the stack grows. Instead of base/max
how about min/max
for the lowest/highest addresses? And for the current location, STACK_POINTER
is probably least confusing, but then we'd want DYNAMIC_POINTER, STATIC_POINTER
for those other two, which I'm not sure about... but maybe we can leave those aside.
Did some renaming: Should we also rename the variables in the pthread/threadParams structure as well ? |
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.
Would you mind doing any renaming as separate PR? Its good to separate out non-function changes from the functional ones.
Ok, reverted the last 2 commits. |
Thanks, this looks good overall, aside from the test comment I just wrote. The |
…hould point to the top of the stack, not the bottom.
…west address since the wasm stack grows downwards.
Should be fixed. |
The stack cookie check would store to STACK_MAX-1 overwriting the malloc header when using the wasm backend. |
Great, thanks @vargaz! |
* After #8811 landed a lot more tests can pass, this enables all those that can. * Remove unnecessary stuff in test_pthread_gcc_atomic_fetch_and_op. * Add more runtime assertions for the stack position. There are still a few tests that don't pass, so this doesn't close #8718. But they are quite few at this point (and look unrelated to stack issues - something else going on there).
* After emscripten-core#8811 landed a lot more tests can pass, this enables all those that can. * Remove unnecessary stuff in test_pthread_gcc_atomic_fetch_and_op. * Add more runtime assertions for the stack position. There are still a few tests that don't pass, so this doesn't close emscripten-core#8718. But they are quite few at this point (and look unrelated to stack issues - something else going on there).
I believe these values have always been written the wrong place (off by one word) since they were adapted for the downward growing stack in #8811. In the downward growing stack that last work in the stack lives a `max` and not `max + 4`.
I believe these values have always been written the wrong place (off by one word) since they were adapted for the downward growing stack in #8811. In the downward growing stack that last work in the stack lives a `max` and not `max + 4`.
No description provided.