📄 schedule.c
字号:
pTh->hTh = hTh; pTh->pcstkTop = 0; pTh->bSuspendCnt = 0; pTh->wInfo = 0; pTh->bWaitState = WAITSTATE_SIGNALLED; pTh->lpCritProxy = 0; pTh->lpProxy = 0; pTh->lpce = 0; pTh->dwLastError = 0; pTh->dwUserTime = 0; pTh->dwKernTime = 0; pTh->dwQuantLeft = 0; pTh->dwQuantum = dwDefaultThreadQuantum; SET_BPRIO(pTh,prio); SET_CPRIO(pTh,prio); pTh->pOwnedList = 0; memset(pTh->pOwnedHash,0,sizeof(pTh->pOwnedHash)); pTh->pSwapStack = 0; return TRUE;}DWORD ThreadSuspend(PTHREAD pth) { DWORD retval, cprio; ACCESSKEY ulOldKey; KCALLPROFON(5); SWITCHKEY(ulOldKey,0xffffffff); if (!pth) { KSetLastError(pCurThread,ERROR_INVALID_PARAMETER); retval = 0xffffffff; } else if ((pth == pCurThread) && GET_DYING(pCurThread) && !GET_DEAD(pCurThread)) { KSetLastError(pCurThread,ERROR_INVALID_PARAMETER); retval = 0xfffffffe; } else if ((pth->bWaitState == WAITSTATE_PROCESSING) || (((GET_RUNSTATE(pth) == RUNSTATE_RUNNABLE) || (GET_RUNSTATE(pth) == RUNSTATE_NEEDSRUN)) && !GET_NEEDDBG(pth) && (((GetThreadIP(pth) >= pTOC->physfirst) && (GetThreadIP(pth) < pTOC->physlast) && !GET_USERBLOCK(pth)) || (csDbg.OwnerThread == pth->hTh) || (ModListcs.OwnerThread == pth->hTh) || (LLcs.OwnerThread == pth->hTh) || (DbgApiCS.OwnerThread == pth->hTh)))) { KSetLastError(pCurThread,ERROR_INVALID_PARAMETER); retval = 0xfffffffe; } else { retval = pth->bSuspendCnt; if (pth->bSuspendCnt) { if (pth->bSuspendCnt != MAX_SUSPEND_COUNT) pth->bSuspendCnt++; else { KSetLastError(pCurThread,ERROR_SIGNAL_REFUSED); retval = 0xffffffff; } } else { pth->bSuspendCnt = 1; switch (GET_RUNSTATE(pth)) { case RUNSTATE_RUNNING: DEBUGCHK(RunList.pth == pth); RunList.pth = 0; SetReschedule(); break; case RUNSTATE_RUNNABLE: cprio = GET_CPRIO(pth); RunqDequeue(pth,cprio); break; case RUNSTATE_NEEDSRUN: if (GET_SLEEPING(pth)) SleepqDequeue(pth); break; }// DEBUGCHK(!((pth->wInfo >> DEBUG_LOOPCNT_SHIFT) & 1)); SET_RUNSTATE(pth,RUNSTATE_BLOCKED); } } SETCURKEY(ulOldKey); KCALLPROFOFF(5); return retval;}/* When a thread gets SuspendThread() */DWORD SC_ThreadSuspend(HANDLE hTh) { DWORD retval; DEBUGMSG(ZONE_ENTRY,(L"SC_ThreadSuspend entry: %8.8lx\r\n",hTh)); if (hTh == GetCurrentThread()) hTh = hCurThread; CELOG_ThreadSuspend(hTh); retval = KCall((PKFN)ThreadSuspend,HandleToThread(hTh)); if (retval == 0xfffffffe) retval = 0xffffffff; DEBUGMSG(ZONE_ENTRY,(L"SC_ThreadSuspend exit: %8.8lx\r\n",retval)); return retval;}DWORD UB_ThreadSuspend(HANDLE hTh) { DWORD retval; if ((hTh == (HANDLE)GetCurrentThread()) || (hTh == hCurThread)) SET_USERBLOCK(pCurThread); retval = SC_ThreadSuspend(hTh); if ((hTh == (HANDLE)GetCurrentThread()) || (hTh == hCurThread)) CLEAR_USERBLOCK(pCurThread); return retval;}DWORD ThreadResume(PTHREAD pth) { DWORD retval = 0; KCALLPROFON(47); if (pth && (retval = pth->bSuspendCnt) && !--pth->bSuspendCnt && (GET_RUNSTATE(pth) == RUNSTATE_BLOCKED) && !GET_SLEEPING(pth) && !pth->lpProxy) MakeRun(pth); CELOG_ThreadResume(pth->hTh); KCALLPROFOFF(47); return retval;}/* When a thread gets ResumeThread() */DWORD SC_ThreadResume(HANDLE hTh) { DWORD retval; DEBUGMSG(ZONE_ENTRY,(L"SC_ThreadResume entry: %8.8lx\r\n",hTh)); if (hTh == GetCurrentThread()) hTh = hCurThread; retval = KCall((PKFN)ThreadResume,HandleToThread(hTh)); DEBUGMSG(ZONE_ENTRY,(L"SC_ThreadResume exit: %8.8lx\r\n",retval)); return retval;}void ThreadYield(void) { KCALLPROFON(35); DEBUGCHK(GET_RUNSTATE(pCurThread) == RUNSTATE_RUNNING); DEBUGCHK(RunList.pth == pCurThread); RunList.pth = 0; SetReschedule(); MakeRun(pCurThread); KCALLPROFOFF(35);}typedef struct sleeper_t { PTHREAD pth; WORD wCount; WORD wPad; DWORD dwMilli; DWORD dwRemain;} sleeper_t;DWORD PutThreadToSleep(sleeper_t *pSleeper) { PTHREAD pth, pth2; PTHREAD *pPrevNext; KCALLPROFON(2); DEBUGCHK(!GET_SLEEPING(pCurThread)); if (!GET_DYING(pCurThread) || GET_DEAD(pCurThread) || !GET_USERBLOCK(pCurThread)) { if (pth = pSleeper->pth) { if (pth->wCount != pSleeper->wCount) { pSleeper->pth = 0; KCALLPROFOFF(2); return 1; }#ifdef DEBUG if (pth->wCount == 0xabab && (DWORD) pth->pProc == 0xabababab) { DEBUGMSG(1, (TEXT("PutThreadToSleep : restarting...\r\n"))); pSleeper->pth = 0; KCALLPROFOFF(2); return 1; }#endif DEBUGCHK((GET_RUNSTATE(pth) == RUNSTATE_BLOCKED) || (GET_RUNSTATE(pth) == RUNSTATE_NEEDSRUN)); DEBUGCHK(GET_SLEEPING(pth)); pPrevNext = &pth->pNextSleepRun; } else pPrevNext = &SleepList; if (pCurThread->pNextSleepRun = pth2 = *pPrevNext) { if ((pth2->dwSleepCnt < pSleeper->dwMilli) || ((pth2->dwSleepCnt == pSleeper->dwMilli) && (GET_CPRIO(pth2) <= GET_CPRIO(pCurThread)))) { pSleeper->dwRemain = pth2->dwSleepCnt; pSleeper->wCount = pth2->wCount; pSleeper->pth = pth2; KCALLPROFOFF(2); return 1; } pth2->pPrevSleepRun = pCurThread; pth2->dwSleepCnt -= pSleeper->dwMilli; } *pPrevNext = pCurThread; pCurThread->pPrevSleepRun = pth; pCurThread->dwSleepCnt = pSleeper->dwMilli; if (pPrevNext == &SleepList) dwSleepMin = pCurThread->dwSleepCnt; RunList.pth = 0; SetReschedule(); DEBUGCHK(!((pCurThread->wInfo >> DEBUG_LOOPCNT_SHIFT) & 1)); SET_RUNSTATE(pCurThread,RUNSTATE_BLOCKED); SET_SLEEPING(pCurThread); } KCALLPROFOFF(2); return 0;}void ThreadSleep(HTHREAD hth, DWORD time) { DWORD dwDiff, dwStart, period; sleeper_t sleeper; sleeper.pth = 0; dwStart = CurMSec; period = 1 + DiffMSec + ticksleft; // assume 1ms clock resolution if (time + period < time) { period = time; time = 0xffffffff; } else { time += period; period = time - period; } sleeper.dwMilli = time; sleeper.dwRemain = 0; while (KCall((PKFN)PutThreadToSleep,&sleeper) && ((dwDiff = CurMSec - dwStart) < period)) sleeper.dwMilli = (sleeper.pth ? sleeper.dwMilli - sleeper.dwRemain : time - dwDiff);}void SC_Sleep(DWORD cMilliseconds) { DEBUGMSG(ZONE_ENTRY,(L"SC_Sleep entry: %8.8lx\r\n",cMilliseconds)); CELOG_Sleep(cMilliseconds); if (cMilliseconds == INFINITE) KCall((PKFN)ThreadSuspend,pCurThread); else if (!cMilliseconds) KCall((PKFN)ThreadYield); else ThreadSleep(hCurThread,cMilliseconds); DEBUGMSG(ZONE_ENTRY,(L"SC_Sleep exit\r\n"));}void UB_Sleep(DWORD cMilliseconds) { SET_USERBLOCK(pCurThread); SC_Sleep(cMilliseconds); CLEAR_USERBLOCK(pCurThread);}void ZeroTLS(PTHREAD pth) { memset(pth->tlsPtr,0,4*TLS_MINIMUM_AVAILABLE);}/* Creates a thread in a process */HANDLE DoCreateThread(LPVOID lpStack, DWORD cbStack, LPVOID lpStart, LPVOID param, DWORD flags, LPDWORD lpthid, ulong mode, WORD prio) { PTHREAD pth, pdbgr; HANDLE hth; LPBYTE pSwapStack; DEBUGMSG(ZONE_SCHEDULE,(TEXT("Scheduler: DoCreateThread(%8.8lx, %8.8lx, %8.8lx, %8.8lx, %8.8lx, %8.8lx, %8.8lx %8.8lx)\r\n"), hCurThread,hCurProc,cbStack,lpStart,param,flags,lpthid,prio)); if (!TBFf) { KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY); return 0; } if (flags & 0x80000000) pSwapStack = 0; else if (!(pSwapStack = GetHelperStack())) { KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY); return 0; } pth = AllocMem(HEAP_THREAD); if (!pth) { FreeHelperStack(pSwapStack); KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY); return 0; } hth = AllocHandle(&cinfThread,pth,pCurProc); if (!hth) { FreeHelperStack(pSwapStack); FreeMem(pth,HEAP_THREAD); KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY); return 0; } IncRef(hth,pCurProc); if (!InitThreadStruct(pth,hth,pCurProc,hCurProc,prio)) { FreeHelperStack(pSwapStack); FreeMem(pth,HEAP_THREAD); FreeHandle(hth); KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY); return 0; } pth->pSwapStack = pSwapStack; GCFT(&pth->ftCreate); if (flags & 0x80000000) { SET_DYING(pth); SET_DEAD(pth); MDCreateThread(pth, lpStack, cbStack, lpStart, param, pCurProc->dwVMBase, mode, (ulong)param); } else if (flags & 0x40000000) MDCreateThread(pth, lpStack, cbStack, (LPVOID)lpStart, param, pCurProc->dwVMBase, mode, (ulong)param); else MDCreateThread(pth, lpStack, cbStack, (LPVOID)TBFf, lpStart, pCurProc->dwVMBase, mode, (ulong)param); ZeroTLS(pth); pth->bSuspendCnt = 1; EnterCriticalSection(&DbgApiCS); if (pCurProc->hDbgrThrd) { pdbgr = HandleToThread(pCurProc->hDbgrThrd); DEBUGCHK(pdbgr); pth->pThrdDbg = AllocDbg(hCurProc); DEBUGCHK(pth->pThrdDbg); pth->pThrdDbg->hNextThrd = pdbgr->pThrdDbg->hFirstThrd; pdbgr->pThrdDbg->hFirstThrd = hth; IncRef(pth->hTh,pdbgr->pOwnerProc); } DEBUGCHK(!((pth->wInfo >> DEBUG_LOOPCNT_SHIFT) & 1)); SET_RUNSTATE(pth,RUNSTATE_BLOCKED); // Save off the thread's program counter for getting its name later. pth->dwStartAddr = (DWORD) lpStart; CELOG_ThreadCreate(pth, pth->pOwnerProc->hProc, NULL); if (pLogThreadCreate) pLogThreadCreate((DWORD)pth,(DWORD)pCurProc); KCall((PKFN)AddToProcRunnable,pCurProc,pth); LeaveCriticalSection(&DbgApiCS); if (!(flags & CREATE_SUSPENDED)) KCall((PKFN)ThreadResume,pth); if (lpthid) *lpthid = (DWORD)hth; return hth;}// Creates a threadHANDLE SC_CreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParm, DWORD fdwCreate, LPDWORD lpIDThread) { HANDLE retval; LPVOID lpStack; DEBUGMSG(ZONE_ENTRY,(L"SC_CreateThread entry: %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx\r\n", lpsa,cbStack,lpStartAddr,lpvThreadParm,fdwCreate,lpIDThread)); if (PageFreeCount < (48*1024/PAGE_SIZE)) { KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY); DEBUGMSG(ZONE_ENTRY,(L"SC_CreateThread exit: %8.8lx\r\n",0)); return 0; } if (fdwCreate & ~(CREATE_SUSPENDED)) { KSetLastError(pCurThread,ERROR_INVALID_PARAMETER); DEBUGMSG(ZONE_ENTRY,(L"SC_CreateThread exit: %8.8lx\r\n",0)); return 0; } lpStack = VirtualAlloc((LPVOID)pCurProc->dwVMBase,pCurProc->e32.e32_stackmax,MEM_RESERVE|MEM_AUTO_COMMIT,PAGE_NOACCESS); if (!lpStack) { KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY); DEBUGMSG(ZONE_ENTRY,(L"SC_CreateThread exit: %8.8lx\r\n",0)); return 0; } if (!VirtualAlloc((LPVOID)((DWORD)lpStack+pCurProc->e32.e32_stackmax-MIN_STACK_SIZE),MIN_STACK_SIZE, MEM_COMMIT,PAGE_READWRITE)) { VirtualFree(lpStack,0,MEM_RELEASE); KSetLastError(pCurThread,ERROR_NOT_ENOUGH_MEMORY); DEBUGMSG(ZONE_ENTRY,(L"SC_CreateThread exit: %8.8lx\r\n",0)); return 0; } retval = DoCreateThread(lpStack, pCurProc->e32.e32_stackmax, (LPVOID)lpStartAddr, lpvThreadParm, fdwCreate, lpIDThread, TH_UMODE,THREAD_RT_PRIORITY_NORMAL); if (!retval) { VirtualFree(lpStack,pCurProc->e32.e32_stackmax,MEM_DECOMMIT); VirtualFree(lpStack,0,MEM_RELEASE); } DEBUGMSG(ZONE_ENTRY,(L"SC_CreateThread exit: %8.8lx\r\n",retval)); return retval;}// Creates a kernel threadHANDLE CreateKernelThread(LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParm, WORD prio, DWORD dwFlags) { LPVOID lpStack; if (!(lpStack = VirtualAlloc((LPVOID)ProcArray[0].dwVMBase,KRN_STACK_SIZE,MEM_RESERVE|MEM_AUTO_COMMIT,PAGE_NOACCESS))) return 0; if (!VirtualAlloc((LPVOID)((DWORD)lpStack+KRN_STACK_SIZE-MIN_STACK_SIZE),MIN_STACK_SIZE,MEM_COMMIT,PAGE_READWRITE)) { VirtualFree(lpStack,0,MEM_RELEASE); return 0; } return DoCreateThread(lpStack, KRN_STACK_SIZE, (LPVOID)lpStartAddr, lpvThreadParm, dwFlags, 0, TH_KMODE, prio);}BOOL SetThreadBasePrio(HANDLE hth, DWORD nPriority) { BOOL bRet; PTHREAD pth; DWORD oldb, oldc, prio; KCALLPROFON(28); bRet = FALSE; if (pth = HandleToThread(hth)) { oldb = GET_BPRIO(pth); if (oldb != nPriority) { oldc = GET_CPRIO(pth); SET_BPRIO(pth,(WORD)nPriority); if (pCurThread == pth) { if (pCurThread->pOwnedList && ((prio = pCurThread->pOwnedList->bListedPrio) < nPriority)) nPriority = prio; if (nPriority != GET_CPRIO(pCurThread)) { SET_CPRIO(pCurThread,nPriority); if (RunList.pRunnable && (nPriority > GET_CPRIO(RunList.pRunnable))) SetReschedule(); } } else if (nPriority < oldc) { SET_CPRIO(pth,nPriority); if (GET_RUNSTATE(pth) == RUNSTATE_RUNNABLE) { RunqDequeue(pth,oldc); MakeRun(pth); } } } bRet = TRUE; } KCALLPROFOFF(28); return bRet;}typedef struct sttd_t { HANDLE hThNeedRun; HANDLE hThNeedBoost;} sttd_t;HANDLE SetThreadToDie(HANDLE hTh, DWORD dwExitCode, sttd_t *psttd) { PTHREAD pth; HANDLE hRet; DWORD prio; LPPROXY pprox; KCALLPROFON(17); if (!hTh) hRet = pCurProc->pTh->hTh; else if (!(pth = HandleToThread(hTh))) hRet = 0; else { hRet = pth->pNextInProc ? pth->pNextInProc->hTh : 0; if (!GET_DYING(pth) && !GET_DEAD(pth)) { SET_DYING(pth); pth->tlsPtr[TLSSLOT_KERNEL] |= TLSKERN_TRYINGTODIE; SetUserInfo(hTh,dwExitCode); psttd->hThNeedBoost = hTh; switch (GET_RUNSTATE(pth)) { case RUNSTATE_RUNNABLE: if ((pth->pOwnerProc == pth->pProc) && (LLcs.OwnerThread != hTh) && !(GetThreadIP(pth) & 0x80000000)) { if (pth->bWaitState == WAITSTATE_PROCESSING) { if (pth->lpce) { pth->lpce->base = pth->lpProxy; pth->lpce->size = (DWORD)pth->lpPendProxy; } else if (pprox = pth->lpProxy) { // must be an interrupt event - special case it! DEBUGCHK(pprox->bType == HT_MANUALEVENT); DEBUGCHK(((LPEVENT)pprox->pObject)->pProxList == pprox); ((LPEVENT)pprox->pObject)->pProxList = 0; pprox->pQDown = 0; } pth->lpProxy = 0; pth->wCount++; pth->bWaitState = WAITSTATE_SIGNALLED; } else if (!pth->pcstkTop || ((DWORD)pth->pcstkTop->pprcLast >= 0x10000)) { prio = GET_CPRIO(pth); RunqDequeue(pth,prio); SetThreadIP(pth, pExitThread);#ifdef THUMBSUPPORT if ((DWORD)pExitThread & 1) pth->ctx.Psr |= THUMB_STATE; else pth->ctx.Psr &= ~THUMB_ST
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -