about summary refs log tree commit diff
path: root/src/tools/miri/tests/utils/genmc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/miri/tests/utils/genmc.rs')
-rw-r--r--src/tools/miri/tests/utils/genmc.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/tools/miri/tests/utils/genmc.rs b/src/tools/miri/tests/utils/genmc.rs
new file mode 100644
index 00000000000..29b3181992b
--- /dev/null
+++ b/src/tools/miri/tests/utils/genmc.rs
@@ -0,0 +1,64 @@
+#![allow(unused)]
+
+use std::ffi::c_void;
+
+use libc::{self, pthread_attr_t, pthread_t};
+
+/// Spawn a thread using `pthread_create`, abort the process on any errors.
+pub unsafe fn spawn_pthread(
+    f: extern "C" fn(*mut c_void) -> *mut c_void,
+    value: *mut c_void,
+) -> pthread_t {
+    let mut thread_id: pthread_t = 0;
+
+    let attr: *const pthread_attr_t = std::ptr::null();
+
+    if unsafe { libc::pthread_create(&raw mut thread_id, attr, f, value) } != 0 {
+        std::process::abort();
+    }
+    thread_id
+}
+
+/// Unsafe because we do *not* check that `F` is `Send + 'static`.
+/// That makes it much easier to write tests...
+pub unsafe fn spawn_pthread_closure<F: FnOnce()>(f: F) -> pthread_t {
+    let mut thread_id: pthread_t = 0;
+    let attr: *const pthread_attr_t = std::ptr::null();
+    let f = Box::new(f);
+    extern "C" fn thread_func<F: FnOnce()>(f: *mut c_void) -> *mut c_void {
+        let f = unsafe { Box::from_raw(f as *mut F) };
+        f();
+        std::ptr::null_mut()
+    }
+    if unsafe {
+        libc::pthread_create(
+            &raw mut thread_id,
+            attr,
+            thread_func::<F>,
+            Box::into_raw(f) as *mut c_void,
+        )
+    } != 0
+    {
+        std::process::abort();
+    }
+    thread_id
+}
+
+// Join the given pthread, abort the process on any errors.
+pub unsafe fn join_pthread(thread_id: pthread_t) {
+    if unsafe { libc::pthread_join(thread_id, std::ptr::null_mut()) } != 0 {
+        std::process::abort();
+    }
+}
+
+/// Spawn `N` threads using `pthread_create` without any arguments, abort the process on any errors.
+pub unsafe fn spawn_pthreads_no_params<const N: usize>(
+    functions: [extern "C" fn(*mut c_void) -> *mut c_void; N],
+) -> [pthread_t; N] {
+    functions.map(|func| spawn_pthread(func, std::ptr::null_mut()))
+}
+
+// Join the `N` given pthreads, abort the process on any errors.
+pub unsafe fn join_pthreads<const N: usize>(thread_ids: [pthread_t; N]) {
+    let _ = thread_ids.map(|id| join_pthread(id));
+}