-
Notifications
You must be signed in to change notification settings - Fork 18
GrowableSharedArrayBuffer.prototype.grow maybe not handling races correctly #39
Comments
Yes, the way this is currently done in the Wasm spec at the operational level is
The axiomatic part of the semantics ensures that all the RMWs are totally ordered, so no growths are "lost". I think this is similar in spirit to our previous discussion about the specification of EDIT: my original comment stated that an SC read of the length is emitted if the growth fails, but our current spec is actually weaker than this, since we don't observably distinguish between non-deterministic OOM errors and growth-over-max errors. EDIT2: also, if I'm reading the JS spec correctly, there needs to be a data write of 0s to the new memory, so that subsequent reads have initial values they can take. |
Another great catch @marjakh. Thanks for the info on the wasm side too, @conrad-watt.
This is how it works in the JS spec and this spec draft as well. In any case I don't think a loop is needed.
Good catch, this is right. |
@syg in the spec you linked, line 8 appears to be performing an SC read of the buffer length, while line 9.c performs a separate SC write. If the read and write are not performed as a single RMW, it's possible to "lose" growths (i.e. two concurrent growths read the same value, and both race to write back their "new length"). I think this is what @marjakh is describing. |
Ah duh, absolutely right on the need for RMW. |
From the spec's perspective, this isn't necessary because the spec fiction is that a shared data block of size maxLength is allocated up front, and since a SAB can never shrink, any new memory is already zeroed. In implementations, I'm actually not too sure how this should be done. Does it basically require zero-fill-on-demand pages? You can't speculatively zero bytes ahead of time, in case while you're doing that another |
Ah I see, that works!
My understanding is that because engines pretty much all implement shared memories in place, all of the zeroed pages are allocated upfront, and some bounds-checking implementation (either explicit checks or trap handler) controls which pages are accessible without provoking OOB errors at the Wasm level. So the formal model you sketched above actually corresponds pretty closely to reality. |
Closes #39 Some interesting tidbits: - HostGrowSharedArrayBuffer does its own bounds checking so the host can control when to do the read as part of a LL/SC pair - The zeroing semantics basically requires ZFOD pages
cc @jandem |
Closes #39 Some interesting tidbits: - HostGrowSharedArrayBuffer does its own bounds checking so the host can control when to do the read as part of a LL/SC pair - The zeroing semantics basically requires ZFOD pages
Closes #39 Some interesting tidbits: - HostGrowSharedArrayBuffer does its own bounds checking so the host can control when to do the read as part of a LL/SC pair - The zeroing semantics basically requires ZFOD pages
Closes #39 Some interesting tidbits: - HostGrowSharedArrayBuffer does its own bounds checking so the host can control when to do the read as part of a LL/SC pair - The zeroing semantics basically requires ZFOD pages
Example: T1 and T2 both have GSABs which share the same backing memory, current length 10.
T1 does:
gsab.grow(20);
T2 does:
gsab.grow(40);
Looks like this could happen:
T1 executes steps 1 - 5 of GrowableSharedArrayBuffer.prototype.grow. (Now we're past the point of throwing because the buffer would shrink.)
T2 executes GrowableSharedArrayBuffer.prototype.grow; 40 is written in the memory as the new byte length.
T2 goes on and does other stuff with the GSAB.
T1 executes the rest of GrowableSharedArrayBuffer.prototype.grow. 20 is written in the memory as the new byte length.
-> From T2's point of view, the buffer has now shrunk.
Potential fix:
Structure the spec like the implementation is structured: read currentByteLength in a loop, and each iteration of the loop does the "throw if shrinking" check.
(Btw, reading currentByteLength seems to be missing from the spec too.)
The text was updated successfully, but these errors were encountered: