-
-
Save Subv/66febe55886eeb052d967c81cf7c41d8 to your computer and use it in GitHub Desktop.
scheduler stuff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// See next file for the only caller of this func | |
void __fastcall configurePreemption(u32 cpuTimeResLimit) | |
{ | |
s64 v2; // r8@9 | |
s64 v3; // r8@11 | |
KThread *v4; // r4@13 | |
KThread *v5; // r2@14 | |
KThreadLinkedList *v6; // r3@15 | |
KRecursiveLock::Lock(&g_criticalSectionLock); | |
if ( useOtherPreemptionMode == 1 ) | |
{ | |
if ( cpuTimeResLimit ) | |
{ | |
if ( !byte_FFF31545 ) | |
{ | |
byte_FFF31545 = 1; | |
byte_FFF31544 = 1; | |
qword_FFF31548 = KTimerAndWDTManager::GetSystemTick(&TimerAndWDTManager) / 0x6646CC + 2; | |
v2 = 0x6646CC * qword_FFF31548; | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer(&TimerAndWDTManager, &stru_FFF31530, v2); | |
KRecursiveLock::LocalUnlock(&TimerAndWDTManager.recursiveLock); | |
} | |
} | |
else | |
{ | |
KTimerAndWDTManager::ClearTimerInterruptAndUnregisterInterruptEvent(&TimerAndWDTManager, &stru_FFF31530); | |
byte_FFF31545 = 0; | |
} | |
} | |
else if ( cpuTimeResLimit ) | |
{ | |
stru_FFF31520.nLimitedTicks = 0x82E9F * cpuTimeResLimit / 100;// 0x82E9F ticks = 2 ms approx | |
stru_FFF31520.timer = 0; | |
if ( !byte_FFF31515 ) // are we preempting | |
{ | |
byte_FFF31515 = 1; | |
byte_FFF31514 = 1; | |
qword_FFF31518 = KTimerAndWDTManager::GetSystemTick(&TimerAndWDTManager) / 0x82E9F + 2; | |
v3 = 0x82E9F * qword_FFF31518; // next 2ms period | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer( | |
&TimerAndWDTManager, | |
(KTimeableInterruptEvent *)&off_FFF31500, | |
v3); | |
KRecursiveLock::LocalUnlock(&TimerAndWDTManager.recursiveLock); | |
} | |
} | |
else | |
{ | |
KTimerAndWDTManager::ClearTimerInterruptAndUnregisterInterruptEvent( | |
&TimerAndWDTManager, | |
(KTimeableInterruptEvent *)&off_FFF31500); | |
byte_FFF31515 = 0; | |
} | |
while ( dword_FFF2E0AC ) | |
{ | |
v4 = dword_FFF2E0AC; | |
if ( dword_FFF2E0AC ) | |
{ | |
v5 = dword_FFF2E0AC->threadListNode.next; | |
if ( v5 ) | |
v6 = (KThreadLinkedList *)&v5->threadListNode; | |
else | |
v6 = &preemptedThreads; | |
dword_FFF2E0AC = dword_FFF2E0AC->threadListNode.next; | |
v6->first = 0; | |
v4->preemptionList = 0; | |
KThread::Reschedule(v4, 1u); | |
v4->preemptionList = 0; | |
} | |
} | |
dword_FFF2E094 = 1; | |
KRecursiveLock::Unlock(&g_criticalSectionLock); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void __fastcall sub_FFF283EC(int this) | |
{ | |
int v2; // r5@1 | |
int v3; // r6@1 | |
unsigned int v4; // r1@2 | |
int v5; // r0@3 | |
__int64 v6; // r2@3 | |
__int64 v7; // kr08_8@3 | |
KThread *v8; // r7@5 | |
KThread *v9; // r2@6 | |
KThreadLinkedList *v10; // r3@7 | |
KThread *v11; // r7@13 | |
KThread *v12; // r2@14 | |
KThreadLinkedList *v13; // r3@15 | |
// at +0x20 of this struct there's a KPreemptionTimer | |
v2 = 0x82E9F | |
* *(_DWORD *)(this + 0x18); // next 2ms period | |
v3 = (0x82E9F | |
* (unsigned __int64)*(_DWORD *)(this + 0x18) >> 32) + 0x82E9F * *(_DWORD *)(this + 0x1C); | |
if ( *(_BYTE *)(this + 0x14) ) | |
{ | |
v4 = *(_DWORD *)(this + 0x24); // wdt timer | |
// 8 microseconds? | |
if ( v4 < 1072 ) | |
{ | |
KRecursiveLock::Lock(&g_criticalSectionLock); | |
while ( dword_FFF2E0AC ) | |
{ // un-preempt, reschedule | |
v11 = dword_FFF2E0AC; | |
if ( dword_FFF2E0AC ) | |
{ | |
v12 = dword_FFF2E0AC->threadListNode.next; | |
if ( v12 ) | |
v13 = (KThreadLinkedList *)&v12->threadListNode; | |
else | |
v13 = &preemptedThreads; | |
dword_FFF2E0AC = dword_FFF2E0AC->threadListNode.next; | |
v13->first = 0; | |
v11->preemptionList = 0; | |
KThread::Reschedule(v11, 1u); | |
v11->preemptionList = 0; | |
} | |
} | |
dword_FFF2E094 = 1; | |
KRecursiveLock::Unlock(&g_criticalSectionLock); | |
*(_BYTE *)(this + 0x14) = 0; | |
} | |
else | |
{ | |
v5 = *(_DWORD *)(this + 0x20); | |
LODWORD(v6) = 2 * v4; | |
HIDWORD(v6) = v3 + __CFADD__(v5, v2); // nlimitedticks? | |
v7 = (unsigned int)(v5 + v2) + v6; | |
v2 = (int)&unk_FFF7D161 + v7; | |
v3 = HIDWORD(v7) - !__CFADD__((_DWORD)v7, &unk_FFF7D161); | |
*(_DWORD *)(this + 0x24) = 0; | |
} | |
} | |
else | |
{ | |
KRecursiveLock::Lock(&g_criticalSectionLock); | |
while ( dword_FFF2E0AC ) | |
{ | |
v8 = dword_FFF2E0AC; | |
if ( dword_FFF2E0AC ) | |
{ | |
v9 = dword_FFF2E0AC->threadListNode.next;// unpreempt, reschedule | |
if ( v9 ) | |
v10 = (KThreadLinkedList *)&v9->threadListNode; | |
else | |
v10 = &preemptedThreads; | |
dword_FFF2E0AC = dword_FFF2E0AC->threadListNode.next; | |
v10->first = 0; | |
v8->preemptionList = 0; | |
KThread::Reschedule(v8, 1u); | |
v8->preemptionList = 0; | |
} | |
} | |
dword_FFF2E094 = 0; | |
KRecursiveLock::Unlock(&g_criticalSectionLock); | |
*(_DWORD *)(this + 0x24) = 0; | |
v3 = (__PAIR__(v3, v2) + (unsigned __int64)*(_DWORD *)(this + 0x20)) >> 32; | |
v2 += *(_DWORD *)(this + 0x20); | |
++*(_QWORD *)(this + 0x18); | |
*(_BYTE *)(this + 0x14) = 1; | |
} | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer( | |
&TimerAndWDTManager, | |
(KTimeableInterruptEvent *)this, | |
__PAIR__(v3, v2)); | |
KRecursiveLock::LocalUnlock(&TimerAndWDTManager.recursiveLock); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Result __fastcall KResourceLimit::SetMaxLimit(KResourceLimit *resLimit, LimitableResource resType, u32 resCount) | |
{ | |
signed int v3; // r10@0 | |
KResourceLimit *v5; // r6@1 | |
KObjectMutex *v6; // r0@1 | |
KObjectMutex *v8; // r4@1 | |
unsigned int v9; // r2@1 | |
bool v10; // zf@1 | |
unsigned int v11; // r3@2 | |
Result result; // r0@8 | |
unsigned int v13; // r2@11 | |
bool v14; // zf@11 | |
unsigned int v15; // r3@12 | |
signed int v16; // r1@18 | |
int *v17; // r0@18 | |
KResourceLimit *v18; // r8@19 | |
KLinkedListNode *threadNode; // r4@24 | |
KProcess *v21; // r1@25 | |
signed int v22; // r0@30 | |
KPreemptionTimer *v23; // r0@31 | |
int v24; // r0@40 | |
KPreemptionTimer *v25; // ST04_4@42 | |
KThread *threadInList; // [sp+0h] [bp-30h]@30 MAPDST | |
v5 = resLimit; | |
v6 = &resLimit->objMutex; | |
v8 = v6; | |
v9 = __ldrex((unsigned int *)v6); | |
v10 = v9 == 0; | |
if ( v9 ) | |
v11 = __strex(v9, (unsigned int *)v6); | |
else | |
v11 = __strex((unsigned int)currentCoreCtx.objectContext.currentThread, (unsigned int *)v6); | |
if ( !v9 ) | |
v10 = v11 == 0; | |
if ( !v10 ) | |
KObjectMutex::TryAcquireMutex(v6); | |
__mcr(15, 0, 0, 7, 10, 5); | |
v5->maxResources[resType] = resCount; | |
result = (Result)v8; | |
__mcr(15, 0, 0, 7, 10, 5); | |
v8->owner = 0; | |
if ( v8->tryAcquireCounter > 0 ) | |
KObjectMutex::ErrorOcurred(); | |
if ( resType == LIMITABLE_RESOURCE_MAX_CPUTIME ) | |
{ | |
v13 = __ldrex((unsigned int *)&threadList.mutex); | |
v14 = v13 == 0; | |
if ( v13 ) | |
v15 = __strex(v13, (unsigned int *)&threadList.mutex); | |
else | |
v15 = __strex((unsigned int)currentCoreCtx.objectContext.currentThread, (unsigned int *)&threadList.mutex); | |
if ( !v13 ) | |
v14 = v15 == 0; | |
if ( !v14 ) | |
KObjectMutex::TryAcquireMutex(&threadList.mutex); | |
__mcr(15, 0, 0, 7, 10, 5); | |
KRecursiveLock::Lock(&g_criticalSectionLock); | |
v17 = &dword_FFF2E08C; | |
if ( resCount >= 90 ) | |
{ | |
if ( resCount == 1000 ) | |
{ | |
off_FFF2E090 = v5; | |
v16 = 1; | |
} | |
else | |
{ | |
v17 = (int *)2; | |
} | |
if ( resCount == 1000 ) | |
v5->preemptionTimer.nLimitedTicks = v16; | |
else | |
v5->preemptionTimer.nLimitedTicks = (u32)v17; | |
} | |
else | |
{ | |
v5->preemptionTimer.nLimitedTicks = 0; | |
v5->preemptionTimer.wantedDuration = 0x6646CC * resCount / 200; | |
v18 = off_FFF2E090; | |
if ( off_FFF2E090 ) | |
{ | |
if ( resCount ) | |
v3 = 1; | |
if ( !resCount ) | |
v3 = 0; | |
off_FFF2E090->preemptionTimer.wantedDuration = 0x6646CC * (90 - resCount) / 200; | |
LOBYTE(dword_FFF2E08C) = v3; | |
for ( threadNode = threadList.list.nodes.first; | |
(KLinkedListNodePair *)threadNode != &threadList.list.nodes; | |
threadNode = threadNode->next ) | |
{ | |
threadInList = (KThread *)threadNode->key; | |
v21 = threadInList->ownerProcess; | |
if ( v21 && v21->resourceLimits == v18 && (signed int)threadInList->basePriority > 0xF ) | |
{ | |
if ( v3 ) | |
{ | |
threadInList = (KThread *)threadNode->key; | |
v22 = v18->maxResources[LIMITABLE_RESOURCE_MAX_CPUTIME]; | |
if ( v22 < 10000 ) | |
{ | |
if ( v22 == 1000 ) | |
{ | |
KRecursiveLock::Lock(&g_criticalSectionLock); | |
v24 = (unsigned __int8)dword_FFF2E08C; | |
if ( (_BYTE)dword_FFF2E08C ) | |
v24 = (int)&v18->preemptionTimer; | |
v25 = (KPreemptionTimer *)v24; | |
KRecursiveLock::Unlock(&g_criticalSectionLock); | |
v23 = v25; | |
} | |
else | |
{ | |
v23 = &v18->preemptionTimer; | |
} | |
} | |
else | |
{ | |
v23 = 0; | |
} | |
threadInList->preemptionTimer = v23; | |
} | |
else | |
{ | |
threadInList->preemptionTimer = 0; | |
} | |
} | |
} | |
} | |
configurePreemption(resCount); | |
} | |
KRecursiveLock::Unlock(&g_criticalSectionLock); | |
result = (Result)&threadList.mutex; | |
__mcr(15, 0, 0, 7, 10, 5); | |
threadList.mutex.owner = 0; | |
if ( threadList.mutex.tryAcquireCounter > 0 ) | |
KObjectMutex::ErrorOcurred(); | |
} | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bool __fastcall KScheduler::ScheduleThreads(KScheduler *this, int reused_var) | |
{ | |
int v2; // r9@0 | |
KThread *v4; // r4@1 | |
volatile KThread *currentThread; // r8@1 | |
int v6; // r11@1 | |
KThread *v7; // r0@2 | |
signed int v8; // r0@8 | |
bool v9; // zf@10 | |
bool v10; // nf@10 | |
unsigned __int8 v11; // vf@10 | |
KObjectMutex *v12; // r0@16 | |
bool v13; // zf@16 | |
int v14; // r2@21 | |
bool v15; // zf@25 | |
int v16; // r2@33 | |
bool v17; // zf@37 | |
bool v18; // zf@46 | |
KPreemptionTimer *v19; // r0@51 | |
KPreemptionTimer *v20; // r0@58 | |
signed int v21; // r6@58 | |
KPreemptionTimer *v22; // r7@60 | |
u32 v23; // r1@61 | |
char *v24; // r2@62 | |
unsigned __int8 *v25; // r0@64 | |
unsigned int v26; // r2@65 | |
KThreadLinkedList *v27; // r6@67 | |
KThreadLinkedList *v28; // r2@68 | |
KThreadLinkedListNode v29; // r0@71 | |
KThreadLinkedList *v30; // r2@72 | |
int v31; // ST04_4@76 | |
unsigned int v32; // r5@76 | |
s64 v33; // kr08_8@76 | |
KRecursiveLock *v34; // r0@77 | |
KPreemptionTimer *v35; // r0@86 | |
unsigned __int8 *v36; // r0@90 | |
unsigned int v37; // r1@91 | |
bool v38; // zf@105 | |
KTimeableInterruptEvent *rofl; // [sp+0h] [bp-30h]@76 | |
v4 = (KThread *)reused_var; | |
currentThread = currentCoreCtx.objectContext.currentThread; | |
v6 = reused_var == 0; | |
if ( this->postInterruptReschedulingNeeded ) | |
{ | |
this->postInterruptReschedulingNeeded = 0; | |
v7 = currentCoreCtx.objectContext.currentSchedulableInterruptEventLinkedList->handlingKernelThread; | |
reused_var = v7->schedulingMask; | |
if ( !(reused_var & 0xF) ) | |
KThread::Reschedule(v7, 1u); | |
} | |
if ( this->listOfHandledThreads.last ) | |
KScheduler::ScheduleLastThread(this); | |
LABEL_6: | |
if ( v4 ) | |
goto LABEL_52; | |
while ( 1 ) | |
{ | |
reused_var = this->highPriorityThreadsBitfield; | |
do | |
{ | |
v8 = __clz(reused_var); | |
if ( v8 == 32 ) | |
v8 = __clz(this->lowPriorityThreadsBitfield) + 32; | |
v11 = __OFSUB__(v8, 63); | |
v9 = v8 == 63; | |
v10 = v8 - 63 < 0; | |
if ( v8 > 63 ) | |
v4 = this->schedulerThread; | |
else | |
v8 = (signed int)this + 8 * v8; | |
if ( (unsigned __int8)(v10 ^ v11) | v9 ) | |
v4 = *(KThread **)(v8 + 44); | |
} | |
while ( !v4 ); | |
v12 = v4->mutex; | |
v13 = v12 == 0; | |
if ( v12 ) | |
{ | |
v12 = (KObjectMutex *)v12->owner; | |
v13 = v12 == 0; | |
} | |
if ( !v13 ) | |
{ | |
if ( v12[14].owner == (KThread *)this->coreNumber ) | |
{ | |
if ( (v12[6].tryAcquireCounter & 0xF) == 1 ) | |
goto LABEL_54; | |
v14 = __clz(reused_var); | |
if ( v14 == 32 ) | |
{ | |
v12 = (KObjectMutex *)__clz(this->lowPriorityThreadsBitfield); | |
v14 = (int)&v12[4]; | |
} | |
if ( v14 <= 63 ) | |
{ | |
while ( 1 ) | |
{ | |
v12 = (KObjectMutex *)this->threadsByPriority[v14].last; | |
if ( v12 ) | |
break; | |
LABEL_31: | |
if ( ++v14 > 63 ) | |
goto LABEL_44; | |
} | |
while ( 1 ) | |
{ | |
reused_var = (int)v12[9].owner; | |
v15 = reused_var == 0; | |
if ( reused_var ) | |
{ | |
v4 = *(KThread **)reused_var; | |
v15 = *(_DWORD *)reused_var == 0; | |
} | |
if ( v15 ) | |
break; | |
reused_var = this->coreNumber; | |
if ( v4->createdByProcessor == reused_var ) | |
{ | |
reused_var = v4->schedulingMask & 0xF; | |
if ( reused_var == 1 ) | |
goto LABEL_45; | |
} | |
v12 = *(KObjectMutex **)&v12[20].tryAcquireCounter; | |
if ( !v12 ) | |
goto LABEL_31; | |
} | |
LABEL_54: | |
v4 = (KThread *)v12; | |
goto LABEL_45; | |
} | |
} | |
else | |
{ | |
v16 = __clz(reused_var); | |
if ( v16 == 32 ) | |
{ | |
v12 = (KObjectMutex *)__clz(this->lowPriorityThreadsBitfield); | |
v16 = (int)&v12[4]; | |
} | |
if ( v16 <= 63 ) | |
{ | |
while ( 1 ) | |
{ | |
v12 = (KObjectMutex *)this->threadsByPriority[v16].last; | |
if ( v12 ) | |
break; | |
LABEL_43: | |
if ( ++v16 > 63 ) | |
goto LABEL_44; | |
} | |
while ( 1 ) | |
{ | |
reused_var = (int)v12[9].owner; | |
v17 = reused_var == 0; | |
if ( reused_var ) | |
{ | |
v4 = *(KThread **)reused_var; | |
v17 = *(_DWORD *)reused_var == 0; | |
} | |
if ( v17 ) | |
goto LABEL_54; | |
reused_var = this->coreNumber; | |
if ( v4->createdByProcessor == reused_var ) | |
{ | |
reused_var = v4->schedulingMask & 0xF; | |
if ( reused_var == 1 ) | |
goto LABEL_45; | |
} | |
v12 = *(KObjectMutex **)&v12[20].tryAcquireCounter; | |
if ( !v12 ) | |
goto LABEL_43; | |
} | |
} | |
} | |
LABEL_44: | |
v4 = this->schedulerThread; | |
} | |
LABEL_45: | |
if ( v4 == currentThread ) | |
{ | |
v18 = v6 == 0; | |
if ( v6 ) | |
{ | |
v12 = (KObjectMutex *)currentThread->ownerProcess; | |
v18 = v12 == 0; | |
} | |
if ( !v18 ) | |
{ | |
reused_var = (int)currentCoreCtx.objectContext.currentProcess; | |
if ( v12 != (KObjectMutex *)currentCoreCtx.objectContext.currentProcess ) | |
{ | |
currentCoreCtx.objectContext.currentProcess = (KProcess *volatile )v12; | |
KProcessHwInfo::SwitchContext((KProcessHwInfo *)&v12[3].tryAcquireCounter); | |
} | |
} | |
v19 = v4->preemptionTimer; | |
if ( !v19 ) | |
return (unsigned int)v19; | |
} | |
LABEL_52: | |
if ( this->coreNumber != 1 ) | |
goto func_end; | |
reused_var = useOtherPreemptionMode; | |
if ( useOtherPreemptionMode != 1 ) | |
{ | |
if ( !dword_FFF2E094 | |
&& !currentThread->preemptionTimer | |
&& (unsigned int)(currentThread->dynamicPriority - 1) < 0x3F ) | |
{ | |
reused_var = (int)&off_FFF31500; | |
stru_FFF31520.timer += stru_FFF31520.previousWDTValue - MPCORE_CPU1_WDT_COUNTER; | |
} | |
v35 = v4->preemptionTimer; | |
if ( !v35 ) | |
{ | |
if ( !dword_FFF2E094 ) | |
{ | |
reused_var = MPCORE_CPU1_WDT_COUNTER; | |
stru_FFF31520.previousWDTValue = MPCORE_CPU1_WDT_COUNTER; | |
} | |
goto func_end; | |
} | |
if ( v35->nLimitedTicks == dword_FFF2E094 ) | |
goto func_end; | |
reused_var = (int)v4->endOfThreadContext; | |
v27 = &preemptedThreads; | |
if ( *(_BYTE *)(reused_var - 0xB8) ) | |
goto func_end; | |
if ( *(_BYTE *)(reused_var - 0xB5) ) | |
{ | |
v36 = (unsigned __int8 *)(reused_var - 0xB8); | |
do | |
{ | |
v37 = __ldrex(v36); | |
reused_var = (char)(v37 | 2); | |
} | |
while ( __strex(reused_var, v36) ); | |
goto func_end; | |
} | |
v4->preemptionList = &preemptedThreads; | |
KThread::Reschedule(v4, 0); | |
if ( preemptedThreads.first ) | |
reused_var = (int)&preemptedThreads.first->threadListNode; | |
else | |
reused_var = (int)&preemptedThreads; | |
v4->threadListNode.prev = preemptedThreads.first; | |
v4->threadListNode.next = 0; | |
*(_DWORD *)(reused_var + 4) = v4; | |
preemptedThreads.first = v4; | |
if ( v4->shallTerminate ) | |
{ | |
v29 = v4->threadListNode; | |
if ( v29.prev ) | |
v30 = (KThreadLinkedList *)&v29.prev->threadListNode; | |
else | |
v30 = &preemptedThreads; | |
if ( v29.next ) | |
goto LABEL_75; | |
goto LABEL_101; | |
} | |
LABEL_102: | |
v4 = 0; | |
goto LABEL_6; | |
} | |
v20 = currentThread->preemptionTimer; // else, other (failed) preemption mode | |
v21 = 0; | |
if ( v20 ) | |
{ | |
v2 = MPCORE_CPU1_WDT_COUNTER; | |
v21 = 1; | |
reused_var = v20->previousWDTValue - MPCORE_CPU1_WDT_COUNTER + v20->timer; | |
v20->timer = reused_var; | |
} | |
v22 = v4->preemptionTimer; | |
if ( !v22 ) | |
goto func_end; | |
v23 = v22->wantedDuration; | |
if ( v22->timer < v23 ) | |
break; | |
v24 = (char *)v4->endOfThreadContext; | |
reused_var = (unsigned __int8)v24[-0xB8u]; | |
if ( v24[-0xB8u] ) | |
goto LABEL_80; | |
if ( v24[-0xB5u] ) | |
{ | |
reused_var = 2; | |
v25 = (unsigned __int8 *)(v24 - 0xB8); | |
do | |
v26 = __ldrex(v25); | |
while ( __strex(v26 | 2, v25) ); | |
goto LABEL_80; | |
} | |
v27 = &preemptedThreads; | |
v4->preemptionList = &preemptedThreads; | |
KThread::Reschedule(v4, 0); | |
reused_var = (int)preemptedThreads.first; | |
if ( preemptedThreads.first ) | |
v28 = (KThreadLinkedList *)&preemptedThreads.first->threadListNode; | |
else | |
v28 = &preemptedThreads; | |
v4->threadListNode.prev = preemptedThreads.first; | |
v4->threadListNode.next = 0; | |
v28->last = v4; | |
preemptedThreads.first = v4; | |
if ( !v4->shallTerminate ) | |
goto LABEL_102; | |
v29 = v4->threadListNode; | |
if ( v29.prev ) | |
v30 = (KThreadLinkedList *)&v29.prev->threadListNode; | |
else | |
v30 = &preemptedThreads; | |
if ( v29.next ) | |
LABEL_75: | |
v27 = (KThreadLinkedList *)&v29.next->threadListNode; | |
LABEL_101: | |
v30->last = v29.next; | |
v27->first = v29.prev; | |
KThread::Reschedule(v4, 1u); | |
v4->preemptionList = 0; | |
} | |
v31 = v23 - v22->timer; | |
v32 = 0x6646CC * qword_FFF31548; | |
rofl = (KTimeableInterruptEvent *)((0x6646CC * (unsigned __int64)(unsigned int)qword_FFF31548 >> 32) | |
+ 0x6646CC * HIDWORD(qword_FFF31548)); | |
v33 = KTimerAndWDTManager::GetSystemTick(&TimerAndWDTManager) + (unsigned int)(2 * v31); | |
if ( SHIDWORD(v33) >= (signed int)rofl + ((unsigned int)v33 < v32) ) | |
{ | |
byte_FFF31544 = 1; | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer( | |
&TimerAndWDTManager, | |
&stru_FFF31530, | |
__PAIR__((unsigned int)rofl, v32)); | |
v34 = &TimerAndWDTManager.recursiveLock; | |
} | |
else | |
{ | |
byte_FFF31544 = 0; | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer(&TimerAndWDTManager, &stru_FFF31530, v33); | |
v34 = &TimerAndWDTManager.recursiveLock; | |
} | |
KRecursiveLock::LocalUnlock(v34); | |
LABEL_80: | |
if ( !v21 ) | |
v2 = MPCORE_CPU1_WDT_COUNTER; | |
v22->previousWDTValue = v2; | |
func_end: | |
v38 = v6 == 0; | |
if ( v6 ) | |
{ | |
reused_var = (int)v4->ownerProcess; | |
v38 = reused_var == 0; | |
} | |
if ( !v38 && (KProcess *volatile )reused_var != currentCoreCtx.objectContext.currentProcess ) | |
{ | |
currentCoreCtx.objectContext.currentProcess = (KProcess *volatile )reused_var; | |
KProcessHwInfo::SwitchContext((KProcessHwInfo *)(reused_var + 28)); | |
} | |
currentCoreCtx.objectContext.currentThread = v4; | |
__mcr(15, 0, (unsigned int)v4->threadLocalStorage, 13, 0, 3); | |
return (unsigned int)v4->svcRegisterStorage; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The **non-default** pre-emption mode that doesn't appear to work | |
// a1 = this = off_FFF31530 (struct of size 0x30) | |
// at +0x20 there's a KPreemptionTimer | |
sub_FFF26580 is the function eventually called after the interrupt, see https://www.3dbrew.org/wiki/KSchedulableInterruptEventLinkedList | |
void __fastcall sub_FFF26580(void *a1) | |
{ | |
int v1; // r0@2 | |
int v2; // r1@3 | |
int i; // r0@3 | |
KThread *v4; // r4@6 | |
KThreadLinkedListNode *v5; // r3@8 | |
KPreemptionTimer *v6; // r0@12 | |
int remaining; // r9@13 | |
s64 v8; // r6@13 | |
s64 v9; // r2@13 | |
s64 v10; // kr08_8@14 | |
KRecursiveLock *v11; // r0@14 | |
unsigned int v12; // r8@17 | |
unsigned int v13; // r5@17 | |
KThread *volatile v14; // r4@19 | |
KPreemptionTimer *v15; // r0@19 | |
int v16; // r1@20 | |
char *v17; // r1@21 | |
KThreadLinkedList *v18; // r5@21 | |
unsigned __int8 *v19; // r0@23 | |
unsigned int v20; // r2@25 | |
KThread *v21; // r0@24 | |
KThreadLinkedListNode *v22; // r1@28 | |
KThread *v23; // r1@31 | |
KThread *v24; // r2@31 | |
KThreadLinkedList *v25; // r0@32 | |
unsigned int v26; // r5@37 | |
unsigned int v27; // r7@37 | |
// struct[2] FFF31500, size 0x30 each, 1 for each sched. mode | |
if ( *((_BYTE *)a1 + 0x14) == 1 ) | |
{ | |
++*((_QWORD *)a1 + 3); | |
KRecursiveLock::Lock(&g_criticalSectionLock); | |
v2 = MPCORE_CPU1_WDT_COUNTER; | |
for ( i = off_FFF2E09C; i; i = *(_DWORD *)(i + 0x10) ) | |
{ | |
*(_DWORD *)(i + 8) = v2; | |
*(_DWORD *)(i + 4) = 0; | |
} | |
while ( dword_FFF2E0AC ) | |
{ | |
v4 = dword_FFF2E0AC; | |
if ( dword_FFF2E0AC ) // pop last thread in list | |
{ | |
dword_FFF2E0AC = dword_FFF2E0AC->threadListNode.next; | |
if ( dword_FFF2E0AC ) | |
v5 = &dword_FFF2E0AC->threadListNode; | |
else | |
v5 = (KThreadLinkedListNode *)&preemptedThreads; | |
v5->prev = 0; | |
v4->preemptionList = 0; | |
KThread::Reschedule(v4, 1u); // add in back in the normal scheduler list | |
v4->preemptionList = 0; | |
} | |
} | |
v6 = currentCoreCtx.objectContext.currentThread->preemptionTimer; | |
if ( v6 ) | |
{ | |
remaining = v6->wantedDuration - v6->timer; | |
v8 = 0x6646CC * qword_FFF31548; // 25ms | |
v9 = KTimerAndWDTManager::GetSystemTick(&TimerAndWDTManager) + (unsigned int)(2 * remaining); | |
if ( SHIDWORD(v9) >= HIDWORD(v8) + ((unsigned int)v9 < (unsigned int)v8) ) | |
{ | |
byte_FFF31544 = 1; | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer(&TimerAndWDTManager, &stru_FFF31530, v8);// reschedule ourselves, etc | |
v11 = &TimerAndWDTManager.recursiveLock; | |
} | |
else | |
{ | |
byte_FFF31544 = 0; | |
v10 = v9; | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer(&TimerAndWDTManager, &stru_FFF31530, v10); | |
v11 = &TimerAndWDTManager.recursiveLock; | |
} | |
KRecursiveLock::LocalUnlock(v11); | |
} | |
else | |
{ | |
byte_FFF31544 = 1; | |
v12 = 0x6646CC * qword_FFF31548; | |
v13 = (0x6646CC * (unsigned __int64)(unsigned int)qword_FFF31548 >> 32) + 0x6646CC * HIDWORD(qword_FFF31548); | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer(&TimerAndWDTManager, &stru_FFF31530, __PAIR__(v13, v12)); | |
KRecursiveLock::LocalUnlock(&TimerAndWDTManager.recursiveLock); | |
} | |
KRecursiveLock::Unlock(&g_criticalSectionLock); | |
} | |
else | |
{ | |
v1 = *((_DWORD *)a1 + 4); | |
KRecursiveLock::Lock(&g_criticalSectionLock); | |
v14 = currentCoreCtx.objectContext.currentThread; | |
v15 = currentCoreCtx.objectContext.currentThread->preemptionTimer; | |
if ( v15 ) | |
{ | |
v16 = MPCORE_CPU1_WDT_COUNTER; | |
if ( v15->wantedDuration <= v15->previousWDTValue - v16 + v15->timer ) | |
{ | |
v17 = (char *)currentCoreCtx.objectContext.currentThread->endOfThreadContext; | |
v18 = &preemptedThreads; | |
if ( !v17[-0xB8u] ) | |
{ | |
if ( v17[-0xB5u] ) // are we executing a svc? | |
{ | |
v19 = (unsigned __int8 *)(v17 - 0xB8); | |
do | |
v20 = __ldrex(v19); | |
while ( __strex(v20 | 2, v19) ); // force a ctx switch after the svc | |
} | |
else | |
{ | |
v21 = currentCoreCtx.objectContext.currentThread; | |
currentCoreCtx.objectContext.currentThread->preemptionList = &preemptedThreads; | |
KThread::Reschedule(v21, 0); | |
if ( preemptedThreads.first ) | |
v22 = &preemptedThreads.first->threadListNode; | |
else | |
v22 = (KThreadLinkedListNode *)&preemptedThreads;// add it at the front | |
v14->threadListNode.prev = preemptedThreads.first; | |
v14->threadListNode.next = 0; | |
v22->next = v14; | |
preemptedThreads.first = v14; | |
if ( v14->shallTerminate ) | |
{ | |
v23 = v14->threadListNode.prev; | |
v24 = v14->threadListNode.next; | |
if ( v23 ) | |
v25 = (KThreadLinkedList *)&v23->threadListNode; | |
else | |
v25 = &preemptedThreads; | |
if ( v24 ) | |
v18 = (KThreadLinkedList *)&v24->threadListNode; | |
v25->last = v24; | |
v18->first = v23; | |
KThread::Reschedule(v14, 1u); | |
v14->preemptionList = 0; | |
} | |
} | |
} | |
} | |
} | |
byte_FFF31544 = 1; | |
v26 = 0x6646CC * qword_FFF31548; | |
v27 = (0x6646CC * (unsigned __int64)(unsigned int)qword_FFF31548 >> 32) + 0x6646CC * HIDWORD(qword_FFF31548);// 1 / 640.7? | |
KRecursiveLock::Lock(&TimerAndWDTManager.recursiveLock); | |
KTimerAndWDTManager::RegisterInterruptEventWithTimer(&TimerAndWDTManager, &stru_FFF31530, __PAIR__(v27, v26)); | |
KRecursiveLock::LocalUnlock(&TimerAndWDTManager.recursiveLock); | |
KRecursiveLock::Unlock(&g_criticalSectionLock); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment