about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/sys/wasi/mod.rs3
-rw-r--r--library/std/src/sys/wasi/os.rs34
2 files changed, 28 insertions, 9 deletions
diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs
index 683a07a34dc..c8c47763a34 100644
--- a/library/std/src/sys/wasi/mod.rs
+++ b/library/std/src/sys/wasi/mod.rs
@@ -25,6 +25,9 @@ pub mod cmath;
 pub mod env;
 pub mod fd;
 pub mod fs;
+#[allow(unused)]
+#[path = "../wasm/atomics/futex.rs"]
+pub mod futex;
 pub mod io;
 #[path = "../unsupported/locks/mod.rs"]
 pub mod locks;
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index cab2887dfcf..f5513e9996d 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -1,11 +1,11 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
-use crate::any::Any;
 use crate::error::Error as StdError;
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
+use crate::ops::Drop;
 use crate::os::wasi::prelude::*;
 use crate::path::{self, PathBuf};
 use crate::str;
@@ -24,10 +24,26 @@ mod libc {
     }
 }
 
-#[cfg(not(target_feature = "atomics"))]
-pub unsafe fn env_lock() -> impl Any {
-    // No need for a lock if we're single-threaded, but this function will need
-    // to get implemented for multi-threaded scenarios
+cfg_if::cfg_if! {
+    if #[cfg(target_feature = "atomics")] {
+        // Access to the environment must be protected by a lock in multi-threaded scenarios.
+        use crate::sync::{PoisonError, RwLock};
+        static ENV_LOCK: RwLock<()> = RwLock::new(());
+        pub fn env_read_lock() -> impl Drop {
+            ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
+        }
+        pub fn env_write_lock() -> impl Drop {
+            ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner)
+        }
+    } else {
+        // No need for a lock if we are single-threaded.
+        pub fn env_read_lock() -> impl Drop {
+            Box::new(())
+        }
+        pub fn env_write_lock() -> impl Drop {
+            Box::new(())
+        }
+    }
 }
 
 pub fn errno() -> i32 {
@@ -144,7 +160,7 @@ impl Iterator for Env {
 
 pub fn env() -> Env {
     unsafe {
-        let _guard = env_lock();
+        let _guard = env_read_lock();
         let mut environ = libc::environ;
         let mut result = Vec::new();
         if !environ.is_null() {
@@ -175,7 +191,7 @@ pub fn env() -> Env {
 
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     let s = run_with_cstr(k.as_bytes(), |k| unsafe {
-        let _guard = env_lock();
+        let _guard = env_read_lock();
         Ok(libc::getenv(k.as_ptr()) as *const libc::c_char)
     })
     .ok()?;
@@ -189,7 +205,7 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
     run_with_cstr(k.as_bytes(), |k| {
         run_with_cstr(v.as_bytes(), |v| unsafe {
-            let _guard = env_lock();
+            let _guard = env_write_lock();
             cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
         })
     })
@@ -197,7 +213,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
 
 pub fn unsetenv(n: &OsStr) -> io::Result<()> {
     run_with_cstr(n.as_bytes(), |nbuf| unsafe {
-        let _guard = env_lock();
+        let _guard = env_write_lock();
         cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
     })
 }