📄 mt5_util.c
字号:
/***************************************************************************
** 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 + -