Skip to content

Commit 55f29d2

Browse files
committed
Auto merge of rust-lang#3304 - RalfJung:pthread_cond, r=RalfJung
add direct test of pthread_cond Fixes rust-lang/miri#2271
2 parents fd5a84b + 03cec74 commit 55f29d2

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

Diff for: src/tools/miri/tests/pass-dep/shims/pthread-sync.rs

+52-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
#![feature(sync_unsafe_cell)]
55

66
use std::cell::SyncUnsafeCell;
7-
use std::thread;
8-
use std::{mem, ptr};
7+
use std::mem::MaybeUninit;
8+
use std::{mem, ptr, thread};
99

1010
fn main() {
1111
test_mutex_libc_init_recursive();
@@ -15,9 +15,10 @@ fn main() {
1515
#[cfg(target_os = "linux")]
1616
test_mutex_libc_static_initializer_recursive();
1717

18-
test_mutex();
18+
check_mutex();
1919
check_rwlock_write();
2020
check_rwlock_read_no_deadlock();
21+
check_cond();
2122
}
2223

2324
fn test_mutex_libc_init_recursive() {
@@ -119,7 +120,7 @@ impl<T> Clone for SendPtr<T> {
119120
}
120121
}
121122

122-
fn test_mutex() {
123+
fn check_mutex() {
123124
// Specifically *not* using `Arc` to make sure there is no synchronization apart from the mutex.
124125
unsafe {
125126
let data = SyncUnsafeCell::new((libc::PTHREAD_MUTEX_INITIALIZER, 0));
@@ -213,6 +214,53 @@ fn check_rwlock_read_no_deadlock() {
213214
}
214215
}
215216

217+
fn check_cond() {
218+
unsafe {
219+
let mut cond: MaybeUninit<libc::pthread_cond_t> = MaybeUninit::uninit();
220+
assert_eq!(libc::pthread_cond_init(cond.as_mut_ptr(), ptr::null()), 0);
221+
let cond = SendPtr { ptr: cond.as_mut_ptr() };
222+
223+
let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
224+
let mutex = SendPtr { ptr: &mut mutex };
225+
226+
let mut data = 0;
227+
let data = SendPtr { ptr: &mut data };
228+
229+
let t = thread::spawn(move || {
230+
let mutex = mutex; // circumvent per-field closure capture
231+
let cond = cond;
232+
let data = data;
233+
assert_eq!(libc::pthread_mutex_lock(mutex.ptr), 0);
234+
assert!(data.ptr.read() == 0);
235+
data.ptr.write(1);
236+
libc::pthread_cond_wait(cond.ptr, mutex.ptr);
237+
assert!(data.ptr.read() == 3);
238+
data.ptr.write(4);
239+
assert_eq!(libc::pthread_mutex_unlock(mutex.ptr), 0);
240+
});
241+
242+
thread::yield_now();
243+
244+
assert_eq!(libc::pthread_mutex_lock(mutex.ptr), 0);
245+
assert!(data.ptr.read() == 1);
246+
data.ptr.write(2);
247+
assert_eq!(libc::pthread_cond_signal(cond.ptr), 0);
248+
thread::yield_now(); // the other thread wakes up but can't get the lock yet
249+
assert!(data.ptr.read() == 2);
250+
data.ptr.write(3);
251+
assert_eq!(libc::pthread_mutex_unlock(mutex.ptr), 0);
252+
253+
thread::yield_now(); // now the other thread gets the lock back
254+
255+
assert_eq!(libc::pthread_mutex_lock(mutex.ptr), 0);
256+
assert!(data.ptr.read() == 4);
257+
assert_eq!(libc::pthread_cond_broadcast(cond.ptr), 0); // just a smoke test
258+
assert_eq!(libc::pthread_mutex_unlock(mutex.ptr), 0);
259+
260+
t.join().unwrap();
261+
}
262+
}
263+
216264
// std::sync::RwLock does not even used pthread_rwlock any more.
217265
// Do some smoke testing of the API surface.
218266
fn test_rwlock_libc_static_initializer() {

0 commit comments

Comments
 (0)