summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/kernel.cpp8
-rw-r--r--src/core/hle/kernel/thread.cpp5
-rw-r--r--src/core/hle/kernel/thread.h16
-rw-r--r--src/core/hle/svc.cpp14
4 files changed, 22 insertions, 21 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 6f61d526a..955f50a9b 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -55,10 +55,16 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
55 if (ShouldWait(thread.get())) 55 if (ShouldWait(thread.get()))
56 continue; 56 continue;
57 57
58 bool ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(), 58 // A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or
59 // in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready.
60 bool ready_to_run = true;
61 if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) {
62 ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
59 [&thread](const SharedPtr<WaitObject>& object) { 63 [&thread](const SharedPtr<WaitObject>& object) {
60 return object->ShouldWait(thread.get()); 64 return object->ShouldWait(thread.get());
61 }); 65 });
66 }
67
62 if (ready_to_run) { 68 if (ready_to_run) {
63 candidate = thread.get(); 69 candidate = thread.get();
64 candidate_priority = thread->current_priority; 70 candidate_priority = thread->current_priority;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index aa99d18c7..568cef5b9 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -579,6 +579,11 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
579 context.cpu_registers[1] = output; 579 context.cpu_registers[1] = output;
580} 580}
581 581
582s32 Thread::GetWaitObjectIndex(WaitObject* object) const {
583 auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object);
584 return std::distance(match, wait_objects.rend()) - 1;
585}
586
582//////////////////////////////////////////////////////////////////////////////////////////////////// 587////////////////////////////////////////////////////////////////////////////////////////////////////
583 588
584void ThreadingInit() { 589void ThreadingInit() {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 6cd8c20e2..af72b76ea 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -135,13 +135,14 @@ public:
135 135
136 /** 136 /**
137 * Retrieves the index that this particular object occupies in the list of objects 137 * Retrieves the index that this particular object occupies in the list of objects
138 * that the thread passed to WaitSynchronizationN. 138 * that the thread passed to WaitSynchronizationN, starting the search from the last element.
139 * It is used to set the output value of WaitSynchronizationN when the thread is awakened. 139 * It is used to set the output value of WaitSynchronizationN when the thread is awakened.
140 * When a thread wakes up due to an object signal, the kernel will use the index of the last
141 * matching object in the wait objects list in case of having multiple instances of the same
142 * object in the list.
140 * @param object Object to query the index of. 143 * @param object Object to query the index of.
141 */ 144 */
142 s32 GetWaitObjectIndex(const WaitObject* object) const { 145 s32 GetWaitObjectIndex(WaitObject* object) const;
143 return wait_objects_index.at(object->GetObjectId());
144 }
145 146
146 /** 147 /**
147 * Stops a thread, invalidating it from further use 148 * Stops a thread, invalidating it from further use
@@ -190,13 +191,10 @@ public:
190 191
191 SharedPtr<Process> owner_process; ///< Process that owns this thread 192 SharedPtr<Process> owner_process; ///< Process that owns this thread
192 193
193 /// Objects that the thread is waiting on. 194 /// Objects that the thread is waiting on, in the same order as they were
194 /// This is only populated when the thread should wait for all the objects to become ready. 195 // passed to WaitSynchronization1/N.
195 std::vector<SharedPtr<WaitObject>> wait_objects; 196 std::vector<SharedPtr<WaitObject>> wait_objects;
196 197
197 /// Mapping of Object ids to their position in the last waitlist that this object waited on.
198 boost::container::flat_map<int, s32> wait_objects_index;
199
200 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address 198 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
201 199
202 /// True if the WaitSynchronizationN output parameter should be set on thread wakeup. 200 /// True if the WaitSynchronizationN output parameter should be set on thread wakeup.
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 1e1ca5180..855f3af82 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -277,6 +277,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
277 if (nano_seconds == 0) 277 if (nano_seconds == 0)
278 return ERR_SYNC_TIMEOUT; 278 return ERR_SYNC_TIMEOUT;
279 279
280 thread->wait_objects = {object};
280 object->AddWaitingThread(thread); 281 object->AddWaitingThread(thread);
281 thread->status = THREADSTATUS_WAIT_SYNCH_ANY; 282 thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
282 283
@@ -325,11 +326,6 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
325 objects[i] = object; 326 objects[i] = object;
326 } 327 }
327 328
328 // Clear the mapping of wait object indices.
329 // We don't want any lingering state in this map.
330 // It will be repopulated later in the wait_all = false case.
331 thread->wait_objects_index.clear();
332
333 if (wait_all) { 329 if (wait_all) {
334 bool all_available = 330 bool all_available =
335 std::all_of(objects.begin(), objects.end(), 331 std::all_of(objects.begin(), objects.end(),
@@ -358,7 +354,6 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
358 object->AddWaitingThread(thread); 354 object->AddWaitingThread(thread);
359 } 355 }
360 356
361 // Set the thread's waitlist to the list of objects passed to WaitSynchronizationN
362 thread->wait_objects = std::move(objects); 357 thread->wait_objects = std::move(objects);
363 358
364 // Create an event to wake the thread up after the specified nanosecond delay has passed 359 // Create an event to wake the thread up after the specified nanosecond delay has passed
@@ -395,17 +390,14 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
395 // Put the thread to sleep 390 // Put the thread to sleep
396 thread->status = THREADSTATUS_WAIT_SYNCH_ANY; 391 thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
397 392
398 // Clear the thread's waitlist, we won't use it for wait_all = false
399 thread->wait_objects.clear();
400
401 // Add the thread to each of the objects' waiting threads. 393 // Add the thread to each of the objects' waiting threads.
402 for (size_t i = 0; i < objects.size(); ++i) { 394 for (size_t i = 0; i < objects.size(); ++i) {
403 Kernel::WaitObject* object = objects[i].get(); 395 Kernel::WaitObject* object = objects[i].get();
404 // Set the index of this object in the mapping of Objects -> index for this thread.
405 thread->wait_objects_index[object->GetObjectId()] = static_cast<int>(i);
406 object->AddWaitingThread(thread); 396 object->AddWaitingThread(thread);
407 } 397 }
408 398
399 thread->wait_objects = std::move(objects);
400
409 // Note: If no handles and no timeout were given, then the thread will deadlock, this is 401 // Note: If no handles and no timeout were given, then the thread will deadlock, this is
410 // consistent with hardware behavior. 402 // consistent with hardware behavior.
411 403