@@ -165,7 +165,7 @@ fn intervals2dur(intervals: u64) -> Duration {
165
165
166
166
mod perf_counter {
167
167
use super :: NANOS_PER_SEC ;
168
- use crate :: sync:: atomic:: { AtomicUsize , Ordering :: SeqCst } ;
168
+ use crate :: sync:: atomic:: { AtomicU64 , Ordering } ;
169
169
use crate :: sys:: c;
170
170
use crate :: sys:: cvt;
171
171
use crate :: sys_common:: mul_div_u64;
@@ -197,27 +197,25 @@ mod perf_counter {
197
197
}
198
198
199
199
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 ;
203
213
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 ;
211
214
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
220
215
}
216
+
217
+ FREQUENCY . store ( frequency as u64 , Ordering :: Relaxed ) ;
218
+ frequency
221
219
}
222
220
223
221
fn query ( ) -> c:: LARGE_INTEGER {
0 commit comments