Procházet zdrojové kódy

Merge pull request #5862 from bunnei/kevent

Kernel Rework: Refactor KEvent/KReadableEvent/KWritableEvent
bunnei před 5 roky
rodič
revize
1498a7c9a8
63 změnil soubory, kde provedl 737 přidání a 568 odebrání
  1. 6 0
      src/common/scope_exit.h
  2. 6 4
      src/core/CMakeLists.txt
  3. 2 2
      src/core/hle/kernel/hle_ipc.cpp
  4. 2 2
      src/core/hle/kernel/hle_ipc.h
  5. 8 2
      src/core/hle/kernel/k_address_arbiter.cpp
  6. 32 0
      src/core/hle/kernel/k_event.cpp
  7. 57 0
      src/core/hle/kernel/k_event.h
  8. 57 0
      src/core/hle/kernel/k_readable_event.cpp
  9. 51 0
      src/core/hle/kernel/k_readable_event.h
  10. 3 0
      src/core/hle/kernel/k_synchronization_object.cpp
  11. 1 0
      src/core/hle/kernel/k_synchronization_object.h
  12. 27 0
      src/core/hle/kernel/k_writable_event.cpp
  13. 44 0
      src/core/hle/kernel/k_writable_event.h
  14. 5 1
      src/core/hle/kernel/object.cpp
  15. 5 2
      src/core/hle/kernel/object.h
  16. 9 10
      src/core/hle/kernel/process.cpp
  17. 1 1
      src/core/hle/kernel/process.h
  18. 0 52
      src/core/hle/kernel/readable_event.cpp
  19. 0 59
      src/core/hle/kernel/readable_event.h
  20. 81 59
      src/core/hle/kernel/svc.cpp
  21. 1 0
      src/core/hle/kernel/svc_results.h
  22. 0 41
      src/core/hle/kernel/writable_event.cpp
  23. 0 60
      src/core/hle/kernel/writable_event.h
  24. 40 35
      src/core/hle/service/am/am.cpp
  25. 12 11
      src/core/hle/service/am/am.h
  26. 22 18
      src/core/hle/service/am/applets/applets.cpp
  27. 10 8
      src/core/hle/service/am/applets/applets.h
  28. 11 9
      src/core/hle/service/aoc/aoc_u.cpp
  29. 2 2
      src/core/hle/service/aoc/aoc_u.h
  30. 8 7
      src/core/hle/service/audio/audout_u.cpp
  31. 23 20
      src/core/hle/service/audio/audren_u.cpp
  32. 10 6
      src/core/hle/service/bcat/backend/backend.cpp
  33. 5 5
      src/core/hle/service/bcat/backend/backend.h
  34. 4 4
      src/core/hle/service/bcat/module.cpp
  35. 6 5
      src/core/hle/service/btdrv/btdrv.cpp
  36. 18 16
      src/core/hle/service/btm/btm.cpp
  37. 8 6
      src/core/hle/service/friend/friend.cpp
  38. 11 8
      src/core/hle/service/hid/controllers/npad.cpp
  39. 7 3
      src/core/hle/service/hid/controllers/npad.h
  40. 2 2
      src/core/hle/service/hid/hid.cpp
  41. 17 14
      src/core/hle/service/nfp/nfp.cpp
  42. 7 4
      src/core/hle/service/nfp/nfp.h
  43. 9 6
      src/core/hle/service/nifm/nifm.cpp
  44. 10 8
      src/core/hle/service/nim/nim.cpp
  45. 5 5
      src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
  46. 2 2
      src/core/hle/service/nvdrv/interface.cpp
  47. 1 1
      src/core/hle/service/nvdrv/interface.h
  48. 10 8
      src/core/hle/service/nvdrv/nvdrv.cpp
  49. 8 4
      src/core/hle/service/nvdrv/nvdrv.h
  50. 12 11
      src/core/hle/service/nvflinger/buffer_queue.cpp
  51. 7 5
      src/core/hle/service/nvflinger/buffer_queue.h
  52. 2 2
      src/core/hle/service/nvflinger/nvflinger.cpp
  53. 3 3
      src/core/hle/service/nvflinger/nvflinger.h
  54. 11 9
      src/core/hle/service/ptm/psm.cpp
  55. 5 3
      src/core/hle/service/time/standard_user_system_clock_core.cpp
  56. 5 2
      src/core/hle/service/time/standard_user_system_clock_core.h
  57. 2 2
      src/core/hle/service/time/system_clock_context_update_callback.cpp
  58. 3 3
      src/core/hle/service/time/system_clock_context_update_callback.h
  59. 8 6
      src/core/hle/service/vi/display/vi_display.cpp
  60. 6 3
      src/core/hle/service/vi/display/vi_display.h
  61. 2 2
      src/core/hle/service/vi/vi.cpp
  62. 3 3
      src/yuzu/debugger/wait_tree.cpp
  63. 2 2
      src/yuzu/debugger/wait_tree.h

+ 6 - 0
src/common/scope_exit.h

@@ -49,3 +49,9 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
  * \endcode
  */
 #define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)
+
+/**
+ * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
+ * used when the caller might want to cancel the ScopeExit.
+ */
+#define SCOPE_GUARD(body) detail::ScopeExit([&]() body)

+ 6 - 4
src/core/CMakeLists.txt

@@ -160,10 +160,14 @@ add_library(core STATIC
     hle/kernel/k_affinity_mask.h
     hle/kernel/k_condition_variable.cpp
     hle/kernel/k_condition_variable.h
+    hle/kernel/k_event.cpp
+    hle/kernel/k_event.h
     hle/kernel/k_light_condition_variable.h
     hle/kernel/k_light_lock.cpp
     hle/kernel/k_light_lock.h
     hle/kernel/k_priority_queue.h
+    hle/kernel/k_readable_event.cpp
+    hle/kernel/k_readable_event.h
     hle/kernel/k_resource_limit.cpp
     hle/kernel/k_resource_limit.h
     hle/kernel/k_scheduler.cpp
@@ -176,6 +180,8 @@ add_library(core STATIC
     hle/kernel/k_thread.cpp
     hle/kernel/k_thread.h
     hle/kernel/k_thread_queue.h
+    hle/kernel/k_writable_event.cpp
+    hle/kernel/k_writable_event.h
     hle/kernel/kernel.cpp
     hle/kernel/kernel.h
     hle/kernel/memory/address_space_info.cpp
@@ -204,8 +210,6 @@ add_library(core STATIC
     hle/kernel/process.h
     hle/kernel/process_capability.cpp
     hle/kernel/process_capability.h
-    hle/kernel/readable_event.cpp
-    hle/kernel/readable_event.h
     hle/kernel/server_port.cpp
     hle/kernel/server_port.h
     hle/kernel/server_session.cpp
@@ -226,8 +230,6 @@ add_library(core STATIC
     hle/kernel/time_manager.h
     hle/kernel/transfer_memory.cpp
     hle/kernel/transfer_memory.h
-    hle/kernel/writable_event.cpp
-    hle/kernel/writable_event.h
     hle/lock.cpp
     hle/lock.h
     hle/result.h

+ 2 - 2
src/core/hle/kernel/hle_ipc.cpp

@@ -17,16 +17,16 @@
 #include "core/hle/kernel/errors.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_scheduler.h"
 #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
 #include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/object.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/server_session.h"
 #include "core/hle/kernel/time_manager.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/memory.h"
 
 namespace Kernel {

+ 2 - 2
src/core/hle/kernel/hle_ipc.h

@@ -41,8 +41,8 @@ class KernelCore;
 class Process;
 class ServerSession;
 class KThread;
-class ReadableEvent;
-class WritableEvent;
+class KReadableEvent;
+class KWritableEvent;
 
 enum class ThreadWakeupReason;
 

+ 8 - 2
src/core/hle/kernel/k_address_arbiter.cpp

@@ -120,7 +120,10 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
         s32 user_value{};
         R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1),
                  Svc::ResultInvalidCurrentMemory);
-        R_UNLESS(user_value == value, Svc::ResultInvalidState);
+
+        if (user_value != value) {
+            return Svc::ResultInvalidState;
+        }
 
         auto it = thread_tree.nfind_light({addr, -1});
         while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
@@ -211,7 +214,10 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
         }
 
         R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory);
-        R_UNLESS(user_value == value, Svc::ResultInvalidState);
+
+        if (user_value != value) {
+            return Svc::ResultInvalidState;
+        }
 
         while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
                (it->GetAddressArbiterKey() == addr)) {

+ 32 - 0
src/core/hle/kernel/k_event.cpp

@@ -0,0 +1,32 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
+
+namespace Kernel {
+
+KEvent::KEvent(KernelCore& kernel, std::string&& name) : Object{kernel, std::move(name)} {}
+
+KEvent::~KEvent() = default;
+
+std::shared_ptr<KEvent> KEvent::Create(KernelCore& kernel, std::string&& name) {
+    return std::make_shared<KEvent>(kernel, std::move(name));
+}
+
+void KEvent::Initialize() {
+    // Create our sub events.
+    readable_event = std::make_shared<KReadableEvent>(kernel, GetName() + ":Readable");
+    writable_event = std::make_shared<KWritableEvent>(kernel, GetName() + ":Writable");
+
+    // Initialize our sub sessions.
+    readable_event->Initialize(this);
+    writable_event->Initialize(this);
+
+    // Mark initialized.
+    initialized = true;
+}
+
+} // namespace Kernel

+ 57 - 0
src/core/hle/kernel/k_event.h

@@ -0,0 +1,57 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/object.h"
+
+namespace Kernel {
+
+class KernelCore;
+class KReadableEvent;
+class KWritableEvent;
+
+class KEvent final : public Object {
+public:
+    explicit KEvent(KernelCore& kernel, std::string&& name);
+    ~KEvent() override;
+
+    static std::shared_ptr<KEvent> Create(KernelCore& kernel, std::string&& name);
+
+    void Initialize();
+
+    void Finalize() override {}
+
+    std::string GetTypeName() const override {
+        return "KEvent";
+    }
+
+    static constexpr HandleType HANDLE_TYPE = HandleType::Event;
+    HandleType GetHandleType() const override {
+        return HANDLE_TYPE;
+    }
+
+    std::shared_ptr<KReadableEvent>& GetReadableEvent() {
+        return readable_event;
+    }
+
+    std::shared_ptr<KWritableEvent>& GetWritableEvent() {
+        return writable_event;
+    }
+
+    const std::shared_ptr<KReadableEvent>& GetReadableEvent() const {
+        return readable_event;
+    }
+
+    const std::shared_ptr<KWritableEvent>& GetWritableEvent() const {
+        return writable_event;
+    }
+
+private:
+    std::shared_ptr<KReadableEvent> readable_event;
+    std::shared_ptr<KWritableEvent> writable_event;
+    bool initialized{};
+};
+
+} // namespace Kernel

+ 57 - 0
src/core/hle/kernel/k_readable_event.cpp

@@ -0,0 +1,57 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include "common/assert.h"
+#include "common/common_funcs.h"
+#include "common/logging/log.h"
+#include "core/hle/kernel/errors.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
+#include "core/hle/kernel/svc_results.h"
+
+namespace Kernel {
+
+KReadableEvent::KReadableEvent(KernelCore& kernel, std::string&& name)
+    : KSynchronizationObject{kernel, std::move(name)} {}
+KReadableEvent::~KReadableEvent() = default;
+
+bool KReadableEvent::IsSignaled() const {
+    ASSERT(kernel.GlobalSchedulerContext().IsLocked());
+
+    return is_signaled;
+}
+
+ResultCode KReadableEvent::Signal() {
+    KScopedSchedulerLock lk{kernel};
+
+    if (!is_signaled) {
+        is_signaled = true;
+        NotifyAvailable();
+    }
+
+    return RESULT_SUCCESS;
+}
+
+ResultCode KReadableEvent::Clear() {
+    Reset();
+
+    return RESULT_SUCCESS;
+}
+
+ResultCode KReadableEvent::Reset() {
+    KScopedSchedulerLock lk{kernel};
+
+    if (!is_signaled) {
+        return Svc::ResultInvalidState;
+    }
+
+    is_signaled = false;
+    return RESULT_SUCCESS;
+}
+
+} // namespace Kernel

+ 51 - 0
src/core/hle/kernel/k_readable_event.h

@@ -0,0 +1,51 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/k_synchronization_object.h"
+#include "core/hle/kernel/object.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+class KernelCore;
+class KEvent;
+
+class KReadableEvent final : public KSynchronizationObject {
+public:
+    explicit KReadableEvent(KernelCore& kernel, std::string&& name);
+    ~KReadableEvent() override;
+
+    std::string GetTypeName() const override {
+        return "KReadableEvent";
+    }
+
+    static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
+    HandleType GetHandleType() const override {
+        return HANDLE_TYPE;
+    }
+
+    KEvent* GetParent() const {
+        return parent;
+    }
+
+    void Initialize(KEvent* parent_) {
+        is_signaled = false;
+        parent = parent_;
+    }
+
+    bool IsSignaled() const override;
+    void Finalize() override {}
+
+    ResultCode Signal();
+    ResultCode Clear();
+    ResultCode Reset();
+
+private:
+    bool is_signaled{};
+    KEvent* parent{};
+};
+
+} // namespace Kernel

