mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25: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
|
// Check if there's any thread waiting on this event
|
||||||
if (event->waitlist != 0) {
|
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
|
|
||||||
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);
|
wakeupAllThreads(event->waitlist, handle);
|
||||||
event->waitlist = 0; // No threads waiting;
|
event->waitlist = 0; // No threads waiting;
|
||||||
|
|
||||||
|
if (event->resetType == ResetType::OneShot) {
|
||||||
|
event->fired = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must reschedule our threads if we signalled one. Some games such as FE: Awakening rely on this
|
rescheduleThreads();
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,11 @@ void Kernel::sendSyncRequest() {
|
||||||
u32 messagePointer = getTLSPointer() + 0x80; // The message is stored starting at TLS+0x80
|
u32 messagePointer = getTLSPointer() + 0x80; // The message is stored starting at TLS+0x80
|
||||||
logSVC("SendSyncRequest(session handle = %X)\n", handle);
|
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
|
// The sync request is being sent at a service rather than whatever port, so have the service manager intercept it
|
||||||
if (KernelHandles::isServiceHandle(handle)) {
|
if (KernelHandles::isServiceHandle(handle)) {
|
||||||
// The service call might cause a reschedule and change threads. Hence, set r0 before executing the service call
|
// 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 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) {
|
if (moo->lockCount == 0) {
|
||||||
moo->locked = false;
|
moo->locked = false;
|
||||||
|
|
||||||
if (moo->waitlist != 0) {
|
if (moo->waitlist != 0) {
|
||||||
int index = wakeupOneThread(moo->waitlist, moo->handle); // Wake up one thread and get its index
|
int index = wakeupOneThread(moo->waitlist, moo->handle); // Wake up one thread and get its index
|
||||||
moo->waitlist ^= (1ull << index); // Remove thread from waitlist
|
moo->waitlist ^= (1ull << index); // Remove thread from waitlist
|
||||||
|
@ -338,10 +339,20 @@ void Kernel::wakeupAllThreads(u64 waitlist, Handle handle) {
|
||||||
void Kernel::sleepThread(s64 ns) {
|
void Kernel::sleepThread(s64 ns) {
|
||||||
if (ns < 0) {
|
if (ns < 0) {
|
||||||
Helpers::panic("Sleeping a thread for a negative amount of ns");
|
Helpers::panic("Sleeping a thread for a negative amount of ns");
|
||||||
} else if (ns == 0) { // Used when we want to force a thread switch
|
} else if (ns == 0) {
|
||||||
requireReschedule();
|
// TODO: This is garbage, absolutely not getting merged
|
||||||
} else { // If we're sleeping for > 0 ns
|
|
||||||
Thread& t = threads[currentThreadIndex];
|
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.status = ThreadStatus::WaitSleep;
|
||||||
t.waitingNanoseconds = ns;
|
t.waitingNanoseconds = ns;
|
||||||
t.sleepTick = cpu.getTicks();
|
t.sleepTick = cpu.getTicks();
|
||||||
|
|
Loading…
Add table
Reference in a new issue