31
31
32
32
#![ stable( feature = "time" , since = "1.3.0" ) ]
33
33
34
- mod monotonic;
35
34
#[ cfg( test) ]
36
35
mod tests;
37
36
@@ -125,6 +124,23 @@ pub use core::time::FromFloatSecsError;
125
124
/// > structure cannot represent the new point in time.
126
125
///
127
126
/// [`add`]: Instant::add
127
+ ///
128
+ /// ## Monotonicity
129
+ ///
130
+ /// On all platforms `Instant` will try to use an OS API that guarantees monotonic behavior
131
+ /// if available, which is the case for all [tier 1] platforms.
132
+ /// In practice such guarantees are – under rare circumstances – broken by hardware, virtualization
133
+ /// or operating system bugs. To work around these bugs and platforms not offering monotonic clocks
134
+ /// [`duration_since`], [`elapsed`] and [`sub`] saturate to zero. [`checked_duration_since`] can
135
+ /// be used to detect and handle situations where monotonicity is violated, or `Instant`s are
136
+ /// subtracted in the wrong order.
137
+ ///
138
+ /// [tier 1]: https://doc.rust-lang.org/rustc/platform-support.html
139
+ /// [`duration_since`]: Instant::duration_since
140
+ /// [`elapsed`]: Instant::elapsed
141
+ /// [`sub`]: Instant::sub
142
+ /// [`checked_duration_since`]: Instant::checked_duration_since
143
+ ///
128
144
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
129
145
#[ stable( feature = "time2" , since = "1.8.0" ) ]
130
146
pub struct Instant ( time:: Instant ) ;
@@ -247,59 +263,12 @@ impl Instant {
247
263
#[ must_use]
248
264
#[ stable( feature = "time2" , since = "1.8.0" ) ]
249
265
pub fn now ( ) -> Instant {
250
- let os_now = time:: Instant :: now ( ) ;
251
-
252
- // And here we come upon a sad state of affairs. The whole point of
253
- // `Instant` is that it's monotonically increasing. We've found in the
254
- // wild, however, that it's not actually monotonically increasing for
255
- // one reason or another. These appear to be OS and hardware level bugs,
256
- // and there's not really a whole lot we can do about them. Here's a
257
- // taste of what we've found:
258
- //
259
- // * #48514 - OpenBSD, x86_64
260
- // * #49281 - linux arm64 and s390x
261
- // * #51648 - windows, x86
262
- // * #56560 - windows, x86_64, AWS
263
- // * #56612 - windows, x86, vm (?)
264
- // * #56940 - linux, arm64
265
- // * https://bugzilla.mozilla.org/show_bug.cgi?id=1487778 - a similar
266
- // Firefox bug
267
- //
268
- // It seems that this just happens a lot in the wild.
269
- // We're seeing panics across various platforms where consecutive calls
270
- // to `Instant::now`, such as via the `elapsed` function, are panicking
271
- // as they're going backwards. Placed here is a last-ditch effort to try
272
- // to fix things up. We keep a global "latest now" instance which is
273
- // returned instead of what the OS says if the OS goes backwards.
274
- //
275
- // To hopefully mitigate the impact of this, a few platforms are
276
- // excluded as "these at least haven't gone backwards yet".
277
- //
278
- // While issues have been seen on arm64 platforms the Arm architecture
279
- // requires that the counter monotonically increases and that it must
280
- // provide a uniform view of system time (e.g. it must not be possible
281
- // for a core to receive a message from another core with a time stamp
282
- // and observe time going backwards (ARM DDI 0487G.b D11.1.2). While
283
- // there have been a few 64bit SoCs that have bugs which cause time to
284
- // not monoticially increase, these have been fixed in the Linux kernel
285
- // and we shouldn't penalize all Arm SoCs for those who refuse to
286
- // update their kernels:
287
- // SUN50I_ERRATUM_UNKNOWN1 - Allwinner A64 / Pine A64 - fixed in 5.1
288
- // FSL_ERRATUM_A008585 - Freescale LS2080A/LS1043A - fixed in 4.10
289
- // HISILICON_ERRATUM_161010101 - Hisilicon 1610 - fixed in 4.11
290
- // ARM64_ERRATUM_858921 - Cortex A73 - fixed in 4.12
291
- if time:: Instant :: actually_monotonic ( ) {
292
- return Instant ( os_now) ;
293
- }
294
-
295
- Instant ( monotonic:: monotonize ( os_now) )
266
+ Instant ( time:: Instant :: now ( ) )
296
267
}
297
268
298
- /// Returns the amount of time elapsed from another instant to this one.
299
- ///
300
- /// # Panics
269
+ /// Returns the amount of time elapsed from another instant to this one,
270
+ /// or zero duration if that instant is later than this one.
301
271
///
302
- /// This function will panic if `earlier` is later than `self`.
303
272
///
304
273
/// # Examples
305
274
///
@@ -311,16 +280,22 @@ impl Instant {
311
280
/// sleep(Duration::new(1, 0));
312
281
/// let new_now = Instant::now();
313
282
/// println!("{:?}", new_now.duration_since(now));
283
+ /// println!("{:?}", now.duration_since(new_now)); // 0ns
314
284
/// ```
315
285
#[ must_use]
316
286
#[ stable( feature = "time2" , since = "1.8.0" ) ]
317
287
pub fn duration_since ( & self , earlier : Instant ) -> Duration {
318
- self . 0 . checked_sub_instant ( & earlier. 0 ) . expect ( "supplied instant is later than self" )
288
+ self . checked_duration_since ( earlier) . unwrap_or_default ( )
319
289
}
320
290
321
291
/// Returns the amount of time elapsed from another instant to this one,
322
292
/// or None if that instant is later than this one.
323
293
///
294
+ /// Due to [monotonicity bugs], even under correct logical ordering of the passed `Instant`s,
295
+ /// this method can return `None`.
296
+ ///
297
+ /// [monotonicity bugs]: Instant#monotonicity
298
+ ///
324
299
/// # Examples
325
300
///
326
301
/// ```no_run
@@ -362,12 +337,6 @@ impl Instant {
362
337
363
338
/// Returns the amount of time elapsed since this instant was created.
364
339
///
365
- /// # Panics
366
- ///
367
- /// This function may panic if the current time is earlier than this
368
- /// instant, which is something that can happen if an `Instant` is
369
- /// produced synthetically.
370
- ///
371
340
/// # Examples
372
341
///
373
342
/// ```no_run
0 commit comments