mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 07:05:40 +12:00
More threading fixes
This commit is contained in:
parent
7047bf6ec8
commit
65de2637ae
3 changed files with 24 additions and 15 deletions
|
@ -35,22 +35,15 @@ bool Kernel::signalEvent(Handle handle) {
|
|||
|
||||
// Check if there's any thread waiting on this event
|
||||
if (event->waitlist != 0) {
|
||||
// One-shot events get cleared once they are acquired by some thread and only wake up 1 thread at a time
|
||||
wakeupAllThreads(event->waitlist, handle);
|
||||
event->waitlist = 0; // No threads waiting;
|
||||
|
||||
if (event->resetType == ResetType::OneShot) {
|
||||
int index = wakeupOneThread(event->waitlist, handle); // Wake up one thread with the highest priority
|
||||
event->waitlist ^= (1ull << index); // Remove thread from waitlist
|
||||
event->fired = false;
|
||||
} else {
|
||||
wakeupAllThreads(event->waitlist, handle);
|
||||
event->waitlist = 0; // No threads waiting;
|
||||
}
|
||||
|
||||
// We must reschedule our threads if we signalled one. Some games such as FE: Awakening rely on this
|
||||
// If this does not happen, we can have phenomena such as a thread waiting up a higher priority thread,
|
||||
// and the higher priority thread just never running
|
||||
requireReschedule();
|
||||
}
|
||||
|
||||
|
||||
rescheduleThreads();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,11 @@ void Kernel::sendSyncRequest() {
|
|||
u32 messagePointer = getTLSPointer() + 0x80; // The message is stored starting at TLS+0x80
|
||||
logSVC("SendSyncRequest(session handle = %X)\n", handle);
|
||||
|
||||
// Service calls via SendSyncRequest and file access needs to put the caller to sleep for a given amount of time
|
||||
// To make sure that the other threads don't get starved. Various games rely on this (including Sonic Boom: Shattering Crystal it seems)
|
||||
constexpr u64 syncRequestDelayNs = 39000;
|
||||
sleepThread(syncRequestDelayNs);
|
||||
|
||||
// The sync request is being sent at a service rather than whatever port, so have the service manager intercept it
|
||||
if (KernelHandles::isServiceHandle(handle)) {
|
||||
// The service call might cause a reschedule and change threads. Hence, set r0 before executing the service call
|
||||
|
|
|
@ -178,6 +178,7 @@ void Kernel::releaseMutex(Mutex* moo) {
|
|||
// If the lock count reached 0 then the thread no longer owns the mootex and it can be given to a new one
|
||||
if (moo->lockCount == 0) {
|
||||
moo->locked = false;
|
||||
|
||||
if (moo->waitlist != 0) {
|
||||
int index = wakeupOneThread(moo->waitlist, moo->handle); // Wake up one thread and get its index
|
||||
moo->waitlist ^= (1ull << index); // Remove thread from waitlist
|
||||
|
@ -338,10 +339,20 @@ void Kernel::wakeupAllThreads(u64 waitlist, Handle handle) {
|
|||
void Kernel::sleepThread(s64 ns) {
|
||||
if (ns < 0) {
|
||||
Helpers::panic("Sleeping a thread for a negative amount of ns");
|
||||
} else if (ns == 0) { // Used when we want to force a thread switch
|
||||
requireReschedule();
|
||||
} else { // If we're sleeping for > 0 ns
|
||||
} else if (ns == 0) {
|
||||
// TODO: This is garbage, absolutely not getting merged
|
||||
Thread& t = threads[currentThreadIndex];
|
||||
|
||||
t.status = ThreadStatus::Dead;
|
||||
auto nextThreadIndex = getNextThread();
|
||||
t.status = ThreadStatus::Ready;
|
||||
|
||||
if (nextThreadIndex.has_value()) {
|
||||
switchThread(nextThreadIndex.value());
|
||||
}
|
||||
} else { // If we're sleeping for >= 0 ns
|
||||
Thread& t = threads[currentThreadIndex];
|
||||
|
||||
t.status = ThreadStatus::WaitSleep;
|
||||
t.waitingNanoseconds = ns;
|
||||
t.sleepTick = cpu.getTicks();
|
||||
|
|
Loading…
Add table
Reference in a new issue