📄 schedule.c
字号:
if (bInitialOwner) { lpmutex->LockCount = 1; lpmutex->pOwner = pCurThread; KCall((PKFN)LaterLinkCritMut,(LPCRIT)lpmutex,0); } else { lpmutex->LockCount = 0; lpmutex->pOwner = 0; }exit: CELOG_MutexCreate(hMutex, lpmutex->name); LeaveCriticalSection(&NameCS); if (lpName) UnlockPages(lpName,len); DEBUGMSG(ZONE_ENTRY,(L"SC_CreateMutex exit: %8.8lx\r\n",hMutex)); return hMutex;}DWORD SC_SetLowestScheduledPriority(DWORD maxprio) { DWORD retval; DEBUGMSG(ZONE_ENTRY,(L"SC_SetLowestScheduledPriority entry: %8.8lx\r\n",maxprio)); if (maxprio > MAX_WIN32_PRIORITY_LEVELS - 1) maxprio = MAX_WIN32_PRIORITY_LEVELS - 1; retval = currmaxprio; if (retval < MAX_PRIORITY_LEVELS - MAX_WIN32_PRIORITY_LEVELS) retval = MAX_PRIORITY_LEVELS - MAX_WIN32_PRIORITY_LEVELS; retval -= (MAX_PRIORITY_LEVELS - MAX_WIN32_PRIORITY_LEVELS); currmaxprio = maxprio + (MAX_PRIORITY_LEVELS - MAX_WIN32_PRIORITY_LEVELS); pOOMThread = pCurThread; DEBUGMSG(ZONE_ENTRY,(L"SC_SetLowestScheduledPriority exit: %8.8lx\r\n",retval)); return retval;}void NextThread(void) { PTHREAD pth; LPEVENT lpe; LPPROXY pprox; DWORD pend, intr; KCALLPROFON(10); /* Handle interrupts */ dointr: INTERRUPTS_OFF(); pend = PendEvents; PendEvents = 0; INTERRUPTS_ON(); if (pend) { do { intr = GetHighPos(pend); pend &= ~(1<<intr); if (lpe = IntrEvents[intr]) { if (!lpe->pProxList) lpe->state = 1; else { DEBUGCHK(!lpe->state); pprox = lpe->pProxList; DEBUGCHK(pprox->pObject == (LPBYTE)lpe); DEBUGCHK(pprox->bType == HT_MANUALEVENT); DEBUGCHK(pprox->pQDown == pprox); DEBUGCHK(pprox->pQPrev == (LPPROXY)lpe); DEBUGCHK(pprox->dwRetVal == WAIT_OBJECT_0); lpe->pProxList = 0; pth = pprox->pTh; DEBUGCHK(!pth->lpce); pth->wCount++; DEBUGCHK(pth->lpProxy == pprox); DEBUGCHK(pth->lpProxy == lpe->pIntrProxy); pth->lpProxy = 0; if (pth->bWaitState == WAITSTATE_BLOCKED) { DEBUGCHK(GET_RUNSTATE(pth) != RUNSTATE_RUNNABLE); DEBUGCHK(GET_RUNSTATE(pth) != RUNSTATE_RUNNING); DEBUGCHK(GET_RUNSTATE(pth) != RUNSTATE_NEEDSRUN); pth->retValue = WAIT_OBJECT_0; if (GET_SLEEPING(pth)) SleepqDequeue(pth); MakeRun(pth); } else { DEBUGCHK(!GET_SLEEPING(pth)); DEBUGCHK(pth->bWaitState == WAITSTATE_PROCESSING); pth->dwPendReturn = WAIT_OBJECT_0; pth->bWaitState = WAITSTATE_SIGNALLED; } } } } while (pend); if (PendEvents) goto dointr; KCALLPROFOFF(10); return; } INTERRUPTS_OFF(); pend = DiffMSec; DiffMSec = 0; INTERRUPTS_ON(); if (dwPreempt) { if (pend >= dwPreempt) { bPreempt = 1; dwPreempt = 0; SetReschedule(); } else dwPreempt -= pend; } if (ticksleft += pend) { /* Handle timeouts */ if (!(pth = SleepList)) { ticksleft = 0; dwPartialDiffMSec = 0; DEBUGCHK(!dwSleepMin); } else if (pth->dwSleepCnt > ticksleft) { pth->dwSleepCnt -= ticksleft; dwSleepMin = pth->dwSleepCnt; ticksleft = 0; } else { ticksleft -= pth->dwSleepCnt; if (SleepList = pth->pNextSleepRun) { SleepList->pPrevSleepRun = 0; if (!SleepList->dwSleepCnt) { ++SleepList->dwSleepCnt; ++ticksleft; } dwSleepMin = SleepList->dwSleepCnt; } else dwSleepMin = 0; dwPartialDiffMSec = 0; DEBUGCHK(GET_SLEEPING(pth)); CLEAR_SLEEPING(pth); pth->wCount++; if (GET_RUNSTATE(pth) != RUNSTATE_NEEDSRUN) { DEBUGCHK(GET_RUNSTATE(pth) == RUNSTATE_BLOCKED); if (pth->lpce) { // not set if purely sleeping pth->lpce->base = pth->lpProxy; pth->lpce->size = (DWORD)pth->lpPendProxy; pth->lpProxy = 0; } else if (pth->lpProxy) { // must be an interrupt event - special case it! pprox = pth->lpProxy; lpe = (LPEVENT)pprox->pObject; DEBUGCHK(pprox->bType == HT_MANUALEVENT); DEBUGCHK(pprox->pQDown == pprox); DEBUGCHK(pprox->pQPrev == (LPPROXY)lpe); DEBUGCHK(pprox->dwRetVal == WAIT_OBJECT_0); lpe->pProxList = 0; pprox->pQDown = 0; pth->lpProxy = 0; } MakeRun(pth); } } } KCALLPROFOFF(10);}void GoToUserTime() { INTERRUPTS_OFF(); SET_TIMEUSER(pCurThread); pCurThread->dwKernTime += CurMSec - CurrTime; CurrTime = CurMSec; INTERRUPTS_ON(); randdw1 = ((randdw1<<5) | (randdw1>>27)) ^ (CurMSec & 0x1f);}void GoToKernTime() { INTERRUPTS_OFF(); SET_TIMEKERN(pCurThread); pCurThread->dwUserTime += CurMSec - CurrTime; CurrTime = CurMSec; INTERRUPTS_ON(); randdw2 = ((randdw2<<5) | (randdw2>>27)) ^ (CurMSec & 0x1f);}void KCNextThread(void) { DWORD prio, prio2, NewTime, dwTmp; PTHREAD pth, pth2, pth3, pOwner; LPCRIT pCrit; LPCRITICAL_SECTION lpcs; KCALLPROFON(44); if (!bLastIdle && !RunList.pth) pCurThread->dwQuantLeft = pCurThread->dwQuantum; if ((pth = RunList.pth) && (pth2 = RunList.pRunnable) && (((prio = GET_CPRIO(pth)) > (prio2 = GET_CPRIO(pth2))) || ((prio == prio2) && bPreempt))) { if (prio == prio2) { // Current thread and next runnable thread have same priority, same run list. Use // runnable thread pointer (pth2, first on list) to place current thread (pth) last on list. pth->dwQuantLeft = pth->dwQuantum; pth->pUpRun = pth2->pUpRun; pth->pUpRun->pDownRun = pth2->pUpRun = pth; pth->pDownRun = pth2; pth->pPrevSleepRun = pth->pNextSleepRun = 0; } else { // Find appropriate place to enqueue current thread. dwTmp = DiffMSec; pth->dwQuantLeft = (dwPreempt > dwTmp) ? (dwPreempt - dwTmp) : 0; prio2 = prio/PRIORITY_LEVELS_HASHSCALE; if (pth2 = RunList.pHashThread[prio2]) { // Hash table entry for current thread priority already exists if (prio < GET_CPRIO(pth2)) { // Insert new run list for current thread priority before list pointed to by // hash table. pth->pUpRun = pth->pDownRun = RunList.pHashThread[prio2] = pth; pth->pPrevSleepRun = pth2->pPrevSleepRun; pth->pNextSleepRun = pth2; pth->pPrevSleepRun->pNextSleepRun = pth2->pPrevSleepRun = pth; } else if (prio == GET_CPRIO(pth2)) { // Run list for current thread priority exists, make current thread first if time // left in quantum or if quantum is 0 (run to completion). if (pth->dwQuantLeft || !pth->dwQuantum) { // make first pth->pPrevSleepRun = pth2->pPrevSleepRun; pth->pPrevSleepRun->pNextSleepRun = pth; if (pth->pNextSleepRun = pth2->pNextSleepRun) pth->pNextSleepRun->pPrevSleepRun = pth; pth2->pPrevSleepRun = pth2->pNextSleepRun = 0; pth->pUpRun = pth2->pUpRun; pth->pUpRun->pDownRun = pth2->pUpRun = pth; pth->pDownRun = pth2; // Update hash table entry to new first thread on list. RunList.pHashThread[prio2] = pth; } else { // make last pth->dwQuantLeft = pth->dwQuantum; pth->pUpRun = pth2->pUpRun; pth->pUpRun->pDownRun = pth2->pUpRun = pth; pth->pDownRun = pth2; pth->pPrevSleepRun = pth->pNextSleepRun = 0; } } else { // Look for appropriate run list to enqueue current thread on. FinishEnqueue: // bounded by PRIORITY_LEVELS_HASHSCALE while ((pth3 = pth2->pNextSleepRun) && (prio > GET_CPRIO(pth3))) pth2 = pth3; if (prio == GET_CPRIO(pth2)) { // Found run list. Make current thread first if time left in quantum // or if quantum is 0 (run to completion). if (pth->dwQuantLeft || !pth->dwQuantum) { // make first pth->pPrevSleepRun = pth2->pPrevSleepRun; pth->pPrevSleepRun->pNextSleepRun = pth; if (pth->pNextSleepRun = pth2->pNextSleepRun) pth->pNextSleepRun->pPrevSleepRun = pth; pth2->pPrevSleepRun = pth2->pNextSleepRun = 0; pth->pUpRun = pth2->pUpRun; pth->pUpRun->pDownRun = pth2->pUpRun = pth; pth->pDownRun = pth2; } else { // make last pth->dwQuantLeft = pth->dwQuantum; pth->pUpRun = pth2->pUpRun; pth->pUpRun->pDownRun = pth2->pUpRun = pth; pth->pDownRun = pth2; pth->pPrevSleepRun = pth->pNextSleepRun = 0; } } else if (!pth3) { // New run list. pth->pNextSleepRun = 0; pth->pPrevSleepRun = pth2; pth->pUpRun = pth->pDownRun = pth2->pNextSleepRun = pth; } else { if (prio == GET_CPRIO(pth3)) { // Found run list. Make current thread first if time left in quantum // or if quantum is 0 (run to completion). if (pth->dwQuantLeft || !pth->dwQuantum) { // make first pth->pPrevSleepRun = pth3->pPrevSleepRun; pth->pPrevSleepRun->pNextSleepRun = pth; if (pth->pNextSleepRun = pth3->pNextSleepRun) pth->pNextSleepRun->pPrevSleepRun = pth; pth3->pPrevSleepRun = pth3->pNextSleepRun = 0; pth->pUpRun = pth3->pUpRun; pth->pUpRun->pDownRun = pth3->pUpRun = pth; pth->pDownRun = pth3; } else { // make last pth->dwQuantLeft = pth->dwQuantum; pth->pUpRun = pth3->pUpRun; pth->pUpRun->pDownRun = pth3->pUpRun = pth; pth->pDownRun = pth3; pth->pPrevSleepRun = pth->pNextSleepRun = 0; } } else { // New run list. pth->pPrevSleepRun = pth2; pth->pUpRun = pth->pDownRun = pth2->pNextSleepRun = pth3->pPrevSleepRun = pth; pth->pNextSleepRun = pth3; } } } } else { // No hash table entry for current thread priority exists. Point to current thread // and enqueue. RunList.pHashThread[prio2] = pth; // bounded by PRIORITY_LEVELS_HASHSIZE while (!(pth2 = RunList.pHashThread[--prio2])) ; goto FinishEnqueue; } } SET_RUNSTATE(pth,RUNSTATE_RUNNABLE); RunList.pth = 0; bPreempt = 0; } else if (bPreempt) { if (!bLastIdle) { pCurThread->dwQuantLeft = pCurThread->dwQuantum; if (pCurThread->dwQuantum) dwPreempt = pCurThread->dwQuantum + DiffMSec; else dwPreempt = 0; // 0 if Quantum=0 } bPreempt = 0; }findHighest: if (!RunList.pth && (pth = RunList.pRunnable)) { if ((prio = GET_CPRIO(pth)) > currmaxprio) { pOwner = pOOMThread; while (pOwner && !PendEvents) { if (GET_RUNSTATE(pOwner) == RUNSTATE_RUNNABLE) { pth = pOwner; prio = GET_CPRIO(pOwner); goto foundone; } if (GET_RUNSTATE(pOwner) == RUNSTATE_NEEDSRUN) { if (GET_SLEEPING(pOwner)) SleepqDequeue(pOwner); MakeRun(pOwner); goto findHighest; } if ((GET_RUNSTATE(pOwner) == RUNSTATE_BLOCKED) && !GET_SLEEPING(pOwner) && pOwner->lpProxy && pOwner->lpProxy->pQDown && !pOwner->lpProxy->pThLinkNext && (pOwner->lpProxy->bType == HT_CRITSEC)) { pCrit = (LPCRIT)pOwner->lpProxy->pObject; DEBUGCHK(pCrit); SWITCHKEY(dwTmp, 0xffffffff); lpcs = pCrit->lpcs; DEBUGCHK(lpcs); DEBUGCHK(lpcs->OwnerThread); pOwner = HandleToThread((HANDLE)((DWORD)lpcs->OwnerThread & ~1)); SETCURKEY(dwTmp); DEBUGCHK(pOwner); } else pOwner = 0; } goto nonewthread; }foundone: RunList.pth = pth; SET_RUNSTATE(pth,RUNSTATE_RUNNING); RunqDequeue(pth,prio); pth->hLastCrit = 0; pth->lpCritProxy = 0; bPreempt = 0; if (!pth->dwQuantLeft) pth->dwQuantLeft = pth->dwQuantum; if (pth->dwQuantum) dwPreempt = pth->dwQuantLeft + DiffMSec; else dwPreempt = 0; // 0 if Quantum=0 if (!GET_NOPRIOCALC(pth)) { prio = GET_BPRIO(pth); if (pth->pOwnedList && ((prio2 = pth->pOwnedList->bListedPrio) < prio)) prio = prio2; if (prio > GET_CPRIO(pth)) { SET_CPRIO(pth,prio); CELOG_SystemInvert(pth->hTh, prio); if (RunList.pRunnable && (prio > GET_CPRIO(RunList.pRunnable))) SetReschedule(); } } }nonewthread: NewTime = CurMSec; randdw2 = ((randdw2<<5) | (randdw2>>27)) ^ ((NewTime>>5) & 0x1f); if (!bLastIdle) { if (GET_TIMEMODE(pCurThread) == TIMEMODE_USER) pCurThread->dwUserTime += NewTime - CurrTime; else pCurThread->dwKernTime += NewTime - CurrTime; } CurrTime = NewTime; bLastIdle = !RunList.pth; if (!bLastIdle) { CELOG_ThreadSwitch(RunList.pth); if (pLogThreadSwitch) pLogThreadSwitch((DWORD)RunList.pth,(DWORD)RunList.pth->pOwnerProc); } else { dwPreempt = 0; CELOG_ThreadSwitch(0); if (pLogThreadSwitch) pLogThreadSwitch(0,0); }#ifndef SHIP_BUILD if (pCurThread != RunList.pth) KInfoTable[KINX_DEBUGGER]++;#endif#ifdef SH4 if (RunList.pth) { if (g_CurFPUOwner != RunList.pth) RunList.pth->ctx.Psr |= 0x8000; else RunList.pth->ctx.Psr &= ~0x8000; }#endif#ifdef SH3 if (RunList.pth) { if (g_CurDSPOwner != RunList.pth) RunList.pth->ctx.Psr &= ~0x1000; else RunList.pth->ctx.Psr |= 0x1000; }#endif KCALLPROFOFF(44);}LPTHRDDBG AllocDbg(HANDLE hProc) { LPTHRDDBG pdbg; if (!(pdbg = (LPTHRDDBG)AllocMem(HEAP_THREADDBG))) return 0; if (!(pdbg->hEvent = CreateEvent(0,0,0,0))) { FreeMem(pdbg,HEAP_THREADDBG); return 0; } if (!(pdbg->hBlockEvent = CreateEvent(0,0,0,0))) { CloseHandle(pdbg->hEvent); FreeMem(pdbg,HEAP_THREADDBG); return 0; } if (hProc) { SC_SetHandleOwner(pdbg->hEvent,hProc); SC_SetHandleOwner(pdbg->hBlockEvent,hProc); } pdbg->hFirstThrd = 0; pdbg->psavedctx = 0; pdbg->dbginfo.dwDebugEventCode = 0; pdbg->bDispatched = 0; return pdbg;}BOOL InitThreadStruct(PTHREAD pTh, HANDLE hTh, PPROCESS pProc, HANDLE hProc, WORD prio) { SetUserInfo(hTh,STILL_ACTIVE); pTh->pProc = pProc; pTh->pOwnerProc = pProc; pTh->pProxList = 0; pTh->pThrdDbg = 0; pTh->aky = pProc->aky; AddAccess(&pTh->aky,ProcArray[0].aky);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -