Stream: git-wasmtime

Topic: wasmtime / issue #12809 Epoch interruption of memory.atom...


view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 09:13):

Destructor17 opened issue #12809:

Feature

Epoch interruption has no effect on memory.atomic.wait* instructions since they just block and give no opportunity for epoch checking to occur. So it would be nice to make threads work with epoch interruption.

Benefit

Being able to interrupt threads that stale on waiting for something to happen on another thread.

I'm personally interested in being able to do the following with programs targeting wasip1-threads:

Implementation

I believe this problem can be solved by doing the following:

This is what I initially tried to do on my own, but wasmtime-internal-cranelift crate scared me a bit, so I guess it is better to be done by someone who knows what to do.

I'm believe there is no need to try to do the same with fuel consumption.

Alternatives

Alternative 1. Almost the same can be done by transforming WASM. Same loop, but timeout is limited to, let's say, 10 ms. Not sure when to break that loop. It comes with huge performance penalty of program that spawn lots of stale threads.

Alternative 2. Notify all waits on all shared memories without doing any changes, probably multiple times, SO memory.atomic.wait* would simply return 0 (Ok). May break some logic in guest code, so it is suitable only for terminating.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 09:15):

Destructor17 edited issue #12809:

Feature

Epoch interruption has no effect on memory.atomic.wait* instructions since they just block and give no opportunity for epoch checking to occur. So it would be nice to make threads work with epoch interruption.

Benefit

Being able to interrupt threads that stale on waiting for something to happen on another thread.

I'm personally interested in being able to do the following with programs targeting wasip1-threads:

Implementation

I believe this problem can be solved by doing the following:

This is what I initially tried to do on my own, but wasmtime-internal-cranelift crate scared me a bit, so I guess it is better to be done by someone who knows what to do.

I believe there is no need to try to do the same with fuel consumption.

Alternatives

Alternative 1. Almost the same can be done by transforming WASM. Same loop, but timeout is limited to, let's say, 10 ms. Not sure when to break that loop. It comes with huge performance penalty of program that spawn lots of stale threads.

Alternative 2. Notify all waits on all shared memories without doing any changes, probably multiple times, SO memory.atomic.wait* would simply return 0 (Ok). May break some logic in guest code, so it is suitable only for terminating.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 09:16):

Destructor17 edited issue #12809:

Feature

Epoch interruption has no effect on memory.atomic.wait* instructions since they just block and give no opportunity for epoch checking to occur. So it would be nice to make threads work with epoch interruption.

Benefit

Being able to interrupt threads that stale on waiting for something to happen on another thread.

I'm personally interested in being able to do the following with programs targeting wasip1-threads:

Implementation

I believe this problem can be solved by doing the following:

This is what I initially tried to do on my own, but wasmtime-internal-cranelift crate scared me a bit, so I guess it is better to be done by someone who knows what to do.

I believe there is no need to try to do the same for fuel consumption.

Alternatives

Alternative 1. Almost the same can be done by transforming WASM. Same loop, but timeout is limited to, let's say, 10 ms. Not sure when to break that loop. It comes with huge performance penalty of program that spawn lots of stale threads.

Alternative 2. Notify all waits on all shared memories without doing any changes, probably multiple times, so memory.atomic.wait* instructions would simply return 0 (Ok). May break some logic in guest code, so it is suitable only for terminating.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 09:17):

Destructor17 edited issue #12809:

Feature

Currently epoch interruption has no effect on memory.atomic.wait* instructions since they just block and give no opportunity for epoch checking to occur. It would be nice to make threads work with epoch interruption.

Benefit

Being able to interrupt threads that stale on waiting for something to happen on another thread.

I'm personally interested in being able to do the following with programs targeting wasip1-threads:

Implementation

I believe this problem can be solved by doing the following:

This is what I initially tried to do on my own, but wasmtime-internal-cranelift crate scared me a bit, so I guess it is better to be done by someone who knows what to do.

I believe there is no need to try to do the same for fuel consumption.

Alternatives

Alternative 1. Almost the same can be done by transforming WASM. Same loop, but timeout is limited to, let's say, 10 ms. Not sure when to break that loop. It comes with huge performance penalty of program that spawn lots of stale threads.

Alternative 2. Notify all waits on all shared memories without doing any changes, probably multiple times, so memory.atomic.wait* instructions would simply return 0 (Ok). May break some logic in guest code, so it is suitable only for terminating.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 09:29):

Destructor17 edited issue #12809:

Feature

Currently epoch interruption has no effect on memory.atomic.wait* instructions since they just block and give no opportunity for epoch checking to occur. It would be nice to make threads work with epoch interruption.

Benefit

Being able to interrupt threads that stale on waiting for something to happen on another thread.

I'm personally interested in being able to do the following with programs targeting wasip1-threads:

Implementation

I believe this problem can be solved by doing the following:

This is what I initially tried to do on my own, but wasmtime-internal-cranelift crate scared me a bit, so I guess it is better to be done by someone who knows what to do.

I believe there is no need to try to do the same for fuel consumption.

Alternatives

Alternative 1. Almost the same can be done by transforming WASM. Same loop, but timeout is limited to, let's say, 10 ms. Not sure when to break that loop. It comes with huge performance penalty of program that spawn lots of stale threads.

Alternative 2. Notify all waits on all shared memories without doing any changes, probably multiple times, so memory.atomic.wait* instructions would simply return 0 (Ok). May break some logic in guest code, so it is suitable only for terminating.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 09:49):

Destructor17 edited issue #12809:

Feature

Currently epoch interruption has no effect on memory.atomic.wait* instructions since they just block and give no opportunity for epoch checking to occur. It would be nice to make threads work with epoch interruption.

Benefit

Being able to interrupt threads that stale on waiting for something to happen on another thread.

I'm personally interested in being able to do the following with programs targeting wasip1-threads:

Implementation

I believe this problem can be solved by doing the following:

This is what I initially tried to do on my own, but wasmtime-internal-cranelift crate scared me a bit, so I guess it is better to be done by someone who knows what to do.

I believe there is no need to try to do the same for fuel consumption.

Alternatives

Alternative 1. Almost the same can be done by transforming WASM. Same loop, but timeout is limited to, let's say, 10 ms. Not sure when to break that loop. It comes with huge performance penalty of program that spawn lots of stale threads.

Alternative 2. Notify all waits on all shared memories without doing any changes, probably multiple times, so memory.atomic.wait* instructions would simply return 0 (Ok). May break some logic in guest code, so it is suitable only for terminating.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 09:51):

Destructor17 edited issue #12809:

Feature

Currently epoch interruption has no effect on memory.atomic.wait* instructions since they just block and give no opportunity for epoch checking to occur. It would be nice to make threads work with epoch interruption.

Benefit

Being able to interrupt threads that stale on waiting for something to happen on another thread.

I'm personally interested in being able to do the following with programs targeting wasip1-threads:

Implementation

I believe this problem can be solved by doing the following:

This is what I initially tried to do on my own, but wasmtime-internal-cranelift crate scared me a bit, so I guess it is better to be done by someone who knows what to do.

I believe there is no need to try to do the same for fuel consumption.

Alternatives

Alternative 1. Almost the same can be done by transforming WASM. Same loop, but timeout is limited to, let's say, 10 ms. Not sure when to break that loop. It comes with huge performance penalty for programs that spawn lots of stale threads.

Alternative 2. Notify all waits on all shared memories without doing any changes, probably multiple times, so memory.atomic.wait* instructions would simply return 0 (Ok). May break some logic in guest code, so it is suitable only for terminating.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 12:26):

Destructor17 edited issue #12809:

Feature

Currently epoch interruption has no effect on memory.atomic.wait* instructions since they just block and give no opportunity for epoch checking to occur. It would be nice to make threads work with epoch interruption.

Benefit

Being able to interrupt threads that stale on waiting for something to happen on another thread.

I'm personally interested in being able to do the following with programs targeting wasip1-threads:

Implementation

I believe this problem can be solved by doing the following:

This is what I initially tried to do on my own, but wasmtime-internal-cranelift crate scared me a bit, so I guess it is better to be done by someone who knows what to do.

I believe there is no need to try to do the same for fuel consumption.

Alternatives

Alternative 1. Almost the same can be done by transforming WASM. Same loop, but timeout is limited to, let's say, 10 ms. Not sure when to break that loop. It comes with huge performance penalty for programs that spawn lots of stale threads.

