Skip to content

Epoch interruption of memory.atomic.wait* instructions #12809

@Destructor17

Description

@Destructor17

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:

  • Terminating all threads on some event (a trap, proc_exit, etc.)
  • Pausing all threads for debug purposes

Implementation

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

  • Extending wasmtime::runtime::vm::WaitResult with an new case. (e.g. Interrupted = 3)
  • Adding a function to notify all shared memories in engine to return that new case. Maybe even call it on each Engine::increment_epoch
  • Wrapping each call to memory_atomic_wait* builtin function with a loop. That loop would check epoch and continue if returned value is Interrupted, and break otherwise. It may worth it to gate this transformation behind some condition, like weather epoch interruption is enabled, or a dedicated flag in Config.

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions