⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 schedule.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -