diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index 23e5d3f10..2e59894ab 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -8,7 +8,7 @@
 #include "audio_core/codec.h"
 #include "common/assert.h"
 #include "common/logging/log.h"
-#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/writable_event.h"
 #include "core/memory.h"
 
 namespace AudioCore {
@@ -72,7 +72,7 @@ private:
     EffectInStatus info{};
 };
 AudioRenderer::AudioRenderer(AudioRendererParameter params,
-                             Kernel::SharedPtr<Kernel::Event> buffer_event)
+                             Kernel::SharedPtr<Kernel::WritableEvent> buffer_event)
     : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
       effects(params.effect_count) {
 
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h
index 71ba4be40..7826881bf 100644
--- a/src/audio_core/audio_renderer.h
+++ b/src/audio_core/audio_renderer.h
@@ -15,7 +15,7 @@
 #include "core/hle/kernel/object.h"
 
 namespace Kernel {
-class Event;
+class WritableEvent;
 }
 
 namespace AudioCore {
@@ -208,7 +208,8 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size
 
 class AudioRenderer {
 public:
-    AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event);
+    AudioRenderer(AudioRendererParameter params,
+                  Kernel::SharedPtr<Kernel::WritableEvent> buffer_event);
     ~AudioRenderer();
 
     std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params);
@@ -224,7 +225,7 @@ private:
     class VoiceState;
 
     AudioRendererParameter worker_params;
-    Kernel::SharedPtr<Kernel::Event> buffer_event;
+    Kernel::SharedPtr<Kernel::WritableEvent> buffer_event;
     std::vector<VoiceState> voices;
     std::vector<EffectState> effects;
     std::unique_ptr<AudioOut> audio_out;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index e1f21a764..73aec8ab0 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -97,8 +97,6 @@ add_library(core STATIC
     hle/kernel/client_session.cpp
     hle/kernel/client_session.h
     hle/kernel/errors.h
-    hle/kernel/event.cpp
-    hle/kernel/event.h
     hle/kernel/handle_table.cpp
     hle/kernel/handle_table.h
     hle/kernel/hle_ipc.cpp
@@ -111,6 +109,8 @@ add_library(core STATIC
     hle/kernel/object.h
     hle/kernel/process.cpp
     hle/kernel/process.h
+    hle/kernel/readable_event.cpp
+    hle/kernel/readable_event.h
     hle/kernel/resource_limit.cpp
     hle/kernel/resource_limit.h
     hle/kernel/scheduler.cpp
@@ -133,6 +133,8 @@ add_library(core STATIC
     hle/kernel/vm_manager.h
     hle/kernel/wait_object.cpp
     hle/kernel/wait_object.h
+    hle/kernel/writable_event.cpp
+    hle/kernel/writable_event.h
     hle/lock.cpp
     hle/lock.h
     hle/result.h
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 68d5376cb..61ce7d7e4 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -15,13 +15,14 @@
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/hle_ipc.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/writable_event.h"
 #include "core/memory.h"
 
 namespace Kernel {
@@ -36,11 +37,9 @@ void SessionRequestHandler::ClientDisconnected(const SharedPtr<ServerSession>& s
     boost::range::remove_erase(connected_sessions, server_session);
 }
 
-SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
-                                                      const std::string& reason, u64 timeout,
-                                                      WakeupCallback&& callback,
-                                                      Kernel::SharedPtr<Kernel::Event> event) {
-
+SharedPtr<WritableEvent> HLERequestContext::SleepClientThread(
+    SharedPtr<Thread> thread, const std::string& reason, u64 timeout, WakeupCallback&& callback,
+    SharedPtr<WritableEvent> writable_event) {
     // Put the client thread to sleep until the wait event is signaled or the timeout expires.
     thread->SetWakeupCallback([context = *this, callback](
                                   ThreadWakeupReason reason, SharedPtr<Thread> thread,
@@ -51,23 +50,25 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
         return true;
     });
 
-    if (!event) {
+    auto& kernel = Core::System::GetInstance().Kernel();
+    if (!writable_event) {
         // Create event if not provided
-        auto& kernel = Core::System::GetInstance().Kernel();
-        event =
-            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
+        const auto pair = WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                         "HLE Pause Event: " + reason);
+        writable_event = pair.writable;
     }
 
-    event->Clear();
+    const auto readable_event{writable_event->GetReadableEvent()};
+    writable_event->Clear();
     thread->SetStatus(ThreadStatus::WaitHLEEvent);
-    thread->SetWaitObjects({event});
-    event->AddWaitingThread(thread);
+    thread->SetWaitObjects({readable_event});
+    readable_event->AddWaitingThread(thread);
 
     if (timeout > 0) {
         thread->WakeAfterDelay(timeout);
     }
 
-    return event;
+    return writable_event;
 }
 
 HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session)
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index a38e34b74..e5c0610cd 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -24,10 +24,11 @@ class ServiceFrameworkBase;
 namespace Kernel {
 
 class Domain;
-class Event;
 class HandleTable;
 class HLERequestContext;
 class Process;
+class ReadableEvent;
+class WritableEvent;
 
 /**
  * Interface implemented by HLE Session handlers.
@@ -119,12 +120,13 @@ public:
      * @param callback Callback to be invoked when the thread is resumed. This callback must write
      * the entire command response once again, regardless of the state of it before this function
      * was called.
-     * @param event Event to use to wake up the thread. If unspecified, an event will be created.
+     * @param writable_event Event to use to wake up the thread. If unspecified, an event will be
+     * created.
      * @returns Event that when signaled will resume the thread and call the callback function.
      */
-    SharedPtr<Event> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason,
-                                       u64 timeout, WakeupCallback&& callback,
-                                       Kernel::SharedPtr<Kernel::Event> event = nullptr);
+    SharedPtr<WritableEvent> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason,
+                                               u64 timeout, WakeupCallback&& callback,
+                                               SharedPtr<WritableEvent> writable_event = nullptr);
 
     /// Populates this context with data from the requesting process/thread.
     ResultCode PopulateFromIncomingCommandBuffer(const HandleTable& handle_table,
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index c9f4d0bb3..69082ce3e 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -33,9 +33,9 @@ enum class HandleType : u32 {
 };
 
 enum class ResetType {
-    OneShot,
-    Sticky,
-    Pulse,
+    OneShot, ///< Reset automatically on object acquisition
+    Sticky,  ///< Never reset automatically
+    Pulse,   ///< Reset automatically on wakeup
 };
 
 class Object : NonCopyable {
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/readable_event.cpp
similarity index 54%
rename from src/core/hle/kernel/event.cpp
rename to src/core/hle/kernel/readable_event.cpp
index 8967e602e..92e16b4e6 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/readable_event.cpp
@@ -4,46 +4,37 @@
 
 #include <algorithm>
 #include "common/assert.h"
-#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/object.h"
+#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/writable_event.h"
 
 namespace Kernel {
 
-Event::Event(KernelCore& kernel) : WaitObject{kernel} {}
-Event::~Event() = default;
+ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {}
+ReadableEvent::~ReadableEvent() = default;
 
-SharedPtr<Event> Event::Create(KernelCore& kernel, ResetType reset_type, std::string name) {
-    SharedPtr<Event> evt(new Event(kernel));
-
-    evt->signaled = false;
-    evt->reset_type = reset_type;
-    evt->name = std::move(name);
-
-    return evt;
-}
-
-bool Event::ShouldWait(Thread* thread) const {
+bool ReadableEvent::ShouldWait(Thread* thread) const {
     return !signaled;
 }
 
-void Event::Acquire(Thread* thread) {
+void ReadableEvent::Acquire(Thread* thread) {
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
 
     if (reset_type == ResetType::OneShot)
         signaled = false;
 }
 
-void Event::Signal() {
+void ReadableEvent::Signal() {
     signaled = true;
     WakeupAllWaitingThreads();
 }
 
-void Event::Clear() {
+void ReadableEvent::Clear() {
     signaled = false;
 }
 
-void Event::WakeupAllWaitingThreads() {
+void ReadableEvent::WakeupAllWaitingThreads() {
     WaitObject::WakeupAllWaitingThreads();
 
     if (reset_type == ResetType::Pulse)
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
new file mode 100644
index 000000000..b1f1f4871
--- /dev/null
+++ b/src/core/hle/kernel/readable_event.h
@@ -0,0 +1,55 @@
+// 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/object.h"
+#include "core/hle/kernel/wait_object.h"
+
+namespace Kernel {
+
+class KernelCore;
+class WritableEvent;
+
+class ReadableEvent final : public WaitObject {
+    friend class WritableEvent;
+
+public:
+    ~ReadableEvent() override;
+
+    std::string GetTypeName() const override {
+        return "ReadableEvent";
+    }
+    std::string GetName() const override {
+        return name;
+    }
+
+    ResetType GetResetType() const {
+        return reset_type;
+    }
+
+    static const HandleType HANDLE_TYPE = HandleType::Event;
+    HandleType GetHandleType() const override {
+        return HANDLE_TYPE;
+    }
+
+    bool ShouldWait(Thread* thread) const override;
+    void Acquire(Thread* thread) override;
+
+    void WakeupAllWaitingThreads() override;
+
+    void Clear();
+
+private:
+    explicit ReadableEvent(KernelCore& kernel);
+
+    void Signal();
+
+    ResetType reset_type;
+    bool signaled;
+
+    std::string name; ///< Name of event (optional)
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 3339777c1..051b09d00 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -20,17 +20,18 @@
 #include "core/hle/kernel/address_arbiter.h"
 #include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/client_session.h"
-#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/mutex.h"
 #include "core/hle/kernel/process.h"
+#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/resource_limit.h"
 #include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/shared_memory.h"
 #include "core/hle/kernel/svc.h"
 #include "core/hle/kernel/svc_wrap.h"
 #include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/writable_event.h"
 #include "core/hle/lock.h"
 #include "core/hle/result.h"
 #include "core/hle/service/service.h"
@@ -1361,7 +1362,7 @@ static ResultCode ResetSignal(Handle handle) {
     LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
 
     const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
-    auto event = handle_table.Get<Event>(handle);
+    auto event = handle_table.Get<ReadableEvent>(handle);
 
     ASSERT(event != nullptr);
 
@@ -1524,7 +1525,7 @@ static ResultCode ClearEvent(Handle handle) {
     LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
 
     const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
-    SharedPtr<Event> evt = handle_table.Get<Event>(handle);
+    SharedPtr<ReadableEvent> evt = handle_table.Get<ReadableEvent>(handle);
     if (evt == nullptr) {
         LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle);
         return ERR_INVALID_HANDLE;
diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp
new file mode 100644
index 000000000..a58ea6ec8
--- /dev/null
+++ b/src/core/hle/kernel/writable_event.cpp
@@ -0,0 +1,52 @@
+// 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/kernel.h"
+#include "core/hle/kernel/object.h"
+#include "core/hle/kernel/readable_event.h"
+#include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/writable_event.h"
+
+namespace Kernel {
+
+WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
+WritableEvent::~WritableEvent() = default;
+
+EventPair WritableEvent::CreateEventPair(KernelCore& kernel, ResetType reset_type,
+                                         std::string name) {
+    SharedPtr<WritableEvent> writable_event(new WritableEvent(kernel));
+    SharedPtr<ReadableEvent> readable_event(new ReadableEvent(kernel));
+
+    writable_event->name = name + ":Writable";
+    writable_event->readable = readable_event;
+    readable_event->name = name + ":Readable";
+    readable_event->signaled = false;
+    readable_event->reset_type = reset_type;
+
+    return {std::move(readable_event), std::move(writable_event)};
+}
+
+SharedPtr<ReadableEvent> WritableEvent::GetReadableEvent() const {
+    return readable;
+}
+
+ResetType WritableEvent::GetResetType() const {
+    return readable->reset_type;
+}
+
+void WritableEvent::Signal() {
+    readable->Signal();
+}
+
+void WritableEvent::Clear() {
+    readable->Clear();
+}
+
+bool WritableEvent::IsSignaled() const {
+    return readable->signaled;
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/writable_event.h
similarity index 60%
rename from src/core/hle/kernel/event.h
rename to src/core/hle/kernel/writable_event.h
index 27d6126b0..fc57d18d7 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/writable_event.h
@@ -11,20 +11,29 @@
 namespace Kernel {
 
 class KernelCore;
+class ReadableEvent;
+class WritableEvent;
 
-class Event final : public WaitObject {
+struct EventPair {
+    SharedPtr<ReadableEvent> readable;
+    SharedPtr<WritableEvent> writable;
+};
+
+class WritableEvent final : public Object {
 public:
+    ~WritableEvent() override;
+
     /**
      * Creates an event
      * @param kernel The kernel instance to create this event under.
      * @param reset_type ResetType describing how to create event
      * @param name Optional name of event
      */
-    static SharedPtr<Event> Create(KernelCore& kernel, ResetType reset_type,
-                                   std::string name = "Unknown");
+    static EventPair CreateEventPair(KernelCore& kernel, ResetType reset_type,
+                                     std::string name = "Unknown");
 
     std::string GetTypeName() const override {
-        return "Event";
+        return "WritableEvent";
     }
     std::string GetName() const override {
         return name;
@@ -35,25 +44,19 @@ public:
         return HANDLE_TYPE;
     }
 
-    ResetType GetResetType() const {
-        return reset_type;
-    }
+    SharedPtr<ReadableEvent> GetReadableEvent() const;
 
-    bool ShouldWait(Thread* thread) const override;
-    void Acquire(Thread* thread) override;
-
-    void WakeupAllWaitingThreads() override;
+    ResetType GetResetType() const;
 
     void Signal();
     void Clear();
+    bool IsSignaled() const;
 
 private:
-    explicit Event(KernelCore& kernel);
-    ~Event() override;
+    explicit WritableEvent(KernelCore& kernel);
 
-    ResetType reset_type; ///< Current ResetType
+    SharedPtr<ReadableEvent> readable;
 
-    bool signaled;    ///< Whether the event has already been signaled
     std::string name; ///< Name of event (optional)
 };
 
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index d595c37b0..3a7b6da84 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -9,9 +9,11 @@
 #include "audio_core/audio_renderer.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/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/shared_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"
@@ -208,8 +210,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
     RegisterHandlers(functions);
 
     auto& kernel = Core::System::GetInstance().Kernel();
-    launchable_event =
-        Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent");
+    launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+                                                              "ISelfController:LaunchableEvent");
 }
 
 ISelfController::~ISelfController() = default;
@@ -295,11 +297,11 @@ void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
 void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
     LOG_WARNING(Service_AM, "(STUBBED) called");
 
-    launchable_event->Signal();
+    launchable_event.writable->Signal();
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(launchable_event);
+    rb.PushCopyObjects(launchable_event.readable);
 }
 
 void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) {
@@ -348,36 +350,38 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c
 
 AppletMessageQueue::AppletMessageQueue() {
     auto& kernel = Core::System::GetInstance().Kernel();
-    on_new_message = Kernel::Event::Create(kernel, Kernel::ResetType::Sticky,
-                                           "AMMessageQueue:OnMessageRecieved");
-    on_operation_mode_changed = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
-                                                      "AMMessageQueue:OperationModeChanged");
+    on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+                                                            "AMMessageQueue:OnMessageRecieved");
+    on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair(
+        kernel, Kernel::ResetType::OneShot, "AMMessageQueue:OperationModeChanged");
 }
 
 AppletMessageQueue::~AppletMessageQueue() = default;
 
-const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetMesssageRecieveEvent() const {
-    return on_new_message;
+const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetMesssageRecieveEvent()
+    const {
+    return on_new_message.readable;
 }
 
-const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetOperationModeChangedEvent() const {
-    return on_operation_mode_changed;
+const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
+    const {
+    return on_operation_mode_changed.readable;
 }
 
 void AppletMessageQueue::PushMessage(AppletMessage msg) {
     messages.push(msg);
-    on_new_message->Signal();
+    on_new_message.writable->Signal();
 }
 
 AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
     if (messages.empty()) {
-        on_new_message->Clear();
+        on_new_message.writable->Clear();
         return AppletMessage::NoMessage;
     }
     auto msg = messages.front();
     messages.pop();
     if (messages.empty()) {
-        on_new_message->Clear();
+        on_new_message.writable->Clear();
     }
     return msg;
 }
@@ -389,7 +393,7 @@ std::size_t AppletMessageQueue::GetMessageCount() const {
 void AppletMessageQueue::OperationModeChanged() {
     PushMessage(AppletMessage::OperationModeChanged);
     PushMessage(AppletMessage::PerformanceModeChanged);
-    on_operation_mode_changed->Signal();
+    on_operation_mode_changed.writable->Signal();
 }
 
 ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue)
@@ -426,9 +430,6 @@ ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_q
     // clang-format on
 
     RegisterHandlers(functions);
-
-    auto& kernel = Core::System::GetInstance().Kernel();
-    event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ICommonStateGetter:Event");
 }
 
 ICommonStateGetter::~ICommonStateGetter() = default;
@@ -564,8 +565,8 @@ private:
     void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) {
         LOG_DEBUG(Service_AM, "called");
 
+        applet->GetBroker().SignalStateChanged();
         const auto event = applet->GetBroker().GetStateChangedEvent();
-        event->Signal();
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 44c1bcde5..34c45fadf 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -6,12 +6,9 @@
 
 #include <memory>
 #include <queue>
+#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/service.h"
 
-namespace Kernel {
-class Event;
-}
-
 namespace Service {
 namespace NVFlinger {
 class NVFlinger;
@@ -52,8 +49,8 @@ public:
     AppletMessageQueue();
     ~AppletMessageQueue();
 
-    const Kernel::SharedPtr<Kernel::Event>& GetMesssageRecieveEvent() const;
-    const Kernel::SharedPtr<Kernel::Event>& GetOperationModeChangedEvent() const;
+    const Kernel::SharedPtr<Kernel::ReadableEvent>& GetMesssageRecieveEvent() const;
+    const Kernel::SharedPtr<Kernel::ReadableEvent>& GetOperationModeChangedEvent() const;
     void PushMessage(AppletMessage msg);
     AppletMessage PopMessage();
     std::size_t GetMessageCount() const;
@@ -61,8 +58,8 @@ public:
 
 private:
     std::queue<AppletMessage> messages;
-    Kernel::SharedPtr<Kernel::Event> on_new_message;
-    Kernel::SharedPtr<Kernel::Event> on_operation_mode_changed;
+    Kernel::EventPair on_new_message;
+    Kernel::EventPair on_operation_mode_changed;
 };
 
 class IWindowController final : public ServiceFramework<IWindowController> {
@@ -122,7 +119,7 @@ private:
     void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
 
     std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
-    Kernel::SharedPtr<Kernel::Event> launchable_event;
+    Kernel::EventPair launchable_event;
     u32 idle_time_detection_extension = 0;
 };
 
@@ -151,7 +148,6 @@ private:
     void GetBootMode(Kernel::HLERequestContext& ctx);
     void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
 
-    Kernel::SharedPtr<Kernel::Event> event;
     std::shared_ptr<AppletMessageQueue> msg_queue;
 };
 
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index becbadd06..47da35537 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -5,8 +5,9 @@
 #include <cstring>
 #include "common/assert.h"
 #include "core/core.h"
-#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/server_port.h"
+#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applets.h"
 
@@ -14,11 +15,11 @@ namespace Service::AM::Applets {
 
 AppletDataBroker::AppletDataBroker() {
     auto& kernel = Core::System::GetInstance().Kernel();
-    state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
-                                                "ILibraryAppletAccessor:StateChangedEvent");
-    pop_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
-                                               "ILibraryAppletAccessor:PopDataOutEvent");
-    pop_interactive_out_data_event = Kernel::Event::Create(
+    state_changed_event = Kernel::WritableEvent::CreateEventPair(
+        kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:StateChangedEvent");
+    pop_out_data_event = Kernel::WritableEvent::CreateEventPair(
+        kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopDataOutEvent");
+    pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
         kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
 }
 
@@ -66,7 +67,7 @@ void AppletDataBroker::PushNormalDataFromGame(IStorage storage) {
 
 void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) {
     out_channel.push(std::make_unique<IStorage>(storage));
-    pop_out_data_event->Signal();
+    pop_out_data_event.writable->Signal();
 }
 
 void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) {
@@ -75,23 +76,23 @@ void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) {
 
 void AppletDataBroker::PushInteractiveDataFromApplet(IStorage storage) {
     out_interactive_channel.push(std::make_unique<IStorage>(storage));
-    pop_interactive_out_data_event->Signal();
+    pop_interactive_out_data_event.writable->Signal();
 }
 
 void AppletDataBroker::SignalStateChanged() const {
-    state_changed_event->Signal();
+    state_changed_event.writable->Signal();
 }
 
-Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetNormalDataEvent() const {
-    return pop_out_data_event;
+Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
+    return pop_out_data_event.readable;
 }
 
-Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetInteractiveDataEvent() const {
-    return pop_interactive_out_data_event;
+Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
+    return pop_interactive_out_data_event.readable;
 }
 
-Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetStateChangedEvent() const {
-    return state_changed_event;
+Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
+    return state_changed_event.readable;
 }
 
 Applet::Applet() = default;
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index f65ea119c..b0a8913c3 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -8,13 +8,10 @@
 #include <queue>
 #include "common/swap.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/writable_event.h"
 
 union ResultCode;
 
-namespace Kernel {
-class Event;
-}
-
 namespace Service::AM {
 
 class IStorage;
@@ -40,9 +37,9 @@ public:
 
     void SignalStateChanged() const;
 
-    Kernel::SharedPtr<Kernel::Event> GetNormalDataEvent() const;
-    Kernel::SharedPtr<Kernel::Event> GetInteractiveDataEvent() const;
-    Kernel::SharedPtr<Kernel::Event> GetStateChangedEvent() const;
+    Kernel::SharedPtr<Kernel::ReadableEvent> GetNormalDataEvent() const;
+    Kernel::SharedPtr<Kernel::ReadableEvent> GetInteractiveDataEvent() const;
+    Kernel::SharedPtr<Kernel::ReadableEvent> GetStateChangedEvent() const;
 
 private:
     // Queues are named from applet's perspective
@@ -59,13 +56,13 @@ private:
     // PopInteractiveDataToGame and PushInteractiveDataFromApplet
     std::queue<std::unique_ptr<IStorage>> out_interactive_channel;
 
-    Kernel::SharedPtr<Kernel::Event> state_changed_event;
+    Kernel::EventPair state_changed_event;
 
     // Signaled on PushNormalDataFromApplet
-    Kernel::SharedPtr<Kernel::Event> pop_out_data_event;
+    Kernel::EventPair pop_out_data_event;
 
     // Signaled on PushInteractiveDataFromApplet
-    Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event;
+    Kernel::EventPair pop_interactive_out_data_event;
 };
 
 class Applet {
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index bacf19de2..b276de332 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -13,8 +13,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/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/hle/service/filesystem/filesystem.h"
 #include "core/loader/loader.h"
@@ -61,8 +63,8 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs
     RegisterHandlers(functions);
 
     auto& kernel = Core::System::GetInstance().Kernel();
-    aoc_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::Sticky,
-                                             "GetAddOnContentListChanged:Event");
+    aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+                                                              "GetAddOnContentListChanged:Event");
 }
 
 AOC_U::~AOC_U() = default;
@@ -144,7 +146,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
 
     IPC::ResponseBuilder rb{ctx, 2, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(aoc_change_event);
+    rb.PushCopyObjects(aoc_change_event.readable);
 }
 
 void InstallInterfaces(SM::ServiceManager& service_manager) {
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
index 68d94fdaa..5effea730 100644
--- a/src/core/hle/service/aoc/aoc_u.h
+++ b/src/core/hle/service/aoc/aoc_u.h
@@ -6,6 +6,10 @@
 
 #include "core/hle/service/service.h"
 
+namespace Kernel {
+class WritableEvent;
+}
+
 namespace Service::AOC {
 
 class AOC_U final : public ServiceFramework<AOC_U> {
@@ -21,7 +25,7 @@ private:
     void GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx);
 
     std::vector<u64> add_on_content;
-    Kernel::SharedPtr<Kernel::Event> aoc_change_event;
+    Kernel::EventPair aoc_change_event;
 };
 
 /// Registers all AOC services with the specified service manager.
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index d0dd1ef10..dc6a6b188 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -13,8 +13,10 @@
 #include "common/swap.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/hle_ipc.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/memory.h"
 
@@ -67,11 +69,12 @@ public:
 
         // This is the event handle used to check if the audio buffer was released
         auto& kernel = Core::System::GetInstance().Kernel();
-        buffer_event =
-            Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
+        buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+                                                              "IAudioOutBufferReleased");
 
         stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,
-                                       std::move(unique_name), [=]() { buffer_event->Signal(); });
+                                       std::move(unique_name),
+                                       [=]() { buffer_event.writable->Signal(); });
     }
 
 private:
@@ -121,7 +124,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(buffer_event);
+        rb.PushCopyObjects(buffer_event.readable);
     }
 
     void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
@@ -187,8 +190,8 @@ private:
 
     AudoutParams audio_params{};
 
-    /// This is the evend handle used to check if the audio buffer was released
-    Kernel::SharedPtr<Kernel::Event> buffer_event;
+    /// This is the event handle used to check if the audio buffer was released
+    Kernel::EventPair buffer_event;
 };
 
 void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 1c418a9bb..945259c7d 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -12,8 +12,10 @@
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/hle_ipc.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"
 
 namespace Service::Audio {
@@ -41,14 +43,14 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = Core::System::GetInstance().Kernel();
-        system_event =
-            Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");
-        renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event);
+        system_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+                                                              "IAudioRenderer:SystemEvent");
+        renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event.writable);
     }
 
 private:
     void UpdateAudioCallback() {
-        system_event->Signal();
+        system_event.writable->Signal();
     }
 
     void GetSampleRate(Kernel::HLERequestContext& ctx) {
@@ -112,7 +114,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(system_event);
+        rb.PushCopyObjects(system_event.readable);
     }
 
     void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) {
@@ -135,7 +137,7 @@ private:
         rb.Push(rendering_time_limit_percent);
     }
 
-    Kernel::SharedPtr<Kernel::Event> system_event;
+    Kernel::EventPair system_event;
     std::unique_ptr<AudioCore::AudioRenderer> renderer;
     u32 rendering_time_limit_percent = 100;
 };
@@ -162,8 +164,8 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = Core::System::GetInstance().Kernel();
-        buffer_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
-                                             "IAudioOutBufferReleasedEvent");
+        buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                              "IAudioOutBufferReleasedEvent");
     }
 
 private:
@@ -207,11 +209,11 @@ private:
     void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
         LOG_WARNING(Service_Audio, "(STUBBED) called");
 
-        buffer_event->Signal();
+        buffer_event.writable->Signal();
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(buffer_event);
+        rb.PushCopyObjects(buffer_event.readable);
     }
 
     void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
@@ -222,7 +224,7 @@ private:
         rb.Push<u32>(1);
     }
 
-    Kernel::SharedPtr<Kernel::Event> buffer_event;
+    Kernel::EventPair buffer_event;
 
 }; // namespace Audio
 
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 2eadcdd05..5704ca0ab 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -4,8 +4,10 @@
 
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/hle_ipc.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"
@@ -30,20 +32,22 @@ public:
         };
         // clang-format on
         RegisterHandlers(functions);
+
+        auto& kernel = Core::System::GetInstance().Kernel();
+        register_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                                "BT:RegisterEvent");
     }
 
 private:
     void RegisterEvent(Kernel::HLERequestContext& ctx) {
         LOG_WARNING(Service_BTM, "(STUBBED) called");
 
-        auto& kernel = Core::System::GetInstance().Kernel();
-        register_event =
-            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "BT:RegisterEvent");
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(register_event);
+        rb.PushCopyObjects(register_event.readable);
     }
-    Kernel::SharedPtr<Kernel::Event> register_event;
+
+    Kernel::EventPair register_event;
 };
 
 class BtDrv final : public ServiceFramework<BtDrv> {
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 463a79351..ef7398a23 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -6,8 +6,10 @@
 
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/hle_ipc.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"
 
@@ -53,53 +55,55 @@ public:
         };
         // clang-format on
         RegisterHandlers(functions);
+
+        auto& kernel = Core::System::GetInstance().Kernel();
+        scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                            "IBtmUserCore:ScanEvent");
+        connection_event = Kernel::WritableEvent::CreateEventPair(
+            kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConnectionEvent");
+        service_discovery = Kernel::WritableEvent::CreateEventPair(
+            kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery");
+        config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                              "IBtmUserCore:ConfigEvent");
     }
 
 private:
     void GetScanEvent(Kernel::HLERequestContext& ctx) {
         LOG_WARNING(Service_BTM, "(STUBBED) called");
 
-        auto& kernel = Core::System::GetInstance().Kernel();
-        scan_event =
-            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ScanEvent");
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(scan_event);
+        rb.PushCopyObjects(scan_event.readable);
     }
+
     void GetConnectionEvent(Kernel::HLERequestContext& ctx) {
         LOG_WARNING(Service_BTM, "(STUBBED) called");
 
-        auto& kernel = Core::System::GetInstance().Kernel();
-        connection_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
-                                                 "IBtmUserCore:ConnectionEvent");
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(connection_event);
+        rb.PushCopyObjects(connection_event.readable);
     }
+
     void GetDiscoveryEvent(Kernel::HLERequestContext& ctx) {
         LOG_WARNING(Service_BTM, "(STUBBED) called");
 
-        auto& kernel = Core::System::GetInstance().Kernel();
-        service_discovery =
-            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery");
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(service_discovery);
+        rb.PushCopyObjects(service_discovery.readable);
     }
