From c7133838161ce0c17276ef96c0decfb855510165 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 26 Nov 2018 18:31:22 -0500 Subject: kernel: Divide Event into ReadableEvent and WritableEvent More hardware accurate. On the actual system, there is a differentiation between the signaler and signalee, they form a client/server relationship much like ServerPort and ClientPort. --- src/core/hle/kernel/event.cpp | 53 ---------------------- src/core/hle/kernel/event.h | 60 ------------------------- src/core/hle/kernel/readable_event.cpp | 48 ++++++++++++++++++++ src/core/hle/kernel/readable_event.h | 56 +++++++++++++++++++++++ src/core/hle/kernel/writable_event.cpp | 81 ++++++++++++++++++++++++++++++++++ src/core/hle/kernel/writable_event.h | 75 +++++++++++++++++++++++++++++++ 6 files changed, 260 insertions(+), 113 deletions(-) delete mode 100644 src/core/hle/kernel/event.cpp delete mode 100644 src/core/hle/kernel/event.h create mode 100644 src/core/hle/kernel/readable_event.cpp create mode 100644 src/core/hle/kernel/readable_event.h create mode 100644 src/core/hle/kernel/writable_event.cpp create mode 100644 src/core/hle/kernel/writable_event.h (limited to 'src/core/hle') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp deleted file mode 100644 index 8967e602e..000000000 --- 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/event.h b/src/core/hle/kernel/event.h deleted file mode 100644 index 27d6126b0..000000000 --- a/src/core/hle/kernel/event.h +++ /dev/null @@ -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 "common/common_types.h" -#include "core/hle/kernel/object.h" -#include "core/hle/kernel/wait_object.h" - -namespace Kernel { - -class KernelCore; - -class Event final : public WaitObject { -public: - /** - * 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"); - - std::string GetTypeName() const override { - return "Event"; - } - std::string GetName() const override { - return name; - } - - static const HandleType HANDLE_TYPE = HandleType::Event; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } - - ResetType GetResetType() const { - return reset_type; - } - - bool ShouldWait(Thread* thread) const override; - void Acquire(Thread* thread) override; - - void WakeupAllWaitingThreads() override; - - void Signal(); - void Clear(); - -private: - explicit Event(KernelCore& kernel); - ~Event() override; - - ResetType reset_type; ///< Current ResetType - - bool signaled; ///< Whether the event has already been signaled - std::string name; ///< Name of event (optional) -}; - -} // 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 000000000..164cffbdb --- /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 000000000..020ef4ebc --- /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 000000000..4eb387ac0 --- /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/writable_event.h b/src/core/hle/kernel/writable_event.h new file mode 100644 index 000000000..c0fe42302 --- /dev/null +++ b/src/core/hle/kernel/writable_event.h @@ -0,0 +1,75 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" +#include "core/hle/kernel/object.h" +#include "core/hle/kernel/wait_object.h" + +namespace Kernel { + +class KernelCore; +class ReadableEvent; + +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 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 "WritableEvent"; + } + std::string GetName() const override { + return name; + } + + static const HandleType HANDLE_TYPE = HandleType::Event; + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } + + ResetType GetResetType() const { + return reset_type; + } + + bool ShouldWait(Thread* thread) const override; + void Acquire(Thread* thread) override; + + void WakeupAllWaitingThreads() override; + + void Signal(); + void Clear(); + void ResetOnAcquire(); + void ResetOnWakeup(); + bool IsSignaled() const; + +private: + explicit WritableEvent(KernelCore& kernel); + + ResetType reset_type; ///< Current ResetType + + bool signaled; ///< Whether the event has already been signaled + std::string name; ///< Name of event (optional) +}; + +} // namespace Kernel -- cgit v1.2.3