From 14cfdd0eb358ebe951bd2089fc597e015d2dbb82 Mon Sep 17 00:00:00 2001 From: DH Date: Wed, 5 Jul 2023 01:43:47 +0300 Subject: [PATCH] [orbis-kernel] Implement evf syscalls --- .gitmodules | 3 - orbis-kernel/CMakeLists.txt | 1 + .../include/orbis/KernelAllocator.hpp | 2 +- orbis-kernel/include/orbis/KernelContext.hpp | 15 + orbis-kernel/include/orbis/evf.hpp | 108 +++++++ orbis-kernel/include/orbis/sys/sysproto.hpp | 16 +- orbis-kernel/include/orbis/thread/Process.hpp | 15 +- orbis-kernel/src/evf.cpp | 167 +++++++++++ orbis-kernel/src/sys/sys_sce.cpp | 275 +++++++++++++----- orbis-kernel/src/utils/SharedMutex.cpp | 3 +- 10 files changed, 519 insertions(+), 86 deletions(-) delete mode 100644 .gitmodules create mode 100644 orbis-kernel/include/orbis/evf.hpp create mode 100644 orbis-kernel/src/evf.cpp diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 247564b4b..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "orbis-kernel"] - path = orbis-kernel - url = ../orbis-kernel.git diff --git a/orbis-kernel/CMakeLists.txt b/orbis-kernel/CMakeLists.txt index 1a445145c..daf17846a 100644 --- a/orbis-kernel/CMakeLists.txt +++ b/orbis-kernel/CMakeLists.txt @@ -3,6 +3,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE on) add_library(obj.orbis-kernel OBJECT src/module.cpp src/sysvec.cpp + src/evf.cpp src/KernelContext.cpp src/sys/sys_acct.cpp src/sys/sys_audit.cpp diff --git a/orbis-kernel/include/orbis/KernelAllocator.hpp b/orbis-kernel/include/orbis/KernelAllocator.hpp index 22537bda0..4d372bb82 100644 --- a/orbis-kernel/include/orbis/KernelAllocator.hpp +++ b/orbis-kernel/include/orbis/KernelAllocator.hpp @@ -44,7 +44,7 @@ using kunmap = template T *knew(Args &&...args) { auto loc = static_cast(utils::kalloc(sizeof(T), alignof(T))); auto res = std::construct_at(loc, std::forward(args)...); - if constexpr (WithRc) + if constexpr (requires(T *t) { t->_total_size = sizeof(T); }) res->_total_size = sizeof(T); return res; } diff --git a/orbis-kernel/include/orbis/KernelContext.hpp b/orbis-kernel/include/orbis/KernelContext.hpp index 6b2b7e535..a32496acc 100644 --- a/orbis-kernel/include/orbis/KernelContext.hpp +++ b/orbis-kernel/include/orbis/KernelContext.hpp @@ -1,6 +1,7 @@ #pragma once #include "utils/LinkedNode.hpp" #include "utils/SharedMutex.hpp" +#include "evf.hpp" #include "orbis/thread/types.hpp" #include "KernelAllocator.hpp" @@ -23,9 +24,23 @@ public: std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__); static void kfree(void *ptr, std::size_t size); + std::pair createEventFlag(std::string name, std::int32_t flags) { + auto [it, inserted] = m_event_flags.try_emplace(std::move(name), knew(flags)); + return { it->second.get(), inserted }; + } + + Ref findEventFlag(std::string_view name) { + if (auto it = m_event_flags.find(name); it != m_event_flags.end()) { + return it->second; + } + + return{}; + } + private: mutable shared_mutex m_proc_mtx; utils::LinkedNode *m_processes = nullptr; + kmap> m_event_flags; struct node { std::size_t size; diff --git a/orbis-kernel/include/orbis/evf.hpp b/orbis-kernel/include/orbis/evf.hpp new file mode 100644 index 000000000..72fcb2893 --- /dev/null +++ b/orbis-kernel/include/orbis/evf.hpp @@ -0,0 +1,108 @@ +#pragma once +#include "thread/Thread.hpp" +#include "utils/SharedMutex.hpp" +#include +#include + +namespace orbis { +enum { + kEvfAttrThFifo = 0x01, + kEvfAttrThPrio = 0x02, + kEvfAttrSingle = 0x10, + kEvfAttrMulti = 0x20, +}; + +enum { + kEvfWaitModeAnd = 0x01, + kEvfWaitModeOr = 0x02, + kEvfWaitModeClearAll = 0x10, + kEvfWaitModeClearPat = 0x20, +}; + +struct EventFlag { + char name[32]; + + bool isDeleted = false; + std::uint8_t attrs; + std::atomic references{1}; + std::atomic value; + + struct WaitingThread { + Thread *thread; + shared_mutex *mtx; + std::uint64_t *patternSet; + bool *isCanceled; + std::uint64_t bitPattern; + std::uint8_t waitMode; + + bool test(std::uint64_t value) const { + if (waitMode & kEvfWaitModeAnd) { + return (value & bitPattern) == bitPattern; + } + + return (value & bitPattern) != 0; + } + + std::uint64_t applyClear(std::uint64_t value) { + if (waitMode & kEvfWaitModeClearAll) { + return 0; + } + + if (waitMode & kEvfWaitModeClearPat) { + return value & ~bitPattern; + } + + return value; + } + }; + + WaitingThread waitingThreads[32]; // TODO: create vector? + std::atomic waitingThreadsCount = 0; + + shared_mutex queueMtx; + + explicit EventFlag(std::int32_t attrs) : attrs(attrs) {} + + ErrorCode wait(Thread *thread, std::uint8_t waitMode, + std::uint64_t bitPattern, std::uint64_t *patternSet, + std::uint32_t *timeout); + ErrorCode tryWait(Thread *thread, std::uint8_t waitMode, + std::uint64_t bitPattern, std::uint64_t *patternSet); + std::size_t notify(bool isCancel = false, std::uint64_t cancelValue = 0); + + std::size_t destroy() { + isDeleted = true; + return notify(); + } + + std::size_t cancel(std::uint64_t value) { + return notify(true, value); + } + + std::size_t set(std::uint64_t bits) { + { + writer_lock lock(queueMtx); + value.fetch_or(bits, std::memory_order::relaxed); + } + + return notify(); + } + + void clear(std::uint64_t bits) { + { + writer_lock lock(queueMtx); + value.fetch_and(bits, std::memory_order::relaxed); + } + + value &= bits; + } + + void incRef() { references.fetch_add(1, std::memory_order::relaxed); } + + void decRef() { + if (references.fetch_sub(1, std::memory_order::relaxed) == 1) { + delete this; + } + } +}; +} // namespace orbis diff --git a/orbis-kernel/include/orbis/sys/sysproto.hpp b/orbis-kernel/include/orbis/sys/sysproto.hpp index f3b5acdcc..47cf15727 100644 --- a/orbis-kernel/include/orbis/sys/sysproto.hpp +++ b/orbis-kernel/include/orbis/sys/sysproto.hpp @@ -409,15 +409,15 @@ SysResult sys_jitshm_alias(Thread *thread /* TODO */); SysResult sys_dl_get_list(Thread *thread /* TODO */); SysResult sys_dl_get_info(Thread *thread /* TODO */); SysResult sys_dl_notify_event(Thread *thread /* TODO */); -SysResult sys_evf_create(Thread *thread, ptr name, sint flag, ptr evf); -SysResult sys_evf_delete(Thread *thread, sint fd); +SysResult sys_evf_create(Thread *thread, ptr name, sint attrs, ptr evf); +SysResult sys_evf_delete(Thread *thread, sint id); SysResult sys_evf_open(Thread *thread, ptr name); -SysResult sys_evf_close(Thread *thread, sint fd); -SysResult sys_evf_wait(Thread *thread /* TODO */); -SysResult sys_evf_trywait(Thread *thread /* TODO */); -SysResult sys_evf_set(Thread *thread, sint fd); -SysResult sys_evf_clear(Thread *thread, sint fd); -SysResult sys_evf_cancel(Thread *thread, sint fd); +SysResult sys_evf_close(Thread *thread, sint id); +SysResult sys_evf_wait(Thread *thread, sint id, uint64_t patternSet, uint64_t mode, ptr pPatternSet, ptr pTimeout); +SysResult sys_evf_trywait(Thread *thread, sint id, uint64_t patternSet, uint64_t mode, ptr pPatternSet); // FIXME: verify args +SysResult sys_evf_set(Thread *thread, sint id, uint64_t value); +SysResult sys_evf_clear(Thread *thread, sint id, uint64_t value); +SysResult sys_evf_cancel(Thread *thread, sint id, uint64_t value, ptr pNumWaitThreads); SysResult sys_query_memory_protection(Thread *thread /* TODO */); SysResult sys_batch_map(Thread *thread /* TODO */); SysResult sys_osem_create(Thread *thread /* TODO */); diff --git a/orbis-kernel/include/orbis/thread/Process.hpp b/orbis-kernel/include/orbis/thread/Process.hpp index 4cb4ae442..5cea1d950 100644 --- a/orbis-kernel/include/orbis/thread/Process.hpp +++ b/orbis-kernel/include/orbis/thread/Process.hpp @@ -1,11 +1,13 @@ #pragma once -#include "ProcessState.hpp" #include "orbis-config.hpp" + +#include "../evf.hpp" +#include "../thread/Thread.hpp" +#include "../thread/types.hpp" +#include "ProcessState.hpp" #include "orbis/module/Module.hpp" #include "orbis/utils/IdMap.hpp" #include "orbis/utils/SharedMutex.hpp" -#include "../thread/types.hpp" -#include "../thread/Thread.hpp" #include @@ -22,8 +24,10 @@ struct Process { ProcessState state = ProcessState::NEW; Process *parentProcess = nullptr; shared_mutex mtx; - void (*onSysEnter)(Thread *thread, int id, uint64_t *args, int argsCount) = nullptr; - void (*onSysExit)(Thread *thread, int id, uint64_t *args, int argsCount, SysResult result) = nullptr; + void (*onSysEnter)(Thread *thread, int id, uint64_t *args, + int argsCount) = nullptr; + void (*onSysExit)(Thread *thread, int id, uint64_t *args, int argsCount, + SysResult result) = nullptr; ptr processParam = nullptr; uint64_t processParamSize = 0; const ProcessOps *ops = nullptr; @@ -31,6 +35,7 @@ struct Process { std::uint64_t nextTlsSlot = 1; std::uint64_t lastTlsOffset = 0; + utils::RcIdMap evfMap; utils::RcIdMap modulesMap; utils::OwningIdMap threadsMap; utils::RcIdMap fileDescriptors; diff --git a/orbis-kernel/src/evf.cpp b/orbis-kernel/src/evf.cpp new file mode 100644 index 000000000..80b03c7ea --- /dev/null +++ b/orbis-kernel/src/evf.cpp @@ -0,0 +1,167 @@ +#include "evf.hpp" +#include "error/ErrorCode.hpp" +#include "utils/Logs.hpp" +#include + +orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode, + std::uint64_t bitPattern, + std::uint64_t *patternSet, + std::uint32_t *timeout) { + if (timeout != nullptr) { + ORBIS_LOG_FATAL("evf: timeout is not implemented"); + std::abort(); + } + + shared_mutex mtx; + writer_lock lock(mtx); + + bool isCanceled = false; + + { + writer_lock lock(queueMtx); + + if (isDeleted) { + return ErrorCode::ACCES; + } + + auto waitingThread = WaitingThread{.thread = thread, + .mtx = &mtx, + .patternSet = patternSet, + .isCanceled = &isCanceled, + .bitPattern = bitPattern, + .waitMode = waitMode}; + + if (auto patValue = value.load(std::memory_order::relaxed); + waitingThread.test(patValue)) { + auto resultValue = waitingThread.applyClear(patValue); + value.store(resultValue, std::memory_order::relaxed); + if (patternSet != nullptr) { + *patternSet = resultValue; + } + return {}; + } + + std::size_t position; + + if (attrs & kEvfAttrSingle) { + if (waitingThreadsCount.fetch_add(1, std::memory_order::relaxed) != 0) { + waitingThreadsCount.store(1, std::memory_order::relaxed); + return ErrorCode::PERM; + } + + position = 0; + } else { + if (attrs & kEvfAttrThFifo) { + position = waitingThreadsCount.fetch_add(1, std::memory_order::relaxed); + } else { + // FIXME: sort waitingThreads by priority + position = waitingThreadsCount.fetch_add(1, std::memory_order::relaxed); + } + } + + if (position >= std::size(waitingThreads)) { + std::abort(); + } + + waitingThreads[position] = waitingThread; + } + + // TODO: update thread state + + mtx.lock(); // HACK: lock self to wait unlock from another thread :) + + if (isCanceled) { + return ErrorCode::CANCELED; + } + + if (isDeleted) { + return ErrorCode::ACCES; + } + + return {}; +} + +orbis::ErrorCode orbis::EventFlag::tryWait(Thread *, + std::uint8_t waitMode, + std::uint64_t bitPattern, + std::uint64_t *patternSet) { + writer_lock lock(queueMtx); + + if (isDeleted) { + return ErrorCode::ACCES; + } + + auto waitingThread = WaitingThread{ + .bitPattern = bitPattern, + .waitMode = waitMode}; + + if (auto patValue = value.load(std::memory_order::relaxed); + waitingThread.test(patValue)) { + auto resultValue = waitingThread.applyClear(patValue); + value.store(resultValue, std::memory_order::relaxed); + if (patternSet != nullptr) { + *patternSet = resultValue; + } + + return {}; + } + + return ErrorCode::BUSY; +} + +std::size_t orbis::EventFlag::notify(bool isCancel, std::uint64_t cancelValue) { + writer_lock lock(queueMtx); + auto count = waitingThreadsCount.load(std::memory_order::relaxed); + auto patValue = value.load(std::memory_order::relaxed); + + auto testThread = [&](WaitingThread *thread) { + if (!isCancel && !isDeleted && !thread->test(patValue)) { + return false; + } + + auto resultValue = thread->applyClear(patValue); + patValue = resultValue; + if (thread->patternSet != nullptr) { + *thread->patternSet = resultValue; + } + if (isCancel) { + *thread->isCanceled = true; + } else { + value.store(resultValue, std::memory_order::relaxed); + } + + // TODO: update thread state + thread->mtx->unlock(); // release wait on waiter thread + + waitingThreadsCount.fetch_sub(1, std::memory_order::relaxed); + --count; + std::memmove(thread, thread + 1, waitingThreads + count - (thread + 1)); + return true; + }; + + std::size_t result = 0; + if (attrs & kEvfAttrThFifo) { + for (std::size_t i = count; i > 0;) { + if (!testThread(waitingThreads + i - 1)) { + --i; + continue; + } + + ++result; + } + } else { + for (std::size_t i = 0; i < count;) { + if (!testThread(waitingThreads + i)) { + ++i; + continue; + } + + ++result; + } + } + + if (isCancel) { + value.store(cancelValue, std::memory_order::relaxed); + } + return result; +} diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index 9c746dada..cb5506997 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -1,7 +1,11 @@ +#include "KernelContext.hpp" #include "error.hpp" +#include "evf.hpp" #include "module/ModuleInfo.hpp" #include "module/ModuleInfoEx.hpp" #include "sys/sysproto.hpp" +#include "utils/Logs.hpp" +#include orbis::SysResult orbis::sys_netcontrol(Thread *thread, sint fd, uint op, ptr buf, uint nbuf) { @@ -30,8 +34,8 @@ orbis::SysResult orbis::sys_mtypeprotect(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op, - uint32_t id, ptr result, ptr value, - uint64_t type) { + uint32_t id, ptr result, + ptr value, uint64_t type) { if (op == 25) { struct nonsys_int { union { @@ -49,20 +53,17 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op, auto int_value = reinterpret_cast(value); - std::printf(" encoded_id = %lx\n", int_value->encoded_id); - std::printf(" data[0] = %02x\n", int_value->encoded_id_parts.data[0]); - std::printf(" data[1] = %02x\n", int_value->encoded_id_parts.data[1]); - std::printf(" data[2] = %02x\n", int_value->encoded_id_parts.data[2]); - std::printf(" data[3] = %02x\n", int_value->encoded_id_parts.data[3]); - std::printf(" table = %u\n", int_value->encoded_id_parts.table); - std::printf(" index = %u\n", int_value->encoded_id_parts.index); - std::printf(" checksum = %x\n", int_value->encoded_id_parts.checksum); - std::printf(" unk = %x\n", int_value->unk); - std::printf(" value = %x\n", int_value->value); + ORBIS_LOG_TODO( + __FUNCTION__, int_value->encoded_id, + int_value->encoded_id_parts.data[0], + int_value->encoded_id_parts.data[1], + int_value->encoded_id_parts.data[2], + int_value->encoded_id_parts.data[3], int_value->encoded_id_parts.table, + int_value->encoded_id_parts.index, int_value->encoded_id_parts.checksum, + int_value->unk, int_value->value); } - return{}; - + return {}; } orbis::SysResult orbis::sys_jitshm_create(Thread *thread /* TODO */) { return ErrorCode::NOSYS; @@ -80,32 +81,159 @@ orbis::SysResult orbis::sys_dl_notify_event(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr name, - sint flag, ptr evf) { - return ErrorCode::NOSYS; + sint attrs, ptr evf) { + if (name == nullptr || evf != nullptr) { + return ErrorCode::INVAL; + } + + if (attrs & + ~(kEvfAttrSingle | kEvfAttrMulti | kEvfAttrThPrio | kEvfAttrThFifo)) { + return ErrorCode::INVAL; + } + + switch (attrs & (kEvfAttrSingle | kEvfAttrMulti)) { + case 0: + case kEvfAttrSingle | kEvfAttrMulti: + return ErrorCode::INVAL; + + default: + break; + } + + switch (attrs & (kEvfAttrThPrio | kEvfAttrThFifo)) { + case 0: + case kEvfAttrThPrio | kEvfAttrThFifo: + return ErrorCode::INVAL; + } + + char _name[32]; + if (auto result = ureadString(_name, sizeof(_name), name); + result != ErrorCode{}) { + return result; + } + + auto eventFlag = knew(attrs); + thread->retval[0] = thread->tproc->evfMap.insert(eventFlag); + return {}; } -orbis::SysResult orbis::sys_evf_delete(Thread *thread, sint fd) { +orbis::SysResult orbis::sys_evf_delete(Thread *thread, sint id) { + ORBIS_LOG_TODO(__FUNCTION__, id); return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_evf_open(Thread *thread, ptr name) { - return ErrorCode::NOSYS; + char _name[32]; + if (auto result = ureadString(_name, sizeof(_name), name); + result != ErrorCode{}) { + return result; + } + + auto eventFlag = thread->tproc->context->findEventFlag(name); + + if (eventFlag == nullptr) { + return ErrorCode::SRCH; + } + + std::strcpy(eventFlag->name, _name); + thread->retval[0] = thread->tproc->evfMap.insert(eventFlag); + return {}; } -orbis::SysResult orbis::sys_evf_close(Thread *thread, sint fd) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_evf_close(Thread *thread, sint id) { + if (!thread->tproc->evfMap.remove(id)) { + return ErrorCode::BADF; + } + + return {}; } -orbis::SysResult orbis::sys_evf_wait(Thread *thread /* TODO */) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_evf_wait(Thread *thread, sint id, + uint64_t patternSet, uint64_t mode, + ptr pPatternSet, + ptr pTimeout) { + if ((mode & (kEvfWaitModeAnd | kEvfWaitModeOr)) == 0 || + (mode & ~(kEvfWaitModeAnd | kEvfWaitModeOr | kEvfWaitModeClearAll | + kEvfWaitModeClearPat)) != 0 || + patternSet == 0) { + return ErrorCode::INVAL; + } + + auto evf = thread->tproc->evfMap.get(id); + + if (evf == nullptr) { + return ErrorCode::BADF; + } + + std::uint32_t resultTimeout{}; + std::uint64_t resultPattern{}; + auto result = evf->wait(thread, mode, patternSet, + pPatternSet != nullptr ? &resultPattern : nullptr, + pTimeout != nullptr ? &resultTimeout : nullptr); + + if (pPatternSet != nullptr) { + uwrite(pPatternSet, (uint64_t)resultPattern); + } + + if (pTimeout != nullptr) { + uwrite(pTimeout, (uint32_t)resultTimeout); + } + return result; } -orbis::SysResult orbis::sys_evf_trywait(Thread *thread /* TODO */) { - return ErrorCode::NOSYS; + +orbis::SysResult orbis::sys_evf_trywait(Thread *thread, sint id, + uint64_t patternSet, uint64_t mode, + ptr pPatternSet) { + if ((mode & (kEvfWaitModeAnd | kEvfWaitModeOr)) == 0 || + (mode & ~(kEvfWaitModeAnd | kEvfWaitModeOr | kEvfWaitModeClearAll | + kEvfWaitModeClearPat)) != 0 || + patternSet == 0) { + return ErrorCode::INVAL; + } + + auto evf = thread->tproc->evfMap.get(id); + + if (evf == nullptr) { + return ErrorCode::BADF; + } + + std::uint64_t resultPattern{}; + auto result = evf->tryWait(thread, mode, patternSet, pPatternSet != nullptr ? &resultPattern : nullptr); + + if (pPatternSet != nullptr) { + uwrite(pPatternSet, (uint64_t)resultPattern); + } + + return result; } -orbis::SysResult orbis::sys_evf_set(Thread *thread, sint fd) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_evf_set(Thread *thread, sint id, uint64_t value) { + auto evf = thread->tproc->evfMap.get(id); + + if (evf == nullptr) { + return ErrorCode::BADF; + } + + evf->set(value); + return{}; } -orbis::SysResult orbis::sys_evf_clear(Thread *thread, sint fd) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_evf_clear(Thread *thread, sint id, uint64_t value) { + auto evf = thread->tproc->evfMap.get(id); + + if (evf == nullptr) { + return ErrorCode::BADF; + } + + evf->clear(value); + return{}; } -orbis::SysResult orbis::sys_evf_cancel(Thread *thread, sint fd) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_evf_cancel(Thread *thread, sint id, uint64_t value, ptr pNumWaitThreads) { + auto evf = thread->tproc->evfMap.get(id); + + if (evf == nullptr) { + return ErrorCode::BADF; + } + + auto numWaitThreads = evf->cancel(value); + if (pNumWaitThreads != nullptr) { + *pNumWaitThreads = numWaitThreads; + } + return{}; } orbis::SysResult orbis::sys_query_memory_protection(Thread *thread /* TODO */) { return ErrorCode::NOSYS; @@ -137,13 +265,15 @@ orbis::SysResult orbis::sys_osem_post(Thread *thread /* TODO */) { orbis::SysResult orbis::sys_osem_cancel(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } -orbis::SysResult orbis::sys_namedobj_create(Thread *thread, ptr name, ptr object, uint64_t type) { - std::printf("sys_namedobj_create(name = %s, object = %p, type = 0x%lx) -> %d\n", name, object, type, 1); +orbis::SysResult orbis::sys_namedobj_create(Thread *thread, + ptr name, + ptr object, uint64_t type) { + ORBIS_LOG_TODO(__FUNCTION__, name, object, type); thread->retval[0] = 1; return {}; } orbis::SysResult orbis::sys_namedobj_delete(Thread *thread /* TODO */) { - std::printf("TODO: sys_namedobj_delete\n"); + ORBIS_LOG_TODO(__FUNCTION__); return {}; } orbis::SysResult orbis::sys_set_vm_container(Thread *thread /* TODO */) { @@ -232,13 +362,14 @@ orbis::SysResult orbis::sys_obs_eport_close(Thread *thread /* TODO */) { } orbis::SysResult orbis::sys_is_in_sandbox(Thread *thread /* TODO */) { std::printf("sys_is_in_sandbox() -> 0\n"); - return{}; + return {}; } orbis::SysResult orbis::sys_dmem_container(Thread *thread) { thread->retval[0] = 0; // returns default direct memory device return {}; } -orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid, ptr info) { +orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid, + ptr info) { struct authinfo { uint64_t a; uint64_t b; @@ -249,8 +380,10 @@ orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid, ptr in return {}; } -orbis::SysResult orbis::sys_mname(Thread *thread, ptr address, uint64_t length, ptr name) { - std::printf("sys_mname(%p, %p, '%s')\n", address, (char *)address + length, name); +orbis::SysResult orbis::sys_mname(Thread *thread, ptr address, + uint64_t length, ptr name) { + std::printf("sys_mname(%p, %p, '%s')\n", address, (char *)address + length, + name); return {}; } orbis::SysResult orbis::sys_dynlib_dlopen(Thread *thread /* TODO */) { @@ -280,7 +413,7 @@ orbis::SysResult orbis::sys_dynlib_get_list(Thread *thread, pArray[actualNum++] = id; } - *pActualNum = actualNum; + uwrite(pActualNum, actualNum); return {}; } orbis::SysResult orbis::sys_dynlib_get_info(Thread *thread, @@ -307,25 +440,27 @@ orbis::SysResult orbis::sys_dynlib_get_info(Thread *thread, uwrite(pInfo, result); return {}; } -orbis::SysResult -orbis::sys_dynlib_load_prx(Thread *thread, ptr name, uint64_t arg1, ptr pHandle, uint64_t arg3) { +orbis::SysResult orbis::sys_dynlib_load_prx(Thread *thread, + ptr name, uint64_t arg1, + ptr pHandle, + uint64_t arg3) { if (auto dynlib_load_prx = thread->tproc->ops->dynlib_load_prx) { return dynlib_load_prx(thread, name, arg1, pHandle, arg3); } return ErrorCode::NOSYS; } -orbis::SysResult -orbis::sys_dynlib_unload_prx(Thread *thread, SceKernelModule handle) { +orbis::SysResult orbis::sys_dynlib_unload_prx(Thread *thread, + SceKernelModule handle) { if (auto dynlib_unload_prx = thread->tproc->ops->dynlib_unload_prx) { return dynlib_unload_prx(thread, handle); } return ErrorCode::NOSYS; } -orbis::SysResult -orbis::sys_dynlib_do_copy_relocations(Thread *thread) { - if (auto dynlib_do_copy_relocations = thread->tproc->ops->dynlib_do_copy_relocations) { +orbis::SysResult orbis::sys_dynlib_do_copy_relocations(Thread *thread) { + if (auto dynlib_do_copy_relocations = + thread->tproc->ops->dynlib_do_copy_relocations) { return dynlib_do_copy_relocations(thread); } @@ -335,8 +470,6 @@ orbis::SysResult orbis::sys_dynlib_prepare_dlclose(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } -// template using le = T; - orbis::SysResult orbis::sys_dynlib_get_proc_param(Thread *thread, ptr> procParam, ptr procParamSize) { @@ -385,24 +518,30 @@ struct mdbg_property { char name[32]; }; -orbis::SysResult orbis::sys_mdbg_service(Thread *thread, uint32_t op, ptr arg0, ptr arg1) { - std::printf("sys_mdbg_service(op = %d, arg0 = %p, arg1 = %p)\n", op, arg0, arg1); +orbis::SysResult orbis::sys_mdbg_service(Thread *thread, uint32_t op, + ptr arg0, ptr arg1) { + std::printf("sys_mdbg_service(op = %d, arg0 = %p, arg1 = %p)\n", op, arg0, + arg1); switch (op) { case 1: { - auto *prop = (mdbg_property *)arg0; + auto prop = uread((ptr)arg0); std::printf( "sys_mdbg_service set property (name='%s', address=0x%lx, size=%lu)\n", - prop->name, prop->addr_ptr, prop->areaSize); + prop.name, prop.addr_ptr, prop.areaSize); + // FIXME: investigate crash + // ORBIS_LOG_WARNING(__FUNCTION__, prop.name, prop.addr_ptr, prop.areaSize); break; } case 3: { - std::printf("sys_mdbg_service: ERROR CODE: %X\n", (unsigned)reinterpret_cast(arg0)); + auto errorCode = (unsigned)(uint64_t)(arg0); + ORBIS_LOG_ERROR("sys_mdbg_service: ERROR CODE", errorCode); break; } case 7: { + // TODO: read string from userspace std::printf("sys_mdbg_service: %s\n", (char *)arg0); break; } @@ -411,7 +550,7 @@ orbis::SysResult orbis::sys_mdbg_service(Thread *thread, uint32_t op, ptr break; } - return{}; + return {}; } orbis::SysResult orbis::sys_randomized_path(Thread *thread /* TODO */) { std::printf("TODO: sys_randomized_path()\n"); @@ -488,13 +627,10 @@ orbis::SysResult orbis::sys_get_proc_type_info(Thread *thread, uint64_t size = sizeof(dargs); uint32_t ptype; uint32_t pflags; - } args = { - .ptype = 1, - .pflags = 0 - }; + } args = {.ptype = 1, .pflags = 0}; uwrite((ptr)destProcessInfo, args); - return{}; + return {}; } orbis::SysResult orbis::sys_get_resident_count(Thread *thread, pid_t pid) { return ErrorCode::NOSYS; @@ -526,18 +662,20 @@ orbis::SysResult orbis::sys_suspend_system(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } -enum ImpiOpcode { - kIpmiCreateClient = 2 -}; +enum ImpiOpcode { kIpmiCreateClient = 2 }; struct IpmiCreateClientParams { orbis::ptr arg0; orbis::ptr name; orbis::ptr arg2; }; + static_assert(sizeof(IpmiCreateClientParams) == 0x18); -orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint64_t id, uint64_t arg2, ptr result, ptr params, uint64_t paramsSize, uint64_t arg6) { +orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint64_t id, + uint64_t arg2, ptr result, + ptr params, + uint64_t paramsSize, uint64_t arg6) { std::printf("TODO: sys_ipmimgr_call(id = %lld)\n", (unsigned long long)id); if (id == kIpmiCreateClient) { @@ -548,12 +686,10 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint64_t id, uint64_t a auto createParams = (ptr)params; std::printf("ipmi create client(%p, '%s', %p)\n", - (void *)createParams->arg0, - (char *)createParams->name, - (void *)createParams->arg2 - ); + (void *)createParams->arg0, (char *)createParams->name, + (void *)createParams->arg2); - return{}; + return {}; } if (id == 1131 || id == 1024 || id == 800) { @@ -651,7 +787,10 @@ orbis::sys_get_sdk_compiled_version(Thread *thread /* TODO */) { orbis::SysResult orbis::sys_app_state_change(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } -orbis::SysResult orbis::sys_dynlib_get_obj_member(Thread *thread, SceKernelModule handle, uint64_t index, ptr> addrp) { +orbis::SysResult orbis::sys_dynlib_get_obj_member(Thread *thread, + SceKernelModule handle, + uint64_t index, + ptr> addrp) { if (auto dynlib_get_obj_member = thread->tproc->ops->dynlib_get_obj_member) { return dynlib_get_obj_member(thread, handle, index, addrp); } diff --git a/orbis-kernel/src/utils/SharedMutex.cpp b/orbis-kernel/src/utils/SharedMutex.cpp index d36627f3f..1afdaf790 100644 --- a/orbis-kernel/src/utils/SharedMutex.cpp +++ b/orbis-kernel/src/utils/SharedMutex.cpp @@ -45,7 +45,8 @@ void shared_mutex::impl_lock_shared(unsigned val) { } if ((old % c_sig) + c_one >= c_sig) - std::abort; // "shared_mutex overflow" + std::abort(); // "shared_mutex overflow" + impl_wait(); lock_downgrade(); }