Skip to main content

relibc/header/pthread/
barrier.rs

1use crate::header::errno::EINVAL;
2
3use core::num::NonZeroU32;
4
5use crate::sync::barrier::{Barrier, WaitResult};
6
7use super::{
8    PTHREAD_BARRIER_SERIAL_THREAD, PTHREAD_PROCESS_PRIVATE, c_int, c_uint, pthread_barrier_t,
9    pthread_barrierattr_t,
10};
11
12pub(crate) type RlctBarrier = Barrier;
13
14#[derive(Clone, Copy)]
15pub(crate) struct RlctBarrierAttr {
16    pshared: c_int,
17}
18impl Default for RlctBarrierAttr {
19    fn default() -> Self {
20        // pshared = PTHREAD_PROCESS_PRIVATE is default according to POSIX.
21        Self {
22            pshared: PTHREAD_PROCESS_PRIVATE,
23        }
24    }
25}
26
27/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_barrier_destroy.html>.
28///
29/// Destroys the barrier referenced by `barrier` and releases any resources
30/// used by the barrier.
31///
32/// Upon success, returns `0`. Upon error, returns an error number.
33///
34/// # Implementation
35/// Not async-signal-safe.
36///
37/// # Safety
38/// The following will result in undefined behaviour:
39/// - Use of `barrier` after this function unless reinitialized by
40///   `pthread_barrier_init()`.
41/// - This function is called with an uninitialized `barrier`.
42/// - This function is called when any thread is blocked on `barrier`.
43#[unsafe(no_mangle)]
44pub unsafe extern "C" fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int {
45    // No-op, currently.
46    unsafe { core::ptr::drop_in_place(barrier.cast::<RlctBarrier>()) };
47
48    0
49}
50
51/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_barrier_init.html>.
52///
53/// Allocates any resources required to use the barrier referenced by `barrier`
54/// and shall initialize the barrier with attributes referenced by `attr`.
55///
56/// Upon success, returns `0`. Upon error, returns an error number.
57///
58/// # Implementation
59/// Not async-signal-safe.
60///
61/// # Safety
62/// The following will result in undefined behaviour:
63/// - Use of `barrier` before this function is called.
64/// - This function is called with an already initialized `barrier`.
65/// - This function is called when any thread is blocked on `barrier`.
66#[unsafe(no_mangle)]
67pub unsafe extern "C" fn pthread_barrier_init(
68    barrier: *mut pthread_barrier_t,
69    attr: *const pthread_barrierattr_t,
70    count: c_uint,
71) -> c_int {
72    let attr = unsafe { attr.cast::<RlctBarrierAttr>().as_ref() }
73        .copied()
74        .unwrap_or_default();
75
76    let Some(count) = NonZeroU32::new(count) else {
77        return EINVAL;
78    };
79
80    unsafe { barrier.cast::<RlctBarrier>().write(RlctBarrier::new(count)) };
81    0
82}
83
84fn unlikely(condition: bool) -> bool {
85    condition
86}
87
88/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_barrier_wait.html>.
89///
90/// Synchronizes participating threads at the barrier referenced by `barrier`.
91///
92/// Upon success, returns `PTHREAD_BARRIER_SERIAL_THREAD` for a single
93/// (arbitrary) thread synchronized at the barrier and `0` for each of the
94/// other threads. Upon failure, returns an error number.
95///
96/// # Implementation
97/// Not async-signal-safe.
98///
99/// # Safety
100/// Undefined behaviour will occur if `barrier` is uninitialized.
101#[unsafe(no_mangle)]
102pub unsafe extern "C" fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> c_int {
103    let barrier = unsafe { &*barrier.cast::<RlctBarrier>() };
104
105    match barrier.wait() {
106        WaitResult::NotifiedAll => PTHREAD_BARRIER_SERIAL_THREAD,
107        WaitResult::Waited => 0,
108    }
109}
110
111/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_barrierattr_init.html>.
112///
113/// Initializes a barrier attributes object `attr` with the default value of
114/// all of the attributes defined by the implementation.
115///
116/// Upon success, returns `0`. Upon error, returns an error number.
117///
118/// # Implementation
119/// Not async-signal-safe.
120///
121/// # Safety
122/// Undefined behaviour will occur if `attr` is already initialized.
123#[unsafe(no_mangle)]
124pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int {
125    unsafe { core::ptr::write(attr.cast::<RlctBarrierAttr>(), RlctBarrierAttr::default()) };
126
127    0
128}
129
130/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_barrierattr_setpshared.html>.
131///
132/// Sets the process-shared attribute in an initialized attributes object
133/// referenced by `attr`.
134///
135/// Upon success, returns `0`. Upon error, returns an error number.
136///
137/// # Implementation
138/// Not async-signal-safe.
139///
140/// # Safety
141/// Undefined behaviour will occur if `attr` is uninitialized.
142#[unsafe(no_mangle)]
143pub unsafe extern "C" fn pthread_barrierattr_setpshared(
144    attr: *mut pthread_barrierattr_t,
145    pshared: c_int,
146) -> c_int {
147    unsafe {
148        (*attr.cast::<RlctBarrierAttr>()).pshared = pshared;
149    }
150    0
151}
152
153/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_barrierattr_getpshared.html>.
154///
155/// Obtains the value of the process-shared attribute from the attributes
156/// object referenced by `attr`.
157///
158/// Upon success, returns `0` and stores the value of the process-shared
159/// attribute of `attr` into the object referenced by `pshared`. Upon error,
160/// returns an error number.
161///
162/// # Implementation
163/// Not async-signal-safe.
164///
165/// # Safety
166/// Undefined behaviour will occur if `attr` is uninitialized.
167#[unsafe(no_mangle)]
168pub unsafe extern "C" fn pthread_barrierattr_getpshared(
169    attr: *const pthread_barrierattr_t,
170    pshared: *mut c_int,
171) -> c_int {
172    unsafe { core::ptr::write(pshared, (*attr.cast::<RlctBarrierAttr>()).pshared) };
173    0
174}
175
176/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_barrierattr_destroy.html>.
177///
178/// Destroys a barrier attributes object.
179///
180/// Upon success, returns `0`. Upon error, returns an error number.
181///
182/// # Implementation
183/// Not async-signal-safe.
184///
185/// # Safety
186/// Undefined behaviour will occur if `attr` is uninitialized or if `attr` is
187/// used after calling this function.
188#[unsafe(no_mangle)]
189pub unsafe extern "C" fn pthread_barrierattr_destroy(attr: *mut pthread_barrierattr_t) -> c_int {
190    unsafe { core::ptr::drop_in_place(attr) };
191    0
192}