+
     void GetConfigEvent(Kernel::HLERequestContext& ctx) {
         LOG_WARNING(Service_BTM, "(STUBBED) called");
 
-        auto& kernel = Core::System::GetInstance().Kernel();
-        config_event =
-            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConfigEvent");
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(config_event);
+        rb.PushCopyObjects(config_event.readable);
     }
-    Kernel::SharedPtr<Kernel::Event> scan_event;
-    Kernel::SharedPtr<Kernel::Event> connection_event;
-    Kernel::SharedPtr<Kernel::Event> service_discovery;
-    Kernel::SharedPtr<Kernel::Event> config_event;
+
+    Kernel::EventPair scan_event;
+    Kernel::EventPair connection_event;
+    Kernel::EventPair service_discovery;
+    Kernel::EventPair config_event;
 };
 
 class BTM_USR final : public ServiceFramework<BTM_USR> {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index b49e34594..d6829d0b8 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -12,7 +12,9 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/input.h"
-#include "core/hle/kernel/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"
 
@@ -167,8 +169,8 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
 
 void Controller_NPad::OnInit() {
     auto& kernel = Core::System::GetInstance().Kernel();
-    styleset_changed_event =
-        Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged");
+    styleset_changed_event = Kernel::WritableEvent::CreateEventPair(
+        kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged");
 
     if (!IsControllerActivated()) {
         return;
@@ -494,7 +496,7 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
             had_controller_update = true;
         }
         if (had_controller_update) {
-            styleset_changed_event->Signal();
+            styleset_changed_event.writable->Signal();
         }
     }
 }
@@ -509,7 +511,7 @@ std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
 }
 
 void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
-    styleset_changed_event->Signal();
+    styleset_changed_event.writable->Signal();
     hold_type = joy_hold_type;
 }
 
@@ -539,11 +541,11 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
     last_processed_vibration = vibrations.back();
 }
 
-Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() const {
+Kernel::SharedPtr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent() const {
     // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should
     // be signalled at least once, and signaled after a new controller is connected?
-    styleset_changed_event->Signal();
-    return styleset_changed_event;
+    styleset_changed_event.writable->Signal();
+    return styleset_changed_event.readable;
 }
 
 Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index abff6544d..29851f16a 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -8,7 +8,8 @@
 #include "common/bit_field.h"
 #include "common/common_types.h"
 #include "core/frontend/input.h"
-#include "core/hle/kernel/event.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"
 
@@ -108,7 +109,7 @@ public:
     void VibrateController(const std::vector<u32>& controller_ids,
                            const std::vector<Vibration>& vibrations);
 
-    Kernel::SharedPtr<Kernel::Event> GetStyleSetChangedEvent() const;
+    Kernel::SharedPtr<Kernel::ReadableEvent> GetStyleSetChangedEvent() const;
     Vibration GetLastVibration() const;
 
     void AddNewController(NPadControllerType controller);
@@ -303,7 +304,7 @@ private:
         sticks;
     std::vector<u32> supported_npad_id_types{};
     NpadHoldType hold_type{NpadHoldType::Vertical};
-    Kernel::SharedPtr<Kernel::Event> styleset_changed_event;
+    Kernel::EventPair styleset_changed_event;
     Vibration last_processed_vibration{};
     std::array<ControllerHolder, 10> connected_controllers{};
     bool can_controllers_vibrate{true};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 46496e9bb..2ec38c726 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -13,8 +13,9 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/client_session.h"
-#include "core/hle/kernel/event.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/hid.h"
 #include "core/hle/service/hid/irs.h"
 #include "core/hle/service/hid/xcd.h"
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index ff9170c24..d5df112a0 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -7,7 +7,9 @@
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/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/hid/hid.h"
 #include "core/hle/service/nfp/nfp.h"
@@ -23,8 +25,8 @@ constexpr ResultCode ERR_TAG_FAILED(ErrorModule::NFP,
 Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
     : ServiceFramework(name), module(std::move(module)) {
     auto& kernel = Core::System::GetInstance().Kernel();
-    nfc_tag_load =
-        Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:NFCTagDetected");
+    nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                          "IUser:NFCTagDetected");
 }
 
 Module::Interface::~Interface() = default;
@@ -63,10 +65,10 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = Core::System::GetInstance().Kernel();
-        deactivate_event =
-            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent");
-        availability_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
-                                                          "IUser:AvailabilityChangeEvent");
+        deactivate_event = Kernel::WritableEvent::CreateEventPair(
+            kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent");
+        availability_change_event = Kernel::WritableEvent::CreateEventPair(
+            kernel, Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent");
     }
 
 private:
@@ -164,7 +166,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(deactivate_event);
+        rb.PushCopyObjects(deactivate_event.readable);
     }
 
     void StopDetection(Kernel::HLERequestContext& ctx) {
@@ -173,7 +175,7 @@ private:
         switch (device_state) {
         case DeviceState::TagFound:
         case DeviceState::TagNearby:
-            deactivate_event->Signal();
+            deactivate_event.writable->Signal();
             device_state = DeviceState::Initialized;
             break;
         case DeviceState::SearchingForTag:
@@ -264,7 +266,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(availability_change_event);
+        rb.PushCopyObjects(availability_change_event.readable);
     }
 
     void GetRegisterInfo(Kernel::HLERequestContext& ctx) {
@@ -319,8 +321,8 @@ private:
     const u32 npad_id{0}; // Player 1 controller
     State state{State::NonInitialized};
     DeviceState device_state{DeviceState::Initialized};
-    Kernel::SharedPtr<Kernel::Event> deactivate_event;
-    Kernel::SharedPtr<Kernel::Event> availability_change_event;
+    Kernel::EventPair deactivate_event;
+    Kernel::EventPair availability_change_event;
     const Module::Interface& nfp_interface;
 };
 
@@ -339,12 +341,14 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
     }
 
     std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
