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

📄 ktmgr.cpp

📁 一本叫自己动手写嵌入式操作系统的书的源代码,作者是蓝枫叶,详细介绍了如何写一个嵌入式操作系统,而不是操作系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			lpKernelThread);
	}
	else                                               //Add into Suspended Queue.
	{
		if(!lpMgr->lpSuspendedQueue->InsertIntoQueue((__COMMON_OBJECT*)lpMgr->lpSuspendedQueue,
			(__COMMON_OBJECT*)lpKernelThread,dwPriority))
			goto __TERMINAL;
	}

	//Call the create hook.
	lpMgr->CallThreadHook(THREAD_HOOK_TYPE_CREATE,lpKernelThread,
		NULL);
	bSuccess = TRUE;  //Now,the TRANSACTION of create a kernel thread is successfully.

__TERMINAL:
	if(!bSuccess)
	{
		//First,release the resources created successfully.
		if(NULL != lpKernelThread)
			ObjectManager.DestroyObject(&ObjectManager,(__COMMON_OBJECT*)lpKernelThread);
		if(NULL != lpStack)
			KMemFree(lpStack,KMEM_SIZE_TYPE_ANY,0L);
		return NULL;
	}
	else
		return lpKernelThread;
}

//
//DestroyKernelThread's implementation.
//The routine do the following:
// 1. Check the status of the kernel thread object will be destroyed,if the
//    status is KERNEL_THREAD_STATUS_TERMINAL,then does the rest steps,else,
//    simple return;
// 2. Delete the kernel thread object from Terminal Queue;
// 3. Destroy the kernel thread object by calling DestroyObject.
//

static VOID DestroyKernelThread(__COMMON_OBJECT* lpThis,__COMMON_OBJECT* lpKernel)
{
	__KERNEL_THREAD_OBJECT*     lpKernelThread   = NULL;
	__KERNEL_THREAD_MANAGER*    lpMgr            = NULL;
	__PRIORITY_QUEUE*           lpTerminalQueue  = NULL;
	LPVOID                      lpStack          = NULL;

	if((NULL == lpThis) || (NULL == lpKernel))    //Parameter check.
		return;

	lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpKernel;
	lpMgr          = (__KERNEL_THREAD_MANAGER*)lpThis;

	if(KERNEL_THREAD_STATUS_TERMINAL != lpKernelThread->dwThreadStatus)
		return;

	lpTerminalQueue = lpMgr->lpTerminalQueue;
	lpTerminalQueue->DeleteFromQueue((__COMMON_OBJECT*)lpTerminalQueue,
		                             (__COMMON_OBJECT*)lpKernelThread);  //Delete from terminal queue.

	//Call terminal hook routine.
	lpMgr->CallThreadHook(THREAD_HOOK_TYPE_TERMINAL,
		lpKernelThread,NULL);

	lpStack = lpKernelThread->lpInitStackPointer;
	lpStack = (LPVOID)((DWORD)lpStack - lpKernelThread->dwStackSize);
	KMemFree(lpStack,KMEM_SIZE_TYPE_ANY,0L);    //Free the stack of the kernel thread.

	ObjectManager.DestroyObject(&ObjectManager,
		                        (__COMMON_OBJECT*)lpKernelThread);

}

//SuspendKernelThread's implementation.
static BOOL SuspendKernelThread(__COMMON_OBJECT* lpThis,__COMMON_OBJECT* lpKernelThread)
{
	return FALSE;
}

//ResumeKernelThread's implementation.
static BOOL ResumeKernelThread(__COMMON_OBJECT* lpThis,__COMMON_OBJECT* lpKernelThread)
{
	return FALSE;
}

