From 8aae8e1564dff0e6abd9c258236b9de8980bf086 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Dec 2018 11:27:44 -0700 Subject: [PATCH] Add PTE Add sys_timeb header --- .gitmodules | 3 + Makefile | 14 +- include/bits/errno.h | 2 + pthreads-emb | 1 + src/header/mod.rs | 1 + src/header/sys_time/mod.rs | 1 + src/header/sys_timeb/cbindgen.toml | 7 + src/header/sys_timeb/mod.rs | 29 +++ src/platform/redox/mod.rs | 1 + src/platform/redox/pte.rs | 352 +++++++++++++++++++++++++++++ 10 files changed, 410 insertions(+), 1 deletion(-) create mode 160000 pthreads-emb create mode 100644 src/header/sys_timeb/cbindgen.toml create mode 100644 src/header/sys_timeb/mod.rs create mode 100644 src/platform/redox/pte.rs diff --git a/.gitmodules b/.gitmodules index 1476a84826..f4880e3f48 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "posix-regex"] path = posix-regex url = https://gitlab.redox-os.org/redox-os/posix-regex.git +[submodule "pthreads-emb"] + path = pthreads-emb + url = https://gitlab.redox-os.org/redox-os/pthreads-emb.git diff --git a/Makefile b/Makefile index 09cb3f0aa7..de0100e6c8 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ SRC=\ .PHONY: all clean fmt include install libc libm test -all: | libc libm +all: | libc libm libpthread clean: $(CARGO) clean @@ -61,6 +61,8 @@ libc: $(BUILD)/release/libc.a $(BUILD)/release/crt0.o $(BUILD)/release/crti.o $( libm: $(BUILD)/openlibm/libopenlibm.a +libpthread: $(BUILD)/pthreads-emb/libpthread.a + sysroot: all rm -rf $@ rm -rf $@.partial @@ -112,3 +114,13 @@ $(BUILD)/openlibm: openlibm $(BUILD)/openlibm/libopenlibm.a: $(BUILD)/openlibm $(BUILD)/include make CC=$(CC) CPPFLAGS="-fno-stack-protector -I$(shell pwd)/include -I $(shell pwd)/$(BUILD)/include" -C $< libopenlibm.a + +$(BUILD)/pthreads-emb: pthreads-emb + rm -rf $@ $@.partial + mkdir -p $(BUILD) + cp -r $< $@.partial + mv $@.partial $@ + touch $@ + +$(BUILD)/pthreads-emb/libpthread.a: $(BUILD)/pthreads-emb $(BUILD)/include + make CC=$(CC) CFLAGS="-fno-stack-protector -I$(shell pwd)/include -I $(shell pwd)/$(BUILD)/include" -C $< libpthread.a diff --git a/include/bits/errno.h b/include/bits/errno.h index c8594c12f7..d59af2876a 100644 --- a/include/bits/errno.h +++ b/include/bits/errno.h @@ -5,6 +5,8 @@ extern "C" { #endif +#define ENOTSUP EOPNOTSUPP + //TODO extern __thread int errno; extern int errno; diff --git a/pthreads-emb b/pthreads-emb new file mode 160000 index 0000000000..6720dfdc95 --- /dev/null +++ b/pthreads-emb @@ -0,0 +1 @@ +Subproject commit 6720dfdc95246f85aeb1e867e0105d4eb43ad759 diff --git a/src/header/mod.rs b/src/header/mod.rs index 5c097d55f5..b834a0f65a 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -36,6 +36,7 @@ pub mod sys_select; pub mod sys_socket; pub mod sys_stat; pub mod sys_time; +pub mod sys_timeb; //pub mod sys_times; pub mod sys_un; pub mod sys_utsname; diff --git a/src/header/sys_time/mod.rs b/src/header/sys_time/mod.rs index f3a96d9669..efa185ff40 100644 --- a/src/header/sys_time/mod.rs +++ b/src/header/sys_time/mod.rs @@ -16,6 +16,7 @@ pub struct timeval { pub tv_usec: suseconds_t, } #[repr(C)] +#[derive(Default)] pub struct timezone { pub tz_minuteswest: c_int, pub tz_dsttime: c_int, diff --git a/src/header/sys_timeb/cbindgen.toml b/src/header/sys_timeb/cbindgen.toml new file mode 100644 index 0000000000..1f27a3625a --- /dev/null +++ b/src/header/sys_timeb/cbindgen.toml @@ -0,0 +1,7 @@ +sys_includes = ["sys/types.h"] +include_guard = "_SYS_TIMEB_H" +language = "C" +style = "Tag" + +[enum] +prefix_with_name = true diff --git a/src/header/sys_timeb/mod.rs b/src/header/sys_timeb/mod.rs new file mode 100644 index 0000000000..4c1489f70f --- /dev/null +++ b/src/header/sys_timeb/mod.rs @@ -0,0 +1,29 @@ +//! sys/time implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/systime.h.html + +use header::sys_time::{gettimeofday, timeval, timezone}; +use platform::types::*; + +#[repr(C)] +#[derive(Default)] +pub struct timeb { + pub time: time_t, + pub millitm: c_ushort, + pub timezone: c_short, + pub dstflag: c_short, +} + +#[no_mangle] +pub unsafe extern "C" fn ftime(tp: *mut timeb) -> c_int { + let mut tv = timeval::default(); + let mut tz = timezone::default(); + if gettimeofday(&mut tv, &mut tz) < 0 { + return -1; + } + + (*tp).time = tv.tv_sec; + (*tp).millitm = (tv.tv_usec/1000) as c_ushort; + (*tp).timezone = tz.tz_minuteswest as c_short; + (*tp).dstflag = tz.tz_dsttime as c_short; + + 0 +} diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 106cdd9747..4443aef4f9 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -28,6 +28,7 @@ use io::{self, BufReader, SeekFrom}; use super::types::*; use super::{errno, Pal, Read}; +mod pte; mod signal; mod socket; diff --git a/src/platform/redox/pte.rs b/src/platform/redox/pte.rs new file mode 100644 index 0000000000..ba6309a88c --- /dev/null +++ b/src/platform/redox/pte.rs @@ -0,0 +1,352 @@ +use alloc::boxed::Box; +use alloc::collections::BTreeMap; +use core::{mem, intrinsics, ptr}; +use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; +use syscall; + +use platform::types::{c_int, c_uint, c_void}; + +type pte_osThreadHandle = usize; +type pte_osMutexHandle = *mut i32; +type pte_osSemaphoreHandle = *mut i32; +type pte_osThreadEntryPoint = unsafe extern "C" fn(params: *mut c_void) -> c_int; + +#[repr(C)] +pub enum pte_osResult { + PTE_OS_OK = 0, + PTE_OS_NO_RESOURCES, + PTE_OS_GENERAL_FAILURE, + PTE_OS_TIMEOUT, + PTE_OS_INTERRUPTED, + PTE_OS_INVALID_PARAM +} + +use self::pte_osResult::*; + +static mut pid_mutexes: Option> = None; +static mut pid_mutexes_lock: i32 = 0; + +#[thread_local] +static mut LOCALS: *mut BTreeMap = ptr::null_mut(); + +static NEXT_KEY: AtomicUsize = ATOMIC_USIZE_INIT; + +unsafe fn locals() -> &'static mut BTreeMap { + if LOCALS == ptr::null_mut() { + LOCALS = Box::into_raw(Box::new(BTreeMap::new())); + } + &mut *LOCALS +} + +// pte_osResult pte_osInit(void) +#[no_mangle] +pub unsafe extern "C" fn pte_osInit() -> pte_osResult { + PTE_OS_OK +} + +/* +pte_osResult pte_osThreadCreate(pte_osThreadEntryPoint entryPoint, + int stackSize, + int initialPriority, + void *argv, + pte_osThreadHandle* ppte_osThreadHandle) +*/ + +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadCreate(entryPoint: pte_osThreadEntryPoint, + _stackSize: c_int, + _initialPriority: c_int, + argv: *mut c_void, + ppte_osThreadHandle: *mut pte_osThreadHandle + ) -> pte_osResult { + // XXX error handling + let id = syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES).unwrap(); + + let mutex = Box::into_raw(Box::new(0)); + pte_osMutexLock(mutex); + + if id == 0 { + // Wait until pte_osThreadStart + pte_osMutexLock(mutex); + entryPoint(argv); + let _ = syscall::exit(0); + } else { + pte_osMutexLock(&mut pid_mutexes_lock); + if pid_mutexes.is_none() { + pid_mutexes = Some(BTreeMap::new()); + } + pid_mutexes.as_mut().unwrap().insert(id, mutex); + pte_osMutexUnlock(&mut pid_mutexes_lock); + *ppte_osThreadHandle = id; + } + PTE_OS_OK +} + +// pte_osResult pte_osThreadStart(pte_osThreadHandle osThreadHandle) +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadStart(handle: pte_osThreadHandle) -> pte_osResult { + let mut ret = PTE_OS_GENERAL_FAILURE; + pte_osMutexLock(&mut pid_mutexes_lock); + if let Some(ref mutexes) = pid_mutexes { + if let Some(mutex) = mutexes.get(&handle) { + pte_osMutexUnlock(*mutex); + ret = PTE_OS_OK; + } + } + pte_osMutexUnlock(&mut pid_mutexes_lock); + ret +} + +/* +void pte_osThreadExit() +pte_osResult pte_osThreadExitAndDelete(pte_osThreadHandle handle) +pte_osResult pte_osThreadDelete(pte_osThreadHandle handle) +*/ +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadExit() { + syscall::exit(0); +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadExitAndDelete(handle: pte_osThreadHandle) -> pte_osResult { + pte_osThreadDelete(handle); + syscall::exit(0); + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadDelete(handle: pte_osThreadHandle) -> pte_osResult { + pte_osMutexLock(&mut pid_mutexes_lock); + if let Some(ref mut mutexes) = pid_mutexes { + if let Some(mutex) = mutexes.remove(&handle) { + Box::from_raw(mutex); + } + } + pte_osMutexUnlock(&mut pid_mutexes_lock); + PTE_OS_OK +} + +// pte_osResult pte_osThreadWaitForEnd(pte_osThreadHandle threadHandle) +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadWaitForEnd(handle: pte_osThreadHandle) -> pte_osResult { + let mut status = 0; + syscall::waitpid(handle, &mut status, 0); + PTE_OS_OK +} + +// pte_osResult pte_osThreadCancel(pte_osThreadHandle threadHandle) + +// pte_osResult pte_osThreadCheckCancel(pte_osThreadHandle threadHandle) + +//void pte_osThreadSleep(unsigned int msecs) +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadSleep(msecs: c_uint) { + let tm = syscall::TimeSpec { + tv_sec: msecs as i64 / 1000, + tv_nsec: (msecs as i32 % 1000) * 1000, + }; + let mut rmtp = mem::uninitialized(); + let _ = syscall::nanosleep(&tm, &mut rmtp); +} + +// pte_osThreadHandle pte_osThreadGetHandle(void) +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadGetHandle() -> pte_osThreadHandle { + syscall::getpid().unwrap() +} + +/* +int pte_osThreadGetPriority(pte_osThreadHandle threadHandle) +pte_osResult pte_osThreadSetPriority(pte_osThreadHandle threadHandle, int newPriority) +int pte_osThreadGetMinPriority() +int pte_osThreadGetMaxPriority() +int pte_osThreadGetDefaultPriority() +*/ + +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadGetPriority(threadHandle: pte_osThreadHandle) -> c_int { + // XXX Shouldn't Redox support priorities? + 1 +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadSetPriority(threadHandle: pte_osThreadHandle, newPriority: c_int) -> pte_osResult { + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadGetMinPriority() -> c_int { + 1 +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadGetMaxPriority() -> c_int { + 1 +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osThreadGetDefaultPriority() -> c_int { + 1 +} + +/* +pte_osResult pte_osMutexCreate(pte_osMutexHandle *pHandle) +pte_osResult pte_osMutexDelete(pte_osMutexHandle handle) +pte_osResult pte_osMutexLock(pte_osMutexHandle handle) +pte_osResult pte_osMutexUnlock(pte_osMutexHandle handle) +*/ + +#[no_mangle] +pub unsafe extern "C" fn pte_osMutexCreate(pHandle: *mut pte_osMutexHandle) -> pte_osResult { + *pHandle = Box::into_raw(Box::new(0)); + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osMutexDelete(handle: pte_osMutexHandle) -> pte_osResult { + Box::from_raw(handle); + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osMutexLock(handle: pte_osMutexHandle) -> pte_osResult { + let mut c = 0; + for _i in 0..100 { + c = intrinsics::atomic_cxchg(handle, 0, 1).0; + if c == 0 { + break; + } + } + if c == 1 { + c = intrinsics::atomic_xchg(handle, 2); + } + while c != 0 { + let _ = syscall::futex(handle, syscall::FUTEX_WAIT, 2, 0, ptr::null_mut()); + c = intrinsics::atomic_xchg(handle, 2); + } + + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osMutexUnlock(handle: pte_osMutexHandle) -> pte_osResult { + if *handle == 2 { + *handle = 0; + } else if intrinsics::atomic_xchg(handle, 0) == 1 { + return PTE_OS_OK; + } + for _i in 0..100 { + if *handle != 0 { + if intrinsics::atomic_cxchg(handle, 1, 2).0 != 0 { + return PTE_OS_OK; + } + } + } + let _ = syscall::futex(handle, syscall::FUTEX_WAKE, 1, 0, ptr::null_mut()); + + PTE_OS_OK +} + +/* +pte_osResult pte_osSemaphoreCreate(int initialValue, pte_osSemaphoreHandle *pHandle) +pte_osResult pte_osSemaphoreDelete(pte_osSemaphoreHandle handle) +pte_osResult pte_osSemaphorePost(pte_osSemaphoreHandle handle, int count) +pte_osResult pte_osSemaphorePend(pte_osSemaphoreHandle handle, unsigned int *pTimeoutMsecs) +pte_osResult pte_osSemaphoreCancellablePend(pte_osSemaphoreHandle semHandle, unsigned int *pTimeout) +*/ + +#[no_mangle] +pub unsafe extern "C" fn pte_osSemaphoreCreate(initialValue: c_int, pHandle: *mut pte_osSemaphoreHandle) -> pte_osResult { + *pHandle = Box::into_raw(Box::new(initialValue)); + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osSemaphoreDelete(handle: pte_osSemaphoreHandle) -> pte_osResult { + Box::from_raw(handle); + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osSemaphorePost(handle: pte_osSemaphoreHandle, count: c_int) -> pte_osResult { + if intrinsics::atomic_xadd(handle, 1) <= 0 { + while match syscall::futex(handle, syscall::FUTEX_WAKE, 1, 0, ptr::null_mut()) { + Ok(waiters) => waiters < 1, + Err(err) => return PTE_OS_GENERAL_FAILURE, + } { + syscall::sched_yield(); + } + } + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osSemaphorePend(handle: pte_osSemaphoreHandle, pTimeout: *mut c_uint) -> pte_osResult { + if intrinsics::atomic_xsub(handle, 1) < 0 { + let _ = syscall::futex(handle, syscall::FUTEX_WAIT, *handle, 0, ptr::null_mut()); + } + PTE_OS_OK +} + +/* +int pte_osAtomicExchange(int *ptarg, int val) +int pte_osAtomicCompareExchange(int *pdest, int exchange, int comp) +int pte_osAtomicExchangeAdd(int volatile* pAddend, int value) +int pte_osAtomicDecrement(int *pdest) +int pte_osAtomicIncrement(int *pdest) +*/ + +#[no_mangle] +pub unsafe extern "C" fn pte_osAtomicExchange(ptarg: *mut c_int, val: c_int) -> c_int { + intrinsics::atomic_xchg(ptarg, val) +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osAtomicCompareExchange(pdest: *mut c_int, exchange: c_int, comp: c_int) -> c_int { + intrinsics::atomic_cxchg(pdest, comp, exchange).0 +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osAtomicExchangeAdd(pAppend: *mut c_int, value: c_int) -> c_int { + intrinsics::atomic_xadd(pAppend, value) +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osAtomicDecrement(pdest: *mut c_int) -> c_int { + intrinsics::atomic_xadd(pdest, -1) - 1 +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osAtomicIncrement(pdest: *mut c_int) -> c_int { + intrinsics::atomic_xadd(pdest, 1) + 1 +} + +/* +pte_osResult pte_osTlsSetValue(unsigned int index, void * value) +void * pte_osTlsGetValue(unsigned int index) +pte_osResult pte_osTlsAlloc(unsigned int *pKey) +pte_osResult pte_osTlsFree(unsigned int index) +*/ + +#[no_mangle] +pub unsafe extern "C" fn pte_osTlsSetValue(index: c_uint, value: *mut c_void) -> pte_osResult { + locals().insert(index, value); + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osTlsGetValue(index: c_uint) -> *mut c_void { + locals().get_mut(&index).map(|x| *x).unwrap_or(ptr::null_mut()) +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osTlsAlloc(pKey: *mut c_uint) -> pte_osResult { + NEXT_KEY.fetch_add(1, Ordering::SeqCst); + PTE_OS_OK +} + +#[no_mangle] +pub unsafe extern "C" fn pte_osTlsFree(index: c_uint) -> pte_osResult { + // XXX free keys + PTE_OS_OK +}