diff options
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 61 |
1 files changed, 28 insertions, 33 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 6b0bdebb5..62b85f56a 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -22,11 +22,11 @@ | |||
| 22 | 22 | ||
| 23 | namespace Kernel { | 23 | namespace Kernel { |
| 24 | 24 | ||
| 25 | ResultVal<bool> Thread::Wait(unsigned index) { | 25 | ResultVal<bool> Thread::Wait(bool wait_thread) { |
| 26 | const bool wait = status != THREADSTATUS_DORMANT; | 26 | const bool wait = status != THREADSTATUS_DORMANT; |
| 27 | if (wait) { | 27 | if (wait && wait_thread) { |
| 28 | AddWaitingThread(GetCurrentThread()); | 28 | AddWaitingThread(GetCurrentThread()); |
| 29 | WaitCurrentThread_WaitSynchronization(WAITTYPE_THREADEND, this, index); | 29 | WaitCurrentThread_WaitSynchronization(WAITTYPE_THREADEND, this); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | return MakeResult<bool>(wait); | 32 | return MakeResult<bool>(wait); |
| @@ -97,7 +97,7 @@ static bool CheckWaitType(const Thread* thread, WaitType type) { | |||
| 97 | /// Check if a thread is blocking on a specified wait type with a specified handle | 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) { | 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) { | 99 | for (auto itr = thread->wait_objects.begin(); itr != thread->wait_objects.end(); ++itr) { |
| 100 | if (itr->first == wait_object) | 100 | if (*itr == wait_object) |
| 101 | return CheckWaitType(thread, type); | 101 | return CheckWaitType(thread, type); |
| 102 | } | 102 | } |
| 103 | return false; | 103 | return false; |
| @@ -234,16 +234,7 @@ void WaitCurrentThread_WaitSynchronization(WaitType wait_type, WaitObject* wait_ | |||
| 234 | Thread* thread = GetCurrentThread(); | 234 | Thread* thread = GetCurrentThread(); |
| 235 | thread->wait_type = wait_type; | 235 | thread->wait_type = wait_type; |
| 236 | 236 | ||
| 237 | bool insert_wait_object = true; | 237 | thread->wait_objects.push_back(wait_object); |
| 238 | for (auto itr = thread->wait_objects.begin(); itr < thread->wait_objects.end(); ++itr) { | ||
| 239 | if (itr->first == wait_object) { | ||
| 240 | insert_wait_object = false; | ||
| 241 | break; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | if (insert_wait_object) | ||
| 246 | thread->wait_objects.push_back(std::pair<SharedPtr<WaitObject>, unsigned>(wait_object, index)); | ||
| 247 | 238 | ||
| 248 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 239 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 249 | } | 240 | } |
| @@ -288,31 +279,35 @@ void Thread::ReleaseFromWait(WaitObject* wait_object) { | |||
| 288 | return; | 279 | return; |
| 289 | } | 280 | } |
| 290 | 281 | ||
| 291 | // Remove this thread from the wait_object | 282 | // Remove this thread from the waiting object's thread list |
| 292 | wait_object->RemoveWaitingThread(this); | 283 | wait_object->RemoveWaitingThread(this); |
| 293 | 284 | ||
| 294 | // Find the waiting object | 285 | unsigned index = 0; |
| 295 | auto itr = wait_objects.begin(); | 286 | bool wait_all_failed = false; // Will be set to true if any object is unavailable |
| 296 | for (; itr != wait_objects.end(); ++itr) { | ||
| 297 | if (wait_object == itr->first) | ||
| 298 | break; | ||
| 299 | } | ||
| 300 | unsigned index = itr->second; | ||
| 301 | 287 | ||
| 302 | // Remove the wait_object from this thread | 288 | // Iterate through all waiting objects to check availability... |
| 303 | if (itr != wait_objects.end()) | 289 | for (auto itr = wait_objects.begin(); itr != wait_objects.end(); ++itr) { |
| 304 | wait_objects.erase(itr); | 290 | auto res = (*itr)->Wait(false); |
| 305 | 291 | ||
| 306 | // If wait_all=false, resume the thread on a release wait_object from wait | 292 | if (*res && res.Succeeded()) |
| 307 | if (!wait_all) { | 293 | wait_all_failed = true; |
| 308 | SetReturnValue(RESULT_SUCCESS, index); | 294 | |
| 309 | ResumeFromWait(); | 295 | // The output should be the last index of wait_object |
| 310 | } else { | 296 | if (*itr == wait_object) |
| 311 | // Otherwise, wait_all=true, only resume the thread if all wait_object's have been released | 297 | index = itr - wait_objects.begin(); |
| 312 | if (wait_objects.empty()) { | 298 | } |
| 299 | |||
| 300 | // If we are waiting on all objects... | ||
| 301 | if (wait_all) { | ||
| 302 | // Resume the thread only if all are available... | ||
| 303 | if (!wait_all_failed) { | ||
| 313 | SetReturnValue(RESULT_SUCCESS, -1); | 304 | SetReturnValue(RESULT_SUCCESS, -1); |
| 314 | ResumeFromWait(); | 305 | ResumeFromWait(); |
| 315 | } | 306 | } |
| 307 | } else { | ||
| 308 | // Otherwise, resume | ||
| 309 | SetReturnValue(RESULT_SUCCESS, index); | ||
| 310 | ResumeFromWait(); | ||
| 316 | } | 311 | } |
| 317 | } | 312 | } |
| 318 | 313 | ||
| @@ -324,7 +319,7 @@ void Thread::ResumeFromWait() { | |||
| 324 | 319 | ||
| 325 | // Remove this thread from all other WaitObjects | 320 | // Remove this thread from all other WaitObjects |
| 326 | for (auto wait_object : wait_objects) | 321 | for (auto wait_object : wait_objects) |
| 327 | wait_object.first->RemoveWaitingThread(this); | 322 | wait_object->RemoveWaitingThread(this); |
| 328 | 323 | ||
| 329 | wait_objects.clear(); | 324 | wait_objects.clear(); |
| 330 | 325 | ||