diff options
| author | 2015-01-14 23:41:33 -0500 | |
|---|---|---|
| committer | 2015-01-21 18:42:04 -0500 | |
| commit | 1f7a04f05a488b7d457d356f9bf2dda296cd6b92 (patch) | |
| tree | ab6bffea6b9f85039af93f4f809c4d657f192d8f /src | |
| parent | Event: Get rid of permanent_lock hack. (diff) | |
| download | yuzu-1f7a04f05a488b7d457d356f9bf2dda296cd6b92.tar.gz yuzu-1f7a04f05a488b7d457d356f9bf2dda296cd6b92.tar.xz yuzu-1f7a04f05a488b7d457d356f9bf2dda296cd6b92.zip | |
Thread: Keep track of multiple wait objects.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 35 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 6 |
3 files changed, 30 insertions, 16 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index b7434aaf2..ff1472066 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | namespace Kernel { |
| 17 | 17 | ||
| 18 | class AddressArbiter : public Object { | 18 | class AddressArbiter : public WaitObject { |
| 19 | public: | 19 | public: |
| 20 | std::string GetTypeName() const override { return "Arbiter"; } | 20 | std::string GetTypeName() const override { return "Arbiter"; } |
| 21 | std::string GetName() const override { return name; } | 21 | std::string GetName() const override { return name; } |
| @@ -30,7 +30,8 @@ public: | |||
| 30 | 30 | ||
| 31 | /// Arbitrate an address | 31 | /// Arbitrate an address |
| 32 | ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) { | 32 | ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) { |
| 33 | Object* object = Kernel::g_handle_table.GetGeneric(handle).get(); | 33 | WaitObject* object = static_cast<WaitObject*>(Kernel::g_handle_table.GetGeneric(handle).get()); |
| 34 | |||
| 34 | if (object == nullptr) | 35 | if (object == nullptr) |
| 35 | return InvalidHandle(ErrorModule::Kernel); | 36 | return InvalidHandle(ErrorModule::Kernel); |
| 36 | 37 | ||
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 845672702..00b72477e 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -65,7 +65,7 @@ static void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { | |||
| 65 | t->current_priority = t->initial_priority; | 65 | t->current_priority = t->initial_priority; |
| 66 | } | 66 | } |
| 67 | t->wait_type = WAITTYPE_NONE; | 67 | t->wait_type = WAITTYPE_NONE; |
| 68 | t->wait_object = nullptr; | 68 | t->wait_objects.clear(); |
| 69 | t->wait_address = 0; | 69 | t->wait_address = 0; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| @@ -92,7 +92,11 @@ static bool CheckWaitType(const Thread* thread, WaitType type) { | |||
| 92 | 92 | ||
| 93 | /// Check if a thread is blocking on a specified wait type with a specified handle | 93 | /// Check if a thread is blocking on a specified wait type with a specified handle |
| 94 | static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object) { | 94 | static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object) { |
| 95 | return CheckWaitType(thread, type) && wait_object == thread->wait_object; | 95 | auto itr = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object); |
| 96 | if (itr == thread->wait_objects.end()) { | ||
| 97 | return false; | ||
| 98 | } | ||
| 99 | return CheckWaitType(thread, type); | ||
| 96 | } | 100 | } |
| 97 | 101 | ||
| 98 | /// Check if a thread is blocking on a specified wait type with a specified handle and address | 102 | /// Check if a thread is blocking on a specified wait type with a specified handle and address |
| @@ -111,7 +115,7 @@ void Thread::Stop(const char* reason) { | |||
| 111 | 115 | ||
| 112 | // Stopped threads are never waiting. | 116 | // Stopped threads are never waiting. |
| 113 | wait_type = WAITTYPE_NONE; | 117 | wait_type = WAITTYPE_NONE; |
| 114 | wait_object = nullptr; | 118 | wait_objects.clear(); |
| 115 | wait_address = 0; | 119 | wait_address = 0; |
| 116 | } | 120 | } |
| 117 | 121 | ||
| @@ -216,14 +220,18 @@ static Thread* NextThread() { | |||
| 216 | return next; | 220 | return next; |
| 217 | } | 221 | } |
| 218 | 222 | ||
| 219 | void WaitCurrentThread(WaitType wait_type, Object* wait_object) { | 223 | void WaitCurrentThread(WaitType wait_type, WaitObject* wait_object) { |
| 220 | Thread* thread = GetCurrentThread(); | 224 | Thread* thread = GetCurrentThread(); |
| 221 | thread->wait_type = wait_type; | 225 | thread->wait_type = wait_type; |
| 222 | thread->wait_object = wait_object; | 226 | |
| 227 | auto res = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object); | ||
| 228 | if (res == thread->wait_objects.end()) { | ||
| 229 | thread->wait_objects.push_back(wait_object); | ||
| 230 | } | ||
| 223 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 231 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 224 | } | 232 | } |
| 225 | 233 | ||
| 226 | void WaitCurrentThread(WaitType wait_type, Object* wait_object, VAddr wait_address) { | 234 | void WaitCurrentThread(WaitType wait_type, WaitObject* wait_object, VAddr wait_address) { |
| 227 | WaitCurrentThread(wait_type, wait_object); | 235 | WaitCurrentThread(wait_type, wait_object); |
| 228 | GetCurrentThread()->wait_address = wait_address; | 236 | GetCurrentThread()->wait_address = wait_address; |
| 229 | } | 237 | } |
| @@ -260,7 +268,13 @@ void Thread::ResumeFromWait() { | |||
| 260 | CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle()); | 268 | CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle()); |
| 261 | 269 | ||
| 262 | status &= ~THREADSTATUS_WAIT; | 270 | status &= ~THREADSTATUS_WAIT; |
| 263 | wait_object = nullptr; | 271 | |
| 272 | // Remove this thread from all other WaitObjects | ||
| 273 | for (auto wait_object : wait_objects) | ||
| 274 | wait_object->RemoveWaitingThread(this); | ||
| 275 | |||
| 276 | wait_objects.clear(); | ||
| 277 | |||
| 264 | wait_type = WAITTYPE_NONE; | 278 | wait_type = WAITTYPE_NONE; |
| 265 | if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | 279 | if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { |
| 266 | ChangeReadyState(this, true); | 280 | ChangeReadyState(this, true); |
| @@ -328,7 +342,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 328 | thread->initial_priority = thread->current_priority = priority; | 342 | thread->initial_priority = thread->current_priority = priority; |
| 329 | thread->processor_id = processor_id; | 343 | thread->processor_id = processor_id; |
| 330 | thread->wait_type = WAITTYPE_NONE; | 344 | thread->wait_type = WAITTYPE_NONE; |
| 331 | thread->wait_object = nullptr; | 345 | thread->wait_objects.clear(); |
| 332 | thread->wait_address = 0; | 346 | thread->wait_address = 0; |
| 333 | thread->name = std::move(name); | 347 | thread->name = std::move(name); |
| 334 | 348 | ||
| @@ -412,9 +426,8 @@ void Reschedule() { | |||
| 412 | LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); | 426 | LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); |
| 413 | 427 | ||
| 414 | for (auto& thread : thread_list) { | 428 | for (auto& thread : thread_list) { |
| 415 | LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X", | 429 | LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X", |
| 416 | thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, | 430 | thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type); |
| 417 | (thread->wait_object ? thread->wait_object->GetHandle() : INVALID_HANDLE)); | ||
| 418 | } | 431 | } |
| 419 | } | 432 | } |
| 420 | } | 433 | } |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index daaeb26a4..9ec96c18c 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -96,7 +96,7 @@ public: | |||
| 96 | s32 processor_id; | 96 | s32 processor_id; |
| 97 | 97 | ||
| 98 | WaitType wait_type; | 98 | WaitType wait_type; |
| 99 | Object* wait_object; | 99 | std::vector<SharedPtr<WaitObject>> wait_objects; |
| 100 | VAddr wait_address; | 100 | VAddr wait_address; |
| 101 | 101 | ||
| 102 | std::string name; | 102 | std::string name; |
| @@ -128,7 +128,7 @@ Thread* GetCurrentThread(); | |||
| 128 | * @param wait_type Type of wait | 128 | * @param wait_type Type of wait |
| 129 | * @param wait_object Kernel object that we are waiting on, defaults to current thread | 129 | * @param wait_object Kernel object that we are waiting on, defaults to current thread |
| 130 | */ | 130 | */ |
| 131 | void WaitCurrentThread(WaitType wait_type, Object* wait_object = GetCurrentThread()); | 131 | void WaitCurrentThread(WaitType wait_type, WaitObject* wait_object = GetCurrentThread()); |
| 132 | 132 | ||
| 133 | /** | 133 | /** |
| 134 | * Schedules an event to wake up the specified thread after the specified delay. | 134 | * Schedules an event to wake up the specified thread after the specified delay. |
| @@ -143,7 +143,7 @@ void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds); | |||
| 143 | * @param wait_object Kernel object that we are waiting on | 143 | * @param wait_object Kernel object that we are waiting on |
| 144 | * @param wait_address Arbitration address used to resume from wait | 144 | * @param wait_address Arbitration address used to resume from wait |
| 145 | */ | 145 | */ |
| 146 | void WaitCurrentThread(WaitType wait_type, Object* wait_object, VAddr wait_address); | 146 | void WaitCurrentThread(WaitType wait_type, WaitObject* wait_object, VAddr wait_address); |
| 147 | 147 | ||
| 148 | 148 | ||
| 149 | 149 | ||