Browse Source
kernel: Divide Event into ReadableEvent and WritableEvent
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.nce_cpp
6 changed files with 210 additions and 61 deletions
-
6src/core/CMakeLists.txt
-
53src/core/hle/kernel/event.cpp
-
48src/core/hle/kernel/readable_event.cpp
-
56src/core/hle/kernel/readable_event.h
-
81src/core/hle/kernel/writable_event.cpp
-
27src/core/hle/kernel/writable_event.h
@ -1,53 +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/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> 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 { |
|||
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
|
|||
@ -0,0 +1,48 @@ |
|||
// 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/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> 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
|
|||
@ -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> thread) override; |
|||
void RemoveWaitingThread(Thread* thread) override; |
|||
|
|||
void Signal(); |
|||
void Clear(); |
|||
|
|||
SharedPtr<WritableEvent> PromoteToWritable() const { |
|||
return writable_event; |
|||
} |
|||
|
|||
private: |
|||
explicit ReadableEvent(KernelCore& kernel); |
|||
|
|||
SharedPtr<WritableEvent> writable_event; ///< WritableEvent associated with this ReadableEvent |
|||
|
|||
std::string name; ///< Name of event (optional) |
|||
}; |
|||
|
|||
} // namespace Kernel |
|||
@ -0,0 +1,81 @@ |
|||
// 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) : WaitObject{kernel} {} |
|||
WritableEvent::~WritableEvent() = default; |
|||
|
|||
std::tuple<SharedPtr<WritableEvent>, SharedPtr<ReadableEvent>> 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->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> 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
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue