/*
* '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 <linux/sched.h>
#include <linux/kernel.h>
#include <signal.h>
#include <linux/sys.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>

#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 < jiffies) {
@@??
     (*p)->signal |= (1<<(SIGALRM-1));@@14-1
     (*p)->alarm = 0;
    }
   if ((*p)->signal && (*p)->state==TASK_INTERRUPTIBLE)
    (*p)->state=TASK_RUNNING;
  }
@@ task 1 如何变为TASK_RUNNING??signal 如何得到,alarm如何变非0且<jiffies

/* this is the scheduler proper: */
@@操作系统最重要的函数,调度算法
@@这个循环要找到一个可运行的任务才能退出,会死在这吗?即如没有一个可运行
while (1) {
  c = -1;
  next = 0;
  i = NR_TASKS;
  p = &task[NR_TASKS];
  while (--i) {
   if (!*--p)
    continue;
   if ((*p)->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;i<NR_TASKS;i++) {
  task[i] = NULL;
  p->a=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);
}
 
 

本文转自中文Linux论坛