|
12 | 12 |
|
13 | 13 | #![stable(feature = "time", since = "1.3.0")]
|
14 | 14 |
|
| 15 | +use cmp; |
15 | 16 | use error::Error;
|
16 | 17 | use fmt;
|
17 | 18 | use ops::{Add, Sub, AddAssign, SubAssign};
|
18 | 19 | use sys::time;
|
19 | 20 | use sys_common::FromInner;
|
| 21 | +use sys_common::mutex::Mutex; |
20 | 22 |
|
21 | 23 | #[stable(feature = "time", since = "1.3.0")]
|
22 | 24 | pub use core::time::Duration;
|
@@ -153,7 +155,45 @@ impl Instant {
|
153 | 155 | /// ```
|
154 | 156 | #[stable(feature = "time2", since = "1.8.0")]
|
155 | 157 | pub fn now() -> Instant {
|
156 |
| - Instant(time::Instant::now()) |
| 158 | + let os_now = time::Instant::now(); |
| 159 | + |
| 160 | + // And here we come upon a sad state of affairs. The whole point of |
| 161 | + // `Instant` is that it's monotonically increasing. We've found in the |
| 162 | + // wild, however, that it's not actually monotonically increasing for |
| 163 | + // one reason or another. These appear to be OS and hardware level bugs, |
| 164 | + // and there's not really a whole lot we can do about them. Here's a |
| 165 | + // taste of what we've found: |
| 166 | + // |
| 167 | + // * #48514 - OpenBSD, x86_64 |
| 168 | + // * #49281 - linux arm64 and s390x |
| 169 | + // * #51648 - windows, x86 |
| 170 | + // * #56560 - windows, x86_64, AWS |
| 171 | + // * #56612 - windows, x86, vm (?) |
| 172 | + // * #56940 - linux, arm64 |
| 173 | + // * https://bugzilla.mozilla.org/show_bug.cgi?id=1487778 - a similar |
| 174 | + // Firefox bug |
| 175 | + // |
| 176 | + // It simply seems that this it just happens so that a lot in the wild |
| 177 | + // we're seeing panics across various platforms where consecutive calls |
| 178 | + // to `Instant::now`, such as via the `elapsed` function, are panicking |
| 179 | + // as they're going backwards. Placed here is a last-ditch effort to try |
| 180 | + // to fix things up. We keep a global "latest now" instance which is |
| 181 | + // returned instead of what the OS says if the OS goes backwards. |
| 182 | + // |
| 183 | + // To hopefully mitigate the impact of this though a few platforms are |
| 184 | + // whitelisted as "these at least haven't gone backwards yet". |
| 185 | + if time::Instant::actually_monotonic() { |
| 186 | + return Instant(os_now) |
| 187 | + } |
| 188 | + |
| 189 | + static LOCK: Mutex = Mutex::new(); |
| 190 | + static mut LAST_NOW: time::Instant = time::Instant::zero(); |
| 191 | + unsafe { |
| 192 | + let _lock = LOCK.lock(); |
| 193 | + let now = cmp::max(LAST_NOW, os_now); |
| 194 | + LAST_NOW = now; |
| 195 | + Instant(now) |
| 196 | + } |
157 | 197 | }
|
158 | 198 |
|
159 | 199 | /// Returns the amount of time elapsed from another instant to this one.
|
|
0 commit comments