diff --git a/orbis-kernel/include/orbis/sys/sysproto.hpp b/orbis-kernel/include/orbis/sys/sysproto.hpp index 6976f3a85..d19f150bf 100644 --- a/orbis-kernel/include/orbis/sys/sysproto.hpp +++ b/orbis-kernel/include/orbis/sys/sysproto.hpp @@ -607,7 +607,7 @@ SysResult sys_socketex(Thread *thread, ptr name, sint domain, sint type, sint protocol); SysResult sys_socketclose(Thread *thread, sint fd); SysResult sys_netgetiflist(Thread *thread /* TODO */); -SysResult sys_kqueueex(Thread *thread /* TODO */); +SysResult sys_kqueueex(Thread *thread, ptr name, sint flags); SysResult sys_mtypeprotect(Thread *thread /* TODO */); SysResult sys_regmgr_call(Thread *thread, uint32_t op, uint32_t id, ptr result, ptr value, uint64_t type); diff --git a/orbis-kernel/src/sys/sys_event.cpp b/orbis-kernel/src/sys/sys_event.cpp index de801fd13..18965dd79 100644 --- a/orbis-kernel/src/sys/sys_event.cpp +++ b/orbis-kernel/src/sys/sys_event.cpp @@ -1,18 +1,93 @@ +#include "KernelAllocator.hpp" #include "sys/sysproto.hpp" #include "thread/Process.hpp" #include "utils/Logs.hpp" +#include "utils/SharedMutex.hpp" +#include +#include -struct KQueue : orbis::File {}; +namespace orbis { +struct KEvent { + uintptr_t ident; + sshort filter; + ushort flags; + uint fflags; + intptr_t data; + ptr udata; +}; + +struct KNote { + KEvent event; + bool enabled; +}; + +struct KQueue : orbis::File { + std::list> notes; +}; + +static constexpr auto kEvFiltRead = -1; +static constexpr auto kEvFiltWrite = -2; +static constexpr auto kEvFiltAio = -3; +static constexpr auto kEvFiltVnode = -4; +static constexpr auto kEvFiltProc = -5; +static constexpr auto kEvFiltSignal = -6; +static constexpr auto kEvFiltTimer = -7; +static constexpr auto kEvFiltFs = -9; +static constexpr auto kEvFiltLio = -10; +static constexpr auto kEvFiltUser = -11; +static constexpr auto kEvFiltPolling = -12; +static constexpr auto kEvFiltDisplay = -13; +static constexpr auto kEvFiltGraphicsCore = -14; +static constexpr auto kEvFiltHrTimer = -15; +static constexpr auto kEvFiltUvdTrap = -16; +static constexpr auto kEvFiltVceTrap = -17; +static constexpr auto kEvFiltSdmaTrap = -18; +static constexpr auto kEvFiltRegEv = -19; +static constexpr auto kEvFiltGpuException = -20; +static constexpr auto kEvFiltGpuSystemException = -21; +static constexpr auto kEvFiltGpuDbgGcEv = -22; +static constexpr auto kEvFiltSysCount = 22; + +// actions +static constexpr auto kEvAdd = 0x0001; +static constexpr auto kEvDelete = 0x0002; +static constexpr auto kEvEnable = 0x0004; +static constexpr auto kEvDisable = 0x0008; + +// flags +static constexpr auto kEvOneshot = 0x0010; +static constexpr auto kEvClear = 0x0020; +static constexpr auto kEvReceipt = 0x0040; +static constexpr auto kEvDispatch = 0x0080; +static constexpr auto kEvSysFlags = 0xf000; +static constexpr auto kEvFlag1 = 0x2000; + +static constexpr auto kEvEof = 0x8000; +static constexpr auto kEvError = 0x4000; +} // namespace orbis orbis::SysResult orbis::sys_kqueue(Thread *thread) { - ORBIS_LOG_TODO(__FUNCTION__); auto queue = knew(); if (queue == nullptr) { return ErrorCode::NOMEM; } - thread->retval[0] = thread->tproc->fileDescriptors.insert(queue); + auto fd = thread->tproc->fileDescriptors.insert(queue); + ORBIS_LOG_TODO(__FUNCTION__, fd); + thread->retval[0] = fd; + return {}; +} + +orbis::SysResult orbis::sys_kqueueex(Thread *thread, ptr name, sint flags) { + auto queue = knew(); + if (queue == nullptr) { + return ErrorCode::NOMEM; + } + + auto fd = thread->tproc->fileDescriptors.insert(queue); + ORBIS_LOG_TODO(__FUNCTION__, name, flags, fd); + thread->retval[0] = fd; return {}; } @@ -20,7 +95,62 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd, ptr changelist, sint nchanges, ptr eventlist, sint nevents, ptr timeout) { - // ORBIS_LOG_TODO(__FUNCTION__, fd, changelist, nchanges, eventlist, nevents, timeout); - thread->retval[0] = nevents; + // ORBIS_LOG_TODO(__FUNCTION__, fd, changelist, nchanges, eventlist, nevents, + // timeout); + Ref kqf = thread->tproc->fileDescriptors.get(fd); + if (kqf == nullptr) { + return orbis::ErrorCode::BADF; + } + + std::lock_guard lock(kqf->mtx); + + auto kq = dynamic_cast(kqf.get()); + + if (kq == nullptr) { + return orbis::ErrorCode::BADF; + } + + + if (nchanges != 0) { + for (auto change : std::span(changelist, nchanges)) { + ORBIS_LOG_TODO(__FUNCTION__, change.ident, change.filter, change.flags, + change.fflags, change.data, change.udata); + + if (change.flags & kEvAdd) { + if (change.filter != kEvFiltDisplay && change.filter != kEvFiltGraphicsCore) { + std::abort(); + } + + kq->notes.push_back({ + .event = change, + .enabled = (change.flags & kEvDisable) == 0 + }); + + kq->notes.back().event.flags &= ~(kEvAdd | kEvClear | kEvDelete | kEvDisable); + } + + // TODO + } + } + + std::vector result; + result.reserve(nevents); + + for (auto ¬e : kq->notes) { + if (result.size() >= nevents) { + break; + } + + if (!note.enabled) { + continue; + } + + if (note.event.filter == kEvFiltDisplay || note.event.filter == kEvFiltGraphicsCore) { + result.push_back(note.event); + } + } + + std::memcpy(eventlist, result.data(), result.size() * sizeof(KEvent)); + thread->retval[0] = result.size(); return {}; } diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index dfa4b2406..39796bf12 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -53,19 +53,7 @@ orbis::SysResult orbis::sys_socketclose(Thread *thread, sint fd) { orbis::SysResult orbis::sys_netgetiflist(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } -struct KQueueEx : orbis::File {}; -orbis::SysResult orbis::sys_kqueueex(Thread *thread /* TODO */) { - ORBIS_LOG_TODO(__FUNCTION__); - auto queue = knew(); - if (queue == nullptr) { - return ErrorCode::NOMEM; - } - - thread->retval[0] = thread->tproc->fileDescriptors.insert(queue); - thread->where(); - return {}; -} orbis::SysResult orbis::sys_mtypeprotect(Thread *thread /* TODO */) { return ErrorCode::NOSYS; }