Delete historical interruptable support in Wasmtime (#3925)

* Delete historical interruptable support in Wasmtime

This commit removes the `Config::interruptable` configuration along with
the `InterruptHandle` type from the `wasmtime` crate. The original
support for adding interruption to WebAssembly was added pretty early on
in the history of Wasmtime when there was no other method to prevent an
infinite loop from the host. Nowadays, however, there are alternative
methods for interruption such as fuel or epoch-based interruption.

One of the major downsides of `Config::interruptable` is that even when
it's not enabled it forces an atomic swap to happen when entering
WebAssembly code. This technically could be a non-atomic swap if the
configuration option isn't enabled but that produces even more branch-y
code on entry into WebAssembly which is already something we try to
optimize. Calling into WebAssembly is on the order of a dozens of
nanoseconds at this time and an atomic swap, even uncontended, can add
up to 5ns on some platforms.

The main goal of this PR is to remove this atomic swap on entry into
WebAssembly. This is done by removing the `Config::interruptable` field
entirely, moving all existing consumers to epochs instead which are
suitable for the same purposes. This means that the stack overflow check
is no longer entangled with the interruption check and perhaps one day
we could continue to optimize that further as well.

Some consequences of this change are:

* Epochs are now the only method of remote-thread interruption.
* There are no more Wasmtime traps that produces the `Interrupted` trap
  code, although we may wish to move future traps to this so I left it
  in place.
* The C API support for interrupt handles was also removed and bindings
  for epoch methods were added.
* Function-entry checks for interruption are a tiny bit less efficient
  since one check is performed for the stack limit and a second is
  performed for the epoch as opposed to the `Config::interruptable`
  style of bundling the stack limit and the interrupt check in one. It's
  expected though that this is likely to not really be measurable.
* The old `VMInterrupts` structure is renamed to `VMRuntimeLimits`.
This commit is contained in:
Alex Crichton
2022-03-14 15:25:11 -05:00
committed by GitHub
parent 62a6a7ab6c
commit c22033bf93
33 changed files with 293 additions and 589 deletions

View File

@@ -167,6 +167,7 @@
#include <wasi.h>
#include <wasmtime/config.h>
#include <wasmtime/error.h>
#include <wasmtime/engine.h>
#include <wasmtime/extern.h>
#include <wasmtime/func.h>
#include <wasmtime/global.h>

View File

@@ -96,15 +96,6 @@ enum wasmtime_profiling_strategy_enum { // ProfilingStrategy
*/
WASMTIME_CONFIG_PROP(void, debug_info, bool)
/**
* \brief Enables WebAssembly code to be interrupted.
*
* This setting is `false` by default. When enabled it will enable getting an
* interrupt handle via #wasmtime_interrupt_handle_new which can be used to
* interrupt currently-executing WebAssembly code.
*/
WASMTIME_CONFIG_PROP(void, interruptable, bool)
/**
* \brief Whether or not fuel is enabled for generated code.
*
@@ -114,6 +105,22 @@ WASMTIME_CONFIG_PROP(void, interruptable, bool)
*/
WASMTIME_CONFIG_PROP(void, consume_fuel, bool)
/**
* \brief Whether or not epoch-based interruption is enabled for generated code.
*
* This setting is `false` by default. When enabled wasm code will check the
* current epoch periodically and abort if the current epoch is beyond a
* store-configured limit.
*
* Note that when this setting is enabled all stores will immediately trap and
* need to have their epoch deadline otherwise configured with
* #wasmtime_context_set_epoch_deadline.
*
* Note that the current epoch is engine-local and can be incremented with
* #wasmtime_engine_increment_epoch.
*/
WASMTIME_CONFIG_PROP(void, epoch_interruption, bool)
/**
* \brief Configures the maximum stack size, in bytes, that JIT code can use.
*

View File

@@ -0,0 +1,36 @@
/**
* \file wasmtime/engine.h
*
* Wasmtime-specific extensions to #wasm_engine_t.
*/
#ifndef WASMTIME_ENGINE_H
#define WASMTIME_ENGINE_H
#include <wasm.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Increments the engine-local epoch variable.
*
* This function will increment the engine's current epoch which can be used to
* force WebAssembly code to trap if the current epoch goes beyond the
* #wasmtime_store_t configured epoch deadline.
*
* This function is safe to call from any thread, and it is also
* async-signal-safe.
*
* See also #wasmtime_config_epoch_interruption_set.
*/
WASM_API_EXTERN void wasmtime_engine_increment_epoch(wasm_engine_t *engine);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WASMTIME_ENGINE_H

View File

@@ -154,7 +154,7 @@ WASM_API_EXTERN bool wasmtime_context_fuel_consumed(const wasmtime_context_t *co
WASM_API_EXTERN wasmtime_error_t *wasmtime_context_consume_fuel(wasmtime_context_t *context, uint64_t fuel, uint64_t *remaining);
/**
* \brief Configres WASI state within the specified store.
* \brief Configures WASI state within the specified store.
*
* This function is required if #wasmtime_linker_define_wasi is called. This
* will configure the WASI state for instances defined within this store to the
@@ -167,47 +167,15 @@ WASM_API_EXTERN wasmtime_error_t *wasmtime_context_consume_fuel(wasmtime_context
WASM_API_EXTERN wasmtime_error_t *wasmtime_context_set_wasi(wasmtime_context_t *context, wasi_config_t *wasi);
/**
* \typedef wasmtime_interrupt_handle_t
* \brief Convenience alias for #wasmtime_interrupt_handle_t
* \brief Configures the relative deadline at which point WebAssembly code will
* trap.
*
* \struct wasmtime_interrupt_handle_t
* \brief A handle used to interrupt executing WebAssembly code.
* This function configures the store-local epoch deadline after which point
* WebAssembly code will trap.
*
* This structure is an opaque handle that represents a handle to a store. This
* handle can be used to remotely (from another thread) interrupt currently
* executing WebAssembly code.
*
* This structure is safe to share from multiple threads.
* See also #wasmtime_config_epoch_interruption_set.
*/
typedef struct wasmtime_interrupt_handle wasmtime_interrupt_handle_t;
/**
* \brief Creates a new interrupt handle to interrupt executing WebAssembly from
* the provided store.
*
* There are a number of caveats about how interrupt is handled in Wasmtime. For
* more information see the [Rust
* documentation](https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Store.html#method.interrupt_handle).
*
* This function returns `NULL` if the store's configuration does not have
* interrupts enabled. See #wasmtime_config_interruptable_set.
*/
WASM_API_EXTERN wasmtime_interrupt_handle_t *wasmtime_interrupt_handle_new(wasmtime_context_t *context);
/**
* \brief Requests that WebAssembly code running in the store attached to this
* interrupt handle is interrupted.
*
* For more information about interrupts see #wasmtime_interrupt_handle_new.
*
* Note that this is safe to call from any thread.
*/
WASM_API_EXTERN void wasmtime_interrupt_handle_interrupt(wasmtime_interrupt_handle_t *handle);
/**
* \brief Deletes an interrupt handle.
*/
WASM_API_EXTERN void wasmtime_interrupt_handle_delete(wasmtime_interrupt_handle_t *handle);
WASM_API_EXTERN void wasmtime_context_set_epoch_deadline(wasmtime_context_t *context, uint64_t ticks_beyond_current);
#ifdef __cplusplus
} // extern "C"