summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar bunnei2021-02-05 23:00:43 -0800
committerGravatar GitHub2021-02-05 23:00:43 -0800
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.gz
yuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.tar.xz
yuzu-1498a7c9a84037d7c78ff21b3bc996622269db43.zip
Merge pull request #5862 from bunnei/kevent
Kernel Rework: Refactor KEvent/KReadableEvent/KWritableEvent
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 @@
17#include "core/hle/kernel/errors.h" 17#include "core/hle/kernel/errors.h"
18#include "core/hle/kernel/handle_table.h" 18#include "core/hle/kernel/handle_table.h"
19#include "core/hle/kernel/hle_ipc.h" 19#include "core/hle/kernel/hle_ipc.h"
20#include "core/hle/kernel/k_readable_event.h"
20#include "core/hle/kernel/k_scheduler.h" 21#include "core/hle/kernel/k_scheduler.h"
21#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 22#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
22#include "core/hle/kernel/k_thread.h" 23#include "core/hle/kernel/k_thread.h"
24#include "core/hle/kernel/k_writable_event.h"
23#include "core/hle/kernel/kernel.h" 25#include "core/hle/kernel/kernel.h"
24#include "core/hle/kernel/object.h" 26#include "core/hle/kernel/object.h"
25#include "core/hle/kernel/process.h" 27#include "core/hle/kernel/process.h"
26#include "core/hle/kernel/readable_event.h"
27#include "core/hle/kernel/server_session.h" 28#include "core/hle/kernel/server_session.h"
28#include "core/hle/kernel/time_manager.h" 29#include "core/hle/kernel/time_manager.h"
29#include "core/hle/kernel/writable_event.h"
30#include "core/memory.h" 30#include "core/memory.h"
31 31
32namespace Kernel { 32namespace 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;
41class Process; 41class Process;
42class ServerSession; 42class ServerSession;
43class KThread; 43class KThread;
44class ReadableEvent; 44class KReadableEvent;
45class WritableEvent; 45class KWritableEvent;
46 46
47enum class ThreadWakeupReason; 47enum class ThreadWakeupReason;
48 48
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
120 s32 user_value{}; 120 s32 user_value{};
121 R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1), 121 R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1),
122 Svc::ResultInvalidCurrentMemory); 122 Svc::ResultInvalidCurrentMemory);
123 R_UNLESS(user_value == value, Svc::ResultInvalidState); 123
124 if (user_value != value) {
125 return Svc::ResultInvalidState;
126 }
124 127
125 auto it = thread_tree.nfind_light({addr, -1}); 128 auto it = thread_tree.nfind_light({addr, -1});
126 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && 129 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
@@ -211,7 +214,10 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
211 } 214 }
212 215
213 R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory); 216 R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory);
214 R_UNLESS(user_value == value, Svc::ResultInvalidState); 217
218 if (user_value != value) {
219 return Svc::ResultInvalidState;
220 }
215 221
216 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && 222 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
217 (it->GetAddressArbiterKey() == addr)) { 223 (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 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/k_event.h"
6#include "core/hle/kernel/k_readable_event.h"
7#include "core/hle/kernel/k_writable_event.h"
8
9namespace Kernel {
10
11KEvent::KEvent(KernelCore& kernel, std::string&& name) : Object{kernel, std::move(name)} {}
12
13KEvent::~KEvent() = default;
14
15std::shared_ptr<KEvent> KEvent::Create(KernelCore& kernel, std::string&& name) {
16 return std::make_shared<KEvent>(kernel, std::move(name));
17}
18
19void KEvent::Initialize() {
20 // Create our sub events.
21 readable_event = std::make_shared<KReadableEvent>(kernel, GetName() + ":Readable");
22 writable_event = std::make_shared<KWritableEvent>(kernel, GetName() + ":Writable");
23
24 // Initialize our sub sessions.
25 readable_event->Initialize(this);
26 writable_event->Initialize(this);
27
28 // Mark initialized.
29 initialized = true;
30}
31
32} // 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 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/object.h"
8
9namespace Kernel {
10
11class KernelCore;
12class KReadableEvent;
13class KWritableEvent;
14
15class KEvent final : public Object {
16public:
17 explicit KEvent(KernelCore& kernel, std::string&& name);
18 ~KEvent() override;
19
20 static std::shared_ptr<KEvent> Create(KernelCore& kernel, std::string&& name);
21
22 void Initialize();
23
24 void Finalize() override {}
25
26 std::string GetTypeName() const override {
27 return "KEvent";
28 }
29
30 static constexpr HandleType HANDLE_TYPE = HandleType::Event;
31 HandleType GetHandleType() const override {
32 return HANDLE_TYPE;
33 }
34
35 std::shared_ptr<KReadableEvent>& GetReadableEvent() {
36 return readable_event;
37 }
38
39 std::shared_ptr<KWritableEvent>& GetWritableEvent() {
40 return writable_event;
41 }
42
43 const std::shared_ptr<KReadableEvent>& GetReadableEvent() const {
44 return readable_event;
45 }
46
47 const std::shared_ptr<KWritableEvent>& GetWritableEvent() const {
48 return writable_event;
49 }
50
51private:
52 std::shared_ptr<KReadableEvent> readable_event;
53 std::shared_ptr<KWritableEvent> writable_event;
54 bool initialized{};
55};
56
57} // 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 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "common/common_funcs.h"
8#include "common/logging/log.h"
9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/k_scheduler.h"
12#include "core/hle/kernel/k_thread.h"
13#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/object.h"
15#include "core/hle/kernel/svc_results.h"
16
17namespace Kernel {
18
19KReadableEvent::KReadableEvent(KernelCore& kernel, std::string&& name)
20 : KSynchronizationObject{kernel, std::move(name)} {}
21KReadableEvent::~KReadableEvent() = default;
22
23bool KReadableEvent::IsSignaled() const {
24 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
25
26 return is_signaled;
27}
28
29ResultCode KReadableEvent::Signal() {
30 KScopedSchedulerLock lk{kernel};
31
32 if (!is_signaled) {
33 is_signaled = true;
34 NotifyAvailable();
35 }
36
37 return RESULT_SUCCESS;
38}
39
40ResultCode KReadableEvent::Clear() {
41 Reset();
42
43 return RESULT_SUCCESS;
44}
45
46ResultCode KReadableEvent::Reset() {
47 KScopedSchedulerLock lk{kernel};
48
49 if (!is_signaled) {
50 return Svc::ResultInvalidState;
51 }
52
53 is_signaled = false;
54 return RESULT_SUCCESS;
55}
56
57} // 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 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/k_synchronization_object.h"
8#include "core/hle/kernel/object.h"
9#include "core/hle/result.h"
10
11namespace Kernel {
12
13class KernelCore;
14class KEvent;
15
16class KReadableEvent final : public KSynchronizationObject {
17public:
18 explicit KReadableEvent(KernelCore& kernel, std::string&& name);
19 ~KReadableEvent() override;
20
21 std::string GetTypeName() const override {
22 return "KReadableEvent";
23 }
24
25 static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
26 HandleType GetHandleType() const override {
27 return HANDLE_TYPE;
28 }
29
30 KEvent* GetParent() const {
31 return parent;
32 }
33
34 void Initialize(KEvent* parent_) {
35 is_signaled = false;
36 parent = parent_;
37 }
38
39 bool IsSignaled() const override;
40 void Finalize() override {}
41
42 ResultCode Signal();
43 ResultCode Clear();
44 ResultCode Reset();
45
46private:
47 bool is_signaled{};
48 KEvent* parent{};
49};
50
51} // 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,
132 132
133KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {} 133KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {}
134 134
135KSynchronizationObject::KSynchronizationObject(KernelCore& kernel, std::string&& name)
136 : Object{kernel, std::move(name)} {}
137
135KSynchronizationObject::~KSynchronizationObject() = default; 138KSynchronizationObject::~KSynchronizationObject() = default;
136 139
137void KSynchronizationObject::NotifyAvailable(ResultCode result) { 140void 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:
33 33
34protected: 34protected:
35 explicit KSynchronizationObject(KernelCore& kernel); 35 explicit KSynchronizationObject(KernelCore& kernel);
36 explicit KSynchronizationObject(KernelCore& kernel, std::string&& name);
36 virtual ~KSynchronizationObject(); 37 virtual ~KSynchronizationObject();
37 38
38 void NotifyAvailable(ResultCode result); 39 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 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/k_event.h"
6#include "core/hle/kernel/k_readable_event.h"
7#include "core/hle/kernel/k_writable_event.h"
8
9namespace Kernel {
10
11KWritableEvent::KWritableEvent(KernelCore& kernel, std::string&& name)
12 : Object{kernel, std::move(name)} {}
13KWritableEvent::~KWritableEvent() = default;
14
15void KWritableEvent::Initialize(KEvent* parent_) {
16 parent = parent_;
17}
18
19ResultCode KWritableEvent::Signal() {
20 return parent->GetReadableEvent()->Signal();
21}
22
23ResultCode KWritableEvent::Clear() {
24 return parent->GetReadableEvent()->Clear();
25}
26
27} // 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 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/object.h"
8#include "core/hle/result.h"
9
10namespace Kernel {
11
12class KernelCore;
13class KEvent;
14
15class KWritableEvent final : public Object {
16public:
17 explicit KWritableEvent(KernelCore& kernel, std::string&& name);
18 ~KWritableEvent() override;
19
20 std::string GetTypeName() const override {
21 return "KWritableEvent";
22 }
23
24 static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
25 HandleType GetHandleType() const override {
26 return HANDLE_TYPE;
27 }
28
29 void Initialize(KEvent* parent_);
30
31 void Finalize() override {}
32
33 ResultCode Signal();
34 ResultCode Clear();
35
36 KEvent* GetParent() const {
37 return parent;
38 }
39
40private:
41 KEvent* parent{};
42};
43
44} // 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 @@
8 8
9namespace Kernel { 9namespace Kernel {
10 10
11Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {} 11Object::Object(KernelCore& kernel_)
12 : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{"[UNKNOWN KERNEL OBJECT]"} {}
13Object::Object(KernelCore& kernel_, std::string&& name_)
14 : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{std::move(name_)} {}
12Object::~Object() = default; 15Object::~Object() = default;
13 16
14bool Object::IsWaitable() const { 17bool Object::IsWaitable() const {
@@ -21,6 +24,7 @@ bool Object::IsWaitable() const {
21 return true; 24 return true;
22 25
23 case HandleType::Unknown: 26 case HandleType::Unknown:
27 case HandleType::Event:
24 case HandleType::WritableEvent: 28 case HandleType::WritableEvent:
25 case HandleType::SharedMemory: 29 case HandleType::SharedMemory:
26 case HandleType::TransferMemory: 30 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;
18 18
19enum class HandleType : u32 { 19enum class HandleType : u32 {
20 Unknown, 20 Unknown,
21 Event,
21 WritableEvent, 22 WritableEvent,
22 ReadableEvent, 23 ReadableEvent,
23 SharedMemory, 24 SharedMemory,
@@ -34,7 +35,8 @@ enum class HandleType : u32 {
34 35
35class Object : NonCopyable, public std::enable_shared_from_this<Object> { 36class Object : NonCopyable, public std::enable_shared_from_this<Object> {
36public: 37public:
37 explicit Object(KernelCore& kernel); 38 explicit Object(KernelCore& kernel_);
39 explicit Object(KernelCore& kernel_, std::string&& name_);
38 virtual ~Object(); 40 virtual ~Object();
39 41
40 /// Returns a unique identifier for the object. For debugging purposes only. 42 /// Returns a unique identifier for the object. For debugging purposes only.
@@ -46,7 +48,7 @@ public:
46 return "[BAD KERNEL OBJECT TYPE]"; 48 return "[BAD KERNEL OBJECT TYPE]";
47 } 49 }
48 virtual std::string GetName() const { 50 virtual std::string GetName() const {
49 return "[UNKNOWN KERNEL OBJECT]"; 51 return name;
50 } 52 }
51 virtual HandleType GetHandleType() const = 0; 53 virtual HandleType GetHandleType() const = 0;
52 54
@@ -69,6 +71,7 @@ protected:
69 71
70private: 72private:
71 std::atomic<u32> object_id{0}; 73 std::atomic<u32> object_id{0};
74 std::string name;
72}; 75};
73 76
74template <typename T> 77template <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 @@
23#include "core/hle/kernel/memory/page_table.h" 23#include "core/hle/kernel/memory/page_table.h"
24#include "core/hle/kernel/memory/slab_heap.h" 24#include "core/hle/kernel/memory/slab_heap.h"
25#include "core/hle/kernel/process.h" 25#include "core/hle/kernel/process.h"
26#include "core/hle/kernel/svc_results.h"
26#include "core/hle/lock.h" 27#include "core/hle/lock.h"
27#include "core/memory.h" 28#include "core/memory.h"
28#include "core/settings.h" 29#include "core/settings.h"
@@ -241,18 +242,16 @@ void Process::UnregisterThread(const KThread* thread) {
241 thread_list.remove(thread); 242 thread_list.remove(thread);
242} 243}
243 244
244ResultCode Process::ClearSignalState() { 245ResultCode Process::Reset() {
245 KScopedSchedulerLock lock(system.Kernel()); 246 // Lock the process and the scheduler.
246 if (status == ProcessStatus::Exited) { 247 KScopedLightLock lk(state_lock);
247 LOG_ERROR(Kernel, "called on a terminated process instance."); 248 KScopedSchedulerLock sl{kernel};
248 return ERR_INVALID_STATE;
249 }
250 249
251 if (!is_signaled) { 250 // Validate that we're in a state that we can reset.
252 LOG_ERROR(Kernel, "called on a process instance that isn't signaled."); 251 R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState);
253 return ERR_INVALID_STATE; 252 R_UNLESS(is_signaled, Svc::ResultInvalidState);
254 }
255 253
254 // Clear signaled.
256 is_signaled = false; 255 is_signaled = false;
257 return RESULT_SUCCESS; 256 return RESULT_SUCCESS;
258} 257}
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:
312 /// @pre The process must be in a signaled state. If this is called on a 312 /// @pre The process must be in a signaled state. If this is called on a
313 /// process instance that is not signaled, ERR_INVALID_STATE will be 313 /// process instance that is not signaled, ERR_INVALID_STATE will be
314 /// returned. 314 /// returned.
315 ResultCode ClearSignalState(); 315 ResultCode Reset();
316 316
317 /** 317 /**
318 * Loads process-specifics configuration info with metadata provided 318 * 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 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "common/logging/log.h"
8#include "core/hle/kernel/errors.h"
9#include "core/hle/kernel/k_scheduler.h"
10#include "core/hle/kernel/k_thread.h"
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/object.h"
13#include "core/hle/kernel/readable_event.h"
14
15namespace Kernel {
16
17ReadableEvent::ReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {}
18ReadableEvent::~ReadableEvent() = default;
19
20void ReadableEvent::Signal() {
21 if (is_signaled) {
22 return;
23 }
24
25 is_signaled = true;
26 NotifyAvailable();
27}
28
29bool ReadableEvent::IsSignaled() const {
30 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
31
32 return is_signaled;
33}
34
35void ReadableEvent::Clear() {
36 is_signaled = false;
37}
38
39ResultCode ReadableEvent::Reset() {
40 KScopedSchedulerLock lock(kernel);
41 if (!is_signaled) {
42 LOG_TRACE(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}",
43 GetObjectId(), GetTypeName(), GetName());
44 return ERR_INVALID_STATE;
45 }
46
47 Clear();
48
49 return RESULT_SUCCESS;
50}
51
52} // 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 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/k_synchronization_object.h"
8#include "core/hle/kernel/object.h"
9
10union ResultCode;
11
12namespace Kernel {
13
14class KernelCore;
15class WritableEvent;
16
17class ReadableEvent final : public KSynchronizationObject {
18 friend class WritableEvent;
19
20public:
21 ~ReadableEvent() override;
22
23 std::string GetTypeName() const override {
24 return "ReadableEvent";
25 }
26 std::string GetName() const override {
27 return name;
28 }
29
30 static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
31 HandleType GetHandleType() const override {
32 return HANDLE_TYPE;
33 }
34
35 /// Unconditionally clears the readable event's state.
36 void Clear();
37
38 /// Clears the readable event's state if and only if it
39 /// has already been signaled.
40 ///
41 /// @pre The event must be in a signaled state. If this event
42 /// is in an unsignaled state and this function is called,
43 /// then ERR_INVALID_STATE will be returned.
44 ResultCode Reset();
45
46 void Signal();
47
48 bool IsSignaled() const override;
49
50 void Finalize() override {}
51
52private:
53 explicit ReadableEvent(KernelCore& kernel);
54
55 bool is_signaled{};
56 std::string name; ///< Name of event (optional)
57};
58
59} // 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 @@
14#include "common/fiber.h" 14#include "common/fiber.h"
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/microprofile.h" 16#include "common/microprofile.h"
17#include "common/scope_exit.h"
17#include "common/string_util.h" 18#include "common/string_util.h"
18#include "core/arm/exclusive_monitor.h" 19#include "core/arm/exclusive_monitor.h"
19#include "core/core.h" 20#include "core/core.h"
@@ -26,18 +27,20 @@
26#include "core/hle/kernel/handle_table.h" 27#include "core/hle/kernel/handle_table.h"
27#include "core/hle/kernel/k_address_arbiter.h" 28#include "core/hle/kernel/k_address_arbiter.h"
28#include "core/hle/kernel/k_condition_variable.h" 29#include "core/hle/kernel/k_condition_variable.h"
30#include "core/hle/kernel/k_event.h"
31#include "core/hle/kernel/k_readable_event.h"
29#include "core/hle/kernel/k_resource_limit.h" 32#include "core/hle/kernel/k_resource_limit.h"
30#include "core/hle/kernel/k_scheduler.h" 33#include "core/hle/kernel/k_scheduler.h"
31#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 34#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
32#include "core/hle/kernel/k_synchronization_object.h" 35#include "core/hle/kernel/k_synchronization_object.h"
33#include "core/hle/kernel/k_thread.h" 36#include "core/hle/kernel/k_thread.h"
37#include "core/hle/kernel/k_writable_event.h"
34#include "core/hle/kernel/kernel.h" 38#include "core/hle/kernel/kernel.h"
35#include "core/hle/kernel/memory/memory_block.h" 39#include "core/hle/kernel/memory/memory_block.h"
36#include "core/hle/kernel/memory/memory_layout.h" 40#include "core/hle/kernel/memory/memory_layout.h"
37#include "core/hle/kernel/memory/page_table.h" 41#include "core/hle/kernel/memory/page_table.h"
38#include "core/hle/kernel/physical_core.h" 42#include "core/hle/kernel/physical_core.h"
39#include "core/hle/kernel/process.h" 43#include "core/hle/kernel/process.h"
40#include "core/hle/kernel/readable_event.h"
41#include "core/hle/kernel/shared_memory.h" 44#include "core/hle/kernel/shared_memory.h"
42#include "core/hle/kernel/svc.h" 45#include "core/hle/kernel/svc.h"
43#include "core/hle/kernel/svc_results.h" 46#include "core/hle/kernel/svc_results.h"
@@ -45,7 +48,6 @@
45#include "core/hle/kernel/svc_wrap.h" 48#include "core/hle/kernel/svc_wrap.h"
46#include "core/hle/kernel/time_manager.h" 49#include "core/hle/kernel/time_manager.h"
47#include "core/hle/kernel/transfer_memory.h" 50#include "core/hle/kernel/transfer_memory.h"
48#include "core/hle/kernel/writable_event.h"
49#include "core/hle/lock.h" 51#include "core/hle/lock.h"
50#include "core/hle/result.h" 52#include "core/hle/result.h"
51#include "core/hle/service/service.h" 53#include "core/hle/service/service.h"
@@ -1725,20 +1727,28 @@ static ResultCode CloseHandle32(Core::System& system, Handle handle) {
1725static ResultCode ResetSignal(Core::System& system, Handle handle) { 1727static ResultCode ResetSignal(Core::System& system, Handle handle) {
1726 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); 1728 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
1727 1729
1730 // Get the current handle table.
1728 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1731 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1729 1732
1730 auto event = handle_table.Get<ReadableEvent>(handle); 1733 // Try to reset as readable event.
1731 if (event) { 1734 {
1732 return event->Reset(); 1735 auto readable_event = handle_table.Get<KReadableEvent>(handle);
1736 if (readable_event) {
1737 return readable_event->Reset();
1738 }
1733 } 1739 }
1734 1740
1735 auto process = handle_table.Get<Process>(handle); 1741 // Try to reset as process.
1736 if (process) { 1742 {
1737 return process->ClearSignalState(); 1743 auto process = handle_table.Get<Process>(handle);
1744 if (process) {
1745 return process->Reset();
1746 }
1738 } 1747 }
1739 1748
1740 LOG_ERROR(Kernel_SVC, "Invalid handle (0x{:08X})", handle); 1749 LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle);
1741 return ERR_INVALID_HANDLE; 1750
1751 return Svc::ResultInvalidHandle;
1742} 1752}
1743 1753
1744static ResultCode ResetSignal32(Core::System& system, Handle handle) { 1754static ResultCode ResetSignal32(Core::System& system, Handle handle) {
@@ -1866,80 +1876,92 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle
1866 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask); 1876 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
1867} 1877}
1868 1878
1869static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { 1879static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
1870 LOG_DEBUG(Kernel_SVC, "called"); 1880 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
1871 1881
1872 auto& kernel = system.Kernel(); 1882 // Get the current handle table.
1873 const auto [readable_event, writable_event] = 1883 const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1874 WritableEvent::CreateEventPair(kernel, "CreateEvent");
1875 1884
1876 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); 1885 // Get the writable event.
1886 auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
1887 R_UNLESS(writable_event, Svc::ResultInvalidHandle);
1877 1888
1878 const auto write_create_result = handle_table.Create(writable_event); 1889 return writable_event->Signal();
1879 if (write_create_result.Failed()) {
1880 return write_create_result.Code();
1881 }
1882 *write_handle = *write_create_result;
1883
1884 const auto read_create_result = handle_table.Create(readable_event);
1885 if (read_create_result.Failed()) {
1886 handle_table.Close(*write_create_result);
1887 return read_create_result.Code();
1888 }
1889 *read_handle = *read_create_result;
1890
1891 LOG_DEBUG(Kernel_SVC,
1892 "successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}",
1893 *write_create_result, *read_create_result);
1894 return RESULT_SUCCESS;
1895} 1890}
1896 1891
1897static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) { 1892static ResultCode SignalEvent32(Core::System& system, Handle event_handle) {
1898 return CreateEvent(system, write_handle, read_handle); 1893 return SignalEvent(system, event_handle);
1899} 1894}
1900 1895
1901static ResultCode ClearEvent(Core::System& system, Handle handle) { 1896static ResultCode ClearEvent(Core::System& system, Handle event_handle) {
1902 LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); 1897 LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
1903 1898
1899 // Get the current handle table.
1904 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1900 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1905 1901
1906 auto writable_event = handle_table.Get<WritableEvent>(handle); 1902 // Try to clear the writable event.
1907 if (writable_event) { 1903 {
1908 writable_event->Clear(); 1904 auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
1909 return RESULT_SUCCESS; 1905 if (writable_event) {
1906 return writable_event->Clear();
1907 }
1910 } 1908 }
1911 1909
1912 auto readable_event = handle_table.Get<ReadableEvent>(handle); 1910 // Try to clear the readable event.
1913 if (readable_event) { 1911 {
1914 readable_event->Clear(); 1912 auto readable_event = handle_table.Get<KReadableEvent>(event_handle);
1915 return RESULT_SUCCESS; 1913 if (readable_event) {
1914 return readable_event->Clear();
1915 }
1916 } 1916 }
1917 1917
1918 LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); 1918 LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle);
1919 return ERR_INVALID_HANDLE; 1919
1920 return Svc::ResultInvalidHandle;
1920} 1921}
1921 1922
1922static ResultCode ClearEvent32(Core::System& system, Handle handle) { 1923static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
1923 return ClearEvent(system, handle); 1924 return ClearEvent(system, event_handle);
1924} 1925}
1925 1926
1926static ResultCode SignalEvent(Core::System& system, Handle handle) { 1927static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
1927 LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle); 1928 LOG_DEBUG(Kernel_SVC, "called");
1929
1930 // Get the kernel reference and handle table.
1931 auto& kernel = system.Kernel();
1932 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
1933
1934 // Create a new event.
1935 const auto event = KEvent::Create(kernel, "CreateEvent");
1936 R_UNLESS(event != nullptr, Svc::ResultOutOfResource);
1928 1937
1929 HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1938 // Initialize the event.
1930 auto writable_event = handle_table.Get<WritableEvent>(handle); 1939 event->Initialize();
1931 1940
1932 if (!writable_event) { 1941 // Add the writable event to the handle table.
1933 LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle); 1942 const auto write_create_result = handle_table.Create(event->GetWritableEvent());
1934 return ERR_INVALID_HANDLE; 1943 if (write_create_result.Failed()) {
1944 return write_create_result.Code();
1945 }
1946 *out_write = *write_create_result;
1947
1948 // Add the writable event to the handle table.
1949 auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); });
1950
1951 // Add the readable event to the handle table.
1952 const auto read_create_result = handle_table.Create(event->GetReadableEvent());
1953 if (read_create_result.Failed()) {
1954 return read_create_result.Code();
1935 } 1955 }
1956 *out_read = *read_create_result;
1936 1957
1937 writable_event->Signal(); 1958 // We succeeded.
1959 handle_guard.Cancel();
1938 return RESULT_SUCCESS; 1960 return RESULT_SUCCESS;
1939} 1961}
1940 1962
1941static ResultCode SignalEvent32(Core::System& system, Handle handle) { 1963static ResultCode CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
1942 return SignalEvent(system, handle); 1964 return CreateEvent(system, out_write, out_read);
1943} 1965}
1944 1966
1945static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { 1967static 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 {
11constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57}; 11constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
12constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; 12constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
13constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; 13constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
14constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103};
14constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; 15constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
15constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; 16constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
16constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113}; 17constexpr 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 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "core/hle/kernel/k_thread.h"
8#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/object.h"
10#include "core/hle/kernel/readable_event.h"
11#include "core/hle/kernel/writable_event.h"
12
13namespace Kernel {
14
15WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
16WritableEvent::~WritableEvent() = default;
17
18EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
19 std::shared_ptr<WritableEvent> writable_event(new WritableEvent(kernel));
20 std::shared_ptr<ReadableEvent> readable_event(new ReadableEvent(kernel));
21
22 writable_event->name = name + ":Writable";
23 writable_event->readable = readable_event;
24 readable_event->name = name + ":Readable";
25
26 return {std::move(readable_event), std::move(writable_event)};
27}
28
29std::shared_ptr<ReadableEvent> WritableEvent::GetReadableEvent() const {
30 return readable;
31}
32
33void WritableEvent::Signal() {
34 readable->Signal();
35}
36
37void WritableEvent::Clear() {
38 readable->Clear();
39}
40
41} // 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 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8
9#include "core/hle/kernel/object.h"
10
11namespace Kernel {
12
13class KernelCore;
14class ReadableEvent;
15class WritableEvent;
16
17struct EventPair {
18 std::shared_ptr<ReadableEvent> readable;
19 std::shared_ptr<WritableEvent> writable;
20};
21
22class WritableEvent final : public Object {
23public:
24 ~WritableEvent() override;
25
26 /**
27 * Creates an event
28 * @param kernel The kernel instance to create this event under.
29 * @param name Optional name of event
30 */
31 static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown");
32
33 std::string GetTypeName() const override {
34 return "WritableEvent";
35 }
36 std::string GetName() const override {
37 return name;
38 }
39
40 static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
41 HandleType GetHandleType() const override {
42 return HANDLE_TYPE;
43 }
44
45 std::shared_ptr<ReadableEvent> GetReadableEvent() const;
46
47 void Signal();
48 void Clear();
49
50 void Finalize() override {}
51
52private:
53 explicit WritableEvent(KernelCore& kernel);
54
55 std::shared_ptr<ReadableEvent> readable;
56
57 std::string name; ///< Name of event (optional)
58};
59
60} // namespace Kernel