[orbis-kernel][rpcsx-os] POC thr_new implementation (disabled by default)

This commit is contained in:
DH 2023-07-06 16:55:25 +03:00
parent 5bb820084e
commit 7bfa977086
4 changed files with 99 additions and 39 deletions

View File

@ -94,7 +94,8 @@ orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr<char> 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<char> name,
switch (attrs & (kEvfAttrThPrio | kEvfAttrThFifo)) {
case 0:
case kEvfAttrThPrio | kEvfAttrThFifo:
return ErrorCode::INVAL;
attrs = (attrs & ~(kEvfAttrThPrio | kEvfAttrThFifo)) | kEvfAttrThFifo;
break;
default:
break;
}
char _name[32];

View File

@ -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<void *>(stackStartAddress), stackSize,
rx::vm::kMapProtCpuWrite | rx::vm::kMapProtCpuRead,
rx::vm::kMapFlagAnonymous | rx::vm::kMapFlagFixed |
rx::vm::kMapFlagPrivate | rx::vm::kMapFlagStack);
mainThread.stackEnd =
reinterpret_cast<std::byte *>(mainThread.stackStart) + stackSize;
mainThread->stackEnd =
reinterpret_cast<std::byte *>(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<std::uint64_t> argvOffsets;
std::vector<std::uint64_t> envpOffsets;
@ -415,7 +395,7 @@ static int ps4Exec(orbis::Process *mainProcess,
// *reinterpret_cast<std::uint32_t *>(
// reinterpret_cast<std::byte *>(libkernel->base) + 0x6c2e4) = ~0;
StackWriter stack{reinterpret_cast<std::uint64_t>(mainThread.stackEnd)};
StackWriter stack{reinterpret_cast<std::uint64_t>(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();
}

View File

@ -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 <chrono>
#include <cstdio>
#include <filesystem>
#include <map>
#include <optional>
#include <set>
#include <thread>
#include <unistd.h>
using namespace orbis;
@ -421,11 +424,52 @@ SysResult thr_create(orbis::Thread *thread, orbis::ptr<struct ucontext> ctxt,
ptr<orbis::slong> arg, orbis::sint flags) {
return ErrorCode::NOTSUP;
}
SysResult thr_new(orbis::Thread *thread, orbis::ptr<struct thr_param> param,
SysResult thr_new(orbis::Thread *thread, orbis::ptr<thr_param> 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<std::uintptr_t>(_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<Thread>(childThread)] {
uwrite(_param.child_tid, slong(childThread->tid));
auto context = new ucontext_t{};
context->uc_mcontext.gregs[REG_RDI] = reinterpret_cast<std::uintptr_t>(_param.arg);
context->uc_mcontext.gregs[REG_RSI] = reinterpret_cast<std::uintptr_t>(_param.arg);
context->uc_mcontext.gregs[REG_RSP] = reinterpret_cast<std::uintptr_t>(childThread->stackEnd);
context->uc_mcontext.gregs[REG_RIP] = reinterpret_cast<std::uintptr_t>(_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<orbis::slong> 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) {

View File

@ -1,5 +1,7 @@
#include "thread.hpp"
#include "orbis/sys/sysentry.hpp"
#include <asm/prctl.h>
#include <csignal>
#include <immintrin.h>
#include <link.h>
#include <linux/prctl.h>
@ -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);