1#![allow(non_camel_case_types)]
6#![allow(non_upper_case_globals)]
7use super::{
8 bits_limits_ptdi::PTHREAD_DESTRUCTOR_ITERATIONS,
9 bits_pthread::{self, pthread_cond_t, pthread_key_t, pthread_mutex_t, pthread_mutexattr_t},
10 errno::{EBUSY, EINTR, ENOMEM, ETIMEDOUT},
11 pthread::{
12 self, PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_RECURSIVE, RlctCond, pthread_cond_broadcast,
13 pthread_cond_destroy, pthread_cond_signal, pthread_cond_timedwait, pthread_cond_wait,
14 pthread_create, pthread_detach, pthread_equal, pthread_exit, pthread_getspecific,
15 pthread_join, pthread_key_create, pthread_key_delete, pthread_mutex_destroy,
16 pthread_mutex_init, pthread_mutex_lock, pthread_mutex_timedlock, pthread_mutex_trylock,
17 pthread_mutex_unlock, pthread_mutexattr_init, pthread_mutexattr_settype, pthread_self,
18 pthread_setspecific,
19 },
20 sched::sched_yield,
21 time::{CLOCK_REALTIME, clock_nanosleep, timespec},
22};
23use crate::platform::{
24 ERRNO,
25 types::{c_int, c_long, c_void},
26};
27use core::mem::MaybeUninit;
28
29pub type thrd_t = bits_pthread::pthread_t;
30pub type once_flag = bits_pthread::pthread_once_t;
31pub type tss_t = bits_pthread::pthread_key_t;
32pub type mtx_t = bits_pthread::pthread_mutex_t;
33pub type cnd_t = bits_pthread::pthread_cond_t;
34
35pub type thrd_start_t = extern "C" fn(*mut c_void) -> c_int;
36pub type tss_dtor_t = Option<extern "C" fn(*mut c_void)>;
37
38pub const thrd_success: c_int = 0;
39pub const thrd_busy: c_int = 1;
40pub const thrd_error: c_int = 2;
41pub const thrd_nomem: c_int = 3;
42pub const thrd_timedout: c_int = 4;
43
44pub const mtx_plain: c_int = 0;
45pub const mtx_recursive: c_int = 1;
46pub const mtx_timed: c_int = 2;
47
48pub const TSS_DTOR_ITERATIONS: c_long = PTHREAD_DESTRUCTOR_ITERATIONS;
49
50#[unsafe(no_mangle)]
52pub unsafe extern "C" fn call_once(flag: *mut once_flag, func: extern "C" fn()) {
53 unsafe {
54 pthread::pthread_once(flag, func);
55 };
56}
57
58#[unsafe(no_mangle)]
60pub unsafe extern "C" fn cnd_broadcast(cnd: *mut cnd_t) -> c_int {
61 if unsafe { pthread_cond_broadcast(cnd.cast::<pthread_cond_t>()) } == 0 {
62 thrd_success
63 } else {
64 thrd_error
65 }
66}
67
68#[unsafe(no_mangle)]
70pub unsafe extern "C" fn cnd_destroy(cnd: *mut cnd_t) {
71 unsafe { pthread_cond_destroy(cnd.cast::<pthread_cond_t>()) };
72}
73
74#[unsafe(no_mangle)]
76pub unsafe extern "C" fn cnd_init(cnd: *mut cnd_t) -> c_int {
77 unsafe {
78 cnd.cast::<RlctCond>().write(RlctCond::new());
79 }
80 thrd_success
81}
82
83#[unsafe(no_mangle)]
85pub unsafe extern "C" fn cnd_signal(cnd: *mut cnd_t) -> c_int {
86 if unsafe { pthread_cond_signal(cnd.cast::<pthread_cond_t>()) } == 0 {
87 thrd_success
88 } else {
89 thrd_error
90 }
91}
92
93#[unsafe(no_mangle)]
95pub unsafe extern "C" fn cnd_timedwait(
96 cnd: *mut cnd_t,
97 mtx: *mut mtx_t,
98 timeout: *const timespec,
99) -> c_int {
100 ERRNO.set(0);
101 let ret = unsafe {
102 pthread_cond_timedwait(
103 cnd.cast::<pthread_cond_t>(),
104 mtx.cast::<pthread_mutex_t>(),
105 timeout,
106 )
107 };
108 let new_errno = ERRNO.get();
109 match ret {
110 0 => thrd_success,
111 _ if new_errno == ETIMEDOUT => thrd_timedout,
112 _ => thrd_error,
113 }
114}
115
116#[unsafe(no_mangle)]
118pub unsafe extern "C" fn cnd_wait(cnd: *mut cnd_t, mtx: *mut mtx_t) -> c_int {
119 if unsafe { pthread_cond_wait(cnd.cast::<pthread_cond_t>(), mtx.cast::<pthread_mutex_t>()) }
120 == 0
121 {
122 thrd_success
123 } else {
124 thrd_error
125 }
126}
127
128#[unsafe(no_mangle)]
130pub unsafe extern "C" fn mtx_destroy(mtx: *mut mtx_t) {
131 unsafe {
132 pthread_mutex_destroy(mtx.cast::<pthread_mutex_t>());
133 }
134}
135
136#[unsafe(no_mangle)]
138pub unsafe extern "C" fn mtx_init(mtx: *mut mtx_t, ty: c_int) -> c_int {
139 let mut attr = MaybeUninit::<pthread_mutexattr_t>::uninit();
140 unsafe {
141 pthread_mutexattr_init(attr.as_mut_ptr());
142 }
143 let mut attr = unsafe { attr.assume_init() };
144
145 let _ = unsafe {
146 pthread_mutexattr_settype(
147 &raw mut attr,
148 if ty & mtx_recursive == mtx_recursive {
149 PTHREAD_MUTEX_RECURSIVE
150 } else {
151 PTHREAD_MUTEX_NORMAL
152 },
153 )
154 };
155 if unsafe { pthread_mutex_init(mtx.cast::<pthread_mutex_t>(), &raw const attr) } == 0 {
156 thrd_success
157 } else {
158 thrd_error
159 }
160}
161
162#[unsafe(no_mangle)]
164pub unsafe extern "C" fn mtx_lock(mtx: *mut mtx_t) -> c_int {
165 if unsafe { pthread_mutex_lock(mtx.cast::<pthread_mutex_t>()) } == 0 {
166 thrd_success
167 } else {
168 thrd_error
169 }
170}
171
172#[unsafe(no_mangle)]
174pub unsafe extern "C" fn mtx_timedlock(mtx: *mut mtx_t, timeout: ×pec) -> c_int {
175 ERRNO.set(0);
176 let ret = unsafe { pthread_mutex_timedlock(mtx.cast::<pthread_mutex_t>(), timeout) };
177 let new_errno = ERRNO.get();
178 match ret {
179 0 => thrd_success,
180 _ if new_errno == ETIMEDOUT => thrd_timedout,
181 _ => thrd_error,
182 }
183}
184
185#[unsafe(no_mangle)]
187pub unsafe extern "C" fn mtx_trylock(mtx: *mut mtx_t) -> c_int {
188 ERRNO.set(0);
189 let ret = unsafe { pthread_mutex_trylock(mtx.cast::<pthread_mutex_t>()) };
190 let new_errno = ERRNO.get();
191 match ret {
192 0 => thrd_success,
193 _ if new_errno == EBUSY => thrd_busy,
194 _ => thrd_error,
195 }
196}
197
198#[unsafe(no_mangle)]
200pub unsafe extern "C" fn mtx_unlock(mtx: *mut mtx_t) -> c_int {
201 if unsafe { pthread_mutex_unlock(mtx.cast::<pthread_mutex_t>()) } == 0 {
202 thrd_success
203 } else {
204 thrd_error
205 }
206}
207
208#[unsafe(no_mangle)]
210pub unsafe extern "C" fn thrd_create(
211 thrd: *mut thrd_t,
212 start: thrd_start_t,
213 arg: *mut c_void,
214) -> c_int {
215 ERRNO.set(0);
216 let ret = unsafe {
217 pthread_create(
218 thrd,
219 core::ptr::null(),
220 #[expect(clippy::missing_transmute_annotations)] core::mem::transmute::<_, extern "C" fn(*mut c_void) -> *mut c_void>(start),
222 arg,
223 )
224 };
225 let new_errno = ERRNO.get();
226 match ret {
227 0 => thrd_success,
228 _ if new_errno == ENOMEM => thrd_nomem,
229 _ => thrd_error,
230 }
231}
232
233#[unsafe(no_mangle)]
235pub unsafe extern "C" fn thrd_current() -> thrd_t {
236 unsafe { pthread_self() }
237}
238
239#[unsafe(no_mangle)]
241pub unsafe extern "C" fn thrd_detach(thrd: thrd_t) -> c_int {
242 if unsafe { pthread_detach(thrd) } == 0 {
243 thrd_success
244 } else {
245 thrd_error
246 }
247}
248
249#[unsafe(no_mangle)]
251pub extern "C" fn thrd_equal(thrd1: thrd_t, thrd2: thrd_t) -> c_int {
252 pthread_equal(thrd1, thrd2)
253}
254
255#[unsafe(no_mangle)]
257pub unsafe extern "C" fn thrd_exit(ret: c_int) -> ! {
258 unsafe { pthread_exit(ret as *mut c_void) }
259}
260
261#[unsafe(no_mangle)]
263pub unsafe extern "C" fn thrd_join(thrd: thrd_t, retval: *mut c_int) -> c_int {
264 if unsafe { pthread_join(thrd, retval.cast::<*mut c_void>()) } == 0 {
265 thrd_success
266 } else {
267 thrd_error
268 }
269}
270
271#[unsafe(no_mangle)]
273pub unsafe extern "C" fn thrd_sleep(time1: ×pec, time2: *mut timespec) -> c_int {
274 ERRNO.set(0);
275 let ret = clock_nanosleep(CLOCK_REALTIME, 0, time1, time2);
276 let new_errno = ERRNO.get();
277 match ret {
278 0 => 0,
279 -1 if new_errno == EINTR => -1,
280 _ => -2,
281 }
282}
283
284#[unsafe(no_mangle)]
286pub unsafe extern "C" fn thrd_yield() {
287 sched_yield();
288}
289
290#[unsafe(no_mangle)]
292pub unsafe extern "C" fn tss_create(tss: *mut tss_t, dtor: tss_dtor_t) -> c_int {
293 if unsafe { pthread_key_create(tss.cast::<pthread_key_t>(), dtor) } == 0 {
294 thrd_success
295 } else {
296 thrd_error
297 }
298}
299
300#[unsafe(no_mangle)]
302pub unsafe extern "C" fn tss_delete(tss: tss_t) {
303 unsafe {
305 pthread_key_delete(tss);
306 }
307}
308
309#[unsafe(no_mangle)]
311pub unsafe extern "C" fn tss_get(tss: tss_t) -> *mut c_void {
312 unsafe { pthread_getspecific(tss) }
314}
315
316#[unsafe(no_mangle)]
318pub unsafe extern "C" fn tss_set(tss: tss_t, value: *mut c_void) -> c_int {
319 if unsafe { pthread_setspecific(tss, value) } == 0 {
321 thrd_success
322 } else {
323 thrd_error
324 }
325}