diff --git a/src/util.rs b/src/util.rs index a0675be21..63a9eab38 100644 --- a/src/util.rs +++ b/src/util.rs @@ -53,7 +53,8 @@ impl LazyUsize { // Synchronously runs the init() function. Only one caller will have their // init() function running at a time, and exactly one successful call will - // be run. The init() function should never return LazyUsize::ACTIVE. + // be run. init() returning UNINIT or ACTIVE will be considered a failure, + // and future calls to sync_init will rerun their init() function. pub fn sync_init(&self, init: impl FnOnce() -> usize, mut wait: impl FnMut()) -> usize { // Common and fast path with no contention. Don't wast time on CAS. match self.0.load(Relaxed) { @@ -65,7 +66,13 @@ impl LazyUsize { match self.0.compare_and_swap(Self::UNINIT, Self::ACTIVE, Relaxed) { Self::UNINIT => { let val = init(); - self.0.store(val, Relaxed); + self.0.store( + match val { + Self::UNINIT | Self::ACTIVE => Self::UNINIT, + val => val, + }, + Relaxed, + ); return val; } Self::ACTIVE => wait(), diff --git a/src/util_libc.rs b/src/util_libc.rs index 8804fdc6e..606bc1ffd 100644 --- a/src/util_libc.rs +++ b/src/util_libc.rs @@ -80,7 +80,12 @@ impl LazyFd { None => LazyUsize::UNINIT, }, || unsafe { - libc::usleep(1000); + // We are usually waiting on an open(2) syscall to complete, + // which typically takes < 10us if the file is a device. + // However, we might end up waiting much longer if the entropy + // pool isn't initialized, but even in that case, this loop will + // consume a negligible amount of CPU on most platforms. + libc::usleep(10); }, ); match fd {