diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index 9ae6e81ad..d16458585 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -94,7 +94,8 @@ orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr name, switch (attrs & (kEvfAttrSingle | kEvfAttrMulti)) { case 0: case kEvfAttrSingle | kEvfAttrMulti: - return ErrorCode::INVAL; + attrs = (attrs & ~(kEvfAttrSingle | kEvfAttrMulti)) | kEvfAttrSingle; + break; default: break; @@ -103,7 +104,11 @@ orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr name, switch (attrs & (kEvfAttrThPrio | kEvfAttrThFifo)) { case 0: case kEvfAttrThPrio | kEvfAttrThFifo: - return ErrorCode::INVAL; + attrs = (attrs & ~(kEvfAttrThPrio | kEvfAttrThFifo)) | kEvfAttrThFifo; + break; + + default: + break; } char _name[32]; diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index 6c134904e..ab784d992 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -36,12 +36,6 @@ static int g_gpuPid; -struct ThreadParam { - void (*startFunc)(void *); - void *arg; - orbis::Thread *thread; -}; - static void printStackTrace(ucontext_t *context, int fileno) { unw_cursor_t cursor; @@ -158,19 +152,10 @@ static void printStackTrace(ucontext_t *context, orbis::Thread *thread, __attribute__((no_stack_protector)) static void handle_signal(int sig, siginfo_t *info, void *ucontext) { - std::uint64_t hostFs = _readgsbase_u64(); - if (hostFs != 0) { + if (auto hostFs = _readgsbase_u64()) { _writefsbase_u64(hostFs); } - if (sig == SIGSYS) { - auto prevContext = std::exchange(rx::thread::g_current->context, ucontext); - orbis::syscall_entry(rx::thread::g_current); - rx::thread::g_current->context = prevContext; - _writefsbase_u64(rx::thread::g_current->fsBase); - return; - } - if (g_gpuPid > 0) { // stop gpu thread ::kill(g_gpuPid, SIGINT); @@ -234,14 +219,9 @@ static void setupSigHandlers() { exit(EXIT_FAILURE); } - struct sigaction act; - sigset_t mask; - memset(&act, 0, sizeof(act)); - sigemptyset(&mask); - + struct sigaction act{}; act.sa_sigaction = handle_signal; act.sa_flags = SA_SIGINFO | SA_ONSTACK; - act.sa_mask = mask; if (sigaction(SIGSYS, &act, NULL)) { perror("Error sigaction:"); @@ -367,22 +347,22 @@ static int ps4Exec(orbis::Process *mainProcess, mainProcess->sysent = &orbis::ps4_sysvec; mainProcess->ops = &rx::procOpsTable; - orbis::Thread mainThread; - mainThread.tproc = mainProcess; - mainThread.tid = mainProcess->pid; - mainThread.state = orbis::ThreadState::RUNNING; + auto [baseId, mainThread] = mainProcess->threadsMap.emplace(); + mainThread->tproc = mainProcess; + mainThread->tid = mainProcess->pid + baseId; + mainThread->state = orbis::ThreadState::RUNNING; const auto stackEndAddress = 0x7'ffff'c000ull; const auto stackSize = 0x40000 * 16; auto stackStartAddress = stackEndAddress - stackSize; - mainThread.stackStart = + mainThread->stackStart = rx::vm::map(reinterpret_cast(stackStartAddress), stackSize, rx::vm::kMapProtCpuWrite | rx::vm::kMapProtCpuRead, rx::vm::kMapFlagAnonymous | rx::vm::kMapFlagFixed | rx::vm::kMapFlagPrivate | rx::vm::kMapFlagStack); - mainThread.stackEnd = - reinterpret_cast(mainThread.stackStart) + stackSize; + mainThread->stackEnd = + reinterpret_cast(mainThread->stackStart) + stackSize; rx::vfs::mount("/dev/dmem0", createDmemCharacterDevice(0)); rx::vfs::mount("/dev/dmem1", createDmemCharacterDevice(1)); @@ -402,9 +382,9 @@ static int ps4Exec(orbis::Process *mainProcess, rx::vfs::mount("/dev/gc", createGcCharacterDevice()); rx::vfs::mount("/dev/rng", createRngCharacterDevice()); - rx::procOpsTable.open(&mainThread, "/dev/stdin", 0, 0); - rx::procOpsTable.open(&mainThread, "/dev/stdout", 0, 0); - rx::procOpsTable.open(&mainThread, "/dev/stderr", 0, 0); + rx::procOpsTable.open(mainThread, "/dev/stdin", 0, 0); + rx::procOpsTable.open(mainThread, "/dev/stdout", 0, 0); + rx::procOpsTable.open(mainThread, "/dev/stderr", 0, 0); std::vector argvOffsets; std::vector envpOffsets; @@ -415,7 +395,7 @@ static int ps4Exec(orbis::Process *mainProcess, // *reinterpret_cast( // reinterpret_cast(libkernel->base) + 0x6c2e4) = ~0; - StackWriter stack{reinterpret_cast(mainThread.stackEnd)}; + StackWriter stack{reinterpret_cast(mainThread->stackEnd)}; for (auto elem : argv) { argvOffsets.push_back(stack.pushString(elem)); @@ -469,8 +449,8 @@ static int ps4Exec(orbis::Process *mainProcess, });; context->uc_mcontext.gregs[REG_RIP] = libkernel->entryPoint; - mainThread.context = context; - rx::thread::invoke(&mainThread); + mainThread->context = context; + rx::thread::invoke(mainThread); std::abort(); } diff --git a/rpcsx-os/ops.cpp b/rpcsx-os/ops.cpp index 76c2f8e14..af2e4707e 100644 --- a/rpcsx-os/ops.cpp +++ b/rpcsx-os/ops.cpp @@ -5,13 +5,16 @@ #include "orbis/thread/Process.hpp" #include "orbis/thread/Thread.hpp" #include "orbis/utils/Rc.hpp" +#include "thread.hpp" #include "vfs.hpp" #include "vm.hpp" +#include #include #include #include #include #include +#include #include using namespace orbis; @@ -421,11 +424,52 @@ SysResult thr_create(orbis::Thread *thread, orbis::ptr ctxt, ptr arg, orbis::sint flags) { return ErrorCode::NOTSUP; } -SysResult thr_new(orbis::Thread *thread, orbis::ptr param, +SysResult thr_new(orbis::Thread *thread, orbis::ptr param, orbis::sint param_size) { + return {}; // FIXME: remove when we ready for MT + auto _param = uread(param); + + auto proc = thread->tproc; + auto [baseId, childThread] = proc->threadsMap.emplace(); + childThread->tproc = proc; + childThread->tid = proc->pid + baseId; + childThread->state = orbis::ThreadState::RUNQ; + childThread->stackStart = _param.stack_base; + childThread->stackEnd = _param.stack_base + _param.stack_size; + childThread->fsBase = reinterpret_cast(_param.tls_base); + + uwrite(_param.parent_tid, slong(childThread->tid)); + + // FIXME: implement scheduler + + std::printf("Starting child thread %lu\n", (long)(proc->pid + baseId)); + + std::thread { + [=, childThread = Ref(childThread)] { + uwrite(_param.child_tid, slong(childThread->tid)); + auto context = new ucontext_t{}; + + context->uc_mcontext.gregs[REG_RDI] = reinterpret_cast(_param.arg); + context->uc_mcontext.gregs[REG_RSI] = reinterpret_cast(_param.arg); + context->uc_mcontext.gregs[REG_RSP] = reinterpret_cast(childThread->stackEnd); + context->uc_mcontext.gregs[REG_RIP] = reinterpret_cast(_param.start_func); + + childThread->context = context; + childThread->state = orbis::ThreadState::RUNNING; + rx::thread::invoke(childThread.get()); + } + }.detach(); + return {}; } SysResult thr_exit(orbis::Thread *thread, orbis::ptr state) { + std::printf("Requested exit of thread %u, state %p\n", (unsigned)thread->tid, state); + // FIXME: do sys_mtx(WAKE) if state is not null + + // FIXME: implement exit + while (true) { + std::this_thread::sleep_for(std::chrono::seconds(60)); + } return ErrorCode::NOTSUP; } SysResult thr_kill(orbis::Thread *thread, orbis::slong id, orbis::sint sig) { diff --git a/rpcsx-os/thread.cpp b/rpcsx-os/thread.cpp index beb54945b..4a52f92c3 100644 --- a/rpcsx-os/thread.cpp +++ b/rpcsx-os/thread.cpp @@ -1,5 +1,7 @@ #include "thread.hpp" +#include "orbis/sys/sysentry.hpp" #include +#include #include #include #include @@ -15,7 +17,19 @@ struct LibcInfo { std::uint64_t textSize = 0; }; -static LibcInfo libcInfo; +LibcInfo libcInfo; + +static __attribute__((no_stack_protector)) void +handleSigSys(int sig, siginfo_t *info, void *ucontext) { + if (auto hostFs = _readgsbase_u64()) { + _writefsbase_u64(hostFs); + } + + auto prevContext = std::exchange(rx::thread::g_current->context, ucontext); + orbis::syscall_entry(rx::thread::g_current); + rx::thread::g_current->context = prevContext; + _writefsbase_u64(rx::thread::g_current->fsBase); +} void rx::thread::initialize() { auto processPhdr = [](struct dl_phdr_info *info, size_t, void *data) { @@ -50,6 +64,15 @@ void rx::thread::initialize() { std::printf("libc text %zx-%zx\n", libcInfo.textBegin, libcInfo.textBegin + libcInfo.textSize); + + struct sigaction act {}; + act.sa_sigaction = handleSigSys; + act.sa_flags = SA_SIGINFO | SA_ONSTACK; + + if (sigaction(SIGSYS, &act, NULL)) { + perror("Error sigaction:"); + exit(-1); + } } void rx::thread::deinitialize() {} @@ -57,6 +80,14 @@ void rx::thread::deinitialize() {} void rx::thread::invoke(orbis::Thread *thread) { g_current = thread; + sigset_t unblockSigs{}; + sigset_t oldSigmask{}; + sigaddset(&unblockSigs, SIGSYS); + if (pthread_sigmask(SIG_UNBLOCK, &unblockSigs, &oldSigmask)) { + perror("pthread_sigmask failed\n"); + exit(-1); + } + std::uint64_t hostFs = _readfsbase_u64(); _writegsbase_u64(hostFs);