📄 ktmgr.cpp
字号:
__LEAVE_CRITICAL_SECTION(NULL,dwFlags)
return TRUE;
}
//
//The following routine is used to lock a kernel thread,especially the current kernel thread.
//When a kernel thread is locked,it can not be interrupted,even a kernel thread with high priority
//ready to run.The different between lock kernel thread and lock interrupt is,when interrupt is
//locked,the system will never be interrupted by hardware,and the schedule will never occur,because
//timer interrupt also be locked,but when lock a kernel thread,only disables the schedule of the
//system,interrupt is not locked,so,hardware interrupt can also be processed by system.
//CAUTION: When lock a kernel thread,you must unlock it by calling UnlockKernelThread routine to
//unlock the kernel thread,otherwise,others kernel thread(s) will never be scheduled.
//
static BOOL LockKernelThread(__COMMON_OBJECT* lpThis,__COMMON_OBJECT* lpThread)
{
__KERNEL_THREAD_MANAGER* lpManager = NULL;
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
DWORD dwFlags = 0L;
if(NULL == lpThis) //Parameter check.
return FALSE;
lpManager = (__KERNEL_THREAD_MANAGER*)lpThis;
//ENTER_CRITICAL_SECTION();
__ENTER_CRITICAL_SECTION(NULL,dwFlags)
lpKernelThread = (NULL == lpThread) ? lpManager->lpCurrentKernelThread :
(__KERNEL_THREAD_OBJECT*)lpThread; //If lpThread is NULL,then lock the current kernel thread.
if(KERNEL_THREAD_STATUS_RUNNING != lpKernelThread->dwThreadStatus)
{
//LEAVE_CRITICAL_SECTION();
__LEAVE_CRITICAL_SECTION(NULL,dwFlags)
return FALSE;
}
lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED; //Once mark the status of
//the target thread to
//BLOCKED,it will never be
//switched out.
//LEAVE_CRITICAL_SECTION();
__LEAVE_CRITICAL_SECTION(NULL,dwFlags)
return TRUE;
}
//
//The following routine unlockes a kernel thread who is locked by LockKernelThread routine.
//
static VOID UnlockKernelThread(__COMMON_OBJECT* lpThis,__COMMON_OBJECT* lpThread)
{
__KERNEL_THREAD_MANAGER* lpManager = NULL;
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
DWORD dwFlags = 0L;
if(NULL == lpThis) //Parameter check.
return;
lpManager = (__KERNEL_THREAD_MANAGER*)lpThis;
//ENTER_CRITICAL_SECTION();
__ENTER_CRITICAL_SECTION(NULL,dwFlags)
lpKernelThread = (NULL == lpThread) ? lpManager->lpCurrentKernelThread :
(__KERNEL_THREAD_OBJECT*)lpThread;
if(KERNEL_THREAD_STATUS_BLOCKED != lpKernelThread->dwThreadStatus) //If not be locked.
{
//LEAVE_CRITICAL_SECTION();
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return;
}
lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
//LEAVE_CRITICAL_SECTION();
__LEAVE_CRITICAL_SECTION(NULL,dwFlags)
return;
}
/**************************************************************
***************************************************************
***************************************************************
**************************************************************/
//
//The definition of Kernel Thread Manager.
//
__KERNEL_THREAD_MANAGER KernelThreadManager = {
0L, //dwCurrentIRQL.
NULL, //CurrentKernelThread.
NULL, //lpRunningQueue.
NULL, //lpReadyQueue.
NULL, //lpSuspendedQueue.
NULL, //lpSleepingQueue.
NULL, //lpTerminalQueue.
//0L, //dwClockTickCounter.
0L, //dwNextWakeupTick.
KernelThreadMgrInit, //Initialize routine.
CreateKernelThread, //CreateKernelThread routine.
DestroyKernelThread, //DestroyKernelThread routine.
SuspendKernelThread, //SuspendKernelThread routine.
ResumeKernelThread, //ResumeKernelThread routine.
ScheduleFromProc, //ScheduleFromProc routine.
ScheduleFromInt, //ScheduleFromInt routine.
SetThreadPriority, //SetThreadPriority routine.
GetThreadPriority, //GetThreadPriority routine.
TerminalKernelThread, //TerminalKernelThread routine.
Sleep, //Sleep routine.
CancelSleep, //CancelSleep routine.
SetCurrentIRQL, //SetCurrentIRQL routine.
GetCurrentIRQL, //GetCurrentIRQL routine.
GetLastError, //GetLastError routine.
SetLastError, //SetLastError routine.
GetThreadID, //GetThreadID routine.
GetThreadStatus, //GetThreadStatus routine.
SetThreadStatus, //SetThreadStatus routine.
MgrSendMessage, //SendMessage routine.
MgrGetMessage, //GetMessage routine.
MsgQueueFull, //MsgQueueFull routine.
MsgQueueEmpty, //MsgQueueEmpty routine.
LockKernelThread, //LockKernelThread routine.
UnlockKernelThread //UnlockKernelThread routine.
};
//
/***************************************************************************************
****************************************************************************************
****************************************************************************************
****************************************************************************************
***************************************************************************************/
//
//
//KernelThreadWrapper routine.
//The routine is all kernel thread's entry porint.
//The routine does the following:
// 1. Calles the kernel thread's start routine;
// 2. When the start routine is over,put the kernel thread object into terminal queue;
// 3. Wakeup all kernel thread(s) waiting for this kernel thread object.
// 4. Reschedule all kernel thread(s).
//This routine will never return.
//
static VOID KernelThreadWrapper(__COMMON_OBJECT* lpKThread)
{
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
__KERNEL_THREAD_OBJECT* lpWaitingThread = NULL;
__PRIORITY_QUEUE* lpWaitingQueue = NULL;
__PRIORITY_QUEUE* lpReadyQueue = NULL;
DWORD dwRetValue = 0L;
DWORD dwFlags = 0L;
if(NULL == lpKThread) //Parameter check.
goto __TERMINAL;
lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpKThread;
if(NULL == lpKernelThread->KernelThreadRoutine) //If the main routine is empty.
goto __TERMINAL;
dwRetValue = lpKernelThread->KernelThreadRoutine(lpKernelThread->lpRoutineParam);
//ENTER_CRITICAL_SECTION();
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
lpKernelThread->dwReturnValue = dwRetValue; //Set the return value of this thread.
lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_TERMINAL; //Change the status.
//LEAVE_CRITICAL_SECTION();
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
//
//The following code wakeup all kernel thread(s) who waiting for this kernel thread
//object.
//
lpWaitingQueue = lpKernelThread->lpWaitingQueue;
lpReadyQueue = KernelThreadManager.lpReadyQueue;
lpWaitingThread = (__KERNEL_THREAD_OBJECT*)lpWaitingQueue->GetHeaderElement((__COMMON_OBJECT*)lpWaitingQueue,
NULL);
while(lpWaitingThread)
{
lpWaitingThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
lpReadyQueue->InsertIntoQueue((__COMMON_OBJECT*)lpReadyQueue,
(__COMMON_OBJECT*)lpWaitingThread,
lpWaitingThread->dwScheduleCounter);
lpWaitingThread = (__KERNEL_THREAD_OBJECT*)lpWaitingQueue->GetHeaderElement(
(__COMMON_OBJECT*)lpWaitingQueue,
NULL);
}
__TERMINAL:
KernelThreadManager.lpTerminalQueue->InsertIntoQueue((__COMMON_OBJECT*)KernelThreadManager.lpTerminalQueue,
(__COMMON_OBJECT*)lpKernelThread,
0L); //Insert the current kernel thread object into TERMINAL queue.
//DisableInterrupt();
//KernelThreadManager.lpCurrentKernelThread = NULL; //Change the current kernel thread to
//NULL.
//EnableInterrupt();
//
//The following code fetch the first READY kernel thread from Ready Queue,restore it's
//context,and switch to this kernel thread to continue running.
//
lpKernelThread = (__KERNEL_THREAD_OBJECT*)KernelThreadManager.lpReadyQueue->GetHeaderElement(
(__COMMON_OBJECT*)KernelThreadManager.lpReadyQueue,
NULL);
if(NULL == lpKernelThread) //If this condition is occurs,the system will crash.
{
PrintLine("In KernelThreadWrapper.");
PrintLine(lpszCriticalMsg);
return;
}
//ENTER_CRITICAL_SECTION();
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
KernelThreadManager.lpCurrentKernelThread = lpKernelThread; //!-!-!-!-!-!-!-!-!-!-!-!
//EnableInterrupt(); //If Enable Interrupt here,maybe cause some trouble.
//Assume an interrupt occurs here,the interrupt handler
//will save the current kernel thread's context to
//lpCurrentKernelThread's context,but the kernel thread
//running currently is not the lpCurrentKernelThread.
//The reason for this case is we have changed the lpCurrent-
//KernelThread variable,but do not switch to this kernel
//thread.
//So,the changing of lpCurrentKernelThread and switch
//context must be done as atomic operation.In order to
//achieve this target,we disable interrupt here.
//In SwitchTo procedure,only at the end of the procedure
//the interrupt is enabled,so this can work.
SwitchTo(&lpKernelThread->KernelThreadContext); //Switch to the new kernel thread.
return; //***** CAUTION! ***** : This instruction will never reach.
}
//
/**************************************************************************************
****************************************************************************************
****************************************************************************************
****************************************************************************************
***************************************************************************************/
//The following are some global functions.
//
//
//Get a message from the current kernel thread.
//
BOOL GetMessage(__KERNEL_THREAD_MESSAGE* lpMsg)
{
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
lpKernelThread = KernelThreadManager.lpCurrentKernelThread;
return KernelThreadManager.GetMessage((__COMMON_OBJECT*)lpKernelThread,lpMsg);
}
//
//Send a message to a kernel thread.
//
BOOL SendMessage(__COMMON_OBJECT* lpThread,__KERNEL_THREAD_MESSAGE* lpMsg)
{
return KernelThreadManager.SendMessage(lpThread,lpMsg);
}
//
//Dispatch a message to an message(event) handler.
//
DWORD DispatchMessage(__KERNEL_THREAD_MESSAGE* lpMsg,__KERNEL_THREAD_MESSAGE_HANDLER lpHandler)
{
return lpHandler(lpMsg->wCommand,lpMsg->wParam,lpMsg->dwParam);
}
//---------------------------------------------------------------------------------
//
// WaitForKernelThreadObject's implementation.
//
//---------------------------------------------------------------------------------
//
//The implementation of WaitForKernelThreadObject,because this routine calls ScheduleFromproc,
//so we implement it here(After the implementation of ScheduleFromProc).
//The routine does the following:
// 1. Check the current status of the kernel thread object;
// 2. If the current status is not KERNEL_THREAD_STATUS_TERMINAL,then block the
// current kernel thread(who want to wait),put it into the object's waiting queue;
// 3. Call ScheduleFromProc to fetch next kernel thread whose status is READY to run.
//
static DWORD WaitForKernelThreadObject(__COMMON_OBJECT* lpThis)
{
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
__KERNEL_THREAD_OBJECT* lpCurrent = NULL;
__PRIORITY_QUEUE* lpWaitingQueue = NULL;
DWORD dwFlags = 0L;
if(NULL == lpThis) //Parameter check.
return 1L;
lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpThis;
if(KERNEL_THREAD_STATUS_TERMINAL == lpKernelThread->dwThreadStatus) //If the object's
//status is TERMINAL,
//the wait operation
//will secussfully.
{
return 1L;
}
//
//If the waited object's status is not TERMINAL,then the waiting operation will
//not secussful,the current kernel thread who want to wait will be blocked.
//
lpWaitingQueue = lpKernelThread->lpWaitingQueue;
lpCurrent = KernelThreadManager.lpCurrentKernelThread;
//ENTER_CRITICAL_SECTION();
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
lpCurrent->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED;
//LEAVE_CRITICAL_SECTION();
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
lpWaitingQueue->InsertIntoQueue((__COMMON_OBJECT*)lpWaitingQueue,
(__COMMON_OBJECT*)lpCurrent,
0L); //Insert into the current kernel thread into waiting queue.
ScheduleFromProc(&lpCurrent->KernelThreadContext);
return 0L;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -