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