📄 schedule.c
字号:
}
#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);
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 thread
HANDLE 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 thread
HANDLE 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -