pte.rs 11 KB

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