about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/sys/unix/futex.rs43
-rw-r--r--library/std/src/sys/unix/thread.rs20
2 files changed, 43 insertions, 20 deletions
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs
index e6f0c48c59b..7ec3794d0b0 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,29 @@ 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;
+    }
+
+    let timeout_ms = timeout.map(|d| d.as_millis());
+    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_ms.map_or(crate::f64::INFINITY, |d| d as libc::c_double),
+        );
+    }
+}
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
 pub fn futex_wake(futex: &AtomicI32) {
     unsafe {
         libc::syscall(
@@ -35,3 +65,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 fdf114d6df6..b7b72cc392f 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);