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

📄 mt5_util.c

📁 小型操作系统,以VC为开发环境,需要boachs调试
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************
**     File name   : mt5_util.c
**     Author      : x.cheng
**     Create date :
**
**	   Comment:
**        utility function for multitask system module
**
**     Revisions:
**     $Log: mt5_util.c,v $
**     Revision 1.5  2005/08/19 15:02:17  x.cheng
**     bug fix, be aware of NULL ptr
**
**     Revision 1.4  2005/07/30 06:11:58  x.cheng
**     in new virtual space function, remove PDE(0) and PDE(1),other,
**     tasksleep() and ps function bug fix...
**
**     Revision 1.3  2005/07/27 15:54:53  x.cheng
**     bug fix, function added:
**              inline void Mt5BrowserQueue( ts_QueueNode **ppstHeadNode, char *szQueueName)
**
**     Revision 1.2  2005/07/27 07:39:27  x.cheng
**     two function added.
**        ts_Task* pstMt5GetTaskInfo( int iPid )
**        void vMt5WakeupWaitQueue(ts_WaitQueueNode *pstWaitQueue )
**
**     Revision 1.1.1.1  2005/07/27 06:53:15  x.cheng
**     add into repositories
**
**
***************************************************************************/
#include "const.h"
#include "type.h"
#include "stdarg.h"

#include "stdlib.h"
#include "string.h"
#include "queue.h"
#include "..\..\inc\i386\page.h"		//kernel\inc\i386
#include "..\..\inc\i386\system.h"
#include "..\..\inc\spinlock.h"
#include "..\..\inc\pmm.h"
#include "..\..\inc\task.h"			//kernel\inc
#include "..\..\inc\pmm.h"
#include "..\..\inc\mts.h" 
#include "..\..\inc\tui.h"

#include "..\inc\def_mts.h"
#include "..\inc\def_sched.h"

/* debug preprocessor instrument
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
				
	#endif
	#endif	
***************************/


//!
//! 这个函数是个为开发准备的函数,用来打印一个队列中的所有项 
//!
inline void Mt5BrowserQueue( ts_QueueNode **ppstHeadNode, char *szQueueName)
{
	ts_QueueNode *pstQueueNode;
	int iCnt;

	if ( *ppstHeadNode == NULL ) {
		kprintf("%s 0 node, head at %p\n", szQueueName, *ppstHeadNode);
		return;
	}
	kprintf("\n%s %d node, head at %p->", szQueueName, iCountQueueElement(ppstHeadNode), *ppstHeadNode);
	if ( *ppstHeadNode != NULL ) {
		for (pstQueueNode = *ppstHeadNode, iCnt = iCountQueueElement(ppstHeadNode); 
			 iCnt--;  pstQueueNode = pstQueueNode->pstNext ) {
			kprintf("(%p|%s)->", pstQueueNode, ((ts_Task*)pstQueueNode->pvVal)->szName);
		}
	}
	kprintf("(%p|%s)->", pstQueueNode, ((ts_Task*)pstQueueNode->pvVal)->szName);
	kprintf("end\n");
}


// --- PID operators ---------------------------------------------------//
// the following two function is:
//		Operators to manage the pids for the tasks.
//! Last used pid.
int	giLastPid = 0;

//! A spinlock used to generate new pids.
DECLARE_SPINLOCK( stPidGenerateLock );

/************************************************************
*************************************************************
**      Function Name:			iMt5GeneratePid
**      Author:                 x.cheng
**
**      Comment:
**			inline function to generate a new pid.
**
**      List of parameters:
**			
**
**      Return value:   
**			The new pid generated.
**
**      Revisions:
**			This routine generate a pid using an atomic increment.
*************************************************************
*************************************************************/
inline int iMt5GeneratePid( void )
{
	int iPid;

	SpinlockLock(&stPidGenerateLock);
	
	iPid = ++ giLastPid;
	
	SpinlockUnlock(&stPidGenerateLock);

	return iPid;
}

/************************************************************
*************************************************************
**      Function Name:			vMt5CreateVirtualSpace
**      Author:                 x.cheng
**
**      Comment:
**			Create new virtual space for a task
**		 BE sure to enter here in mutual exclusion!!!
**
**      List of parameters:
**			ts_Task 
**
**      Return value:   
**			none
**
**      Revisions:
**			pstTask->pulPdbr 中存放着新的页目录的虚拟地址
*************************************************************
*************************************************************/
void vMt5CreateVirtualSpace(ts_Task* pstTask)
{
	int i;

	// Create the virtual space of the task.
	pstTask->pulPdbr = (unsigned long*)pvPmmGetOneFreeTmpPage();
	if ( NULL == pstTask->pulPdbr ) {
		//out of virtual memroy
		kprintf("%s: out of temporary memory space!\n", __FUNCTION__);
		return;
	}

	//initialize PDBR.
		//非内核空间的页目录都为零
	memset(pstTask->pulPdbr, 0, ulPdeIndex(KERNEL_VIRTUAL_START)*sizeof(unsigned long) );
/*
		//为什么这里要设置这两个页目录呢?如果不设置的话,切换cr3就重启,真奇怪,应该没用到啊!
		pstTask->pulPdbr[0] = ( (unsigned long*)PAGE_DIR_TABLE_START_ADDRESS) [0];
		pstTask->pulPdbr[1] = ( (unsigned long*)PAGE_DIR_TABLE_START_ADDRESS) [1];
		//------------------------------
*/
	if ( g_pstCurrentTask ) {
		for( i=ulPdeIndex(KERNEL_VIRTUAL_START); i<1023; i++) {
			pstTask->pulPdbr[i] = g_pstCurrentTask->pulPdbr[i];
		}
	} else {
		for( i=ulPdeIndex(KERNEL_VIRTUAL_START); i<1023; i++) {
			pstTask->pulPdbr[i] = ( (unsigned long*)PAGE_DIR_TABLE_START_ADDRESS) [i];
		}
	}
	//map page directory into itself
	pstTask->pulPdbr[ 1023 ] = ulVirtualAddressToPhysical( (unsigned long)(pstTask->pulPdbr) ) | P_PRESENT | P_WRITE;

	//get the PDBR counter of the father, (we've just made the update!)
	if (g_pstCurrentTask) {
		pstTask->ulPdbrUpdateCounter = g_pstCurrentTask->ulPdbrUpdateCounter;
	}
}

/************************************************************
*************************************************************
**      Function Name:			pulMt5SetupStack
**      Author:                 x.cheng
**
**      Comment:
**			Initialize the stack for a new process.
**
**      List of parameters:
**			unsigned long - where the stack is placed in memroy. 
**
**      Return value:   
**			the starting stack pointer after initialization.
**
**      Revisions:
**			
*************************************************************
*************************************************************/
unsigned long *pulMt5SetupStack(unsigned long ulStackStart)
{
	unsigned long *pulStackTop = (unsigned long*)( ulAlignDown(ulStackStart, sizeof(unsigned long)) - sizeof(unsigned long) );

	// Copy the exit point address.
	//*(--stack) = (size_t)(&__task_exit_point);

	// Insert a NULL into the stack.
	*(pulStackTop - 1) = NULL;

	// Return the initial stack pointer.
	return( pulStackTop );

}

/************************************************************
*************************************************************
**      Function Name:			vMt5SwitchTaskMMU
**      Author:                 x.cheng
**
**      Comment:
**			Switch into a different task virtual address space.
**
**      List of parameters:
**			
**
**      Return value:   
**			
**
**      Revisions:
**			
*************************************************************
*************************************************************/
inline void vMt5SwitchTaskMMU( ts_Task *pstPrevTask, ts_Task *pstNextTask )
{
	unsigned long ulPrevTaskCR3 = ulVirtualAddressToPhysical( (unsigned long)(pstPrevTask->pulPdbr) );
	unsigned long ulNextTaskCR3 = ulVirtualAddressToPhysical( (unsigned long)(pstNextTask->pulPdbr) );

	if( ulPrevTaskCR3 != ulNextTaskCR3 )
	{
		if( pstNextTask->ulPdbrUpdateCounter != pstPrevTask->ulPdbrUpdateCounter )
		{
			unsigned long ulFlags;
			SaveEflagsAndCli( ulFlags );

			// Update the page directory for kernel address space.
			// This must be done to preserve coherency between
			// page directories of each task.
			memcpy( pulPdeOffset(pstNextTask->pulPdbr, KERNEL_VIRTUAL_START),
					pulPdeOffset(pstPrevTask->pulPdbr, KERNEL_VIRTUAL_START),
				( ulPdeIndex(PAGE_DIR_TABLE_START_ADDRESS) - ulPdeIndex(KERNEL_VIRTUAL_START) ) * sizeof(unsigned long) );

			// Update the pdbr counter.
			pstNextTask->ulPdbrUpdateCounter = pstPrevTask->ulPdbrUpdateCounter;

			RestoreEflags( ulFlags );

		}
		// Switch into the new virtual space.
		vSwitchMMU( ulNextTaskCR3 );	//in page.h
	}
}

/************************************************************

⌨️ 快捷键说明

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