diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e1f21a764d..73aec8ab0b 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/event.cpp b/src/core/hle/kernel/event.cpp deleted file mode 100644 index 8967e602ea..0000000000 --- a/src/core/hle/kernel/event.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include "common/assert.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/object.h" -#include "core/hle/kernel/thread.h" - -namespace Kernel { - -Event::Event(KernelCore& kernel) : WaitObject{kernel} {} -Event::~Event() = default; - -SharedPtr Event::Create(KernelCore& kernel, ResetType reset_type, std::string name) { - SharedPtr 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 { - return !signaled; -} - -void Event::Acquire(Thread* thread) { - ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); - - if (reset_type == ResetType::OneShot) - signaled = false; -} - -void Event::Signal() { - signaled = true; - WakeupAllWaitingThreads(); -} - -void Event::Clear() { - signaled = false; -} - -void Event::WakeupAllWaitingThreads() { - WaitObject::WakeupAllWaitingThreads(); - - if (reset_type == ResetType::Pulse) - signaled = false; -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp new file mode 100644 index 0000000000..164cffbdbe --- /dev/null +++ b/src/core/hle/kernel/readable_event.cpp @@ -0,0 +1,48 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "common/assert.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 { + +ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {} +ReadableEvent::~ReadableEvent() = default; + +bool ReadableEvent::ShouldWait(Thread* thread) const { + return !writable_event->IsSignaled(); +} + +void ReadableEvent::Acquire(Thread* thread) { + ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); + + writable_event->ResetOnAcquire(); +} + +void ReadableEvent::AddWaitingThread(SharedPtr thread) { + writable_event->AddWaitingThread(thread); +} + +void ReadableEvent::RemoveWaitingThread(Thread* thread) { + writable_event->RemoveWaitingThread(thread); +} + +void ReadableEvent::Signal() { + writable_event->Signal(); +} + +void ReadableEvent::Clear() { + writable_event->Clear(); +} + +void ReadableEvent::WakeupAllWaitingThreads() { + writable_event->WakeupAllWaitingThreads(); + writable_event->ResetOnWakeup(); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h new file mode 100644 index 0000000000..020ef4ebc7 --- /dev/null +++ b/src/core/hle/kernel/readable_event.h @@ -0,0 +1,56 @@ +// 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; + } + + 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 AddWaitingThread(SharedPtr thread) override; + void RemoveWaitingThread(Thread* thread) override; + + void Signal(); + void Clear(); + + SharedPtr PromoteToWritable() const { + return writable_event; + } + +private: + explicit ReadableEvent(KernelCore& kernel); + + SharedPtr writable_event; ///< WritableEvent associated with this ReadableEvent + + std::string name; ///< Name of event (optional) +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp new file mode 100644 index 0000000000..4eb387ac04 --- /dev/null +++ b/src/core/hle/kernel/writable_event.cpp @@ -0,0 +1,81 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#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) : WaitObject{kernel} {} +WritableEvent::~WritableEvent() = default; + +std::tuple, SharedPtr> WritableEvent::CreateEventPair( + KernelCore& kernel, ResetType reset_type, std::string name) { + SharedPtr writable_event(new WritableEvent(kernel)); + SharedPtr readable_event(new ReadableEvent(kernel)); + + writable_event->name = name + ":Writable"; + writable_event->signaled = false; + writable_event->reset_type = reset_type; + readable_event->name = name + ":Readable"; + readable_event->writable_event = writable_event; + + return std::make_tuple(std::move(writable_event), std::move(readable_event)); +} + +SharedPtr WritableEvent::CreateRegisteredEventPair(KernelCore& kernel, + ResetType reset_type, + std::string name) { + auto [writable_event, readable_event] = CreateEventPair(kernel, reset_type, name); + kernel.AddNamedEvent(name, std::move(readable_event)); + return std::move(writable_event); +} + +bool WritableEvent::ShouldWait(Thread* thread) const { + return !signaled; +} + +void WritableEvent::Acquire(Thread* thread) { + ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); + + if (reset_type == ResetType::OneShot) + signaled = false; +} + +void WritableEvent::Signal() { + signaled = true; + WakeupAllWaitingThreads(); +} + +void WritableEvent::Clear() { + signaled = false; +} + +void WritableEvent::ResetOnAcquire() { + if (reset_type == ResetType::OneShot) + Clear(); +} + +void WritableEvent::ResetOnWakeup() { + if (reset_type == ResetType::Pulse) + Clear(); +} + +bool WritableEvent::IsSignaled() const { + return signaled; +} + +void WritableEvent::WakeupAllWaitingThreads() { + WaitObject::WakeupAllWaitingThreads(); + + if (reset_type == ResetType::Pulse) + signaled = false; +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/writable_event.h similarity index 56% rename from src/core/hle/kernel/event.h rename to src/core/hle/kernel/writable_event.h index 27d6126b0a..c0fe42302b 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/writable_event.h @@ -11,20 +11,33 @@ namespace Kernel { class KernelCore; +class ReadableEvent; -class Event final : public WaitObject { +class WritableEvent final : public WaitObject { 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 Create(KernelCore& kernel, ResetType reset_type, - std::string name = "Unknown"); + static std::tuple, SharedPtr> CreateEventPair( + KernelCore& kernel, ResetType reset_type, std::string name = "Unknown"); + + /** + * Creates an event and registers it in the kernel's named event table + * @param kernel The kernel instance to create this event under. + * @param reset_type ResetType describing how to create event + * @param name name of event + */ + static SharedPtr CreateRegisteredEventPair(KernelCore& kernel, + ResetType reset_type, + std::string name); std::string GetTypeName() const override { - return "Event"; + return "WritableEvent"; } std::string GetName() const override { return name; @@ -46,10 +59,12 @@ public: void Signal(); void Clear(); + void ResetOnAcquire(); + void ResetOnWakeup(); + bool IsSignaled() const; private: - explicit Event(KernelCore& kernel); - ~Event() override; + explicit WritableEvent(KernelCore& kernel); ResetType reset_type; ///< Current ResetType