1 //@ignore-target-windows: No libc on Windows
2 //@ignore-target-apple: pthread_condattr_setclock is not supported on MacOS.
3 //@compile-flags: -Zmiri-disable-isolation
5 /// Test that conditional variable timeouts are working properly with both
6 /// monotonic and system clocks.
7 use std::mem::MaybeUninit;
8 use std::time::Instant;
10 fn test_timed_wait_timeout(clock_id: i32) {
12 let mut attr: MaybeUninit<libc::pthread_condattr_t> = MaybeUninit::uninit();
13 assert_eq!(libc::pthread_condattr_init(attr.as_mut_ptr()), 0);
14 assert_eq!(libc::pthread_condattr_setclock(attr.as_mut_ptr(), clock_id), 0);
16 let mut cond: MaybeUninit<libc::pthread_cond_t> = MaybeUninit::uninit();
17 assert_eq!(libc::pthread_cond_init(cond.as_mut_ptr(), attr.as_ptr()), 0);
18 assert_eq!(libc::pthread_condattr_destroy(attr.as_mut_ptr()), 0);
20 let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
22 let mut now_mu: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
23 assert_eq!(libc::clock_gettime(clock_id, now_mu.as_mut_ptr()), 0);
24 let now = now_mu.assume_init();
25 // Waiting for a second... mostly because waiting less requires mich more tricky arithmetic.
27 let timeout = libc::timespec { tv_sec: now.tv_sec + 1, tv_nsec: now.tv_nsec };
29 assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
30 let current_time = Instant::now();
32 libc::pthread_cond_timedwait(cond.as_mut_ptr(), &mut mutex as *mut _, &timeout),
35 let elapsed_time = current_time.elapsed().as_millis();
36 assert!(900 <= elapsed_time && elapsed_time <= 1300);
38 // Test calling `pthread_cond_timedwait` again with an already elapsed timeout.
40 libc::pthread_cond_timedwait(cond.as_mut_ptr(), &mut mutex as *mut _, &timeout),
44 // Test that invalid nanosecond values (above 10^9 or negative) are rejected with the
45 // correct error code.
46 let invalid_timeout_1 = libc::timespec { tv_sec: now.tv_sec + 1, tv_nsec: 1_000_000_000 };
48 libc::pthread_cond_timedwait(
55 let invalid_timeout_2 = libc::timespec { tv_sec: now.tv_sec + 1, tv_nsec: -1 };
57 libc::pthread_cond_timedwait(
64 // Test that invalid second values (negative) are rejected with the correct error code.
65 let invalid_timeout_3 = libc::timespec { tv_sec: -1, tv_nsec: 0 };
67 libc::pthread_cond_timedwait(
75 assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
76 assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
77 assert_eq!(libc::pthread_cond_destroy(cond.as_mut_ptr()), 0);
82 test_timed_wait_timeout(libc::CLOCK_MONOTONIC);
83 test_timed_wait_timeout(libc::CLOCK_REALTIME);