summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2017-05-31 19:46:15 -0400
committerGravatar GitHub2017-05-31 19:46:15 -0400
commitaf1ff4d3ce4a97e6f98e9b8b55da017b77cfcb0e (patch)
tree690988495a40708deae96f057db79d68704acb02 /src/core/hle/kernel/kernel.cpp
parentMerge pull request #2721 from wwylele/texture-cube (diff)
parentKernel: Move HandleTable to a separate file (diff)
downloadyuzu-af1ff4d3ce4a97e6f98e9b8b55da017b77cfcb0e.tar.gz
yuzu-af1ff4d3ce4a97e6f98e9b8b55da017b77cfcb0e.tar.xz
yuzu-af1ff4d3ce4a97e6f98e9b8b55da017b77cfcb0e.zip
Merge pull request #2739 from yuriks/kernel-reorg
Split-up kernel.h
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp164
1 files changed, 1 insertions, 163 deletions
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) {