Unschedule threads properly...

...instead of using a shitty yield when opening the Rosalina menu
This commit is contained in:
TuxSH
2017-06-14 19:35:03 +02:00
parent 24de7c5272
commit 3d534c9a81
15 changed files with 229 additions and 30 deletions

View File

@@ -74,7 +74,7 @@ s32 (*kernelToUsrStrncpy)(char *dst, const char *src, u32 len);
void (*svcFallbackHandler)(u8 svcId);
void (*kernelpanic)(void);
void (*PostprocessSvc)(void);
void (*officialPostProcessSvc)(void);
Result (*SignalDebugEvent)(DebugEventType type, u32 info, ...);
@@ -91,6 +91,7 @@ bool *isDevUnit;
vu8 *configPage;
u32 kernelVersion;
FcramLayout fcramLayout;
KCoreContext *coreCtxs;
void *originalHandlers[8] = {NULL};
@@ -107,5 +108,5 @@ void (*coreBarrier)(void);
CfwInfo cfwInfo;
u32 rosalinaState;
vu32 rosalinaState;
bool hasStartedRosalinaNetworkFuncsOnce;

View File

@@ -96,6 +96,7 @@ void configHook(vu8 *cfgPage)
*isDevUnit = true; // enable debug features
}
void wat(u32 a, ...);
static void findUsefulSymbols(void)
{
u32 *off;
@@ -111,7 +112,7 @@ static void findUsefulSymbols(void)
for(off = (u32 *)originalHandlers[2]; *off != 0xE1A00009; off++);
svcFallbackHandler = (void (*)(u8))decodeARMBranch(off + 1);
for(; *off != 0xE92D000F; off++);
PostprocessSvc = (void (*)(void))decodeARMBranch(off + 1);
officialPostProcessSvc = (void (*)(void))decodeARMBranch(off + 1);
KProcessHandleTable__ToKProcess = (KProcess * (*)(KProcessHandleTable *, Handle))decodeARMBranch(5 + (u32 *)officialSVCs[0x76]);
@@ -135,7 +136,7 @@ static void findUsefulSymbols(void)
for(off = (u32 *)officialSVCs[0x19]; *off != 0xE1A04005; off++);
KEvent__Clear = (Result (*)(KEvent *))decodeARMBranch(off + 1);
for(off = (u32 *)KEvent__Clear; *off != 0xE8BD8070; off++)
for(off = (u32 *)KEvent__Clear; *off != 0xE8BD8070; off++);
synchronizationMutex = *(KObjectMutex **)(off + 1);
for(off = (u32 *)officialSVCs[0x24]; *off != 0xE59F004C; off++);
@@ -247,7 +248,7 @@ static void findUsefulSymbols(void)
}
}
void main(FcramLayout *layout)
void main(FcramLayout *layout, KCoreContext *ctxs)
{
struct KExtParameters *p = &kExtParameters;
u32 TTBCR_;
@@ -255,8 +256,9 @@ void main(FcramLayout *layout)
layout->systemSize -= __end__ - __start__;
fcramLayout = *layout;
coreCtxs = ctxs;
__asm__ volatile("mrc p15, 0, %0, c2, c0, 2" : "=r"(TTBCR_));
__asm__ __volatile__("mrc p15, 0, %0, c2, c0, 2" : "=r"(TTBCR_));
TTBCR = TTBCR_;
isN3DS = getNumberOfCores() == 4;
memcpy(L1MMUTableAddrs, (const void *)p->L1MMUTableAddrs, 16);
@@ -275,4 +277,5 @@ void main(FcramLayout *layout)
rosalinaState = 0;
hasStartedRosalinaNetworkFuncsOnce = false;
//wat(0xAA, criticalSectionLock);
}

View File

@@ -41,6 +41,7 @@ _start:
.word kExtParameters
.word 1 @ enableUserExceptionHandlersForCPUExc
b KThread__DebugReschedule
start:
@ Only core0 executes this, the other cores are running coreBarrier
@@ -50,6 +51,7 @@ start:
push {r0-r12, lr}
sub r0, r4, #8
sub r1, r8, #0x8000
bl main
pop {r0-r12, pc}

View File

@@ -25,6 +25,7 @@
*/
#include "memory.h"
#include "synchronization.h"
#include "svc.h"
#include "svc/ControlMemory.h"
#include "svc/GetProcessInfo.h"
@@ -47,24 +48,11 @@
void *officialSVCs[0x7E] = {NULL};
static inline void yieldDuringRosalinaMenu(void)
{
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
u64 titleId = codeSetOfProcess(currentProcess)->titleId;
u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)titleId;
while((rosalinaState & 1) && idOfProcess(currentProcess) >= nbSection0Modules &&
(highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02))))
SleepThread(25 * 1000 * 1000LL);
}
void signalSvcEntry(u8 *pageEnd)
{
u32 svcId = (u32) *(u8 *)(pageEnd - 0xB5);
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
yieldDuringRosalinaMenu();
if(svcId == 0xFE)
svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x3FFFFFFF. We don't support catching svcIds >= 0x100 atm either
@@ -78,8 +66,6 @@ void signalSvcReturn(u8 *pageEnd)
u32 svcId = (u32) *(u8 *)(pageEnd - 0xB5);
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
yieldDuringRosalinaMenu();
if(svcId == 0xFE)
svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x1FFFFFFF. We don't support catching svcIds >= 0x100 atm either
@@ -88,6 +74,15 @@ void signalSvcReturn(u8 *pageEnd)
SignalDebugEvent(DBGEVENT_OUTPUT_STRING, 0xFFFFFFFF, svcId);
}
void postprocessSvc(void)
{
KThread *currentThread = currentCoreContext->objectContext.currentThread;
if(!currentThread->shallTerminate && rosalinaThreadLockPredicate(currentThread))
rosalinaRescheduleThread(currentThread, true);
officialPostProcessSvc();
}
static bool doingVeryShittyPmResLimitWorkaround = false; // I feel dirty
void *svcHook(u8 *pageEnd)

