add direct test of pthread_cond
This commit is contained in:
parent
fd5a84b529
commit
03cec74a3c
3 changed files with 52 additions and 4 deletions
|
|
@ -4,8 +4,8 @@
|
|||
#![feature(sync_unsafe_cell)]
|
||||
|
||||
use std::cell::SyncUnsafeCell;
|
||||
use std::thread;
|
||||
use std::{mem, ptr};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::{mem, ptr, thread};
|
||||
|
||||
fn main() {
|
||||
test_mutex_libc_init_recursive();
|
||||
|
|
@ -15,9 +15,10 @@ fn main() {
|
|||
#[cfg(target_os = "linux")]
|
||||
test_mutex_libc_static_initializer_recursive();
|
||||
|
||||
test_mutex();
|
||||
check_mutex();
|
||||
check_rwlock_write();
|
||||
check_rwlock_read_no_deadlock();
|
||||
check_cond();
|
||||
}
|
||||
|
||||
fn test_mutex_libc_init_recursive() {
|
||||
|
|
@ -119,7 +120,7 @@ impl<T> Clone for SendPtr<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn test_mutex() {
|
||||
fn check_mutex() {
|
||||
// Specifically *not* using `Arc` to make sure there is no synchronization apart from the mutex.
|
||||
unsafe {
|
||||
let data = SyncUnsafeCell::new((libc::PTHREAD_MUTEX_INITIALIZER, 0));
|
||||
|
|
@ -213,6 +214,53 @@ fn check_rwlock_read_no_deadlock() {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_cond() {
|
||||
unsafe {
|
||||
let mut cond: MaybeUninit<libc::pthread_cond_t> = MaybeUninit::uninit();
|
||||
assert_eq!(libc::pthread_cond_init(cond.as_mut_ptr(), ptr::null()), 0);
|
||||
let cond = SendPtr { ptr: cond.as_mut_ptr() };
|
||||
|
||||
let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
|
||||
let mutex = SendPtr { ptr: &mut mutex };
|
||||
|
||||
let mut data = 0;
|
||||
let data = SendPtr { ptr: &mut data };
|
||||
|
||||
let t = thread::spawn(move || {
|
||||
let mutex = mutex; // circumvent per-field closure capture
|
||||
let cond = cond;
|
||||
let data = data;
|
||||
assert_eq!(libc::pthread_mutex_lock(mutex.ptr), 0);
|
||||
assert!(data.ptr.read() == 0);
|
||||
data.ptr.write(1);
|
||||
libc::pthread_cond_wait(cond.ptr, mutex.ptr);
|
||||
assert!(data.ptr.read() == 3);
|
||||
data.ptr.write(4);
|
||||
assert_eq!(libc::pthread_mutex_unlock(mutex.ptr), 0);
|
||||
});
|
||||
|
||||
thread::yield_now();
|
||||
|
||||
assert_eq!(libc::pthread_mutex_lock(mutex.ptr), 0);
|
||||
assert!(data.ptr.read() == 1);
|
||||
data.ptr.write(2);
|
||||
assert_eq!(libc::pthread_cond_signal(cond.ptr), 0);
|
||||
thread::yield_now(); // the other thread wakes up but can't get the lock yet
|
||||
assert!(data.ptr.read() == 2);
|
||||
data.ptr.write(3);
|
||||
assert_eq!(libc::pthread_mutex_unlock(mutex.ptr), 0);
|
||||
|
||||
thread::yield_now(); // now the other thread gets the lock back
|
||||
|
||||
assert_eq!(libc::pthread_mutex_lock(mutex.ptr), 0);
|
||||
assert!(data.ptr.read() == 4);
|
||||
assert_eq!(libc::pthread_cond_broadcast(cond.ptr), 0); // just a smoke test
|
||||
assert_eq!(libc::pthread_mutex_unlock(mutex.ptr), 0);
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// std::sync::RwLock does not even used pthread_rwlock any more.
|
||||
// Do some smoke testing of the API surface.
|
||||
fn test_rwlock_libc_static_initializer() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue