📄 schedule.c
字号:
if (pDown = pth->pDownSleep) {
DEBUGCHK (!GET_NEEDSLEEP(pDown) && GET_SLEEPING (pDown));
#ifdef DEBUG
if (cprio > GET_CPRIO (pDown)) {
DEBUGMSG (1, (L"pth->bprio = %d, pth->cprio = %d, pDown->bprio = %d, pDown->cprio = %d\r\n",
pth->bBPrio, cprio, pDown->bBPrio, GET_CPRIO(pDown)));
if (pth->pOwnedList) {
DEBUGMSG (1, (L"pth->pOwnedList->bListedPrio = %dlx\r\n", pth->pOwnedList->bListedPrio));
}
if (pDown->pOwnedList) {
DEBUGMSG (1, (L"pDown->pOwnedList->bListedPrio = %dlx\r\n", pDown->pOwnedList->bListedPrio));
}
DEBUGMSG (1, (L"pth->wInfo = %8.8lx, pDown->wInfo = %8.8lx\r\n", pth->wInfo, pDown->wInfo));
DEBUGCHK (0);
}
#endif
DEBUGCHK (!pDown->bSuspendCnt);
pDown->wCount ++;
pDown->wCount2 ++;
CLEAR_SLEEPING (pDown);
pDown->pUpSleep = pth->pDownSleep = 0;
// don't worry about it if NEEDRUN flag is set
if (GET_RUNSTATE(pDown) != RUNSTATE_NEEDSRUN) {
// setup proxy for cleanup if not pure sleeping
DEBUGCHK(GET_RUNSTATE(pDown) == RUNSTATE_BLOCKED);
if (pDown->lpce) { // not set if purely sleeping
pDown->lpce->base = pDown->lpProxy;
pDown->lpce->size = (DWORD)pDown->lpPendProxy;
pDown->lpProxy = 0;
} else if (pDown->lpProxy) {
// must be an interrupt event - special case it!
LPPROXY pprox = pDown->lpProxy;
LPEVENT 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;
pDown->lpProxy = 0;
}
// replace pth's slot if of same priority
if (cprio == GET_CPRIO (pDown)) {
if (pth == pth->pDownRun) {
// only node in this priority
pDown->pUpRun = pDown->pDownRun = pDown;
} else {
// fixup the links
if (pDown->pUpRun = pth->pUpRun)
pDown->pUpRun->pDownRun = pDown;
if (pDown->pDownRun = pth->pDownRun)
pDown->pDownRun->pUpRun = pDown;
}
// fix up next node
if (pDown->pNextSleepRun = pth->pNextSleepRun)
pDown->pNextSleepRun->pPrevSleepRun = pDown;
// fix up prev node, update pRunnable if necessary
if (pDown->pPrevSleepRun = pth->pPrevSleepRun) {
pDown->pPrevSleepRun->pNextSleepRun = pDown;
} else if (RunList.pRunnable == pth) {
RunList.pRunnable = pDown;
}
// update hash table if necessary
if (RunList.pHashThread[prio] == pth)
RunList.pHashThread[prio] = pDown;
SET_RUNSTATE (pDown, RUNSTATE_RUNNABLE);
return;
}
// not of the same priority, just call MakeRun
// might want to save an instruction or two by
// handling the logic here (don't have to check
// suspend/pRunnable, etc.
MakeRun (pDown);
}
}
// remove pth from the run queue
pDown = pth->pDownRun;
pNext = pth->pNextSleepRun;
if (RunList.pHashThread[prio] == pth) {
RunList.pHashThread[prio] = ((pDown != pth) ? pDown :
(pNext && (GET_CPRIO(pNext)/PRIORITY_LEVELS_HASHSCALE == (WORD)prio)) ? pNext : 0);
}
if (pDown == pth) {
if (!pth->pPrevSleepRun) {
DEBUGCHK(RunList.pRunnable == pth);
if (RunList.pRunnable = pNext)
pNext->pPrevSleepRun = 0;
} else {
if (pth->pPrevSleepRun->pNextSleepRun = pNext)
pNext->pPrevSleepRun = pth->pPrevSleepRun;
}
} else {
pDown->pUpRun = pth->pUpRun;
pth->pUpRun->pDownRun = pDown;
if (pth->pPrevSleepRun) {
pth->pPrevSleepRun->pNextSleepRun = pDown;
pDown->pPrevSleepRun = pth->pPrevSleepRun;
goto FinishDequeue;
} else if (pth == RunList.pRunnable) {
RunList.pRunnable = pDown;
DEBUGCHK(!pDown->pPrevSleepRun);
FinishDequeue:
if (pNext) {
pNext->pPrevSleepRun = pDown;
pDown->pNextSleepRun = pNext;
}
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SleepqDequeue(
PTHREAD pth
)
{
PTHREAD pth2;
DEBUGCHK(pth && GET_SLEEPING(pth));
pth->wCount2++;
if (pth2 = pth->pUpSleep) {
DEBUGCHK (pth != SleepList);
DEBUGCHK (!pth->pNextSleepRun && !pth->pPrevSleepRun);
if (pth2->pDownSleep = pth->pDownSleep) {
pth2->pDownSleep->pUpSleep = pth2;
pth->pDownSleep = 0;
}
pth->pUpSleep = 0;
} else if (pth2 = pth->pDownSleep) {
DEBUGCHK (!pth2->pNextSleepRun && !pth2->pPrevSleepRun);
if (pth2->pNextSleepRun = pth->pNextSleepRun) {
pth2->pNextSleepRun->pPrevSleepRun = pth2;
}
if (pth2->pPrevSleepRun = pth->pPrevSleepRun) {
pth2->pPrevSleepRun->pNextSleepRun = pth2;
} else {
DEBUGCHK (pth == SleepList);
SleepList = pth2;
}
pth2->pUpSleep = pth->pDownSleep = 0;
} else if (pth2 = pth->pPrevSleepRun) {
if (pth2->pNextSleepRun = pth->pNextSleepRun) {
pth2->pNextSleepRun->pPrevSleepRun = pth2;
}
} else {
DEBUGCHK (pth == SleepList);
// update SleepList
if (SleepList = pth->pNextSleepRun) {
SleepList->pPrevSleepRun = 0;
}
}
CLEAR_SLEEPING(pth);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
VOID
MakeRunIfNeeded(
HANDLE hth
)
{
PTHREAD pth;
KCALLPROFON(39);
if ((pth = HandleToThread(hth)) && (GET_RUNSTATE(pth) == RUNSTATE_NEEDSRUN)) {
if (GET_SLEEPING(pth)) {
SleepqDequeue(pth);
pth->wCount ++;
}
MakeRun(pth);
}
KCALLPROFOFF(39);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
VOID
DequeueFlatProxy(
LPPROXY pprox
)
{
LPPROXY pDown;
LPEVENT pObject;
KCALLPROFON(54);
DEBUGCHK((pprox->bType == SH_CURPROC) || (pprox->bType == SH_CURTHREAD) || (pprox->bType == HT_MANUALEVENT));
if (pDown = pprox->pQDown) { // not already dequeued
if (pprox->pQPrev) { // we're first
pObject = ((LPEVENT)pprox->pQPrev);
DEBUGCHK(pObject->pProxList == pprox);
if (pDown == pprox) { // we're alone
pObject->pProxList = 0;
} else {
pDown->pQUp = pprox->pQUp;
pprox->pQUp->pQDown = pObject->pProxList = pDown;
pDown->pQPrev = (LPPROXY)pObject;
}
} else {
pDown->pQUp = pprox->pQUp;
pprox->pQUp->pQDown = pDown;
}
pprox->pQDown = 0;
}
KCALLPROFOFF(54);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
DequeuePrioProxy(
LPPROXY pprox
)
{
LPCRIT lpcrit;
LPPROXY pDown, pNext;
WORD prio;
BOOL bRet;
KCALLPROFON(31);
DEBUGCHK((pprox->bType == HT_EVENT) || (pprox->bType == HT_CRITSEC) || (pprox->bType == HT_MUTEX) || (pprox->bType == HT_SEMAPHORE));
bRet = FALSE;
if (pDown = pprox->pQDown) { // not already dequeued
lpcrit = (LPCRIT)pprox->pObject;
prio = pprox->prio/PRIORITY_LEVELS_HASHSCALE;
pDown = pprox->pQDown;
pNext = pprox->pQNext;
if (lpcrit->pProxHash[prio] == pprox) {
lpcrit->pProxHash[prio] = ((pDown != pprox) ? pDown :
(pNext && (pNext->prio/PRIORITY_LEVELS_HASHSCALE == prio)) ? pNext : 0);
}
if (pDown == pprox) {
if (!pprox->pQPrev) {
DEBUGCHK(lpcrit->pProxList == pprox);
if (lpcrit->pProxList = pNext)
pNext->pQPrev = 0;
bRet = TRUE;
} else {
if (pprox->pQPrev->pQNext = pNext)
pNext->pQPrev = pprox->pQPrev;
}
} else {
pDown->pQUp = pprox->pQUp;
pprox->pQUp->pQDown = pDown;
if (pprox->pQPrev) {
pprox->pQPrev->pQNext = pDown;
pDown->pQPrev = pprox->pQPrev;
goto FinishDequeue;
} else if (pprox == lpcrit->pProxList) {
lpcrit->pProxList = pDown;
DEBUGCHK(!pDown->pQPrev);
FinishDequeue:
if (pNext) {
pNext->pQPrev = pDown;
pDown->pQNext = pNext;
}
}
}
pprox->pQDown = 0;
}
KCALLPROFOFF(31);
return bRet;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
DoReprioCrit(
LPCRIT lpcrit
)
{
HANDLE hth;
PTHREAD pth;
KCALLPROFON(4);
if ((hth = lpcrit->lpcs->OwnerThread) && (pth = HandleToThread((HANDLE)((DWORD)hth & ~1))))
ReprioCritMut(lpcrit,pth);
KCALLPROFOFF(4);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
DoReprioMutex(
LPMUTEX lpm
)
{
KCALLPROFON(29);
if (lpm->pOwner)
ReprioCritMut((LPCRIT)lpm,lpm->pOwner);
KCALLPROFOFF(29);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
DequeueProxy(
LPPROXY pProx
)
{
switch (pProx->bType) {
case SH_CURPROC:
case SH_CURTHREAD:
case HT_MANUALEVENT:
KCall((PKFN)DequeueFlatProxy,pProx);
break;
case HT_MUTEX:
if (KCall((PKFN)DequeuePrioProxy,pProx))
KCall((PKFN)DoReprioMutex,pProx->pObject);
break;
case HT_CRITSEC:
if (KCall((PKFN)DequeuePrioProxy,pProx))
KCall((PKFN)DoReprioCrit,pProx->pObject);
break;
case HT_EVENT:
case HT_SEMAPHORE:
KCall((PKFN)DequeuePrioProxy,pProx);
break;
default:
DEBUGCHK(0);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
BoostCPrio(
PTHREAD pth,
DWORD prio
)
{
DWORD oldcprio;
oldcprio = GET_CPRIO(pth);
SET_CPRIO(pth,prio);
if (GET_RUNSTATE(pth) == RUNSTATE_RUNNABLE) {
RunqDequeue(pth,oldcprio);
MakeRun(pth);
} else if (GET_SLEEPING (pth) && pth->pUpSleep && (GET_RUNSTATE(pth) != RUNSTATE_NEEDSRUN)) {
SleepqDequeue (pth);
SET_NEEDSLEEP (pth);
if (pth->lpce) {
pth->bWaitState = WAITSTATE_PROCESSING; // re-process the wait
}
MakeRun (pth);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
PostBoostMut(
LPMUTEX lpm
)
{
PTHREAD pth;
WORD prio;
KCALLPROFON(56);
if (pCurThread->bWaitState == WAITSTATE_PROCESSING) {
pth = lpm->pOwner;
DEBUGCHK(pth);
prio = GET_CPRIO(pCurThread);
if (prio < GET_CPRIO(pth)) {
BoostCPrio(pth,prio);
if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
CELOG_SystemInvert(pth->hTh, prio);
}
}
if (!GET_NOPRIOCALC(pth))
LaterLinkMutOwner(lpm);
ReprioCritMut((LPCRIT)lpm,pth);
}
KCALLPROFOFF(56);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -