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

📄 ktmgr.cpp

📁 C写的小型操作系统源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	//ENTER_CRITICAL_SECTION();
	__ENTER_CRITICAL_SECTION(NULL,dwFlags)
	if((0 == lpManager->dwNextWakeupTick) ||
	   (lpManager->dwNextWakeupTick > dwTmpCounter))
	   lpManager->dwNextWakeupTick = dwTmpCounter;     //Update dwNextWakeupTick value.
	lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_SLEEPING;
	dwTmpCounter = MAX_DWORD_VALUE - dwTmpCounter;     //Calculates the priority of the
	                                                   //current kernel thread in the sleeping
	                                                   //queue.
	lpManager->lpSleepingQueue->InsertIntoQueue((__COMMON_OBJECT*)lpManager->lpSleepingQueue,
		(__COMMON_OBJECT*)lpKernelThread,
		dwTmpCounter);
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags)
	//lpContext = &lpKernelThread->KernelThreadContext;
	lpManager->ScheduleFromProc(NULL);
	return TRUE;
}

//CancelSleep Routine.
static BOOL CancelSleep(__COMMON_OBJECT* lpThis,__COMMON_OBJECT* lpKernelThread)
{
	return FALSE;
}

//SetCurrentIRQL.
static DWORD SetCurrentIRQL(__COMMON_OBJECT* lpThis,DWORD dwNewIRQL)
{
	return 0L;
}

//GetCurrentIRQL.
static DWORD GetCurrentIRQL(__COMMON_OBJECT* lpThis)
{
	return 0L;
}

//SetLastError.
static DWORD SetLastError(/*__COMMON_OBJECT* lpKernelThread,*/DWORD dwNewError)
{
	DWORD  dwOldError = 0L;

	dwOldError = KernelThreadManager.lpCurrentKernelThread->dwLastError;
	KernelThreadManager.lpCurrentKernelThread->dwLastError = dwNewError;
	return dwOldError;
}

//GetLastError.
static DWORD GetLastError(/*__COMMON_OBJECT* lpKernelThread*/)
{
	return KernelThreadManager.lpCurrentKernelThread->dwLastError;
}

//GetThreadID.
static DWORD GetThreadID(__COMMON_OBJECT* lpKernelThread)
{
	if(NULL == lpKernelThread)
		return 0L;

	return ((__KERNEL_THREAD_OBJECT*)lpKernelThread)->dwThreadID;
}

//GetThreadStatus.
static DWORD GetThreadStatus(__COMMON_OBJECT* lpKernelThread)
{
	if(NULL == lpKernelThread)
		return 0L;

	return ((__KERNEL_THREAD_OBJECT*)lpKernelThread)->dwThreadStatus;
}

//SetThreadStatus.
static DWORD SetThreadStatus(__COMMON_OBJECT* lpKernelThread,DWORD dwStatus)
{
	return 0L;
}

//MsgQueueFull.
static BOOL MsgQueueFull(__COMMON_OBJECT* lpThread)
{
	__KERNEL_THREAD_OBJECT*     lpKernelThread  = NULL;

	if(NULL == lpThread)    //Parameter check.
		return FALSE;

	lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpThread;

	return MAX_KTHREAD_MSG_NUM == lpKernelThread->ucCurrentMsgNum ? TRUE : FALSE;
}

//MsgQueueEmpty.
static BOOL MsgQueueEmpty(__COMMON_OBJECT* lpThread)
{
	__KERNEL_THREAD_OBJECT*     lpKernelThread = NULL;

	if(NULL == lpThread)   //Parameter check.
		return FALSE;

	lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpThread;

	return 0 == lpKernelThread->ucCurrentMsgNum ? TRUE : FALSE;
}

