summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar Subv2017-09-28 11:53:32 -0500
committerGravatar Subv2017-09-28 11:53:32 -0500
commit8432749db7afecc9beea20f993cc036418caaa15 (patch)
tree10dd3fcd755bd7bdc27eef120885c7e700ab4288 /src/core/hle/kernel/thread.cpp
parentMerge pull request #2907 from Subv/warnings3 (diff)
downloadyuzu-8432749db7afecc9beea20f993cc036418caaa15.tar.gz
yuzu-8432749db7afecc9beea20f993cc036418caaa15.tar.xz
yuzu-8432749db7afecc9beea20f993cc036418caaa15.zip
Kernel/Threads: When putting a thread to wait, specify a function to execute when it is awoken.
This change makes for a clearer (less confusing) path of execution in the scheduler, now the code to execute when a thread awakes is closer to the code that puts the thread to sleep (WaitSynch1, WaitSynchN). It also allows us to implement the special wake up behavior of ReplyAndReceive without hacking up WaitObject::WakeupAllWaitingThreads. If savestates are desired in the future, we can change this implementation to one similar to the CoreTiming event system, where we first register the callback functions at startup and assign their identifiers to the Thread callback variable instead of directly assigning a lambda to the wake up callback variable.
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 61378211f..690cb20b3 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -247,12 +247,15 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
247 247
248 if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY || 248 if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
249 thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) { 249 thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) {
250 thread->wait_set_output = false; 250
251 // Invoke the wakeup callback before clearing the wait objects
252 if (thread->wakeup_callback)
253 thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr);
254
251 // Remove the thread from each of its waiting objects' waitlists 255 // Remove the thread from each of its waiting objects' waitlists
252 for (auto& object : thread->wait_objects) 256 for (auto& object : thread->wait_objects)
253 object->RemoveWaitingThread(thread.get()); 257 object->RemoveWaitingThread(thread.get());
254 thread->wait_objects.clear(); 258 thread->wait_objects.clear();
255 thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
256 } 259 }
257 260
258 thread->ResumeFromWait(); 261 thread->ResumeFromWait();
@@ -278,6 +281,9 @@ void Thread::ResumeFromWait() {
278 break; 281 break;
279 282
280 case THREADSTATUS_READY: 283 case THREADSTATUS_READY:
284 // The thread's wakeup callback must have already been cleared when the thread was first
285 // awoken.
286 ASSERT(wakeup_callback == nullptr);
281 // If the thread is waiting on multiple wait objects, it might be awoken more than once 287 // If the thread is waiting on multiple wait objects, it might be awoken more than once
282 // before actually resuming. We can ignore subsequent wakeups if the thread status has 288 // before actually resuming. We can ignore subsequent wakeups if the thread status has
283 // already been set to THREADSTATUS_READY. 289 // already been set to THREADSTATUS_READY.
@@ -293,6 +299,8 @@ void Thread::ResumeFromWait() {
293 return; 299 return;
294 } 300 }
295 301
302 wakeup_callback = nullptr;
303
296 ready_queue.push_back(current_priority, this); 304 ready_queue.push_back(current_priority, this);
297 status = THREADSTATUS_READY; 305 status = THREADSTATUS_READY;
298 Core::System::GetInstance().PrepareReschedule(); 306 Core::System::GetInstance().PrepareReschedule();
@@ -394,7 +402,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
394 thread->nominal_priority = thread->current_priority = priority; 402 thread->nominal_priority = thread->current_priority = priority;
395 thread->last_running_ticks = CoreTiming::GetTicks(); 403 thread->last_running_ticks = CoreTiming::GetTicks();
396 thread->processor_id = processor_id; 404 thread->processor_id = processor_id;
397 thread->wait_set_output = false;
398 thread->wait_objects.clear(); 405 thread->wait_objects.clear();
399 thread->wait_address = 0; 406 thread->wait_address = 0;
400 thread->name = std::move(name); 407 thread->name = std::move(name);