📄 sched.c
字号:
#include "../include/kernel/sched.h"#include "../include/kernel/sys.h"#include "../include/kernel/irq.h"#include "../include/kernel/task.h"#include "../include/kernel/typedef.h"#include "../include/s3c2410/timer.h"#include "../include/s3c2410/cpu.h"#include "../include/mm/mm.h"#include "../include/kernel/gui.h"#define TASK_MEM_LIMIT (1024*1024*32)//#define _SCHEDULE_DEBUG/* * 任务数组指针 */int volatile jiffies=0;struct task_struct* task[NR_TASKS];struct task_struct* current;unsigned int last_pid;extern struct irq_ctrl_object irq_ctrl_object;extern void restorer();extern void irq();#define FIRST_TASK &task[0]#define LAST_TASK &task[NR_TASKS-1]#define KERNEL_BASE 0x30095000#define KERNEL_LIMIT 0x30400000struct task_struct INIT_TASK={ .state =TASK_RUNNING, .priority =15, .counter =15, .signal =0, .deal_signal =0, .blocked =0, .sigaction ={0,}, .alarm =0, .utime =0, .stime =0, .cutime =0, .cstime =0, .start_time =0, .exit_code =0, /* * 任务0的代码段使用了内核的空间而数据段的虚拟地址则是0x00000000~0x01ffffff, * * 本内核中规定任务的代码段和数据段必须相同,而任务0比较特殊,他的代码段和数 * 据段是分开的 */ .code_segment_base =0x30000000, .code_segment_limit =0x30a00000, .data_segment_base =0, .data_segment_limit =0x2000000, .pid =0, .father =0, .cpu_registers={/* r0 */ .r0=0,/* r1 */ .r1=0,/* r2 */ .r2=0,/* r3 */ .r3=0,/* r4 */ .r4=0,/* r5 */ .r5=0,/* r6 */ .r6=0,/* r7 */ .r7=0,/* r8 */ .r8=0,/* r9 */ .r9=0,/* r10 */ .r10=0,/* r11 */ .r11=0,/* r12 */ .r12=0,/* sp */ .sp=0x2000000-4,/* lr */ .lr=0,/* pc */ .pc=0,/* cpsr */ .cpsr=0, }};union task_union init_task; void sched_init(){ int i; for(i=0;i<NR_TASKS;i++) { task[i]=0; } last_pid=0; jiffies =0; init_task.task=INIT_TASK; task[0]=&init_task.task; current=task[0];}void sleep_on(struct task_struct** p){ struct task_struct* tmp; if(!p) return; if(current==task[0]) panic("task0 try to sleep.\n"); //进入临界区 //ENTER_CRITICAL(); //EXIT_CRITICAL();}void wake_up(struct task_struct** p){ //进入临界区 ENTER_CRITICAL(); EXIT_CRITICAL();}void save_cpu_context(unsigned int *regs){ unsigned int *p_reglist=¤t->cpu_registers.r0; int regid; for(regid=0;regid<17;regid++) { p_reglist[regid]=regs[regid]; } p_reglist[15]=regs[15]-4;}void load_cpu_context(unsigned int *regs){ unsigned int *p_reglist=¤t->cpu_registers.r0; int regid; for(regid=0;regid<17;regid++) { regs[regid]=p_reglist[regid]; } regs[15]=p_reglist[15]+4;}void switch_to_next(struct cpu_registers *regs,int nr){ if(current!=task[nr]) { //切换任务 save_cpu_context(regs); //保存当前任务状态 current=task[nr]; //当前任务切换为待加载的任务 set_process_id(nr); //更改CPU的Process ID寄存器(与MVA有关) load_cpu_context(regs); //加载新任务 /* * 将新任务的cpsr写入irq的spsr,中断返回的时候会把spsr的值加载到 * cpsr.这样才能保证每个任务运行在自己的特权级 */ write_spsr(current->cpu_registers.cpsr); }}/* * 任务调度函数,这个函数是支持多任务并行的关键 */int schedule(){ unsigned int max_counter=0;//当前最长时间片 int i; int nr; feed_dog(); /* * 任务调度的基本思路是这样的:从任务数组中选拥有最长间片 * 的任务,切换运行.若所有任务的时间片都是0,说明所有任务 * 都用完了时间片,则重新对时间片进行付值 */ while(1) { //挑选出最长时间片的任务 for(i=0;i<NR_TASKS;i++) { //当前任务槽不为空且该任务槽的任务是运行状态的 if((task[i])&&(task[i]->state==TASK_RUNNING)) { //该任务时间片是否大于当前最长时间片 if(task[i]->counter>max_counter) { max_counter=task[i]->counter; nr=i;//获得当前最长时间片的任务号 } } } //所有任务的时间片都是0,说明所有任务都用完了时间片 if(max_counter==0) { for(i=0;i<NR_TASKS;i++) { //重新分配任务的时间片 if(task[i]!=0) task[i]->counter=task[i]->priority; } } else break; } return nr;//返回准备调度的任务号}//手动切换进程int switch_task(){ int next; next=schedule(); return next;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -