Skip to content

Commit 70d551a

Browse files
committed
add env var to override sys::Instant::actually_monotonic() for windows and linux
the environment variable is read on first use and cached in an atomic
1 parent 25c15cd commit 70d551a

File tree

4 files changed

+53
-6
lines changed

4 files changed

+53
-6
lines changed

library/std/src/sys/common/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
#![allow(dead_code)]
1212

1313
pub mod alloc;
14+
pub mod time;

library/std/src/sys/common/time.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use crate::env;
2+
use crate::sync::atomic::{AtomicU8, Ordering};
3+
4+
#[repr(u8)]
5+
#[derive(Copy, Clone)]
6+
pub enum InstantReliability {
7+
// 0 is the placeholder for initialization pending
8+
Default = 1,
9+
AssumeMonotonic = 2,
10+
AssumeBroken = 3,
11+
}
12+
13+
static INSTANT_RELIABILITY: AtomicU8 = AtomicU8::new(0);
14+
15+
pub fn instant_reliability_override() -> InstantReliability {
16+
let current = INSTANT_RELIABILITY.load(Ordering::Relaxed);
17+
18+
if current == 0 {
19+
let new = match env::var("RUST_CLOCK_ASSUME_MONOTONIC").as_deref() {
20+
Ok("1") => InstantReliability::AssumeMonotonic,
21+
Ok("0") => InstantReliability::AssumeBroken,
22+
Ok(_) => {
23+
eprintln!("unsupported value in RUST_CLOCK_ASSUME_MONOTONIC; using default");
24+
InstantReliability::Default
25+
}
26+
_ => InstantReliability::Default,
27+
};
28+
INSTANT_RELIABILITY.store(new as u8, Ordering::Relaxed);
29+
new
30+
} else {
31+
// SAFETY: The enum has a compatible layout and after initialization only values
32+
// cast from enum variants are stored in the atomic static.
33+
unsafe { crate::mem::transmute(current) }
34+
}
35+
}

library/std/src/sys/unix/time.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,12 @@ mod inner {
273273

274274
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
275275
mod inner {
276+
use super::Timespec;
276277
use crate::fmt;
278+
use crate::sys::common::time::{instant_reliability_override, InstantReliability};
277279
use crate::sys::cvt;
278280
use crate::time::Duration;
279281

280-
use super::Timespec;
281-
282282
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
283283
pub struct Instant {
284284
t: Timespec,
@@ -301,9 +301,15 @@ mod inner {
301301
}
302302

303303
pub fn actually_monotonic() -> bool {
304-
(cfg!(target_os = "linux") && cfg!(target_arch = "x86_64"))
305-
|| (cfg!(target_os = "linux") && cfg!(target_arch = "x86"))
306-
|| cfg!(target_os = "fuchsia")
304+
match instant_reliability_override() {
305+
InstantReliability::Default => {
306+
(cfg!(target_os = "linux") && cfg!(target_arch = "x86_64"))
307+
|| (cfg!(target_os = "linux") && cfg!(target_arch = "x86"))
308+
|| cfg!(target_os = "fuchsia")
309+
}
310+
InstantReliability::AssumeMonotonic => true,
311+
InstantReliability::AssumeBroken => false,
312+
}
307313
}
308314

309315
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {

library/std/src/sys/windows/time.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::convert::TryInto;
33
use crate::fmt;
44
use crate::mem;
55
use crate::sys::c;
6+
use crate::sys::common::time::{instant_reliability_override, InstantReliability};
67
use crate::time::Duration;
78

89
use core::hash::{Hash, Hasher};
@@ -42,7 +43,11 @@ impl Instant {
4243
}
4344

4445
pub fn actually_monotonic() -> bool {
45-
false
46+
match instant_reliability_override() {
47+
InstantReliability::Default => false,
48+
InstantReliability::AssumeMonotonic => true,
49+
InstantReliability::AssumeBroken => false,
50+
}
4651
}
4752

4853
pub const fn zero() -> Instant {

0 commit comments

Comments
 (0)