-
Notifications
You must be signed in to change notification settings - Fork 347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for FUTEX_{WAIT,WAKE}_BITSET #2054
Changes from all commits
37cefa3
a72a929
12c8888
53ed500
5581e33
03417de
4fdda31
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
f262ca12aac76152c4b46cefcf8300f0249a5eb2 | ||
306ba8357fb36212b7d30efb9eb9e41659ac1445 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
#![feature(rustc_private)] | ||
extern crate libc; | ||
|
||
use std::mem::MaybeUninit; | ||
use std::ptr; | ||
use std::thread; | ||
use std::time::{Duration, Instant}; | ||
|
@@ -93,6 +94,42 @@ fn wait_timeout() { | |
assert!((200..1000).contains(&start.elapsed().as_millis())); | ||
} | ||
|
||
fn wait_absolute_timeout() { | ||
let start = Instant::now(); | ||
|
||
// Get the current monotonic timestamp as timespec. | ||
let mut timeout = unsafe { | ||
let mut now: MaybeUninit<libc::timespec> = MaybeUninit::uninit(); | ||
assert_eq!(libc::clock_gettime(libc::CLOCK_MONOTONIC, now.as_mut_ptr()), 0); | ||
now.assume_init() | ||
}; | ||
|
||
// Add 200ms. | ||
timeout.tv_nsec += 200_000_000; | ||
if timeout.tv_nsec > 1_000_000_000 { | ||
timeout.tv_nsec -= 1_000_000_000; | ||
timeout.tv_sec += 1; | ||
} | ||
|
||
let futex: i32 = 123; | ||
|
||
// Wait for 200ms from now, with nobody waking us up early. | ||
unsafe { | ||
assert_eq!(libc::syscall( | ||
libc::SYS_futex, | ||
&futex as *const i32, | ||
libc::FUTEX_WAIT_BITSET, | ||
123, | ||
&timeout, | ||
0, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This turns out to be a subtle bug, since (It'd probably still work on x86 due to details of the calling convention, but e.g. if arguments are passed on the stack then |
||
u32::MAX, | ||
), -1); | ||
assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT); | ||
} | ||
|
||
assert!((200..1000).contains(&start.elapsed().as_millis())); | ||
} | ||
|
||
fn wait_wake() { | ||
let start = Instant::now(); | ||
|
||
|
@@ -123,10 +160,59 @@ fn wait_wake() { | |
assert!((200..1000).contains(&start.elapsed().as_millis())); | ||
} | ||
|
||
fn wait_wake_bitset() { | ||
let start = Instant::now(); | ||
|
||
static FUTEX: i32 = 0; | ||
|
||
thread::spawn(move || { | ||
thread::sleep(Duration::from_millis(200)); | ||
unsafe { | ||
assert_eq!(libc::syscall( | ||
libc::SYS_futex, | ||
&FUTEX as *const i32, | ||
libc::FUTEX_WAKE_BITSET, | ||
10, // Wake up at most 10 threads. | ||
0, | ||
0, | ||
0b1001, // bitset | ||
), 0); // Didn't match any thread. | ||
} | ||
thread::sleep(Duration::from_millis(200)); | ||
unsafe { | ||
assert_eq!(libc::syscall( | ||
libc::SYS_futex, | ||
&FUTEX as *const i32, | ||
libc::FUTEX_WAKE_BITSET, | ||
10, // Wake up at most 10 threads. | ||
0, | ||
0, | ||
0b0110, // bitset | ||
), 1); // Woken up one thread. | ||
} | ||
}); | ||
|
||
unsafe { | ||
assert_eq!(libc::syscall( | ||
libc::SYS_futex, | ||
&FUTEX as *const i32, | ||
libc::FUTEX_WAIT_BITSET, | ||
0, | ||
ptr::null::<libc::timespec>(), | ||
0, | ||
0b0100, // bitset | ||
), 0); | ||
} | ||
|
||
assert!((400..1000).contains(&start.elapsed().as_millis())); | ||
} | ||
|
||
fn main() { | ||
wake_nobody(); | ||
wake_dangling(); | ||
wait_wrong_val(); | ||
wait_timeout(); | ||
wait_absolute_timeout(); | ||
wait_wake(); | ||
wait_wake_bitset(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test also passes if I put FUTEX_WAIT here, as it seems that the monotonic clock starts at zero in the tests. It'd be a better test if it was run with a monotonic clock that does not start at zero.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifically, our monotone clock is relative to the
time_anchor
which is initialized viaInstant::now()
when the interpreter starts.I guess we could add an arbitrary offset to that? It also should make a difference if the interpreter has already been running for a bit (e.g. because of a previous timeout test).