//
//ScheduleFromProc's implementation.
//This routine can be called anywhere that re-schedule is required.
//
static VOID ScheduleFromProc(__KERNEL_THREAD_CONTEXT* lpContext)
{
	__KERNEL_THREAD_OBJECT*          lpKernelThread     = NULL;
	__KERNEL_THREAD_OBJECT*          lpCurrent          = NULL;
	__KERNEL_THREAD_OBJECT*          lpNew              = NULL;
	__KERNEL_THREAD_CONTEXT**        lppOldContext      = NULL;
	__KERNEL_THREAD_CONTEXT**        lppNewContext      = NULL;
	DWORD                            dwFlags            = 0L;

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	lpCurrent = KernelThreadManager.lpCurrentKernelThread;
	switch(lpCurrent->dwThreadStatus)  //Do different actions according to status.
	{
	case KERNEL_THREAD_STATUS_RUNNING:
		lpNew = KernelThreadManager.GetScheduleKernelThread(
			(__COMMON_OBJECT*)&KernelThreadManager,
			lpCurrent->dwThreadPriority);    //Get a ready kernel thread.
		if(NULL == lpNew)  //Current one is most priority whose status is READY.
		{
			lpCurrent->dwTotalRunTime += SYSTEM_TIME_SLICE;
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			return;  //Let current kernel thread continue to run.
		}
		else  //Should swap out current kernel thread and run next ready one.
		{
			lpCurrent->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
			KernelThreadManager.AddReadyKernelThread(
				(__COMMON_OBJECT*)&KernelThreadManager,
				lpCurrent);  //Insert into ready queue.
			lpNew->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
			lpNew->dwTotalRunTime += SYSTEM_TIME_SLICE;
			KernelThreadManager.lpCurrentKernelThread = lpNew;
			//Call schedule hook before swich.
			KernelThreadManager.CallThreadHook(
				THREAD_HOOK_TYPE_ENDSCHEDULE | THREAD_HOOK_TYPE_BEGINSCHEDULE,
				lpCurrent,lpNew);

			__SaveAndSwitch(&lpCurrent->lpKernelThreadContext,
				&lpNew->lpKernelThreadContext);  //Switch.
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			return;
		}
		break;
	case KERNEL_THREAD_STATUS_READY:
		lpNew = KernelThreadManager.GetScheduleKernelThread(
			(__COMMON_OBJECT*)&KernelThreadManager,
			lpCurrent->dwThreadPriority);  //Get a ready thread.

		if(NULL == lpNew)  //Should not occur.
		{
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			BUG();
			return;
		}
		if(lpNew == lpCurrent)  //The same one.
		{
			lpCurrent->dwTotalRunTime += SYSTEM_TIME_SLICE;
			lpCurrent->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			return;
		}
		else  //Not the same one.
		{
			lpNew->dwTotalRunTime += SYSTEM_TIME_SLICE;
			lpNew->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
			KernelThreadManager.lpCurrentKernelThread = lpNew;
			//Call schedule hook routine.
			KernelThreadManager.CallThreadHook(
				THREAD_HOOK_TYPE_ENDSCHEDULE | THREAD_HOOK_TYPE_BEGINSCHEDULE,
				lpCurrent,lpNew);

			__SaveAndSwitch(&lpCurrent->lpKernelThreadContext,
				&lpNew->lpKernelThreadContext);
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			return;
		}
		break;
	case KERNEL_THREAD_STATUS_BLOCKED:
	case KERNEL_THREAD_STATUS_SUSPENDED:
	case KERNEL_THREAD_STATUS_TERMINAL:
	case KERNEL_THREAD_STATUS_SLEEPING:
		lpNew = KernelThreadManager.GetScheduleKernelThread(
			(__COMMON_OBJECT*)&KernelThreadManager,
			0L);  //Get a ready thread to run.

		if(NULL == lpNew)
		{
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			BUG();
			PrintLine("Fatal error: in ScheduleFromProc,lpNew == NULL.");
			return;
		}
		lpNew->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
		lpNew->dwTotalRunTime += SYSTEM_TIME_SLICE;
		KernelThreadManager.lpCurrentKernelThread = lpNew;
		//Call schedule hook.
		KernelThreadManager.CallThreadHook(
			THREAD_HOOK_TYPE_ENDSCHEDULE | THREAD_HOOK_TYPE_BEGINSCHEDULE,
			lpCurrent,lpNew);

		__SaveAndSwitch(&lpCurrent->lpKernelThreadContext,
			&lpNew->lpKernelThreadContext);
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		return;
		break;
	default:
		BUG();
		break;
	}
}