View File

@@ -107,6 +107,11 @@ Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
if(rosalinaState & 2)
hasStartedRosalinaNetworkFuncsOnce = true;
if(rosalinaState & 1)
rosalinaLockAllThreads();
else if(varg1 & 1)
rosalinaUnlockAllThreads();
break;
}
case 0x10001:

View File

@@ -113,9 +113,7 @@ svcHandler:
push {r0-r7, r12, lr}
push {r0-r3}
ldr r0, =PostprocessSvc
ldr r0, [r0]
blx r0
bl postprocessSvc
pop {r0-r3}
ldrb lr, [sp, #0x58+0] @ page end - 0xb8 + 0: scheduling flags

View File

@@ -27,6 +27,7 @@
#include "synchronization.h"
#include "utils.h"
#include "kernel.h"
#include "globals.h"
extern SGI0Handler_t SGI0Handler;
@@ -36,6 +37,126 @@ void executeFunctionOnCores(SGI0Handler_t handler, u8 targetList, u8 targetListF
SGI0Handler = handler;
if(targetListFilter == 0 && (targetListFilter & (1 << coreID)) != 0)
__asm__ volatile("cpsie i"); // make sure interrupts aren't masked
__enable_irq(); // make sure interrupts aren't masked
MPCORE_GID_SGI = (targetListFilter << 24) | (targetList << 16) | 0;
}
void KScheduler__TriggerCrossCoreInterrupt(KScheduler *this)
{
this->triggerCrossCoreInterrupt = false;
for(s16 i = 0; i < (s16)getNumberOfCores(); i++)
{
if(this->coreNumber != i)
MPCORE_GID_SGI = (1 << (16 + i)) | 8;
}
}
void KThread__DebugReschedule(KThread *this, bool lock)
{
KRecursiveLock__Lock(criticalSectionLock);
u32 oldSchedulingMask = this->schedulingMask;
if(lock) // the original k11 function discards the other flags
this->schedulingMask |= 0x80;
else
this->schedulingMask &= ~0x80;
KScheduler__AdjustThread(currentCoreContext->objectContext.currentScheduler, this, oldSchedulingMask);
KRecursiveLock__Unlock(criticalSectionLock);
}
bool rosalinaThreadLockPredicate(KThread *thread)
{
KProcess *process = thread->ownerProcess;
if(process == NULL)
return false;
u64 titleId = codeSetOfProcess(process)->titleId;
u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)titleId;
return
((rosalinaState & 1) && idOfProcess(process) >= nbSection0Modules &&
(highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02))));
}
void rosalinaRescheduleThread(KThread *thread, bool lock)
{
KRecursiveLock__Lock(criticalSectionLock);
u32 oldSchedulingMask = thread->schedulingMask;
if(lock)
thread->schedulingMask |= 0x40;
else
thread->schedulingMask &= ~0x40;
KScheduler__AdjustThread(currentCoreContext->objectContext.currentScheduler, thread, oldSchedulingMask);
KRecursiveLock__Unlock(criticalSectionLock);
}
void rosalinaLockThread(KThread *thread)
{
KThread *syncThread = synchronizationMutex->owner;
s8 *eotc = (s8 *)thread->endOfThreadContext;
if(syncThread == NULL || syncThread != thread)
rosalinaRescheduleThread(thread, true);
}
void rosalinaLockAllThreads(void)
{
bool currentThreadsFound = false;
KRecursiveLock__Lock(criticalSectionLock);
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
KThread *thread = (KThread *)node->key;
if(!rosalinaThreadLockPredicate(thread))
continue;
if(thread == coreCtxs[thread->coreId].objectContext.currentThread)
currentThreadsFound = true;
else
rosalinaLockThread(thread);
}
if(currentThreadsFound)
{
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
KThread *thread = (KThread *)node->key;
if(!rosalinaThreadLockPredicate(thread))
continue;
if(!(thread->schedulingMask & 0x40))
{
rosalinaLockThread(thread);
KRecursiveLock__Lock(criticalSectionLock);
if(thread->coreId != getCurrentCoreID())
{
u32 cpsr = __get_cpsr();
__disable_irq();
coreCtxs[thread->coreId].objectContext.currentScheduler->triggerCrossCoreInterrupt = true;
currentCoreContext->objectContext.currentScheduler->triggerCrossCoreInterrupt = true;
__set_cpsr_cx(cpsr);
}
KRecursiveLock__Unlock(criticalSectionLock);
}
}
KScheduler__TriggerCrossCoreInterrupt(currentCoreContext->objectContext.currentScheduler);
}
KRecursiveLock__Unlock(criticalSectionLock);
}
void rosalinaUnlockAllThreads(void)
{
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
KThread *thread = (KThread *)node->key;
s8 *eotc = (s8 *)thread->endOfThreadContext;
if((thread->schedulingMask & 0xF) == 2) // thread is terminating
continue;
if(thread->schedulingMask & 0x40)
rosalinaRescheduleThread(thread, false);
}
}

View File

@@ -118,6 +118,11 @@ safecpy:
_safecpy_end:
.global wat
.type wat, %function
wat:
bkpt 1
bx lr
.section .rodata
.global safecpy_sz