diff options
| author | bors <bors@rust-lang.org> | 2020-11-12 05:52:17 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-11-12 05:52:17 +0000 |
| commit | 55794e43960ad3647e78ea5b0cb5ad0c5c0596a8 (patch) | |
| tree | 8f15452ce9172f3340c458c214eb9f70ff91e359 /library/std/src/sys | |
| parent | 5a6a41e7847ff5f85a31b87431ce2af29c567f1d (diff) | |
| parent | bf3be09ee800de4ec98dfeea5088639e1c538813 (diff) | |
| download | rust-55794e43960ad3647e78ea5b0cb5ad0c5c0596a8.tar.gz rust-55794e43960ad3647e78ea5b0cb5ad0c5c0596a8.zip | |
Auto merge of #78965 - jryans:emscripten-threads-libc, r=kennytm
Update thread and futex APIs to work with Emscripten This updates the thread and futex APIs in `std` to match the APIs exposed by Emscripten. This allows threads to run on `wasm32-unknown-emscripten` and the thread parker to compile without errors related to the missing `futex` module. To make use of this, Rust code must be compiled with `-C target-feature=atomics` and Emscripten must link with `-pthread`. I have confirmed this works well locally when building multithreaded crates. Attempting to enable `std` thread tests currently fails for seemingly obscure reasons and Emscripten is currently disabled in CI, so further work is needed to have proper test coverage here.
Diffstat (limited to 'library/std/src/sys')
| -rw-r--r-- | library/std/src/sys/unix/futex.rs | 42 | ||||
| -rw-r--r-- | library/std/src/sys/unix/thread.rs | 20 |
2 files changed, 42 insertions, 20 deletions
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs index e6f0c48c59b..42ddc1d514e 100644 --- a/library/std/src/sys/unix/futex.rs +++ b/library/std/src/sys/unix/futex.rs @@ -1,10 +1,17 @@ -#![cfg(any(target_os = "linux", target_os = "android"))] +#![cfg(any( + target_os = "linux", + target_os = "android", + all(target_os = "emscripten", target_feature = "atomics") +))] +#[cfg(any(target_os = "linux", target_os = "android"))] use crate::convert::TryInto; +#[cfg(any(target_os = "linux", target_os = "android"))] use crate::ptr::null; use crate::sync::atomic::AtomicI32; use crate::time::Duration; +#[cfg(any(target_os = "linux", target_os = "android"))] pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) { let timespec = timeout.and_then(|d| { Some(libc::timespec { @@ -25,6 +32,28 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) { } } +#[cfg(target_os = "emscripten")] +pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) { + extern "C" { + fn emscripten_futex_wait( + addr: *const AtomicI32, + val: libc::c_uint, + max_wait_ms: libc::c_double, + ) -> libc::c_int; + } + + unsafe { + emscripten_futex_wait( + futex as *const AtomicI32, + // `val` is declared unsigned to match the Emscripten headers, but since it's used as + // an opaque value, we can ignore the meaning of signed vs. unsigned and cast here. + expected as libc::c_uint, + timeout.map_or(crate::f64::INFINITY, |d| d.as_secs_f64() * 1000.0), + ); + } +} + +#[cfg(any(target_os = "linux", target_os = "android"))] pub fn futex_wake(futex: &AtomicI32) { unsafe { libc::syscall( @@ -35,3 +64,14 @@ pub fn futex_wake(futex: &AtomicI32) { ); } } + +#[cfg(target_os = "emscripten")] +pub fn futex_wake(futex: &AtomicI32) { + extern "C" { + fn emscripten_futex_wake(addr: *const AtomicI32, count: libc::c_int) -> libc::c_int; + } + + unsafe { + emscripten_futex_wake(futex as *const AtomicI32, 1); + } +} diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index f1ab302d30e..cda17eb4bd2 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -22,24 +22,6 @@ pub struct Thread { unsafe impl Send for Thread {} unsafe impl Sync for Thread {} -// The pthread_attr_setstacksize symbol doesn't exist in the emscripten libc, -// so we have to not link to it to satisfy emcc's ERROR_ON_UNDEFINED_SYMBOLS. -#[cfg(not(target_os = "emscripten"))] -unsafe fn pthread_attr_setstacksize( - attr: *mut libc::pthread_attr_t, - stack_size: libc::size_t, -) -> libc::c_int { - libc::pthread_attr_setstacksize(attr, stack_size) -} - -#[cfg(target_os = "emscripten")] -unsafe fn pthread_attr_setstacksize( - _attr: *mut libc::pthread_attr_t, - _stack_size: libc::size_t, -) -> libc::c_int { - panic!() -} - impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> { @@ -50,7 +32,7 @@ impl Thread { let stack_size = cmp::max(stack, min_stack_size(&attr)); - match pthread_attr_setstacksize(&mut attr, stack_size) { + match libc::pthread_attr_setstacksize(&mut attr, stack_size) { 0 => {} n => { assert_eq!(n, libc::EINVAL); |
