@@ -165,7 +165,7 @@ fn intervals2dur(intervals: u64) -> Duration {
165165
166166mod perf_counter {
167167 use super :: NANOS_PER_SEC ;
168- use crate :: sync:: atomic:: { AtomicUsize , Ordering :: SeqCst } ;
168+ use crate :: sync:: atomic:: { AtomicU64 , Ordering } ;
169169 use crate :: sys:: c;
170170 use crate :: sys:: cvt;
171171 use crate :: sys_common:: mul_div_u64;
@@ -197,27 +197,25 @@ mod perf_counter {
197197 }
198198
199199 fn frequency ( ) -> c:: LARGE_INTEGER {
200- static mut FREQUENCY : c:: LARGE_INTEGER = 0 ;
201- static STATE : AtomicUsize = AtomicUsize :: new ( 0 ) ;
202-
200+ // Either the cached result of `QueryPerformanceFrequency` or `0` for
201+ // uninitialized. Storing this as a single `AtomicU64` allows us to use
202+ // `Relaxed` operations, as we are only interested in the effects on a
203+ // single memory location.
204+ static FREQUENCY : AtomicU64 = AtomicU64 :: new ( 0 ) ;
205+
206+ let cached = FREQUENCY . load ( Ordering :: Relaxed ) ;
207+ // If a previous thread has filled in this global state, use that.
208+ if cached != 0 {
209+ return cached as c:: LARGE_INTEGER ;
210+ }
211+ // ... otherwise learn for ourselves ...
212+ let mut frequency = 0 ;
203213 unsafe {
204- // If a previous thread has filled in this global state, use that.
205- if STATE . load ( SeqCst ) == 2 {
206- return FREQUENCY ;
207- }
208-
209- // ... otherwise learn for ourselves ...
210- let mut frequency = 0 ;
211214 cvt ( c:: QueryPerformanceFrequency ( & mut frequency) ) . unwrap ( ) ;
212-
213- // ... and attempt to be the one thread that stores it globally for
214- // all other threads
215- if STATE . compare_exchange ( 0 , 1 , SeqCst , SeqCst ) . is_ok ( ) {
216- FREQUENCY = frequency;
217- STATE . store ( 2 , SeqCst ) ;
218- }
219- frequency
220215 }
216+
217+ FREQUENCY . store ( frequency as u64 , Ordering :: Relaxed ) ;
218+ frequency
221219 }
222220
223221 fn query ( ) -> c:: LARGE_INTEGER {
0 commit comments