diff options
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 42 |
1 files changed, 25 insertions, 17 deletions
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) { | |||
| 83 | } | 83 | } |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | /// Check if a thread is blocking on a the specified object | 86 | /// Check if a thread is waiting on a the specified wait object |
| 87 | static bool CheckWaitType(const Thread* thread, Object* wait_object) { | 87 | static bool CheckWait_WaitObject(const Thread* thread, WaitObject* wait_object) { |
| 88 | for (auto itr = thread->wait_objects.begin(); itr != thread->wait_objects.end(); ++itr) { | 88 | for (auto itr = thread->wait_objects.begin(); itr != thread->wait_objects.end(); ++itr) { |
| 89 | if (*itr == wait_object) | 89 | if (*itr == wait_object) |
| 90 | return (thread->IsWaiting()); | 90 | return (thread->IsWaiting()); |
| @@ -92,9 +92,9 @@ static bool CheckWaitType(const Thread* thread, Object* wait_object) { | |||
| 92 | return false; | 92 | return false; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | /// Check if a thread is blocking on a the specified object and an address | 95 | /// Check if the specified thread is waiting on the specified address to be arbitrated |
| 96 | static bool CheckWaitType(const Thread* thread, Object* wait_object, VAddr wait_address) { | 96 | static bool CheckWait_AddressArbiter(const Thread* thread, VAddr wait_address) { |
| 97 | return CheckWaitType(thread, wait_object) && (wait_address == thread->wait_address); | 97 | return thread->IsWaiting() && thread->wait_objects.empty() && wait_address == thread->wait_address; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | /// Stops the current thread | 100 | /// Stops the current thread |
| @@ -121,17 +121,17 @@ static void ChangeThreadState(Thread* t, ThreadStatus new_status) { | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | /// Arbitrate the highest priority thread that is waiting | 123 | /// Arbitrate the highest priority thread that is waiting |
| 124 | Thread* ArbitrateHighestPriorityThread(WaitObject* arbiter, u32 address) { | 124 | Thread* ArbitrateHighestPriorityThread(u32 address) { |
| 125 | Thread* highest_priority_thread = nullptr; | 125 | Thread* highest_priority_thread = nullptr; |
| 126 | s32 priority = THREADPRIO_LOWEST; | 126 | s32 priority = THREADPRIO_LOWEST; |
| 127 | 127 | ||
| 128 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 128 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 129 | for (auto& thread : thread_list) { | 129 | for (auto& thread : thread_list) { |
| 130 | if (!CheckWaitType(thread.get(), arbiter, address)) | 130 | if (!CheckWait_AddressArbiter(thread.get(), address)) |
| 131 | continue; | 131 | continue; |
| 132 | 132 | ||
| 133 | if (thread == nullptr) | 133 | if (thread == nullptr) |
| 134 | continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. | 134 | continue; |
| 135 | 135 | ||
| 136 | if(thread->current_priority <= priority) { | 136 | if(thread->current_priority <= priority) { |
| 137 | highest_priority_thread = thread.get(); | 137 | highest_priority_thread = thread.get(); |
| @@ -141,19 +141,19 @@ Thread* ArbitrateHighestPriorityThread(WaitObject* arbiter, u32 address) { | |||
| 141 | 141 | ||
| 142 | // If a thread was arbitrated, resume it | 142 | // If a thread was arbitrated, resume it |
| 143 | if (nullptr != highest_priority_thread) { | 143 | if (nullptr != highest_priority_thread) { |
| 144 | highest_priority_thread->ReleaseFromWait(arbiter); | 144 | highest_priority_thread->ResumeFromWait(); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | return highest_priority_thread; | 147 | return highest_priority_thread; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | /// Arbitrate all threads currently waiting | 150 | /// Arbitrate all threads currently waiting |
| 151 | void ArbitrateAllThreads(WaitObject* arbiter, u32 address) { | 151 | void ArbitrateAllThreads(u32 address) { |
| 152 | 152 | ||
| 153 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 153 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 154 | for (auto& thread : thread_list) { | 154 | for (auto& thread : thread_list) { |
| 155 | if (CheckWaitType(thread.get(), arbiter, address)) | 155 | if (CheckWait_AddressArbiter(thread.get(), address)) |
| 156 | thread->ReleaseFromWait(arbiter); | 156 | thread->ResumeFromWait(); |
| 157 | } | 157 | } |
| 158 | } | 158 | } |
| 159 | 159 | ||
| @@ -202,21 +202,28 @@ static Thread* NextThread() { | |||
| 202 | return next; | 202 | return next; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | void WaitCurrentThread() { | 205 | void WaitCurrentThread_Sleep() { |
| 206 | Thread* thread = GetCurrentThread(); | 206 | Thread* thread = GetCurrentThread(); |
| 207 | thread->wait_all = false; | ||
| 208 | thread->wait_address = 0; | ||
| 209 | thread->wait_objects.clear(); | ||
| 207 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 210 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 208 | } | 211 | } |
| 209 | 212 | ||
| 210 | void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_all) { | 213 | void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_all) { |
| 211 | Thread* thread = GetCurrentThread(); | 214 | Thread* thread = GetCurrentThread(); |
| 212 | thread->wait_all = wait_all; | 215 | thread->wait_all = wait_all; |
| 216 | thread->wait_address = 0; | ||
| 213 | thread->wait_objects.push_back(wait_object); | 217 | thread->wait_objects.push_back(wait_object); |
| 214 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 218 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 215 | } | 219 | } |
| 216 | 220 | ||
| 217 | void WaitCurrentThread_ArbitrateAddress(WaitObject* wait_object, VAddr wait_address) { | 221 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { |
| 218 | WaitCurrentThread_WaitSynchronization(wait_object); | 222 | Thread* thread = GetCurrentThread(); |
| 219 | GetCurrentThread()->wait_address = wait_address; | 223 | thread->wait_all = false; |
| 224 | thread->wait_address = wait_address; | ||
| 225 | thread->wait_objects.clear(); | ||
| 226 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | ||
| 220 | } | 227 | } |
| 221 | 228 | ||
| 222 | /// Event type for the thread wake up event | 229 | /// Event type for the thread wake up event |
| @@ -248,7 +255,7 @@ void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) { | |||
| 248 | CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle()); | 255 | CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle()); |
| 249 | } | 256 | } |
| 250 | 257 | ||
| 251 | void Thread::ReleaseFromWait(WaitObject* wait_object) { | 258 | void Thread::ReleaseWaitObject(WaitObject* wait_object) { |
| 252 | if (wait_objects.empty()) { | 259 | if (wait_objects.empty()) { |
| 253 | LOG_CRITICAL(Kernel, "thread is not waiting on any objects!"); | 260 | LOG_CRITICAL(Kernel, "thread is not waiting on any objects!"); |
| 254 | return; | 261 | return; |
| @@ -298,6 +305,7 @@ void Thread::ResumeFromWait() { | |||
| 298 | 305 | ||
| 299 | wait_objects.clear(); | 306 | wait_objects.clear(); |
| 300 | wait_all = false; | 307 | wait_all = false; |
| 308 | wait_address = 0; | ||
| 301 | 309 | ||
| 302 | if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | 310 | if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { |
| 303 | ChangeReadyState(this, true); | 311 | ChangeReadyState(this, true); |