//SendMessage.
static BOOL MgrSendMessage(__COMMON_OBJECT* lpThread,__KERNEL_THREAD_MESSAGE* lpMsg)
{
	__KERNEL_THREAD_OBJECT*     lpKernelThread = NULL;
	__KERNEL_THREAD_OBJECT*     lpNewThread    = NULL;
	BOOL                        bResult        = FALSE;
	DWORD                       dwFlags        = 0L;

	if((NULL == lpThread) || (NULL == lpMsg)) //Parameters check.
		return bResult;
	lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpThread;

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	if(MsgQueueFull(lpThread))             //Message queue is full.
	{
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		return bResult;
	}
	//Message queue not full,put the message to the queue.
	lpKernelThread->KernelThreadMsg[lpKernelThread->ucMsgQueueTrial].wCommand
		= lpMsg->wCommand;
	lpKernelThread->KernelThreadMsg[lpKernelThread->ucMsgQueueTrial].wParam
		= lpMsg->wParam;
	lpKernelThread->KernelThreadMsg[lpKernelThread->ucMsgQueueTrial].dwParam
		= lpMsg->dwParam;
	lpKernelThread->ucMsgQueueTrial ++;
	if(MAX_KTHREAD_MSG_NUM == lpKernelThread->ucMsgQueueTrial)
		lpKernelThread->ucMsgQueueTrial = 0;     //so the message queue is a circle
	lpKernelThread->ucCurrentMsgNum ++;     //by this para, one can check if the queue is full?

	lpNewThread = (__KERNEL_THREAD_OBJECT*)lpKernelThread->lpMsgWaitingQueue->GetHeaderElement(
		(__COMMON_OBJECT*)lpKernelThread->lpMsgWaitingQueue,
		NULL);
	if(lpNewThread)  //Should wakeup the target kernel thread.
	{
		lpNewThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
		KernelThreadManager.AddReadyKernelThread(
			(__COMMON_OBJECT*)&KernelThreadManager,
			lpNewThread);  //Add to ready queue.
	}
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
	//
	//If in kernel thread context,then re-schedule kernel thread.
	//
	if(IN_KERNELTHREAD())  //---- !!!!!!!! PROBLEM CAUSED !!!!!!!! ----
	{
		KernelThreadManager.ScheduleFromProc(NULL);
	}
	bResult = TRUE;
	return bResult;
}

//GetMessage.
static BOOL MgrGetMessage(__COMMON_OBJECT* lpThread,__KERNEL_THREAD_MESSAGE* lpMsg)
{
	__KERNEL_THREAD_OBJECT*     lpKernelThread  = NULL;
	DWORD                       dwFlags         = 0L;

	if((NULL == lpThread) || (NULL == lpMsg)) //Parameters check.
		return FALSE;
	lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpThread;

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	if(MsgQueueEmpty(lpThread))  //Current message queue is empty,should waiting.
	{
		lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED;
		lpKernelThread->lpMsgWaitingQueue->InsertIntoQueue(
			(__COMMON_OBJECT*)lpKernelThread->lpMsgWaitingQueue,
			(__COMMON_OBJECT*)lpKernelThread,
			0L);
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		KernelThreadManager.ScheduleFromProc(NULL);  //Re-schedule.
		//lpKernelThread->lpMsgEvent->WaitForThisObject(
		//	(__COMMON_OBJECT*)(lpKernelThread->lpMsgEvent));  //Block the current thread.
	}
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

	__ENTER_CRITICAL_SECTION(NULL,dwFlags)
	lpMsg->wCommand     = lpKernelThread->KernelThreadMsg[lpKernelThread->ucMsgQueueHeader].wCommand;
	lpMsg->wParam       = lpKernelThread->KernelThreadMsg[lpKernelThread->ucMsgQueueHeader].wParam;
	lpMsg->dwParam      = lpKernelThread->KernelThreadMsg[lpKernelThread->ucMsgQueueHeader].dwParam;

	lpKernelThread->ucMsgQueueHeader ++;
	if(MAX_KTHREAD_MSG_NUM == lpKernelThread->ucMsgQueueHeader)
		lpKernelThread->ucMsgQueueHeader = 0x0000;
	lpKernelThread->ucCurrentMsgNum --;

	//if(0 == lpKernelThread->ucCurrentMsgNum)     //The message queue is empty.
	//	lpKernelThread->lpMsgEvent->ResetEvent((__COMMON_OBJECT*)(lpKernelThread->lpMsgEvent));
	//LEAVE_CRITICAL_SECTION();                    //Enable the interrupt.
	__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.

	{0},                                             //Ready queue array.
	//0L,                                              //dwClockTickCounter.
	0L,                                              //dwNextWakeupTick.

	NULL,                                            //lpCreateHook.
	NULL,                                            //lpEndScheduleHook.
	NULL,                                            //lpBeginScheduleHook.
	NULL,                                            //lpTerminalHook.
	SetThreadHook,                                   //SetThreadHook.
	CallThreadHook,                                  //CallThreadHook.

	GetScheduleKernelThread,                         //GetScheduleKernelThread.
	AddReadyKernelThread,                            //AddReadyKernelThread.
	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.
};

//
/**************************************************************************************
****************************************************************************************
****************************************************************************************
****************************************************************************************
***************************************************************************************/
//
//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);
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -