summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/debugger/wait_tree.cpp1
-rw-r--r--src/citra_qt/debugger/wait_tree.h4
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/hle/ipc_helpers.h2
-rw-r--r--src/core/hle/kernel/address_arbiter.h1
-rw-r--r--src/core/hle/kernel/client_port.h1
-rw-r--r--src/core/hle/kernel/client_session.h3
-rw-r--r--src/core/hle/kernel/event.h1
-rw-r--r--src/core/hle/kernel/handle_table.cpp97
-rw-r--r--src/core/hle/kernel/handle_table.h126
-rw-r--r--src/core/hle/kernel/kernel.cpp164
-rw-r--r--src/core/hle/kernel/kernel.h181
-rw-r--r--src/core/hle/kernel/memory.cpp1
-rw-r--r--src/core/hle/kernel/mutex.h1
-rw-r--r--src/core/hle/kernel/resource_limit.cpp1
-rw-r--r--src/core/hle/kernel/semaphore.h2
-rw-r--r--src/core/hle/kernel/server_port.h1
-rw-r--r--src/core/hle/kernel/server_session.h3
-rw-r--r--src/core/hle/kernel/thread.cpp1
-rw-r--r--src/core/hle/kernel/thread.h1
-rw-r--r--src/core/hle/kernel/timer.cpp1
-rw-r--r--src/core/hle/kernel/timer.h1
-rw-r--r--src/core/hle/kernel/wait_object.cpp99
-rw-r--r--src/core/hle/kernel/wait_object.h67
-rw-r--r--src/core/hle/service/apt/apt.h2
-rw-r--r--src/core/hle/service/service.h1
-rw-r--r--src/core/hle/svc.cpp7
27 files changed, 430 insertions, 344 deletions
diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp
index b6ecf3819..8c244b6b2 100644
--- a/src/citra_qt/debugger/wait_tree.cpp
+++ b/src/citra_qt/debugger/wait_tree.cpp
@@ -10,6 +10,7 @@
10#include "core/hle/kernel/semaphore.h" 10#include "core/hle/kernel/semaphore.h"
11#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
12#include "core/hle/kernel/timer.h" 12#include "core/hle/kernel/timer.h"
13#include "core/hle/kernel/wait_object.h"
13 14
14WaitTreeItem::~WaitTreeItem() {} 15WaitTreeItem::~WaitTreeItem() {}
15 16
diff --git a/src/citra_qt/debugger/wait_tree.h b/src/citra_qt/debugger/wait_tree.h
index ee9708fc1..06ef58ea7 100644
--- a/src/citra_qt/debugger/wait_tree.h
+++ b/src/citra_qt/debugger/wait_tree.h
@@ -4,12 +4,10 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <boost/container/flat_set.hpp>
8
9#include <QAbstractItemModel> 7#include <QAbstractItemModel>
10#include <QDockWidget> 8#include <QDockWidget>
11#include <QTreeView> 9#include <QTreeView>
12 10#include <boost/container/flat_set.hpp>
13#include "core/core.h" 11#include "core/core.h"
14#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
15 13
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3cdb2b817..d66139c9c 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -45,6 +45,7 @@ set(SRCS
45 hle/kernel/client_port.cpp 45 hle/kernel/client_port.cpp
46 hle/kernel/client_session.cpp 46 hle/kernel/client_session.cpp
47 hle/kernel/event.cpp 47 hle/kernel/event.cpp
48 hle/kernel/handle_table.cpp
48 hle/kernel/kernel.cpp 49 hle/kernel/kernel.cpp
49 hle/kernel/memory.cpp 50 hle/kernel/memory.cpp
50 hle/kernel/mutex.cpp 51 hle/kernel/mutex.cpp
@@ -57,6 +58,7 @@ set(SRCS
57 hle/kernel/thread.cpp 58 hle/kernel/thread.cpp
58 hle/kernel/timer.cpp 59 hle/kernel/timer.cpp
59 hle/kernel/vm_manager.cpp 60 hle/kernel/vm_manager.cpp
61 hle/kernel/wait_object.cpp
60 hle/service/ac/ac.cpp 62 hle/service/ac/ac.cpp
61 hle/service/ac/ac_i.cpp 63 hle/service/ac/ac_i.cpp
62 hle/service/ac/ac_u.cpp 64 hle/service/ac/ac_u.cpp
@@ -236,6 +238,7 @@ set(HEADERS
236 hle/kernel/client_session.h 238 hle/kernel/client_session.h
237 hle/kernel/errors.h 239 hle/kernel/errors.h
238 hle/kernel/event.h 240 hle/kernel/event.h
241 hle/kernel/handle_table.h
239 hle/kernel/kernel.h 242 hle/kernel/kernel.h
240 hle/kernel/memory.h 243 hle/kernel/memory.h
241 hle/kernel/mutex.h 244 hle/kernel/mutex.h
@@ -249,6 +252,7 @@ set(HEADERS
249 hle/kernel/thread.h 252 hle/kernel/thread.h
250 hle/kernel/timer.h 253 hle/kernel/timer.h
251 hle/kernel/vm_manager.h 254 hle/kernel/vm_manager.h
255 hle/kernel/wait_object.h
252 hle/result.h 256 hle/result.h
253 hle/service/ac/ac.h 257 hle/service/ac/ac.h
254 hle/service/ac/ac_i.h 258 hle/service/ac/ac_i.h
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 06c4c5a85..d7348c09d 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -3,7 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6
6#include "core/hle/ipc.h" 7#include "core/hle/ipc.h"
8#include "core/hle/kernel/handle_table.h"
7#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
8 10
9namespace IPC { 11namespace IPC {
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 6a7af93a9..1d24401b1 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -6,6 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
9#include "core/hle/result.h"
9 10
10// Address arbiters are an underlying kernel synchronization object that can be created/used via 11// Address arbiters are an underlying kernel synchronization object that can be created/used via
11// supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR 12// supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 511490c7c..8f7d6ac44 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -7,6 +7,7 @@
7#include <string> 7#include <string>
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
10#include "core/hle/result.h"
10 11
11namespace Kernel { 12namespace Kernel {
12 13
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index 9f3adb72b..2de379c09 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -6,10 +6,9 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11
12#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/result.h"
13 12
14namespace Kernel { 13namespace Kernel {
15 14
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 3e3673508..cc41abb85 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -6,6 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/wait_object.h"
9 10
10namespace Kernel { 11namespace Kernel {
11 12
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
new file mode 100644
index 000000000..c7322d883
--- /dev/null
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -0,0 +1,97 @@
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 <utility>
6#include "common/assert.h"
7#include "common/logging/log.h"
8#include "core/hle/kernel/errors.h"
9#include "core/hle/kernel/handle_table.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/process.h"
12#include "core/hle/kernel/thread.h"
13
14namespace Kernel {
15
16HandleTable g_handle_table;
17
18HandleTable::HandleTable() {
19 next_generation = 1;
20 Clear();
21}
22
23ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
24 DEBUG_ASSERT(obj != nullptr);
25
26 u16 slot = next_free_slot;
27 if (slot >= generations.size()) {
28 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
29 return ERR_OUT_OF_HANDLES;
30 }
31 next_free_slot = generations[slot];
32
33 u16 generation = next_generation++;
34
35 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
36 // CTR-OS doesn't use generation 0, so skip straight to 1.
37 if (next_generation >= (1 << 15))
38 next_generation = 1;
39
40 generations[slot] = generation;
41 objects[slot] = std::move(obj);
42
43 Handle handle = generation | (slot << 15);
44 return MakeResult<Handle>(handle);
45}
46
47ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
48 SharedPtr<Object> object = GetGeneric(handle);
49 if (object == nullptr) {
50 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
51 return ERR_INVALID_HANDLE;
52 }
53 return Create(std::move(object));
54}
55
56ResultCode HandleTable::Close(Handle handle) {
57 if (!IsValid(handle))
58 return ERR_INVALID_HANDLE;
59
60 u16 slot = GetSlot(handle);
61
62 objects[slot] = nullptr;
63
64 generations[slot] = next_free_slot;
65 next_free_slot = slot;
66 return RESULT_SUCCESS;
67}
68
69bool HandleTable::IsValid(Handle handle) const {
70 size_t slot = GetSlot(handle);
71 u16 generation = GetGeneration(handle);
72
73 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
74}
75
76SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
77 if (handle == CurrentThread) {
78 return GetCurrentThread();
79 } else if (handle == CurrentProcess) {
80 return g_current_process;
81 }
82
83 if (!IsValid(handle)) {
84 return nullptr;
85 }
86 return objects[GetSlot(handle)];
87}
88
89void HandleTable::Clear() {
90 for (u16 i = 0; i < MAX_COUNT; ++i) {
91 generations[i] = i + 1;
92 objects[i] = nullptr;
93 }
94 next_free_slot = 0;
95}
96
97} // namespace
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
new file mode 100644
index 000000000..d6aaefbf7
--- /dev/null
+++ b/src/core/hle/kernel/handle_table.h
@@ -0,0 +1,126 @@
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 <array>
8#include <cstddef>
9#include "common/common_types.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/result.h"
12
13namespace Kernel {
14
15enum KernelHandle : Handle {
16 CurrentThread = 0xFFFF8000,
17 CurrentProcess = 0xFFFF8001,
18};
19
20/**
21 * This class allows the creation of Handles, which are references to objects that can be tested
22 * for validity and looked up. Here they are used to pass references to kernel objects to/from the
23 * emulated process. it has been designed so that it follows the same handle format and has
24 * approximately the same restrictions as the handle manager in the CTR-OS.
25 *
26 * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0).
27 * The slot index is used to index into the arrays in this class to access the data corresponding
28 * to the Handle.
29 *
30 * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter
31 * is kept and incremented every time a Handle is created. This is the Handle's "generation". The
32 * value of the counter is stored into the Handle as well as in the handle table (in the
33 * "generations" array). When looking up a handle, the Handle's generation must match with the
34 * value stored on the class, otherwise the Handle is considered invalid.
35 *
36 * To find free slots when allocating a Handle without needing to scan the entire object array, the
37 * generations field of unallocated slots is re-purposed as a linked list of indices to free slots.
38 * When a Handle is created, an index is popped off the list and used for the new Handle. When it
39 * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is
40 * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been
41 * verified and isn't likely to cause any problems.
42 */
43class HandleTable final : NonCopyable {
44public:
45 HandleTable();
46
47 /**
48 * Allocates a handle for the given object.
49 * @return The created Handle or one of the following errors:
50 * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
51 */
52 ResultVal<Handle> Create(SharedPtr<Object> obj);
53
54 /**
55 * Returns a new handle that points to the same object as the passed in handle.
56 * @return The duplicated Handle or one of the following errors:
57 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
58 * - Any errors returned by `Create()`.
59 */
60 ResultVal<Handle> Duplicate(Handle handle);
61
62 /**
63 * Closes a handle, removing it from the table and decreasing the object's ref-count.
64 * @return `RESULT_SUCCESS` or one of the following errors:
65 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
66 */
67 ResultCode Close(Handle handle);
68
69 /// Checks if a handle is valid and points to an existing object.
70 bool IsValid(Handle handle) const;
71
72 /**
73 * Looks up a handle.
74 * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
75 */
76 SharedPtr<Object> GetGeneric(Handle handle) const;
77
78 /**
79 * Looks up a handle while verifying its type.
80 * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
81 * type differs from the requested one.
82 */
83 template <class T>
84 SharedPtr<T> Get(Handle handle) const {
85 return DynamicObjectCast<T>(GetGeneric(handle));
86 }
87
88 /// Closes all handles held in this table.
89 void Clear();
90
91private:
92 /**
93 * This is the maximum limit of handles allowed per process in CTR-OS. It can be further
94 * reduced by ExHeader values, but this is not emulated here.
95 */
96 static const size_t MAX_COUNT = 4096;
97
98 static u16 GetSlot(Handle handle) {
99 return handle >> 15;
100 }
101 static u16 GetGeneration(Handle handle) {
102 return handle & 0x7FFF;
103 }
104
105 /// Stores the Object referenced by the handle or null if the slot is empty.
106 std::array<SharedPtr<Object>, MAX_COUNT> objects;
107
108 /**
109 * The value of `next_generation` when the handle was created, used to check for validity. For
110 * empty slots, contains the index of the next free slot in the list.
111 */
112 std::array<u16, MAX_COUNT> generations;
113
114 /**
115 * Global counter of the number of created handles. Stored in `generations` when a handle is
116 * created, and wraps around to 1 when it hits 0x8000.
117 */
118 u16 next_generation;
119
120 /// Head of the free slots linked list.
121 u16 next_free_slot;
122};
123
124extern HandleTable g_handle_table;
125
126} // namespace
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 7f84e01aa..7470a97ca 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -2,11 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include "common/assert.h"
7#include "common/logging/log.h"
8#include "core/hle/config_mem.h" 5#include "core/hle/config_mem.h"
9#include "core/hle/kernel/errors.h" 6#include "core/hle/kernel/handle_table.h"
10#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/memory.h" 8#include "core/hle/kernel/memory.h"
12#include "core/hle/kernel/process.h" 9#include "core/hle/kernel/process.h"
@@ -18,165 +15,6 @@
18namespace Kernel { 15namespace Kernel {
19 16
20unsigned int Object::next_object_id; 17unsigned int Object::next_object_id;
21HandleTable g_handle_table;
22
23void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
24 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
25 if (itr == waiting_threads.end())
26 waiting_threads.push_back(std::move(thread));
27}
28
29void WaitObject::RemoveWaitingThread(Thread* thread) {
30 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
31 // If a thread passed multiple handles to the same object,
32 // the kernel might attempt to remove the thread from the object's
33 // waiting threads list multiple times.
34 if (itr != waiting_threads.end())
35 waiting_threads.erase(itr);
36}
37
38SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
39 Thread* candidate = nullptr;
40 s32 candidate_priority = THREADPRIO_LOWEST + 1;
41
42 for (const auto& thread : waiting_threads) {
43 // The list of waiting threads must not contain threads that are not waiting to be awakened.
44 ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
45 thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
46 "Inconsistent thread statuses in waiting_threads");
47
48 if (thread->current_priority >= candidate_priority)
49 continue;
50
51 if (ShouldWait(thread.get()))
52 continue;
53
54 // A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or
55 // in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready.
56 bool ready_to_run = true;
57 if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) {
58 ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
59 [&thread](const SharedPtr<WaitObject>& object) {
60 return object->ShouldWait(thread.get());
61 });
62 }
63
64 if (ready_to_run) {
65 candidate = thread.get();
66 candidate_priority = thread->current_priority;
67 }
68 }
69
70 return candidate;
71}
72
73void WaitObject::WakeupAllWaitingThreads() {
74 while (auto thread = GetHighestPriorityReadyThread()) {
75 if (!thread->IsSleepingOnWaitAll()) {
76 Acquire(thread.get());
77 // Set the output index of the WaitSynchronizationN call to the index of this object.
78 if (thread->wait_set_output) {
79 thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(this));
80 thread->wait_set_output = false;
81 }
82 } else {
83 for (auto& object : thread->wait_objects) {
84 object->Acquire(thread.get());
85 }
86 // Note: This case doesn't update the output index of WaitSynchronizationN.
87 }
88
89 for (auto& object : thread->wait_objects)
90 object->RemoveWaitingThread(thread.get());
91 thread->wait_objects.clear();
92
93 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
94 thread->ResumeFromWait();
95 }
96}
97
98const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {
99 return waiting_threads;
100}
101
102HandleTable::HandleTable() {
103 next_generation = 1;
104 Clear();
105}
106
107ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
108 DEBUG_ASSERT(obj != nullptr);
109
110 u16 slot = next_free_slot;
111 if (slot >= generations.size()) {
112 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
113 return ERR_OUT_OF_HANDLES;
114 }
115 next_free_slot = generations[slot];
116
117 u16 generation = next_generation++;
118
119 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
120 // CTR-OS doesn't use generation 0, so skip straight to 1.
121 if (next_generation >= (1 << 15))
122 next_generation = 1;
123
124 generations[slot] = generation;
125 objects[slot] = std::move(obj);
126
127 Handle handle = generation | (slot << 15);
128 return MakeResult<Handle>(handle);
129}
130
131ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
132 SharedPtr<Object> object = GetGeneric(handle);
133 if (object == nullptr) {
134 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
135 return ERR_INVALID_HANDLE;
136 }
137 return Create(std::move(object));
138}
139
140ResultCode HandleTable::Close(Handle handle) {
141 if (!IsValid(handle))
142 return ERR_INVALID_HANDLE;
143
144 u16 slot = GetSlot(handle);
145
146 objects[slot] = nullptr;
147
148 generations[slot] = next_free_slot;
149 next_free_slot = slot;
150 return RESULT_SUCCESS;
151}
152
153bool HandleTable::IsValid(Handle handle) const {
154 size_t slot = GetSlot(handle);
155 u16 generation = GetGeneration(handle);
156
157 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
158}
159
160SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
161 if (handle == CurrentThread) {
162 return GetCurrentThread();
163 } else if (handle == CurrentProcess) {
164 return g_current_process;
165 }
166
167 if (!IsValid(handle)) {
168 return nullptr;
169 }
170 return objects[GetSlot(handle)];
171}
172
173void HandleTable::Clear() {
174 for (u16 i = 0; i < MAX_COUNT; ++i) {
175 generations[i] = i + 1;
176 objects[i] = nullptr;
177 }
178 next_free_slot = 0;
179}
180 18
181/// Initialize the kernel 19/// Initialize the kernel
182void Init(u32 system_mode) { 20void Init(u32 system_mode) {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 94f2025a0..9cf288b08 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -4,26 +4,16 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <algorithm>
8#include <array>
9#include <cstddef> 7#include <cstddef>
10#include <string> 8#include <string>
11#include <vector> 9#include <utility>
12#include <boost/smart_ptr/intrusive_ptr.hpp> 10#include <boost/smart_ptr/intrusive_ptr.hpp>
13#include "common/common_types.h" 11#include "common/common_types.h"
14#include "core/hle/result.h"
15 12
16namespace Kernel { 13namespace Kernel {
17 14
18using Handle = u32; 15using Handle = u32;
19 16
20class Thread;
21
22enum KernelHandle : Handle {
23 CurrentThread = 0xFFFF8000,
24 CurrentProcess = 0xFFFF8001,
25};
26
27enum class HandleType : u32 { 17enum class HandleType : u32 {
28 Unknown, 18 Unknown,
29 Event, 19 Event,
@@ -121,170 +111,17 @@ inline void intrusive_ptr_release(Object* object) {
121template <typename T> 111template <typename T>
122using SharedPtr = boost::intrusive_ptr<T>; 112using SharedPtr = boost::intrusive_ptr<T>;
123 113
124/// Class that represents a Kernel object that a thread can be waiting on
125class WaitObject : public Object {
126public:
127 /**
128 * Check if the specified thread should wait until the object is available
129 * @param thread The thread about which we're deciding.
130 * @return True if the current thread should wait due to this object being unavailable
131 */
132 virtual bool ShouldWait(Thread* thread) const = 0;
133
134 /// Acquire/lock the object for the specified thread if it is available
135 virtual void Acquire(Thread* thread) = 0;
136
137 /**
138 * Add a thread to wait on this object
139 * @param thread Pointer to thread to add
140 */
141 virtual void AddWaitingThread(SharedPtr<Thread> thread);
142
143 /**
144 * Removes a thread from waiting on this object (e.g. if it was resumed already)
145 * @param thread Pointer to thread to remove
146 */
147 virtual void RemoveWaitingThread(Thread* thread);
148
149 /**
150 * Wake up all threads waiting on this object that can be awoken, in priority order,
151 * and set the synchronization result and output of the thread.
152 */
153 virtual void WakeupAllWaitingThreads();
154
155 /// Obtains the highest priority thread that is ready to run from this object's waiting list.
156 SharedPtr<Thread> GetHighestPriorityReadyThread();
157
158 /// Get a const reference to the waiting threads list for debug use
159 const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
160
161private:
162 /// Threads waiting for this object to become available
163 std::vector<SharedPtr<Thread>> waiting_threads;
164};
165
166/** 114/**
167 * This class allows the creation of Handles, which are references to objects that can be tested 115 * Attempts to downcast the given Object pointer to a pointer to T.
168 * for validity and looked up. Here they are used to pass references to kernel objects to/from the 116 * @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.
169 * emulated process. it has been designed so that it follows the same handle format and has
170 * approximately the same restrictions as the handle manager in the CTR-OS.
171 *
172 * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0).
173 * The slot index is used to index into the arrays in this class to access the data corresponding
174 * to the Handle.
175 *
176 * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter
177 * is kept and incremented every time a Handle is created. This is the Handle's "generation". The
178 * value of the counter is stored into the Handle as well as in the handle table (in the
179 * "generations" array). When looking up a handle, the Handle's generation must match with the
180 * value stored on the class, otherwise the Handle is considered invalid.
181 *
182 * To find free slots when allocating a Handle without needing to scan the entire object array, the
183 * generations field of unallocated slots is re-purposed as a linked list of indices to free slots.
184 * When a Handle is created, an index is popped off the list and used for the new Handle. When it
185 * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is
186 * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been
187 * verified and isn't likely to cause any problems.
188 */ 117 */
189class HandleTable final : NonCopyable { 118template <typename T>
190public: 119inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) {
191 HandleTable(); 120 if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
192 121 return boost::static_pointer_cast<T>(std::move(object));
193 /**
194 * Allocates a handle for the given object.
195 * @return The created Handle or one of the following errors:
196 * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
197 */
198 ResultVal<Handle> Create(SharedPtr<Object> obj);
199
200 /**
201 * Returns a new handle that points to the same object as the passed in handle.
202 * @return The duplicated Handle or one of the following errors:
203 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
204 * - Any errors returned by `Create()`.
205 */
206 ResultVal<Handle> Duplicate(Handle handle);
207
208 /**
209 * Closes a handle, removing it from the table and decreasing the object's ref-count.
210 * @return `RESULT_SUCCESS` or one of the following errors:
211 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
212 */
213 ResultCode Close(Handle handle);
214
215 /// Checks if a handle is valid and points to an existing object.
216 bool IsValid(Handle handle) const;
217
218 /**
219 * Looks up a handle.
220 * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
221 */
222 SharedPtr<Object> GetGeneric(Handle handle) const;
223
224 /**
225 * Looks up a handle while verifying its type.
226 * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
227 * type differs from the handle type `T::HANDLE_TYPE`.
228 */
229 template <class T>
230 SharedPtr<T> Get(Handle handle) const {
231 SharedPtr<Object> object = GetGeneric(handle);
232 if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
233 return boost::static_pointer_cast<T>(std::move(object));
234 }
235 return nullptr;
236 }
237
238 /**
239 * Looks up a handle while verifying that it is an object that a thread can wait on
240 * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or it is
241 * not a waitable object.
242 */
243 SharedPtr<WaitObject> GetWaitObject(Handle handle) const {
244 SharedPtr<Object> object = GetGeneric(handle);
245 if (object != nullptr && object->IsWaitable()) {
246 return boost::static_pointer_cast<WaitObject>(std::move(object));
247 }
248 return nullptr;
249 }
250
251 /// Closes all handles held in this table.
252 void Clear();
253
254private:
255 /**
256 * This is the maximum limit of handles allowed per process in CTR-OS. It can be further
257 * reduced by ExHeader values, but this is not emulated here.
258 */
259 static const size_t MAX_COUNT = 4096;
260
261 static u16 GetSlot(Handle handle) {
262 return handle >> 15;
263 }
264 static u16 GetGeneration(Handle handle) {
265 return handle & 0x7FFF;
266 } 122 }
267 123 return nullptr;
268 /// Stores the Object referenced by the handle or null if the slot is empty. 124}
269 std::array<SharedPtr<Object>, MAX_COUNT> objects;
270
271 /**
272 * The value of `next_generation` when the handle was created, used to check for validity. For
273 * empty slots, contains the index of the next free slot in the list.
274 */
275 std::array<u16, MAX_COUNT> generations;
276
277 /**
278 * Global counter of the number of created handles. Stored in `generations` when a handle is
279 * created, and wraps around to 1 when it hits 0x8000.
280 */
281 u16 next_generation;
282
283 /// Head of the free slots linked list.
284 u16 next_free_slot;
285};
286
287extern HandleTable g_handle_table;
288 125
289/// Initialize the kernel with the specified system mode. 126/// Initialize the kernel with the specified system mode.
290void Init(u32 system_mode); 127void Init(u32 system_mode);
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 8250a90b5..804f23b1c 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
5#include <cinttypes> 6#include <cinttypes>
6#include <map> 7#include <map>
7#include <memory> 8#include <memory>
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index c57adf400..bacacd690 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -7,6 +7,7 @@
7#include <string> 7#include <string>
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/wait_object.h"
10 11
11namespace Kernel { 12namespace Kernel {
12 13
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 3f51bc5de..a8f10a3ee 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> 5#include <cstring>
6#include "common/assert.h"
6#include "common/logging/log.h" 7#include "common/logging/log.h"
7#include "core/hle/kernel/resource_limit.h" 8#include "core/hle/kernel/resource_limit.h"
8 9
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index cde94f7cc..7b0cacf2e 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -8,6 +8,8 @@
8#include <string> 8#include <string>
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/wait_object.h"
12#include "core/hle/result.h"
11 13
12namespace Kernel { 14namespace Kernel {
13 15
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 6f8bdb6a9..2a24d8412 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -9,6 +9,7 @@
9#include <tuple> 9#include <tuple>
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/wait_object.h"
12 13
13namespace Service { 14namespace Service {
14class SessionRequestHandler; 15class SessionRequestHandler;
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index c907d487c..f1b76d8aa 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -10,7 +10,7 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/session.h" 12#include "core/hle/kernel/session.h"
13#include "core/hle/kernel/thread.h" 13#include "core/hle/kernel/wait_object.h"
14#include "core/hle/result.h" 14#include "core/hle/result.h"
15#include "core/hle/service/service.h" 15#include "core/hle/service/service.h"
16#include "core/memory.h" 16#include "core/memory.h"
@@ -20,6 +20,7 @@ namespace Kernel {
20class ClientSession; 20class ClientSession;
21class ClientPort; 21class ClientPort;
22class ServerSession; 22class ServerSession;
23class Thread;
23 24
24/** 25/**
25 * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS 26 * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 519ff51a8..75ce626f8 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -15,6 +15,7 @@
15#include "core/core.h" 15#include "core/core.h"
16#include "core/core_timing.h" 16#include "core/core_timing.h"
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/kernel.h" 19#include "core/hle/kernel/kernel.h"
19#include "core/hle/kernel/memory.h" 20#include "core/hle/kernel/memory.h"
20#include "core/hle/kernel/mutex.h" 21#include "core/hle/kernel/mutex.h"
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 7b5169cfc..6a3566f15 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -12,6 +12,7 @@
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/hle/kernel/kernel.h" 14#include "core/hle/kernel/kernel.h"
15#include "core/hle/kernel/wait_object.h"
15#include "core/hle/result.h" 16#include "core/hle/result.h"
16 17
17enum ThreadPriority : s32 { 18enum ThreadPriority : s32 {
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index a00c75679..6f2cf3b02 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -6,6 +6,7 @@
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/core_timing.h" 8#include "core/core_timing.h"
9#include "core/hle/kernel/handle_table.h"
9#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
11#include "core/hle/kernel/timer.h" 12#include "core/hle/kernel/timer.h"
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index b0f818933..82552372d 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -6,6 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/wait_object.h"
9 10
10namespace Kernel { 11namespace Kernel {
11 12
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
new file mode 100644
index 000000000..f245eda6c
--- /dev/null
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -0,0 +1,99 @@
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/config_mem.h"
9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/memory.h"
12#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/resource_limit.h"
14#include "core/hle/kernel/thread.h"
15#include "core/hle/kernel/timer.h"
16#include "core/hle/shared_page.h"
17
18namespace Kernel {
19
20void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
21 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
22 if (itr == waiting_threads.end())
23 waiting_threads.push_back(std::move(thread));
24}
25
26void WaitObject::RemoveWaitingThread(Thread* thread) {
27 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
28 // If a thread passed multiple handles to the same object,
29 // the kernel might attempt to remove the thread from the object's
30 // waiting threads list multiple times.
31 if (itr != waiting_threads.end())
32 waiting_threads.erase(itr);
33}
34
35SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
36 Thread* candidate = nullptr;
37 s32 candidate_priority = THREADPRIO_LOWEST + 1;
38
39 for (const auto& thread : waiting_threads) {
40 // The list of waiting threads must not contain threads that are not waiting to be awakened.
41 ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
42 thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
43 "Inconsistent thread statuses in waiting_threads");
44
45 if (thread->current_priority >= candidate_priority)
46 continue;
47
48 if (ShouldWait(thread.get()))
49 continue;
50
51 // A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or
52 // in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready.
53 bool ready_to_run = true;
54 if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) {
55 ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
56 [&thread](const SharedPtr<WaitObject>& object) {
57 return object->ShouldWait(thread.get());
58 });
59 }
60
61 if (ready_to_run) {
62 candidate = thread.get();
63 candidate_priority = thread->current_priority;
64 }
65 }
66
67 return candidate;
68}
69
70void WaitObject::WakeupAllWaitingThreads() {
71 while (auto thread = GetHighestPriorityReadyThread()) {
72 if (!thread->IsSleepingOnWaitAll()) {
73 Acquire(thread.get());
74 // Set the output index of the WaitSynchronizationN call to the index of this object.
75 if (thread->wait_set_output) {
76 thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(this));
77 thread->wait_set_output = false;
78 }
79 } else {
80 for (auto& object : thread->wait_objects) {
81 object->Acquire(thread.get());
82 }
83 // Note: This case doesn't update the output index of WaitSynchronizationN.
84 }
85
86 for (auto& object : thread->wait_objects)
87 object->RemoveWaitingThread(thread.get());
88 thread->wait_objects.clear();
89
90 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
91 thread->ResumeFromWait();
92 }
93}
94
95const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {
96 return waiting_threads;
97}
98
99} // namespace Kernel
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
new file mode 100644
index 000000000..861578186
--- /dev/null
+++ b/src/core/hle/kernel/wait_object.h
@@ -0,0 +1,67 @@
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 <vector>
8#include <boost/smart_ptr/intrusive_ptr.hpp>
9#include "common/common_types.h"
10#include "core/hle/kernel/kernel.h"
11
12namespace Kernel {
13
14class Thread;
15
16/// Class that represents a Kernel object that a thread can be waiting on
17class WaitObject : public Object {
18public:
19 /**
20 * Check if the specified thread should wait until the object is available
21 * @param thread The thread about which we're deciding.
22 * @return True if the current thread should wait due to this object being unavailable
23 */
24 virtual bool ShouldWait(Thread* thread) const = 0;
25
26 /// Acquire/lock the object for the specified thread if it is available
27 virtual void Acquire(Thread* thread) = 0;
28
29 /**
30 * Add a thread to wait on this object
31 * @param thread Pointer to thread to add
32 */
33 virtual void AddWaitingThread(SharedPtr<Thread> thread);
34
35 /**
36 * Removes a thread from waiting on this object (e.g. if it was resumed already)
37 * @param thread Pointer to thread to remove
38 */
39 virtual void RemoveWaitingThread(Thread* thread);
40
41 /**
42 * Wake up all threads waiting on this object that can be awoken, in priority order,
43 * and set the synchronization result and output of the thread.
44 */
45 virtual void WakeupAllWaitingThreads();
46
47 /// Obtains the highest priority thread that is ready to run from this object's waiting list.
48 SharedPtr<Thread> GetHighestPriorityReadyThread();
49
50 /// Get a const reference to the waiting threads list for debug use
51 const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
52
53private:
54 /// Threads waiting for this object to become available
55 std::vector<SharedPtr<Thread>> waiting_threads;
56};
57
58// Specialization of DynamicObjectCast for WaitObjects
59template <>
60inline SharedPtr<WaitObject> DynamicObjectCast<WaitObject>(SharedPtr<Object> object) {
61 if (object != nullptr && object->IsWaitable()) {
62 return boost::static_pointer_cast<WaitObject>(std::move(object));
63 }
64 return nullptr;
65}
66
67} // namespace Kernel
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index e63b61450..ee80926d2 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -4,6 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <vector>
8#include "common/common_funcs.h"
7#include "common/common_types.h" 9#include "common/common_types.h"
8#include "common/swap.h" 10#include "common/swap.h"
9#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index e6a5f1417..ffabc24a4 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -12,7 +12,6 @@
12#include "core/hle/ipc.h" 12#include "core/hle/ipc.h"
13#include "core/hle/ipc_helpers.h" 13#include "core/hle/ipc_helpers.h"
14#include "core/hle/kernel/client_port.h" 14#include "core/hle/kernel/client_port.h"
15#include "core/hle/kernel/thread.h"
16#include "core/hle/result.h" 15#include "core/hle/result.h"
17#include "core/memory.h" 16#include "core/memory.h"
18 17
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 30230d65a..e68b9f16a 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
5#include <cinttypes> 6#include <cinttypes>
6#include <map> 7#include <map>
7#include "common/logging/log.h" 8#include "common/logging/log.h"
@@ -16,6 +17,7 @@
16#include "core/hle/kernel/client_session.h" 17#include "core/hle/kernel/client_session.h"
17#include "core/hle/kernel/errors.h" 18#include "core/hle/kernel/errors.h"
18#include "core/hle/kernel/event.h" 19#include "core/hle/kernel/event.h"
20#include "core/hle/kernel/handle_table.h"
19#include "core/hle/kernel/memory.h" 21#include "core/hle/kernel/memory.h"
20#include "core/hle/kernel/mutex.h" 22#include "core/hle/kernel/mutex.h"
21#include "core/hle/kernel/process.h" 23#include "core/hle/kernel/process.h"
@@ -27,6 +29,7 @@
27#include "core/hle/kernel/thread.h" 29#include "core/hle/kernel/thread.h"
28#include "core/hle/kernel/timer.h" 30#include "core/hle/kernel/timer.h"
29#include "core/hle/kernel/vm_manager.h" 31#include "core/hle/kernel/vm_manager.h"
32#include "core/hle/kernel/wait_object.h"
30#include "core/hle/result.h" 33#include "core/hle/result.h"
31#include "core/hle/service/service.h" 34#include "core/hle/service/service.h"
32 35
@@ -244,7 +247,7 @@ static ResultCode CloseHandle(Kernel::Handle handle) {
244 247
245/// Wait for a handle to synchronize, timeout after the specified nanoseconds 248/// Wait for a handle to synchronize, timeout after the specified nanoseconds
246static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) { 249static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) {
247 auto object = Kernel::g_handle_table.GetWaitObject(handle); 250 auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handle);
248 Kernel::Thread* thread = Kernel::GetCurrentThread(); 251 Kernel::Thread* thread = Kernel::GetCurrentThread();
249 252
250 if (object == nullptr) 253 if (object == nullptr)
@@ -299,7 +302,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
299 std::vector<ObjectPtr> objects(handle_count); 302 std::vector<ObjectPtr> objects(handle_count);
300 303
301 for (int i = 0; i < handle_count; ++i) { 304 for (int i = 0; i < handle_count; ++i) {
302 auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); 305 auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handles[i]);
303 if (object == nullptr) 306 if (object == nullptr)
304 return ERR_INVALID_HANDLE; 307 return ERR_INVALID_HANDLE;
305 objects[i] = object; 308 objects[i] = object;