code:clock - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki
3708
3709 /*
3710 * clock is called straight from
3711 * the real time clock interrupt.
3712 *
3713 * Functions:
3714 * reprime clock
3715 * copy *switches to display
3716 * implement callouts
3717 * maintain user/system times
3718 * maintain date
3719 * profile
3720 * tout wakeup (sys sleep)
3721 * lightning bolt wakeup (every 4 sec)
3722 * alarm clock signals
3723 * jab the scheduler
3724 */
3725 clock(dev, sp, r1, nps, r0, pc, ps)
总体思想3726 {将统计/计数的工作留给 不重要的时候 再做 而不是严格的按照时间来做
- 将 整体处理 划分为几部分,划分标准
- 处理机优先级是否为0 (是否有更重要的任务需要完成)
- 先前态是否为用户态 (核心态运行时,时钟中断尽可能不占用时间)
- 时钟中断尽可能节省时间
3727 register struct callo *p1, *p2;
3728 register struct proc *pp;
3729
3730 /*
3731 * restart clock
3732 */
3733
3734 *lks = 0115;
3735
3736 /*
3737 * display register
3738 */
3739
3740 display();
3741
3742 /*
- "显示"函数在pdp11/40中无实现
3743 * callouts
3744 * if done, just return
3745 * else update first non-zero time
3746 */
callout总体说明3747
3748 if(callout[0].c_func == 0)
3749 goto out;
3750 p2 = &callout[0];
- 若callout为空,则跳过callout处理过程
3751 while(p2->c_time<=0 && p2->c_func!=0)
3752 p2++;
3753 p2->c_time--;
3754
3755 /*
- callout中第一个未到期的事件 的 剩余时间-1
3756 * if ps is high, just return
3757 */
3758
3759 if((ps&0340) != 0)
3760 goto out;
3761
3762 /*
3763 * callout
3764 */
3765
3766 spl5();
3767 if(callout[0].c_time <= 0) {
- 处理机优先级 置 5
- 避免插入不必要的中断,使得整个时钟处理时间延长
3768 p1 = &callout[0];
3769 while(p1->c_func != 0 && p1->c_time <= 0) {
3770 (*p1->c_func)(p1->c_arg);
3771 p1++;
3772 }
3773 p2 = &callout[0];
3774 while(p2->c_func = p1->c_func) {
3775 p2->c_time = p1->c_time;
3776 p2->c_arg = p1->c_arg;
3777 p1++;
3778 p2++;
3779 }
3780 }
3781
- 处理callout中所有到期事件,并从callout中移除到期事件
3782 /*
3783 * lightning bolt time-out
3784 * and time of day
3785 */
3786
3787 out:
3788 if((ps&UMODE) == UMODE) {
3789 u.u_utime++;
3790 if(u.u_prof[3])
3792 } else
3793 u.u_stime++;
3794 pp = u.u_procp;
3795 if(++pp->p_cpu == 0)
3796 pp->p_cpu--;
3797 if(++lbolt >= HZ) {
- 当前进程 CPU使用度+1
- 若越界,则 不进行+1
3798 if((ps&0340) != 0)
- 若 时钟滴答数 积攒到 整秒,进行整秒处理
3799 return;
3800 lbolt =- HZ;
- 若 处理机优先级 不为0,则直接返回
- 这样跳过整秒处理,为了节省执行时间
3801 if(++time[1] == 0)
3802 ++time[0];
3803 spl1();
- 修正 系统时间
3804 if(time[1]==tout[1] && time[0]==tout[0])
3805 wakeup(tout);
3806 if((time[1]&03) == 0) {
- 处理 因tout睡眠 且 到期的进程,参看睡眠原因#tout
3807 runrun++;
3808 wakeup(&lbolt);
3809 }
3810 for(pp = &proc[0]; pp < &proc[NPROC]; pp++)(需要等待较长时间才进行的事务处理,一般用于与外设同步,如在pc-11驱动函数pcopen中使用)
- 每4秒
- 置runrun,强制进行进程调度
- 唤醒因lbolt睡眠的进程,睡眠原因 :lbolt
3811 if (pp->p_stat) {
3812 if(pp->p_time != 127)
- 遍历proc数组,对于使用的proc,做如下操作
- p_time++,但最大值为127
- p_cpu-10,但最小值为0,参看进程调度#优先数计算
- 优先数>PUSER,则重新计算优先数,参看进程调度#优先数计算
3813 pp->p_time++;
3814 if((pp->p_cpu & 0377) > SCHMAG)
3815 pp->p_cpu =- SCHMAG; else
3816 pp->p_cpu = 0;
3817 if(pp->p_pri > PUSER)
3818 setpri(pp);
3819 }
3820 if(runin!=0) {
3821 runin = 0;
3822 wakeup(&runin);
3823 }
3824 if((ps&UMODE) == UMODE) {
- 唤醒 等待图像调入内存的进程
- 调度决策频率 1次/秒
3825 u.u_ar0 = &r0;
3826 if(issig())
3827 psig();
3829 }
3830 }
3831 }
3832 /* ------------------------- */