?? kthread.cpp
字號(hào):
//The following function terminal a kernal thread roughly.
//
VOID TerminalKThread(DWORD dwKThreadID)
{
__KTHREAD_CONTROL_BLOCK* pControlBlock = NULL;
DWORD dwStackSize = 0;
if((dwKThreadID < 1) || (dwKThreadID > MAX_KTHREAD_NUM)) //Parameter check.
return;
dwKThreadID --; //Make sure the dwKThreadID is the index
//to allocate the system array.
g_bKThreadQueueStatus[dwKThreadID] = 0; //Free the control block slot.
pControlBlock = g_pKThreadQueue[dwKThreadID];
if(NULL != pControlBlock)
{
dwStackSize = pControlBlock->dwStackSize;
KMemFree((LPVOID)pControlBlock,KMEM_SIZE_TYPE_4K,dwStackSize); //Free the memory.
}
return;
}
//
//Get kernal thread's control block by it's ID.
//If failed,returns NULL,else,returns the pointer of kernal thread's
//control block.
//
__KTHREAD_CONTROL_BLOCK* GetKThreadControlBlock(DWORD dwKThreadID)
{
__KTHREAD_CONTROL_BLOCK* pControlBlock = NULL;
if((0 == dwKThreadID) || (MAX_KTHREAD_NUM == dwKThreadID)) //Parameter check.
{
return pControlBlock;
}
dwKThreadID --;
pControlBlock = g_pKThreadQueue[dwKThreadID];
return pControlBlock;
}
//
//The following function reset the kernal thread's priority by it's ID.
//
VOID SetKThreadPriority(DWORD dwKThreadID,DWORD dwPriority)
{
if((dwKThreadID < 1) || (dwKThreadID > MAX_KTHREAD_NUM)) //Parameter check.
return;
g_pKThreadQueue[dwKThreadID - 1]->dwKThreadPriority = dwPriority;
return;
}
//
//The following function switch to the kernal thread identified by it's control
//block.
//The parameter,pContext,pointing to the CPU context information of the transmited
//kernal thread.
//
__declspec(naked) static VOID SwitchKThread(LPVOID pContext)
{
#ifdef __I386__ //Intel's x86 CPU implementation.
__asm{
cli
push ebp
mov ebp,esp //Build the stack frame.
mov eax,dword ptr [ebp + 0x08] //Now,eax countains the pContext value.
mov esp,dword ptr [eax + 28] //Set the esp value to transmited kernal thread.
push dword ptr [eax + 36] //Push EFlags register to stack.
xor ebx,ebx
mov bx,0x08
push ebx //Extend and push CS to stack.
push dword ptr [eax + 32] //Push EIP to stack.
//Now,we have built the correct stack frame.
push dword ptr [eax] //Save eax to stack.
push dword ptr [eax + 4] //Save ebx to stack.
push dword ptr [eax + 8] //ecx
push dword ptr [eax + 12] //edx
push dword ptr [eax + 16] //esi
push dword ptr [eax + 20] //edi
push dword ptr [eax + 24] //ebp
mov ebp,dword ptr [esp] //Restore the ebp register.
add esp,0x04
mov edi,dword ptr [esp] //Restore edi
add esp,0x04
mov esi,dword ptr [esp] //Restore esi
add esp,0x04
mov edx,dword ptr [esp] //Restore edx
add esp,0x04
mov ecx,dword ptr [esp] //Restore ecx
add esp,0x04
mov ebx,dword ptr [esp] //Restore ebx
add esp,0x04
mov al,0x20
out 0x20,al
out 0xa0,al
mov eax,dword ptr [esp]
add esp,0x04 //Now,the esp pointer points to the current
//position.
sti
iretd
retn //This instruction will never be reached.
}
#else
#endif
}
//
//The following function save the current kernal thread's context.
//The parameter,dwEsp,is the esp register's value before the TimerHandler is called,
//the general registers' value of the interrupted kernal thread are saved into stack,
//the stack frame,before the TimerHandler is called,as following:
//EFlags / (DWORD)CS / EIP / EAX / EBX / ECX / EDX / ESI / EDI / EBP / ESP,where ESP
//is the value after the EBP is pushed.
//So,we can access the general registers' value of the current kernal thread by dwEsp
//parameter.
//
static VOID SaveKThreadContext(__KTHREAD_CONTROL_BLOCK* pControlBlock,DWORD dwEsp)
{
DWORD* pdwEsp = (DWORD*)dwEsp;
if(NULL == pControlBlock) //Parameter check.
return;
#ifdef __I386__
pControlBlock->dwEBP = *pdwEsp;
pdwEsp ++;
pControlBlock->dwEDI = *pdwEsp;
pdwEsp ++;
pControlBlock->dwESI = *pdwEsp;
pdwEsp ++;
pControlBlock->dwEDX = *pdwEsp;
pdwEsp ++;
pControlBlock->dwECX = *pdwEsp;
pdwEsp ++;
pControlBlock->dwEBX = *pdwEsp;
pdwEsp ++;
pControlBlock->dwEAX = *pdwEsp;
pdwEsp ++;
pControlBlock->dwEIP = *pdwEsp;
pdwEsp ++;
pdwEsp ++; //Skip the CS's space.
pControlBlock->dwEFlags = *pdwEsp;
pdwEsp ++;
pControlBlock->dwESP = (DWORD)pdwEsp;
#else
#endif
}
//
//The following function re-schedule the kernal thread.
//It saves the current kernal thread's context,
//select a proper kernal thread,and schedule it to run.
//
VOID ScheduleKThread(DWORD dwEsp) //The dwEsp parameter is the esp value
//before the TimerHandler is called.
//We can access the current kernal
//thread's context,such as general
//registers by this parameter.
{
DWORD dwKThreadID = g_dwCurrentKThreadID;
DWORD dwIndex = 0;
__KTHREAD_CONTROL_BLOCK* pControlBlock = NULL;
__KTHREAD_CONTROL_BLOCK* pCurrControlBlock = NULL;
LPVOID pContext = NULL;
//BYTE Buffer[12]; //---------- ** debug ** ------------
//static DWORD dwTmp = 0;
//dwTmp ++;
//DisableInterrupt(); //Disable interrupt.
//******************
if(NULL == g_pReadyQueue) //If there is not any ready kernal thread.
goto __TERMINAL;
if(0 == dwKThreadID)
{
goto __TERMINAL;
}
pControlBlock = g_pKThreadQueue[dwKThreadID - 1]; //Get the current kernal thread's
//control block.
pCurrControlBlock = pControlBlock;
if(NULL == pControlBlock->pNext)
pControlBlock = g_pReadyQueue;
else
{
if(KTHREAD_STATUS_READY == pControlBlock->pNext->dwKThreadStatus)
pControlBlock = pControlBlock->pNext;
else
pControlBlock = g_pReadyQueue;
}
if(NULL == pControlBlock) //If there is not any ready kernal
//thread to schedule.
goto __TERMINAL;
if(KTHREAD_STATUS_READY == pControlBlock->dwKThreadStatus)
{
/*if(dwTmp % 10 == 0)
{
PrintLine("------------- ** debug ** -----------------"); //---- ** debug ** ----
Hex2Str((DWORD)pCurrControlBlock,Buffer);
PrintLine(Buffer);
Hex2Str((DWORD)pControlBlock,Buffer);
PrintLine(Buffer);
}*/
SaveKThreadContext(pCurrControlBlock,dwEsp);
g_dwCurrentKThreadID = pControlBlock->dwKThreadID;
#ifdef __I386__
pContext = (LPVOID)&pControlBlock->dwEAX;
#else
#endif
SwitchKThread(pContext);
goto __TERMINAL;
}
__TERMINAL:
//EnableInterrupt();
return;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -