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

📄 mt1_process.c

📁 小型操作系统,以VC为开发环境,需要boachs调试
💻 C
字号:
/***************************************************************************
**     File name   : mt1_process.c
**     Author      : x.cheng
**     Create date :
**
**	   Comment:
**        function for process management
**
**     Revisions:
**     $Log: mt1_process.c,v $
**     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\x86.h"
#include "..\..\inc\i386\system.h"
#include "..\..\inc\task.h"			//kernel\inc
#include "..\..\inc\mts.h"
#include "..\..\inc\tui.h"
#include "..\..\inc\debug.h"
#define __USER_SPACE_ALLOCTOR__
#include "..\..\inc\vmm.h"
#define __MTS_SRC__ 
#include "..\inc\def_mts.h"
#include "..\inc\def_sched.h"


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

/************************************************************
*************************************************************
**      Function Name:			pstMt1CreateProcess
**      Author:                 x.cheng
**
**      Comment:
**			Create a process for routine with new virtual space
**
**      List of parameters:
**			pvRoutine - The address of the entry point for the task.
**			szName	- The name of the new task
**			iPrivilege - The privilege level (KERNEL_PRIVILEGE or USER_PRIVILEGE).
**
**      Return value:   
**          A pointer to the new-created task structure.
**			error: NULL If an error occurs (in particular out-of-memory)
**
**      Revisions:
**
*************************************************************
*************************************************************/
ts_Task* pstMt1CreateProcess(void *pvRoutine, char *szName, int iPrivilege)
{
	ts_Task *pstNewTask;

	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		POSITION();
	#endif
	#endif

	vScheduleEnterCritialRegion();

	vDbgDummy();
	// --- Create the task structure ------------------------------ //
	//
	// IA-32 Intel(R) Architecture Software Developer's Manual
	// Volume 3: System Programming Guide - Chapter 6 - reports:
	//
	// "If paging is used, care should be taken to avoid placing a
	// page boundary within the part of the TSS that the processor
	// reads during a task switch (the first 104 bytes). If a page
	// boundary is placed within this part of the TSS, the pages on
	// either side of the boundary must be present at the same time
	// and contiguous in physical memory.
	// 
	// 在发生任务切换的时候,CPU 总是读TSS段开始的物理地址连续的104个字节,
	// 在读取这些字节的时候,可能并不使用分页转换。因此如果分配的给TSS
	// 的物理内存不连续(跨页)的话,则为将来的任务切换埋下了隐患...
	#ifdef _DEBUG__
	#ifdef _DEBUG_IDE__
	POSITION();
	#endif
	#endif
	pstNewTask = pvVmmKeAlignMalloc( PAGE_SIZE, sizeof(ts_Task), GFP_KERNEL );
		//pstNewTask的地址总是在PAGE_SIZE界上开始,比如0xD0001000
	if (pstNewTask == NULL) {
		//out of virtua memory
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		kprintf("%s: cannot allocate task structure for '%s'\n", __FUNCTION__, szName);
	#endif 
	#endif	
		vScheduleLeaveCriticalRegion();
		return NULL;
	}
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		kprintf("PCB for \"%s\" locate at %p\n", szName, pstNewTask);
	#endif 
	#endif	

	// Add the task into the zombie queue, so if the current task
	// is killed the space allocated until now can be freed by the
	// PageDaemon daemon.
	iAddQueueNode(&g_pstZombieQueue, pstNewTask);
	pstNewTask->ucState = TASK_STATE_NEW;

	// Create the kernel(Ring0) stack.
	pstNewTask->ulRing0Stack = (unsigned long)pvVmmKeMalloc(TASK_KERNEL_STACK_SIZE, GFP_KERNEL);
	if ( NULL == pstNewTask->ulRing0Stack ) {
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		kprintf("%s: cannot allocate Ring0 stack for '%s'\n", __FUNCTION__, szName);
	#endif
	#endif
		vVmmKeFree(pstNewTask);
		vScheduleLeaveCriticalRegion();
		return NULL;
	}
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		kprintf("%s: pstNewTask->ulRing0Stack =%p\n", __FUNCTION__, pstNewTask->ulRing0Stack);
	#endif
	#endif

	// Zero the stack..
	memset( (void *)pstNewTask->ulRing0Stack, 0, TASK_KERNEL_STACK_SIZE);

	// Setup the privileged stack in tss.
	// when switch to ring0, stack is different with ring3(user mode) one.
	pstNewTask->stTSS.ss0 = KERNEL_STACK;
	pstNewTask->stTSS.esp0 = ulAlignDown(
		(unsigned long)(pstNewTask->ulRing0Stack) + TASK_KERNEL_STACK_SIZE - sizeof(unsigned long),	sizeof(unsigned long) );

	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		kprintf("%s: pstNewTask->stTSS.esp0  =%p\n", __FUNCTION__, pstNewTask->stTSS.esp0 );
		kprintf("sizeof(ts_TSS_IO)=%x, &pstNewTask->stTSS=%p, ACS_TSSSEG=%x\n", sizeof(ts_TSS_IO),
				&pstNewTask->stTSS, ACS_TSSSEG);
	#endif
	#endif
	// Setup the TSS
		// funcion uiSetupGdtEntry defined in system.h
	pstNewTask->uiTssSelector = uiSetupGdtEntry(sizeof(ts_TSS_IO), (unsigned long)&pstNewTask->stTSS, ACS_TSSSEG, 0);
	if ( NULL == pstNewTask->uiTssSelector ) {
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		kprintf("%s: out of GDT entrys!!!can't create task '%s'\n", __FUNCTION__, szName);
	#endif
	#endif
		vVmmKeFree(pstNewTask);
		vVmmKeFree( (void *)pstNewTask->ulRing0Stack );
		vScheduleLeaveCriticalRegion();

		return NULL;
	}
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		kprintf("%s: pstNewTask->uiTssSelector  =%x\n", __FUNCTION__, pstNewTask->uiTssSelector );
	#endif
	#endif

	// set the privilege level(KERNEL_PRIVILEGE or USER_PRIVILEGE)
	pstNewTask->iPrivilege = iPrivilege;
	// set the task type
	pstNewTask->stFlags.Type = TASK_TYPE_PROCESS;

	// Create the virtual space of the task.
	vMt5CreateVirtualSpace(pstNewTask);
	if ( NULL == pstNewTask->pulPdbr ) {   //注意,pulPdbr现在放的虚拟地址
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
		kprintf("%s: out of memory!!!can't create pdbr for '%s'\n", __FUNCTION__, szName);
	#endif
	#endif
		vVmmKeFree(pstNewTask);
		vVmmKeFree( (void *)pstNewTask->ulRing0Stack );
		vRemoveGdtEntry(pstNewTask->uiTssSelector);

		vScheduleLeaveCriticalRegion();
		return NULL;
	}
	
	//setup the task page directory address.
		//function ulVirtualAddressToPhysical defined in page.h
	pstNewTask->stTSS.cr3 = ulVirtualAddressToPhysical((unsigned long)pstNewTask->pulPdbr);

	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
	kprintf("pstNewTask->stTSS.cr3 = %08x\n", pstNewTask->stTSS.cr3);
	vDbgDummy();	//dummy function for break point assertion...
	#endif
	#endif
	//暂时先切换到新的地址空间去运行一下,
	//注意,现在时在内核空间,所有进程的内核空间都时空享的,所以没有页错误
		//oops, some bug inside...
	if ( NULL != g_pstCurrentTask ) {
		vMt5SwitchTaskMMU(g_pstCurrentTask, pstNewTask);
	} else {
		vSwitchMMU(pstNewTask->stTSS.cr3);		//inline function in page.h
	}

	//create the task stack
	pstNewTask->stTSS.ss = (iPrivilege == KERNEL_PRIVILEGE) ? KERNEL_STACK : USER_STACK | 3;
	if ( KERNEL_PRIVILEGE == iPrivilege ) {
		pstNewTask->stTSS.esp = (unsigned long)pulMt5SetupStack( pstNewTask->stTSS.esp0+sizeof(unsigned long) );

	} else {
		pstNewTask->stTSS.esp = (unsigned long)pulMt5SetupStack( TASK_USER_STACK_START );
	}
	
	#ifdef _DEBUG__
	#ifdef _DEBUG_MTS__
	kprintf("pstNewTask->stTSS.ss = %04x\tpstNewTask->stTSS.esp = %08x\n", pstNewTask->stTSS.ss, pstNewTask->stTSS.esp);
	vDbgDummy();	//dummy function for break point assertion...
	#endif
	#endif

	//initilize the use heap
	vVmmUeMallocInit(pstNewTask, TASK_USER_HEAP_START, TASK_USER_HEAP_SIZE);

	//restore the old address space
	if (g_pstCurrentTask != NULL) {
		vMt5SwitchTaskMMU(pstNewTask, g_pstCurrentTask);
	}

	//setup the io port mapping
	pstNewTask->stTSS.uiIoMapAddr = sizeof(ts_TSS);
	memsetl( pstNewTask->stTSS.aulIoMap, 0xFFFFFFFF, IO_MAP_SIZE);

	// Setup general registers.
	if ( iPrivilege == KERNEL_PRIVILEGE ) {
		pstNewTask->stTSS.ds = pstNewTask->stTSS.es = 
		pstNewTask->stTSS.fs = pstNewTask->stTSS.gs = KERNEL_DATA;
	} else {
		pstNewTask->stTSS.ds = pstNewTask->stTSS.es = 
		pstNewTask->stTSS.fs = pstNewTask->stTSS.gs = USER_DATA | 3;
	}

	// setup the eflags register.
	pstNewTask->stTSS.eflags = EFLAGS_IOPL0 | EFLAGS_IF | 0x02;

	// setup the starting address(program counter).
	pstNewTask->stTSS.cs = (iPrivilege == KERNEL_PRIVILEGE) ? KERNEL_CODE : USER_CODE | 3;
	pstNewTask->stTSS.eip = (unsigned long)pvRoutine;

	// store the process's name
	strncpy( pstNewTask->szName, szName, sizeof(pstNewTask->szName)-2 );

	// Set the process credentials.
	pstNewTask->iPid = iMt5GeneratePid();
		//id setup...

	// set the parent
	pstNewTask->pstFather = g_pstCurrentTask;

	// set the console
	if (g_pstCurrentTask != NULL)	pstNewTask->iConsole = g_pstCurrentTask->iConsole;
	// set the priority
	pstNewTask->iPriority = pstNewTask->iCounter = HIGH_PRIORITY;

	// insert the task to the ready queue.
	iRemoveQueueNode(&g_pstZombieQueue, pstNewTask);
	iAddQueueNode(&g_pstReadyQueue, pstNewTask);
	pstNewTask->ucState = TASK_STATE_READY;

	vScheduleLeaveCriticalRegion();

	// This is a little trick... Because we exit
	// from a very long critical region we call
	// the scheduler to enforce a new task selection.
	if( g_pstCurrentTask != NULL )
		vMt3Schedule();

	return (pstNewTask);
}

⌨️ 快捷键说明

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