?? 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 : Garry
// Last modified Date : Sep,30,2006
// Last modified Content :
// 1.
// 2.
// Lines number :
//***********************************************************************/
#ifndef __STDAFX_H__
#include "..\INCLUDE\StdAfx.h"
#endif
#include "..\INCLUDE\ARCHSTD.H"
//
//Pre-declare for extern global routines,these routines may
//be implemented in KTMGRx.CPP file,where x is 2,3,etc.
//
extern __THREAD_HOOK_ROUTINE SetThreadHook(DWORD dwHookType,
__THREAD_HOOK_ROUTINE lpRoutine);
extern VOID CallThreadHook(DWORD dwHookType,
__KERNEL_THREAD_OBJECT* lpPrev,
__KERNEL_THREAD_OBJECT* lpNext);
extern __KERNEL_THREAD_OBJECT* GetScheduleKernelThread(__COMMON_OBJECT* lpThis,
DWORD dwPriority);
extern VOID AddReadyKernelThread(__COMMON_OBJECT* lpThis,
__KERNEL_THREAD_OBJECT* lpKernelThread);
extern VOID KernelThreadWrapper(__COMMON_OBJECT*);
extern DWORD WaitForKernelThreadObject(__COMMON_OBJECT* lpThis);
//
//Static global varaibles.
//
CHAR* lpszCriticalMsg = "CRITICAL ERROR : The internal data structure is not consecutive,\
please restart the system!!";
//
//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;
__PRIORITY_QUEUE* lpMsgWaitingQueue = 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;
lpMsgWaitingQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(
&ObjectManager,
NULL,
OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpMsgWaitingQueue) //Can not create message waiting queue.
goto __TERMINAL;
if(!lpMsgWaitingQueue->Initialize((__COMMON_OBJECT*)lpMsgWaitingQueue))
goto __TERMINAL;
lpKernelThread->lpWaitingQueue = lpWaitingQueue;
lpKernelThread->lpMsgWaitingQueue = lpMsgWaitingQueue;
lpKernelThread->WaitForThisObject = WaitForKernelThreadObject;
lpKernelThread->lpKernelThreadContext = NULL;
bResult = TRUE;
__TERMINAL:
if(!bResult) //Initialize failed.
{
if(lpWaitingQueue != NULL)
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpWaitingQueue);
if(lpMsgWaitingQueue != NULL)
ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpMsgWaitingQueue);
}
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;
lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpThis;
//Destroy waiting queue.
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpKernelThread->lpWaitingQueue);
//Destroy message waiting queue.
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpKernelThread->lpMsgWaitingQueue);
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;
DWORD i;
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;
//Initializes the ready queue array.Any element failure can cause the whole
//process to fail.
for(i = 0;i < MAX_KERNEL_THREAD_PRIORITY + 1;i ++)
{
lpReadyQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(&ObjectManager,
NULL,
OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpReadyQueue)
{
goto __TERMINAL;
}
if(!lpReadyQueue->Initialize((__COMMON_OBJECT*)lpReadyQueue)) //Can not initialize it.
{
goto __TERMINAL;
}
lpMgr->ReadyQueue[i] = lpReadyQueue;
}
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,
LPSTR lpszName)
{
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
__KERNEL_THREAD_MANAGER* lpMgr = NULL;
LPVOID lpStack = NULL;
BOOL bSuccess = FALSE;
DWORD* lpStackPtr = NULL;
DWORD i;
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;
lpKernelThread = (__KERNEL_THREAD_OBJECT*)ObjectManager.CreateObject(&ObjectManager,
NULL,
OBJECT_TYPE_KERNEL_THREAD);
if(NULL == lpKernelThread) //If failed to create the kernel thread object.
goto __TERMINAL;
if(!lpKernelThread->Initialize((__COMMON_OBJECT*)lpKernelThread)) //Failed to initialize.
goto __TERMINAL;
if(0 == dwStackSize) //If the dwStackSize is zero,then allocate the default size's
//stack.
{
dwStackSize = DEFAULT_STACK_SIZE;
}
else
{
if(dwStackSize < MIN_STACK_SIZE) //If dwStackSize is too small.
{
dwStackSize = MIN_STACK_SIZE;
}
}
lpStack = KMemAlloc(dwStackSize,KMEM_SIZE_TYPE_ANY);
if(NULL == lpStack) //Failed to create kernel thread stack.
{
goto __TERMINAL;
}
//The following code initializes the kernel thread object created just now.
lpKernelThread->dwThreadID = lpKernelThread->dwObjectID;
lpKernelThread->dwThreadStatus = dwStatus;
lpKernelThread->dwThreadPriority = dwPriority;
lpKernelThread->dwScheduleCounter = dwPriority; //***** CAUTION!!! *****
lpKernelThread->dwReturnValue = 0L;
lpKernelThread->dwTotalRunTime = 0L;
lpKernelThread->dwTotalMemSize = 0L;
lpKernelThread->bUsedMath = FALSE; //May be updated in the future.
lpKernelThread->dwStackSize = dwStackSize ? dwStackSize : DEFAULT_STACK_SIZE;
lpKernelThread->lpInitStackPointer = (LPVOID)((DWORD)lpStack + dwStackSize);
lpKernelThread->KernelThreadRoutine = lpStartRoutine; //Will be updated.
lpKernelThread->lpRoutineParam = lpRoutineParam;
lpKernelThread->ucMsgQueueHeader = 0;
lpKernelThread->ucMsgQueueTrial = 0;
lpKernelThread->ucCurrentMsgNum = 0;
lpKernelThread->dwLastError = 0L;
lpKernelThread->dwWaitingStatus = OBJECT_WAIT_WAITING;
//Copy kernel thread name.
if(lpszName)
{
for(i = 0;i < MAX_THREAD_NAME - 1;i ++)
{
if(lpszName[i] == 0) //End.
{
break;
}
lpKernelThread->KernelThreadName[i] = lpszName[i];
}
}
lpKernelThread->KernelThreadName[i] = 0; //Set string's terminator.
//
//The following routine initializes the hardware context
//of the kernel thread.
//It's implementation depends on the hardware platform,so
//this routine is implemented in ARCH directory.
//
InitKernelThreadContext(lpKernelThread,KernelThreadWrapper);
if(KERNEL_THREAD_STATUS_READY == dwStatus) //Add into Ready Queue.
{
lpMgr->AddReadyKernelThread((__COMMON_OBJECT*)lpMgr,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -