From af3b8bc5ee9d23ee349cc861589dd0c281dc52fe Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Thu, 11 Jul 2019 12:02:01 -0700 Subject: [PATCH 1/2] Incorperate feedback on Lazy helpers --- src/util.rs | 1 + src/util_libc.rs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/util.rs b/src/util.rs index a0675be21..3145eb4c1 100644 --- a/src/util.rs +++ b/src/util.rs @@ -65,6 +65,7 @@ impl LazyUsize { match self.0.compare_and_swap(Self::UNINIT, Self::ACTIVE, Relaxed) { Self::UNINIT => { let val = init(); + assert!(val != Self::ACTIVE); self.0.store(val, Relaxed); return val; } 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 { From 318cde8ce66e894a2aba1338dba5a7ba6ce54266 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Thu, 11 Jul 2019 13:11:58 -0700 Subject: [PATCH 2/2] Don't panic on init() returning ACTIVE --- src/util.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/util.rs b/src/util.rs index 3145eb4c1..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,8 +66,13 @@ impl LazyUsize { match self.0.compare_and_swap(Self::UNINIT, Self::ACTIVE, Relaxed) { Self::UNINIT => { let val = init(); - assert!(val != Self::ACTIVE); - self.0.store(val, Relaxed); + self.0.store( + match val { + Self::UNINIT | Self::ACTIVE => Self::UNINIT, + val => val, + }, + Relaxed, + ); return val; } Self::ACTIVE => wait(),