summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-02-06 08:00:43 +0100
committerGitHub <noreply@github.com>2021-02-06 08:00:43 +0100
commit1498a7c9a84037d7c78ff21b3bc996622269db43 (patch)
tree0fb418f721db6e307fb7105cc57fe3a2eec7d0bf /src/core/hle/kernel
parentMerge pull request #5875 from lioncash/identifier (diff)
parenthle: kernel: Drop R_UNLESS_NOLOG in favor of expanded if-statement. (diff)
downloadyuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.tar
yuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.tar.gz
yuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.tar.bz2
yuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.tar.lz
yuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.tar.xz
yuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.tar.zst
yuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.zip
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp4
-rw-r--r--src/core/hle/kernel/hle_ipc.h4
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp10
-rw-r--r--src/core/hle/kernel/k_event.cpp32
-rw-r--r--src/core/hle/kernel/k_event.h57
-rw-r--r--src/core/hle/kernel/k_readable_event.cpp57
-rw-r--r--src/core/hle/kernel/k_readable_event.h51
-rw-r--r--src/core/hle/kernel/k_synchronization_object.cpp3
-rw-r--r--src/core/hle/kernel/k_synchronization_object.h1
-rw-r--r--src/core/hle/kernel/k_writable_event.cpp27
-rw-r--r--src/core/hle/kernel/k_writable_event.h44
-rw-r--r--src/core/hle/kernel/object.cpp6
-rw-r--r--src/core/hle/kernel/object.h7
-rw-r--r--src/core/hle/kernel/process.cpp19
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/hle/kernel/readable_event.cpp52
-rw-r--r--src/core/hle/kernel/readable_event.h59
-rw-r--r--src/core/hle/kernel/svc.cpp140
-rw-r--r--src/core/hle/kernel/svc_results.h1
-rw-r--r--src/core/hle/kernel/writable_event.cpp41
-rw-r--r--src/core/hle/kernel/writable_event.h60
21 files changed, 386 insertions, 291 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index c7b10ca7a..7ec62cf18 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -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 {
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 9f764c79a..9a769781b 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -41,8 +41,8 @@ class KernelCore;
class Process;
class ServerSession;
class KThread;
-class ReadableEvent;
-class WritableEvent;
+class KReadableEvent;
+class KWritableEvent;
enum class ThreadWakeupReason;
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index 1685d25bb..f2f497dc4 100644
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -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)) {
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp
new file mode 100644
index 000000000..bb2fa4ad5
--- /dev/null
+++ b/src/core/hle/kernel/k_event.cpp
@@ -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
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
new file mode 100644
index 000000000..2fb887129
--- /dev/null
+++ b/src/core/hle/kernel/k_event.h
@@ -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
diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp
new file mode 100644
index 000000000..d8a42dbaf
--- /dev/null
+++ b/src/core/hle/kernel/k_readable_event.cpp
@@ -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
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h
new file mode 100644
index 000000000..e6f0fd900
--- /dev/null
+++ b/src/core/hle/kernel/k_readable_event.h
@@ -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
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp
index a3b34f82f..140cc46a7 100644
--- a/src/core/hle/kernel/k_synchronization_object.cpp
+++ b/src/core/hle/kernel/k_synchronization_object.cpp
@@ -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) {
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h
index f65c71c28..5803718fd 100644
--- a/src/core/hle/kernel/k_synchronization_object.h
+++ b/src/core/hle/kernel/k_synchronization_object.h
@@ -33,6 +33,7 @@ public:
protected:
explicit KSynchronizationObject(KernelCore& kernel);
+ explicit KSynchronizationObject(KernelCore& kernel, std::string&& name);
virtual ~KSynchronizationObject();
void NotifyAvailable(ResultCode result);
diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp
new file mode 100644
index 000000000..25c52edb2
--- /dev/null
+++ b/src/core/hle/kernel/k_writable_event.cpp
@@ -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
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h
new file mode 100644
index 000000000..518f5448d
--- /dev/null
+++ b/src/core/hle/kernel/k_writable_event.h
@@ -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
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index 2c571792b..d7f40c403 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -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:
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index be7fcb5fb..501e58b33 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -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>
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index afdb27c54..2286b292d 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -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;
}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index c8af76ce8..320b0f347 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -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
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp
deleted file mode 100644
index 596d01479..000000000
--- a/src/core/hle/kernel/readable_event.cpp
+++ /dev/null
@@ -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
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
deleted file mode 100644
index 2195710c2..000000000
--- a/src/core/hle/kernel/readable_event.h
+++ /dev/null
@@ -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
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 74eb90100..edf208eff 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -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) {
- LOG_DEBUG(Kernel_SVC, "called");
+static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
+ LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
- auto& kernel = system.Kernel();
- const auto [readable_event, writable_event] =
- WritableEvent::CreateEventPair(kernel, "CreateEvent");
+ // Get the current handle table.
+ const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
- HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
+ // Get the writable event.
+ auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
+ R_UNLESS(writable_event, Svc::ResultInvalidHandle);
- const auto write_create_result = handle_table.Create(writable_event);
- 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);
- if (read_create_result.Failed()) {
- handle_table.Close(*write_create_result);
- return read_create_result.Code();
- }
- *read_handle = *read_create_result;
-
- LOG_DEBUG(Kernel_SVC,
- "successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}",
- *write_create_result, *read_create_result);
- return RESULT_SUCCESS;
+ return writable_event->Signal();
}
-static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) {
- return CreateEvent(system, write_handle, read_handle);
+static ResultCode SignalEvent32(Core::System& system, Handle event_handle) {
+ return SignalEvent(system, event_handle);
}
-static ResultCode ClearEvent(Core::System& system, Handle handle) {
- LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", 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();
- auto writable_event = handle_table.Get<WritableEvent>(handle);
- if (writable_event) {
- writable_event->Clear();
- return RESULT_SUCCESS;
+ // Try to clear the writable event.
+ {
+ auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
+ if (writable_event) {
+ return writable_event->Clear();
+ }
}
- auto readable_event = handle_table.Get<ReadableEvent>(handle);
- if (readable_event) {
- readable_event->Clear();
- return RESULT_SUCCESS;
+ // 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, handle=0x{:08X}", handle);
- return ERR_INVALID_HANDLE;
+ 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 handle) {
- return ClearEvent(system, handle);
+static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
+ return ClearEvent(system, event_handle);
}
-static ResultCode SignalEvent(Core::System& system, Handle handle) {
- LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", 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();
+ HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
+
+ // Create a new event.
+ const auto event = KEvent::Create(kernel, "CreateEvent");
+ R_UNLESS(event != nullptr, Svc::ResultOutOfResource);
- HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
- auto writable_event = handle_table.Get<WritableEvent>(handle);
+ // Initialize the event.
+ event->Initialize();
- if (!writable_event) {
- LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle);
- return ERR_INVALID_HANDLE;
+ // 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();
+ }
+ *out_write = *write_create_result;
+
+ // 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()) {
+ return read_create_result.Code();
}
+ *out_read = *read_create_result;
- writable_event->Signal();
+ // We succeeded.
+ handle_guard.Cancel();
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) {
diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h
index 7b897fbce..204cd989d 100644
--- a/src/core/hle/kernel/svc_results.h
+++ b/src/core/hle/kernel/svc_results.h
@@ -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};
diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp
deleted file mode 100644
index 142212ee4..000000000
--- a/src/core/hle/kernel/writable_event.cpp
+++ /dev/null
@@ -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
diff --git a/src/core/hle/kernel/writable_event.h b/src/core/hle/kernel/writable_event.h
deleted file mode 100644
index 467eb2c21..000000000
--- a/src/core/hle/kernel/writable_event.h
+++ /dev/null
@@ -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