- Each core has its own KScheduler instance.
Each KObject manages a list of threads that are waiting on it. This list is iterated over each time the KObject is signaled.
The KObject will try to retrieve the KThread with the highest priority from this list, check if it is ready to run (See KThread waitlist), and append it to the scheduler's queue if it is ready.
This awakening operation is performed for every KThread that is ready to run.
Each KThread has a list of objects that it is waiting on as a result of a WaitSynchronizationN call. A KThread will only be added to the scheduler's queue if all of the objects in this list are signalled and ready.
This list is reset during a WaitSynchronizationN call, and is unused otherwise.
When called with Timeout = 0, WaitSynchronization1 does not cause a reschedule if the KObject is already signalled, it only acquires it and returns control to the caller thread.
On the other hand, if Timeout is 0 but the KObject is not ready, it will immediately return error code 0x9401BFE
and return control to the caller thread.
If the KObject is not ready and the Timeout is greater than 0, WaitSynchronization1 will add the KThread to the KObject's waitlist and suspend the thread, to be awoken later by the KObject during the signalling procedure.
If the KObject is ready and Timeout is not 0, the KObject is acquired and no reschedule happens.
The KThread waitlist is left untouched by this function.
WaitSynchronizationN has two divergent behaviors, it either waits until all the objects are ready, or waits until one of the objects are ready.
WaitSynchronizationN will clear the KThread's waitlist and add the KThread to each of the KObjects' waitlist regardless of the wait mode used. However, only wait_all = true will re-populate the KThread's waitlist with the KObjects.
In this mode, WaitSynchronizationN will iterate over the KObjects in order and acquire the first one that is ready.
If the specified Timeout is 0, no rescheduling will be performed and error code 0x9401BFE
will be returned in case that no KObjects were available.
If no Timeout was specified (-1) and an object was available, said object will be acquired and no rescheduling will be performed.
However, if a Timeout value greater than 0 was given, then the thread will be suspended for up to the specified amount of time if no KObjects were ready.
In this mode, the kernel will first check if all the objects are ready before acquiring them all.
If the specified Timeout is 0, no rescheduling will be performed and error code 0x9401BFE
will be returned in case that not all the KObjects were available.
If the KThread couldn't acquire all objects, and an unknown field in KThread is true (offset 0x36), then the thread is descheduled and added to the scheduler's queue again (Presumably to force a context switch?), and the WaitSynchronizationN call returns 0xD920060D
If the aforementioned KThread field (offset 0x36) is false, WaitSynchronizationN will add the thread to each object's waitlist and add all objects to the thread's waitlist. The thread will be suspended with the specified timeout (if it is greater than zero).
There is some weird behavior in this last case, after the thread is suspended, WaitSynchronizationN will remove the thread from each of the objects' waitlist, and clear the thread's waitlist again. It is speculated that something akin to a coroutine return occurs somewhere between putting the thread to sleep, and running this code, as it appears to be the code that sets the return value of WaitSynchronizationN.
TODO