Stream: wasmtime

Topic: epoch-based interruption without `target_has_atomic = "64"`


view this post on Zulip Antoine Lavandier (Sep 30 2025 at 13:47):

Hello,

I would like to use epoch-based interruption with wasmtime but my target doesn't have 64 bits atomics. I would like to add support for this in the wasmtime. There are two orthogonal questions on which I would like feedback before trying to contribute anything

For the first question, this would increase mean writing stuff like :

    #[cfg( target_has_atomic = "64")]
    epoch: AtomicU64,
    #[cfg(all(feature = "runtime", target_has_atomic = "32", not(target_has_atomic = "64")))]
    epoch: AtomicU32,

// On every function previously #[cfg( target_has_atomic = "64")]
#[cfg(any(target_has_atomic = "64", target_has_atomic = "32"))]
fn a() {}

And documenting that the maximum number of epochs isn't the same for every platform.

Using portable-atomic would allow every platform that supports portable-atomic to use an AtomicU64. This would most likely require adding a new portable-atomic feature to wasmtime that enables this dependency and uses its atomic types instead of the ones provided by core.

view this post on Zulip Alex Crichton (Sep 30 2025 at 14:06):

Would using fuel work for your use case? Epochs get pretty tricky without 64-bit atomics unfortunately. One of the difficulties is plumbing this support through not only #[cfg] but through. Cranelift as well to understand it's a 32-bit variable instead of a 64-bit variable

view this post on Zulip Antoine Lavandier (Sep 30 2025 at 14:21):

Then using portable-atomic would be more suited than lowering the size of the atomics.
I could probably use fuel provided that it works well with async but I'm worried about the increased code size from the fuel instrumentation

view this post on Zulip Alex Crichton (Sep 30 2025 at 14:25):

Oh that'd be an interesting point of comparison yeah, code size with/without fuel. If the code size of fuel vs epochs is a tipping point it's honestly probably easier to make the code size for fuel smaller (e.g. I assume you're using Pulley so we could start adding some custom opcodes)

view this post on Zulip Alex Crichton (Sep 30 2025 at 14:27):

Otherwise though one way we could manage #[cfg] is to, in theory, have:

#[cfg(long_expr)]
mod epoch64;
#[cfg(not(long_expr), longer_expr)]
mod epoch32;
#[cfg(not(long_expr), not(longer_expr))]
mod epoch_disabled;

or something like that, basically only having #[cfg] at the module level and stuffing it all in there

view this post on Zulip Antoine Lavandier (Sep 30 2025 at 14:38):

I tried to precompile the same component with the following options :

    config.memory_reservation(0);
    config.wasm_custom_page_sizes(true);
    config.memory_may_move(false);
    config.memory_init_cow(false);
    config.cranelift_opt_level(wasmtime::OptLevel::SpeedAndSize);
    config.target("pulley32");

view this post on Zulip Antoine Lavandier (Sep 30 2025 at 14:42):

If using the portable-atomic it could also be as simple as changing this in engine.rs

use core::sync::atomic::Ordering;
#[cfg(target_has_atomic = "64")]
use core::sync::atomic::AtomicU64;
#[cfg(feature = "portable-atomic")]
use portable_atomic::AtomicU64;

Or am I missing something with regards to Cranelift ?

view this post on Zulip Alex Crichton (Sep 30 2025 at 15:41):

I'm not really sure, I don't know how portable-atomic is itself implemented

view this post on Zulip Alex Crichton (Sep 30 2025 at 15:41):

I'd have to dig into how an atomic 64-bit read works, because for example that's what Cranelift does and whatever portable-atomic does would need to be reflected into Cranelift too


Last updated: Dec 06 2025 at 06:05 UTC