mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-02-03 22:34:19 +01:00
[orbis-kernel] Implement evf syscalls
This commit is contained in:
parent
d279166c0b
commit
14cfdd0eb3
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "orbis-kernel"]
|
||||
path = orbis-kernel
|
||||
url = ../orbis-kernel.git
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ using kunmap =
|
|||
template <typename T, typename... Args> T *knew(Args &&...args) {
|
||||
auto loc = static_cast<T *>(utils::kalloc(sizeof(T), alignof(T)));
|
||||
auto res = std::construct_at(loc, std::forward<Args>(args)...);
|
||||
if constexpr (WithRc<T>)
|
||||
if constexpr (requires(T *t) { t->_total_size = sizeof(T); })
|
||||
res->_total_size = sizeof(T);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<EventFlag *, bool> createEventFlag(std::string name, std::int32_t flags) {
|
||||
auto [it, inserted] = m_event_flags.try_emplace(std::move(name), knew<EventFlag>(flags));
|
||||
return { it->second.get(), inserted };
|
||||
}
|
||||
|
||||
Ref<EventFlag> 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<Process> *m_processes = nullptr;
|
||||
kmap<std::string, Ref<EventFlag>> m_event_flags;
|
||||
|
||||
struct node {
|
||||
std::size_t size;
|
||||
|
|
|
|||
108
orbis-kernel/include/orbis/evf.hpp
Normal file
108
orbis-kernel/include/orbis/evf.hpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#pragma once
|
||||
#include "thread/Thread.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
|
||||
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<unsigned> references{1};
|
||||
std::atomic<std::uint64_t> 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<std::uint32_t> 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
|
||||
|
|
@ -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<char> name, sint flag, ptr<struct evFlag> evf);
|
||||
SysResult sys_evf_delete(Thread *thread, sint fd);
|
||||
SysResult sys_evf_create(Thread *thread, ptr<char> name, sint attrs, ptr<struct evFlag> evf);
|
||||
SysResult sys_evf_delete(Thread *thread, sint id);
|
||||
SysResult sys_evf_open(Thread *thread, ptr<char> 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<uint64_t> pPatternSet, ptr<uint> pTimeout);
|
||||
SysResult sys_evf_trywait(Thread *thread, sint id, uint64_t patternSet, uint64_t mode, ptr<uint64_t> 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<sint> pNumWaitThreads);
|
||||
SysResult sys_query_memory_protection(Thread *thread /* TODO */);
|
||||
SysResult sys_batch_map(Thread *thread /* TODO */);
|
||||
SysResult sys_osem_create(Thread *thread /* TODO */);
|
||||
|
|
|
|||
|
|
@ -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 <mutex>
|
||||
|
||||
|
|
@ -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<void> 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<EventFlag, sint, 4097, 1> evfMap;
|
||||
utils::RcIdMap<Module, ModuleHandle> modulesMap;
|
||||
utils::OwningIdMap<Thread, lwpid_t> threadsMap;
|
||||
utils::RcIdMap<utils::RcBase, sint> fileDescriptors;
|
||||
|
|
|
|||
167
orbis-kernel/src/evf.cpp
Normal file
167
orbis-kernel/src/evf.cpp
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
#include "evf.hpp"
|
||||
#include "error/ErrorCode.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <atomic>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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 <chrono>
|
||||
|
||||
orbis::SysResult orbis::sys_netcontrol(Thread *thread, sint fd, uint op,
|
||||
ptr<void> 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<void> result, ptr<void> value,
|
||||
uint64_t type) {
|
||||
uint32_t id, ptr<void> result,
|
||||
ptr<void> 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<nonsys_int *>(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<char> name,
|
||||
sint flag, ptr<struct evFlag> evf) {
|
||||
return ErrorCode::NOSYS;
|
||||
sint attrs, ptr<struct evFlag> 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<EventFlag>(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<char> 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<uint64_t> pPatternSet,
|
||||
ptr<uint> 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<uint64_t> 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<sint> 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<const char> name, ptr<void> 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<const char> name,
|
||||
ptr<void> 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<void> info) {
|
||||
orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid,
|
||||
ptr<void> 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<void> in
|
|||
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_mname(Thread *thread, ptr<void> address, uint64_t length, ptr<const char> name) {
|
||||
std::printf("sys_mname(%p, %p, '%s')\n", address, (char *)address + length, name);
|
||||
orbis::SysResult orbis::sys_mname(Thread *thread, ptr<void> address,
|
||||
uint64_t length, ptr<const char> 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<const char> name, uint64_t arg1, ptr<ModuleHandle> pHandle, uint64_t arg3) {
|
||||
orbis::SysResult orbis::sys_dynlib_load_prx(Thread *thread,
|
||||
ptr<const char> name, uint64_t arg1,
|
||||
ptr<ModuleHandle> 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<typename T> using le = T;
|
||||
|
||||
orbis::SysResult orbis::sys_dynlib_get_proc_param(Thread *thread,
|
||||
ptr<ptr<void>> procParam,
|
||||
ptr<uint64_t> procParamSize) {
|
||||
|
|
@ -385,24 +518,30 @@ struct mdbg_property {
|
|||
char name[32];
|
||||
};
|
||||
|
||||
orbis::SysResult orbis::sys_mdbg_service(Thread *thread, uint32_t op, ptr<void> arg0, ptr<void> 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<void> arg0, ptr<void> 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<mdbg_property>)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<uint64_t>(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<void>
|
|||
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<dargs>)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<void> arg0;
|
||||
orbis::ptr<char> name;
|
||||
orbis::ptr<void> arg2;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiCreateClientParams) == 0x18);
|
||||
|
||||
orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint64_t id, uint64_t arg2, ptr<uint64_t> result, ptr<uint64_t> params, uint64_t paramsSize, uint64_t arg6) {
|
||||
orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint64_t id,
|
||||
uint64_t arg2, ptr<uint64_t> result,
|
||||
ptr<uint64_t> 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<IpmiCreateClientParams>)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<ptr<void>> addrp) {
|
||||
orbis::SysResult orbis::sys_dynlib_get_obj_member(Thread *thread,
|
||||
SceKernelModule handle,
|
||||
uint64_t index,
|
||||
ptr<ptr<void>> addrp) {
|
||||
if (auto dynlib_get_obj_member = thread->tproc->ops->dynlib_get_obj_member) {
|
||||
return dynlib_get_obj_member(thread, handle, index, addrp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue