Skip to content

Commit 9395f0a

Browse files
committed
Auto merge of #53725 - tbu-:pr_getrandom_syscalls, r=alexcrichton
Reduce number of syscalls in `rand` This skips the initial zero-length `getrandom` call and directly hands the user buffer to the operating system, saving one `getrandom` syscall.
2 parents 763d91a + b95c491 commit 9395f0a

File tree

1 file changed

+26
-40
lines changed

1 file changed

+26
-40
lines changed

src/libstd/sys/unix/rand.rs

+26-40
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ pub fn hashmap_random_keys() -> (u64, u64) {
2929
mod imp {
3030
use fs::File;
3131
use io::Read;
32+
#[cfg(any(target_os = "linux", target_os = "android"))]
3233
use libc;
33-
use sys::os::errno;
3434

3535
#[cfg(any(target_os = "linux", target_os = "android"))]
3636
fn getrandom(buf: &mut [u8]) -> libc::c_long {
@@ -40,71 +40,57 @@ mod imp {
4040
}
4141

4242
#[cfg(not(any(target_os = "linux", target_os = "android")))]
43-
fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
43+
fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool { false }
4444

45+
#[cfg(any(target_os = "linux", target_os = "android"))]
4546
fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
47+
use sync::atomic::{AtomicBool, Ordering};
48+
use sys::os::errno;
49+
50+
static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
51+
if GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed) {
52+
return false;
53+
}
54+
4655
let mut read = 0;
4756
while read < v.len() {
4857
let result = getrandom(&mut v[read..]);
4958
if result == -1 {
5059
let err = errno() as libc::c_int;
5160
if err == libc::EINTR {
5261
continue;
62+
} else if err == libc::ENOSYS {
63+
GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed);
64+
return false;
5365
} else if err == libc::EAGAIN {
54-
return false
66+
return false;
5567
} else {
5668
panic!("unexpected getrandom error: {}", err);
5769
}
5870
} else {
5971
read += result as usize;
6072
}
6173
}
62-
63-
return true
74+
true
6475
}
6576

66-
#[cfg(any(target_os = "linux", target_os = "android"))]
67-
fn is_getrandom_available() -> bool {
68-
use io;
69-
use sync::atomic::{AtomicBool, Ordering};
70-
use sync::Once;
71-
72-
static CHECKER: Once = Once::new();
73-
static AVAILABLE: AtomicBool = AtomicBool::new(false);
74-
75-
CHECKER.call_once(|| {
76-
let mut buf: [u8; 0] = [];
77-
let result = getrandom(&mut buf);
78-
let available = if result == -1 {
79-
let err = io::Error::last_os_error().raw_os_error();
80-
err != Some(libc::ENOSYS)
81-
} else {
82-
true
83-
};
84-
AVAILABLE.store(available, Ordering::Relaxed);
85-
});
86-
87-
AVAILABLE.load(Ordering::Relaxed)
88-
}
89-
90-
#[cfg(not(any(target_os = "linux", target_os = "android")))]
91-
fn is_getrandom_available() -> bool { false }
92-
9377
pub fn fill_bytes(v: &mut [u8]) {
9478
// getrandom_fill_bytes here can fail if getrandom() returns EAGAIN,
9579
// meaning it would have blocked because the non-blocking pool (urandom)
96-
// has not initialized in the kernel yet due to a lack of entropy the
80+
// has not initialized in the kernel yet due to a lack of entropy. The
9781
// fallback we do here is to avoid blocking applications which could
9882
// depend on this call without ever knowing they do and don't have a
99-
// work around. The PRNG of /dev/urandom will still be used but not
100-
// over a completely full entropy pool
101-
if is_getrandom_available() && getrandom_fill_bytes(v) {
102-
return
83+
// work around. The PRNG of /dev/urandom will still be used but over a
84+
// possibly predictable entropy pool.
85+
if getrandom_fill_bytes(v) {
86+
return;
10387
}
10488

105-
let mut file = File::open("/dev/urandom")
106-
.expect("failed to open /dev/urandom");
107-
file.read_exact(v).expect("failed to read /dev/urandom");
89+
// getrandom failed because it is permanently or temporarily (because
90+
// of missing entropy) unavailable. Open /dev/urandom, read from it,
91+
// and close it again.
92+
let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
93+
file.read_exact(v).expect("failed to read /dev/urandom")
10894
}
10995
}
11096

0 commit comments

Comments
 (0)