diff options
| author | 2015-01-20 20:53:52 -0500 | |
|---|---|---|
| committer | 2015-01-21 20:48:46 -0500 | |
| commit | 68ddaaa2f5726e3619accee77b488ec285f3a2d7 (patch) | |
| tree | f9d349d09c66efe768fbb4aed67b7b163c3ffec7 /src/core/hle/kernel/thread.cpp | |
| parent | Thread: Use std::find in CheckWait_WaitObject. (diff) | |
| download | yuzu-68ddaaa2f5726e3619accee77b488ec285f3a2d7.tar.gz yuzu-68ddaaa2f5726e3619accee77b488ec285f3a2d7.tar.xz yuzu-68ddaaa2f5726e3619accee77b488ec285f3a2d7.zip | |
Thread: Fix WaitSynchronization1 to not set register 1 on thread wakeup.
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 58523e145..03b492c75 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -205,25 +205,24 @@ static Thread* NextThread() { | |||
| 205 | 205 | ||
| 206 | void WaitCurrentThread_Sleep() { | 206 | void WaitCurrentThread_Sleep() { |
| 207 | Thread* thread = GetCurrentThread(); | 207 | Thread* thread = GetCurrentThread(); |
| 208 | thread->wait_all = false; | ||
| 209 | thread->wait_address = 0; | ||
| 210 | thread->wait_objects.clear(); | ||
| 211 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 208 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 212 | } | 209 | } |
| 213 | 210 | ||
| 214 | void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bool wait_all) { | 211 | void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bool wait_set_output, bool wait_all) { |
| 215 | Thread* thread = GetCurrentThread(); | 212 | Thread* thread = GetCurrentThread(); |
| 213 | thread->wait_set_output = wait_set_output; | ||
| 216 | thread->wait_all = wait_all; | 214 | thread->wait_all = wait_all; |
| 217 | thread->wait_address = 0; | 215 | |
| 218 | thread->wait_objects.push_back(wait_object); | 216 | // It's possible to call WaitSynchronizationN without any objects passed in... |
| 217 | if (wait_object != nullptr) | ||
| 218 | thread->wait_objects.push_back(wait_object); | ||
| 219 | |||
| 219 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 220 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 220 | } | 221 | } |
| 221 | 222 | ||
| 222 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { | 223 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { |
| 223 | Thread* thread = GetCurrentThread(); | 224 | Thread* thread = GetCurrentThread(); |
| 224 | thread->wait_all = false; | ||
| 225 | thread->wait_address = wait_address; | 225 | thread->wait_address = wait_address; |
| 226 | thread->wait_objects.clear(); | ||
| 227 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 226 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 228 | } | 227 | } |
| 229 | 228 | ||
| @@ -239,8 +238,11 @@ static void ThreadWakeupCallback(u64 parameter, int cycles_late) { | |||
| 239 | return; | 238 | return; |
| 240 | } | 239 | } |
| 241 | 240 | ||
| 242 | thread->SetReturnValue(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, | 241 | thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, |
| 243 | ErrorSummary::StatusChanged, ErrorLevel::Info), -1); | 242 | ErrorSummary::StatusChanged, ErrorLevel::Info)); |
| 243 | |||
| 244 | if (thread->wait_set_output) | ||
| 245 | thread->SetWaitSynchronizationOutput(-1); | ||
| 244 | 246 | ||
| 245 | thread->ResumeFromWait(); | 247 | thread->ResumeFromWait(); |
| 246 | } | 248 | } |
| @@ -282,12 +284,18 @@ void Thread::ReleaseWaitObject(WaitObject* wait_object) { | |||
| 282 | if (wait_all) { | 284 | if (wait_all) { |
| 283 | // Resume the thread only if all are available... | 285 | // Resume the thread only if all are available... |
| 284 | if (!wait_all_failed) { | 286 | if (!wait_all_failed) { |
| 285 | SetReturnValue(RESULT_SUCCESS, -1); | 287 | SetWaitSynchronizationResult(RESULT_SUCCESS); |
| 288 | SetWaitSynchronizationOutput(-1); | ||
| 289 | |||
| 286 | ResumeFromWait(); | 290 | ResumeFromWait(); |
| 287 | } | 291 | } |
| 288 | } else { | 292 | } else { |
| 289 | // Otherwise, resume | 293 | // Otherwise, resume |
| 290 | SetReturnValue(RESULT_SUCCESS, index); | 294 | SetWaitSynchronizationResult(RESULT_SUCCESS); |
| 295 | |||
| 296 | if (wait_set_output) | ||
| 297 | SetWaitSynchronizationOutput(index); | ||
| 298 | |||
| 291 | ResumeFromWait(); | 299 | ResumeFromWait(); |
| 292 | } | 300 | } |
| 293 | } | 301 | } |
| @@ -303,6 +311,7 @@ void Thread::ResumeFromWait() { | |||
| 303 | wait_object->RemoveWaitingThread(this); | 311 | wait_object->RemoveWaitingThread(this); |
| 304 | 312 | ||
| 305 | wait_objects.clear(); | 313 | wait_objects.clear(); |
| 314 | wait_set_output = false; | ||
| 306 | wait_all = false; | 315 | wait_all = false; |
| 307 | wait_address = 0; | 316 | wait_address = 0; |
| 308 | 317 | ||
| @@ -371,6 +380,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 371 | thread->stack_size = stack_size; | 380 | thread->stack_size = stack_size; |
| 372 | thread->initial_priority = thread->current_priority = priority; | 381 | thread->initial_priority = thread->current_priority = priority; |
| 373 | thread->processor_id = processor_id; | 382 | thread->processor_id = processor_id; |
| 383 | thread->wait_set_output = false; | ||
| 374 | thread->wait_all = false; | 384 | thread->wait_all = false; |
| 375 | thread->wait_objects.clear(); | 385 | thread->wait_objects.clear(); |
| 376 | thread->wait_address = 0; | 386 | thread->wait_address = 0; |
| @@ -462,9 +472,12 @@ void Reschedule() { | |||
| 462 | } | 472 | } |
| 463 | } | 473 | } |
| 464 | 474 | ||
| 465 | void Thread::SetReturnValue(ResultCode return_val, s32 out_val) { | 475 | void Thread::SetWaitSynchronizationResult(ResultCode result) { |
| 466 | context.cpu_registers[0] = return_val.raw; | 476 | context.cpu_registers[0] = result.raw; |
| 467 | context.cpu_registers[1] = out_val; | 477 | } |
| 478 | |||
| 479 | void Thread::SetWaitSynchronizationOutput(s32 output) { | ||
| 480 | context.cpu_registers[1] = output; | ||
| 468 | } | 481 | } |
| 469 | 482 | ||
| 470 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 483 | //////////////////////////////////////////////////////////////////////////////////////////////////// |