diff options
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 65 |
1 files changed, 19 insertions, 46 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 62b85f56a..601e0eb20 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -22,14 +22,8 @@ | |||
| 22 | 22 | ||
| 23 | namespace Kernel { | 23 | namespace Kernel { |
| 24 | 24 | ||
| 25 | ResultVal<bool> Thread::Wait(bool wait_thread) { | 25 | ResultVal<bool> Thread::Wait() { |
| 26 | const bool wait = status != THREADSTATUS_DORMANT; | 26 | return MakeResult<bool>(status != THREADSTATUS_DORMANT); |
| 27 | if (wait && wait_thread) { | ||
| 28 | AddWaitingThread(GetCurrentThread()); | ||
| 29 | WaitCurrentThread_WaitSynchronization(WAITTYPE_THREADEND, this); | ||
| 30 | } | ||
| 31 | |||
| 32 | return MakeResult<bool>(wait); | ||
| 33 | } | 27 | } |
| 34 | 28 | ||
| 35 | ResultVal<bool> Thread::Acquire() { | 29 | ResultVal<bool> Thread::Acquire() { |
| @@ -68,7 +62,7 @@ static void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { | |||
| 68 | if (t->current_priority < lowest_priority) { | 62 | if (t->current_priority < lowest_priority) { |
| 69 | t->current_priority = t->initial_priority; | 63 | t->current_priority = t->initial_priority; |
| 70 | } | 64 | } |
| 71 | t->wait_type = WAITTYPE_NONE; | 65 | |
| 72 | t->wait_objects.clear(); | 66 | t->wait_objects.clear(); |
| 73 | t->wait_address = 0; | 67 | t->wait_address = 0; |
| 74 | } | 68 | } |
| @@ -89,23 +83,18 @@ static void ChangeReadyState(Thread* t, bool ready) { | |||
| 89 | } | 83 | } |
| 90 | } | 84 | } |
| 91 | 85 | ||
| 92 | /// Check if a thread is blocking on a specified wait type | 86 | /// Check if a thread is blocking on a the specified object |
| 93 | static bool CheckWaitType(const Thread* thread, WaitType type) { | 87 | static bool CheckWaitType(const Thread* thread, Object* wait_object) { |
| 94 | return (type == thread->wait_type) && (thread->IsWaiting()); | ||
| 95 | } | ||
| 96 | |||
| 97 | /// Check if a thread is blocking on a specified wait type with a specified handle | ||
| 98 | static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object) { | ||
| 99 | for (auto itr = thread->wait_objects.begin(); itr != thread->wait_objects.end(); ++itr) { | 88 | for (auto itr = thread->wait_objects.begin(); itr != thread->wait_objects.end(); ++itr) { |
| 100 | if (*itr == wait_object) | 89 | if (*itr == wait_object) |
| 101 | return CheckWaitType(thread, type); | 90 | return (thread->IsWaiting()); |
| 102 | } | 91 | } |
| 103 | return false; | 92 | return false; |
| 104 | } | 93 | } |
| 105 | 94 | ||
| 106 | /// Check if a thread is blocking on a specified wait type with a specified handle and address | 95 | /// Check if a thread is blocking on a the specified object and an address |
| 107 | static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object, VAddr wait_address) { | 96 | static bool CheckWaitType(const Thread* thread, Object* wait_object, VAddr wait_address) { |
| 108 | return CheckWaitType(thread, type, wait_object) && (wait_address == thread->wait_address); | 97 | return CheckWaitType(thread, wait_object) && (wait_address == thread->wait_address); |
| 109 | } | 98 | } |
| 110 | 99 | ||
| 111 | /// Stops the current thread | 100 | /// Stops the current thread |
| @@ -118,7 +107,6 @@ void Thread::Stop(const char* reason) { | |||
| 118 | ReleaseAllWaitingThreads(); | 107 | ReleaseAllWaitingThreads(); |
| 119 | 108 | ||
| 120 | // Stopped threads are never waiting. | 109 | // Stopped threads are never waiting. |
| 121 | wait_type = WAITTYPE_NONE; | ||
| 122 | wait_objects.clear(); | 110 | wait_objects.clear(); |
| 123 | wait_address = 0; | 111 | wait_address = 0; |
| 124 | } | 112 | } |
| @@ -130,12 +118,6 @@ static void ChangeThreadState(Thread* t, ThreadStatus new_status) { | |||
| 130 | } | 118 | } |
| 131 | ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); | 119 | ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); |
| 132 | t->status = new_status; | 120 | t->status = new_status; |
| 133 | |||
| 134 | if (new_status == THREADSTATUS_WAIT) { | ||
| 135 | if (t->wait_type == WAITTYPE_NONE) { | ||
| 136 | LOG_ERROR(Kernel, "Waittype none not allowed"); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | 121 | } |
| 140 | 122 | ||
| 141 | /// Arbitrate the highest priority thread that is waiting | 123 | /// Arbitrate the highest priority thread that is waiting |
| @@ -145,7 +127,7 @@ Thread* ArbitrateHighestPriorityThread(WaitObject* arbiter, u32 address) { | |||
| 145 | 127 | ||
| 146 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 128 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 147 | for (auto& thread : thread_list) { | 129 | for (auto& thread : thread_list) { |
| 148 | if (!CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address)) | 130 | if (!CheckWaitType(thread.get(), arbiter, address)) |
| 149 | continue; | 131 | continue; |
| 150 | 132 | ||
| 151 | if (thread == nullptr) | 133 | if (thread == nullptr) |
| @@ -170,7 +152,7 @@ void ArbitrateAllThreads(WaitObject* arbiter, u32 address) { | |||
| 170 | 152 | ||
| 171 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 153 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 172 | for (auto& thread : thread_list) { | 154 | for (auto& thread : thread_list) { |
| 173 | if (CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address)) | 155 | if (CheckWaitType(thread.get(), arbiter, address)) |
| 174 | thread->ReleaseFromWait(arbiter); | 156 | thread->ReleaseFromWait(arbiter); |
| 175 | } | 157 | } |
| 176 | } | 158 | } |
| @@ -178,9 +160,6 @@ void ArbitrateAllThreads(WaitObject* arbiter, u32 address) { | |||
| 178 | /// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields) | 160 | /// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields) |
| 179 | static void CallThread(Thread* t) { | 161 | static void CallThread(Thread* t) { |
| 180 | // Stop waiting | 162 | // Stop waiting |
| 181 | if (t->wait_type != WAITTYPE_NONE) { | ||
| 182 | t->wait_type = WAITTYPE_NONE; | ||
| 183 | } | ||
| 184 | ChangeThreadState(t, THREADSTATUS_READY); | 163 | ChangeThreadState(t, THREADSTATUS_READY); |
| 185 | } | 164 | } |
| 186 | 165 | ||
| @@ -201,7 +180,6 @@ static void SwitchContext(Thread* t) { | |||
| 201 | current_thread = t; | 180 | current_thread = t; |
| 202 | ChangeReadyState(t, false); | 181 | ChangeReadyState(t, false); |
| 203 | t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; | 182 | t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; |
| 204 | t->wait_type = WAITTYPE_NONE; | ||
| 205 | Core::g_app_core->LoadContext(t->context); | 183 | Core::g_app_core->LoadContext(t->context); |
| 206 | } else { | 184 | } else { |
| 207 | current_thread = nullptr; | 185 | current_thread = nullptr; |
| @@ -224,23 +202,20 @@ static Thread* NextThread() { | |||
| 224 | return next; | 202 | return next; |
| 225 | } | 203 | } |
| 226 | 204 | ||
| 227 | void WaitCurrentThread(WaitType wait_type) { | 205 | void WaitCurrentThread() { |
| 228 | Thread* thread = GetCurrentThread(); | 206 | Thread* thread = GetCurrentThread(); |
| 229 | thread->wait_type = wait_type; | ||
| 230 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 207 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 231 | } | 208 | } |
| 232 | 209 | ||
| 233 | void WaitCurrentThread_WaitSynchronization(WaitType wait_type, WaitObject* wait_object, unsigned index) { | 210 | void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_all) { |
| 234 | Thread* thread = GetCurrentThread(); | 211 | Thread* thread = GetCurrentThread(); |
| 235 | thread->wait_type = wait_type; | 212 | thread->wait_all = wait_all; |
| 236 | |||
| 237 | thread->wait_objects.push_back(wait_object); | 213 | thread->wait_objects.push_back(wait_object); |
| 238 | |||
| 239 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 214 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 240 | } | 215 | } |
| 241 | 216 | ||
| 242 | void WaitCurrentThread_ArbitrateAddress(WaitObject* wait_object, VAddr wait_address) { | 217 | void WaitCurrentThread_ArbitrateAddress(WaitObject* wait_object, VAddr wait_address) { |
| 243 | WaitCurrentThread_WaitSynchronization(WaitType::WAITTYPE_ARB, wait_object, 0); | 218 | WaitCurrentThread_WaitSynchronization(wait_object); |
| 244 | GetCurrentThread()->wait_address = wait_address; | 219 | GetCurrentThread()->wait_address = wait_address; |
| 245 | } | 220 | } |
| 246 | 221 | ||
| @@ -287,7 +262,7 @@ void Thread::ReleaseFromWait(WaitObject* wait_object) { | |||
| 287 | 262 | ||
| 288 | // Iterate through all waiting objects to check availability... | 263 | // Iterate through all waiting objects to check availability... |
| 289 | for (auto itr = wait_objects.begin(); itr != wait_objects.end(); ++itr) { | 264 | for (auto itr = wait_objects.begin(); itr != wait_objects.end(); ++itr) { |
| 290 | auto res = (*itr)->Wait(false); | 265 | auto res = (*itr)->Wait(); |
| 291 | 266 | ||
| 292 | if (*res && res.Succeeded()) | 267 | if (*res && res.Succeeded()) |
| 293 | wait_all_failed = true; | 268 | wait_all_failed = true; |
| @@ -322,9 +297,8 @@ void Thread::ResumeFromWait() { | |||
| 322 | wait_object->RemoveWaitingThread(this); | 297 | wait_object->RemoveWaitingThread(this); |
| 323 | 298 | ||
| 324 | wait_objects.clear(); | 299 | wait_objects.clear(); |
| 325 | |||
| 326 | wait_type = WAITTYPE_NONE; | ||
| 327 | wait_all = false; | 300 | wait_all = false; |
| 301 | |||
| 328 | if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | 302 | if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { |
| 329 | ChangeReadyState(this, true); | 303 | ChangeReadyState(this, true); |
| 330 | } | 304 | } |
| @@ -390,7 +364,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 390 | thread->stack_size = stack_size; | 364 | thread->stack_size = stack_size; |
| 391 | thread->initial_priority = thread->current_priority = priority; | 365 | thread->initial_priority = thread->current_priority = priority; |
| 392 | thread->processor_id = processor_id; | 366 | thread->processor_id = processor_id; |
| 393 | thread->wait_type = WAITTYPE_NONE; | ||
| 394 | thread->wait_all = false; | 367 | thread->wait_all = false; |
| 395 | thread->wait_objects.clear(); | 368 | thread->wait_objects.clear(); |
| 396 | thread->wait_address = 0; | 369 | thread->wait_address = 0; |
| @@ -476,8 +449,8 @@ void Reschedule() { | |||
| 476 | LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); | 449 | LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); |
| 477 | 450 | ||
| 478 | for (auto& thread : thread_list) { | 451 | for (auto& thread : thread_list) { |
| 479 | LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X", | 452 | LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X", thread->GetHandle(), |
| 480 | thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type); | 453 | thread->current_priority, thread->status); |
| 481 | } | 454 | } |
| 482 | } | 455 | } |
| 483 | } | 456 | } |