hle: kernel: Reimplement KReadableEvent and KWritableEvent.
This commit is contained in:
parent
6bf80dfee0
commit
ff3c7c068b
38 changed files with 342 additions and 299 deletions
|
@ -1,9 +1,10 @@
|
|||
// Copyright 2014 Citra Emulator Project
|
||||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
|
@ -11,40 +12,43 @@
|
|||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
KReadableEvent::KReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {}
|
||||
KReadableEvent::KReadableEvent(KernelCore& kernel, std::string&& name)
|
||||
: KSynchronizationObject{kernel, std::move(name)} {}
|
||||
KReadableEvent::~KReadableEvent() = default;
|
||||
|
||||
void KReadableEvent::Signal() {
|
||||
if (is_signaled) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_signaled = true;
|
||||
NotifyAvailable();
|
||||
}
|
||||
|
||||
bool KReadableEvent::IsSignaled() const {
|
||||
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
||||
|
||||
return is_signaled;
|
||||
}
|
||||
|
||||
void KReadableEvent::Clear() {
|
||||
is_signaled = false;
|
||||
ResultCode KReadableEvent::Signal() {
|
||||
KScopedSchedulerLock lk{kernel};
|
||||
|
||||
if (!is_signaled) {
|
||||
is_signaled = true;
|
||||
NotifyAvailable();
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode KReadableEvent::Clear() {
|
||||
Reset();
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode KReadableEvent::Reset() {
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
if (!is_signaled) {
|
||||
LOG_TRACE(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}",
|
||||
GetObjectId(), GetTypeName(), GetName());
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
KScopedSchedulerLock lk{kernel};
|
||||
|
||||
Clear();
|
||||
R_UNLESS_NOLOG(is_signaled, Svc::ResultInvalidState);
|
||||
|
||||
is_signaled = false;
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 Citra Emulator Project
|
||||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -6,25 +6,20 @@
|
|||
|
||||
#include "core/hle/kernel/k_synchronization_object.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
union ResultCode;
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KernelCore;
|
||||
class KWritableEvent;
|
||||
class KEvent;
|
||||
|
||||
class KReadableEvent final : public KSynchronizationObject {
|
||||
friend class KWritableEvent;
|
||||
|
||||
public:
|
||||
explicit KReadableEvent(KernelCore& kernel, std::string&& name);
|
||||
~KReadableEvent() override;
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
return "ReadableEvent";
|
||||
}
|
||||
std::string GetName() const override {
|
||||
return name;
|
||||
return "KReadableEvent";
|
||||
}
|
||||
|
||||
static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
|
||||
|
@ -32,28 +27,25 @@ public:
|
|||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
/// Unconditionally clears the readable event's state.
|
||||
void Clear();
|
||||
KEvent* GetParent() const {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/// Clears the readable event's state if and only if it
|
||||
/// has already been signaled.
|
||||
///
|
||||
/// @pre The event must be in a signaled state. If this event
|
||||
/// is in an unsignaled state and this function is called,
|
||||
/// then ERR_INVALID_STATE will be returned.
|
||||
ResultCode Reset();
|
||||
|
||||
void Signal();
|
||||
void Initialize(KEvent* parent_) {
|
||||
is_signaled = false;
|
||||
parent = parent_;
|
||||
}
|
||||
|
||||
bool IsSignaled() const override;
|
||||
|
||||
void Finalize() override {}
|
||||
|
||||
private:
|
||||
explicit KReadableEvent(KernelCore& kernel);
|
||||
ResultCode Signal();
|
||||
ResultCode Clear();
|
||||
ResultCode Reset();
|
||||
|
||||
private:
|
||||
bool is_signaled{};
|
||||
std::string name; ///< Name of event (optional)
|
||||
KEvent* parent{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -132,6 +132,9 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
|
|||
|
||||
KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {}
|
||||
|
||||
KSynchronizationObject::KSynchronizationObject(KernelCore& kernel, std::string&& name)
|
||||
: Object{kernel, std::move(name)} {}
|
||||
|
||||
KSynchronizationObject::~KSynchronizationObject() = default;
|
||||
|
||||
void KSynchronizationObject::NotifyAvailable(ResultCode result) {
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
protected:
|
||||
explicit KSynchronizationObject(KernelCore& kernel);
|
||||
explicit KSynchronizationObject(KernelCore& kernel, std::string&& name);
|
||||
virtual ~KSynchronizationObject();
|
||||
|
||||
void NotifyAvailable(ResultCode result);
|
||||
|
|
|
@ -1,41 +1,27 @@
|
|||
// Copyright 2014 Citra Emulator Project
|
||||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include "common/assert.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
KWritableEvent::KWritableEvent(KernelCore& kernel) : Object{kernel} {}
|
||||
KWritableEvent::KWritableEvent(KernelCore& kernel, std::string&& name)
|
||||
: Object{kernel, std::move(name)} {}
|
||||
KWritableEvent::~KWritableEvent() = default;
|
||||
|
||||
EventPair KWritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
|
||||
std::shared_ptr<KWritableEvent> writable_event(new KWritableEvent(kernel));
|
||||
std::shared_ptr<KReadableEvent> readable_event(new KReadableEvent(kernel));
|
||||
|
||||
writable_event->name = name + ":Writable";
|
||||
writable_event->readable = readable_event;
|
||||
readable_event->name = name + ":Readable";
|
||||
|
||||
return {std::move(readable_event), std::move(writable_event)};
|
||||
void KWritableEvent::Initialize(KEvent* parent_) {
|
||||
parent = parent_;
|
||||
}
|
||||
|
||||
std::shared_ptr<KReadableEvent> KWritableEvent::GetReadableEvent() const {
|
||||
return readable;
|
||||
ResultCode KWritableEvent::Signal() {
|
||||
return parent->GetReadableEvent()->Signal();
|
||||
}
|
||||
|
||||
void KWritableEvent::Signal() {
|
||||
readable->Signal();
|
||||
}
|
||||
|
||||
void KWritableEvent::Clear() {
|
||||
readable->Clear();
|
||||
ResultCode KWritableEvent::Clear() {
|
||||
return parent->GetReadableEvent()->Clear();
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -4,37 +4,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KernelCore;
|
||||
class KReadableEvent;
|
||||
class KWritableEvent;
|
||||
|
||||
struct EventPair {
|
||||
std::shared_ptr<KReadableEvent> readable;
|
||||
std::shared_ptr<KWritableEvent> writable;
|
||||
};
|
||||
class KEvent;
|
||||
|
||||
class KWritableEvent final : public Object {
|
||||
public:
|
||||
explicit KWritableEvent(KernelCore& kernel, std::string&& name);
|
||||
~KWritableEvent() override;
|
||||
|
||||
/**
|
||||
* Creates an event
|
||||
* @param kernel The kernel instance to create this event under.
|
||||
* @param name Optional name of event
|
||||
*/
|
||||
static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown");
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
return "WritableEvent";
|
||||
}
|
||||
std::string GetName() const override {
|
||||
return name;
|
||||
return "KWritableEvent";
|
||||
}
|
||||
|
||||
static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
|
||||
|
@ -42,19 +26,19 @@ public:
|
|||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
std::shared_ptr<KReadableEvent> GetReadableEvent() const;
|
||||
|
||||
void Signal();
|
||||
void Clear();
|
||||
void Initialize(KEvent* parent_);
|
||||
|
||||
void Finalize() override {}
|
||||
|
||||
ResultCode Signal();
|
||||
ResultCode Clear();
|
||||
|
||||
KEvent* GetParent() const {
|
||||
return parent;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit KWritableEvent(KernelCore& kernel);
|
||||
|
||||
std::shared_ptr<KReadableEvent> readable;
|
||||
|
||||
std::string name; ///< Name of event (optional)
|
||||
KEvent* parent{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {}
|
||||
Object::Object(KernelCore& kernel_)
|
||||
: kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{"[UNKNOWN KERNEL OBJECT]"} {}
|
||||
Object::Object(KernelCore& kernel_, std::string&& name_)
|
||||
: kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{std::move(name_)} {}
|
||||
Object::~Object() = default;
|
||||
|
||||
bool Object::IsWaitable() const {
|
||||
|
@ -21,6 +24,7 @@ bool Object::IsWaitable() const {
|
|||
return true;
|
||||
|
||||
case HandleType::Unknown:
|
||||
case HandleType::Event:
|
||||
case HandleType::WritableEvent:
|
||||
case HandleType::SharedMemory:
|
||||
case HandleType::TransferMemory:
|
||||
|
|
|
@ -18,6 +18,7 @@ using Handle = u32;
|
|||
|
||||
enum class HandleType : u32 {
|
||||
Unknown,
|
||||
Event,
|
||||
WritableEvent,
|
||||
ReadableEvent,
|
||||
SharedMemory,
|
||||
|
@ -34,7 +35,8 @@ enum class HandleType : u32 {
|
|||
|
||||
class Object : NonCopyable, public std::enable_shared_from_this<Object> {
|
||||
public:
|
||||
explicit Object(KernelCore& kernel);
|
||||
explicit Object(KernelCore& kernel_);
|
||||
explicit Object(KernelCore& kernel_, std::string&& name_);
|
||||
virtual ~Object();
|
||||
|
||||
/// Returns a unique identifier for the object. For debugging purposes only.
|
||||
|
@ -46,7 +48,7 @@ public:
|
|||
return "[BAD KERNEL OBJECT TYPE]";
|
||||
}
|
||||
virtual std::string GetName() const {
|
||||
return "[UNKNOWN KERNEL OBJECT]";
|
||||
return name;
|
||||
}
|
||||
virtual HandleType GetHandleType() const = 0;
|
||||
|
||||
|
@ -69,6 +71,7 @@ protected:
|
|||
|
||||
private:
|
||||
std::atomic<u32> object_id{0};
|
||||
std::string name;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/k_address_arbiter.h"
|
||||
#include "core/hle/kernel/k_condition_variable.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_resource_limit.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
|
@ -1870,18 +1871,18 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle
|
|||
LOG_DEBUG(Kernel_SVC, "called");
|
||||
|
||||
auto& kernel = system.Kernel();
|
||||
const auto [readable_event, writable_event] =
|
||||
KWritableEvent::CreateEventPair(kernel, "CreateEvent");
|
||||
const auto event = KEvent::Create(kernel, "CreateEvent");
|
||||
event->Initialize();
|
||||
|
||||
HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
|
||||
|
||||
const auto write_create_result = handle_table.Create(writable_event);
|
||||
const auto write_create_result = handle_table.Create(event->GetWritableEvent());
|
||||
if (write_create_result.Failed()) {
|
||||
return write_create_result.Code();
|
||||
}
|
||||
*write_handle = *write_create_result;
|
||||
|
||||
const auto read_create_result = handle_table.Create(readable_event);
|
||||
const auto read_create_result = handle_table.Create(event->GetReadableEvent());
|
||||
if (read_create_result.Failed()) {
|
||||
handle_table.Close(*write_create_result);
|
||||
return read_create_result.Code();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue