mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-05 14:37:08 +00:00
[orbis-kernel] Implement evf syscalls
This commit is contained in:
parent
d279166c0b
commit
14cfdd0eb3
10 changed files with 519 additions and 86 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue