wazero icon indicating copy to clipboard operation
wazero copied to clipboard

Support read visibility of mutable globals across goroutines

Open codefromthecrypt opened this issue 3 years ago • 5 comments

Globals in WebAssembly 1.0 (MVP) are alllowed to be mutable, and stored internally as a uint64. We need to internally guarantee visibility of writes across goroutines for these, or document that any module that uses a global mutable is not goroutine safe. The jist of the problem is in https://go.dev/ref/mem that there is "no guarantee that the write to done will ever be observed"

Details:

This recent comment from go underscores the existing memory model guarantee, that in a single goroutine writer model, ordering is preserved. It also vaguely mentions there are no shearing of machine-size words, which is good for our current and planned supported archs (64bit).

However, that same issue mentions and re-iterates the "possibly never" conditions on a write from another goroutine. Delayed reads of a mutable global are likely to be understood, but the "possibly never" would invalidate the point in having it mutable, unless you are guaranteed that these are pinned to a goroutine or all access is externally synchronized. I mention "all access" because global writes can also be done in wasm by global.set.

codefromthecrypt avatar Feb 23 '22 23:02 codefromthecrypt

Another aspect related would be memory imports, though I suspect these are more likely to be understood as unsafe as they are always multi-word (page size is 64K)

codefromthecrypt avatar Feb 23 '22 23:02 codefromthecrypt

Current Status:

Current thinking for globals is to leave mutability supported at scope of goroutine. This means any number of modules can share a global as long as they don't leave a goroutine.

Next Action:

To share mutable across goroutines requires end-user demand, as it is tricky to implement. Concretely, someone needs to ask for this, on this issue.

Details:

It is possible to implement mutable globals in such a way that writes are eventually visible to other goroutines. The simpler implementation of this is to use a go function to manage each mutable shared global (on config). A more sophisticated one would share a mutex compiled in JIT. The key is that both the host and wasm can mutate a global, and wasm is implemented in assembly if using JIT. This means implementation is trickier than a simple lock. Hence, end user demand needs to justify the effort!

codefromthecrypt avatar Feb 24 '22 07:02 codefromthecrypt

I'm not really even sure mutable global import/export is a WebAssembly 1.0 (MVP) feature or not. I think it is, but raised https://github.com/WebAssembly/spec/issues/1425 to qualify

codefromthecrypt avatar Feb 25 '22 01:02 codefromthecrypt

actually it is supported as looking at the diff, the following like was removed, and the published spec doesn't have this line:

In the current version of WebAssembly, only immutable globals may be exported.

codefromthecrypt avatar Feb 25 '22 01:02 codefromthecrypt

Mutable globals are enabled by default, but can be disabled by RuntimeConfig now

codefromthecrypt avatar Mar 03 '22 22:03 codefromthecrypt