+ 3 - 0
src/core/hle/kernel/k_synchronization_object.cpp

@@ -132,6 +132,9 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
 
 KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {}
 
+KSynchronizationObject::KSynchronizationObject(KernelCore& kernel, std::string&& name)
+    : Object{kernel, std::move(name)} {}
+
 KSynchronizationObject::~KSynchronizationObject() = default;
 
 void KSynchronizationObject::NotifyAvailable(ResultCode result) {

+ 1 - 0
src/core/hle/kernel/k_synchronization_object.h

@@ -33,6 +33,7 @@ public:
 
 protected:
     explicit KSynchronizationObject(KernelCore& kernel);
+    explicit KSynchronizationObject(KernelCore& kernel, std::string&& name);
     virtual ~KSynchronizationObject();
 
     void NotifyAvailable(ResultCode result);

+ 27 - 0
src/core/hle/kernel/k_writable_event.cpp

@@ -0,0 +1,27 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
+
+namespace Kernel {
+
+KWritableEvent::KWritableEvent(KernelCore& kernel, std::string&& name)
+    : Object{kernel, std::move(name)} {}
+KWritableEvent::~KWritableEvent() = default;
+
+void KWritableEvent::Initialize(KEvent* parent_) {
+    parent = parent_;
+}
+
+ResultCode KWritableEvent::Signal() {
+    return parent->GetReadableEvent()->Signal();
+}
+
+ResultCode KWritableEvent::Clear() {
+    return parent->GetReadableEvent()->Clear();
+}
+
+} // namespace Kernel

+ 44 - 0
src/core/hle/kernel/k_writable_event.h

@@ -0,0 +1,44 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/object.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+class KernelCore;
+class KEvent;
+
+class KWritableEvent final : public Object {
+public:
+    explicit KWritableEvent(KernelCore& kernel, std::string&& name);
+    ~KWritableEvent() override;
+
+    std::string GetTypeName() const override {
+        return "KWritableEvent";
+    }
+
+    static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
+    HandleType GetHandleType() const override {
+        return HANDLE_TYPE;
+    }
+
+    void Initialize(KEvent* parent_);
+
+    void Finalize() override {}
+
+    ResultCode Signal();
+    ResultCode Clear();
+
+    KEvent* GetParent() const {
+        return parent;
+    }
+
+private:
+    KEvent* parent{};
+};
+
+} // namespace Kernel

+ 5 - 1
src/core/hle/kernel/object.cpp

