diff options
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index cc70cbca7..b01779f2e 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -11,10 +11,11 @@ | |||
| 11 | #include "common/thread_queue_list.h" | 11 | #include "common/thread_queue_list.h" |
| 12 | 12 | ||
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/mem_map.h" | ||
| 15 | #include "core/hle/hle.h" | 14 | #include "core/hle/hle.h" |
| 16 | #include "core/hle/kernel/kernel.h" | 15 | #include "core/hle/kernel/kernel.h" |
| 17 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 17 | #include "core/hle/result.h" | ||
| 18 | #include "core/mem_map.h" | ||
| 18 | 19 | ||
| 19 | namespace Kernel { | 20 | namespace Kernel { |
| 20 | 21 | ||
| @@ -38,16 +39,17 @@ public: | |||
| 38 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | 39 | * @param wait Boolean wait set if current thread should wait as a result of sync operation |
| 39 | * @return Result of operation, 0 on success, otherwise error code | 40 | * @return Result of operation, 0 on success, otherwise error code |
| 40 | */ | 41 | */ |
| 41 | Result WaitSynchronization(bool* wait) override { | 42 | ResultVal<bool> WaitSynchronization() override { |
| 42 | if (status != THREADSTATUS_DORMANT) { | 43 | if (status != THREADSTATUS_DORMANT) { |
| 43 | Handle thread = GetCurrentThreadHandle(); | 44 | Handle thread = GetCurrentThreadHandle(); |
| 44 | if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { | 45 | if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { |
| 45 | waiting_threads.push_back(thread); | 46 | waiting_threads.push_back(thread); |
| 46 | } | 47 | } |
| 47 | WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); | 48 | WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); |
| 48 | *wait = true; | 49 | return MakeResult<bool>(true); |
| 50 | } else { | ||
| 51 | return MakeResult<bool>(false); | ||
| 49 | } | 52 | } |
| 50 | return 0; | ||
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | ThreadContext context; | 55 | ThreadContext context; |
| @@ -144,9 +146,9 @@ void ChangeReadyState(Thread* t, bool ready) { | |||
| 144 | } | 146 | } |
| 145 | 147 | ||
| 146 | /// Verify that a thread has not been released from waiting | 148 | /// Verify that a thread has not been released from waiting |
| 147 | inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) { | 149 | inline bool VerifyWait(Handle handle, WaitType type, Handle wait_handle) { |
| 148 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 150 | Thread* thread = g_object_pool.Get<Thread>(handle); |
| 149 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 151 | _dbg_assert_(KERNEL, thread != nullptr); |
| 150 | 152 | ||
| 151 | if (type != thread->wait_type || wait_handle != thread->wait_handle) | 153 | if (type != thread->wait_type || wait_handle != thread->wait_handle) |
| 152 | return false; | 154 | return false; |
| @@ -155,9 +157,9 @@ inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) | |||
| 155 | } | 157 | } |
| 156 | 158 | ||
| 157 | /// Stops the current thread | 159 | /// Stops the current thread |
| 158 | void StopThread(Handle handle, const char* reason) { | 160 | ResultCode StopThread(Handle handle, const char* reason) { |
| 159 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 161 | Thread* thread = g_object_pool.Get<Thread>(handle); |
| 160 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 162 | if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 161 | 163 | ||
| 162 | ChangeReadyState(thread, false); | 164 | ChangeReadyState(thread, false); |
| 163 | thread->status = THREADSTATUS_DORMANT; | 165 | thread->status = THREADSTATUS_DORMANT; |
| @@ -172,6 +174,8 @@ void StopThread(Handle handle, const char* reason) { | |||
| 172 | // Stopped threads are never waiting. | 174 | // Stopped threads are never waiting. |
| 173 | thread->wait_type = WAITTYPE_NONE; | 175 | thread->wait_type = WAITTYPE_NONE; |
| 174 | thread->wait_handle = 0; | 176 | thread->wait_handle = 0; |
| 177 | |||
| 178 | return RESULT_SUCCESS; | ||
| 175 | } | 179 | } |
| 176 | 180 | ||
| 177 | /// Changes a threads state | 181 | /// Changes a threads state |
| @@ -201,7 +205,9 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { | |||
| 201 | if (!VerifyWait(handle, WAITTYPE_ARB, arbiter)) | 205 | if (!VerifyWait(handle, WAITTYPE_ARB, arbiter)) |
| 202 | continue; | 206 | continue; |
| 203 | 207 | ||
| 204 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 208 | Thread* thread = g_object_pool.Get<Thread>(handle); |
| 209 | if (thread == nullptr) | ||
| 210 | continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. | ||
| 205 | if(thread->current_priority <= priority) { | 211 | if(thread->current_priority <= priority) { |
| 206 | highest_priority_thread = handle; | 212 | highest_priority_thread = handle; |
| 207 | priority = thread->current_priority; | 213 | priority = thread->current_priority; |
| @@ -272,7 +278,7 @@ Thread* NextThread() { | |||
| 272 | if (next == 0) { | 278 | if (next == 0) { |
| 273 | return nullptr; | 279 | return nullptr; |
| 274 | } | 280 | } |
| 275 | return Kernel::g_object_pool.GetFast<Thread>(next); | 281 | return Kernel::g_object_pool.Get<Thread>(next); |
| 276 | } | 282 | } |
| 277 | 283 | ||
| 278 | /** | 284 | /** |
| @@ -289,8 +295,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { | |||
| 289 | 295 | ||
| 290 | /// Resumes a thread from waiting by marking it as "ready" | 296 | /// Resumes a thread from waiting by marking it as "ready" |
| 291 | void ResumeThreadFromWait(Handle handle) { | 297 | void ResumeThreadFromWait(Handle handle) { |
| 292 | u32 error; | 298 | Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); |
| 293 | Thread* thread = Kernel::g_object_pool.Get<Thread>(handle, error); | ||
| 294 | if (thread) { | 299 | if (thread) { |
| 295 | thread->status &= ~THREADSTATUS_WAIT; | 300 | thread->status &= ~THREADSTATUS_WAIT; |
| 296 | if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | 301 | if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { |
| @@ -378,19 +383,23 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 | |||
| 378 | } | 383 | } |
| 379 | 384 | ||
| 380 | /// Get the priority of the thread specified by handle | 385 | /// Get the priority of the thread specified by handle |
| 381 | u32 GetThreadPriority(const Handle handle) { | 386 | ResultVal<u32> GetThreadPriority(const Handle handle) { |
| 382 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 387 | Thread* thread = g_object_pool.Get<Thread>(handle); |
| 383 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 388 | if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 384 | return thread->current_priority; | 389 | |
| 390 | return MakeResult<u32>(thread->current_priority); | ||
| 385 | } | 391 | } |
| 386 | 392 | ||
| 387 | /// Set the priority of the thread specified by handle | 393 | /// Set the priority of the thread specified by handle |
| 388 | Result SetThreadPriority(Handle handle, s32 priority) { | 394 | ResultCode SetThreadPriority(Handle handle, s32 priority) { |
| 389 | Thread* thread = nullptr; | 395 | Thread* thread = nullptr; |
| 390 | if (!handle) { | 396 | if (!handle) { |
| 391 | thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? | 397 | thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? |
| 392 | } else { | 398 | } else { |
| 393 | thread = g_object_pool.GetFast<Thread>(handle); | 399 | thread = g_object_pool.Get<Thread>(handle); |
| 400 | if (thread == nullptr) { | ||
| 401 | return InvalidHandle(ErrorModule::Kernel); | ||
| 402 | } | ||
| 394 | } | 403 | } |
| 395 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 404 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); |
| 396 | 405 | ||
| @@ -417,7 +426,7 @@ Result SetThreadPriority(Handle handle, s32 priority) { | |||
| 417 | thread_ready_queue.push_back(thread->current_priority, handle); | 426 | thread_ready_queue.push_back(thread->current_priority, handle); |
| 418 | } | 427 | } |
| 419 | 428 | ||
| 420 | return 0; | 429 | return RESULT_SUCCESS; |
| 421 | } | 430 | } |
| 422 | 431 | ||
| 423 | /// Sets up the primary application thread | 432 | /// Sets up the primary application thread |