linux-schec.c

/*
*  linux/kernel/sched.c
*                                            //--内核中有关任务(进程)调度管理的程序
*  (C) 1991  Linus Torvalds
*/
/*
* '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 <linux/sys.h>
#include <linux/fdreg.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <signal.h>
#define _S(nr) (1<<((nr)-1))                        //--左移nr-1位
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
void show_task(int nr,struct task_struct * p)
{                                    //--内核调试函数,显示任务号nr的进程号,进程状态和内核栈空闲字节数
    int i,j = 4096-sizeof(struct task_struct);
    printk("%d: pid=%d, state=%d, father=%d, child=%d, ",nr,p->pid,
        p->state, p->p_pptr->pid, p->p_cptr ? p->p_cptr->pid : -1);
    i=0;
    while (i<j && !((char *)(p+1))[i])        //--检测0的字节数
        i++;
    printk("%d/%d chars free in kstack/n/r",i,j);
    printk("   PC=%08X.", *(1019 + (unsigned long *) p));
    if (p->p_ysptr || p->p_osptr)
        printk("   Younger sib=%d, older sib=%d/n/r",
            p->p_ysptr ? p->p_ysptr->pid : -1,
            p->p_osptr ? p->p_osptr->pid : -1);
    else
        printk("/n/r");
}
void show_state(void)
{
    int i;
    printk("/rTask-info:/n/r");
    for (i=0;i<NR_TASKS;i++)        //--NR_TASKS系统能容纳的最大进程数(64)
        if (task[i])
            show_task(i,task[i]);
}
#define LATCH (1193180/HZ)            //--8253时钟初始值
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,};
unsigned long volatile jiffies=0;
unsigned long startup_time=0;
int jiffies_offset = 0;        /* # clock ticks to add to get "true
                   time".  Should always be less than
                   1 second's worth.  For time fanatics
                   who like to syncronize their machines
                   to WWV :-) */
struct task_struct *current = &(init_task.task);
struct task_struct *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 == current)
        return;
    __asm__("fwait");
    if (last_task_used_math) {
        __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
    }
    last_task_used_math=current;
    if (current->used_math) {
        __asm__("frstor %0"::"m" (current->tss.i387));
    } else {
        __asm__("fninit"::);
        current->used_math=1;
    }
}
/*
*  '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)->timeout && (*p)->timeout < jiffies) {
                (*p)->timeout = 0;                    //--超时定时器复位
                if ((*p)->state == TASK_INTERRUPTIBLE)
                    (*p)->state = TASK_RUNNING;        //--置为就绪态
            }
            if ((*p)->alarm && (*p)->alarm < jiffies) {
                (*p)->signal |= (1<<(SIGALRM-1));
                (*p)->alarm = 0;                    //--alarm定时值
            }
            if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
            (*p)->state==TASK_INTERRUPTIBLE)
                (*p)->state=TASK_RUNNING;            //--信号位图
        }
/* this is the scheduler proper: */
    while (1) {
        c = -1;
        next = 0;
        i = NR_TASKS;
        p = &task[NR_TASKS];
        while (--i) {                                //--找counter值最大的,即运行时间最短的
            if (!*--p)
                continue;
            if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
                c = (*p)->counter, next = i;
        }
        if (c) break;                                //--若counter=0,则重置counter=priority
        for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
            if (*p)
                (*p)->counter = ((*p)->counter >> 1) +
                        (*p)->priority;                //--计算counter=counter/2+priority;
    }
    switch_to(next);                                //--切换到下一个任务
}
int sys_pause(void)                                    //--未完全实现的函数
{
    current->state = TASK_INTERRUPTIBLE;
    schedule();
    return 0;
}
static inline void __sleep_on(struct task_struct **p, int state)
{
    struct task_struct *tmp;                        //--置当前任务为指定的睡眠状态
    if (!p)
        return;
    if (current == &(init_task.task))
        panic("task[0] trying to sleep");
    tmp = *p;
    *p = current;
    current->state = state;
repeat:    schedule();
    if (*p && *p != current) {
        (**p).state = 0;
        current->state = TASK_UNINTERRUPTIBLE;
        goto repeat;
    }
    if (!*p)
        printk("Warning: *P = NULL/n/r");
    if (*p = tmp)
        tmp->state=0;
}
void interruptible_sleep_on(struct task_struct **p)        //--置当前任务为可中断的等待状态
{
    __sleep_on(p,TASK_INTERRUPTIBLE);
}
void sleep_on(struct task_struct **p)                    //--置当前任务为不可中断的等待状态
{
    __sleep_on(p,TASK_UNINTERRUPTIBLE);
}
void wake_up(struct task_struct **p)                    //--唤醒*p指向的任务
{
    if (p && *p) {
        if ((**p).state == TASK_STOPPED)
            printk("wake_up: TASK_STOPPED");
        if ((**p).state == TASK_ZOMBIE)
            printk("wake_up: TASK_ZOMBIE");
        (**p).state=0;
    }
}
/*
* OK, here are some floppy things that shouldn't be in the kernel
* proper. They are here because the floppy needs a timer, and this
* was the easiest way of doing it.
*/                                                //--下面为一些有关软盘的子程序,220-281为处理软驱定时
static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
static int  mon_timer[4]={0,0,0,0};
static int moff_timer[4]={0,0,0,0};
unsigned char current_DOR = 0x0C;
                                                
int ticks_to_floppy_on(unsigned int nr)            //--设置moff_timer[]和mon_timer[]
{
    extern unsigned char selected;
    unsigned char mask = 0x10 << nr;
    if (nr>3)
        panic("floppy_on: nr>3");
    moff_timer[nr]=10000;        /* 100 s = very big :-) */
    cli();                /* use floppy_off to turn it off */
    mask |= current_DOR;
    if (!selected) {
        mask &= 0xFC;
        mask |= nr;
    }
    if (mask != current_DOR) {
        outb(mask,FD_DOR);
        if ((mask ^ current_DOR) & 0xf0)
            mon_timer[nr] = HZ/2;
        else if (mon_timer[nr] < 2)
            mon_timer[nr] = 2;
        current_DOR = mask;
    }
    sti();
    return mon_timer[nr];
}
void floppy_on(unsigned int nr)                //--等待马达启动
{
    cli();
    while (ticks_to_floppy_on(nr))
        sleep_on(nr+wait_motor);
    sti();
}
void floppy_off(unsigned int nr)            //--停转等待时间
{
    moff_timer[nr]=3*HZ;
}
void do_floppy_timer(void)                    //--设置mon_timer[]和moff_timer[]
{
    int i;
    unsigned char mask = 0x10;
    for (i=0 ; i<4 ; i++,mask <<= 1) {
        if (!(mask & current_DOR))
            continue;
        if (mon_timer[i]) {
            if (!--mon_timer[i])
                wake_up(i+wait_motor);
        } else if (!moff_timer[i]) {
            current_DOR &= ~mask;
            outb(current_DOR,FD_DOR);
        } else
            moff_timer[i]--;
    }
}
                                            //--下面是关于定时器的代码
#define TIME_REQUESTS 64
static struct timer_list {                    //--定时器链表结构和定时器数组
    long jiffies;
    void (*fn)();                            //--定时处理函数
    struct timer_list * next;
} timer_list[TIME_REQUESTS], * next_timer = NULL;
void add_timer(long jiffies, void (*fn)(void))        //--增加定时器
{
    struct timer_list * p;
    if (!fn)
        return;
    cli();
    if (jiffies <= 0)
        (fn)();
    else {
        for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
            if (!p->fn)
                break;
        if (p >= timer_list + TIME_REQUESTS)
            panic("No more time requests free");
        p->fn = fn;
        p->jiffies = jiffies;
        p->next = next_timer;
        next_timer = p;
        while (p->next && p->next->jiffies < p->jiffies) {
            p->jiffies -= p->next->jiffies;
            fn = p->fn;
            p->fn = p->next->fn;
            p->next->fn = fn;
            jiffies = p->jiffies;
            p->jiffies = p->next->jiffies;
            p->next->jiffies = jiffies;
            p = p->next;
        }
    }
    sti();
}
void do_timer(long cpl)                        //--时钟中断处理程序
{
    static int blanked = 0;
    if (blankcount || !blankinterval) {        //--判黑屏超时
        if (blanked)
            unblank_screen();
        if (blankcount)
            blankcount--;
        blanked = 0;
    } else if (!blanked) {
        blank_screen();
        blanked = 1;
    }
    if (hd_timeout)                            //--处理硬盘操作超时
        if (!--hd_timeout)
            hd_times_out();
    if (beepcount)                            //--发声计数
        if (!--beepcount)
            sysbeepstop();
    if (cpl)                                //--cpl=0为超级用户,cpl>0为普通用户
        current->utime++;
    else
        current->stime++;
    if (next_timer) {                        //--定时器链表处理
        next_timer->jiffies--;
        while (next_timer && next_timer->jiffies <= 0) {
            void (*fn)(void);
            
            fn = next_timer->fn;
            next_timer->fn = NULL;
            next_timer = next_timer->next;
            (fn)();
        }
    }
    if (current_DOR & 0xf0)
        do_floppy_timer();
    if ((--current->counter)>0) return;
    current->counter=0;
    if (!cpl) return;
    schedule();
}
int sys_alarm(long seconds)                        //--系统调用功能,设置报警时间值
{
    int old = current->alarm;
    if (old)
        old = (old - jiffies) / HZ;
    current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
    return (old);
}
int sys_getpid(void)
{
    return current->pid;
}
int sys_getppid(void)
{
    return current->p_pptr->pid;
}
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)                        //--降低对CPU的使用优先权
{
    if (current->priority-increment>0)
        current->priority -= increment;
    return 0;
}
void sched_init(void)                                //--内核调度程序的初始化子程序
{
    int i;
    struct desc_struct * p;
    if (sizeof(struct sigaction) != 16)
        panic("Struct sigaction MUST be 16 bytes");
    set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));    //--全局描述符表中设置初始任务0的
    set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.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++;
    }
/* Clear NT, so that we won't have troubles with that later on */
    __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");    //--清除标志寄存器的NT位
    ltr(0);                                            //--将任务0的TSS段段选择符加载到任务寄存器tr上
    lldt(0);
    outb_p(0x36,0x43);        /* binary, mode 3, LSB/MSB, ch 0 */
    outb_p(LATCH & 0xff , 0x40);    /* LSB */        //--初始化8253寄存器
    outb(LATCH >> 8 , 0x40);    /* MSB */
    set_intr_gate(0x20,&timer_interrupt);            //--设置时钟中断处理程序句柄
    outb(inb_p(0x21)&~0x01,0x21);
    set_system_gate(0x80,&system_call);
}
|xGv00|fcc8d4de8197f69fde70263fb4d52380

你可能感兴趣的:(linux-schec.c)