📄 schedule.c
字号:
LockPages(lpName,len,0,LOCKFLAG_READ);
}
EnterCriticalSection(&NameCS);
if (lpName) {
for (hMutex = hMutexList; hMutex; hMutex = lpmutex->hNext) {
lpmutex = HandleToMutex(hMutex);
DEBUGCHK(lpmutex);
if (lpmutex->name && !strcmpW(lpmutex->name->name,lpName)) {
IncRef(hMutex,pCurProc);
KSetLastError(pCurThread,ERROR_ALREADY_EXISTS);
goto exit;
}
}
KSetLastError(pCurThread,0);
}
if (!(lpmutex = (LPMUTEX)AllocMem(HEAP_MUTEX))) {
KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY);
hMutex = 0;
goto exit;
}
if (!(hMutex = AllocHandle(&cinfMutex,lpmutex,pCurProc))) {
KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY);
FreeMem(lpmutex,HEAP_EVENT);
hMutex = 0;
goto exit;
}
if (lpName) {
if (!(lpmutex->name = AllocName(len))) {
KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY);
FreeHandle(hMutex);
FreeMem(lpmutex,HEAP_EVENT);
hMutex = 0;
goto exit;
}
memcpy(lpmutex->name->name,lpName,len);
} else
lpmutex->name = 0;
memset(lpmutex->pProxHash,0,sizeof(lpmutex->pProxHash));
lpmutex->pProxList = 0;
lpmutex->hNext = hMutexList;
hMutexList = hMutex;
lpmutex->bListed = 0;
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -