Skip to content

Commit

Permalink
Update memfd support with a runtime toggle (bytecodealliance#3778)
Browse files Browse the repository at this point in the history
This commit updates the `memfd` support in Wasmtime to have a runtime
toggle as to whether it's used or not. The compile-time feature gating
`memfd` support is now also re-enabled by default, but the new runtime
switch is still disabled-by-default.

Additionally this commit updates our fuzz oracle to turn on/off the
memfd flag to re-enable fuzzing with memfd on oss-fuzz.
  • Loading branch information
alexcrichton authored and mpardesh committed Mar 17, 2022
1 parent 65b984f commit f58dd88
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ default = [
"wasmtime/parallel-compilation",
"wasi-nn",
"pooling-allocator",
"memfd",
]
jitdump = ["wasmtime/jitdump"]
vtune = ["wasmtime/vtune"]
Expand Down
4 changes: 3 additions & 1 deletion crates/fuzzing/src/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub struct WasmtimeConfig {
pub(crate) consume_fuel: bool,
memory_config: MemoryConfig,
force_jump_veneers: bool,
memfd: bool,
}

#[derive(Arbitrary, Clone, Debug, Eq, Hash, PartialEq)]
Expand Down Expand Up @@ -99,7 +100,8 @@ impl Config {
.cranelift_nan_canonicalization(self.wasmtime.canonicalize_nans)
.cranelift_opt_level(self.wasmtime.opt_level.to_wasmtime())
.interruptable(self.wasmtime.interruptable)
.consume_fuel(self.wasmtime.consume_fuel);
.consume_fuel(self.wasmtime.consume_fuel)
.memfd(self.wasmtime.memfd);

// If the wasm-smith-generated module use nan canonicalization then we
// don't need to enable it, but if it doesn't enable it already then we
Expand Down
11 changes: 10 additions & 1 deletion crates/wasmtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,16 @@ wasi-cap-std-sync = { path = "../wasi-common/cap-std-sync" }
maintenance = { status = "actively-developed" }

[features]
default = ['async', 'cache', 'wat', 'jitdump', 'parallel-compilation', 'cranelift', 'pooling-allocator']
default = [
'async',
'cache',
'wat',
'jitdump',
'parallel-compilation',
'cranelift',
'pooling-allocator',
'memfd',
]

# An on-by-default feature enabling runtime compilation of WebAssembly modules
# with the Cranelift compiler. Cranelift is the default compilation backend of
Expand Down
30 changes: 30 additions & 0 deletions crates/wasmtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ pub struct Config {
pub(crate) module_version: ModuleVersionStrategy,
pub(crate) parallel_compilation: bool,
pub(crate) paged_memory_initialization: bool,
pub(crate) memfd: bool,
}

impl Config {
Expand All @@ -129,6 +130,7 @@ impl Config {
parallel_compilation: true,
// Default to paged memory initialization when using uffd on linux
paged_memory_initialization: cfg!(all(target_os = "linux", feature = "uffd")),
memfd: false,
};
#[cfg(compiler)]
{
Expand Down Expand Up @@ -1170,6 +1172,33 @@ impl Config {
self
}

/// Configures whether `memfd`, if supported, will be used to initialize
/// applicable module memories.
///
/// This is a Linux-specific feature since `memfd` is only supported on
/// Linux. Support for this is also enabled by default at compile time but
/// is otherwise disabled at runtime by default. This feature needs to be
/// enabled to `true` for support to be used.
///
/// Also note that even if this feature is enabled it may not be applicable
/// to all memories in all wasm modules. At this time memories must meet
/// specific criteria to be memfd-initialized:
///
/// * Only memories defined in the module can be initialized this way.
/// * Data segments for memory must use statically known offsets.
/// * Data segments for memory must all be in-bounds.
///
/// If all of the above applies, this setting is enabled, and the current
/// platform is Linux the `memfd` will be used to efficiently initialize
/// linear memories with `mmap` to avoid copying data from initializers into
/// linear memory.
#[cfg(feature = "memfd")]
#[cfg_attr(nightlydoc, doc(cfg(feature = "memfd")))]
pub fn memfd(&mut self, memfd: bool) -> &mut Self {
self.memfd = memfd;
self
}

pub(crate) fn build_allocator(&self) -> Result<Box<dyn InstanceAllocator>> {
#[cfg(feature = "async")]
let stack_size = self.async_stack_size;
Expand Down Expand Up @@ -1239,6 +1268,7 @@ impl Clone for Config {
module_version: self.module_version.clone(),
parallel_compilation: self.parallel_compilation,
paged_memory_initialization: self.paged_memory_initialization,
memfd: self.memfd,
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions crates/wasmtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,21 @@
//! all architectures for both the JIT compiler and the `wasmtime compile` CLI
//! command.
//!
//! * `pooling-allocator` - Enabled by default, this feature adds support for
//! the pooling allocation strategy enabled via
//! [`Config::allocation_strategy`]. The pooling allocator can enable more
//! efficient reuse of resources for high-concurrency and
//! high-instantiation-count scenarios.
//!
//! * `memfd` - Enabled by default, this feature builds in support for a
//! Linux-specific feature of creating a `memfd` where applicable for a
//! [`Module`]'s initial memory. This makes instantiation much faster by
//! `mmap`-ing the initial memory image into place instead of copying memory
//! into place, allowing sharing pages that end up only getting read and
//! otherwise using copy-on-write for efficient initialization of memory. Note
//! that this is simply compile-time support and this must also be enabled at
//! run-time via [`Config::memfd`].
//!
//! ## Examples
//!
//! In addition to the examples below be sure to check out the [online embedding
Expand Down
3 changes: 3 additions & 0 deletions crates/wasmtime/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,9 @@ impl Module {
}

pub(crate) fn memfds(&self) -> Result<Option<&Arc<ModuleMemFds>>> {
if !self.engine().config().memfd {
return Ok(None);
}
Ok(self
.inner
.memfds
Expand Down

0 comments on commit f58dd88

Please sign in to comment.