/* * 'sched.c' is the main kernel file. It contains scheduling primitives * (sleep_on, wakeup, schedule etc) as well as a number of simple system * call functions (type getpid(), which just extracts a field from * current-task */ #include #include #include #include #include #include #include
#define LATCH (1193180/HZ)
extern void mem_use(void);
extern int timer_interrupt(void); extern int system_call(void);
union task_union { struct task_struct task; char stack[PAGE_SIZE]; };
static union task_union init_task = {INIT_TASK,};
long volatile jiffies=0; long startup_time=0; struct task_struct *current = &(init_task.task), *last_task_used_math = NULL;
struct task_struct * task[NR_TASKS] = {&(init_task.task), };
long user_stack [ PAGE_SIZE>>2 ] ;
struct { long * a; short b; } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 }; /* * 'math_state_restore()' saves the current math information in the * old math state array, and gets the new ones from the current task */ void math_state_restore() @@协处理器状态保存 { if (last_task_used_math) __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387)); if (current->used_math) __asm__("frstor %0"::"m" (current->tss.i387)); else { __asm__("fninit"::); current->used_math=1; } last_task_used_math=current; }
/* * 'schedule()' is the scheduler function. This is GOOD CODE! There * probably won't be any reason to change this, as it should work well * in all circumstances (ie gives IO-bound processes good response etc).
* The one thing you might take a look at is the signal-handler code here. * * NOTE!! Task 0 is the 'idle' task, which gets called when no other * tasks can run. It can not be killed, and it cannot sleep. The 'state'
* information in task[0] is never used. */ void schedule(void) { int i,next,c; struct task_struct ** p;
/* check alarm, wake up any interruptible tasks that have got a signal */
for(p = &LAST_TASK ; p >&FIRST_TASK ; --p) if (*p) { if ((*p)->alarm && (*p)->alarm signal |= (1alarm = 0; } if ((*p)->signal && (*p)->state==TASK_INTERRUPTIBLE) (*p)->state=TASK_RUNNING; } @@ task 1 如何变为TASK_RUNNING??signal 如何得到,alarm如何变非0且state == TASK_RUNNING && (*p)->counter >c) c = (*p)->counter, next = i; } if (c) break; @@记数大于零 for(p = &LAST_TASK ; p >&FIRST_TASK ; --p) if (*p) (*p)->counter = ((*p)->counter >>1) + (*p)->priority; } switch_to(next); }
int sys_pause(void) { current->state = TASK_INTERRUPTIBLE; @@任务可中断 schedule(); return 0; }
void sleep_on(struct task_struct **p) { struct task_struct *tmp;
if (!p) return; if (current == &(init_task.task)) panic("task[0] trying to sleep"); tmp = *p; *p = current; current->state = TASK_UNINTERRUPTIBLE; schedule(); if (tmp) @@激活p,什么时候回来?唤醒上次睡眠的进程 tmp->state=0; }
void interruptible_sleep_on(struct task_struct **p) { struct task_struct *tmp;
if (!p) return; if (current == &(init_task.task)) panic("task[0] trying to sleep"); tmp=*p; *p=current; repeat: current->state = TASK_INTERRUPTIBLE; schedule(); if (*p && *p != current) { (**p).state=0; goto repeat; } @@好象下不来 *p=NULL; if (tmp) tmp->state=0; }
void wake_up(struct task_struct **p) { if (p && *p) { (**p).state=0; @@唤醒该进程running *p=NULL; @@睡眠栈为0 } }
void do_timer(long cpl) @@定时调度 { if (cpl) current->utime++; @@用户态时间加一 else current->stime++; @@系统态时间加一 if ((--current->counter)>0) return; @@当前记数减一 current->counter=0; if (!cpl) return; schedule(); }
int sys_alarm(long seconds) { current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; return seconds; }
int sys_getpid(void) { return current->pid; }
int sys_getppid(void) { return current->father; }
int sys_getuid(void) { return current->uid; }
int sys_geteuid(void) { return current->euid; }
int sys_getgid(void) { return current->gid; }
int sys_getegid(void) { return current->egid; }
int sys_nice(long increment) { if (current->priority-increment>0) current->priority -= increment; return 0; }
int sys_signal(long signal,long addr,long restorer) { long i;
switch (signal) { case SIGHUP: case SIGINT: case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGUSR1: case SIGSEGV: case SIGUSR2: case SIGPIPE: case SIGALRM: case SIGCHLD: i=(long) current->sig_fn[signal-1]; current->sig_fn[signal-1] = (fn_ptr) addr; current->sig_restorer = (fn_ptr) restorer; return i; default: return -1; } }
void sched_init(void) { int i; struct desc_struct * p;
set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));@@init task tss
set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));@@init ldt p = gdt+2+FIRST_TSS_ENTRY; for(i=1;ia=p->b=0; p++; p->a=p->b=0; p++; } ltr(0); @@调入task 0的tss lldt(0); @@调入task 0的ldt outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >>8 , 0x40); /* MSB */ set_intr_gate(0x20,&timer_interrupt); @@irq 0 时钟中断 outb(inb_p(0x21)&~0x01,0x21); set_system_gate(0x80,&system_call); }  
|