📄 ktmgr.cpp
字号:
//***********************************************************************/
// Author : Garry
// Original Date : Oct,18 2004
// Module Name : ktmgr.cpp
// Module Funciton :
// This module countains kernel thread and kernel thread
// manager's implementation code.
//
// ************
// This file is the most important file of Hello China.
// ************
// Last modified Author :
// Last modified Date :
// Last modified Content :
// 1.
// 2.
// Lines number :
//***********************************************************************/
#ifndef __STDAFX_H__
#include "StdAfx.h"
#endif
//
//Pre-declaration of routine.
//
static VOID KernelThreadWrapper(__COMMON_OBJECT*);
static DWORD WaitForKernelThreadObject(__COMMON_OBJECT* lpThis);
//
//Static global varaibles.
//
CHAR* lpszCriticalMsg = "CRITICAL ERROR : The internal data structure is not consecutive,\
please restart the system!!";
//
//SwitchTo routine.
//This routine restore the context of a kernel thread,and continue to run.
//
__declspec(naked) static VOID SwitchTo(__KERNEL_THREAD_CONTEXT* lpContext)
{
#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 lpContext value.
mov esp,dword ptr [eax + CONTEXT_OFFSET_ESP] //Restore the ESP register first.
push dword ptr [eax + CONTEXT_OFFSET_EFLAGS] //Push EFlags register to stack.
xor ebx,ebx
mov bx,word ptr [eax + CONTEXT_OFFSET_CS]
push ebx //Extend and push CS to stack.
push dword ptr [eax + CONTEXT_OFFSET_EIP] //Push EIP to stack.
//Now,we have built the correct
//stack frame.
push dword ptr [eax + CONTEXT_OFFSET_EAX] //Save eax to stack.
push dword ptr [eax + CONTEXT_OFFSET_EBX] //Save ebx to stack.
push dword ptr [eax + CONTEXT_OFFSET_ECX] //ecx
push dword ptr [eax + CONTEXT_OFFSET_EDX] //edx
push dword ptr [eax + CONTEXT_OFFSET_ESI] //esi
push dword ptr [eax + CONTEXT_OFFSET_EDI] //edi
push dword ptr [eax + CONTEXT_OFFSET_EBP] //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
}
//
//SaveContext routine.
//The routine saves the current kernel thread's context,in a interrupt handler.
//
static VOID SaveContext(__KERNEL_THREAD_CONTEXT* lpContext,DWORD* lpdwEsp)
{
if((NULL == lpContext) || (NULL == lpdwEsp)) //Parameters check.
return;
DisableInterrupt();
#ifdef __I386__ //i386's implementation.
lpContext->dwEBP = *lpdwEsp;
lpdwEsp ++;
lpContext->dwEDI = *lpdwEsp;
lpdwEsp ++;
lpContext->dwESI = *lpdwEsp;
lpdwEsp ++;
lpContext->dwEDX = *lpdwEsp;
lpdwEsp ++;
lpContext->dwECX = *lpdwEsp;
lpdwEsp ++;
lpContext->dwEBX = *lpdwEsp;
lpdwEsp ++;
lpContext->dwEAX = *lpdwEsp;
lpdwEsp ++;
lpContext->dwEIP = *lpdwEsp;
lpdwEsp ++;
lpdwEsp ++; //Skip the CS's space.
lpContext->dwEFlags = *lpdwEsp;
lpdwEsp ++;
lpContext->dwESP = (DWORD)lpdwEsp;
#else
#endif
EnableInterrupt();
return;
}
//
//The initialization routine of Kernel Thread Object.
//In the current implementation of Hello China,we do the following task:
// 1. Create the waiting queue object of the kernel thread object;
// 2. Initialize the waiting queue object;
// 3. Set appropriaty value of the member functions,such as WaitForThisObject.
//
BOOL KernelThreadInitialize(__COMMON_OBJECT* lpThis)
{
BOOL bResult = FALSE;
__PRIORITY_QUEUE* lpWaitingQueue = NULL;
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
__EVENT* lpMsgEvent = NULL;
if(NULL == lpThis) //Parameter check.
goto __TERMINAL;
lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpThis;
lpWaitingQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(
&ObjectManager,
NULL,
OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpWaitingQueue) //Failed to create the waiting queue object.
goto __TERMINAL;
if(!lpWaitingQueue->Initialize((__COMMON_OBJECT*)lpWaitingQueue))
//Failed to initialize the waiting queue object.
goto __TERMINAL;
lpMsgEvent = (__EVENT*)ObjectManager.CreateObject(
&ObjectManager,
NULL,
OBJECT_TYPE_EVENT);
if(NULL == lpMsgEvent) //Failed to create event object.
goto __TERMINAL;
if(!lpMsgEvent->Initialize((__COMMON_OBJECT*)lpMsgEvent)) //Failed to initialize.
goto __TERMINAL;
lpKernelThread->lpWaitingQueue = lpWaitingQueue;
lpKernelThread->lpMsgEvent = lpMsgEvent;
lpKernelThread->WaitForThisObject = WaitForKernelThreadObject;
bResult = TRUE;
__TERMINAL:
if(!bResult) //Initialize failed.
{
if(lpWaitingQueue != NULL)
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpWaitingQueue);
if(lpMsgEvent != NULL)
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpMsgEvent);
}
return bResult;
}
//
//The Uninitialize routine of kernel thread object.
//
VOID KernelThreadUninitialize(__COMMON_OBJECT* lpThis)
{
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
__PRIORITY_QUEUE* lpWaitingQueue = NULL;
__EVENT* lpMsgEvent = NULL;
if(NULL == lpThis) //Parameter check.
return;
lpWaitingQueue = ((__KERNEL_THREAD_OBJECT*)lpThis)->lpWaitingQueue;
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpWaitingQueue);
lpMsgEvent = ((__KERNEL_THREAD_OBJECT*)lpThis)->lpMsgEvent;
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpMsgEvent);
return;
}
//
//The implementation of Kernel Thread Manager.
//
//Initializing routine of Kernel Thread Manager.
static BOOL KernelThreadMgrInit(__COMMON_OBJECT* lpThis)
{
BOOL bResult = FALSE;
__KERNEL_THREAD_MANAGER* lpMgr = NULL;
__PRIORITY_QUEUE* lpRunningQueue = NULL;
__PRIORITY_QUEUE* lpReadyQueue = NULL;
__PRIORITY_QUEUE* lpSuspendedQueue = NULL;
__PRIORITY_QUEUE* lpSleepingQueue = NULL;
__PRIORITY_QUEUE* lpTerminalQueue = NULL;
if(NULL == lpThis)
return bResult;
lpMgr = (__KERNEL_THREAD_MANAGER*)lpThis;
//
//The following code creates all objects required by Kernel Thread Manager.
//If any error occurs,the initializing process is terminaled.
//
lpRunningQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(&ObjectManager,NULL,OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpRunningQueue)
goto __TERMINAL;
if(FALSE == lpRunningQueue->Initialize((__COMMON_OBJECT*)lpRunningQueue))
goto __TERMINAL;
lpReadyQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(&ObjectManager,NULL,OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpReadyQueue)
goto __TERMINAL;
if(FALSE == lpReadyQueue->Initialize((__COMMON_OBJECT*)lpReadyQueue))
goto __TERMINAL;
lpSuspendedQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(&ObjectManager,NULL,OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpSuspendedQueue)
goto __TERMINAL;
if(FALSE == lpSuspendedQueue->Initialize((__COMMON_OBJECT*)lpSuspendedQueue))
goto __TERMINAL;
lpSleepingQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(&ObjectManager,NULL,OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpSleepingQueue)
goto __TERMINAL;
if(FALSE == lpSleepingQueue->Initialize((__COMMON_OBJECT*)lpSleepingQueue))
goto __TERMINAL;
lpTerminalQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(&ObjectManager,NULL,OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpTerminalQueue)
goto __TERMINAL;
if(FALSE == lpTerminalQueue->Initialize((__COMMON_OBJECT*)lpTerminalQueue))
goto __TERMINAL;
//
//Now,the objects required by Kernel Thread Manager are created and initialized success-
//fully,initialize the kernel thread manager itself now.
//
lpMgr->lpRunningQueue = lpRunningQueue;
lpMgr->lpReadyQueue = lpReadyQueue;
lpMgr->lpSuspendedQueue = lpSuspendedQueue;
lpMgr->lpSleepingQueue = lpSleepingQueue;
lpMgr->lpTerminalQueue = lpTerminalQueue;
lpMgr->lpCurrentKernelThread = NULL;
bResult = TRUE;
__TERMINAL:
if(!bResult) //If failed to initialize the Kernel Thread Manager.
{
if(NULL != lpRunningQueue) //Destroy the objects created just now.
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpRunningQueue);
if(NULL != lpReadyQueue)
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpReadyQueue);
if(NULL != lpSuspendedQueue)
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpSuspendedQueue);
if(NULL != lpSleepingQueue)
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpSleepingQueue);
if(NULL != lpTerminalQueue)
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpTerminalQueue);
}
return bResult;
}
//
//CreateKernelThread's implementation.
//This routine do the following:
// 1. Create a kernel thread object by calling CreateObject;
// 2. Initializes the kernel thread object;
// 3. Create the kernel thread's stack by calling KMemAlloc;
// 4. Insert the kernel thread object into proper queue.
//
static __KERNEL_THREAD_OBJECT* CreateKernelThread(__COMMON_OBJECT* lpThis,
DWORD dwStackSize,
DWORD dwStatus,
DWORD dwPriority,
__KERNEL_THREAD_ROUTINE lpStartRoutine,
LPVOID lpRoutineParam,
LPVOID lpReserved)
{
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
__KERNEL_THREAD_MANAGER* lpMgr = NULL;
LPVOID lpStack = NULL;
BOOL bSuccess = FALSE;
if((NULL == lpThis) || (NULL == lpStartRoutine)) //Parameter check.
goto __TERMINAL;
if((KERNEL_THREAD_STATUS_READY != dwStatus) && //The initation status of a kernel
//thread should only be READY or
//SUSPENDED.If the initation status
//is READY,then the kernel thread maybe
//scheduled to run in the NEXT schedule
//circle(please note the kernel thread
//does not be scheduled immediately),
//else,the kernel thread will be susp-
//ended,the kernel thread in this status
//can be activated by ResumeKernelThread
//calls.
(KERNEL_THREAD_STATUS_SUSPENDED != dwStatus))
goto __TERMINAL;
lpMgr = (__KERNEL_THREAD_MANAGER*)lpThis;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -