From 4d5e9d1da495ea8ed31c7879f20ffb2db3b8e4b8 Mon Sep 17 00:00:00 2001
From: georgemoralis <giorgosmrls@gmail.com>
Date: Tue, 28 May 2024 15:13:56 +0300
Subject: [PATCH] set,poll event flag

---
 .../kernel/event_flag/event_flag.cpp          | 53 +++++++++++++++++--
 .../kernel/event_flag/event_flag_obj.cpp      | 20 +++++++
 .../kernel/event_flag/event_flag_obj.h        |  2 +
 3 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/src/core/libraries/kernel/event_flag/event_flag.cpp b/src/core/libraries/kernel/event_flag/event_flag.cpp
index 01efad70..fffce0f7 100644
--- a/src/core/libraries/kernel/event_flag/event_flag.cpp
+++ b/src/core/libraries/kernel/event_flag/event_flag.cpp
@@ -72,13 +72,60 @@ int PS4_SYSV_ABI sceKernelCancelEventFlag(OrbisKernelEventFlag ef, u64 setPatter
     return ORBIS_OK;
 }
 int PS4_SYSV_ABI sceKernelSetEventFlag(OrbisKernelEventFlag ef, u64 bitPattern) {
-    LOG_ERROR(Kernel_Event, "(STUBBED) called");
+    LOG_TRACE(Kernel_Event, "called");
+    if (ef == nullptr) {
+        return ORBIS_KERNEL_ERROR_ESRCH;
+    }
+    ef->Set(bitPattern);
     return ORBIS_OK;
 }
 int PS4_SYSV_ABI sceKernelPollEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, u32 waitMode,
                                         u64* pResultPat) {
-    LOG_ERROR(Kernel_Event, "(STUBBED) called");
-    return ORBIS_OK;
+    LOG_INFO(Kernel_Event, "called bitPattern = {:#x} waitMode = {:#x}", bitPattern, waitMode);
+
+    if (ef == nullptr) {
+        return ORBIS_KERNEL_ERROR_ESRCH;
+    }
+
+    if (bitPattern == 0) {
+        return ORBIS_KERNEL_ERROR_EINVAL;
+    }
+
+    EventFlagInternal::WaitMode wait = EventFlagInternal::WaitMode::And;
+    EventFlagInternal::ClearMode clear = EventFlagInternal::ClearMode::None;
+
+    switch (waitMode & 0xf) {
+    case 0x01:
+        wait = EventFlagInternal::WaitMode::And;
+        break;
+    case 0x02:
+        wait = EventFlagInternal::WaitMode::Or;
+        break;
+    default:
+        UNREACHABLE();
+    }
+
+    switch (waitMode & 0xf0) {
+    case 0x00:
+        clear = EventFlagInternal::ClearMode::None;
+        break;
+    case 0x10:
+        clear = EventFlagInternal::ClearMode::All;
+        break;
+    case 0x20:
+        clear = EventFlagInternal::ClearMode::Bits;
+        break;
+    default:
+        UNREACHABLE();
+    }
+
+    auto result = ef->Poll(bitPattern, wait, clear, pResultPat);
+
+    if (result != ORBIS_OK) {
+        LOG_ERROR(Kernel_Event, "returned {}", result);
+    }
+
+    return result;
 }
 int PS4_SYSV_ABI sceKernelWaitEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, u32 waitMode,
                                         u64* pResultPat, OrbisKernelUseconds* pTimeout) {
diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp
index 86250c35..069ae9dc 100644
--- a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp
+++ b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp
@@ -70,4 +70,24 @@ int EventFlagInternal::Wait(u64 bits, WaitMode wait_mode, ClearMode clear_mode,
 
     return ORBIS_OK;
 }
+
+int EventFlagInternal::Poll(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result) {
+    u32 micros = 0;
+    return Wait(bits, wait_mode, clear_mode, result, &micros);
+}
+
+void EventFlagInternal::Set(u64 bits) {
+    std::unique_lock lock{m_mutex};
+
+    while (m_status != Status::Set) {
+        m_mutex.unlock();
+        std::this_thread::sleep_for(std::chrono::microseconds(10));
+        m_mutex.lock();
+    }
+
+    m_bits |= bits;
+
+    m_cond_var.notify_all();
+}
+
 } // namespace Libraries::Kernel
\ No newline at end of file
diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.h b/src/core/libraries/kernel/event_flag/event_flag_obj.h
index 9284ec56..a4a85a8e 100644
--- a/src/core/libraries/kernel/event_flag/event_flag_obj.h
+++ b/src/core/libraries/kernel/event_flag/event_flag_obj.h
@@ -18,6 +18,8 @@ public:
         : m_name(name), m_single_thread(single), m_fifo(fifo), m_bits(bits){};
 
     int Wait(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result, u32* ptr_micros);
+    int Poll(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result);
+    void Set(u64 bits);
 
 private:
     enum class Status { Set, Canceled, Deleted };