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

📄 schedule.c

📁 See Hanoi.cpp for the implementation of this cla
💻 C
📖 第 1 页 / 共 5 页
字号:
	}
#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 + -