diff options
-rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 42 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 17 | ||||
-rw-r--r-- | src/core/hle/svc.cpp | 6 |
5 files changed, 45 insertions, 38 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 520601455..9e855b0bf 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -15,7 +15,7 @@ namespace Kernel { -class AddressArbiter : public WaitObject { +class AddressArbiter : public Object { public: std::string GetTypeName() const override { return "Arbiter"; } std::string GetName() const override { return name; } @@ -30,7 +30,7 @@ public: /// Arbitrate an address ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) { - WaitObject* object = static_cast<WaitObject*>(Kernel::g_handle_table.GetGeneric(handle).get()); + AddressArbiter* object = Kernel::g_handle_table.Get<AddressArbiter>(handle).get(); if (object == nullptr) return InvalidHandle(ErrorModule::Kernel); @@ -41,24 +41,24 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3 case ArbitrationType::Signal: // Negative value means resume all threads if (value < 0) { - ArbitrateAllThreads(object, address); + ArbitrateAllThreads(address); } else { // Resume first N threads for(int i = 0; i < value; i++) - ArbitrateHighestPriorityThread(object, address); + ArbitrateHighestPriorityThread(address); } break; // Wait current thread (acquire the arbiter)... case ArbitrationType::WaitIfLessThan: if ((s32)Memory::Read32(address) <= value) { - Kernel::WaitCurrentThread_ArbitrateAddress(object, address); + Kernel::WaitCurrentThread_ArbitrateAddress(address); HLE::Reschedule(__func__); } break; case ArbitrationType::WaitIfLessThanWithTimeout: if ((s32)Memory::Read32(address) <= value) { - Kernel::WaitCurrentThread_ArbitrateAddress(object, address); + Kernel::WaitCurrentThread_ArbitrateAddress(address); Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); HLE::Reschedule(__func__); } @@ -68,7 +68,7 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3 s32 memory_value = Memory::Read32(address) - 1; Memory::Write32(address, memory_value); if (memory_value <= value) { - Kernel::WaitCurrentThread_ArbitrateAddress(object, address); + Kernel::WaitCurrentThread_ArbitrateAddress(address); HLE::Reschedule(__func__); } break; @@ -78,7 +78,7 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3 s32 memory_value = Memory::Read32(address) - 1; Memory::Write32(address, memory_value); if (memory_value <= value) { - Kernel::WaitCurrentThread_ArbitrateAddress(object, address); + Kernel::WaitCurrentThread_ArbitrateAddress(address); Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); HLE::Reschedule(__func__); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 57e0e8df7..b3ca78ed6 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -36,7 +36,7 @@ Thread* WaitObject::ReleaseNextThread() { auto next_thread = waiting_threads.front(); - next_thread->ReleaseFromWait(this); + next_thread->ReleaseWaitObject(this); waiting_threads.erase(waiting_threads.begin()); return next_thread.get(); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 601e0eb20..16865ccc4 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -83,8 +83,8 @@ static void ChangeReadyState(Thread* t, bool ready) { } } -/// Check if a thread is blocking on a the specified object -static bool CheckWaitType(const Thread* thread, Object* wait_object) { +/// Check if a thread is waiting on a the specified wait object +static bool CheckWait_WaitObject(const Thread* thread, WaitObject* wait_object) { for (auto itr = thread->wait_objects.begin(); itr != thread->wait_objects.end(); ++itr) { if (*itr == wait_object) return (thread->IsWaiting()); @@ -92,9 +92,9 @@ static bool CheckWaitType(const Thread* thread, Object* wait_object) { return false; } -/// Check if a thread is blocking on a the specified object and an address -static bool CheckWaitType(const Thread* thread, Object* wait_object, VAddr wait_address) { - return CheckWaitType(thread, wait_object) && (wait_address == thread->wait_address); +/// Check if the specified thread is waiting on the specified address to be arbitrated +static bool CheckWait_AddressArbiter(const Thread* thread, VAddr wait_address) { + return thread->IsWaiting() && thread->wait_objects.empty() && wait_address == thread->wait_address; } /// Stops the current thread @@ -121,17 +121,17 @@ static void ChangeThreadState(Thread* t, ThreadStatus new_status) { } /// Arbitrate the highest priority thread that is waiting -Thread* ArbitrateHighestPriorityThread(WaitObject* arbiter, u32 address) { +Thread* ArbitrateHighestPriorityThread(u32 address) { Thread* highest_priority_thread = nullptr; s32 priority = THREADPRIO_LOWEST; // Iterate through threads, find highest priority thread that is waiting to be arbitrated... for (auto& thread : thread_list) { - if (!CheckWaitType(thread.get(), arbiter, address)) + if (!CheckWait_AddressArbiter(thread.get(), address)) continue; if (thread == nullptr) - continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. + continue; if(thread->current_priority <= priority) { highest_priority_thread = thread.get(); @@ -141,19 +141,19 @@ Thread* ArbitrateHighestPriorityThread(WaitObject* arbiter, u32 address) { // If a thread was arbitrated, resume it if (nullptr != highest_priority_thread) { - highest_priority_thread->ReleaseFromWait(arbiter); + highest_priority_thread->ResumeFromWait(); } return highest_priority_thread; } /// Arbitrate all threads currently waiting -void ArbitrateAllThreads(WaitObject* arbiter, u32 address) { +void ArbitrateAllThreads(u32 address) { // Iterate through threads, find highest priority thread that is waiting to be arbitrated... for (auto& thread : thread_list) { - if (CheckWaitType(thread.get(), arbiter, address)) - thread->ReleaseFromWait(arbiter); + if (CheckWait_AddressArbiter(thread.get(), address)) + thread->ResumeFromWait(); } } @@ -202,21 +202,28 @@ static Thread* NextThread() { return next; } -void WaitCurrentThread() { +void WaitCurrentThread_Sleep() { Thread* thread = GetCurrentThread(); + thread->wait_all = false; + thread->wait_address = 0; + thread->wait_objects.clear(); ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); } void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_all) { Thread* thread = GetCurrentThread(); thread->wait_all = wait_all; + thread->wait_address = 0; thread->wait_objects.push_back(wait_object); ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); } -void WaitCurrentThread_ArbitrateAddress(WaitObject* wait_object, VAddr wait_address) { - WaitCurrentThread_WaitSynchronization(wait_object); - GetCurrentThread()->wait_address = wait_address; +void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { + Thread* thread = GetCurrentThread(); + thread->wait_all = false; + thread->wait_address = wait_address; + thread->wait_objects.clear(); + ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); } /// Event type for the thread wake up event @@ -248,7 +255,7 @@ void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) { CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle()); } -void Thread::ReleaseFromWait(WaitObject* wait_object) { +void Thread::ReleaseWaitObject(WaitObject* wait_object) { if (wait_objects.empty()) { LOG_CRITICAL(Kernel, "thread is not waiting on any objects!"); return; @@ -298,6 +305,7 @@ void Thread::ResumeFromWait() { wait_objects.clear(); wait_all = false; + wait_address = 0; if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { ChangeReadyState(this, true); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index cb48fcadc..9907aa6e1 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -69,10 +69,10 @@ public: void Stop(const char* reason); /** - * Release an object from the thread's wait list - * @param wait_object WaitObject to release from the thread's wait list + * Release an acquired wait object + * @param wait_object WaitObject to release */ - void ReleaseFromWait(WaitObject* wait_object); + void ReleaseWaitObject(WaitObject* wait_object); /// Resumes a thread from waiting by marking it as "ready" void ResumeFromWait(); @@ -120,16 +120,16 @@ SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); void Reschedule(); /// Arbitrate the highest priority thread that is waiting -Thread* ArbitrateHighestPriorityThread(WaitObject* arbiter, u32 address); +Thread* ArbitrateHighestPriorityThread(u32 address); /// Arbitrate all threads currently waiting... -void ArbitrateAllThreads(WaitObject* arbiter, u32 address); +void ArbitrateAllThreads(u32 address); /// Gets the current thread Thread* GetCurrentThread(); -/// Waits the current thread -void WaitCurrentThread(); +/// Waits the current thread on a sleep +void WaitCurrentThread_Sleep(); /** * Waits the current thread from a WaitSynchronization call @@ -140,10 +140,9 @@ void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_al /** * Waits the current thread from an ArbitrateAddress call - * @param wait_object Kernel object that we are waiting on * @param wait_address Arbitration address used to resume from wait */ -void WaitCurrentThread_ArbitrateAddress(WaitObject* wait_object, VAddr wait_address); +void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); /** * Schedules an event to wake up the specified thread after the specified delay. diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 2d5f41af6..cf029bf69 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -105,7 +105,7 @@ static Result SendSyncRequest(Handle handle) { ResultVal<bool> wait = session->SyncRequest(); if (wait.Succeeded() && *wait) { - Kernel::WaitCurrentThread(); // TODO(bunnei): Is this correct? + Kernel::WaitCurrentThread_Sleep(); // TODO(bunnei): Is this correct? } return wait.Code().raw; @@ -196,7 +196,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, // NOTE: This should deadlock the current thread if no timeout was specified if (!wait_all) { wait_thread = true; - Kernel::WaitCurrentThread(); + Kernel::WaitCurrentThread_Sleep(); } } @@ -450,7 +450,7 @@ static void SleepThread(s64 nanoseconds) { LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); // Sleep current thread and check for next thread to schedule - Kernel::WaitCurrentThread(); + Kernel::WaitCurrentThread_Sleep(); // Create an event to wake the thread up after the specified nanosecond delay has passed Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds); |