From 00cc81cd9656ffb4eae1525b4efcf88d64288310 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sun, 11 May 2025 22:33:35 +0200 Subject: [PATCH] add backend (WIP) --- src/core/libraries/kernel/equeue.cpp | 42 ++++++++++++++++++++++++++-- src/core/libraries/kernel/equeue.h | 6 ++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/kernel/equeue.cpp b/src/core/libraries/kernel/equeue.cpp index da0df1dde..50823c38a 100644 --- a/src/core/libraries/kernel/equeue.cpp +++ b/src/core/libraries/kernel/equeue.cpp @@ -300,25 +300,63 @@ int PS4_SYSV_ABI sceKernelDeleteHRTimerEvent(SceKernelEqueue eq, int id) { } } +extern boost::asio::io_context io_context; + +static bool EventExists(SceKernelEqueue eq, u64 id, s16 filter) { + std::scoped_lock lock{eq->m_mutex}; + + const auto& it = std::ranges::find_if(eq->m_events, [id, filter](auto& ev) { + return ev.event.ident == id && ev.event.filter == filter; + }); + + return it != eq->m_events.cend(); +} + +static void TimerCallback(const boost::system::error_code& error, SceKernelEqueue eq, + SceKernelEvent kevent, SceKernelUseconds interval_ms) { + if (EventExists(eq, kevent.ident, kevent.filter)) { + eq->TriggerEvent(kevent.ident, SceKernelEvent::Filter::Timer, kevent.udata); + + if (!(kevent.flags & SceKernelEvent::Flags::OneShot)) { + auto timer = std::make_unique( + io_context, std::chrono::milliseconds(interval_ms)); + + timer->async_wait([eq, kevent, interval_ms](const boost::system::error_code& ec) { + TimerCallback(ec, eq, kevent, interval_ms); + }); + } + } +} + int PS4_SYSV_ABI sceKernelAddTimerEvent(SceKernelEqueue eq, int id, SceKernelUseconds usec, void* udata) { if (eq == nullptr) { return ORBIS_KERNEL_ERROR_EBADF; } + const u64 interval_ms = static_cast(usec & 0xFFFFFFFF) / 1000; + EqueueEvent event{}; event.event.ident = static_cast(id); event.event.filter = SceKernelEvent::Filter::Timer; event.event.flags = SceKernelEvent::Flags::Add; event.event.fflags = 0; - event.event.data = static_cast(usec & 0xFFFFFFFF) / 1000; + event.event.data = interval_ms; event.event.udata = udata; event.time_added = std::chrono::steady_clock::now(); LOG_INFO(Kernel_Event, "Added timing event: queue name={}, queue id={}, ms-intevall={}, func pointer={:x}", - eq->GetName(), event.event.ident, event.event.data, + eq->GetName(), event.event.ident, interval_ms, reinterpret_cast(udata)); + event.timer = std::make_unique( + io_context, std::chrono::milliseconds(interval_ms)); + + event.timer->async_wait( + [eq, event_data = event.event, interval_ms](const boost::system::error_code& ec) { + TimerCallback(ec, eq, event_data, interval_ms); + }); + if (!eq->AddEvent(event)) { return ORBIS_KERNEL_ERROR_ENOMEM; } diff --git a/src/core/libraries/kernel/equeue.h b/src/core/libraries/kernel/equeue.h index 2bd7ef510..e5847717a 100644 --- a/src/core/libraries/kernel/equeue.h +++ b/src/core/libraries/kernel/equeue.h @@ -152,10 +152,12 @@ public: int WaitForSmallTimer(SceKernelEvent* ev, int num, u32 micros); -private: - std::string m_name; std::mutex m_mutex; std::vector m_events; + +private: + std::string m_name; + EqueueEvent small_timer_event{}; std::condition_variable m_cond; };