|
7 | 7 | #![feature(rustc_private)]
|
8 | 8 | extern crate libc;
|
9 | 9 |
|
| 10 | +use std::mem::MaybeUninit; |
10 | 11 | use std::ptr;
|
11 | 12 | use std::thread;
|
12 | 13 | use std::time::{Duration, Instant};
|
@@ -93,6 +94,42 @@ fn wait_timeout() {
|
93 | 94 | assert!((200..1000).contains(&start.elapsed().as_millis()));
|
94 | 95 | }
|
95 | 96 |
|
| 97 | +fn wait_absolute_timeout() { |
| 98 | + let start = Instant::now(); |
| 99 | + |
| 100 | + // Get the current monotonic timestamp as timespec. |
| 101 | + let mut timeout = unsafe { |
| 102 | + let mut now: MaybeUninit<libc::timespec> = MaybeUninit::uninit(); |
| 103 | + assert_eq!(libc::clock_gettime(libc::CLOCK_MONOTONIC, now.as_mut_ptr()), 0); |
| 104 | + now.assume_init() |
| 105 | + }; |
| 106 | + |
| 107 | + // Add 200ms. |
| 108 | + timeout.tv_nsec += 200_000_000; |
| 109 | + if timeout.tv_nsec > 1_000_000_000 { |
| 110 | + timeout.tv_nsec -= 1_000_000_000; |
| 111 | + timeout.tv_sec += 1; |
| 112 | + } |
| 113 | + |
| 114 | + let futex: i32 = 123; |
| 115 | + |
| 116 | + // Wait for 200ms from now, with nobody waking us up early. |
| 117 | + unsafe { |
| 118 | + assert_eq!(libc::syscall( |
| 119 | + libc::SYS_futex, |
| 120 | + &futex as *const i32, |
| 121 | + libc::FUTEX_WAIT_BITSET, |
| 122 | + 123, |
| 123 | + &timeout, |
| 124 | + 0, |
| 125 | + u32::MAX, |
| 126 | + ), -1); |
| 127 | + assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT); |
| 128 | + } |
| 129 | + |
| 130 | + assert!((200..1000).contains(&start.elapsed().as_millis())); |
| 131 | +} |
| 132 | + |
96 | 133 | fn wait_wake() {
|
97 | 134 | let start = Instant::now();
|
98 | 135 |
|
@@ -128,5 +165,6 @@ fn main() {
|
128 | 165 | wake_dangling();
|
129 | 166 | wait_wrong_val();
|
130 | 167 | wait_timeout();
|
| 168 | + wait_absolute_timeout(); |
131 | 169 | wait_wake();
|
132 | 170 | }
|
0 commit comments