diff options
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 78 |
1 files changed, 39 insertions, 39 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index cc70cbca7..f3f54a4e9 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 | ||
| @@ -33,21 +34,17 @@ public: | |||
| 33 | inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } | 34 | inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } |
| 34 | inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } | 35 | inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } |
| 35 | 36 | ||
| 36 | /** | 37 | ResultVal<bool> WaitSynchronization() override { |
| 37 | * Wait for kernel object to synchronize | 38 | const bool wait = status != THREADSTATUS_DORMANT; |
| 38 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | 39 | if (wait) { |
| 39 | * @return Result of operation, 0 on success, otherwise error code | ||
| 40 | */ | ||
| 41 | Result WaitSynchronization(bool* wait) override { | ||
| 42 | if (status != THREADSTATUS_DORMANT) { | ||
| 43 | Handle thread = GetCurrentThreadHandle(); | 40 | Handle thread = GetCurrentThreadHandle(); |
| 44 | if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { | 41 | if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { |
| 45 | waiting_threads.push_back(thread); | 42 | waiting_threads.push_back(thread); |
| 46 | } | 43 | } |
| 47 | WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); | 44 | WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); |
| 48 | *wait = true; | ||
| 49 | } | 45 | } |
| 50 | return 0; | 46 | |
| 47 | return MakeResult<bool>(wait); | ||
| 51 | } | 48 | } |
| 52 | 49 | ||
| 53 | ThreadContext context; | 50 | ThreadContext context; |
| @@ -144,27 +141,22 @@ void ChangeReadyState(Thread* t, bool ready) { | |||
| 144 | } | 141 | } |
| 145 | 142 | ||
| 146 | /// Verify that a thread has not been released from waiting | 143 | /// Verify that a thread has not been released from waiting |
| 147 | inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) { | 144 | inline bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) { |
| 148 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 145 | _dbg_assert_(KERNEL, thread != nullptr); |
| 149 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 146 | return type == thread->wait_type && wait_handle == thread->wait_handle; |
| 150 | |||
| 151 | if (type != thread->wait_type || wait_handle != thread->wait_handle) | ||
| 152 | return false; | ||
| 153 | |||
| 154 | return true; | ||
| 155 | } | 147 | } |
| 156 | 148 | ||
| 157 | /// Stops the current thread | 149 | /// Stops the current thread |
| 158 | void StopThread(Handle handle, const char* reason) { | 150 | ResultCode StopThread(Handle handle, const char* reason) { |
| 159 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 151 | Thread* thread = g_object_pool.Get<Thread>(handle); |
| 160 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 152 | if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 161 | 153 | ||
| 162 | ChangeReadyState(thread, false); | 154 | ChangeReadyState(thread, false); |
| 163 | thread->status = THREADSTATUS_DORMANT; | 155 | thread->status = THREADSTATUS_DORMANT; |
| 164 | for (size_t i = 0; i < thread->waiting_threads.size(); ++i) { | 156 | for (Handle waiting_handle : thread->waiting_threads) { |
| 165 | const Handle waiting_thread = thread->waiting_threads[i]; | 157 | Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle); |
| 166 | if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { | 158 | if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { |
| 167 | ResumeThreadFromWait(waiting_thread); | 159 | ResumeThreadFromWait(waiting_handle); |
| 168 | } | 160 | } |
| 169 | } | 161 | } |
| 170 | thread->waiting_threads.clear(); | 162 | thread->waiting_threads.clear(); |
| @@ -172,6 +164,8 @@ void StopThread(Handle handle, const char* reason) { | |||
| 172 | // Stopped threads are never waiting. | 164 | // Stopped threads are never waiting. |
| 173 | thread->wait_type = WAITTYPE_NONE; | 165 | thread->wait_type = WAITTYPE_NONE; |
| 174 | thread->wait_handle = 0; | 166 | thread->wait_handle = 0; |
| 167 | |||
| 168 | return RESULT_SUCCESS; | ||
| 175 | } | 169 | } |
| 176 | 170 | ||
| 177 | /// Changes a threads state | 171 | /// Changes a threads state |
| @@ -195,13 +189,15 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { | |||
| 195 | s32 priority = THREADPRIO_LOWEST; | 189 | s32 priority = THREADPRIO_LOWEST; |
| 196 | 190 | ||
| 197 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 191 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 198 | for (const auto& handle : thread_queue) { | 192 | for (Handle handle : thread_queue) { |
| 193 | Thread* thread = g_object_pool.Get<Thread>(handle); | ||
| 199 | 194 | ||
| 200 | // TODO(bunnei): Verify arbiter address... | 195 | // TODO(bunnei): Verify arbiter address... |
| 201 | if (!VerifyWait(handle, WAITTYPE_ARB, arbiter)) | 196 | if (!VerifyWait(thread, WAITTYPE_ARB, arbiter)) |
| 202 | continue; | 197 | continue; |
| 203 | 198 | ||
| 204 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 199 | if (thread == nullptr) |
| 200 | continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. | ||
| 205 | if(thread->current_priority <= priority) { | 201 | if(thread->current_priority <= priority) { |
| 206 | highest_priority_thread = handle; | 202 | highest_priority_thread = handle; |
| 207 | priority = thread->current_priority; | 203 | priority = thread->current_priority; |
| @@ -218,10 +214,11 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { | |||
| 218 | void ArbitrateAllThreads(u32 arbiter, u32 address) { | 214 | void ArbitrateAllThreads(u32 arbiter, u32 address) { |
| 219 | 215 | ||
| 220 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 216 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 221 | for (const auto& handle : thread_queue) { | 217 | for (Handle handle : thread_queue) { |
| 218 | Thread* thread = g_object_pool.Get<Thread>(handle); | ||
| 222 | 219 | ||
| 223 | // TODO(bunnei): Verify arbiter address... | 220 | // TODO(bunnei): Verify arbiter address... |
| 224 | if (VerifyWait(handle, WAITTYPE_ARB, arbiter)) | 221 | if (VerifyWait(thread, WAITTYPE_ARB, arbiter)) |
| 225 | ResumeThreadFromWait(handle); | 222 | ResumeThreadFromWait(handle); |
| 226 | } | 223 | } |
| 227 | } | 224 | } |
| @@ -272,7 +269,7 @@ Thread* NextThread() { | |||
| 272 | if (next == 0) { | 269 | if (next == 0) { |
| 273 | return nullptr; | 270 | return nullptr; |
| 274 | } | 271 | } |
| 275 | return Kernel::g_object_pool.GetFast<Thread>(next); | 272 | return Kernel::g_object_pool.Get<Thread>(next); |
| 276 | } | 273 | } |
| 277 | 274 | ||
| 278 | /** | 275 | /** |
| @@ -289,8 +286,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { | |||
| 289 | 286 | ||
| 290 | /// Resumes a thread from waiting by marking it as "ready" | 287 | /// Resumes a thread from waiting by marking it as "ready" |
| 291 | void ResumeThreadFromWait(Handle handle) { | 288 | void ResumeThreadFromWait(Handle handle) { |
| 292 | u32 error; | 289 | Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); |
| 293 | Thread* thread = Kernel::g_object_pool.Get<Thread>(handle, error); | ||
| 294 | if (thread) { | 290 | if (thread) { |
| 295 | thread->status &= ~THREADSTATUS_WAIT; | 291 | thread->status &= ~THREADSTATUS_WAIT; |
| 296 | if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | 292 | if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { |
| @@ -378,19 +374,23 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 | |||
| 378 | } | 374 | } |
| 379 | 375 | ||
| 380 | /// Get the priority of the thread specified by handle | 376 | /// Get the priority of the thread specified by handle |
| 381 | u32 GetThreadPriority(const Handle handle) { | 377 | ResultVal<u32> GetThreadPriority(const Handle handle) { |
| 382 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 378 | Thread* thread = g_object_pool.Get<Thread>(handle); |
| 383 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 379 | if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 384 | return thread->current_priority; | 380 | |
| 381 | return MakeResult<u32>(thread->current_priority); | ||
| 385 | } | 382 | } |
| 386 | 383 | ||
| 387 | /// Set the priority of the thread specified by handle | 384 | /// Set the priority of the thread specified by handle |
| 388 | Result SetThreadPriority(Handle handle, s32 priority) { | 385 | ResultCode SetThreadPriority(Handle handle, s32 priority) { |
| 389 | Thread* thread = nullptr; | 386 | Thread* thread = nullptr; |
| 390 | if (!handle) { | 387 | if (!handle) { |
| 391 | thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? | 388 | thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? |
| 392 | } else { | 389 | } else { |
| 393 | thread = g_object_pool.GetFast<Thread>(handle); | 390 | thread = g_object_pool.Get<Thread>(handle); |
| 391 | if (thread == nullptr) { | ||
| 392 | return InvalidHandle(ErrorModule::Kernel); | ||
| 393 | } | ||
| 394 | } | 394 | } |
| 395 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 395 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); |
| 396 | 396 | ||
| @@ -417,7 +417,7 @@ Result SetThreadPriority(Handle handle, s32 priority) { | |||
| 417 | thread_ready_queue.push_back(thread->current_priority, handle); | 417 | thread_ready_queue.push_back(thread->current_priority, handle); |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | return 0; | 420 | return RESULT_SUCCESS; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | /// Sets up the primary application thread | 423 | /// Sets up the primary application thread |