-    nfc_tag_load->Signal();
+    nfc_tag_load.writable->Signal();
     return true;
 }
-const Kernel::SharedPtr<Kernel::Event>& Module::Interface::GetNFCEvent() const {
-    return nfc_tag_load;
+
+const Kernel::SharedPtr<Kernel::ReadableEvent>& Module::Interface::GetNFCEvent() const {
+    return nfc_tag_load.readable;
 }
+
 const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const {
     return amiibo;
 }
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 5c0ae8a54..a1817e991 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -6,7 +6,8 @@
 
 #include <array>
 #include <vector>
-#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/readable_event.h"
+#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/service.h"
 
 namespace Service::NFP {
@@ -33,11 +34,11 @@ public:
 
         void CreateUserInterface(Kernel::HLERequestContext& ctx);
         bool LoadAmiibo(const std::vector<u8>& buffer);
-        const Kernel::SharedPtr<Kernel::Event>& GetNFCEvent() const;
+        const Kernel::SharedPtr<Kernel::ReadableEvent>& GetNFCEvent() const;
         const AmiiboFile& GetAmiiboBuffer() const;
 
     private:
-        Kernel::SharedPtr<Kernel::Event> nfc_tag_load{};
+        Kernel::EventPair nfc_tag_load{};
         AmiiboFile amiibo{};
 
     protected:
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index dee391201..60479bb45 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -4,7 +4,9 @@
 
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/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"
 
@@ -56,8 +58,10 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = Core::System::GetInstance().Kernel();
-        event1 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event1");
-        event2 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event2");
+        event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                        "IRequest:Event1");
+        event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                        "IRequest:Event2");
     }
 
 private:
