NetBSD系列介绍--调度器
    调度器的介绍不是很好写,如果简单介绍,那就只有两个文件:src/sys/kern/sched_4bsd.c 和 src/sys/kern/sched_m2.c,默认调度算法还是从4.4BSD就一直沿用的调度算法,即前一个文件中实现的,代码中有关于调度算法的详细注释,直接看代码就可以了。你实现了这两个文件中共有的函数,就算实现了一个调度器了,内核的其他部分会在适当的位置调用这些函数。问题是NetBSD 5.0 对调度器的接口进行了重新设计,现在有了实时调度扩展,并且线程是可抢占的了,i386和amd64平台已经支持抢占。要把这些说清楚就有点麻烦了,因为我自己也还没整明白,呵呵。
    先说个大概吧。
    关于调度器的接口,可以看src/sys/sys/sched.h中声明的函数,这些函数中有几个是src/sys/kern/kern_synch.c和src/sys/kern/sys_sched.c中实现的,这几个函数不是调度器接口,调度器接口是在前面这个头文件中声明,并在sched_4bsd.c和sched_m2.c中实现了的函数。调度器的主要任务是计算出下一个希望运行的是哪个线程,并告诉系统需不需要进行线程切换,如果需要,下一个是哪一个。调度器的功能还是很简单的,关键是调度的过程很复杂,我没怎么弄明白,主要是对x86的smp的工作原理不是很熟悉。
    我的理解是这样,时钟中断进来,调用hardclock(),在hardclock()中有两个变量我还没弄明白是干什么的,分别是stathz和schedhz。这是hardclock()中相关的代码:
        /*
         * If no separate statistics clock is available, run it from here.
         */
        if (stathz == 0)
                statclock(frame);
        /*
         * If no separate schedclock is provided, call it here
         * at about 16 Hz.
         */
        if (schedhz == 0) {
                if ((int)(--ci->ci_schedstate.spc_schedticks)                         schedclock(l);
                        ci->ci_schedstate.spc_schedticks = hardscheddiv;
                }
        }
        if ((--ci->ci_schedstate.spc_ticks)                 sched_tick(ci);

schedclock()和sched_tick()最终会走到调度器中去,然后计算下一个线程是谁,如果是同一cpu,则触发一个软中断,如果不是,就触发一个cpu间中断,在处理这个中断的时候切换线程上下文,中断返回的时候判断是否要切换进程上下文。
    to be continued
12-16 14:12