1 // Unfortunately, the test framework does not support 'only-linux',
2 // so we need to ignore Windows and macOS instead.
3 // ignore-macos: Uses Linux-only APIs
4 // ignore-windows: Uses Linux-only APIs
5 // compile-flags: -Zmiri-disable-isolation
7 #![feature(rustc_private)]
10 use std::mem::MaybeUninit;
13 use std::time::{Duration, Instant};
18 // Wake 1 waiter. Expect zero waiters woken up, as nobody is waiting.
20 assert_eq!(libc::syscall(
28 // Same, but without omitting the unused arguments.
30 assert_eq!(libc::syscall(
35 ptr::null::<libc::timespec>(),
43 let futex = Box::new(0);
44 let ptr: *const i32 = &*futex;
47 // Wake 1 waiter. Expect zero waiters woken up, as nobody is waiting.
49 assert_eq!(libc::syscall(
61 // Only wait if the futex value is 456.
63 assert_eq!(libc::syscall(
68 ptr::null::<libc::timespec>(),
70 assert_eq!(*libc::__errno_location(), libc::EAGAIN);
75 let start = Instant::now();
79 // Wait for 200ms, with nobody waking us up early.
81 assert_eq!(libc::syscall(
91 assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT);
94 assert!((200..1000).contains(&start.elapsed().as_millis()));
97 fn wait_absolute_timeout() {
98 let start = Instant::now();
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);
108 timeout.tv_nsec += 200_000_000;
109 if timeout.tv_nsec > 1_000_000_000 {
110 timeout.tv_nsec -= 1_000_000_000;
114 let futex: i32 = 123;
116 // Wait for 200ms from now, with nobody waking us up early.
118 assert_eq!(libc::syscall(
120 &futex as *const i32,
121 libc::FUTEX_WAIT_BITSET,
127 assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT);
130 assert!((200..1000).contains(&start.elapsed().as_millis()));
134 let start = Instant::now();
136 static FUTEX: i32 = 0;
138 thread::spawn(move || {
139 thread::sleep(Duration::from_millis(200));
141 assert_eq!(libc::syscall(
143 &FUTEX as *const i32,
145 10, // Wake up at most 10 threads.
146 ), 1); // Woken up one thread.
151 assert_eq!(libc::syscall(
153 &FUTEX as *const i32,
156 ptr::null::<libc::timespec>(),
160 assert!((200..1000).contains(&start.elapsed().as_millis()));
163 fn wait_wake_bitset() {
164 let start = Instant::now();
166 static FUTEX: i32 = 0;
168 thread::spawn(move || {
169 thread::sleep(Duration::from_millis(200));
171 assert_eq!(libc::syscall(
173 &FUTEX as *const i32,
174 libc::FUTEX_WAKE_BITSET,
175 10, // Wake up at most 10 threads.
176 ptr::null::<libc::timespec>(),
179 ), 0); // Didn't match any thread.
181 thread::sleep(Duration::from_millis(200));
183 assert_eq!(libc::syscall(
185 &FUTEX as *const i32,
186 libc::FUTEX_WAKE_BITSET,
187 10, // Wake up at most 10 threads.
188 ptr::null::<libc::timespec>(),
191 ), 1); // Woken up one thread.
196 assert_eq!(libc::syscall(
198 &FUTEX as *const i32,
199 libc::FUTEX_WAIT_BITSET,
201 ptr::null::<libc::timespec>(),
207 assert!((400..1000).contains(&start.elapsed().as_millis()));
215 wait_absolute_timeout();