Skip to main content

relibc/header/pthread/
rwlock.rs

1use super::*;
2
3use crate::header::errno::{EBUSY, EINVAL};
4
5use crate::{header::time::CLOCK_REALTIME, pthread::Pshared};
6
7/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_init.html>.
8#[unsafe(no_mangle)]
9pub unsafe extern "C" fn pthread_rwlock_init(
10    rwlock: *mut pthread_rwlock_t,
11    attr: *const pthread_rwlockattr_t,
12) -> c_int {
13    let attr = unsafe { attr.cast::<RlctRwlockAttr>().as_ref() }
14        .copied()
15        .unwrap_or_default();
16
17    unsafe {
18        rwlock
19            .cast::<RlctRwlock>()
20            .write(RlctRwlock::new(attr.pshared))
21    };
22
23    0
24}
25/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_rdlock.html>.
26#[unsafe(no_mangle)]
27pub unsafe extern "C" fn pthread_rwlock_rdlock(rwlock: *mut pthread_rwlock_t) -> c_int {
28    match unsafe { get(rwlock) }.acquire_read_lock(None) {
29        Ok(()) => 0,
30        Err(e) => e.0,
31    }
32}
33/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_clockrdlock.html>.
34#[unsafe(no_mangle)]
35pub unsafe extern "C" fn pthread_rwlock_clockrdlock(
36    rwlock: *mut pthread_rwlock_t,
37    clock_id: clockid_t,
38    abstime: *const timespec,
39) -> c_int {
40    match unsafe { get(rwlock) }.acquire_read_lock(Some((unsafe { &*abstime }, clock_id))) {
41        Ok(()) => 0,
42        Err(e) => e.0,
43    }
44}
45/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_timedrdlock.html>.
46#[unsafe(no_mangle)]
47pub unsafe extern "C" fn pthread_rwlock_timedrdlock(
48    rwlock: *mut pthread_rwlock_t,
49    abstime: *const timespec,
50) -> c_int {
51    match unsafe { get(rwlock) }.acquire_read_lock(Some((unsafe { &*abstime }, CLOCK_REALTIME))) {
52        Ok(()) => 0,
53        Err(e) => e.0,
54    }
55}
56/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_clockwrlock.html>.
57#[unsafe(no_mangle)]
58pub unsafe extern "C" fn pthread_rwlock_clockwrlock(
59    rwlock: *mut pthread_rwlock_t,
60    clock_id: clockid_t,
61    abstime: *const timespec,
62) -> c_int {
63    match unsafe { get(rwlock) }.acquire_write_lock(Some((unsafe { &*abstime }, clock_id))) {
64        Ok(()) => 0,
65        Err(e) => e.0,
66    }
67}
68/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_timedwrlock.html>.
69#[unsafe(no_mangle)]
70pub unsafe extern "C" fn pthread_rwlock_timedwrlock(
71    rwlock: *mut pthread_rwlock_t,
72    abstime: *const timespec,
73) -> c_int {
74    match unsafe { get(rwlock) }.acquire_write_lock(Some((unsafe { &*abstime }, CLOCK_REALTIME))) {
75        Ok(()) => 0,
76        Err(e) => e.0,
77    }
78}
79/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_tryrdlock.html>.
80#[unsafe(no_mangle)]
81pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rwlock: *mut pthread_rwlock_t) -> c_int {
82    match unsafe { get(rwlock) }.try_acquire_read_lock() {
83        Ok(()) => 0,
84        Err(_) => EBUSY,
85    }
86}
87/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_trywrlock.html>.
88#[unsafe(no_mangle)]
89pub unsafe extern "C" fn pthread_rwlock_trywrlock(rwlock: *mut pthread_rwlock_t) -> c_int {
90    match unsafe { get(rwlock) }.try_acquire_write_lock() {
91        Ok(()) => 0,
92        Err(_) => EBUSY,
93    }
94}
95/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_unlock.html>.
96#[unsafe(no_mangle)]
97pub unsafe extern "C" fn pthread_rwlock_unlock(rwlock: *mut pthread_rwlock_t) -> c_int {
98    unsafe { get(rwlock) }.unlock();
99
100    0
101}
102/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_wrlock.html>.
103#[unsafe(no_mangle)]
104pub unsafe extern "C" fn pthread_rwlock_wrlock(rwlock: *mut pthread_rwlock_t) -> c_int {
105    match unsafe { get(rwlock) }.acquire_write_lock(None) {
106        Ok(()) => 0,
107        Err(e) => e.0,
108    }
109}
110
111/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlockattr_init.html>.
112#[unsafe(no_mangle)]
113pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int {
114    unsafe {
115        attr.cast::<RlctRwlockAttr>()
116            .write(RlctRwlockAttr::default())
117    };
118
119    0
120}
121
122/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlockattr_getpshared.html>.
123#[unsafe(no_mangle)]
124pub unsafe extern "C" fn pthread_rwlockattr_getpshared(
125    attr: *const pthread_rwlockattr_t,
126    pshared_out: *mut c_int,
127) -> c_int {
128    unsafe { core::ptr::write(pshared_out, (*attr.cast::<RlctRwlockAttr>()).pshared.raw()) };
129
130    0
131}
132
133/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlockattr_setpshared.html>.
134#[unsafe(no_mangle)]
135pub unsafe extern "C" fn pthread_rwlockattr_setpshared(
136    attr: *mut pthread_rwlockattr_t,
137    pshared: c_int,
138) -> c_int {
139    let Some(pshared) = Pshared::from_raw(pshared) else {
140        return EINVAL;
141    };
142
143    (unsafe { *attr.cast::<RlctRwlockAttr>() }).pshared = pshared;
144    0
145}
146
147/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlockattr_destroy.html>.
148#[unsafe(no_mangle)]
149pub unsafe extern "C" fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> c_int {
150    unsafe { core::ptr::drop_in_place(attr) };
151
152    0
153}
154/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_rwlock_destroy.html>.
155#[unsafe(no_mangle)]
156pub unsafe extern "C" fn pthread_rwlock_destroy(rwlock: *mut pthread_rwlock_t) -> c_int {
157    unsafe { core::ptr::drop_in_place(rwlock) };
158
159    0
160}
161
162pub(crate) type RlctRwlock = crate::sync::rwlock::InnerRwLock;
163
164#[derive(Clone, Copy, Default)]
165pub(crate) struct RlctRwlockAttr {
166    pshared: Pshared,
167}
168#[inline]
169unsafe fn get<'a>(ptr: *mut pthread_rwlock_t) -> &'a RlctRwlock {
170    unsafe { &*ptr.cast() }
171}