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