From 58988b86f743c257f09d56404558c948520569c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Sun, 7 Apr 2019 00:13:32 +0300 Subject: [PATCH 1/4] remove TLS --- src/lib.rs | 17 +---- src/linux_android.rs | 139 ++++++++++++++++++++++++---------------- src/solaris_illumos.rs | 142 ++++++++++++++++++++++++----------------- src/use_file.rs | 79 ++++++++++++++++++----- src/wasm32_bindgen.rs | 26 ++++---- src/wasm32_stdweb.rs | 55 ++++++++-------- 6 files changed, 271 insertions(+), 187 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e5fde089..ad2a79c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,21 +132,6 @@ macro_rules! error { ($($x:tt)*) => () } #[cfg(target_arch = "wasm32")] extern crate std; -#[cfg(any( - target_os = "android", - target_os = "netbsd", - target_os = "solaris", - target_os = "illumos", - target_os = "redox", - target_os = "dragonfly", - target_os = "haiku", - target_os = "linux", - all( - target_arch = "wasm32", - not(target_env = "wasi") - ), -))] -mod utils; mod error; pub use crate::error::Error; @@ -180,7 +165,6 @@ mod_use!(cfg(target_os = "emscripten"), use_file); mod_use!(cfg(target_os = "freebsd"), freebsd); mod_use!(cfg(target_os = "fuchsia"), fuchsia); mod_use!(cfg(target_os = "haiku"), use_file); -mod_use!(cfg(target_os = "illumos"), solaris_illumos); mod_use!(cfg(target_os = "ios"), macos); mod_use!(cfg(target_os = "linux"), linux_android); mod_use!(cfg(target_os = "macos"), macos); @@ -188,6 +172,7 @@ mod_use!(cfg(target_os = "netbsd"), use_file); mod_use!(cfg(target_os = "openbsd"), openbsd_bitrig); mod_use!(cfg(target_os = "redox"), use_file); mod_use!(cfg(target_os = "solaris"), solaris_illumos); +mod_use!(cfg(target_os = "illumos"), solaris_illumos); mod_use!(cfg(windows), windows); mod_use!(cfg(target_env = "sgx"), sgx); mod_use!(cfg(target_env = "wasi"), wasi); diff --git a/src/linux_android.rs b/src/linux_android.rs index 2d260755..728046bc 100644 --- a/src/linux_android.rs +++ b/src/linux_android.rs @@ -10,75 +10,102 @@ extern crate std; use crate::Error; -use crate::utils::use_init; -use std::{thread_local, io::{self, Read}, fs::File}; -use core::cell::RefCell; -use core::num::NonZeroU32; -use core::sync::atomic::{AtomicBool, Ordering}; +use std::fs::File; +use std::io::Read; +use std::num::NonZeroU32; +use std::sync::atomic::{AtomicIsize, AtomicUsize, Ordering}; +use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::{io, mem, thread, time}; -static RNG_INIT: AtomicBool = AtomicBool::new(false); +// replace with AtomicU8 on stabilization and MSRV bump +static RNG_STATE: AtomicUsize = AtomicUsize::new(0); +// replace with AtomicI32 on stabilization and MSRV bump +static RNG_FD: AtomicIsize = AtomicIsize::new(-1); -enum RngSource { - GetRandom, - Device(File), +const STATE_INIT_ONGOING: usize = 1 << 0; +const STATE_USE_SYSCALL: usize = 1 << 1; +const STATE_USE_FD: usize = 1 << 2; + +pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { + let state = RNG_STATE.load(Ordering::Acquire); + if state & STATE_USE_SYSCALL != 0 { + use_syscall(dest) + } else if state & STATE_USE_FD != 0 { + use_fd(dest) + } else { + init_loop(dest) + } } -thread_local!( - static RNG_SOURCE: RefCell> = RefCell::new(None); -); +fn init_loop(dest: &mut [u8]) -> Result<(), Error> { + loop { + let state = RNG_STATE.fetch_or(STATE_INIT_ONGOING, Ordering::AcqRel); -fn syscall_getrandom(dest: &mut [u8]) -> Result<(), io::Error> { - let ret = unsafe { - libc::syscall(libc::SYS_getrandom, dest.as_mut_ptr(), dest.len(), 0) - }; - if ret < 0 || (ret as usize) != dest.len() { - error!("Linux getrandom syscall failed with return value {}", ret); - return Err(io::Error::last_os_error()); + if state & STATE_INIT_ONGOING != 0 { + // initialization is not finished, so wait + thread::sleep(time::Duration::from_nanos(1)); + continue; + } + return if state & STATE_USE_SYSCALL != 0 { + use_syscall(dest) + } else if state & STATE_USE_FD != 0 { + use_fd(dest) + } else { + init(dest) + }; } - Ok(()) } -pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - RNG_SOURCE.with(|f| { - use_init(f, - || { - let s = if is_getrandom_available() { - RngSource::GetRandom - } else { - // read one byte from "/dev/random" to ensure that - // OS RNG has initialized - if !RNG_INIT.load(Ordering::Relaxed) { - File::open("/dev/random")?.read_exact(&mut [0u8; 1])?; - RNG_INIT.store(true, Ordering::Relaxed) +fn init(dest: &mut [u8]) -> Result<(), Error> { + match use_syscall(&mut []) { + Ok(()) => { + RNG_STATE.store(STATE_USE_SYSCALL, Ordering::Release); + use_syscall(dest) + }, + Err(err) if err.code().get() as i32 == libc::ENOSYS => { + match init_fd() { + Ok(fd) => { + RNG_FD.store(fd as isize, Ordering::SeqCst); + RNG_STATE.store(STATE_USE_FD, Ordering::SeqCst); + use_fd(dest) + }, + Err(err) => { + RNG_STATE.store(0, Ordering::Release); + Err(err.into()) } - RngSource::Device(File::open("/dev/urandom")?) - }; - Ok(s) - }, |f| { - match f { - RngSource::GetRandom => syscall_getrandom(dest), - RngSource::Device(f) => f.read_exact(dest), - }.map_err(From::from) - }) - }) + } + }, + Err(err) => Err(err), + } } -fn is_getrandom_available() -> bool { - use std::sync::{Once, ONCE_INIT}; - - static CHECKER: Once = ONCE_INIT; - static AVAILABLE: AtomicBool = AtomicBool::new(false); +fn init_fd() -> io::Result { + // read one byte from "/dev/random" to ensure that OS RNG has initialized + File::open("/dev/random")?.read_exact(&mut [0u8; 1])?; + let f = File::open("/dev/urandom")?; + let fd = f.as_raw_fd(); + mem::forget(f); + Ok(fd) +} - CHECKER.call_once(|| { - let mut buf: [u8; 0] = []; - let available = match syscall_getrandom(&mut buf) { - Ok(()) => true, - Err(err) => err.raw_os_error() != Some(libc::ENOSYS), - }; - AVAILABLE.store(available, Ordering::Relaxed); - }); +fn use_syscall(dest: &mut [u8]) -> Result<(), Error> { + let ret = unsafe { + libc::syscall(libc::SYS_getrandom, dest.as_mut_ptr(), dest.len(), 0) + }; + if ret < 0 || (ret as usize) != dest.len() { + return Err(io::Error::last_os_error().into()); + } + Ok(()) +} - AVAILABLE.load(Ordering::Relaxed) +fn use_fd(dest: &mut [u8]) -> Result<(), Error> { + unsafe { + let fd = RNG_FD.load(Ordering::Acquire) as i32; + let mut f = File::from_raw_fd(fd); + f.read_exact(dest)?; + mem::forget(f); + } + Ok(()) } #[inline(always)] diff --git a/src/solaris_illumos.rs b/src/solaris_illumos.rs index 5484dd0f..746e90aa 100644 --- a/src/solaris_illumos.rs +++ b/src/solaris_illumos.rs @@ -17,85 +17,109 @@ //! To make sure we can compile on both Solaris and its derivatives, as well as //! function, we check for the existance of getrandom(2) in libc by calling //! libc::dlsym. +extern crate libc; extern crate std; use crate::Error; -use crate::utils::use_init; -use std::{thread_local, io::{self, Read}, fs::File}; -use core::cell::RefCell; -use core::num::NonZeroU32; +use std::fs::File; +use std::io::Read; +use std::num::NonZeroU32; +use std::sync::atomic::{AtomicIsize, AtomicUsize, Ordering}; +use std::os::unix::io::{RawFd, AsRawFd, FromRawFd}; +use std::{io, mem, thread, time}; #[cfg(target_os = "illumos")] type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t; #[cfg(target_os = "solaris")] type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::c_int; -enum RngSource { - GetRandom(GetRandomFn), - Device(File), -} +static RNG_FN: AtomicUsize = AtomicUsize::new(0); +// replace with AtomicI32 on stabilization and MSRV bump +static RNG_FD: AtomicIsize = AtomicIsize::new(-1); +// replace with AtomicU8 on stabilization and MSRV bump +static RNG_STATE: AtomicUsize = AtomicUsize::new(0); -thread_local!( - static RNG_SOURCE: RefCell> = RefCell::new(None); -); +const STATE_INIT_ONGOING: usize = 1 << 0; +const STATE_INIT_DONE: usize = 1 << 1; -fn libc_getrandom(rand: GetRandomFn, dest: &mut [u8]) -> Result<(), Error> { - let ret = unsafe { rand(dest.as_mut_ptr(), dest.len(), 0) as libc::ssize_t }; +pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { + let f = RNG_FN.load(Ordering::Acquire); + if f != 0 { + let f: GetRandomFn = unsafe { mem::transmute(f) }; + return use_fn(f, dest); + } + let fd = RNG_FD.load(Ordering::Acquire) as i32; + if fd != -1 { + return use_fd(fd, dest); + } - if ret == -1 || ret != dest.len() as libc::ssize_t { - error!("getrandom syscall failed with ret={}", ret); - Err(io::Error::last_os_error().into()) - } else { - Ok(()) + loop { + let state = RNG_STATE.fetch_or(STATE_INIT_ONGOING, Ordering::AcqRel); + if state & STATE_INIT_DONE != 0 { break; } + if state & STATE_INIT_ONGOING != 0 { + // initialization is not finished, so wait + thread::sleep(time::Duration::from_nanos(1)); + continue; + } + + let f = fetch_getrandom(); + if f == 0 { + let f = match File::open("/dev/random") { + Ok(f) => f, + Err(err) => { + RNG_STATE.store(0, Ordering::Release); + return Err(err.into()); + }, + }; + RNG_FD.store(f.as_raw_fd() as isize, Ordering::SeqCst); + mem::forget(f); + } else { + RNG_FN.store(f, Ordering::SeqCst); + } + RNG_STATE.store(STATE_INIT_DONE, Ordering::SeqCst); + break; } -} -pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - // 256 bytes is the lowest common denominator across all the Solaris - // derived platforms for atomically obtaining random data. - RNG_SOURCE.with(|f| { - use_init( - f, - || { - let s = match fetch_getrandom() { - Some(fptr) => RngSource::GetRandom(fptr), - None => RngSource::Device(File::open("/dev/random")?), - }; - Ok(s) - }, - |f| { - match f { - RngSource::GetRandom(rp) => { - for chunk in dest.chunks_mut(256) { - libc_getrandom(*rp, chunk)? - } - } - RngSource::Device(randf) => { - for chunk in dest.chunks_mut(256) { - randf.read_exact(chunk)? - } - } - }; - Ok(()) - }, - ) - }) + let f = RNG_FN.load(Ordering::Acquire); + if f != 0 { + let f: GetRandomFn = unsafe { mem::transmute(f) }; + return use_fn(f, dest); + } + let fd = RNG_FD.load(Ordering::Acquire) as i32; + use_fd(fd, dest) } -fn fetch_getrandom() -> Option { - use std::mem; - use std::sync::atomic::{AtomicUsize, Ordering}; - static FPTR: AtomicUsize = AtomicUsize::new(1); +fn use_fn(f: GetRandomFn, dest: &mut [u8]) -> Result<(), Error> { + for chunk in dest.chunks_mut(256) { + let ret = unsafe { + f(chunk.as_mut_ptr(), chunk.len(), 0) as libc::ssize_t + }; + + if ret == -1 || ret != chunk.len() as libc::ssize_t { + let err: Error = io::Error::last_os_error().into(); + error!("getrandom syscall failed: {}", err); + return Err(err); + } + } + Ok(()) +} - if FPTR.load(Ordering::SeqCst) == 1 { - let name = "getrandom\0"; - let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize }; - FPTR.store(addr, Ordering::SeqCst); +fn use_fd(fd: RawFd, dest: &mut [u8]) -> Result<(), Error> { + let mut f = unsafe { File::from_raw_fd(fd) }; + for chunk in dest.chunks_mut(256) { + f.read_exact(chunk)? } + mem::forget(f); + Ok(()) +} - let ptr = FPTR.load(Ordering::SeqCst); - unsafe { mem::transmute::>(ptr) } +/// returns 0 if fetch has failed and function pointer otherwise +fn fetch_getrandom() -> usize { + let name = "getrandom\0"; + unsafe { + libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize + } } #[inline(always)] diff --git a/src/use_file.rs b/src/use_file.rs index 404c13b2..6d9fe32a 100644 --- a/src/use_file.rs +++ b/src/use_file.rs @@ -6,31 +6,74 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Implementation for DragonFly / Haiku +//! Implementation for Redox, DragonFly, Haiku, NetBsd, Emscripten extern crate std; use crate::Error; -use crate::utils::use_init; -use std::{thread_local, io::Read, fs::File}; -use core::cell::RefCell; -use core::num::NonZeroU32; - -thread_local!(static RNG_FILE: RefCell> = RefCell::new(None)); +use std::fs::File; +use std::io::Read; +use std::num::NonZeroU32; +use std::sync::atomic::{AtomicIsize, AtomicUsize, Ordering}; +use std::os::unix::io::{RawFd, AsRawFd, FromRawFd}; +use std::{io, thread, mem, time}; #[cfg(target_os = "redox")] -const FILE_PATH: &str = "rand:"; +const FILE_PATH: &'static str = "rand:"; #[cfg(target_os = "netbsd")] -const FILE_PATH: &str = "/dev/urandom"; +const FILE_PATH: &'static str = "/dev/urandom"; #[cfg(any(target_os = "dragonfly", target_os = "emscripten", target_os = "haiku"))] -const FILE_PATH: &str = "/dev/random"; +const FILE_PATH: &'static str = "/dev/random"; + +// replace with AtomicI32 on stabilization and MSRV bump +static RNG_FD: AtomicIsize = AtomicIsize::new(-1); +// replace with AtomicU8 on stabilization and MSRV bump +static RNG_STATE: AtomicUsize = AtomicUsize::new(0); + +const STATE_INIT_ONGOING: usize = 1 << 0; +const STATE_INIT_DONE: usize = 1 << 1; pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - RNG_FILE.with(|f| { - use_init(f, || init_file(), |f| use_file(f, dest)) - }) + let fd = RNG_FD.load(Ordering::Acquire); + // Redox uses usize for descriptors, but `-1i32 as usize` is + // still an invalid descriptor value, see: + // https://github.com/redox-os/syscall/blob/master/src/error.rs#L22 + let fd = if fd != -1 { fd as RawFd } else { init_loop()? }; + let res = use_fd(fd, dest); + if let Err(err) = res { + error!("failed to read random data: {}", err); + return Err(err.into()); + } + Ok(()) +} + +fn init_loop() -> Result { + loop { + let state = RNG_STATE.fetch_or(STATE_INIT_ONGOING, Ordering::AcqRel); + if state & STATE_INIT_DONE != 0 { + // initialization is complete, use fd from atomic + return Ok(RNG_FD.load(Ordering::Acquire) as RawFd); + } else if state & STATE_INIT_ONGOING == 0 { + // start initialization and return resulting fd + match init_fd() { + Ok(fd) => { + RNG_FD.store(fd as isize, Ordering::SeqCst); + RNG_STATE.store(STATE_INIT_DONE, Ordering::SeqCst); + return Ok(fd) + }, + Err(err) => { + RNG_STATE.store(0, Ordering::Release); + error!("initialization has failed: {}", err); + return Err(err.into()); + } + } + } + // initialization is not finished, so wait + thread::sleep(time::Duration::from_nanos(1)); + } } -fn use_file(f: &mut File, dest: &mut [u8]) -> Result<(), Error> { +fn use_fd(fd: RawFd, dest: &mut [u8]) -> io::Result<()> { + let mut f = unsafe { File::from_raw_fd(fd) }; if cfg!(target_os = "emscripten") { // `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes. for chunk in dest.chunks_mut(65536) { @@ -39,17 +82,19 @@ fn use_file(f: &mut File, dest: &mut [u8]) -> Result<(), Error> { } else { f.read_exact(dest)?; } - core::mem::forget(f); + mem::forget(f); Ok(()) } -fn init_file() -> Result { +fn init_fd() -> io::Result { if cfg!(target_os = "netbsd") { // read one byte from "/dev/random" to ensure that OS RNG has initialized File::open("/dev/random")?.read_exact(&mut [0u8; 1])?; } let f = File::open(FILE_PATH)?; - Ok(f) + let fd = f.as_raw_fd(); + mem::forget(f); + Ok(fd) } #[inline(always)] diff --git a/src/wasm32_bindgen.rs b/src/wasm32_bindgen.rs index 7c835383..cac80423 100644 --- a/src/wasm32_bindgen.rs +++ b/src/wasm32_bindgen.rs @@ -7,18 +7,15 @@ // except according to those terms. //! Implementation for WASM via wasm-bindgen -extern crate std; - -use core::cell::RefCell; -use core::mem; -use core::num::NonZeroU32; +use std::cell::RefCell; use std::thread_local; +use std::num::NonZeroU32; +use core::ops::DerefMut; use wasm_bindgen::prelude::*; use crate::Error; use crate::error::CODE_PREFIX; -use crate::utils::use_init; const CODE_CRYPTO_UNDEF: u32 = CODE_PREFIX | 0x80; const CODE_GRV_UNDEF: u32 = CODE_PREFIX | 0x81; @@ -34,11 +31,15 @@ thread_local!( ); pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - assert_eq!(mem::size_of::(), 4); - RNG_SOURCE.with(|f| { - use_init(f, getrandom_init, |source| { - match *source { + let mut f = f.borrow_mut(); + let f: &mut Option = f.deref_mut(); + match f { + None => *f = Some(getrandom_init()?), + _ => (), + } + if let Some(source) = f { + match source { RngSource::Node(ref n) => n.random_fill_sync(dest), RngSource::Browser(ref n) => { // see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues @@ -52,10 +53,9 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { } } } - Ok(()) - }) + } + Ok(()) }) - } fn getrandom_init() -> Result { diff --git a/src/wasm32_stdweb.rs b/src/wasm32_stdweb.rs index 02f89aa0..03ecdde7 100644 --- a/src/wasm32_stdweb.rs +++ b/src/wasm32_stdweb.rs @@ -7,38 +7,41 @@ // except according to those terms. //! Implementation for WASM via stdweb -use core::cell::RefCell; -use core::mem; -use core::num::NonZeroU32; -use std::thread_local; +use std::num::NonZeroU32; +use std::sync::atomic::{AtomicUsize, Ordering}; use stdweb::{js, _js_impl}; use stdweb::unstable::TryInto; use stdweb::web::error::Error as WebError; use crate::Error; -use crate::utils::use_init; -#[derive(Clone, Debug)] -enum RngSource { - Browser, - Node -} +// replace with AtomicU8 on stabilization and MSRV bump +static RNG_STATE: AtomicUsize = AtomicUsize::new(0); -thread_local!( - static RNG_SOURCE: RefCell> = RefCell::new(None); -); +const STATE_INIT_DONE: usize = 1 << 0; +const STATE_USE_BROWSER: usize = 1 << 1; pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - assert_eq!(mem::size_of::(), 4); - - RNG_SOURCE.with(|f| { - use_init(f, getrandom_init, |source| getrandom_fill(source, dest)) - }) - + let state = RNG_STATE.load(Ordering::Acquire); + let use_browser = if state & STATE_INIT_DONE != 0 { + state & STATE_USE_BROWSER != 0 + } else { + let use_browser = getrandom_init()?; + RNG_STATE.store( + if use_browser { + STATE_INIT_DONE | STATE_USE_BROWSER + } else { + STATE_INIT_DONE + }, + Ordering::Release, + ); + use_browser + }; + getrandom_fill(use_browser, dest) } -fn getrandom_init() -> Result { +fn getrandom_init() -> Result { let result = js! { try { if ( @@ -62,8 +65,8 @@ fn getrandom_init() -> Result { if js!{ return @{ result.as_ref() }.success } == true { let ty = js!{ return @{ result }.ty }; - if ty == 1 { Ok(RngSource::Browser) } - else if ty == 2 { Ok(RngSource::Node) } + if ty == 1 { Ok(true) } + else if ty == 2 { Ok(false) } else { unreachable!() } } else { let err: WebError = js!{ return @{ result }.error }.try_into().unwrap(); @@ -72,13 +75,13 @@ fn getrandom_init() -> Result { } } -fn getrandom_fill(source: &mut RngSource, dest: &mut [u8]) -> Result<(), Error> { +fn getrandom_fill(use_browser: bool, dest: &mut [u8]) -> Result<(), Error> { for chunk in dest.chunks_mut(65536) { let len = chunk.len() as u32; let ptr = chunk.as_mut_ptr() as i32; - let result = match source { - RngSource::Browser => js! { + let result = match use_browser { + true => js! { try { let array = new Uint8Array(@{ len }); self.crypto.getRandomValues(array); @@ -89,7 +92,7 @@ fn getrandom_fill(source: &mut RngSource, dest: &mut [u8]) -> Result<(), Error> return { success: false, error: err }; } }, - RngSource::Node => js! { + false => js! { try { let bytes = require("crypto").randomBytes(@{ len }); HEAPU8.set(new Uint8Array(bytes), @{ ptr }); From 2f87b9cfb04ef84e3dff1347c2966e2daad0d59e Mon Sep 17 00:00:00 2001 From: newpavlov Date: Thu, 30 May 2019 14:41:59 +0300 Subject: [PATCH 2/4] replace sleep with yield_now --- src/linux_android.rs | 3 +-- src/solaris_illumos.rs | 3 +-- src/use_file.rs | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/linux_android.rs b/src/linux_android.rs index 728046bc..6d87a587 100644 --- a/src/linux_android.rs +++ b/src/linux_android.rs @@ -42,8 +42,7 @@ fn init_loop(dest: &mut [u8]) -> Result<(), Error> { let state = RNG_STATE.fetch_or(STATE_INIT_ONGOING, Ordering::AcqRel); if state & STATE_INIT_ONGOING != 0 { - // initialization is not finished, so wait - thread::sleep(time::Duration::from_nanos(1)); + thread::yield_now(); continue; } return if state & STATE_USE_SYSCALL != 0 { diff --git a/src/solaris_illumos.rs b/src/solaris_illumos.rs index 746e90aa..daca1918 100644 --- a/src/solaris_illumos.rs +++ b/src/solaris_illumos.rs @@ -57,8 +57,7 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { let state = RNG_STATE.fetch_or(STATE_INIT_ONGOING, Ordering::AcqRel); if state & STATE_INIT_DONE != 0 { break; } if state & STATE_INIT_ONGOING != 0 { - // initialization is not finished, so wait - thread::sleep(time::Duration::from_nanos(1)); + thread::yield_now() continue; } diff --git a/src/use_file.rs b/src/use_file.rs index 6d9fe32a..271fce10 100644 --- a/src/use_file.rs +++ b/src/use_file.rs @@ -68,7 +68,7 @@ fn init_loop() -> Result { } } // initialization is not finished, so wait - thread::sleep(time::Duration::from_nanos(1)); + thread::yield_now(); } } From 1cb77a63ce8a52eadc44382fe3339d37b570e56a Mon Sep 17 00:00:00 2001 From: newpavlov Date: Thu, 30 May 2019 14:48:58 +0300 Subject: [PATCH 3/4] small reordering --- src/lib.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e800db45..81ef0412 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,10 +45,10 @@ //! features are activated for this crate. Note that if both features are //! enabled `wasm-bindgen` will be used. If neither feature is enabled, //! `getrandom` will always fail. -//! +//! //! The WASI target `wasm32-wasi` uses the `__wasi_random_get` function defined //! by the WASI standard. -//! +//! //! //! ## Early boot //! @@ -165,6 +165,7 @@ mod_use!(cfg(target_os = "emscripten"), use_file); mod_use!(cfg(target_os = "freebsd"), freebsd); mod_use!(cfg(target_os = "fuchsia"), fuchsia); mod_use!(cfg(target_os = "haiku"), use_file); +mod_use!(cfg(target_os = "illumos"), solaris_illumos); mod_use!(cfg(target_os = "ios"), macos); mod_use!(cfg(target_os = "linux"), linux_android); mod_use!(cfg(target_os = "macos"), macos); @@ -172,10 +173,9 @@ mod_use!(cfg(target_os = "netbsd"), use_file); mod_use!(cfg(target_os = "openbsd"), openbsd_bitrig); mod_use!(cfg(target_os = "redox"), use_file); mod_use!(cfg(target_os = "solaris"), solaris_illumos); -mod_use!(cfg(target_os = "illumos"), solaris_illumos); -mod_use!(cfg(windows), windows); -mod_use!(cfg(target_env = "sgx"), sgx); mod_use!(cfg(target_os = "wasi"), wasi); +mod_use!(cfg(target_env = "sgx"), sgx); +mod_use!(cfg(windows), windows); mod_use!( cfg(all( @@ -216,16 +216,12 @@ mod_use!( target_os = "openbsd", target_os = "redox", target_os = "solaris", + target_os = "wasi", target_env = "sgx", windows, all( target_arch = "wasm32", - any( - target_os = "emscripten", - target_os = "wasi", - feature = "wasm-bindgen", - feature = "stdweb", - ), + any(feature = "wasm-bindgen", feature = "stdweb"), ), ))), dummy From 9852c8ba29bb840c88df025eb2297c95c8279761 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Tue, 4 Jun 2019 16:31:03 +0300 Subject: [PATCH 4/4] remove unused imports, fix semicolon --- src/linux_android.rs | 4 ++-- src/solaris_illumos.rs | 4 ++-- src/use_file.rs | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/linux_android.rs b/src/linux_android.rs index 6d87a587..84542423 100644 --- a/src/linux_android.rs +++ b/src/linux_android.rs @@ -15,7 +15,7 @@ use std::io::Read; use std::num::NonZeroU32; use std::sync::atomic::{AtomicIsize, AtomicUsize, Ordering}; use std::os::unix::io::{AsRawFd, FromRawFd}; -use std::{io, mem, thread, time}; +use std::{io, mem}; // replace with AtomicU8 on stabilization and MSRV bump static RNG_STATE: AtomicUsize = AtomicUsize::new(0); @@ -42,7 +42,7 @@ fn init_loop(dest: &mut [u8]) -> Result<(), Error> { let state = RNG_STATE.fetch_or(STATE_INIT_ONGOING, Ordering::AcqRel); if state & STATE_INIT_ONGOING != 0 { - thread::yield_now(); + std::thread::yield_now(); continue; } return if state & STATE_USE_SYSCALL != 0 { diff --git a/src/solaris_illumos.rs b/src/solaris_illumos.rs index daca1918..90b4909d 100644 --- a/src/solaris_illumos.rs +++ b/src/solaris_illumos.rs @@ -26,7 +26,7 @@ use std::io::Read; use std::num::NonZeroU32; use std::sync::atomic::{AtomicIsize, AtomicUsize, Ordering}; use std::os::unix::io::{RawFd, AsRawFd, FromRawFd}; -use std::{io, mem, thread, time}; +use std::{io, mem}; #[cfg(target_os = "illumos")] type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t; @@ -57,7 +57,7 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { let state = RNG_STATE.fetch_or(STATE_INIT_ONGOING, Ordering::AcqRel); if state & STATE_INIT_DONE != 0 { break; } if state & STATE_INIT_ONGOING != 0 { - thread::yield_now() + std::thread::yield_now(); continue; } diff --git a/src/use_file.rs b/src/use_file.rs index 271fce10..a726983d 100644 --- a/src/use_file.rs +++ b/src/use_file.rs @@ -15,7 +15,7 @@ use std::io::Read; use std::num::NonZeroU32; use std::sync::atomic::{AtomicIsize, AtomicUsize, Ordering}; use std::os::unix::io::{RawFd, AsRawFd, FromRawFd}; -use std::{io, thread, mem, time}; +use std::{io, mem}; #[cfg(target_os = "redox")] const FILE_PATH: &'static str = "rand:"; @@ -67,8 +67,7 @@ fn init_loop() -> Result { } } } - // initialization is not finished, so wait - thread::yield_now(); + std::thread::yield_now(); } }