summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp43
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
206void WaitCurrentThread_Sleep() { 206void 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
214void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bool wait_all) { 211void 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
222void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { 223void 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
465void Thread::SetReturnValue(ResultCode return_val, s32 out_val) { 475void 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
479void Thread::SetWaitSynchronizationOutput(s32 output) {
480 context.cpu_registers[1] = output;
468} 481}
469 482
470//////////////////////////////////////////////////////////////////////////////////////////////////// 483////////////////////////////////////////////////////////////////////////////////////////////////////