summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp35
1 files changed, 24 insertions, 11 deletions
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
94static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object) { 94static 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
219void WaitCurrentThread(WaitType wait_type, Object* wait_object) { 223void 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
226void WaitCurrentThread(WaitType wait_type, Object* wait_object, VAddr wait_address) { 234void 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}