wasmer_wasix/syscalls/wasix/
context_create.rs1use crate::{WasiEnv, WasiError};
2use futures::FutureExt;
3use tracing::instrument;
4use wasmer::{
5 AsStoreRef, Function, FunctionEnvMut, MemorySize, RuntimeError, StoreMut, TypedFunction, Value,
6 WasmPtr,
7};
8use wasmer_wasix_types::wasi::Errno;
9
10pub fn lookup_typechecked_entrypoint(
12 data: &WasiEnv,
13 mut store: &mut StoreMut<'_>,
14 entrypoint_id: u32,
15) -> Result<Function, Errno> {
16 let entrypoint = match data
17 .inner()
18 .indirect_function_table_lookup(&mut store, entrypoint_id)
19 {
20 Ok(func) => func,
21 Err(e) => {
22 tracing::trace!(
23 "Failed to lookup entrypoint function {}: {:?}",
24 entrypoint_id,
25 e
26 );
27 return Err(Errno::Inval);
28 }
29 };
30
31 #[cfg(not(feature = "js"))]
33 {
34 let entrypoint_type = entrypoint.ty(&store);
35 if !entrypoint_type.params().is_empty() && !entrypoint_type.results().is_empty() {
36 tracing::trace!(
37 "Entrypoint function {entrypoint_id} has invalid signature: expected () -> (), got {:?} -> {:?}",
38 entrypoint_type.params(),
39 entrypoint_type.results()
40 );
41 return Err(Errno::Inval);
42 }
43 }
44
45 Ok(entrypoint)
46}
47
48#[instrument(level = "trace", skip(ctx), ret)]
58pub fn context_create<M: MemorySize>(
59 mut ctx: FunctionEnvMut<'_, WasiEnv>,
60 new_context_ptr: WasmPtr<u64, M>,
61 entrypoint: u32,
62) -> Result<Errno, WasiError> {
63 WasiEnv::do_pending_operations(&mut ctx)?;
64
65 let Some(async_store) = ctx.as_store_async() else {
68 tracing::warn!(
69 "The WASIX context-switching API is only available in engines supporting async execution"
70 );
71 return Ok(Errno::Notsup);
72 };
73
74 let (data, mut store) = ctx.data_and_store_mut();
75
76 let Some(environment) = &data.context_switching_environment else {
78 tracing::warn!(
79 "The WASIX context-switching API is only available in a context-switching environment"
80 );
81 return Ok(Errno::Notsup);
82 };
83
84 let entrypoint = match lookup_typechecked_entrypoint(data, &mut store, entrypoint) {
86 Ok(func) => func,
87 Err(err) => {
88 return Ok(err);
89 }
90 };
91
92 let new_context_id = environment.create_context(
94 entrypoint
95 .call_async(&async_store, vec![])
96 .map(|r| r.map(|_| ())),
97 );
98
99 let memory = unsafe { data.memory_view(&store) };
101 wasi_try_mem_ok!(new_context_ptr.write(&memory, new_context_id));
102
103 return Ok(Errno::Success);
105}