Merge branch 'pthread-cond-docs' into 'master'
document functions in pthread cond See merge request redox-os/relibc!1510
This commit is contained in:
@@ -10,6 +10,9 @@ sys_includes = ["sched.h", "time.h", "bits/pthread.h", "features.h"]
|
||||
# TODO: Any better way to implement pthread_cleanup_push/pthread_cleanup_pop?
|
||||
after_includes = """
|
||||
|
||||
// A value that shall not compare equal to any exiting thread.
|
||||
#define PTHREAD_NULL (pthread_t(NULL))
|
||||
|
||||
#define PTHREAD_COND_INITIALIZER {0}
|
||||
#define PTHREAD_MUTEX_INITIALIZER {0}
|
||||
#define PTHREAD_RWLOCK_INITIALIZER {0}
|
||||
|
||||
+207
-26
@@ -1,18 +1,52 @@
|
||||
// Used design from https://www.remlab.net/op/futex-condvar.shtml
|
||||
|
||||
use crate::header::time::CLOCK_REALTIME;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
header::{
|
||||
pthread::{PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED, RlctMutex, e},
|
||||
time::{CLOCK_REALTIME, timespec},
|
||||
},
|
||||
platform::types::{c_int, clockid_t, pthread_cond_t, pthread_condattr_t, pthread_mutex_t},
|
||||
};
|
||||
|
||||
// PTHREAD_COND_INITIALIZER is defined manually in bits_pthread/cbindgen.toml
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_broadcast.html>.
|
||||
///
|
||||
/// As a single atomic operation, determines which threads, if any, are blocked
|
||||
/// on the specified condition variable `cond` and unblocks all of these
|
||||
/// threads.
|
||||
///
|
||||
/// Has no effect if no threads are blocked on `cond`.
|
||||
///
|
||||
/// Upon success, returns `0`. Upon failure, an error number is returned to
|
||||
/// indicate the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour if `cond` is not initialized.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
|
||||
e((unsafe { &*cond.cast::<RlctCond>() }).broadcast())
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_destroy.html>.
|
||||
///
|
||||
/// Destroys the given condition variable specified by `cond`.
|
||||
///
|
||||
/// Upon success, returns `0`. Upon failure, an error number is returned to
|
||||
/// indicate the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour for the following:
|
||||
/// - `cond` is not initialized when calling this function.
|
||||
/// - Use of `cond` after calling this function without reinitializing it.
|
||||
/// - Attempting to destroy a condition variable upon which other threads are
|
||||
/// currently blocked.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int {
|
||||
// No-op
|
||||
@@ -21,6 +55,20 @@ pub unsafe extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_in
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_init.html>.
|
||||
///
|
||||
/// Initializes the condition variable referenced by `cond` with attributes
|
||||
/// referenced by `attr`.
|
||||
///
|
||||
/// Upon success, returns `0`. Upon failure, an error number is returned to
|
||||
/// indicate the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour for the following:
|
||||
/// - `attr` is not initialized when calling this function.
|
||||
/// - `cond` has already been initialized.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_cond_init(
|
||||
cond: *mut pthread_cond_t,
|
||||
@@ -41,38 +89,99 @@ pub unsafe extern "C" fn pthread_cond_init(
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_signal.html>.
|
||||
///
|
||||
/// As a single atomic operation, determines which threads, if any, are blocked
|
||||
/// on the specified condition variable `cond` and unblocks at least one of
|
||||
/// these threads.
|
||||
///
|
||||
/// Has no effect if no threads are blocked on `cond`.
|
||||
///
|
||||
/// Upon success, returns `0`. Upon failure, an error number is returned to
|
||||
/// indicate the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
/// Identical behaviour to `pthread_cond_broadcast()`.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour if `cond` is not initialized.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
|
||||
e((unsafe { &*cond.cast::<RlctCond>() }).signal())
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_timedwait.html>.
|
||||
///
|
||||
/// Blocks on a condition variable.
|
||||
///
|
||||
/// Clock used for timeout depends on the clock attribute in `cond`. Defaults
|
||||
/// to `CLOCK_REALTIME` if not set.
|
||||
///
|
||||
/// Upon success, returns `0` and the `mutex` shall have been locked and shall
|
||||
/// be owned by the calling thread. Upon failure, an error number is returned
|
||||
/// to indicate the error.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour for the following:
|
||||
/// - `cond` is uninitialized.
|
||||
/// - `mutex` is uninitialized.
|
||||
/// - `mutex` has not been locked by the calling thread before calling this
|
||||
/// function.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_cond_timedwait(
|
||||
cond: *mut pthread_cond_t,
|
||||
mutex: *mut pthread_mutex_t,
|
||||
timeout: *const timespec,
|
||||
abstime: *const timespec,
|
||||
) -> c_int {
|
||||
e((unsafe { &*cond.cast::<RlctCond>() })
|
||||
.timedwait(unsafe { &*mutex.cast::<RlctMutex>() }, unsafe { &*timeout }))
|
||||
.timedwait(unsafe { &*mutex.cast::<RlctMutex>() }, unsafe { &*abstime }))
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_clockwait.html>.
|
||||
///
|
||||
/// Blocks on a condition variable.
|
||||
///
|
||||
/// `clock_id` determines the clock to use for the timeout specified by
|
||||
/// `abstime`.
|
||||
///
|
||||
/// Upon success, returns `0` and the `mutex` shall have been locked and shall
|
||||
/// be owned by the calling thread. Upon failure, an error number is returned
|
||||
/// to indicate the error.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour for the following:
|
||||
/// - `cond` is uninitialized.
|
||||
/// - `mutex` is uninitialized.
|
||||
/// - `mutex` has not been locked by the calling thread before calling this
|
||||
/// function.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_cond_clockwait(
|
||||
cond: *mut pthread_cond_t,
|
||||
mutex: *mut pthread_mutex_t,
|
||||
clock_id: clockid_t,
|
||||
timeout: *const timespec,
|
||||
abstime: *const timespec,
|
||||
) -> c_int {
|
||||
e((unsafe { &*cond.cast::<RlctCond>() }).clockwait(
|
||||
unsafe { &*mutex.cast::<RlctMutex>() },
|
||||
unsafe { &*timeout },
|
||||
unsafe { &*abstime },
|
||||
clock_id,
|
||||
))
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_wait.html>.
|
||||
///
|
||||
/// Blocks on a condition variable.
|
||||
///
|
||||
/// Upon success, returns `0` and the `mutex` shall have been locked and shall
|
||||
/// be owned by the calling thread. Upon failure, an error number is returned
|
||||
/// to indicate the error.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour for the following:
|
||||
/// - `cond` is uninitialized.
|
||||
/// - `mutex` is uninitialized.
|
||||
/// - `mutex` has not been locked by the calling thread before calling this
|
||||
/// function.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_cond_wait(
|
||||
cond: *mut pthread_cond_t,
|
||||
@@ -82,62 +191,134 @@ pub unsafe extern "C" fn pthread_cond_wait(
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_condattr_destroy.html>.
|
||||
///
|
||||
/// Destroys a condition variable attributes object.
|
||||
///
|
||||
/// Upon success, returns `0`. Upon failure, an error number is returned to
|
||||
/// indicated the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour for the following:
|
||||
/// - `attr` is uninitialized.
|
||||
/// - `attr` is used after calling this function without reinitializing it.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_condattr_destroy(condattr: *mut pthread_condattr_t) -> c_int {
|
||||
unsafe { core::ptr::drop_in_place(condattr.cast::<RlctCondAttr>()) };
|
||||
pub unsafe extern "C" fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> c_int {
|
||||
unsafe { core::ptr::drop_in_place(attr.cast::<RlctCondAttr>()) };
|
||||
// No-op
|
||||
0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_condattr_getclock.html>.
|
||||
///
|
||||
/// Obtains the value of the clock attribute from the attributes object
|
||||
/// referenced by `attr`.
|
||||
///
|
||||
/// Upon success, returns `0` and stores the value of the clock attribute of
|
||||
/// `attr` into the object refereced by the `clock_id` argument. Upon failure,
|
||||
/// an error number is returned to indicate the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour if `attr` is uninitialized.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_condattr_getclock(
|
||||
condattr: *const pthread_condattr_t,
|
||||
clock: *mut clockid_t,
|
||||
attr: *const pthread_condattr_t,
|
||||
clock_id: *mut clockid_t,
|
||||
) -> c_int {
|
||||
unsafe { core::ptr::write(clock, (*condattr.cast::<RlctCondAttr>()).clock) };
|
||||
unsafe { core::ptr::write(clock_id, (*attr.cast::<RlctCondAttr>()).clock) };
|
||||
0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_condattr_getpshared.html>.
|
||||
///
|
||||
/// Obtains the value of the process-shared attribute from the attributes
|
||||
/// object referenced by `attr`.
|
||||
///
|
||||
/// Upon success, returns `0` and stores the value of the process-shared
|
||||
/// attribute of `attr` into the object referenced by the `pshared` parameter.
|
||||
/// Upon failure, an error number is returned to indicate the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour if `attr` is uninitialized.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_condattr_getpshared(
|
||||
condattr: *const pthread_condattr_t,
|
||||
attr: *const pthread_condattr_t,
|
||||
pshared: *mut c_int,
|
||||
) -> c_int {
|
||||
unsafe { core::ptr::write(pshared, (*condattr.cast::<RlctCondAttr>()).pshared) };
|
||||
unsafe { core::ptr::write(pshared, (*attr.cast::<RlctCondAttr>()).pshared) };
|
||||
0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_condattr_init.html>.
|
||||
///
|
||||
/// Initializes a condition variable attribute object `attr` with the default
|
||||
/// value for all of the attributes defined by the implementation.
|
||||
///
|
||||
/// Upon success, returns `0`. Upon failure, an error number is returned to
|
||||
/// indicate the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour if `attr` is already initialized.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_condattr_init(condattr: *mut pthread_condattr_t) -> c_int {
|
||||
unsafe {
|
||||
condattr
|
||||
.cast::<RlctCondAttr>()
|
||||
.write(RlctCondAttr::default())
|
||||
};
|
||||
pub unsafe extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
|
||||
unsafe { attr.cast::<RlctCondAttr>().write(RlctCondAttr::default()) };
|
||||
0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_condattr_setclock.html>.
|
||||
///
|
||||
/// Sets the clock attribute in the attributes object referenced by `attr`.
|
||||
/// Upon success, returns `0`. Upon failure, an error number is returned to
|
||||
/// indicated the error.
|
||||
///
|
||||
/// # Implementation
|
||||
/// Always successful, so will never return an error number.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour if `attr` is uninitialized.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_condattr_setclock(
|
||||
condattr: *mut pthread_condattr_t,
|
||||
clock: clockid_t,
|
||||
attr: *mut pthread_condattr_t,
|
||||
clock_id: clockid_t,
|
||||
) -> c_int {
|
||||
(unsafe { *condattr.cast::<RlctCondAttr>() }).clock = clock;
|
||||
// TODO return EINVAL if clock_id is invalid or a CPU-time clock
|
||||
(unsafe { *attr.cast::<RlctCondAttr>() }).clock = clock_id;
|
||||
0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_condattr_setpshared.html>.
|
||||
///
|
||||
/// Sets the process-shared attribute in the attributes object referenced by
|
||||
/// `attr`.
|
||||
///
|
||||
/// Upon success, returns `0`. Upon failure, an error number is returned to
|
||||
/// indicate the error.
|
||||
///
|
||||
/// # Safety
|
||||
/// It is undefined behaviour if `attr` is uninitialized.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_condattr_setpshared(
|
||||
condattr: *mut pthread_condattr_t,
|
||||
attr: *mut pthread_condattr_t,
|
||||
pshared: c_int,
|
||||
) -> c_int {
|
||||
(unsafe { *condattr.cast::<RlctCondAttr>() }).pshared = pshared;
|
||||
0
|
||||
match pshared {
|
||||
PTHREAD_PROCESS_SHARED | PTHREAD_PROCESS_PRIVATE => {
|
||||
(unsafe { *attr.cast::<RlctCondAttr>() }).pshared = pshared;
|
||||
0
|
||||
}
|
||||
_ => crate::header::errno::EINVAL,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type RlctCondAttr = crate::sync::cond::CondAttr;
|
||||
|
||||
@@ -7,12 +7,11 @@ use core::{cell::Cell, ptr::NonNull};
|
||||
|
||||
use crate::{
|
||||
error::Errno,
|
||||
header::{sched::*, time::timespec},
|
||||
header::{sched::sched_param, time::timespec},
|
||||
platform::types::{
|
||||
c_int, c_uchar, c_uint, c_void, clockid_t, pthread_attr_t, pthread_barrier_t,
|
||||
pthread_barrierattr_t, pthread_cond_t, pthread_condattr_t, pthread_key_t, pthread_mutex_t,
|
||||
pthread_mutexattr_t, pthread_once_t, pthread_rwlock_t, pthread_rwlockattr_t, pthread_t,
|
||||
size_t,
|
||||
pthread_barrierattr_t, pthread_key_t, pthread_mutex_t, pthread_mutexattr_t, pthread_once_t,
|
||||
pthread_rwlock_t, pthread_rwlockattr_t, pthread_t, size_t,
|
||||
},
|
||||
pthread,
|
||||
};
|
||||
@@ -73,6 +72,10 @@ pub const PTHREAD_PRIO_NONE: c_int = 0;
|
||||
|
||||
pub const PTHREAD_PRIO_PROTECT: c_int = 0;
|
||||
|
||||
/// Permits a condition variable to be operated upon by any thread that has
|
||||
/// access to the memory where the condition variable is allocated, even if the
|
||||
/// condition variable is allocated in memory that is shared by multiple
|
||||
/// processes.
|
||||
pub const PTHREAD_PROCESS_SHARED: c_int = 0;
|
||||
pub const PTHREAD_PROCESS_PRIVATE: c_int = 1;
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ use crate::{
|
||||
error::Errno,
|
||||
header::{
|
||||
errno::{EINVAL, ETIMEDOUT},
|
||||
pthread::*,
|
||||
pthread::{PTHREAD_PROCESS_PRIVATE, RlctMutex},
|
||||
time::{CLOCK_MONOTONIC, CLOCK_REALTIME, timespec, timespec_realtime_to_monotonic},
|
||||
},
|
||||
platform::types::clockid_t,
|
||||
|
||||
Reference in New Issue
Block a user