Alternative 2. Notify all waits on all shared memories without doing any changes, probably multiple times, so memory.atomic.wait* instructions would simply return 0 (Ok). May break some logic in guest code, so it is suitable only for terminating.

Alternative 3. That loop, as well as checking for epoch, can be implemented on the host side, but I don't know how to access current epoch value from there.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 24 2026 at 15:54):

cfallin commented on issue #12809:

Thanks for filing an issue for this!

I think your suggested approach is, at a high level, what we would prefer. We definitely do not want Alternative 2 because it violates Wasm semantics. Alternative 1, instrumentation-based, is heavyweight and generally not our preferred approach either.

The way I would probably go about this is to implement a mechanism on the Engine to register a thread-to-be-parked that should be awoken on epoch change (with a handle that implements Drop to de-register). Then the thread::park-based implementation would need to have a reference to Engine plumbed through, and would do a scoped thing registering on the Engine just for the duration of the wait. I am imagining something like

let mut park_handle = Engine.park_handle();
match park_handle.park_timeout(timeout) {
  EngineParkResult::Notified => ...,
  EngineParkResult::EpochChange => ...
}

replacing the std::thread::park_timeout call here. That implies the existence of mutex-protected registration state inside Engine. As you say all of this should be gated on epoch-interruption actually being enabled; park-handles should be no-ops that directly pass through to thread parking otherwise. Then the EpochChange return needs to be plumbed upward to the async layer to do an epoch yield (see the normal epoch yield libcall), and that whole thing needs to be wrapped in a retry loop as you say so we don't return to the Wasm from the wait libcall until we get a true notify result.

Others may have other thoughts too but that seems like a workable design to me. I think that this should be implementable without changing the compiled code at all -- wait operations are still single libcalls.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 25 2026 at 10:29):

Destructor17 commented on issue #12809:

And one more thing: I'm believe timeout should be somehow altered in that retry loop. Otherwise, if guest code wants to wait for 1s, but epoch change occurs every 0.5s, EngineParkResult::Notified would never be returned. It makes sense to set a deadline instead, but I'm also unsure weather time spent by epoch handling should be accounted.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 25 2026 at 10:34):

Destructor17 edited a comment on issue #12809:

And one more thing: I'm believe timeout should be somehow altered in that retry loop. Otherwise, if guest code wants to wait for 1s, but epoch change occurs every 0.5s, libcall would never return. It makes sense to set a deadline instead, but I'm also unsure weather time spent by epoch handling should be accounted.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 25 2026 at 13:47):

cfallin commented on issue #12809:

And one more thing: I'm believe timeout should be somehow altered in that retry loop

I don't think that's necessary actually, with the design I outlined: the idea is that the Engine would also hold a list of threads currently parked on any memory wait, and would immediately unpark/wake-up all such threads on an epoch change.

In other words, a timeout isn't needed as part of the wakeup path, and we really don't want that either, because of the additional latency implications.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 30 2026 at 14:13):

alexcrichton added the wasm-proposal:threads label to Issue #12809.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 30 2026 at 14:18):

alexcrichton commented on issue #12809:

Personally I'm a bit wary to push shared memory too too much further, especially with possibly-invasive features like this, without a champion for shared memory. Shared memory has quite a few open issues (#4245) and not much work going towards resolving these issues. This is one behavior that stems from the "spec tests pass" implementation we currently have where we are still relatively far from a production-quality implementation with all the expected knobs and such.

I mostly want to caution you @Destructor17 insofar that wasm32-wasip1-threads is effectively a dead target in terms of upstream development. Wasmtime can run those binaries but not in a way that's highly customizable to embedders (e.g. this issue). Supporting these use cases and adding more features would require a lot of work on your (or someone else's) part in terms of designing the feature, working with maintainers to ensure it's appropriate, implementing/landing/etc.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 30 2026 at 14:38):

Destructor17 commented on issue #12809:

wasm32-wasip1-threads is effectively a dead target in terms of upstream development

Sad to hear that. wasm32-wasip1-threads seem to be the only usable WASI target with threads support so far. I'm looking forward for WASIp3, but for now current state of shared memory support in Wasmtime is fine for my particular usecase. As about this missing feature - it can be easily implemented and kept off-tree and unpolished, as I don't know if other Wasmtime users would actually benefit from it.


Last updated: Apr 12 2026 at 23:10 UTC