-
Notifications
You must be signed in to change notification settings - Fork 13.7k
std: Start supporting WASIp2 natively #145944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pub use super::common::Args; | ||
|
||
/// Returns the command line arguments | ||
pub fn args() -> Args { | ||
Args::new(wasip2::cli::environment::get_arguments().into_iter().map(|arg| arg.into()).collect()) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
use crate::ffi::CStr; | ||
use crate::io; | ||
use crate::num::NonZero; | ||
use crate::time::{Duration, Instant}; | ||
|
||
pub struct Thread(!); | ||
|
||
pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; | ||
|
||
impl Thread { | ||
pub unsafe fn new( | ||
_stack: usize, | ||
_name: Option<&str>, | ||
_p: Box<dyn FnOnce()>, | ||
) -> io::Result<Thread> { | ||
// Note that unlike WASIp1 even if the wasm `atomics` feature is enabled | ||
// there is no support for threads, not even experimentally, not even in | ||
// wasi-libc. Thus this is unconditionally unsupported. | ||
crate::sys::unsupported() | ||
} | ||
|
||
pub fn yield_now() { | ||
// no API for this in WASIp2, but there's also no threads, so that's | ||
// sort of expected. | ||
} | ||
|
||
pub fn set_name(_name: &CStr) { | ||
// nope | ||
} | ||
|
||
pub fn sleep(dur: Duration) { | ||
// Sleep in increments of `u64::MAX` nanoseconds until the `dur` is | ||
// entirely drained. | ||
let mut remaining = dur.as_nanos(); | ||
while remaining > 0 { | ||
let amt = u64::try_from(remaining).unwrap_or(u64::MAX); | ||
wasip2::clocks::monotonic_clock::subscribe_duration(amt).block(); | ||
remaining -= u128::from(amt); | ||
} | ||
} | ||
|
||
pub fn sleep_until(deadline: Instant) { | ||
match u64::try_from(deadline.into_inner().as_duration().as_nanos()) { | ||
// If the point in time we're sleeping to fits within a 64-bit | ||
// number of nanoseconds then directly use `subscribe_instant`. | ||
Ok(deadline) => { | ||
wasip2::clocks::monotonic_clock::subscribe_instant(deadline).block(); | ||
} | ||
// ... otherwise we're sleeping for 500+ years relative to the | ||
// "start" of what the system is using as a clock so speed/accuracy | ||
// is not so much of a concern. Use `sleep` instead. | ||
Err(_) => { | ||
let now = Instant::now(); | ||
|
||
if let Some(delay) = deadline.checked_duration_since(now) { | ||
Self::sleep(delay); | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub fn join(self) { | ||
self.0 | ||
} | ||
} | ||
|
||
pub(crate) fn current_os_id() -> Option<u64> { | ||
None | ||
} | ||
|
||
pub fn available_parallelism() -> io::Result<NonZero<usize>> { | ||
crate::sys::unsupported() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the rationale for returning an error instead of e.g. constant 1? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is following the precedent of wasip1's implementation. Following the git-blame trail that goes back to #74480, the original implementation, which had a fallback of an error for all unknown platforms. Personally I'd say it's somewhat accurate to leave this as unsupported for now since that basically forces callers to assume it's 1 and forces a threaded implementation in the future to come through and implement this as opposed to accidentally forgetting about it |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
use crate::time::Duration; | ||
|
||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] | ||
pub struct Instant(Duration); | ||
|
||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] | ||
pub struct SystemTime(Duration); | ||
|
||
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); | ||
|
||
impl Instant { | ||
pub fn now() -> Instant { | ||
Instant(Duration::from_nanos(wasip2::clocks::monotonic_clock::now())) | ||
} | ||
|
||
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> { | ||
self.0.checked_sub(other.0) | ||
} | ||
|
||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> { | ||
Some(Instant(self.0.checked_add(*other)?)) | ||
} | ||
|
||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> { | ||
Some(Instant(self.0.checked_sub(*other)?)) | ||
} | ||
|
||
pub(super) fn as_duration(&self) -> &Duration { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl SystemTime { | ||
pub fn now() -> SystemTime { | ||
let now = wasip2::clocks::wall_clock::now(); | ||
SystemTime(Duration::new(now.seconds, now.nanoseconds)) | ||
} | ||
|
||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] | ||
pub const fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime { | ||
SystemTime(Duration::from_nanos(ts)) | ||
} | ||
|
||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] | ||
pub const fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> { | ||
// FIXME: const TryInto | ||
let ns = self.0.as_nanos(); | ||
if ns <= u64::MAX as u128 { Some(ns as u64) } else { None } | ||
} | ||
|
||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] | ||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { | ||
// FIXME: ok_or_else with const closures | ||
match self.0.checked_sub(other.0) { | ||
Some(duration) => Ok(duration), | ||
None => Err(other.0 - self.0), | ||
} | ||
} | ||
|
||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] | ||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { | ||
Some(SystemTime(self.0.checked_add(*other)?)) | ||
} | ||
|
||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] | ||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { | ||
Some(SystemTime(self.0.checked_sub(*other)?)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
pub fn fill_bytes(bytes: &mut [u8]) { | ||
bytes.copy_from_slice(&wasip2::random::random::get_random_bytes( | ||
u64::try_from(bytes.len()).unwrap(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this unwrap be fully optimised out since we're on a 32bit target? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
)); | ||
} | ||
|
||
pub fn hashmap_random_keys() -> (u64, u64) { | ||
wasip2::random::insecure_seed::insecure_seed() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -397,6 +397,16 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake | |
); | ||
} | ||
} | ||
|
||
// For testing `wasm32-wasip2`-and-beyond it's required to have | ||
// `wasm-component-ld`. This is enabled by default via `tool_enabled` | ||
// but if it's disabled then double-check it's present on the system. | ||
if target.contains("wasip") | ||
&& !target.contains("wasip1") | ||
&& !build.tool_enabled("wasm-component-ld") | ||
{ | ||
cmd_finder.must_have("wasm-component-ld"); | ||
} | ||
Comment on lines
+401
to
+409
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cc @rust-lang/bootstrap in case anybody wants to look at this |
||
} | ||
|
||
if let Some(ref s) = build.config.ccache { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -490,6 +490,7 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ | |
"windows_x86_64_gnu", | ||
"windows_x86_64_gnullvm", | ||
"windows_x86_64_msvc", | ||
"wit-bindgen", | ||
// tidy-alphabetical-end | ||
]; | ||
|
||
|
@@ -798,7 +799,10 @@ fn check_runtime_no_duplicate_dependencies(metadata: &Metadata, bad: &mut bool) | |
continue; | ||
} | ||
|
||
if !seen_pkgs.insert(&*pkg.name) { | ||
// Skip the `wasi` crate here which the standard library explicitly | ||
// depends on two version of (one for the `wasm32-wasip1` target and | ||
// another for the `wasm32-wasip2` target). | ||
if pkg.name.to_string() != "wasi" && !seen_pkgs.insert(&*pkg.name) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to call out these two changes in particular. Notably the standard library on the wasm32-wasip2 target is picking up a new dependency, The "wasi" check here is then to allow duplicate dependencies on the "wasi" crate from the standard library since it's intentional that wasm32-wasip1 depends on 0.11 and wasm32-wasip2 depends on 0.14. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mind adding a comment about why wasi is special here? |
||
tidy_error!( | ||
bad, | ||
"duplicate package `{}` is not allowed for the standard library", | ||
|
Uh oh!
There was an error while loading. Please reload this page.