Contenu connexe Plus de magoroku Yamamoto Plus de magoroku Yamamoto (20) V6read#22. 9 Hardware Interrupts and Traps
Trap 前回のまとめ
命令の実行に失敗した場合の「わな」仕掛ける
システムコールの呼び出しは特殊な「わな」
「わな」はCPUの処理過程で発生する
Interrupt
CPUの処理に関係なく、外部からの「割り込み」
主に、処理の完了時に「割り込み」
テレタイプ、紙テープ、ラインプリンタ、磁気
ディスク、時計
3. 9.2 The Interrupt Vector
Vector
device priority
Location
060 Teletype input 4
064 Teletype output 4
070 Paper tape input 4
074 Paper tape output 4
100 Line clock 6
104 Programmable clock 6
200 Line printer 4
220 RK disk driver 5
6. Clocks – line and programmable
Line Clock
電源の周期から生成
AC>降圧(トランス)>整流(ダイオード)>コンデンサ
電源周波数のパルスを取り出せる
50HZで20ms間隔
昔の電気式デジタル時計はパルスxHZで1秒を生成
Programmable clock
指定の間隔でパルスを発生
PDP-11ではどちらかが必要
7. low.s
0525: . = 60^. Vector device entry
0526: klin; br4
0527: klou; br4 060 Teletype input klin
0528:
0529: . = 70^. 064 Teletype output klou
0530: pcin; br4
0531: pcou; br4
070 Paper tape input pcin
0532: 074 Paper tape output pcou
0533: . = 100^.
0534: kwlp; br6 100 Line clock kwlp
0535: kwlp; br6
0539:
104 Programmable clock kwlp
0540: . = 200^.
0541: lpou; br4 200 Line printer lpou
0542:
0543: . = 220^. 220 RK disk driver rkio
0544: rkio; br5
8. Clock
外部にあるclockから毎秒50個のパルスがCPUに
入る
1パルス毎に割り込みベクタの処理を実行
Clock
CPU
10. clock
3725: clock(dev, sp, r1, nps, r0, pc, ps) 3761: 3797: if(++lbolt >= HZ) {
3726: { 3762: /* 3798: if((ps&0340) != 0)
3727: register struct callo *p1, *p2; 3763: * callout 3799: return;
3728: register struct proc *pp; 3764: */ 3800: lbolt =- HZ;
3729: 3765: 3801: if(++time[1] == 0)
3730: /* 3766: spl5(); 3802: ++time[0];
3731: * restart clock 3767: if(callout[0].c_time <= 0) { 3803: spl1();
3732: */ 3768: p1 = &callout[0]; 3804: if(time[1]==tout[1] && time[0]==tout[0])
3733: 3769: while(p1->c_func != 0 && p1->c_time <= 0) { 3805: wakeup(tout);
3734: *lks = 0115; 3770: (*p1->c_func)(p1->c_arg); 3806: if((time[1]&03) == 0) {
3735: 3771: p1++; 3807: runrun++;
3736: /* 3772: } 3808: wakeup(&lbolt);
3737: * display register 3773: p2 = &callout[0]; 3809: }
3738: */ 3774: while(p2->c_func = p1->c_func) { 3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
3739: 3775: p2->c_time = p1->c_time; 3811: if (pp->p_stat) {
3740: display(); 3776: p2->c_arg = p1->c_arg; 3812: if(pp->p_time != 127)
3741: 3777: p1++; 3813: pp->p_time++;
3742: /* 3778: p2++; 3814: if((pp->p_cpu & 0377) > SCHMAG)
3743: * callouts 3779: } 3815: pp->p_cpu =- SCHMAG; else
3744: * if none, just return 3780: } 3816: pp->p_cpu = 0;
3745: * else update first non-zero time 3781: 3817: if(pp->p_pri > PUSER)
3746: */ 3782: /* 3818: setpri(pp);
3747: 3783: * lightning bolt time-out 3819: }
3748: if(callout[0].c_func == 0) 3784: * and time of day 3820: if(runin!=0) {
3749: goto out; 3785: */ 3821: runin = 0;
3750: p2 = &callout[0]; 3786: 3822: wakeup(&runin);
3751: while(p2->c_time<=0 && p2->c_func!=0) 3787: out: 3823: }
3752: p2++; 3788: if((ps&UMODE) == UMODE) { 3824: if((ps&UMODE) == UMODE) {
3753: p2->c_time--; 3789: u.u_utime++; 3825: u.u_ar0 = &r0;
3754: 3790: if(u.u_prof[3]) 3826: if(issig())
3755: /* 3791: incupc(pc, u.u_prof); 3827: psig();
3756: * if ps is high, just return 3792: } else 3828: setpri(u.u_procp);
3757: */ 3793: u.u_stime++; 3829: }
3758: 3794: pp = u.u_procp; 3830: }
3759: if((ps&0340) != 0) 3795: if(++pp->p_cpu == 0) 3831: }
3760: goto out; 3796: pp->p_cpu--;
11. clock
3725: clock(dev, sp, r1, nps, r0, pc, ps) 3761: 3797: if(++lbolt >= HZ) {
3726: { 3762: /* 3798: if((ps&0340) != 0)
3727: register struct callo *p1, *p2; 3763: * callout 3799: return;
3728: register struct proc *pp; 3764: */ 3800: lbolt =- HZ;
3729: 3765: 3801: if(++time[1] == 0)
3730: /* 3766: spl5(); 3802: ++time[0];
3731: * restart clock 3767: if(callout[0].c_time <= 0) { 3803: spl1();
3732: */ 3768: p1 = &callout[0]; 3804: if(time[1]==tout[1] && time[0]==tout[0])
3733: 3769: while(p1->c_func != 0 && p1->c_time <= 0) { 3805: wakeup(tout);
3734: *lks = 0115; 3770: (*p1->c_func)(p1->c_arg); 3806: if((time[1]&03) == 0) {
3735: 3771: p1++; 3807: runrun++;
Callout
3736: /* 3772: } 3808: wakeup(&lbolt);
3737: * display register 3773: p2 = &callout[0]; 3809: }
3738: */ 3774: while(p2->c_func = p1->c_func) { 3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
3739: 3775: p2->c_time = p1->c_time; 3811: if (pp->p_stat) {
Sched
3740: display(); 3776: p2->c_arg = p1->c_arg; 3812: if(pp->p_time != 127)
3741: 3777: p1++; 3813: pp->p_time++;
3742: /* 3778: p2++; 3814: if((pp->p_cpu & 0377) > SCHMAG)
3743: * callouts 3779: } 3815: pp->p_cpu =- SCHMAG; else
3744: * if none, just return 3780: } 3816: pp->p_cpu = 0;
3745: * else update first non-zero time 3781: 3817: if(pp->p_pri > PUSER)
の入り口
3746: */ 3782: /* 3818: setpri(pp);
3747: 3783: * lightning bolt time-out 3819: }
3748: if(callout[0].c_func == 0) 3784: * and time of day 3820: if(runin!=0) {
3749: goto out; 3785: */ 3821: runin = 0;
3750: p2 = &callout[0]; 3786: 3822: wakeup(&runin);
Acct
3751: while(p2->c_time<=0 && p2->c_func!=0) 3787: out: 3823: }
3752: p2++; 3788: if((ps&UMODE) == UMODE) { 3824: if((ps&UMODE) == UMODE) {
3753: p2->c_time--; 3789: u.u_utime++; 3825: u.u_ar0 = &r0;
3754: 3790: if(u.u_prof[3]) 3826: if(issig())
3755: /* 3791: incupc(pc, u.u_prof); 3827: psig();
3756: * if ps is high, just return 3792: } else 3828: setpri(u.u_procp);
3757: */ 3793: u.u_stime++; 3829: }
3758: 3794: pp = u.u_procp; 3830: }
3759: if((ps&0340) != 0) 3795: if(++pp->p_cpu == 0) 3831: }
3760: goto out; 3796: pp->p_cpu--;
13. Callout 構造
struct callo
{
int c_time; /* ticks between events */
int c_arg; /* function argument */
int (*c_func)(); /* function pointer */
} callout[NCALL];
14. clock callout (1/2)
先頭のcalloutが未
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++; 最初にc_timeが0
3753: p2->c_time--; より大きいCallout
3758: を見つけて、
3759: if((ps&0340) != 0)
c_timeを-1
3760: goto out;
ここより前の
3761:
calloutはこの後処
理される
15. clock callout (2/2) 先頭に登録時間が
過ぎているcallout
3766: spl5(); が存在したら、
3767: if(callout[0].c_time <= 0) {
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; Callout配列を詰め
3776: p2->c_arg = p1->c_arg; る
3777: p1++;
3778: p2++;
3779: }
3780: }
16. clock acct
USERモードから
3787: out: 割り込まれたら、
3788: if((ps&UMODE) == UMODE) { uのuser時間
3789: u.u_utime++; u_utimeを+1
3790: if(u.u_prof[3])
3791: incupc(pc, u.u_prof); KERNELモードか
3792: } else ら割り込まれたら、
3793: u.u_stime++; uのsystem時間
u_stimeを+1
3794: pp = u.u_procp;
3795: if(++pp->p_cpu == 0) Procのp_cpuを加
3796: pp->p_cpu--; 算。オーバフロー
しないように調整
ppはproc構造のポインタ、uはuser構造。共
にプロセスの管理構造1プロセスに1個づつ
17. clock schedの入り口(1/2)
clockが呼ばれると、ここまでは必
3797: if(++lbolt >= HZ) {
ず実行。lboltを+1して、HZ(50)を
3798: if((ps&0340) != 0)
3799: return;
超過したら、すなわち1秒経過し
3800: lbolt =- HZ;
たら、
3801: if(++time[1] == 0)
3802: ++time[0]; lboltをリセット
3803: spl1();
3804: if(time[1]==tout[1] && time[0]==tout[0])
3805: wakeup(tout);
3806: if((time[1]&03) == 0) {
寝ているプロセスを起こす
3807: runrun++;
3808: wakeup(&lbolt);
3809: } 4秒ごとにlboltで待ってるプロセ
スを起こす
今回はさらりと流す
18. Clock schedの入り口(2/2)
3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++) プロセスの管理構造の配
3811: if (pp->p_stat) {
列をスキャン
3812: if(pp->p_time != 127)
3813: pp->p_time++;
3814: if((pp->p_cpu & 0377) > SCHMAG) p_statに値が入っている=プロ
3815: pp->p_cpu =- SCHMAG; else セスが存在したら、p_timeを
3816: pp->p_cpu = 0; +1
3817: if(pp->p_pri > PUSER)
3818: setpri(pp);
3819: }
3820: if(runin!=0) {
3821: runin = 0;
3822: wakeup(&runin);
runinが真なら、runinで待って
3823: } るプロセスをwakeup
3824: if((ps&UMODE) == UMODE) {
3825: u.u_ar0 = &r0;
3826: if(issig())
3827: psig();
3828: setpri(u.u_procp);
3829: }
3830: }
19. 謎の変数 回答
u.u_time USER時間
u.u_stime SYSTEM時間
pp->p_time プロセス起動からの時間
lbolt 毎秒60回++
time[2] 1970年からの秒
tout[2] sleep(2)が起きる時間
20. Unix のPPDA (PerProcDataArea)
User構造体 user.h
The user structure. One allocated per process.
Contains all per process data that doesn't need
to be referenced while the process is swapped.
Proc構造体 proc.h
One structure allocated per active process. It
contains all data needed about the process while
the process may be swapped out. Other per
process data (user.h) is swapped with the
process.