about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_timedwait.rs (renamed from src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond.rs)0
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_timedwait_isolated.rs (renamed from src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_isolated.rs)0
-rw-r--r--src/tools/miri/tests/pass-dep/shims/pthread-sync.rs56
3 files changed, 52 insertions, 4 deletions
diff --git a/src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond.rs b/src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_timedwait.rs
index f362caa11dc..f362caa11dc 100644
--- a/src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_timedwait.rs
diff --git a/src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_isolated.rs b/src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_timedwait_isolated.rs
index 66c0895a5da..66c0895a5da 100644
--- a/src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_isolated.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/libc_pthread_cond_timedwait_isolated.rs
diff --git a/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs b/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs
index 077bbfff164..c9d10cb83d4 100644
--- a/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs
+++ b/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs
@@ -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() {