@@ -8,7 +8,10 @@
 
 namespace Kernel {
 
-Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {}
+Object::Object(KernelCore& kernel_)
+    : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{"[UNKNOWN KERNEL OBJECT]"} {}
+Object::Object(KernelCore& kernel_, std::string&& name_)
+    : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{std::move(name_)} {}
 Object::~Object() = default;
 
 bool Object::IsWaitable() const {
@@ -21,6 +24,7 @@ bool Object::IsWaitable() const {
         return true;
 
     case HandleType::Unknown:
+    case HandleType::Event:
     case HandleType::WritableEvent:
     case HandleType::SharedMemory:
     case HandleType::TransferMemory:

+ 5 - 2
src/core/hle/kernel/object.h

@@ -18,6 +18,7 @@ using Handle = u32;
 
 enum class HandleType : u32 {
     Unknown,
+    Event,
     WritableEvent,
     ReadableEvent,
     SharedMemory,
@@ -34,7 +35,8 @@ enum class HandleType : u32 {
 
 class Object : NonCopyable, public std::enable_shared_from_this<Object> {
 public:
-    explicit Object(KernelCore& kernel);
+    explicit Object(KernelCore& kernel_);
+    explicit Object(KernelCore& kernel_, std::string&& name_);
     virtual ~Object();
 
     /// Returns a unique identifier for the object. For debugging purposes only.
@@ -46,7 +48,7 @@ public:
         return "[BAD KERNEL OBJECT TYPE]";
     }
     virtual std::string GetName() const {
-        return "[UNKNOWN KERNEL OBJECT]";
+        return name;
     }
     virtual HandleType GetHandleType() const = 0;
 
@@ -69,6 +71,7 @@ protected:
 
 private:
     std::atomic<u32> object_id{0};
+    std::string name;
 };
 
 template <typename T>

+ 9 - 10
src/core/hle/kernel/process.cpp

@@ -23,6 +23,7 @@
 #include "core/hle/kernel/memory/page_table.h"
 #include "core/hle/kernel/memory/slab_heap.h"
 #include "core/hle/kernel/process.h"
+#include "core/hle/kernel/svc_results.h"
 #include "core/hle/lock.h"
 #include "core/memory.h"
 #include "core/settings.h"
@@ -241,18 +242,16 @@ void Process::UnregisterThread(const KThread* thread) {
     thread_list.remove(thread);
 }
 
-ResultCode Process::ClearSignalState() {
-    KScopedSchedulerLock lock(system.Kernel());
-    if (status == ProcessStatus::Exited) {
-        LOG_ERROR(Kernel, "called on a terminated process instance.");
-        return ERR_INVALID_STATE;
-    }
+ResultCode Process::Reset() {
+    // Lock the process and the scheduler.
+    KScopedLightLock lk(state_lock);
+    KScopedSchedulerLock sl{kernel};
 
-    if (!is_signaled) {
-        LOG_ERROR(Kernel, "called on a process instance that isn't signaled.");
-        return ERR_INVALID_STATE;
-    }
+    // Validate that we're in a state that we can reset.
+    R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState);
+    R_UNLESS(is_signaled, Svc::ResultInvalidState);
 
+    // Clear signaled.
     is_signaled = false;
     return RESULT_SUCCESS;
 }

+ 1 - 1
src/core/hle/kernel/process.h

@@ -312,7 +312,7 @@ public:
     /// @pre The process must be in a signaled state. If this is called on a
     ///      process instance that is not signaled, ERR_INVALID_STATE will be
     ///      returned.
-    ResultCode ClearSignalState();
+    ResultCode Reset();
 
     /**
      * Loads process-specifics configuration info with metadata provided

+ 0 - 52
src/core/hle/kernel/readable_event.cpp

@@ -1,52 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include "common/assert.h"
-#include "common/logging/log.h"
-#include "core/hle/kernel/errors.h"
-#include "core/hle/kernel/k_scheduler.h"
-#include "core/hle/kernel/k_thread.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/object.h"
-#include "core/hle/kernel/readable_event.h"
-
-namespace Kernel {
-
-ReadableEvent::ReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {}
-ReadableEvent::~ReadableEvent() = default;
-
-void ReadableEvent::Signal() {
-    if (is_signaled) {
-        return;
-    }
-
-    is_signaled = true;
-    NotifyAvailable();
-}
-
-bool ReadableEvent::IsSignaled() const {
-    ASSERT(kernel.GlobalSchedulerContext().IsLocked());
-
-    return is_signaled;
-}
-
-void ReadableEvent::Clear() {
-    is_signaled = false;
-}
-
-ResultCode ReadableEvent::Reset() {
-    KScopedSchedulerLock lock(kernel);
-    if (!is_signaled) {
-        LOG_TRACE(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}",
-                  GetObjectId(), GetTypeName(), GetName());
-        return ERR_INVALID_STATE;
-    }
-
-    Clear();
-
-    return RESULT_SUCCESS;
-}
-
-} // namespace Kernel

+ 0 - 59
src/core/hle/kernel/readable_event.h

@@ -1,59 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/kernel/k_synchronization_object.h"
-#include "core/hle/kernel/object.h"
-
-union ResultCode;
-
-namespace Kernel {
-
-class KernelCore;
-class WritableEvent;
-
-class ReadableEvent final : public KSynchronizationObject {
-    friend class WritableEvent;
-
-public:
-    ~ReadableEvent() override;
-
-    std::string GetTypeName() const override {
-        return "ReadableEvent";
-    }
-    std::string GetName() const override {
-        return name;
-    }
-
-    static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
-    HandleType GetHandleType() const override {
-        return HANDLE_TYPE;
-    }
-
-    /// Unconditionally clears the readable event's state.
-    void Clear();
-
-    /// Clears the readable event's state if and only if it
-    /// has already been signaled.
-    ///
-    /// @pre The event must be in a signaled state. If this event
-    ///      is in an unsignaled state and this function is called,
-    ///      then ERR_INVALID_STATE will be returned.
-    ResultCode Reset();
-
-    void Signal();
-
-    bool IsSignaled() const override;
-
-    void Finalize() override {}
-
-private:
-    explicit ReadableEvent(KernelCore& kernel);
-
-    bool is_signaled{};
-    std::string name; ///< Name of event (optional)
-};
-
-} // namespace Kernel

+ 81 - 59
src/core/hle/kernel/svc.cpp

@@ -14,6 +14,7 @@
 #include "common/fiber.h"
 #include "common/logging/log.h"
 #include "common/microprofile.h"
+#include "common/scope_exit.h"
 #include "common/string_util.h"
 #include "core/arm/exclusive_monitor.h"
 #include "core/core.h"
@@ -26,18 +27,20 @@
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/k_address_arbiter.h"
 #include "core/hle/kernel/k_condition_variable.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_resource_limit.h"
 #include "core/hle/kernel/k_scheduler.h"
 #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
 #include "core/hle/kernel/k_synchronization_object.h"
 #include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/memory/memory_block.h"
 #include "core/hle/kernel/memory/memory_layout.h"
 #include "core/hle/kernel/memory/page_table.h"
 #include "core/hle/kernel/physical_core.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/shared_memory.h"
 #include "core/hle/kernel/svc.h"
 #include "core/hle/kernel/svc_results.h"
@@ -45,7 +48,6 @@
 #include "core/hle/kernel/svc_wrap.h"
 #include "core/hle/kernel/time_manager.h"
 #include "core/hle/kernel/transfer_memory.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/lock.h"
 #include "core/hle/result.h"
 #include "core/hle/service/service.h"
@@ -1725,20 +1727,28 @@ static ResultCode CloseHandle32(Core::System& system, Handle handle) {
 static ResultCode ResetSignal(Core::System& system, Handle handle) {
     LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
 
+    // Get the current handle table.
     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
 
-    auto event = handle_table.Get<ReadableEvent>(handle);
-    if (event) {
-        return event->Reset();
+    // Try to reset as readable event.
+    {
+        auto readable_event = handle_table.Get<KReadableEvent>(handle);
+        if (readable_event) {
+            return readable_event->Reset();
+        }
     }
 
-    auto process = handle_table.Get<Process>(handle);
-    if (process) {
-        return process->ClearSignalState();
+    // Try to reset as process.
+    {
+        auto process = handle_table.Get<Process>(handle);
+        if (process) {
+            return process->Reset();
+        }
     }
 
-    LOG_ERROR(Kernel_SVC, "Invalid handle (0x{:08X})", handle);
-    return ERR_INVALID_HANDLE;
+    LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle);
+
+    return Svc::ResultInvalidHandle;
 }
 
 static ResultCode ResetSignal32(Core::System& system, Handle handle) {
@@ -1866,80 +1876,92 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle
     return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
 }
 
-static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
-    LOG_DEBUG(Kernel_SVC, "called");
+static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
+    LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
 
-    auto& kernel = system.Kernel();
-    const auto [readable_event, writable_event] =
-        WritableEvent::CreateEventPair(kernel, "CreateEvent");
+    // Get the current handle table.
+    const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
 
-    HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
+    // Get the writable event.
+    auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
+    R_UNLESS(writable_event, Svc::ResultInvalidHandle);
 
-    const auto write_create_result = handle_table.Create(writable_event);
-    if (write_create_result.Failed()) {
-        return write_create_result.Code();
-    }
-    *write_handle = *write_create_result;
-
-    const auto read_create_result = handle_table.Create(readable_event);
-    if (read_create_result.Failed()) {
-        handle_table.Close(*write_create_result);
-        return read_create_result.Code();
-    }
-    *read_handle = *read_create_result;
-
-    LOG_DEBUG(Kernel_SVC,
-              "successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}",
-              *write_create_result, *read_create_result);
-    return RESULT_SUCCESS;
+    return writable_event->Signal();
 }
 
-static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) {
-    return CreateEvent(system, write_handle, read_handle);
+static ResultCode SignalEvent32(Core::System& system, Handle event_handle) {
+    return SignalEvent(system, event_handle);
 }
 
-static ResultCode ClearEvent(Core::System& system, Handle handle) {
-    LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
+static ResultCode ClearEvent(Core::System& system, Handle event_handle) {
+    LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
 
+    // Get the current handle table.
     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
 
-    auto writable_event = handle_table.Get<WritableEvent>(handle);
-    if (writable_event) {
-        writable_event->Clear();
-        return RESULT_SUCCESS;
+    // Try to clear the writable event.
+    {
+        auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
+        if (writable_event) {
+            return writable_event->Clear();
+        }
     }
 
-    auto readable_event = handle_table.Get<ReadableEvent>(handle);
-    if (readable_event) {
-        readable_event->Clear();
-        return RESULT_SUCCESS;
+    // Try to clear the readable event.
+    {
+        auto readable_event = handle_table.Get<KReadableEvent>(event_handle);
+        if (readable_event) {
+            return readable_event->Clear();
+        }
     }
 
-    LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle);
-    return ERR_INVALID_HANDLE;
+    LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle);
+
+    return Svc::ResultInvalidHandle;
 }
 
-static ResultCode ClearEvent32(Core::System& system, Handle handle) {
-    return ClearEvent(system, handle);
+static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
+    return ClearEvent(system, event_handle);
 }
 
-static ResultCode SignalEvent(Core::System& system, Handle handle) {
-    LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle);
+static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
+    LOG_DEBUG(Kernel_SVC, "called");
+
+    // Get the kernel reference and handle table.
+    auto& kernel = system.Kernel();
+    HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
+
+    // Create a new event.
+    const auto event = KEvent::Create(kernel, "CreateEvent");
+    R_UNLESS(event != nullptr, Svc::ResultOutOfResource);
 
-    HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
-    auto writable_event = handle_table.Get<WritableEvent>(handle);
+    // Initialize the event.
+    event->Initialize();
 
-    if (!writable_event) {
-        LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle);
-        return ERR_INVALID_HANDLE;
+    // Add the writable event to the handle table.
+    const auto write_create_result = handle_table.Create(event->GetWritableEvent());
+    if (write_create_result.Failed()) {
+        return write_create_result.Code();
+    }
+    *out_write = *write_create_result;
+
+    // Add the writable event to the handle table.
+    auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); });
+
+    // Add the readable event to the handle table.
+    const auto read_create_result = handle_table.Create(event->GetReadableEvent());
+    if (read_create_result.Failed()) {
+        return read_create_result.Code();
     }
+    *out_read = *read_create_result;
 
-    writable_event->Signal();
+    // We succeeded.
+    handle_guard.Cancel();
     return RESULT_SUCCESS;
 }
 
-static ResultCode SignalEvent32(Core::System& system, Handle handle) {
-    return SignalEvent(system, handle);
+static ResultCode CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
+    return CreateEvent(system, out_write, out_read);
 }
 
 static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {

+ 1 - 0
src/core/hle/kernel/svc_results.h

@@ -11,6 +11,7 @@ namespace Kernel::Svc {
 constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
 constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
 constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
+constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103};
 constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
 constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
 constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};

+ 0 - 41
src/core/hle/kernel/writable_event.cpp

@@ -1,41 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include "common/assert.h"
-#include "core/hle/kernel/k_thread.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/object.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
-
-namespace Kernel {
-
-WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
-WritableEvent::~WritableEvent() = default;
-
-EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
-    std::shared_ptr<WritableEvent> writable_event(new WritableEvent(kernel));
-    std::shared_ptr<ReadableEvent> readable_event(new ReadableEvent(kernel));
-
-    writable_event->name = name + ":Writable";
-    writable_event->readable = readable_event;
-    readable_event->name = name + ":Readable";
-
-    return {std::move(readable_event), std::move(writable_event)};
-}
-
-std::shared_ptr<ReadableEvent> WritableEvent::GetReadableEvent() const {
-    return readable;
-}
-
-void WritableEvent::Signal() {
-    readable->Signal();
-}
-
-void WritableEvent::Clear() {
-    readable->Clear();
-}
-
-} // namespace Kernel

+ 0 - 60
src/core/hle/kernel/writable_event.h

@@ -1,60 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-
-#include "core/hle/kernel/object.h"
-
-namespace Kernel {
-
-class KernelCore;
-class ReadableEvent;
-class WritableEvent;
-
-struct EventPair {
-    std::shared_ptr<ReadableEvent> readable;
-    std::shared_ptr<WritableEvent> writable;
-};
-
-class WritableEvent final : public Object {
-public:
-    ~WritableEvent() override;
-
-    /**
-     * Creates an event
-     * @param kernel The kernel instance to create this event under.
-     * @param name Optional name of event
-     */
-    static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown");
-
-    std::string GetTypeName() const override {
-        return "WritableEvent";
-    }
-    std::string GetName() const override {
-        return name;
-    }
-
-    static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
-    HandleType GetHandleType() const override {
-        return HANDLE_TYPE;
-    }
-
-    std::shared_ptr<ReadableEvent> GetReadableEvent() const;
-
-    void Signal();
-    void Clear();
-
-    void Finalize() override {}
-
-private:
-    explicit WritableEvent(KernelCore& kernel);
-
-    std::shared_ptr<ReadableEvent> readable;
-
-    std::string name; ///< Name of event (optional)
-};
-
-} // namespace Kernel

+ 40 - 35
src/core/hle/service/am/am.cpp

@@ -13,11 +13,12 @@
 #include "core/file_sys/registered_cache.h"
 #include "core/file_sys/savedata_factory.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/transfer_memory.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_ae.h"
@@ -303,17 +304,18 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
     RegisterHandlers(functions);
 
     auto& kernel = system.Kernel();
-    launchable_event =
-        Kernel::WritableEvent::CreateEventPair(kernel, "ISelfController:LaunchableEvent");
+    launchable_event = Kernel::KEvent::Create(kernel, "ISelfController:LaunchableEvent");
+    launchable_event->Initialize();
 
     // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
     // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
     // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
     // suspended if the event has previously been created by a call to
     // GetAccumulatedSuspendedTickChangedEvent.
-    accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair(
-        kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent");
-    accumulated_suspended_tick_changed_event.writable->Signal();
+    accumulated_suspended_tick_changed_event =
+        Kernel::KEvent::Create(kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent");
+    accumulated_suspended_tick_changed_event->Initialize();
+    accumulated_suspended_tick_changed_event->GetWritableEvent()->Signal();
 }
 
 ISelfController::~ISelfController() = default;
@@ -372,11 +374,11 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
 void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
     LOG_WARNING(Service_AM, "(STUBBED) called");
 
-    launchable_event.writable->Signal();
+    launchable_event->GetWritableEvent()->Signal();
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(launchable_event.readable);
+    rb.PushCopyObjects(launchable_event->GetReadableEvent());
 }
 
 void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
@@ -555,41 +557,42 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(accumulated_suspended_tick_changed_event.readable);
+    rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
 }
 
 AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) {
-    on_new_message =
-        Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OnMessageReceived");
+    on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived");
+    on_new_message->Initialize();
     on_operation_mode_changed =
-        Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OperationModeChanged");
+        Kernel::KEvent::Create(kernel, "AMMessageQueue:OperationModeChanged");
+    on_operation_mode_changed->Initialize();
 }
 
 AppletMessageQueue::~AppletMessageQueue() = default;
 
