mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 17:40:05 +00:00
Kernel: Remove Thread::wait_objects_index and use wait_objects to hold all the objects that a thread is waiting on.
This commit is contained in:
parent
cef5f45de2
commit
fd95b6ee26
@ -55,10 +55,16 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
|
|||||||
if (ShouldWait(thread.get()))
|
if (ShouldWait(thread.get()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
|
// A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or
|
||||||
|
// in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready.
|
||||||
|
bool ready_to_run = true;
|
||||||
|
if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) {
|
||||||
|
ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
|
||||||
[&thread](const SharedPtr<WaitObject>& object) {
|
[&thread](const SharedPtr<WaitObject>& object) {
|
||||||
return object->ShouldWait(thread.get());
|
return object->ShouldWait(thread.get());
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (ready_to_run) {
|
if (ready_to_run) {
|
||||||
candidate = thread.get();
|
candidate = thread.get();
|
||||||
candidate_priority = thread->current_priority;
|
candidate_priority = thread->current_priority;
|
||||||
|
@ -579,6 +579,11 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
|
|||||||
context.cpu_registers[1] = output;
|
context.cpu_registers[1] = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 Thread::GetWaitObjectIndex(WaitObject* object) const {
|
||||||
|
auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object);
|
||||||
|
return std::distance(match, wait_objects.rend()) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ThreadingInit() {
|
void ThreadingInit() {
|
||||||
|
@ -135,13 +135,14 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the index that this particular object occupies in the list of objects
|
* Retrieves the index that this particular object occupies in the list of objects
|
||||||
* that the thread passed to WaitSynchronizationN.
|
* that the thread passed to WaitSynchronizationN, starting the search from the last element.
|
||||||
* It is used to set the output value of WaitSynchronizationN when the thread is awakened.
|
* It is used to set the output value of WaitSynchronizationN when the thread is awakened.
|
||||||
|
* When a thread wakes up due to an object signal, the kernel will use the index of the last
|
||||||
|
* matching object in the wait objects list in case of having multiple instances of the same
|
||||||
|
* object in the list.
|
||||||
* @param object Object to query the index of.
|
* @param object Object to query the index of.
|
||||||
*/
|
*/
|
||||||
s32 GetWaitObjectIndex(const WaitObject* object) const {
|
s32 GetWaitObjectIndex(WaitObject* object) const;
|
||||||
return wait_objects_index.at(object->GetObjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops a thread, invalidating it from further use
|
* Stops a thread, invalidating it from further use
|
||||||
@ -190,13 +191,10 @@ public:
|
|||||||
|
|
||||||
SharedPtr<Process> owner_process; ///< Process that owns this thread
|
SharedPtr<Process> owner_process; ///< Process that owns this thread
|
||||||
|
|
||||||
/// Objects that the thread is waiting on.
|
/// Objects that the thread is waiting on, in the same order as they were
|
||||||
/// This is only populated when the thread should wait for all the objects to become ready.
|
// passed to WaitSynchronization1/N.
|
||||||
std::vector<SharedPtr<WaitObject>> wait_objects;
|
std::vector<SharedPtr<WaitObject>> wait_objects;
|
||||||
|
|
||||||
/// Mapping of Object ids to their position in the last waitlist that this object waited on.
|
|
||||||
boost::container::flat_map<int, s32> wait_objects_index;
|
|
||||||
|
|
||||||
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
|
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
|
||||||
|
|
||||||
/// True if the WaitSynchronizationN output parameter should be set on thread wakeup.
|
/// True if the WaitSynchronizationN output parameter should be set on thread wakeup.
|
||||||
|
@ -277,6 +277,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
|
|||||||
if (nano_seconds == 0)
|
if (nano_seconds == 0)
|
||||||
return ERR_SYNC_TIMEOUT;
|
return ERR_SYNC_TIMEOUT;
|
||||||
|
|
||||||
|
thread->wait_objects = {object};
|
||||||
object->AddWaitingThread(thread);
|
object->AddWaitingThread(thread);
|
||||||
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
|
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
|
||||||
|
|
||||||
@ -325,11 +326,6 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
|
|||||||
objects[i] = object;
|
objects[i] = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the mapping of wait object indices.
|
|
||||||
// We don't want any lingering state in this map.
|
|
||||||
// It will be repopulated later in the wait_all = false case.
|
|
||||||
thread->wait_objects_index.clear();
|
|
||||||
|
|
||||||
if (wait_all) {
|
if (wait_all) {
|
||||||
bool all_available =
|
bool all_available =
|
||||||
std::all_of(objects.begin(), objects.end(),
|
std::all_of(objects.begin(), objects.end(),
|
||||||
@ -358,7 +354,6 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
|
|||||||
object->AddWaitingThread(thread);
|
object->AddWaitingThread(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the thread's waitlist to the list of objects passed to WaitSynchronizationN
|
|
||||||
thread->wait_objects = std::move(objects);
|
thread->wait_objects = std::move(objects);
|
||||||
|
|
||||||
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
// 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
|
|||||||
// Put the thread to sleep
|
// Put the thread to sleep
|
||||||
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
|
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
|
||||||
|
|
||||||
// Clear the thread's waitlist, we won't use it for wait_all = false
|
|
||||||
thread->wait_objects.clear();
|
|
||||||
|
|
||||||
// Add the thread to each of the objects' waiting threads.
|
// Add the thread to each of the objects' waiting threads.
|
||||||
for (size_t i = 0; i < objects.size(); ++i) {
|
for (size_t i = 0; i < objects.size(); ++i) {
|
||||||
Kernel::WaitObject* object = objects[i].get();
|
Kernel::WaitObject* object = objects[i].get();
|
||||||
// Set the index of this object in the mapping of Objects -> index for this thread.
|
|
||||||
thread->wait_objects_index[object->GetObjectId()] = static_cast<int>(i);
|
|
||||||
object->AddWaitingThread(thread);
|
object->AddWaitingThread(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread->wait_objects = std::move(objects);
|
||||||
|
|
||||||
// Note: If no handles and no timeout were given, then the thread will deadlock, this is
|
// Note: If no handles and no timeout were given, then the thread will deadlock, this is
|
||||||
// consistent with hardware behavior.
|
// consistent with hardware behavior.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user