Merge pull request #5862 from bunnei/kevent
Kernel Rework: Refactor KEvent/KReadableEvent/KWritableEvent
This commit is contained in:
commit
1498a7c9a8
63 changed files with 746 additions and 577 deletions
|
@ -17,16 +17,16 @@
|
|||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.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"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/readable_event.h"
|
||||
#include "core/hle/kernel/server_session.h"
|
||||
#include "core/hle/kernel/time_manager.h"
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
|
|
@ -41,8 +41,8 @@ class KernelCore;
|
|||
class Process;
|
||||
class ServerSession;
|
||||
class KThread;
|
||||
class ReadableEvent;
|
||||
class WritableEvent;
|
||||
class KReadableEvent;
|
||||
class KWritableEvent;
|
||||
|
||||
enum class ThreadWakeupReason;
|
||||
|
||||
|
|
|
@ -120,7 +120,10 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
|
|||
s32 user_value{};
|
||||
R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1),
|
||||
Svc::ResultInvalidCurrentMemory);
|
||||
R_UNLESS(user_value == value, Svc::ResultInvalidState);
|
||||
|
||||
if (user_value != value) {
|
||||
return Svc::ResultInvalidState;
|
||||
}
|
||||
|
||||
auto it = thread_tree.nfind_light({addr, -1});
|
||||
while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
|
||||
|
@ -211,7 +214,10 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
|
|||
}
|
||||
|
||||
R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory);
|
||||
R_UNLESS(user_value == value, Svc::ResultInvalidState);
|
||||
|
||||
if (user_value != value) {
|
||||
return Svc::ResultInvalidState;
|
||||
}
|
||||
|
||||
while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
|
||||
(it->GetAddressArbiterKey() == addr)) {
|
||||
|
|
32
src/core/hle/kernel/k_event.cpp
Normal file
32
src/core/hle/kernel/k_event.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
KEvent::KEvent(KernelCore& kernel, std::string&& name) : Object{kernel, std::move(name)} {}
|
||||
|
||||
KEvent::~KEvent() = default;
|
||||
|
||||
std::shared_ptr<KEvent> KEvent::Create(KernelCore& kernel, std::string&& name) {
|
||||
return std::make_shared<KEvent>(kernel, std::move(name));
|
||||
}
|
||||
|
||||
void KEvent::Initialize() {
|
||||
// Create our sub events.
|
||||
readable_event = std::make_shared<KReadableEvent>(kernel, GetName() + ":Readable");
|
||||
writable_event = std::make_shared<KWritableEvent>(kernel, GetName() + ":Writable");
|
||||
|
||||
// Initialize our sub sessions.
|
||||
readable_event->Initialize(this);
|
||||
writable_event->Initialize(this);
|
||||
|
||||
// Mark initialized.
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
57
src/core/hle/kernel/k_event.h
Normal file
57
src/core/hle/kernel/k_event.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KernelCore;
|
||||
class KReadableEvent;
|
||||
class KWritableEvent;
|
||||
|
||||
class KEvent final : public Object {
|
||||
public:
|
||||
explicit KEvent(KernelCore& kernel, std::string&& name);
|
||||
~KEvent() override;
|
||||
|
||||
static std::shared_ptr<KEvent> Create(KernelCore& kernel, std::string&& name);
|
||||
|
||||
void Initialize();
|
||||
|
||||
void Finalize() override {}
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
return "KEvent";
|
||||
}
|
||||
|
||||
static constexpr HandleType HANDLE_TYPE = HandleType::Event;
|
||||
HandleType GetHandleType() const override {
|
||||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
std::shared_ptr<KReadableEvent>& GetReadableEvent() {
|
||||
return readable_event;
|
||||
}
|
||||
|
||||
std::shared_ptr<KWritableEvent>& GetWritableEvent() {
|
||||
return writable_event;
|
||||
}
|
||||
|
||||
const std::shared_ptr<KReadableEvent>& GetReadableEvent() const {
|
||||
return readable_event;
|
||||
}
|
||||
|
||||
const std::shared_ptr<KWritableEvent>& GetWritableEvent() const {
|
||||
return writable_event;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<KReadableEvent> readable_event;
|
||||
std::shared_ptr<KWritableEvent> writable_event;
|
||||
bool initialized{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
57
src/core/hle/kernel/k_readable_event.cpp
Normal file
57
src/core/hle/kernel/k_readable_event.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
// 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"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#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, std::string&& name)
|
||||
: KSynchronizationObject{kernel, std::move(name)} {}
|
||||
KReadableEvent::~KReadableEvent() = default;
|
||||
|
||||
bool KReadableEvent::IsSignaled() const {
|
||||
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
||||
|
||||
return is_signaled;
|
||||
}
|
||||
|
||||
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 lk{kernel};
|
||||
|
||||
if (!is_signaled) {
|
||||
return Svc::ResultInvalidState;
|
||||
}
|
||||
|
||||
is_signaled = false;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
51
src/core/hle/kernel/k_readable_event.h
Normal file
51
src/core/hle/kernel/k_readable_event.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/k_synchronization_object.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KernelCore;
|
||||
class KEvent;
|
||||
|
||||
class KReadableEvent final : public KSynchronizationObject {
|
||||
public:
|
||||
explicit KReadableEvent(KernelCore& kernel, std::string&& name);
|
||||
~KReadableEvent() override;
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
return "KReadableEvent";
|
||||
}
|
||||
|
||||
static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
|
||||
HandleType GetHandleType() const override {
|
||||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
KEvent* GetParent() const {
|
||||
return parent;
|
||||
}
|
||||
|
||||
void Initialize(KEvent* parent_) {
|
||||
is_signaled = false;
|
||||
parent = parent_;
|
||||
}
|
||||
|
||||
bool IsSignaled() const override;
|
||||
void Finalize() override {}
|
||||
|
||||
ResultCode Signal();
|
||||
ResultCode Clear();
|
||||
ResultCode Reset();
|
||||
|
||||
private:
|
||||
bool is_signaled{};
|
||||
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);
|
||||
|
|
27
src/core/hle/kernel/k_writable_event.cpp
Normal file
27
src/core/hle/kernel/k_writable_event.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
KWritableEvent::KWritableEvent(KernelCore& kernel, std::string&& name)
|
||||
: Object{kernel, std::move(name)} {}
|
||||
KWritableEvent::~KWritableEvent() = default;
|
||||
|
||||
void KWritableEvent::Initialize(KEvent* parent_) {
|
||||
parent = parent_;
|
||||
}
|
||||
|
||||
ResultCode KWritableEvent::Signal() {
|
||||
return parent->GetReadableEvent()->Signal();
|
||||
}
|
||||
|
||||
ResultCode KWritableEvent::Clear() {
|
||||
return parent->GetReadableEvent()->Clear();
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
44
src/core/hle/kernel/k_writable_event.h
Normal file
44
src/core/hle/kernel/k_writable_event.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2021 yuzu 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/result.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KernelCore;
|
||||
class KEvent;
|
||||
|
||||
class KWritableEvent final : public Object {
|
||||
public:
|
||||
explicit KWritableEvent(KernelCore& kernel, std::string&& name);
|
||||
~KWritableEvent() override;
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
return "KWritableEvent";
|
||||
}
|
||||
|
||||
static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
|
||||
HandleType GetHandleType() const override {
|
||||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
void Initialize(KEvent* parent_);
|
||||
|
||||
void Finalize() override {}
|
||||
|
||||
ResultCode Signal();
|
||||
ResultCode Clear();
|
||||
|
||||
KEvent* GetParent() const {
|
||||
return parent;
|
||||
}
|
||||
|
||||
private:
|
||||
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>
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "core/hle/kernel/memory/page_table.h"
|
||||
#include "core/hle/kernel/memory/slab_heap.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/settings.h"
|
||||
|
@ -241,18 +242,16 @@ void Process::UnregisterThread(const KThread* thread) {
|
|||
thread_list.remove(thread);
|
||||
}
|
||||
|
||||
ResultCode Process::ClearSignalState() {
|
||||
KScopedSchedulerLock lock(system.Kernel());
|
||||
if (status == ProcessStatus::Exited) {
|
||||
LOG_ERROR(Kernel, "called on a terminated process instance.");
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
ResultCode Process::Reset() {
|
||||
// Lock the process and the scheduler.
|
||||
KScopedLightLock lk(state_lock);
|
||||
KScopedSchedulerLock sl{kernel};
|
||||
|
||||
if (!is_signaled) {
|
||||
LOG_ERROR(Kernel, "called on a process instance that isn't signaled.");
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
// Validate that we're in a state that we can reset.
|
||||
R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState);
|
||||
R_UNLESS(is_signaled, Svc::ResultInvalidState);
|
||||
|
||||
// Clear signaled.
|
||||
is_signaled = false;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -312,7 +312,7 @@ public:
|
|||
/// @pre The process must be in a signaled state. If this is called on a
|
||||
/// process instance that is not signaled, ERR_INVALID_STATE will be
|
||||
/// returned.
|
||||
ResultCode ClearSignalState();
|
||||
ResultCode Reset();
|
||||
|
||||
/**
|
||||
* Loads process-specifics configuration info with metadata provided
|
||||
|
|
|
@ -1,52 +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 "common/logging/log.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/readable_event.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ReadableEvent::ReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {}
|
||||
ReadableEvent::~ReadableEvent() = default;
|
||||
|
||||
void ReadableEvent::Signal() {
|
||||
if (is_signaled) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_signaled = true;
|
||||
NotifyAvailable();
|
||||
}
|
||||
|
||||
bool ReadableEvent::IsSignaled() const {
|
||||
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
||||
|
||||
return is_signaled;
|
||||
}
|
||||
|
||||
void ReadableEvent::Clear() {
|
||||
is_signaled = false;
|
||||
}
|
||||
|
||||
ResultCode ReadableEvent::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;
|
||||
}
|
||||
|
||||
Clear();
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
|
@ -1,59 +0,0 @@
|
|||
// 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/k_synchronization_object.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
union ResultCode;
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KernelCore;
|
||||
class WritableEvent;
|
||||
|
||||
class ReadableEvent final : public KSynchronizationObject {
|
||||
friend class WritableEvent;
|
||||
|
||||
public:
|
||||
~ReadableEvent() override;
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
return "ReadableEvent";
|
||||
}
|
||||
std::string GetName() const override {
|
||||
return name;
|
||||
}
|
||||
|
||||
static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
|
||||
HandleType GetHandleType() const override {
|
||||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
/// Unconditionally clears the readable event's state.
|
||||
void Clear();
|
||||
|
||||
/// 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();
|
||||
|
||||
bool IsSignaled() const override;
|
||||
|
||||
void Finalize() override {}
|
||||
|
||||
private:
|
||||
explicit ReadableEvent(KernelCore& kernel);
|
||||
|
||||
bool is_signaled{};
|
||||
std::string name; ///< Name of event (optional)
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
|
@ -14,6 +14,7 @@
|
|||
#include "common/fiber.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
|
@ -26,18 +27,20 @@
|
|||
#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"
|
||||
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
||||
#include "core/hle/kernel/k_synchronization_object.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/memory/memory_block.h"
|
||||
#include "core/hle/kernel/memory/memory_layout.h"
|
||||
#include "core/hle/kernel/memory/page_table.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/readable_event.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
|
@ -45,7 +48,6 @@
|
|||
#include "core/hle/kernel/svc_wrap.h"
|
||||
#include "core/hle/kernel/time_manager.h"
|
||||
#include "core/hle/kernel/transfer_memory.h"
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
@ -1725,20 +1727,28 @@ static ResultCode CloseHandle32(Core::System& system, Handle handle) {
|
|||
static ResultCode ResetSignal(Core::System& system, Handle handle) {
|
||||
LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
|
||||
|
||||
// Get the current handle table.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
|
||||
auto event = handle_table.Get<ReadableEvent>(handle);
|
||||
if (event) {
|
||||
return event->Reset();
|
||||
// Try to reset as readable event.
|
||||
{
|
||||
auto readable_event = handle_table.Get<KReadableEvent>(handle);
|
||||
if (readable_event) {
|
||||
return readable_event->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
auto process = handle_table.Get<Process>(handle);
|
||||
if (process) {
|
||||
return process->ClearSignalState();
|
||||
// Try to reset as process.
|
||||
{
|
||||
auto process = handle_table.Get<Process>(handle);
|
||||
if (process) {
|
||||
return process->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(Kernel_SVC, "Invalid handle (0x{:08X})", handle);
|
||||
return ERR_INVALID_HANDLE;
|
||||
LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle);
|
||||
|
||||
return Svc::ResultInvalidHandle;
|
||||
}
|
||||
|
||||
static ResultCode ResetSignal32(Core::System& system, Handle handle) {
|
||||
|
@ -1866,80 +1876,92 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle
|
|||
return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
|
||||
}
|
||||
|
||||
static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
|
||||
static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
|
||||
LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
|
||||
|
||||
// Get the current handle table.
|
||||
const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
|
||||
// Get the writable event.
|
||||
auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
|
||||
R_UNLESS(writable_event, Svc::ResultInvalidHandle);
|
||||
|
||||
return writable_event->Signal();
|
||||
}
|
||||
|
||||
static ResultCode SignalEvent32(Core::System& system, Handle event_handle) {
|
||||
return SignalEvent(system, event_handle);
|
||||
}
|
||||
|
||||
static ResultCode ClearEvent(Core::System& system, Handle event_handle) {
|
||||
LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
|
||||
|
||||
// Get the current handle table.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
|
||||
// Try to clear the writable event.
|
||||
{
|
||||
auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
|
||||
if (writable_event) {
|
||||
return writable_event->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Try to clear the readable event.
|
||||
{
|
||||
auto readable_event = handle_table.Get<KReadableEvent>(event_handle);
|
||||
if (readable_event) {
|
||||
return readable_event->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle);
|
||||
|
||||
return Svc::ResultInvalidHandle;
|
||||
}
|
||||
|
||||
static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
|
||||
return ClearEvent(system, event_handle);
|
||||
}
|
||||
|
||||
static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
|
||||
LOG_DEBUG(Kernel_SVC, "called");
|
||||
|
||||
// Get the kernel reference and handle table.
|
||||
auto& kernel = system.Kernel();
|
||||
const auto [readable_event, writable_event] =
|
||||
WritableEvent::CreateEventPair(kernel, "CreateEvent");
|
||||
|
||||
HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
|
||||
|
||||
const auto write_create_result = handle_table.Create(writable_event);
|
||||
// Create a new event.
|
||||
const auto event = KEvent::Create(kernel, "CreateEvent");
|
||||
R_UNLESS(event != nullptr, Svc::ResultOutOfResource);
|
||||
|
||||
// Initialize the event.
|
||||
event->Initialize();
|
||||
|
||||
// Add the writable event to the handle table.
|
||||
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;
|
||||
*out_write = *write_create_result;
|
||||
|
||||
const auto read_create_result = handle_table.Create(readable_event);
|
||||
// Add the writable event to the handle table.
|
||||
auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); });
|
||||
|
||||
// Add the readable event to the handle table.
|
||||
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();
|
||||
}
|
||||
*read_handle = *read_create_result;
|
||||
*out_read = *read_create_result;
|
||||
|
||||
LOG_DEBUG(Kernel_SVC,
|
||||
"successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}",
|
||||
*write_create_result, *read_create_result);
|
||||
// We succeeded.
|
||||
handle_guard.Cancel();
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) {
|
||||
return CreateEvent(system, write_handle, read_handle);
|
||||
}
|
||||
|
||||
static ResultCode ClearEvent(Core::System& system, Handle handle) {
|
||||
LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
|
||||
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
|
||||
auto writable_event = handle_table.Get<WritableEvent>(handle);
|
||||
if (writable_event) {
|
||||
writable_event->Clear();
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
auto readable_event = handle_table.Get<ReadableEvent>(handle);
|
||||
if (readable_event) {
|
||||
readable_event->Clear();
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle);
|
||||
return ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static ResultCode ClearEvent32(Core::System& system, Handle handle) {
|
||||
return ClearEvent(system, handle);
|
||||
}
|
||||
|
||||
static ResultCode SignalEvent(Core::System& system, Handle handle) {
|
||||
LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle);
|
||||
|
||||
HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
auto writable_event = handle_table.Get<WritableEvent>(handle);
|
||||
|
||||
if (!writable_event) {
|
||||
LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle);
|
||||
return ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
writable_event->Signal();
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static ResultCode SignalEvent32(Core::System& system, Handle handle) {
|
||||
return SignalEvent(system, handle);
|
||||
static ResultCode CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
|
||||
return CreateEvent(system, out_write, out_read);
|
||||
}
|
||||
|
||||
static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace Kernel::Svc {
|
|||
constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
|
||||
constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
|
||||
constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
|
||||
constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103};
|
||||
constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
|
||||
constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
|
||||
constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};
|
||||
|
|
|
@ -1,41 +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/k_thread.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/readable_event.h"
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
|
||||
WritableEvent::~WritableEvent() = default;
|
||||
|
||||
EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
|
||||
std::shared_ptr<WritableEvent> writable_event(new WritableEvent(kernel));
|
||||
std::shared_ptr<ReadableEvent> readable_event(new ReadableEvent(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)};
|
||||
}
|
||||
|
||||
std::shared_ptr<ReadableEvent> WritableEvent::GetReadableEvent() const {
|
||||
return readable;
|
||||
}
|
||||
|
||||
void WritableEvent::Signal() {
|
||||
readable->Signal();
|
||||
}
|
||||
|
||||
void WritableEvent::Clear() {
|
||||
readable->Clear();
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
|
@ -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 <memory>
|
||||
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KernelCore;
|
||||
class ReadableEvent;
|
||||
class WritableEvent;
|
||||
|
||||
struct EventPair {
|
||||
std::shared_ptr<ReadableEvent> readable;
|
||||
std::shared_ptr<WritableEvent> writable;
|
||||
};
|
||||
|
||||
class WritableEvent final : public Object {
|
||||
public:
|
||||
~WritableEvent() 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;
|
||||
}
|
||||
|
||||
static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
|
||||
HandleType GetHandleType() const override {
|
||||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
std::shared_ptr<ReadableEvent> GetReadableEvent() const;
|
||||
|
||||
void Signal();
|
||||
void Clear();
|
||||
|
||||
void Finalize() override {}
|
||||
|
||||
private:
|
||||
explicit WritableEvent(KernelCore& kernel);
|
||||
|
||||
std::shared_ptr<ReadableEvent> readable;
|
||||
|
||||
std::string name; ///< Name of event (optional)
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
Loading…
Add table
Add a link
Reference in a new issue