-const std::shared_ptr<Kernel::ReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const {
-    return on_new_message.readable;
+const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const {
+    return on_new_message->GetReadableEvent();
 }
 
-const std::shared_ptr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
+const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
     const {
-    return on_operation_mode_changed.readable;
+    return on_operation_mode_changed->GetReadableEvent();
 }
 
 void AppletMessageQueue::PushMessage(AppletMessage msg) {
     messages.push(msg);
-    on_new_message.writable->Signal();
+    on_new_message->GetWritableEvent()->Signal();
 }
 
 AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
     if (messages.empty()) {
-        on_new_message.writable->Clear();
+        on_new_message->GetWritableEvent()->Clear();
         return AppletMessage::NoMessage;
     }
     auto msg = messages.front();
     messages.pop();
     if (messages.empty()) {
-        on_new_message.writable->Clear();
+        on_new_message->GetWritableEvent()->Clear();
     }
     return msg;
 }
@@ -601,7 +604,7 @@ std::size_t AppletMessageQueue::GetMessageCount() const {
 void AppletMessageQueue::OperationModeChanged() {
     PushMessage(AppletMessage::OperationModeChanged);
     PushMessage(AppletMessage::PerformanceModeChanged);
-    on_operation_mode_changed.writable->Signal();
+    on_operation_mode_changed->GetWritableEvent()->Signal();
 }
 
 void AppletMessageQueue::RequestExit() {
@@ -1229,14 +1232,15 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
     RegisterHandlers(functions);
 
     auto& kernel = system.Kernel();
-    gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair(
-        kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
-
-    friend_invitation_storage_channel_event = Kernel::WritableEvent::CreateEventPair(
-        kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent");
-
-    health_warning_disappeared_system_event = Kernel::WritableEvent::CreateEventPair(
-        kernel, "IApplicationFunctions:HealthWarningDisappearedSystemEvent");
+    gpu_error_detected_event =
+        Kernel::KEvent::Create(kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
+    gpu_error_detected_event->Initialize();
+    friend_invitation_storage_channel_event =
+        Kernel::KEvent::Create(kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent");
+    friend_invitation_storage_channel_event->Initialize();
+    health_warning_disappeared_system_event =
+        Kernel::KEvent::Create(kernel, "IApplicationFunctions:HealthWarningDisappearedSystemEvent");
+    health_warning_disappeared_system_event->Initialize();
 }
 
 IApplicationFunctions::~IApplicationFunctions() = default;
@@ -1633,7 +1637,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestCon
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(gpu_error_detected_event.readable);
+    rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
 }
 
 void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
@@ -1641,7 +1645,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(friend_invitation_storage_channel_event.readable);
+    rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
 }
 
 void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
@@ -1657,7 +1661,7 @@ void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERe
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(health_warning_disappeared_system_event.readable);
+    rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
 }
 
 void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
@@ -1693,8 +1697,9 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
 
     RegisterHandlers(functions);
 
-    pop_from_general_channel_event = Kernel::WritableEvent::CreateEventPair(
-        system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent");
+    pop_from_general_channel_event =
+        Kernel::KEvent::Create(system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent");
+    pop_from_general_channel_event->Initialize();
 }
 
 IHomeMenuFunctions::~IHomeMenuFunctions() = default;
@@ -1711,7 +1716,7 @@ void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(pop_from_general_channel_event.readable);
+    rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
 }
 
 IGlobalStateController::IGlobalStateController(Core::System& system_)

+ 12 - 11
src/core/hle/service/am/am.h

@@ -7,11 +7,12 @@
 #include <chrono>
 #include <memory>
 #include <queue>
-#include "core/hle/kernel/writable_event.h"
+
 #include "core/hle/service/service.h"
 
 namespace Kernel {
 class KernelCore;
+class KEvent;
 class TransferMemory;
 } // namespace Kernel
 
@@ -55,8 +56,8 @@ public:
     explicit AppletMessageQueue(Kernel::KernelCore& kernel);
     ~AppletMessageQueue();
 
-    const std::shared_ptr<Kernel::ReadableEvent>& GetMessageReceiveEvent() const;
-    const std::shared_ptr<Kernel::ReadableEvent>& GetOperationModeChangedEvent() const;
+    const std::shared_ptr<Kernel::KReadableEvent>& GetMessageReceiveEvent() const;
+    const std::shared_ptr<Kernel::KReadableEvent>& GetOperationModeChangedEvent() const;
     void PushMessage(AppletMessage msg);
     AppletMessage PopMessage();
     std::size_t GetMessageCount() const;
@@ -65,8 +66,8 @@ public:
 
 private:
     std::queue<AppletMessage> messages;
-    Kernel::EventPair on_new_message;
-    Kernel::EventPair on_operation_mode_changed;
+    std::shared_ptr<Kernel::KEvent> on_new_message;
+    std::shared_ptr<Kernel::KEvent> on_operation_mode_changed;
 };
 
 class IWindowController final : public ServiceFramework<IWindowController> {
@@ -153,8 +154,8 @@ private:
     };
 
     NVFlinger::NVFlinger& nvflinger;
-    Kernel::EventPair launchable_event;
-    Kernel::EventPair accumulated_suspended_tick_changed_event;
+    std::shared_ptr<Kernel::KEvent> launchable_event;
+    std::shared_ptr<Kernel::KEvent> accumulated_suspended_tick_changed_event;
 
     u32 idle_time_detection_extension = 0;
     u64 num_fatal_sections_entered = 0;
@@ -295,9 +296,9 @@ private:
     bool launch_popped_application_specific = false;
     bool launch_popped_account_preselect = false;
     s32 previous_program_index{-1};
-    Kernel::EventPair gpu_error_detected_event;
-    Kernel::EventPair friend_invitation_storage_channel_event;
-    Kernel::EventPair health_warning_disappeared_system_event;
+    std::shared_ptr<Kernel::KEvent> gpu_error_detected_event;
+    std::shared_ptr<Kernel::KEvent> friend_invitation_storage_channel_event;
+    std::shared_ptr<Kernel::KEvent> health_warning_disappeared_system_event;
 };
 
 class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
@@ -309,7 +310,7 @@ private:
     void RequestToGetForeground(Kernel::HLERequestContext& ctx);
     void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx);
 
-    Kernel::EventPair pop_from_general_channel_event;
+    std::shared_ptr<Kernel::KEvent> pop_from_general_channel_event;
 };
 
 class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {

+ 22 - 18
src/core/hle/service/am/applets/applets.cpp

@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 
 #include <cstring>
+
 #include "common/assert.h"
 #include "core/core.h"
 #include "core/frontend/applets/controller.h"
@@ -11,9 +12,10 @@
 #include "core/frontend/applets/profile_select.h"
 #include "core/frontend/applets/software_keyboard.h"
 #include "core/frontend/applets/web_browser.h"
-#include "core/hle/kernel/readable_event.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/server_session.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applets.h"
 #include "core/hle/service/am/applets/controller.h"
@@ -27,11 +29,13 @@ namespace Service::AM::Applets {
 
 AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
     state_changed_event =
-        Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:StateChangedEvent");
-    pop_out_data_event =
-        Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
-    pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
-        kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
+        Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:StateChangedEvent");
+    state_changed_event->Initialize();
+    pop_out_data_event = Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
+    pop_out_data_event->Initialize();
+    pop_interactive_out_data_event =
+        Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
+    pop_interactive_out_data_event->Initialize();
 }
 
 AppletDataBroker::~AppletDataBroker() = default;
@@ -58,7 +62,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
 
     auto out = std::move(out_channel.front());
     out_channel.pop_front();
-    pop_out_data_event.writable->Clear();
+    pop_out_data_event->GetWritableEvent()->Clear();
     return out;
 }
 
@@ -77,7 +81,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
 
     auto out = std::move(out_interactive_channel.front());
     out_interactive_channel.pop_front();
-    pop_interactive_out_data_event.writable->Clear();
+    pop_interactive_out_data_event->GetWritableEvent()->Clear();
     return out;
 }
 
@@ -96,7 +100,7 @@ void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storag
 
 void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) {
     out_channel.emplace_back(std::move(storage));
-    pop_out_data_event.writable->Signal();
+    pop_out_data_event->GetWritableEvent()->Signal();
 }
 
 void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) {
@@ -105,23 +109,23 @@ void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& s
 
 void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) {
     out_interactive_channel.emplace_back(std::move(storage));
-    pop_interactive_out_data_event.writable->Signal();
+    pop_interactive_out_data_event->GetWritableEvent()->Signal();
 }
 
 void AppletDataBroker::SignalStateChanged() const {
-    state_changed_event.writable->Signal();
+    state_changed_event->GetWritableEvent()->Signal();
 }
 
-std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
-    return pop_out_data_event.readable;
+std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
+    return pop_out_data_event->GetReadableEvent();
 }
 
-std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
-    return pop_interactive_out_data_event.readable;
+std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
+    return pop_interactive_out_data_event->GetReadableEvent();
 }
 
-std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
-    return state_changed_event.readable;
+std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
+    return state_changed_event->GetReadableEvent();
 }
 
 Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {}

+ 10 - 8
src/core/hle/service/am/applets/applets.h

@@ -6,9 +6,9 @@
 
 #include <memory>
 #include <queue>
+
 #include "common/swap.h"
 #include "core/hle/kernel/object.h"
-#include "core/hle/kernel/writable_event.h"
 
 union ResultCode;
 
@@ -29,7 +29,9 @@ class WebBrowserApplet;
 
 namespace Kernel {
 class KernelCore;
-}
+class KEvent;
+class KReadableEvent;
+} // namespace Kernel
 
 namespace Service::AM {
 
@@ -87,9 +89,9 @@ public:
 
     void SignalStateChanged() const;
 
-    std::shared_ptr<Kernel::ReadableEvent> GetNormalDataEvent() const;
-    std::shared_ptr<Kernel::ReadableEvent> GetInteractiveDataEvent() const;
-    std::shared_ptr<Kernel::ReadableEvent> GetStateChangedEvent() const;
+    std::shared_ptr<Kernel::KReadableEvent> GetNormalDataEvent() const;
+    std::shared_ptr<Kernel::KReadableEvent> GetInteractiveDataEvent() const;
+    std::shared_ptr<Kernel::KReadableEvent> GetStateChangedEvent() const;
 
 private:
     // Queues are named from applet's perspective
@@ -106,13 +108,13 @@ private:
     // PopInteractiveDataToGame and PushInteractiveDataFromApplet
     std::deque<std::shared_ptr<IStorage>> out_interactive_channel;
 
-    Kernel::EventPair state_changed_event;
+    std::shared_ptr<Kernel::KEvent> state_changed_event;
 
     // Signaled on PushNormalDataFromApplet
-    Kernel::EventPair pop_out_data_event;
+    std::shared_ptr<Kernel::KEvent> pop_out_data_event;
 
     // Signaled on PushInteractiveDataFromApplet
-    Kernel::EventPair pop_interactive_out_data_event;
+    std::shared_ptr<Kernel::KEvent> pop_interactive_out_data_event;
 };
 
 class Applet {

+ 11 - 9
src/core/hle/service/aoc/aoc_u.cpp

@@ -5,6 +5,7 @@
 #include <algorithm>
 #include <numeric>
 #include <vector>
+
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/file_sys/common_funcs.h"
@@ -14,10 +15,10 @@
 #include "core/file_sys/patch_manager.h"
 #include "core/file_sys/registered_cache.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/aoc/aoc_u.h"
 #include "core/loader/loader.h"
 #include "core/settings.h"
@@ -62,8 +63,9 @@ public:
 
         RegisterHandlers(functions);
 
-        purchased_event = Kernel::WritableEvent::CreateEventPair(
-            system.Kernel(), "IPurchaseEventManager:PurchasedEvent");
+        purchased_event =
+            Kernel::KEvent::Create(system.Kernel(), "IPurchaseEventManager:PurchasedEvent");
+        purchased_event->Initialize();
     }
 
 private:
@@ -96,10 +98,10 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(purchased_event.readable);
+        rb.PushCopyObjects(purchased_event->GetReadableEvent());
     }
 
-    Kernel::EventPair purchased_event;
+    std::shared_ptr<Kernel::KEvent> purchased_event;
 };
 
 AOC_U::AOC_U(Core::System& system_)
@@ -124,8 +126,8 @@ AOC_U::AOC_U(Core::System& system_)
     RegisterHandlers(functions);
 
     auto& kernel = system.Kernel();
-    aoc_change_event =
-        Kernel::WritableEvent::CreateEventPair(kernel, "GetAddOnContentListChanged:Event");
+    aoc_change_event = Kernel::KEvent::Create(kernel, "GetAddOnContentListChanged:Event");
+    aoc_change_event->Initialize();
 }
 
 AOC_U::~AOC_U() = default;
@@ -252,7 +254,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(aoc_change_event.readable);
+    rb.PushCopyObjects(aoc_change_event->GetReadableEvent());
 }
 
 void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) {

+ 2 - 2
src/core/hle/service/aoc/aoc_u.h

@@ -11,7 +11,7 @@ class System;
 }
 
 namespace Kernel {
-class WritableEvent;
+class KEvent;
 }
 
 namespace Service::AOC {
@@ -31,7 +31,7 @@ private:
     void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx);
 
     std::vector<u64> add_on_content;
-    Kernel::EventPair aoc_change_event;
+    std::shared_ptr<Kernel::KEvent> aoc_change_event;
 };
 
 /// Registers all AOC services with the specified service manager.

+ 8 - 7
src/core/hle/service/audio/audout_u.cpp

@@ -14,9 +14,10 @@
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/audio/audout_u.h"
 #include "core/hle/service/audio/errors.h"
 #include "core/memory.h"
@@ -66,13 +67,13 @@ public:
         RegisterHandlers(functions);
 
         // This is the event handle used to check if the audio buffer was released
-        buffer_event =
-            Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioOutBufferReleased");
+        buffer_event = Kernel::KEvent::Create(system.Kernel(), "IAudioOutBufferReleased");
+        buffer_event->Initialize();
 
         stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
                                        audio_params.channel_count, std::move(unique_name), [this] {
                                            const auto guard = LockService();
-                                           buffer_event.writable->Signal();
+                                           buffer_event->GetWritableEvent()->Signal();
                                        });
     }
 
@@ -125,7 +126,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(buffer_event.readable);
+        rb.PushCopyObjects(buffer_event->GetReadableEvent());
     }
 
     void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
@@ -219,7 +220,7 @@ private:
     [[maybe_unused]] AudoutParams audio_params{};
 
     /// This is the event handle used to check if the audio buffer was released
-    Kernel::EventPair buffer_event;
+    std::shared_ptr<Kernel::KEvent> buffer_event;
     Core::Memory::Memory& main_memory;
 };
 

+ 23 - 20
src/core/hle/service/audio/audren_u.cpp

@@ -16,9 +16,10 @@
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/audio/audren_u.h"
 #include "core/hle/service/audio/errors.h"
 
@@ -47,13 +48,13 @@ public:
         // clang-format on
         RegisterHandlers(functions);
 
-        system_event =
-            Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent");
+        system_event = Kernel::KEvent::Create(system.Kernel(), "IAudioRenderer:SystemEvent");
+        system_event->Initialize();
         renderer = std::make_unique<AudioCore::AudioRenderer>(
             system.CoreTiming(), system.Memory(), audren_params,
             [this]() {
                 const auto guard = LockService();
-                system_event.writable->Signal();
+                system_event->GetWritableEvent()->Signal();
             },
             instance_number);
     }
@@ -126,7 +127,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(system_event.readable);
+        rb.PushCopyObjects(system_event->GetReadableEvent());
     }
 
     void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) {
@@ -160,7 +161,7 @@ private:
         rb.Push(ERR_NOT_SUPPORTED);
     }
 
-    Kernel::EventPair system_event;
+    std::shared_ptr<Kernel::KEvent> system_event;
     std::unique_ptr<AudioCore::AudioRenderer> renderer;
     u32 rendering_time_limit_percent = 100;
 };
@@ -187,17 +188,19 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = system.Kernel();
-        buffer_event =
-            Kernel::WritableEvent::CreateEventPair(kernel, "IAudioOutBufferReleasedEvent");
+        buffer_event = Kernel::KEvent::Create(kernel, "IAudioOutBufferReleasedEvent");
+        buffer_event->Initialize();
 
         // Should be similar to audio_output_device_switch_event
-        audio_input_device_switch_event = Kernel::WritableEvent::CreateEventPair(
-            kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent");
+        audio_input_device_switch_event =
+            Kernel::KEvent::Create(kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent");
+        audio_input_device_switch_event->Initialize();
 
         // Should only be signalled when an audio output device has been changed, example: speaker
         // to headset
-        audio_output_device_switch_event = Kernel::WritableEvent::CreateEventPair(
-            kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
+        audio_output_device_switch_event =
+            Kernel::KEvent::Create(kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
+        audio_output_device_switch_event->Initialize();
     }
 
 private:
@@ -286,11 +289,11 @@ private:
     void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
         LOG_WARNING(Service_Audio, "(STUBBED) called");
 
-        buffer_event.writable->Signal();
+        buffer_event->GetWritableEvent()->Signal();
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(buffer_event.readable);
+        rb.PushCopyObjects(buffer_event->GetReadableEvent());
     }
 
     void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
@@ -307,7 +310,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(audio_input_device_switch_event.readable);
+        rb.PushCopyObjects(audio_input_device_switch_event->GetReadableEvent());
     }
 
     void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) {
@@ -315,13 +318,13 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(audio_output_device_switch_event.readable);
+        rb.PushCopyObjects(audio_output_device_switch_event->GetReadableEvent());
     }
 
     u32_le revision = 0;
-    Kernel::EventPair buffer_event;
-    Kernel::EventPair audio_input_device_switch_event;
-    Kernel::EventPair audio_output_device_switch_event;
+    std::shared_ptr<Kernel::KEvent> buffer_event;
+    std::shared_ptr<Kernel::KEvent> audio_input_device_switch_event;
+    std::shared_ptr<Kernel::KEvent> audio_output_device_switch_event;
 
 }; // namespace Audio
 

+ 10 - 6
src/core/hle/service/bcat/backend/backend.cpp

@@ -5,6 +5,9 @@
 #include "common/hex_util.h"
 #include "common/logging/log.h"
 #include "core/core.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/lock.h"
 #include "core/hle/service/bcat/backend/backend.h"
 
@@ -12,12 +15,13 @@ namespace Service::BCAT {
 
 ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel,
                                                std::string_view event_name) {
-    event = Kernel::WritableEvent::CreateEventPair(
-        kernel, std::string("ProgressServiceBackend:UpdateEvent:").append(event_name));
+    event = Kernel::KEvent::Create(kernel,
+                                   "ProgressServiceBackend:UpdateEvent:" + std::string(event_name));
+    event->Initialize();
 }
 
-std::shared_ptr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const {
-    return event.readable;
+std::shared_ptr<Kernel::KReadableEvent> ProgressServiceBackend::GetEvent() const {
+    return event->GetReadableEvent();
 }
 
 DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() {
@@ -85,9 +89,9 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) {
 void ProgressServiceBackend::SignalUpdate() const {
     if (need_hle_lock) {
         std::lock_guard lock(HLE::g_hle_lock);
-        event.writable->Signal();
+        event->GetWritableEvent()->Signal();
     } else {
-        event.writable->Signal();
+        event->GetWritableEvent()->Signal();
     }
 }
 

+ 5 - 5
src/core/hle/service/bcat/backend/backend.h

@@ -11,8 +11,6 @@
 
 #include "common/common_types.h"
 #include "core/file_sys/vfs_types.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/result.h"
 
 namespace Core {
@@ -21,7 +19,9 @@ class System;
 
 namespace Kernel {
 class KernelCore;
-}
+class KEvent;
+class KReadableEvent;
+} // namespace Kernel
 
 namespace Service::BCAT {
 
@@ -98,13 +98,13 @@ public:
 private:
     explicit ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name);
 
-    std::shared_ptr<Kernel::ReadableEvent> GetEvent() const;
+    std::shared_ptr<Kernel::KReadableEvent> GetEvent() const;
     DeliveryCacheProgressImpl& GetImpl();
 
     void SignalUpdate() const;
 
     DeliveryCacheProgressImpl impl{};
-    Kernel::EventPair event;
+    std::shared_ptr<Kernel::KEvent> event;
     bool need_hle_lock = false;
 };
 

+ 4 - 4
src/core/hle/service/bcat/module.cpp

@@ -11,9 +11,9 @@
 #include "core/core.h"
 #include "core/file_sys/vfs.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/bcat/backend/backend.h"
 #include "core/hle/service/bcat/bcat.h"
 #include "core/hle/service/bcat/module.h"
@@ -89,7 +89,7 @@ struct DeliveryCacheDirectoryEntry {
 class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> {
 public:
     explicit IDeliveryCacheProgressService(Core::System& system_,
-                                           std::shared_ptr<Kernel::ReadableEvent> event_,
+                                           std::shared_ptr<Kernel::KReadableEvent> event_,
                                            const DeliveryCacheProgressImpl& impl_)
         : ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{std::move(event_)},
           impl{impl_} {
@@ -121,7 +121,7 @@ private:
         rb.Push(RESULT_SUCCESS);
     }
 
-    std::shared_ptr<Kernel::ReadableEvent> event;
+    std::shared_ptr<Kernel::KReadableEvent> event;
     const DeliveryCacheProgressImpl& impl;
 };
 

+ 6 - 5
src/core/hle/service/btdrv/btdrv.cpp

@@ -6,9 +6,9 @@
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/btdrv/btdrv.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/sm.h"
@@ -35,7 +35,8 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = system.Kernel();
-        register_event = Kernel::WritableEvent::CreateEventPair(kernel, "BT:RegisterEvent");
+        register_event = Kernel::KEvent::Create(kernel, "BT:RegisterEvent");
+        register_event->Initialize();
     }
 
 private:
@@ -44,10 +45,10 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(register_event.readable);
+        rb.PushCopyObjects(register_event->GetReadableEvent());
     }
 
