📄 sched.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++){ 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"); 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 + -