summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar Subv2018-01-08 11:35:03 -0500
committerGravatar bunnei2018-01-08 21:12:49 -0500
commit2a3f8e8484fca54767c9874cc21f5985d2be1463 (patch)
tree0976e02e0b495f07b11a51811618199d791d4c4e /src/core/hle/kernel/thread.cpp
parentcmake: Use LIBUNICORN_* on Windows. (diff)
downloadyuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.gz
yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.tar.xz
yuzu-2a3f8e8484fca54767c9874cc21f5985d2be1463.zip
Kernel: Allow chaining WaitSynchronization calls inside a wakeup callback.
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp25
1 files changed, 17 insertions, 8 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f9d821a80..111c496b9 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -244,20 +244,23 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
244 return; 244 return;
245 } 245 }
246 246
247 bool resume = true;
248
247 if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY || 249 if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
248 thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) { 250 thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) {
249 251
250 // Invoke the wakeup callback before clearing the wait objects
251 if (thread->wakeup_callback)
252 thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr);
253
254 // Remove the thread from each of its waiting objects' waitlists 252 // Remove the thread from each of its waiting objects' waitlists
255 for (auto& object : thread->wait_objects) 253 for (auto& object : thread->wait_objects)
256 object->RemoveWaitingThread(thread.get()); 254 object->RemoveWaitingThread(thread.get());
257 thread->wait_objects.clear(); 255 thread->wait_objects.clear();
256
257 // Invoke the wakeup callback before clearing the wait objects
258 if (thread->wakeup_callback)
259 resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
258 } 260 }
259 261
260 thread->ResumeFromWait(); 262 if (resume)
263 thread->ResumeFromWait();
261} 264}
262 265
263void Thread::WakeAfterDelay(s64 nanoseconds) { 266void Thread::WakeAfterDelay(s64 nanoseconds) {
@@ -268,6 +271,10 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
268 CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, callback_handle); 271 CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, callback_handle);
269} 272}
270 273
274void Thread::CancelWakeupTimer() {
275 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
276}
277
271void Thread::ResumeFromWait() { 278void Thread::ResumeFromWait() {
272 ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); 279 ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
273 280
@@ -444,7 +451,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
444 // Map the page to the current process' address space. 451 // Map the page to the current process' address space.
445 // TODO(Subv): Find the correct MemoryState for this region. 452 // TODO(Subv): Find the correct MemoryState for this region.
446 vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, 453 vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
447 linheap_memory, offset, Memory::PAGE_SIZE, MemoryState::ThreadLocalStorage); 454 linheap_memory, offset, Memory::PAGE_SIZE,
455 MemoryState::ThreadLocalStorage);
448 } 456 }
449 457
450 // Mark the slot as used 458 // Mark the slot as used
@@ -501,7 +509,8 @@ SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority,
501 SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); 509 SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
502 510
503 // Register 1 must be a handle to the main thread 511 // Register 1 must be a handle to the main thread
504 thread->guest_handle = Kernel::g_handle_table.Create(thread).Unwrap();; 512 thread->guest_handle = Kernel::g_handle_table.Create(thread).Unwrap();
513
505 thread->context.cpu_registers[1] = thread->guest_handle; 514 thread->context.cpu_registers[1] = thread->guest_handle;
506 515
507 // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires 516 // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
@@ -572,4 +581,4 @@ const std::vector<SharedPtr<Thread>>& GetThreadList() {
572 return thread_list; 581 return thread_list;
573} 582}
574 583
575} // namespace 584} // namespace Kernel