www.pudn.com > WinGOS.rar > Kernel.cpp


#include "GOS.h" 
#include "kernel.h" 
 
#define TABLE_INSERT(aTable,pPrev,pIns) \ 
	if(pPrev){pIns->m_pNext=pPrev->m_pNext; pPrev->m_pNext=pIns;} \ 
	else {pIns->m_pNext=aTable;aTable=pIns;} 
#define TABLE_REMOVE(aTable,pPrev,pNext) \ 
	if(pPrev)pPrev->m_pNext=pNext;else aTable=pNext; 
 
CKernel* g_pKernel; 
 
BOOL CKernel::m_bLockSwitch; 
DWORD CKernel::m_nSwitchTime; 
CThread* CKernel::m_pCurThread; 
CThread* CKernel::m_aThreadTable; 
CCriticalSection CKernel::m_klock; 
 
BOOL CKernel::CreateThread(PVOID pBlock) 
{ 
	m_nPriority=PriorityTimeCritical; 
	m_nWakeTime=GetTickCount(); 
	m_pStack=PVOID(DWORD(pBlock)+_msize(pBlock)-sizeof(DWORD)); 
	m_heap.Create(pBlock); 
	m_pNext=NULL; 
 
	m_bLockSwitch=FALSE; 
	m_nSwitchTime=m_nWakeTime+MAXLONG; 
	m_pCurThread=this; 
	m_aThreadTable=this; 
	return TRUE; 
} 
 
BOOL CKernel::ExitThread(DWORD dwExitCode) 
{ 
	MsgProc(msgExitThread,dwExitCode,0); 
	SetLastError(dwExitCode); 
	RemoveAllMessage(); 
	m_heap.Delete(); 
	g_pKernel->ThreadTableRemove(this); 
	return TRUE; 
} 
 
BOOL CKernel::ThreadTableAdd(CThread* pThread,int nPriority) 
{ 
	PTHREAD pTmp,pPrev=NULL; 
	if(!nPriority) 
		nPriority=PriorityNormal; 
	pThread->m_nPriority=nPriority; 
	g_pKernel->m_klock.Lock(INFINITE); 
	for(pTmp=m_aThreadTable;pTmp;pPrev=pTmp,pTmp=pTmp->m_pNext) 
	{ 
		if(pTmp->m_nPriority>nPriority) 
			break; 
	} 
	TABLE_INSERT(m_aThreadTable,pPrev,pThread); 
	g_pKernel->m_klock.Unlock(); 
	return TRUE; 
} 
BOOL CKernel::ThreadTableRemove(CThread* pThread) 
{ 
	PTHREAD pTmp,pPrev=NULL; 
	g_pKernel->m_klock.Lock(INFINITE); 
	for(pTmp=m_aThreadTable;pTmp;pPrev=pTmp,pTmp=pTmp->m_pNext) 
	{ 
		if(pTmp==pThread) 
		{ 
			TABLE_REMOVE(m_aThreadTable,pPrev,pThread->m_pNext); 
			break; 
		} 
	} 
	pThread->m_nPriority=0; 
	g_pKernel->m_klock.Unlock(); 
	return BOOL(pTmp); 
} 
 
BOOL CKernel::SetPriority(CThread* pThread,int nPriority) 
{ 
	PTHREAD pTmp,pOldPrev=NULL,pNewPrev=NULL; 
	if(!nPriority)nPriority=PriorityNormal; 
	g_pKernel->m_klock.Lock(INFINITE); 
	for(pTmp=m_aThreadTable;pTmp;pOldPrev=pTmp,pTmp=pTmp->m_pNext) 
	{ 
		if(pTmp==pThread) 
			break; 
	} 
	for(pTmp=m_aThreadTable;pTmp;pNewPrev=pTmp,pTmp=pTmp->m_pNext) 
	{ 
		if(pTmp->m_nPriority>nPriority) 
			break; 
	} 
	if(pNewPrev==pOldPrev || pNewPrev==pThread); 
	else if(pThread==m_pCurThread) 
	{ 
		pTmp=pThread->m_pNext; 
		TABLE_INSERT(m_aThreadTable,pNewPrev,pThread); 
		TABLE_REMOVE(m_aThreadTable,pOldPrev,pTmp); 
	} 
	else 
	{ 
		TABLE_REMOVE(m_aThreadTable,pOldPrev,pThread->m_pNext); 
		TABLE_INSERT(m_aThreadTable,pNewPrev,pThread); 
	} 
	pThread->m_nPriority=nPriority; 
	g_pKernel->m_klock.Unlock(); 
	return TRUE; 
} 
 
void CKernel::UnlockSwitch() 
{ 
	LONG nCurTime=GetTickCount(); 
	m_bLockSwitch=FALSE; 
	if(LONG(nCurTime-m_nSwitchTime)>=0) 
		SwitchToThread(); 
} 
 
PVOID CKernel::MemoryAlloc(PVOID pBlock,DWORD nSize) 
{ 
	g_pKernel->m_klock.Lock(INFINITE); 
	pBlock=g_pKernel->m_heap.ReAlloc(pBlock,nSize); 
	g_pKernel->m_klock.Unlock(); 
	return pBlock; 
} 
 
BOOL CKernel::SwitchThread() 
{ 
	PTHREAD pTmp,pPrev=NULL,pRun=NULL; 
	LONG nCurTime=GetTickCount(); 
	LONG nWake,nMinWake=nCurTime+MAXLONG; 
 
	for(pTmp=m_aThreadTable;pTmp;pTmp=pTmp->m_pNext) 
	{ 
		nWake=pTmp->m_nWakeTime; 
		if(LONG(nWake-nCurTime)<=0) 
		{ 
			pRun=pTmp; 
			break; 
		} 
		if(pTmp->m_pWaitObject) 
		{ 
			pRun=pTmp->m_pWaitObject->FindProxy(pTmp,nCurTime); 
			if(pRun)break; 
		} 
		if(LONG(nMinWake-nWake)>0) 
			nMinWake=nWake; 
		pPrev=pTmp; 
	} 
	if(pRun) 
	{ 
		PTHREAD pTmp2,pPrev2=NULL; 
		USHORT nPri=pTmp->m_nPriority; 
		for(pTmp2=pTmp->m_pNext;pTmp2;pPrev2=pTmp2,pTmp2=pTmp2->m_pNext) 
		{ 
			if(pTmp2->m_nPriority!=nPri) 
				break; 
		} 
		if(pPrev2) 
		{ 
			TABLE_REMOVE(m_aThreadTable,pPrev,pTmp->m_pNext); 
			pTmp->m_pNext=pPrev2->m_pNext; 
			pPrev2->m_pNext=pTmp; 
			if(LONG(nMinWake-nCurTime)>ThreadSwitchInterval) 
				nMinWake=nCurTime+ThreadSwitchInterval; 
		} 
		pRun->m_nWakeTime=nCurTime; 
		if(pRun!=m_pCurThread) 
		{ 
			pTmp=m_pCurThread; 
			m_pCurThread=pRun; 
			g_pHAL->SwitchThread(pTmp,pRun); 
		} 
	} 
	m_nSwitchTime=nMinWake; 
	g_pHAL->OnSwitchThread(!pRun); 
 
	return TRUE; 
}