xref: /relibc/src/platform/pte.rs (revision 1a0edd8eeb2e3aae407a91795696461f475b445e)
1 #![allow(non_snake_case)]
2 
3 use alloc::{boxed::Box, collections::BTreeMap};
4 use core::{
5     intrinsics, ptr,
6     sync::atomic::{AtomicU32, Ordering},
7 };
8 
9 use crate::{
10     header::{sys_mman, time::timespec},
11     ld_so::{
12         linker::Linker,
13         tcb::{Master, Tcb},
14     },
15     platform::{
16         types::{c_int, c_uint, c_void, pid_t, size_t},
17         Pal, Sys,
18     },
19     sync::{Mutex, Semaphore},
20     ALLOCATOR,
21 };
22 
23 type pte_osThreadHandle = pid_t;
24 type pte_osMutexHandle = *mut Mutex<()>;
25 type pte_osSemaphoreHandle = *mut Semaphore;
26 type pte_osThreadEntryPoint = unsafe extern "C" fn(params: *mut c_void) -> *mut c_void;
27 
28 #[repr(C)]
29 #[derive(Eq, PartialEq)]
30 #[allow(dead_code)]
31 pub enum pte_osResult {
32     PTE_OS_OK = 0,
33     PTE_OS_NO_RESOURCES,
34     PTE_OS_GENERAL_FAILURE,
35     PTE_OS_TIMEOUT,
36     PTE_OS_INTERRUPTED,
37     PTE_OS_INVALID_PARAM,
38 }
39 
40 use self::pte_osResult::*;
41 
42 static mut pid_mutexes: Option<BTreeMap<pte_osThreadHandle, pte_osMutexHandle>> = None;
43 static mut pid_mutexes_lock: Mutex<()> = Mutex::new(());
44 
45 static mut pid_stacks: Option<BTreeMap<pte_osThreadHandle, (*mut c_void, size_t)>> = None;
46 static mut pid_stacks_lock: Mutex<()> = Mutex::new(());
47 
48 #[thread_local]
49 static mut LOCALS: *mut BTreeMap<c_uint, *mut c_void> = ptr::null_mut();
50 
51 static NEXT_KEY: AtomicU32 = AtomicU32::new(0);
52 
53 unsafe fn locals() -> &'static mut BTreeMap<c_uint, *mut c_void> {
54     if LOCALS.is_null() {
55         LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
56     }
57     &mut *LOCALS
58 }
59 
60 // pte_osResult pte_osInit(void)
61 #[no_mangle]
62 pub unsafe extern "C" fn pte_osInit() -> pte_osResult {
63     PTE_OS_OK
64 }
65 
66 /// A shim to wrap thread entry points in logic to set up TLS, for example
67 unsafe extern "C" fn pte_osThreadShim(
68     entryPoint: pte_osThreadEntryPoint,
69     argv: *mut c_void,
70     mutex: pte_osMutexHandle,
71     tls_size: usize,
72     tls_masters_ptr: *mut Master,
73     tls_masters_len: usize,
74     tls_linker_ptr: *const Mutex<Linker>,
75     tls_mspace: usize,
76 ) {
77     // The kernel allocated TLS does not have masters set, so do not attempt to copy it.
78     // It will be copied by the kernel.
79     if !tls_masters_ptr.is_null() {
80         let tcb = Tcb::new(tls_size).unwrap();
81         tcb.masters_ptr = tls_masters_ptr;
82         tcb.masters_len = tls_masters_len;
83         tcb.linker_ptr = tls_linker_ptr;
84         tcb.mspace = tls_mspace;
85         tcb.copy_masters().unwrap();
86         tcb.activate();
87     }
88 
89     // Wait until pte_osThreadStart
90     pte_osMutexLock(mutex);
91     entryPoint(argv);
92     pte_osThreadExit();
93 }
94 
95 #[no_mangle]
96 pub unsafe extern "C" fn pte_osThreadCreate(
97     entryPoint: pte_osThreadEntryPoint,
98     stackSize: c_int,
99     _initialPriority: c_int,
100     argv: *mut c_void,
101     ppte_osThreadHandle: *mut pte_osThreadHandle,
102 ) -> pte_osResult {
103     // Create a locked mutex, unlocked by pte_osThreadStart
104     let mutex: pte_osMutexHandle = Box::into_raw(Box::new(Mutex::locked(())));
105 
106     let stack_size = if stackSize == 0 {
107         1024 * 1024
108     } else {
109         stackSize as usize
110     };
111     let stack_base = sys_mman::mmap(
112         ptr::null_mut(),
113         stack_size,
114         sys_mman::PROT_READ | sys_mman::PROT_WRITE,
115         sys_mman::MAP_SHARED | sys_mman::MAP_ANONYMOUS,
116         -1,
117         0,
118     );
119     if stack_base as isize == -1 {
120         return PTE_OS_GENERAL_FAILURE;
121     }
122     ptr::write_bytes(stack_base as *mut u8, 0, stack_size);
123     let stack_end = stack_base.add(stack_size);
124     let mut stack = stack_end as *mut usize;
125     {
126         let mut push = |value: usize| {
127             stack = stack.offset(-1);
128             *stack = value;
129         };
130 
131         //WARNING: Stack must be 128-bit aligned for SSE
132         if let Some(tcb) = Tcb::current() {
133             push(tcb.mspace as usize);
134             push(tcb.linker_ptr as usize);
135             push(tcb.masters_len);
136             push(tcb.masters_ptr as usize);
137             push(tcb.tls_len);
138         } else {
139             push(ALLOCATOR.get_book_keeper());
140             push(0);
141             push(0);
142             push(0);
143             push(0);
144         }
145 
146         push(mutex as usize);
147 
148         push(argv as usize);
149         push(entryPoint as usize);
150 
151         push(pte_osThreadShim as usize);
152     }
153 
154     let id = Sys::pte_clone(stack);
155     if id < 0 {
156         return PTE_OS_GENERAL_FAILURE;
157     }
158 
159     pte_osMutexLock(&mut pid_mutexes_lock);
160     if pid_mutexes.is_none() {
161         pid_mutexes = Some(BTreeMap::new());
162     }
163     pid_mutexes.as_mut().unwrap().insert(id, mutex);
164     pte_osMutexUnlock(&mut pid_mutexes_lock);
165 
166     pte_osMutexLock(&mut pid_stacks_lock);
167     if pid_stacks.is_none() {
168         pid_stacks = Some(BTreeMap::new());
169     }
170     pid_stacks
171         .as_mut()
172         .unwrap()
173         .insert(id, (stack_base, stack_size));
174     pte_osMutexUnlock(&mut pid_stacks_lock);
175 
176     *ppte_osThreadHandle = id;
177 
178     PTE_OS_OK
179 }
180 
181 #[no_mangle]
182 pub unsafe extern "C" fn pte_osThreadStart(handle: pte_osThreadHandle) -> pte_osResult {
183     let mut ret = PTE_OS_GENERAL_FAILURE;
184     pte_osMutexLock(&mut pid_mutexes_lock);
185     if let Some(ref mutexes) = pid_mutexes {
186         if let Some(mutex) = mutexes.get(&handle) {
187             pte_osMutexUnlock(*mutex);
188             ret = PTE_OS_OK;
189         }
190     }
191     pte_osMutexUnlock(&mut pid_mutexes_lock);
192     ret
193 }
194 
195 #[no_mangle]
196 pub unsafe extern "C" fn pte_osThreadExit() {
197     Sys::exit(0);
198 }
199 
200 #[no_mangle]
201 pub unsafe extern "C" fn pte_osThreadExitAndDelete(handle: pte_osThreadHandle) -> pte_osResult {
202     let res = pte_osThreadDelete(handle);
203     if res != PTE_OS_OK {
204         return res;
205     }
206     pte_osThreadExit();
207     PTE_OS_OK
208 }
209 
210 #[no_mangle]
211 pub unsafe extern "C" fn pte_osThreadDelete(handle: pte_osThreadHandle) -> pte_osResult {
212     pte_osMutexLock(&mut pid_mutexes_lock);
213     if let Some(ref mut mutexes) = pid_mutexes {
214         if let Some(mutex) = mutexes.remove(&handle) {
215             Box::from_raw(mutex);
216         }
217     }
218     pte_osMutexUnlock(&mut pid_mutexes_lock);
219 
220     pte_osMutexLock(&mut pid_stacks_lock);
221     if let Some(ref mut stacks) = pid_stacks {
222         if let Some((stack_base, stack_size)) = stacks.remove(&handle) {
223             //TODO: this currently unmaps the thread's stack, while it is being used!
224             //sys_mman::munmap(stack_base, stack_size);
225         }
226     }
227     pte_osMutexUnlock(&mut pid_stacks_lock);
228 
229     PTE_OS_OK
230 }
231 
232 #[no_mangle]
233 pub unsafe extern "C" fn pte_osThreadWaitForEnd(handle: pte_osThreadHandle) -> pte_osResult {
234     let mut status = 0;
235     Sys::waitpid(handle, &mut status, 0);
236     PTE_OS_OK
237 }
238 
239 #[no_mangle]
240 pub unsafe extern "C" fn pte_osThreadCancel(handle: pte_osThreadHandle) -> pte_osResult {
241     //TODO: allow cancel of thread
242     PTE_OS_OK
243 }
244 
245 #[no_mangle]
246 pub unsafe extern "C" fn pte_osThreadCheckCancel(handle: pte_osThreadHandle) -> pte_osResult {
247     PTE_OS_OK
248 }
249 
250 #[no_mangle]
251 pub unsafe extern "C" fn pte_osThreadSleep(msecs: c_uint) {
252     let tm = timespec {
253         tv_sec: msecs as i64 / 1000,
254         tv_nsec: (msecs % 1000) as i64 * 1000000,
255     };
256     Sys::nanosleep(&tm, ptr::null_mut());
257 }
258 
259 #[no_mangle]
260 pub unsafe extern "C" fn pte_osThreadGetHandle() -> pte_osThreadHandle {
261     Sys::gettid()
262 }
263 
264 #[no_mangle]
265 pub unsafe extern "C" fn pte_osThreadGetPriority(threadHandle: pte_osThreadHandle) -> c_int {
266     // XXX Shouldn't Redox support priorities?
267     1
268 }
269 
270 #[no_mangle]
271 pub unsafe extern "C" fn pte_osThreadSetPriority(
272     threadHandle: pte_osThreadHandle,
273     newPriority: c_int,
274 ) -> pte_osResult {
275     PTE_OS_OK
276 }
277 
278 #[no_mangle]
279 pub unsafe extern "C" fn pte_osThreadGetMinPriority() -> c_int {
280     1
281 }
282 
283 #[no_mangle]
284 pub unsafe extern "C" fn pte_osThreadGetMaxPriority() -> c_int {
285     1
286 }
287 
288 #[no_mangle]
289 pub unsafe extern "C" fn pte_osThreadGetDefaultPriority() -> c_int {
290     1
291 }
292 
293 #[no_mangle]
294 pub unsafe extern "C" fn pte_osMutexCreate(pHandle: *mut pte_osMutexHandle) -> pte_osResult {
295     *pHandle = Box::into_raw(Box::new(Mutex::new(())));
296     PTE_OS_OK
297 }
298 
299 #[no_mangle]
300 pub unsafe extern "C" fn pte_osMutexDelete(handle: pte_osMutexHandle) -> pte_osResult {
301     Box::from_raw(handle);
302     PTE_OS_OK
303 }
304 
305 #[no_mangle]
306 pub unsafe extern "C" fn pte_osMutexLock(handle: pte_osMutexHandle) -> pte_osResult {
307     (*handle).manual_lock();
308     PTE_OS_OK
309 }
310 
311 #[no_mangle]
312 pub unsafe extern "C" fn pte_osMutexUnlock(handle: pte_osMutexHandle) -> pte_osResult {
313     (*handle).manual_unlock();
314     PTE_OS_OK
315 }
316 
317 #[no_mangle]
318 pub unsafe extern "C" fn pte_osSemaphoreCreate(
319     initialValue: c_int,
320     pHandle: *mut pte_osSemaphoreHandle,
321 ) -> pte_osResult {
322     *pHandle = Box::into_raw(Box::new(Semaphore::new(initialValue)));
323     PTE_OS_OK
324 }
325 
326 #[no_mangle]
327 pub unsafe extern "C" fn pte_osSemaphoreDelete(handle: pte_osSemaphoreHandle) -> pte_osResult {
328     Box::from_raw(handle);
329     PTE_OS_OK
330 }
331 
332 #[no_mangle]
333 pub unsafe extern "C" fn pte_osSemaphorePost(
334     handle: pte_osSemaphoreHandle,
335     count: c_int,
336 ) -> pte_osResult {
337     (*handle).post();
338     PTE_OS_OK
339 }
340 
341 #[no_mangle]
342 pub unsafe extern "C" fn pte_osSemaphorePend(
343     handle: pte_osSemaphoreHandle,
344     pTimeout: *mut c_uint,
345 ) -> pte_osResult {
346     //TODO: pTimeout
347     (*handle).wait();
348     PTE_OS_OK
349 }
350 
351 #[no_mangle]
352 pub unsafe extern "C" fn pte_osSemaphoreCancellablePend(
353     handle: pte_osSemaphoreHandle,
354     pTimeout: *mut c_uint,
355 ) -> pte_osResult {
356     //TODO
357     pte_osSemaphorePend(handle, pTimeout)
358 }
359 
360 #[no_mangle]
361 pub unsafe extern "C" fn pte_osAtomicExchange(ptarg: *mut c_int, val: c_int) -> c_int {
362     intrinsics::atomic_xchg(ptarg, val)
363 }
364 
365 #[no_mangle]
366 pub unsafe extern "C" fn pte_osAtomicCompareExchange(
367     pdest: *mut c_int,
368     exchange: c_int,
369     comp: c_int,
370 ) -> c_int {
371     intrinsics::atomic_cxchg(pdest, comp, exchange).0
372 }
373 
374 #[no_mangle]
375 pub unsafe extern "C" fn pte_osAtomicExchangeAdd(pAppend: *mut c_int, value: c_int) -> c_int {
376     intrinsics::atomic_xadd(pAppend, value)
377 }
378 
379 #[no_mangle]
380 pub unsafe extern "C" fn pte_osAtomicDecrement(pdest: *mut c_int) -> c_int {
381     intrinsics::atomic_xadd(pdest, -1) - 1
382 }
383 
384 #[no_mangle]
385 pub unsafe extern "C" fn pte_osAtomicIncrement(pdest: *mut c_int) -> c_int {
386     intrinsics::atomic_xadd(pdest, 1) + 1
387 }
388 
389 #[no_mangle]
390 pub unsafe extern "C" fn pte_osTlsSetValue(index: c_uint, value: *mut c_void) -> pte_osResult {
391     locals().insert(index, value);
392     PTE_OS_OK
393 }
394 
395 #[no_mangle]
396 pub unsafe extern "C" fn pte_osTlsGetValue(index: c_uint) -> *mut c_void {
397     locals().get_mut(&index).copied().unwrap_or(ptr::null_mut())
398 }
399 
400 #[no_mangle]
401 pub unsafe extern "C" fn pte_osTlsAlloc(pKey: *mut c_uint) -> pte_osResult {
402     *pKey = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
403     PTE_OS_OK
404 }
405 
406 #[no_mangle]
407 pub unsafe extern "C" fn pte_osTlsFree(index: c_uint) -> pte_osResult {
408     // XXX free keys
409     PTE_OS_OK
410 }
411