Skip to main content

relibc/header/semaphore/
mod.rs

1//! `semaphore.h` implementation.
2//!
3//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/semaphore.h.html>.
4
5use crate::{
6    error::ResultExt,
7    header::{
8        errno,
9        time::{self, timespec},
10    },
11    platform::{
12        self,
13        types::{c_char, c_int, c_long, c_uint, clockid_t},
14    },
15};
16
17/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/semaphore.h.html>.
18// TODO: Statically verify size and align
19#[repr(C)]
20#[derive(Clone, Copy)]
21pub union sem_t {
22    pub size: [c_char; 4],
23    pub align: c_long,
24}
25pub type RlctSempahore = crate::sync::Semaphore;
26
27/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_close.html>.
28// #[unsafe(no_mangle)]
29pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
30    todo!("named semaphores")
31}
32
33/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_destroy.html>.
34#[unsafe(no_mangle)]
35pub unsafe extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int {
36    unsafe { core::ptr::drop_in_place(sem.cast::<RlctSempahore>()) };
37    0
38}
39
40/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_getvalue.html>.
41#[unsafe(no_mangle)]
42pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
43    unsafe { sval.write(get(sem).value() as c_int) };
44
45    0
46}
47
48/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_init.html>.
49#[unsafe(no_mangle)]
50pub unsafe extern "C" fn sem_init(sem: *mut sem_t, _pshared: c_int, value: c_uint) -> c_int {
51    unsafe { sem.cast::<RlctSempahore>().write(RlctSempahore::new(value)) };
52
53    0
54}
55
56/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_open.html>.
57// TODO: va_list
58// #[unsafe(no_mangle)]
59pub unsafe extern "C" fn sem_open(
60    name: *const c_char,
61    oflag: c_int, /* (va_list) value: c_uint */
62) -> *mut sem_t {
63    todo!("named semaphores")
64}
65
66/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_post.html>.
67#[unsafe(no_mangle)]
68pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
69    unsafe { get(sem) }.post(1);
70
71    0
72}
73
74/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_trywait.html>.
75#[unsafe(no_mangle)]
76pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
77    if unsafe { get(sem) }.try_wait() {
78        0
79    } else {
80        platform::ERRNO.set(errno::EAGAIN);
81        -1
82    }
83}
84
85/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_unlink.html>.
86// #[unsafe(no_mangle)]
87pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
88    todo!("named semaphores")
89}
90
91/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_trywait.html>.
92#[unsafe(no_mangle)]
93pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
94    unsafe { get(sem) }
95        .wait(None, time::CLOCK_MONOTONIC)
96        .map(|()| 0)
97        .or_minus_one_errno()
98}
99
100/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_clockwait.html>.
101#[unsafe(no_mangle)]
102pub unsafe extern "C" fn sem_clockwait(
103    sem: *mut sem_t,
104    clock_id: clockid_t,
105    abstime: *const timespec,
106) -> c_int {
107    unsafe { get(sem) }
108        .wait(Some(&unsafe { (*abstime).clone() }), clock_id)
109        .map(|()| 0)
110        .or_minus_one_errno()
111}
112
113/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_timedwait.html>.
114#[unsafe(no_mangle)]
115pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abstime: *const timespec) -> c_int {
116    unsafe { get(sem) }
117        .wait(Some(&unsafe { (*abstime).clone() }), time::CLOCK_REALTIME)
118        .map(|()| 0)
119        .or_minus_one_errno()
120}
121
122unsafe fn get<'any>(sem: *mut sem_t) -> &'any RlctSempahore {
123    unsafe { &*sem.cast() }
124}