⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ktmgr.cpp

📁 C写的小型操作系统源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	__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 + -