📄 mt1_process.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 + -