about summary refs log tree commit diff
path: root/src/tools/miri/tests/utils/genmc.rs
blob: 29b3181992b1163b396a0d24c4c00017c49c7c16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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));
}