Skip to content

Instantly share code, notes, and snippets.

@TuxSH
Created January 5, 2017 16:33
Show Gist options
  • Save TuxSH/28cc8794ee5d920664cb50f6afeafc54 to your computer and use it in GitHub Desktop.
Save TuxSH/28cc8794ee5d920664cb50f6afeafc54 to your computer and use it in GitHub Desktop.
scheduler stuff
// 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);
}
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);
}
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;
}
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;
}
// 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