|
|
@ -244,20 +244,23 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool resume = true; |
|
|
|
|
|
|
|
|
if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY || |
|
|
if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY || |
|
|
thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) { |
|
|
thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) { |
|
|
|
|
|
|
|
|
// Invoke the wakeup callback before clearing the wait objects
|
|
|
|
|
|
if (thread->wakeup_callback) |
|
|
|
|
|
thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr); |
|
|
|
|
|
|
|
|
|
|
|
// Remove the thread from each of its waiting objects' waitlists
|
|
|
// Remove the thread from each of its waiting objects' waitlists
|
|
|
for (auto& object : thread->wait_objects) |
|
|
for (auto& object : thread->wait_objects) |
|
|
object->RemoveWaitingThread(thread.get()); |
|
|
object->RemoveWaitingThread(thread.get()); |
|
|
thread->wait_objects.clear(); |
|
|
thread->wait_objects.clear(); |
|
|
|
|
|
|
|
|
|
|
|
// Invoke the wakeup callback before clearing the wait objects
|
|
|
|
|
|
if (thread->wakeup_callback) |
|
|
|
|
|
resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
thread->ResumeFromWait(); |
|
|
|
|
|
|
|
|
if (resume) |
|
|
|
|
|
thread->ResumeFromWait(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void Thread::WakeAfterDelay(s64 nanoseconds) { |
|
|
void Thread::WakeAfterDelay(s64 nanoseconds) { |
|
|
@ -268,6 +271,10 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { |
|
|
CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, callback_handle); |
|
|
CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, callback_handle); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Thread::CancelWakeupTimer() { |
|
|
|
|
|
CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void Thread::ResumeFromWait() { |
|
|
void Thread::ResumeFromWait() { |
|
|
ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); |
|
|
ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); |
|
|
|
|
|
|
|
|
@ -444,7 +451,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, |
|
|
// Map the page to the current process' address space.
|
|
|
// Map the page to the current process' address space.
|
|
|
// TODO(Subv): Find the correct MemoryState for this region.
|
|
|
// TODO(Subv): Find the correct MemoryState for this region.
|
|
|
vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, |
|
|
vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, |
|
|
linheap_memory, offset, Memory::PAGE_SIZE, MemoryState::ThreadLocalStorage); |
|
|
|
|
|
|
|
|
linheap_memory, offset, Memory::PAGE_SIZE, |
|
|
|
|
|
MemoryState::ThreadLocalStorage); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Mark the slot as used
|
|
|
// Mark the slot as used
|
|
|
@ -501,7 +509,8 @@ SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority, |
|
|
SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); |
|
|
SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); |
|
|
|
|
|
|
|
|
// Register 1 must be a handle to the main thread
|
|
|
// Register 1 must be a handle to the main thread
|
|
|
thread->guest_handle = Kernel::g_handle_table.Create(thread).Unwrap();; |
|
|
|
|
|
|
|
|
thread->guest_handle = Kernel::g_handle_table.Create(thread).Unwrap(); |
|
|
|
|
|
|
|
|
thread->context.cpu_registers[1] = thread->guest_handle; |
|
|
thread->context.cpu_registers[1] = thread->guest_handle; |
|
|
|
|
|
|
|
|
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
|
|
|
// 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() { |
|
|
return thread_list; |
|
|
return thread_list; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
} // namespace Kernel
|