Skip to content

Commit

Permalink
Wasi: preview2 poll-oneoff returns list<bool> (bytecodealliance#6498)
Browse files Browse the repository at this point in the history
* poll.wit: we can returl a list<bool> now

* adapter: fixes for poll-oneoff returning list<bool>

* wasi preview2: fixes for poll-oneoff returning list<bool>

* adapter: manually import poll-oneoff to avoid pulling in std to allocate return vec

* comment describing the skip functions
  • Loading branch information
Pat Hickey authored Jun 27, 2023
1 parent dd6adfd commit a330867
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 20 deletions.
52 changes: 42 additions & 10 deletions crates/wasi-preview1-component-adapter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@ pub mod bindings {
world: "wasi:preview/command",
std_feature,
raw_strings,
// The generated definition of command will pull in std, so we are defining it
// manually below instead
skip: ["run", "get-directories", "get-environment"],
// Automatically generated bindings for these functions will allocate
// Vecs, which in turn pulls in the panic machinery from std, which
// creates vtables that end up in the wasm elem section, which we
// can't support in these special core-wasm adapters.
// Instead, we manually define the bindings for these functions in
// terms of raw pointers.
skip: ["run", "get-environment", "poll-oneoff"],
});

#[cfg(feature = "reactor")]
Expand All @@ -45,7 +49,13 @@ pub mod bindings {
world: "wasi:preview/reactor",
std_feature,
raw_strings,
skip: ["get-directories", "get-environment"],
// Automatically generated bindings for these functions will allocate
// Vecs, which in turn pulls in the panic machinery from std, which
// creates vtables that end up in the wasm elem section, which we
// can't support in these special core-wasm adapters.
// Instead, we manually define the bindings for these functions in
// terms of raw pointers.
skip: ["get-environment", "poll-oneoff"],
});
}

Expand Down Expand Up @@ -1686,24 +1696,39 @@ pub unsafe extern "C" fn poll_oneoff(
});
}

let vec = state.import_alloc.with_buffer(
#[link(wasm_import_module = "wasi:poll/poll")]
extern "C" {
#[link_name = "poll-oneoff"]
fn poll_oneoff_import(pollables: *const Pollable, len: usize, rval: *mut BoolList);
}
let mut ready_list = BoolList {
base: std::ptr::null(),
len: 0,
};

state.import_alloc.with_buffer(
results,
nsubscriptions
.checked_mul(size_of::<bool>())
.trapping_unwrap(),
|| poll::poll_oneoff(slice::from_raw_parts(pollables.pointer, pollables.length)),
|| {
poll_oneoff_import(
pollables.pointer,
pollables.length,
&mut ready_list as *mut _,
)
},
);

assert_eq!(vec.len(), nsubscriptions);
assert_eq!(vec.as_ptr(), results);
forget(vec);
assert_eq!(ready_list.len, nsubscriptions);
assert_eq!(ready_list.base, results as *const bool);

drop(pollables);

let ready = subscriptions
.iter()
.enumerate()
.filter_map(|(i, s)| (*results.add(i) != 0).then_some(s));
.filter_map(|(i, s)| (*ready_list.base.add(i)).then_some(s));

let mut count = 0;

Expand Down Expand Up @@ -2176,6 +2201,13 @@ pub struct StrTupleList {
len: usize,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct BoolList {
base: *const bool,
len: usize,
}

const fn bump_arena_size() -> usize {
// The total size of the struct should be a page, so start there
let mut start = PAGE_SIZE;
Expand Down
7 changes: 3 additions & 4 deletions crates/wasi/src/preview2/preview2/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl<T: WasiView> poll::Host for T {
Ok(())
}

async fn poll_oneoff(&mut self, futures: Vec<Pollable>) -> anyhow::Result<Vec<u8>> {
async fn poll_oneoff(&mut self, futures: Vec<Pollable>) -> anyhow::Result<Vec<bool>> {
use crate::preview2::sched::{sync::SyncSched, Poll, Userdata, WasiSched};

// Convert `futures` into `Poll` subscriptions.
Expand Down Expand Up @@ -74,10 +74,9 @@ impl<T: WasiView> poll::Host for T {
// Do the poll.
SyncSched.poll_oneoff(&mut poll).await?;

// Convert the results into a list of `u8` to return.
let mut results = vec![0_u8; len];
let mut results = vec![false; len];
for (_result, data) in poll.results() {
results[u64::from(data) as usize] = u8::from(true);
results[u64::from(data) as usize] = true;
}
Ok(results)
}
Expand Down
10 changes: 4 additions & 6 deletions crates/wasi/wit/deps/poll/poll.wit
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@ interface poll {
/// component model async proposal, which will include a scalable waiting
/// facility.
///
/// Note that the return type would ideally be `list<bool>`, but that would
/// be more difficult to polyfill given the current state of `wit-bindgen`.
/// See <https://github.com/bytecodealliance/preview2-prototyping/pull/11#issuecomment-1329873061>
/// for details. For now, we use zero to mean "not ready" and non-zero to
/// mean "ready".
poll-oneoff: func(in: list<pollable>) -> list<u8>
/// The result list<bool> is the same length as the argument
/// list<pollable>, and indicates the readiness of each corresponding
/// element in that / list, with true indicating ready.
poll-oneoff: func(in: list<pollable>) -> list<bool>
}

0 comments on commit a330867

Please sign in to comment.