-    Kernel::EventPair register_event;
+    std::shared_ptr<Kernel::KEvent> register_event;
 };
 
 class BtDrv final : public ServiceFramework<BtDrv> {

+ 18 - 16
src/core/hle/service/btm/btm.cpp

@@ -8,9 +8,9 @@
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/btm/btm.h"
 #include "core/hle/service/service.h"
 
@@ -58,12 +58,14 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = system.Kernel();
-        scan_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ScanEvent");
-        connection_event =
-            Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConnectionEvent");
-        service_discovery =
-            Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:Discovery");
-        config_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConfigEvent");
+        scan_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ScanEvent");
+        scan_event->Initialize();
+        connection_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConnectionEvent");
+        connection_event->Initialize();
+        service_discovery = Kernel::KEvent::Create(kernel, "IBtmUserCore:Discovery");
+        service_discovery->Initialize();
+        config_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConfigEvent");
+        config_event->Initialize();
     }
 
 private:
@@ -72,7 +74,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(scan_event.readable);
+        rb.PushCopyObjects(scan_event->GetReadableEvent());
     }
 
     void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) {
@@ -80,7 +82,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(connection_event.readable);
+        rb.PushCopyObjects(connection_event->GetReadableEvent());
     }
 
     void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) {
@@ -88,7 +90,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(service_discovery.readable);
+        rb.PushCopyObjects(service_discovery->GetReadableEvent());
     }
 
     void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) {
@@ -96,13 +98,13 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(config_event.readable);
+        rb.PushCopyObjects(config_event->GetReadableEvent());
     }
 
-    Kernel::EventPair scan_event;
-    Kernel::EventPair connection_event;
-    Kernel::EventPair service_discovery;
-    Kernel::EventPair config_event;
+    std::shared_ptr<Kernel::KEvent> scan_event;
+    std::shared_ptr<Kernel::KEvent> connection_event;
+    std::shared_ptr<Kernel::KEvent> service_discovery;
+    std::shared_ptr<Kernel::KEvent> config_event;
 };
 
 class BTM_USR final : public ServiceFramework<BTM_USR> {

+ 8 - 6
src/core/hle/service/friend/friend.cpp

@@ -7,8 +7,9 @@
 #include "common/uuid.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/service/friend/errors.h"
 #include "core/hle/service/friend/friend.h"
 #include "core/hle/service/friend/interface.h"
@@ -183,8 +184,9 @@ public:
 
         RegisterHandlers(functions);
 
-        notification_event = Kernel::WritableEvent::CreateEventPair(
-            system.Kernel(), "INotificationService:NotifyEvent");
+        notification_event =
+            Kernel::KEvent::Create(system.Kernel(), "INotificationService:NotifyEvent");
+        notification_event->Initialize();
     }
 
 private:
@@ -193,7 +195,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(notification_event.readable);
+        rb.PushCopyObjects(notification_event->GetReadableEvent());
     }
 
     void Clear(Kernel::HLERequestContext& ctx) {
@@ -258,7 +260,7 @@ private:
     };
 
     Common::UUID uuid{Common::INVALID_UUID};
-    Kernel::EventPair notification_event;
+    std::shared_ptr<Kernel::KEvent> notification_event;
     std::queue<SizedNotificationInfo> notifications;
     States states{};
 };

+ 11 - 8
src/core/hle/service/hid/controllers/npad.cpp

@@ -12,9 +12,10 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/input.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/hid/controllers/npad.h"
 #include "core/settings.h"
 
@@ -153,7 +154,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
     const auto controller_type = connected_controllers[controller_idx].type;
     auto& controller = shared_memory_entries[controller_idx];
     if (controller_type == NPadControllerType::None) {
-        styleset_changed_events[controller_idx].writable->Signal();
+        styleset_changed_events[controller_idx]->GetWritableEvent()->Signal();
         return;
     }
     controller.joy_styles.raw = 0; // Zero out
@@ -233,8 +234,9 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
 void Controller_NPad::OnInit() {
     auto& kernel = system.Kernel();
     for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
-        styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair(
-            kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
+        styleset_changed_events[i] =
+            Kernel::KEvent::Create(kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
+        styleset_changed_events[i]->Initialize();
     }
 
     if (!IsControllerActivated()) {
@@ -872,13 +874,14 @@ bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_dev
     return vibration_devices_mounted[npad_index][device_index];
 }
 
-std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
+std::shared_ptr<Kernel::KReadableEvent> Controller_NPad::GetStyleSetChangedEvent(
+    u32 npad_id) const {
     const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
-    return styleset_event.readable;
+    return styleset_event->GetReadableEvent();
 }
 
 void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
-    styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal();
+    styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent()->Signal();
 }
 
 void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {

+ 7 - 3
src/core/hle/service/hid/controllers/npad.h

@@ -10,10 +10,14 @@
 #include "common/common_types.h"
 #include "core/frontend/input.h"
 #include "core/hle/kernel/object.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
 #include "core/settings.h"
 
+namespace Kernel {
+class KEvent;
+class KReadableEvent;
+} // namespace Kernel
+
 namespace Service::HID {
 
 constexpr u32 NPAD_HANDHELD = 32;
@@ -187,7 +191,7 @@ public:
 
     bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const;
 
-    std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
+    std::shared_ptr<Kernel::KReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
     void SignalStyleSetChangedEvent(u32 npad_id) const;
 
     // Adds a new controller at an index.
@@ -452,7 +456,7 @@ private:
     // NpadCommunicationMode is unknown, default value is 1
     NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1};
     // Each controller should have their own styleset changed event
-    std::array<Kernel::EventPair, 10> styleset_changed_events;
+    std::array<std::shared_ptr<Kernel::KEvent>, 10> styleset_changed_events;
     std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints;
     std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
     bool permit_vibration_session_enabled{false};

+ 2 - 2
src/core/hle/service/hid/hid.cpp

@@ -14,10 +14,10 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/client_session.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/shared_memory.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/hid/errors.h"
 #include "core/hle/service/hid/hid.h"
 #include "core/hle/service/hid/irs.h"

+ 17 - 14
src/core/hle/service/nfp/nfp.cpp

@@ -8,10 +8,11 @@
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/lock.h"
 #include "core/hle/service/nfp/nfp.h"
 #include "core/hle/service/nfp/nfp_user.h"
@@ -25,7 +26,8 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& syst
                              const char* name)
     : ServiceFramework{system_, name}, module{std::move(module_)} {
     auto& kernel = system.Kernel();
-    nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:NFCTagDetected");
+    nfc_tag_load = Kernel::KEvent::Create(kernel, "IUser:NFCTagDetected");
+    nfc_tag_load->Initialize();
 }
 
 Module::Interface::~Interface() = default;
@@ -64,9 +66,10 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = system.Kernel();
-        deactivate_event = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:DeactivateEvent");
-        availability_change_event =
-            Kernel::WritableEvent::CreateEventPair(kernel, "IUser:AvailabilityChangeEvent");
+        deactivate_event = Kernel::KEvent::Create(kernel, "IUser:DeactivateEvent");
+        deactivate_event->Initialize();
+        availability_change_event = Kernel::KEvent::Create(kernel, "IUser:AvailabilityChangeEvent");
+        availability_change_event->Initialize();
     }
 
 private:
@@ -164,7 +167,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(deactivate_event.readable);
+        rb.PushCopyObjects(deactivate_event->GetReadableEvent());
     }
 
     void StopDetection(Kernel::HLERequestContext& ctx) {
@@ -173,7 +176,7 @@ private:
         switch (device_state) {
         case DeviceState::TagFound:
         case DeviceState::TagNearby:
-            deactivate_event.writable->Signal();
+            deactivate_event->GetWritableEvent()->Signal();
             device_state = DeviceState::Initialized;
             break;
         case DeviceState::SearchingForTag:
@@ -262,7 +265,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(availability_change_event.readable);
+        rb.PushCopyObjects(availability_change_event->GetReadableEvent());
     }
 
     void GetRegisterInfo(Kernel::HLERequestContext& ctx) {
@@ -316,8 +319,8 @@ private:
     const u32 npad_id{0};       // Player 1 controller
     State state{State::NonInitialized};
     DeviceState device_state{DeviceState::Initialized};
-    Kernel::EventPair deactivate_event;
-    Kernel::EventPair availability_change_event;
+    std::shared_ptr<Kernel::KEvent> deactivate_event;
+    std::shared_ptr<Kernel::KEvent> availability_change_event;
     const Module::Interface& nfp_interface;
 };
 
@@ -336,12 +339,12 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
     }
 
     std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
-    nfc_tag_load.writable->Signal();
+    nfc_tag_load->GetWritableEvent()->Signal();
     return true;
 }
 
-const std::shared_ptr<Kernel::ReadableEvent>& Module::Interface::GetNFCEvent() const {
-    return nfc_tag_load.readable;
+const std::shared_ptr<Kernel::KReadableEvent>& Module::Interface::GetNFCEvent() const {
+    return nfc_tag_load->GetReadableEvent();
 }
 
 const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const {

+ 7 - 4
src/core/hle/service/nfp/nfp.h

@@ -6,10 +6,13 @@
 
 #include <array>
 #include <vector>
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
+
 #include "core/hle/service/service.h"
 
+namespace Kernel {
+class KEvent;
+}
+
 namespace Service::NFP {
 
 class Module final {
@@ -35,11 +38,11 @@ public:
 
         void CreateUserInterface(Kernel::HLERequestContext& ctx);
         bool LoadAmiibo(const std::vector<u8>& buffer);
-        const std::shared_ptr<Kernel::ReadableEvent>& GetNFCEvent() const;
+        const std::shared_ptr<Kernel::KReadableEvent>& GetNFCEvent() const;
         const AmiiboFile& GetAmiiboBuffer() const;
 
     private:
-        Kernel::EventPair nfc_tag_load{};
+        std::shared_ptr<Kernel::KEvent> nfc_tag_load;
         AmiiboFile amiibo{};
 
     protected:

+ 9 - 6
src/core/hle/service/nifm/nifm.cpp

@@ -4,9 +4,9 @@
 
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/nifm/nifm.h"
 #include "core/hle/service/service.h"
 #include "core/network/network.h"
@@ -158,8 +158,11 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = system.Kernel();
-        event1 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event1");
-        event2 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event2");
+
+        event1 = Kernel::KEvent::Create(kernel, "IRequest:Event1");
+        event1->Initialize();
+        event2 = Kernel::KEvent::Create(kernel, "IRequest:Event2");
+        event2->Initialize();
     }
 
 private:
@@ -195,7 +198,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 2};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(event1.readable, event2.readable);
+        rb.PushCopyObjects(event1->GetReadableEvent(), event2->GetReadableEvent());
     }
 
     void Cancel(Kernel::HLERequestContext& ctx) {
@@ -226,7 +229,7 @@ private:
         rb.Push<u32>(0);
     }
 
-    Kernel::EventPair event1, event2;
+    std::shared_ptr<Kernel::KEvent> event1, event2;
 };
 
 class INetworkProfile final : public ServiceFramework<INetworkProfile> {

+ 10 - 8
src/core/hle/service/nim/nim.cpp

@@ -6,9 +6,10 @@
 #include <ctime>
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/nim/nim.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/sm.h"
@@ -301,17 +302,18 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = system.Kernel();
-        finished_event = Kernel::WritableEvent::CreateEventPair(
-            kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent");
+        finished_event =
+            Kernel::KEvent::Create(kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent");
+        finished_event->Initialize();
     }
 
 private:
-    Kernel::EventPair finished_event;
+    std::shared_ptr<Kernel::KEvent> finished_event;
 
     void StartTask(Kernel::HLERequestContext& ctx) {
         // No need to connect to the internet, just finish the task straight away.
         LOG_DEBUG(Service_NIM, "called");
-        finished_event.writable->Signal();
+        finished_event->GetWritableEvent()->Signal();
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
     }
@@ -321,7 +323,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(finished_event.readable);
+        rb.PushCopyObjects(finished_event->GetReadableEvent());
     }
 
     void GetResult(Kernel::HLERequestContext& ctx) {
@@ -333,7 +335,7 @@ private:
 
     void Cancel(Kernel::HLERequestContext& ctx) {
         LOG_DEBUG(Service_NIM, "called");
-        finished_event.writable->Clear();
+        finished_event->GetWritableEvent()->Clear();
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
     }

+ 5 - 5
src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp

@@ -8,8 +8,8 @@
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "core/core.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
 #include "video_core/gpu.h"
 
@@ -103,14 +103,14 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
     // This is mostly to take into account unimplemented features. As synced
     // gpu is always synced.
     if (!gpu.IsAsync()) {
-        event.event.writable->Signal();
+        event.event->GetWritableEvent()->Signal();
         return NvResult::Success;
     }
     auto lock = gpu.LockSync();
     const u32 current_syncpoint_value = event.fence.value;
     const s32 diff = current_syncpoint_value - params.threshold;
     if (diff >= 0) {
-        event.event.writable->Signal();
+        event.event->GetWritableEvent()->Signal();
         params.value = current_syncpoint_value;
         std::memcpy(output.data(), &params, sizeof(params));
         return NvResult::Success;
@@ -137,7 +137,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
             params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
         }
         params.value |= event_id;
-        event.event.writable->Clear();
+        event.event->GetWritableEvent()->Clear();
         gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
         std::memcpy(output.data(), &params, sizeof(params));
         return NvResult::Timeout;

+ 2 - 2
src/core/hle/service/nvdrv/interface.cpp

@@ -6,10 +6,10 @@
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/nvdrv/interface.h"
 #include "core/hle/service/nvdrv/nvdata.h"
 #include "core/hle/service/nvdrv/nvdrv.h"

+ 1 - 1
src/core/hle/service/nvdrv/interface.h

@@ -9,7 +9,7 @@
 #include "core/hle/service/service.h"
 
 namespace Kernel {
-class WritableEvent;
+class KWritableEvent;
 }
 
 namespace Service::Nvidia {

+ 10 - 8
src/core/hle/service/nvdrv/nvdrv.cpp

@@ -7,8 +7,9 @@
 #include <fmt/format.h>
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/service/nvdrv/devices/nvdevice.h"
 #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
 #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
@@ -42,7 +43,8 @@ Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} {
     auto& kernel = system.Kernel();
     for (u32 i = 0; i < MaxNvEvents; i++) {
         std::string event_label = fmt::format("NVDRV::NvEvent_{}", i);
-        events_interface.events[i] = {Kernel::WritableEvent::CreateEventPair(kernel, event_label)};
+        events_interface.events[i] = {Kernel::KEvent::Create(kernel, std::move(event_label))};
+        events_interface.events[i].event->Initialize();
         events_interface.status[i] = EventState::Free;
         events_interface.registered[i] = false;
     }
@@ -166,17 +168,17 @@ void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) {
         if (events_interface.assigned_syncpt[i] == syncpoint_id &&
             events_interface.assigned_value[i] == value) {
             events_interface.LiberateEvent(i);
-            events_interface.events[i].event.writable->Signal();
+            events_interface.events[i].event->GetWritableEvent()->Signal();
         }
     }
 }
 
-std::shared_ptr<Kernel::ReadableEvent> Module::GetEvent(const u32 event_id) const {
-    return events_interface.events[event_id].event.readable;
+std::shared_ptr<Kernel::KReadableEvent> Module::GetEvent(const u32 event_id) const {
+    return events_interface.events[event_id].event->GetReadableEvent();
 }
 
-std::shared_ptr<Kernel::WritableEvent> Module::GetEventWriteable(const u32 event_id) const {
-    return events_interface.events[event_id].event.writable;
+std::shared_ptr<Kernel::KWritableEvent> Module::GetEventWriteable(const u32 event_id) const {
+    return events_interface.events[event_id].event->GetWritableEvent();
 }
 
 } // namespace Service::Nvidia

+ 8 - 4
src/core/hle/service/nvdrv/nvdrv.h

@@ -7,8 +7,8 @@
 #include <memory>
 #include <unordered_map>
 #include <vector>
+
 #include "common/common_types.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/nvdrv/nvdata.h"
 #include "core/hle/service/nvdrv/syncpoint_manager.h"
 #include "core/hle/service/service.h"
@@ -17,6 +17,10 @@ namespace Core {
 class System;
 }
 
+namespace Kernel {
+class KEvent;
+}
+
 namespace Service::NVFlinger {
 class NVFlinger;
 }
@@ -31,7 +35,7 @@ class nvdevice;
 
 /// Represents an Nvidia event
 struct NvEvent {
-    Kernel::EventPair event;
+    std::shared_ptr<Kernel::KEvent> event;
     Fence fence{};
 };
 
@@ -132,9 +136,9 @@ public:
 
     void SignalSyncpt(const u32 syncpoint_id, const u32 value);
 
-    std::shared_ptr<Kernel::ReadableEvent> GetEvent(u32 event_id) const;
+    std::shared_ptr<Kernel::KReadableEvent> GetEvent(u32 event_id) const;
 
-    std::shared_ptr<Kernel::WritableEvent> GetEventWriteable(u32 event_id) const;
+    std::shared_ptr<Kernel::KWritableEvent> GetEventWriteable(u32 event_id) const;
 
 private:
     /// Manages syncpoints on the host

+ 12 - 11
src/core/hle/service/nvflinger/buffer_queue.cpp

@@ -7,16 +7,17 @@
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "core/core.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/nvflinger/buffer_queue.h"
 
 namespace Service::NVFlinger {
 
 BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id)
     : id(id), layer_id(layer_id) {
-    buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, "BufferQueue NativeHandle");
+    buffer_wait_event = Kernel::KEvent::Create(kernel, "BufferQueue:WaitEvent");
+    buffer_wait_event->Initialize();
 }
 
 BufferQueue::~BufferQueue() = default;
@@ -41,7 +42,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
         .multi_fence = {},
     };
 
-    buffer_wait_event.writable->Signal();
+    buffer_wait_event->GetWritableEvent()->Signal();
 }
 
 std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
@@ -119,7 +120,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
     }
     free_buffers_condition.notify_one();
 
-    buffer_wait_event.writable->Signal();
+    buffer_wait_event->GetWritableEvent()->Signal();
 }
 
 std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
@@ -154,7 +155,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
     }
     free_buffers_condition.notify_one();
 
-    buffer_wait_event.writable->Signal();
+    buffer_wait_event->GetWritableEvent()->Signal();
 }
 
 void BufferQueue::Connect() {
@@ -169,7 +170,7 @@ void BufferQueue::Disconnect() {
         std::unique_lock lock{queue_sequence_mutex};
         queue_sequence.clear();
     }
-    buffer_wait_event.writable->Signal();
+    buffer_wait_event->GetWritableEvent()->Signal();
     is_connect = false;
     free_buffers_condition.notify_one();
 }
@@ -188,12 +189,12 @@ u32 BufferQueue::Query(QueryType type) {
     return 0;
 }
 
-std::shared_ptr<Kernel::WritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
-    return buffer_wait_event.writable;
+std::shared_ptr<Kernel::KWritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
+    return buffer_wait_event->GetWritableEvent();
 }
 
-std::shared_ptr<Kernel::ReadableEvent> BufferQueue::GetBufferWaitEvent() const {
-    return buffer_wait_event.readable;
+std::shared_ptr<Kernel::KReadableEvent> BufferQueue::GetBufferWaitEvent() const {
+    return buffer_wait_event->GetReadableEvent();
 }
 
 } // namespace Service::NVFlinger

+ 7 - 5
src/core/hle/service/nvflinger/buffer_queue.h

@@ -14,12 +14,14 @@
 #include "common/math_util.h"
 #include "common/swap.h"
 #include "core/hle/kernel/object.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/nvdrv/nvdata.h"
 
 namespace Kernel {
 class KernelCore;
-}
+class KEvent;
+class KReadableEvent;
+class KWritableEvent;
+} // namespace Kernel
 
 namespace Service::NVFlinger {
 
@@ -113,9 +115,9 @@ public:
         return is_connect;
     }
 
-    std::shared_ptr<Kernel::WritableEvent> GetWritableBufferWaitEvent() const;
+    std::shared_ptr<Kernel::KWritableEvent> GetWritableBufferWaitEvent() const;
 
-    std::shared_ptr<Kernel::ReadableEvent> GetBufferWaitEvent() const;
+    std::shared_ptr<Kernel::KReadableEvent> GetBufferWaitEvent() const;
 
 private:
     BufferQueue(const BufferQueue&) = delete;
@@ -127,7 +129,7 @@ private:
     std::list<u32> free_buffers;
     std::array<Buffer, buffer_slots> buffers;
     std::list<u32> queue_sequence;
-    Kernel::EventPair buffer_wait_event;
+    std::shared_ptr<Kernel::KEvent> buffer_wait_event;
 
     std::mutex free_buffers_mutex;
     std::condition_variable free_buffers_condition;

+ 2 - 2
src/core/hle/service/nvflinger/nvflinger.cpp

@@ -14,8 +14,8 @@
 #include "core/core_timing.h"
 #include "core/core_timing_util.h"
 #include "core/hardware_properties.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
 #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
 #include "core/hle/service/nvflinger/buffer_queue.h"
@@ -165,7 +165,7 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) co
     return layer->GetBufferQueue().GetId();
 }
 
-std::shared_ptr<Kernel::ReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const {
+std::shared_ptr<Kernel::KReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const {
     const auto guard = Lock();
     auto* const display = FindDisplay(display_id);
 

+ 3 - 3
src/core/hle/service/nvflinger/nvflinger.h

@@ -26,8 +26,8 @@ struct EventType;
 } // namespace Core::Timing
 
 namespace Kernel {
-class ReadableEvent;
-class WritableEvent;
+class KReadableEvent;
+class KWritableEvent;
 } // namespace Kernel
 
 namespace Service::Nvidia {
@@ -72,7 +72,7 @@ public:
     /// Gets the vsync event for the specified display.
     ///
     /// If an invalid display ID is provided, then nullptr is returned.
-    [[nodiscard]] std::shared_ptr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const;
+    [[nodiscard]] std::shared_ptr<Kernel::KReadableEvent> FindVsyncEvent(u64 display_id) const;
 
     /// Obtains a buffer queue identified by the ID.
     [[nodiscard]] BufferQueue* FindBufferQueue(u32 id);

+ 11 - 9
src/core/hle/service/ptm/psm.cpp

@@ -7,9 +7,10 @@
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/ptm/psm.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/sm.h"
@@ -31,27 +32,28 @@ public:
 
         RegisterHandlers(functions);
 
-        state_change_event = Kernel::WritableEvent::CreateEventPair(
-            system_.Kernel(), "IPsmSession::state_change_event");
+        state_change_event =
+            Kernel::KEvent::Create(system_.Kernel(), "IPsmSession::state_change_event");
+        state_change_event->Initialize();
     }
 
     ~IPsmSession() override = default;
 
     void SignalChargerTypeChanged() {
         if (should_signal && should_signal_charger_type) {
-            state_change_event.writable->Signal();
+            state_change_event->GetWritableEvent()->Signal();
         }
     }
 
     void SignalPowerSupplyChanged() {
         if (should_signal && should_signal_power_supply) {
-            state_change_event.writable->Signal();
+            state_change_event->GetWritableEvent()->Signal();
         }
     }
 
     void SignalBatteryVoltageStateChanged() {
         if (should_signal && should_signal_battery_voltage) {
-            state_change_event.writable->Signal();
+            state_change_event->GetWritableEvent()->Signal();
         }
     }
 
@@ -63,7 +65,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(state_change_event.readable);
+        rb.PushCopyObjects(state_change_event->GetReadableEvent());
     }
 
     void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) {
@@ -112,7 +114,7 @@ private:
     bool should_signal_power_supply{};
     bool should_signal_battery_voltage{};
     bool should_signal{};
-    Kernel::EventPair state_change_event;
+    std::shared_ptr<Kernel::KEvent> state_change_event;
 };
 
 class PSM final : public ServiceFramework<PSM> {

+ 5 - 3
src/core/hle/service/time/standard_user_system_clock_core.cpp

@@ -4,7 +4,7 @@
 
 #include "common/assert.h"
 #include "core/core.h"
-#include "core/hle/kernel/writable_event.h"
+#include "core/hle/kernel/k_event.h"
 #include "core/hle/service/time/standard_local_system_clock_core.h"
 #include "core/hle/service/time/standard_network_system_clock_core.h"
 #include "core/hle/service/time/standard_user_system_clock_core.h"
@@ -18,8 +18,10 @@ StandardUserSystemClockCore::StandardUserSystemClockCore(
       local_system_clock_core{local_system_clock_core},
       network_system_clock_core{network_system_clock_core}, auto_correction_enabled{},
       auto_correction_time{SteadyClockTimePoint::GetRandom()},
-      auto_correction_event{Kernel::WritableEvent::CreateEventPair(
-          system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {}
+      auto_correction_event{Kernel::KEvent::Create(
+          system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {
+    auto_correction_event->Initialize();
+}
 
 ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system,
                                                                       bool value) {

+ 5 - 2
src/core/hle/service/time/standard_user_system_clock_core.h

@@ -4,7 +4,6 @@
 
 #pragma once
 
-#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/time/clock_types.h"
 #include "core/hle/service/time/system_clock_core.h"
 
@@ -12,6 +11,10 @@ namespace Core {
 class System;
 }
 
+namespace Kernel {
+class KEvent;
+}
+
 namespace Service::Time::Clock {
 
 class StandardLocalSystemClockCore;
@@ -51,7 +54,7 @@ private:
     StandardNetworkSystemClockCore& network_system_clock_core;
     bool auto_correction_enabled{};
     SteadyClockTimePoint auto_correction_time;
-    Kernel::EventPair auto_correction_event;
+    std::shared_ptr<Kernel::KEvent> auto_correction_event;
 };
 
 } // namespace Service::Time::Clock

+ 2 - 2
src/core/hle/service/time/system_clock_context_update_callback.cpp

@@ -2,7 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include "core/hle/kernel/writable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/service/time/errors.h"
 #include "core/hle/service/time/system_clock_context_update_callback.h"
 
@@ -21,7 +21,7 @@ bool SystemClockContextUpdateCallback::NeedUpdate(const SystemClockContext& valu
 }
 
 void SystemClockContextUpdateCallback::RegisterOperationEvent(
-    std::shared_ptr<Kernel::WritableEvent>&& writable_event) {
+    std::shared_ptr<Kernel::KWritableEvent>&& writable_event) {
     operation_event_list.emplace_back(std::move(writable_event));
 }
 

+ 3 - 3
src/core/hle/service/time/system_clock_context_update_callback.h

@@ -9,7 +9,7 @@
 #include "core/hle/service/time/clock_types.h"
 
 namespace Kernel {
-class WritableEvent;
+class KWritableEvent;
 }
 
 namespace Service::Time::Clock {
@@ -24,7 +24,7 @@ public:
 
     bool NeedUpdate(const SystemClockContext& value) const;
 
-    void RegisterOperationEvent(std::shared_ptr<Kernel::WritableEvent>&& writable_event);
+    void RegisterOperationEvent(std::shared_ptr<Kernel::KWritableEvent>&& writable_event);
 
     void BroadcastOperationEvent();
 
@@ -37,7 +37,7 @@ protected:
 
 private:
     bool has_context{};
-    std::vector<std::shared_ptr<Kernel::WritableEvent>> operation_event_list;
+    std::vector<std::shared_ptr<Kernel::KWritableEvent>> operation_event_list;
 };
 
 } // namespace Service::Time::Clock

+ 8 - 6
src/core/hle/service/vi/display/vi_display.cpp

@@ -9,7 +9,9 @@
 
 #include "common/assert.h"
 #include "core/core.h"
-#include "core/hle/kernel/readable_event.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/service/vi/display/vi_display.h"
 #include "core/hle/service/vi/layer/vi_layer.h"
 
@@ -17,8 +19,8 @@ namespace Service::VI {
 
 Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} {
     auto& kernel = system.Kernel();
-    vsync_event =
-        Kernel::WritableEvent::CreateEventPair(kernel, fmt::format("Display VSync Event {}", id));
+    vsync_event = Kernel::KEvent::Create(kernel, fmt::format("Display VSync Event {}", id));
+    vsync_event->Initialize();
 }
 
 Display::~Display() = default;
@@ -31,12 +33,12 @@ const Layer& Display::GetLayer(std::size_t index) const {
     return *layers.at(index);
 }
 
-std::shared_ptr<Kernel::ReadableEvent> Display::GetVSyncEvent() const {
-    return vsync_event.readable;
+std::shared_ptr<Kernel::KReadableEvent> Display::GetVSyncEvent() const {
+    return vsync_event->GetReadableEvent();
 }
 
 void Display::SignalVSyncEvent() {
-    vsync_event.writable->Signal();
+    vsync_event->GetWritableEvent()->Signal();
 }
 
 void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) {

+ 6 - 3
src/core/hle/service/vi/display/vi_display.h

@@ -9,7 +9,10 @@
 #include <vector>
 
 #include "common/common_types.h"
-#include "core/hle/kernel/writable_event.h"
+
+namespace Kernel {
+class KEvent;
+}
 
 namespace Service::NVFlinger {
 class BufferQueue;
@@ -58,7 +61,7 @@ public:
     const Layer& GetLayer(std::size_t index) const;
 
     /// Gets the readable vsync event.
-    std::shared_ptr<Kernel::ReadableEvent> GetVSyncEvent() const;
+    std::shared_ptr<Kernel::KReadableEvent> GetVSyncEvent() const;
 
     /// Signals the internal vsync event.
     void SignalVSyncEvent();
@@ -99,7 +102,7 @@ private:
     std::string name;
 
     std::vector<std::shared_ptr<Layer>> layers;
-    Kernel::EventPair vsync_event;
+    std::shared_ptr<Kernel::KEvent> vsync_event;
 };
 
 } // namespace Service::VI

+ 2 - 2
src/core/hle/service/vi/vi.cpp

@@ -18,9 +18,9 @@
 #include "common/swap.h"
 #include "core/core_timing.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_thread.h"
-#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/writable_event.h"
+#include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/service/nvdrv/nvdata.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
 #include "core/hle/service/nvflinger/buffer_queue.h"

+ 3 - 3
src/yuzu/debugger/wait_tree.cpp

@@ -13,11 +13,11 @@
 #include "core/arm/arm_interface.h"
 #include "core/core.h"
 #include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_scheduler.h"
 #include "core/hle/kernel/k_synchronization_object.h"
 #include "core/hle/kernel/k_thread.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/svc_common.h"
 #include "core/hle/kernel/svc_types.h"
 #include "core/memory.h"
@@ -193,7 +193,7 @@ std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::ma
     const Kernel::KSynchronizationObject& object) {
     switch (object.GetHandleType()) {
     case Kernel::HandleType::ReadableEvent:
-        return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object));
+        return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object));
     case Kernel::HandleType::Thread:
         return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object));
     default:
@@ -373,7 +373,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
     return list;
 }
 
-WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object)
+WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object)
     : WaitTreeSynchronizationObject(object) {}
 WaitTreeEvent::~WaitTreeEvent() = default;
 

+ 2 - 2
src/yuzu/debugger/wait_tree.h

@@ -18,9 +18,9 @@ class EmuThread;
 
 namespace Kernel {
 class HandleTable;
+class KReadableEvent;
 class KSynchronizationObject;
 class KThread;
-class ReadableEvent;
 } // namespace Kernel
 
 class WaitTreeThread;
@@ -142,7 +142,7 @@ public:
 class WaitTreeEvent : public WaitTreeSynchronizationObject {
     Q_OBJECT
 public:
-    explicit WaitTreeEvent(const Kernel::ReadableEvent& object);
+    explicit WaitTreeEvent(const Kernel::KReadableEvent& object);
     ~WaitTreeEvent() override;
 };