@@ -88,7 +92,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 2};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(event1, event2);
+        rb.PushCopyObjects(event1.readable, event2.readable);
     }
 
     void Cancel(Kernel::HLERequestContext& ctx) {
@@ -105,7 +109,7 @@ private:
         rb.Push(RESULT_SUCCESS);
     }
 
-    Kernel::SharedPtr<Kernel::Event> event1, event2;
+    Kernel::EventPair event1, event2;
 };
 
 class INetworkProfile final : public ServiceFramework<INetworkProfile> {
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index 1bbccd444..0dabcd23b 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -6,7 +6,9 @@
 #include <ctime>
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/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"
@@ -138,19 +140,18 @@ public:
         RegisterHandlers(functions);
 
         auto& kernel = Core::System::GetInstance().Kernel();
-        finished_event =
-            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
-                                  "IEnsureNetworkClockAvailabilityService:FinishEvent");
+        finished_event = Kernel::WritableEvent::CreateEventPair(
+            kernel, Kernel::ResetType::OneShot,
+            "IEnsureNetworkClockAvailabilityService:FinishEvent");
     }
 
 private:
-    Kernel::SharedPtr<Kernel::Event> finished_event;
+    Kernel::EventPair 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->Signal();
+        finished_event.writable->Signal();
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
     }
@@ -160,7 +161,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushCopyObjects(finished_event);
+        rb.PushCopyObjects(finished_event.readable);
     }
 
     void GetResult(Kernel::HLERequestContext& ctx) {
@@ -172,8 +173,7 @@ private:
 
     void Cancel(Kernel::HLERequestContext& ctx) {
         LOG_DEBUG(Service_NIM, "called");
-
-        finished_event->Clear();
+        finished_event.writable->Clear();
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
     }
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index ff76e0524..3b9ab4b14 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -6,7 +6,9 @@
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/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/nvdrv.h"
 
@@ -69,7 +71,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {
 
     IPC::ResponseBuilder rb{ctx, 3, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushCopyObjects(query_event);
+    rb.PushCopyObjects(query_event.readable);
     rb.Push<u32>(0);
 }
 
@@ -127,7 +129,8 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
     RegisterHandlers(functions);
 
     auto& kernel = Core::System::GetInstance().Kernel();
-    query_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "NVDRV::query_event");
+    query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot,
+                                                         "NVDRV::query_event");
 }
 
 NVDRV::~NVDRV() = default;
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index 5a1e4baa7..fe311b069 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -5,10 +5,13 @@
 #pragma once
 
 #include <memory>
-#include "core/hle/kernel/event.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
 #include "core/hle/service/service.h"
 
+namespace Kernel {
+class WritableEvent;
+}
+
 namespace Service::Nvidia {
 
 class NVDRV final : public ServiceFramework<NVDRV> {
@@ -31,7 +34,7 @@ private:
 
     u64 pid{};
 
-    Kernel::SharedPtr<Kernel::Event> query_event;
+    Kernel::EventPair query_event;
 };
 
 } // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 172a1a441..fc07d9bb8 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -7,14 +7,17 @@
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "core/core.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(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
     auto& kernel = Core::System::GetInstance().Kernel();
-    buffer_wait_event =
-        Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "BufferQueue NativeHandle");
+    buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
+                                                               "BufferQueue NativeHandle");
 }
 
 BufferQueue::~BufferQueue() = default;
@@ -28,7 +31,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
     buffer.status = Buffer::Status::Free;
 
     queue.emplace_back(buffer);
-    buffer_wait_event->Signal();
+    buffer_wait_event.writable->Signal();
 }
 
 std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
@@ -87,7 +90,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
     ASSERT(itr->status == Buffer::Status::Acquired);
     itr->status = Buffer::Status::Free;
 
-    buffer_wait_event->Signal();
+    buffer_wait_event.writable->Signal();
 }
 
 u32 BufferQueue::Query(QueryType type) {
@@ -104,4 +107,12 @@ u32 BufferQueue::Query(QueryType type) {
     return 0;
 }
 
+Kernel::SharedPtr<Kernel::WritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
+    return buffer_wait_event.writable;
+}
+
+Kernel::SharedPtr<Kernel::ReadableEvent> BufferQueue::GetBufferWaitEvent() const {
+    return buffer_wait_event.readable;
+}
+
 } // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 8cff5eb71..b171f256c 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -10,7 +10,8 @@
 #include "common/common_funcs.h"
 #include "common/math_util.h"
 #include "common/swap.h"
-#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/object.h"
+#include "core/hle/kernel/writable_event.h"
 
 namespace CoreTiming {
 struct EventType;
@@ -86,16 +87,16 @@ public:
         return id;
     }
 
