hle: kernel: Reimplement KReadableEvent and KWritableEvent.

This commit is contained in:
bunnei 2021-01-31 01:38:57 -08:00
parent 6bf80dfee0
commit ff3c7c068b
38 changed files with 342 additions and 299 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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) {

View file

@ -33,6 +33,7 @@ public:
protected:
explicit KSynchronizationObject(KernelCore& kernel);
explicit KSynchronizationObject(KernelCore& kernel, std::string&& name);
virtual ~KSynchronizationObject();
void NotifyAvailable(ResultCode result);

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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>

View file

@ -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();