//ScheduleFromInt's implementation.
static VOID ScheduleFromInt(__COMMON_OBJECT* lpThis,LPVOID lpESP)
{
	__KERNEL_THREAD_OBJECT*         lpNextThread    = NULL;
	__KERNEL_THREAD_OBJECT*         lpCurrentThread = NULL;
	__KERNEL_THREAD_MANAGER*        lpMgr           = NULL;

	if((NULL == lpThis) || (NULL == lpESP))    //Parameters check.
		return;

	lpMgr = (__KERNEL_THREAD_MANAGER*)lpThis;

	if(NULL == lpMgr->lpCurrentKernelThread)   //The routine is called first time.
	{
		lpNextThread = KernelThreadManager.GetScheduleKernelThread(
			(__COMMON_OBJECT*)&KernelThreadManager,
			0L);
		if(NULL == lpNextThread)               //If this case is occurs,the system is crash.
		{
			BUG();
			return;
		}
		KernelThreadManager.lpCurrentKernelThread = lpNextThread;
		lpNextThread->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
		lpNextThread->dwTotalRunTime += SYSTEM_TIME_SLICE;
		//Call schedule hook.
		KernelThreadManager.CallThreadHook(
			THREAD_HOOK_TYPE_BEGINSCHEDULE,NULL,lpNextThread);

		__SwitchTo(lpNextThread->lpKernelThreadContext);  //Switch to this thread.
	}
	else  //Not the first time be called.
	{
		lpCurrentThread = KernelThreadManager.lpCurrentKernelThread;
		//This code line saves the context of current kernel thread.
		lpCurrentThread->lpKernelThreadContext = (__KERNEL_THREAD_CONTEXT*)lpESP;

		switch(lpCurrentThread->dwThreadStatus)
		{
		case KERNEL_THREAD_STATUS_BLOCKED:     //Waiting shared object in process.
		case KERNEL_THREAD_STATUS_TERMINAL:    //In process of termination.
		case KERNEL_THREAD_STATUS_SLEEPING:    //In process of falling in sleep.
		case KERNEL_THREAD_STATUS_SUSPENDED:   //In process of being suspended.
		case KERNEL_THREAD_STATUS_READY:       //Wakeup immediately in another interrupt.
			lpCurrentThread->dwTotalRunTime += SYSTEM_TIME_SLICE;
			//lpContext = lpCurrentThread->lpKernelThreadContext;
			KernelThreadManager.CallThreadHook(
				THREAD_HOOK_TYPE_BEGINSCHEDULE,NULL,lpCurrentThread);

			__SwitchTo(lpCurrentThread->lpKernelThreadContext);
			break;                             //This instruction will never reach.

		case KERNEL_THREAD_STATUS_RUNNING:
			lpNextThread = KernelThreadManager.GetScheduleKernelThread(
				(__COMMON_OBJECT*)&KernelThreadManager,
				lpCurrentThread->dwThreadPriority);
			if(NULL == lpNextThread)  //Current is most priority.
			{
				lpCurrentThread->dwTotalRunTime += SYSTEM_TIME_SLICE;
				KernelThreadManager.CallThreadHook(
					THREAD_HOOK_TYPE_BEGINSCHEDULE,NULL,lpCurrentThread);

				__SwitchTo(lpCurrentThread->lpKernelThreadContext);
				return;
			}
			else
			{
				lpCurrentThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
				KernelThreadManager.AddReadyKernelThread(
					(__COMMON_OBJECT*)&KernelThreadManager,
					lpCurrentThread);  //Add to ready queue.

				lpNextThread->dwTotalRunTime += SYSTEM_TIME_SLICE;
				lpNextThread->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
				lpMgr->lpCurrentKernelThread = lpNextThread;
				KernelThreadManager.CallThreadHook(
					THREAD_HOOK_TYPE_BEGINSCHEDULE,NULL,lpNextThread);
				__SwitchTo(lpNextThread->lpKernelThreadContext);
				return;
			}
		default:
			BUG();
			break;
		}
	}
}

//SetThreadPriority.
static DWORD SetThreadPriority(__COMMON_OBJECT* lpKernelThread,DWORD dwPriority)
{
	__KERNEL_THREAD_OBJECT*    lpThread = NULL;
	DWORD                      dwOldPri = PRIORITY_LEVEL_IDLE;
	DWORD                      dwFlags  = 0L;

	if(NULL == lpKernelThread)
		return PRIORITY_LEVEL_IDLE;
	
	lpThread = (__KERNEL_THREAD_OBJECT*)lpKernelThread;
	dwOldPri = lpThread->dwThreadPriority;
	//ENTER_CRITICAL_SECTION();
	__ENTER_CRITICAL_SECTION(NULL,dwFlags)
	lpThread->dwThreadPriority = dwPriority;
	//LEAVE_CRITICAL_SECTION();
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags)

	return dwOldPri;
}

//GetThreadPriority.
static DWORD GetThreadPriority(__COMMON_OBJECT* lpKernelThread)
{
	__KERNEL_THREAD_OBJECT*    lpThread = NULL;

	if(NULL == lpKernelThread)
		return PRIORITY_LEVEL_IDLE;

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

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

//
//Sleep Routine.
//This routine do the following:
// 1. Updates the dwNextWakeupTick value of kernel thread manager;
// 2. Modifies the current kernel thread's status to SLEEPING;
// 3. Puts the current kernel thread into sleeping queue of kernel thread manager;
// 4. Schedules another kernel thread to.
//
static BOOL Sleep(__COMMON_OBJECT* lpThis,/*__COMMON_OBJECT* lpKernelThread,*/DWORD dwMillisecond)
{
	__KERNEL_THREAD_MANAGER*           lpManager      = NULL;
	__KERNEL_THREAD_OBJECT*            lpKernelThread = NULL;
	DWORD                              dwTmpCounter   = 0L;
	__KERNEL_THREAD_CONTEXT*           lpContext      = NULL;
	DWORD                              dwFlags        = 0L;

	if((NULL == lpThis) ||
	  (dwMillisecond < SYSTEM_TIME_SLICE))    //Parameters check.
	  return FALSE;

	lpManager = (__KERNEL_THREAD_MANAGER*)lpThis;
	lpKernelThread = lpManager->lpCurrentKernelThread;
	if(NULL == lpKernelThread)    //The routine is called in system initializing process.
	{
		__ERROR_HANDLER(ERROR_LEVEL_CRITICAL,0L,NULL);
		return FALSE;
	}
	dwTmpCounter =  dwMillisecond / SYSTEM_TIME_SLICE;
	dwTmpCounter += System.dwClockTickCounter;         //Now,dwTmpCounter countains the 
	                                                   //tick counter value when this
	                                                   //kernel thread who calls this routine
	                                                   //must be waken up.

⌨️ 快捷键说明

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