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