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

📄 sched.c

📁 一个基于MMU的操作系统
💻 C
字号:
#include <sched.h>
#include <s3c2410.h>
#include <interrupt.h>
#include <init.h>
#include <mmu.h>
#include <string.h>
#include <serial.h>

struct task_struct task[TASK_NR];
struct task_struct*  current = NULL;
extern void __switch_to(struct task_struct *pcur,struct task_struct *pnext);


/*****************************************************************************
* 初始化task数组
* 初始化任务0,即task[0]
*****************************************************************************/
void sched_init(void)
{
	struct task_struct *p = &task[0];
	int i,j;

	DPRINTK(KERNEL_DEBUG,"\n\rkernel:sched_init,create task 0\n\r");
	
	for(i = 0; i < TASK_NR; i++,p++){
		p->pid = -1;
		p->state = TASK_UNALLOCATE;
		p->count = 0;
		p->priority = 0;
		for(j = 0; j < 1024; j++){
			p->kernelstack[j] = 0;
		}
	}
	p = &task[0];
	p->pid = 0;
	p->state = TASK_RUNNING;
	p->count = 5;
	p->priority = 5;
	p->content[0] = (unsigned long)(&task[1]);
	p->content[1] = 0x5f;   		/*cpsr*/
	p->content[2] = 0x30100000-1024;	/*usr/sys模式堆栈*/
	p->content[3] = 0x13;		/*svc模式*/
	p->content[17]= 0;		/*pc*/
	
	current = &task[0];
}

/*****************************************************************************
* 切换到task数组中处于运行状态的、count值最大的任务
* 如果所有任务的count值都为0,则重新计算count = count / 2 + priority
* 进程0不参与竞争
*****************************************************************************/
void schedule(void)
{
	long max = -1;
	long i = 0,  next = 0;
	struct task_struct * ptmp_tsk = NULL;

	DPRINTK(KERNEL_DEBUG,"kernel:schedule\n\r");	

	while(1){
		for(i = 1; i < TASK_NR; i++){
			if((task[i].state == TASK_RUNNING)&&(max < (long)task[i].count)){
				max = (long)task[i].count;
				next = i;
			}
		}

		/*如果所有任务都不处于就绪状态,max = -1,next = 0,跳出循环执行任务0*/
		/*如果max = 0,则进行下面的计算count值*/
		/*如果max > 0,则跳出循环...*/
		/*这种方法太妙了,摘自linux0.11*/
		if(max)break;	

		for(i = 0; i < TASK_NR; i++){
			if(task[i].state == TASK_RUNNING)
				task[i].count = task[i].priority;
//			task[i].count = (task[i].count >> 1) + task[i].priority;			
		}
	}
	if(current == &task[next])
		return;
	if(task[next].pid < 0)
		return;
	ptmp_tsk = current;
	current = &task[next];
	DPRINTK(KERNEL_DEBUG,"kernel:__switch_to\n\r");		
	__switch_to(ptmp_tsk,&task[next]);
	DPRINTK(KERNEL_DEBUG,"kernel:return from __switch_to\n\r");			
}



/*****************************************************************************
* 当前进程count减1
* 如果当前进程不处于可运行状态,或count=0,调度进程
*****************************************************************************/
void do_timer(void)
{
	int i = 0, b_wakeup = 0;
	DPRINTK(KERNEL_DEBUG,"kernel:do_timer\n\r");

	if(!current){
		DPRINTK(KERNEL_DEBUG,"kernel:leaving do_timer,hasn't init task\n\r");
		return;
	}

	for(i = 1; i < TASK_NR; i++){
		if(task[i].state == TASK_SLEEPING){
			if(!(--task[i].timer)){
				task[i].state = TASK_RUNNING;
				b_wakeup = 1;
			}
		}
	}

	if(current->count){
		current->count--;
	}
	
	if((current->state != TASK_RUNNING)|| !current->count || b_wakeup){
		schedule();
	}
	DPRINTK(KERNEL_DEBUG,"kernel:leaving do_timer\n\r");			
}

/*******************************************************************************
* linux下,在控制台下如此运行程序:file  param0 param1 ...
* 其中的file  param0 param1 ...作为参数传递给int main(int argc, char **argc)
* argc为参数个数,即file,param0,param1...的个数
* argv[0]为file字串的地址,argv[1]为param0字串的地址...
*
* OSCreateProcess中参数含义为:
* 1. nand_start_addr:本进程代码存在nand flash中的位置,len:代码大小,通过这两个参数来
* 确定一个文件file
* 2. parameters为"param0 param1 param2 ...",各参数间以空格分开
* 请注意,进程main函数中的file参数就没什么用处了,我随便设为pid了
* 3. priority:进程优先级
*
* 本函数用于从nand flash中读处代码,设置其main函数执行前的环境:堆栈、参数,设置相应的任务数据结构
**********************************************************************************/
int OSCreateProcess(unsigned long nand_start_addr, unsigned long len, char *parameters, long priority)
{
	unsigned long i = 1,pid,j,argc = 0;
	unsigned long *p_VA;
	char *pDes;
	
	DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess\n\r");
	
	for(; i < TASK_NR; i++){
		if(!(task[i].state == TASK_UNALLOCATE && VALIDE_TASK_INDEX(i)))
			continue;
		
		OS_ENTER_CRITICAL();

		pid = i;

		/*从NAND Flash中复制代码到进程号i对应的物理地址*/
		/*虚拟地址SDRAM_RAW_RW_VA_BASE + i*0x100000指向PID=i的进程的1M内存,并且此虚拟地址>32M,所以与PID无关*/
		DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::nand_read_ll\n\r");

		p_VA = (unsigned long *)(SDRAM_RAW_RW_VA_BASE + pid*0x100000);				
		
		//清0
		for( j = 0; j < 0x100000/4; j++)
			p_VA[j] = 0;
		
		nand_read_ll((unsigned char*)p_VA, nand_start_addr,len);

		/****************************************************************************************
		* 设置用户函数int main(int argc, char **argc)的参数
		* 进程i的1M地址的最后1k空间用于存放参数(地址向上依次为):
		* argc,argv[0],argv[1],...,argv[argc-1],NULL,"argv[0]对应的string","argv[1]对应的string",...
		*****************************************************************************************/
		DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::set the new process's parameters\n\r");			

		//放参数
		p_VA = (unsigned long *)(SDRAM_RAW_RW_VA_BASE + pid*0x100000 + 0x100000 - 1024);
		
		argc = 0;
		j = 0;

		/*计算paramters中参数个数*/
		if(parameters){
			while(parameters[j]){
				while(parameters[j] == ' ')j++;	//吃掉空格
				if(!parameters[j])
					break;
				argc++;
				while(parameters[j] && ( parameters[j] != ' '))j++;	//吃掉非空格
				if(!parameters[j])
					break;
			}
		}
		
		
		*p_VA++ = argc + 1;	   	/*main函数中的argc*/
		
		*p_VA++ = pid;		/*argv[0]*/

		pDes = (char *)(p_VA + argc + 1);	/*pDes指向"...,argc[argc-1],NULL"后面,用来存放argv[...]对应的字符串*/

		for(i = 0, j = 0; i < argc; i++){
			*p_VA++ = (unsigned long)pDes -(SDRAM_RAW_RW_VA_BASE + pid*0x100000);

			while(parameters[j] == ' ')j++;	//吃掉空格
			
			if(!parameters[j])
				break;
			while(parameters[j] && ( parameters[j] != ' ')){//复制参数
 				*pDes = parameters[j];
				pDes++;
				j++;
			}
			*pDes = '\0';
			
		       	pDes = (char *)(((unsigned long)pDes + 4)&(~0x3)); 	//对齐

			if(!parameters[j])
				break;
		}
		
		
		/************************************************************************************
		* 设置参数:
		* 进程刚开始处于usr/sys模式
		* 参考sched.S中保存进程上下文的顺序为:
		* sp_svc,cpsr,sp_usr/sys,0x13(表示svc),r0-r12,lr
		**************************************************************************************/
		DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::set the new process's content\n\r");
		task[pid].pid = pid;
		task[pid].state = TASK_RUNNING;
		task[pid].count = 15;
		task[pid].priority = priority;
		task[pid].content[0] = (unsigned long)(&task[pid+1]);
		task[pid].content[1] = 0x5f;   	/*cpsr*/
		task[pid].content[2] = 0x100000-1024; /*usr/sys模式堆栈*/
		task[pid].content[3] = 0x13;	/*svc模式*/
		task[pid].content[17]= 0;	/*pc*/
		
		OS_EXIT_CRITICAL();
		return 1;
	}
	
	return 0;
}

⌨️ 快捷键说明

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