-    Kernel::SharedPtr<Kernel::Event> GetBufferWaitEvent() const {
-        return buffer_wait_event;
-    }
+    Kernel::SharedPtr<Kernel::WritableEvent> GetWritableBufferWaitEvent() const;
+
+    Kernel::SharedPtr<Kernel::ReadableEvent> GetBufferWaitEvent() const;
 
 private:
     u32 id;
     u64 layer_id;
 
     std::vector<Buffer> queue;
-    Kernel::SharedPtr<Kernel::Event> buffer_wait_event;
+    Kernel::EventPair buffer_wait_event;
 };
 
 } // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 214e6d1b3..05af2d593 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -13,6 +13,9 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/core_timing_util.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/devices/nvdisp_disp0.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
 #include "core/hle/service/nvflinger/buffer_queue.h"
@@ -83,9 +86,8 @@ u32 NVFlinger::GetBufferQueueId(u64 display_id, u64 layer_id) {
     return layer.buffer_queue->GetId();
 }
 
-Kernel::SharedPtr<Kernel::Event> NVFlinger::GetVsyncEvent(u64 display_id) {
-    const auto& display = GetDisplay(display_id);
-    return display.vsync_event;
+Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::GetVsyncEvent(u64 display_id) {
+    return GetDisplay(display_id).vsync_event.readable;
 }
 
 std::shared_ptr<BufferQueue> NVFlinger::GetBufferQueue(u32 id) const {
@@ -117,7 +119,7 @@ Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) {
 void NVFlinger::Compose() {
     for (auto& display : displays) {
         // Trigger vsync for this display at the end of drawing
-        SCOPE_EXIT({ display.vsync_event->Signal(); });
+        SCOPE_EXIT({ display.vsync_event.writable->Signal(); });
 
         // Don't do anything for displays without layers.
         if (display.layers.empty())
@@ -164,7 +166,8 @@ Layer::~Layer() = default;
 
 Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) {
     auto& kernel = Core::System::GetInstance().Kernel();
-    vsync_event = Kernel::Event::Create(kernel, Kernel::ResetType::Pulse, "Display VSync Event");
+    vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Pulse,
+                                                         fmt::format("Display VSync Event {}", id));
 }
 
 Display::~Display() = default;
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 3dc69e69b..9abba555b 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -10,12 +10,17 @@
 #include <vector>
 
 #include "common/common_types.h"
-#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/object.h"
 
 namespace CoreTiming {
 struct EventType;
 }
 
+namespace Kernel {
+class ReadableEvent;
+class WritableEvent;
+} // namespace Kernel
+
 namespace Service::Nvidia {
 class Module;
 }
@@ -40,7 +45,7 @@ struct Display {
     std::string name;
 
     std::vector<Layer> layers;
-    Kernel::SharedPtr<Kernel::Event> vsync_event;
+    Kernel::EventPair vsync_event;
 };
 
 class NVFlinger final {
@@ -61,7 +66,7 @@ public:
     u32 GetBufferQueueId(u64 display_id, u64 layer_id);
 
     /// Gets the vsync event for the specified display.
-    Kernel::SharedPtr<Kernel::Event> GetVsyncEvent(u64 display_id);
+    Kernel::SharedPtr<Kernel::ReadableEvent> GetVsyncEvent(u64 display_id);
 
     /// Obtains a buffer queue identified by the id.
     std::shared_ptr<BufferQueue> GetBufferQueue(u32 id) const;
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 412d5b0c9..311b0c765 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -18,7 +18,8 @@
 #include "common/swap.h"
 #include "core/core_timing.h"
 #include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/readable_event.h"
+#include "core/hle/kernel/writable_event.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
 #include "core/hle/service/nvflinger/buffer_queue.h"
 #include "core/hle/service/nvflinger/nvflinger.h"
@@ -549,7 +550,7 @@ private:
                         IPC::ResponseBuilder rb{ctx, 2};
                         rb.Push(RESULT_SUCCESS);
                     },
-                    buffer_queue->GetBufferWaitEvent());
+                    buffer_queue->GetWritableBufferWaitEvent());
             }
         } else if (transaction == TransactionId::RequestBuffer) {
             IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()};
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 0c831c9f4..96c57fe97 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -7,10 +7,10 @@
 
 #include "common/assert.h"
 #include "core/core.h"
-#include "core/hle/kernel/event.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/mutex.h"
 #include "core/hle/kernel/process.h"
+#include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/timer.h"
@@ -154,7 +154,7 @@ QString WaitTreeWaitObject::GetText() const {
 std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitObject& object) {
     switch (object.GetHandleType()) {
     case Kernel::HandleType::Event:
-        return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::Event&>(object));
+        return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object));
     case Kernel::HandleType::Timer:
         return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object));
     case Kernel::HandleType::Thread:
@@ -332,7 +332,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
     return list;
 }
 
-WaitTreeEvent::WaitTreeEvent(const Kernel::Event& object) : WaitTreeWaitObject(object) {}
+WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) : WaitTreeWaitObject(object) {}
 WaitTreeEvent::~WaitTreeEvent() = default;
 
 std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
@@ -340,7 +340,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
 
     list.push_back(std::make_unique<WaitTreeText>(
         tr("reset type = %1")
-            .arg(GetResetTypeQString(static_cast<const Kernel::Event&>(object).GetResetType()))));
+            .arg(GetResetTypeQString(
+                static_cast<const Kernel::ReadableEvent&>(object).GetResetType()))));
     return list;
 }
 
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index 331f89885..492fb6ac9 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -17,8 +17,8 @@
 class EmuThread;
 
 namespace Kernel {
+class ReadableEvent;
 class WaitObject;
-class Event;
 class Thread;
 class Timer;
 } // namespace Kernel
@@ -144,7 +144,7 @@ public:
 class WaitTreeEvent : public WaitTreeWaitObject {
     Q_OBJECT
 public:
-    explicit WaitTreeEvent(const Kernel::Event& object);
+    explicit WaitTreeEvent(const Kernel::ReadableEvent& object);
     ~WaitTreeEvent() override;
 
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;