SlideShare une entreprise Scribd logo
1  sur  22
Télécharger pour lire hors ligne
オペ―レーティングシステムの読み書き#2
                 2011/10/3
            Nagoya geekbar
9 Hardware Interrupts and Traps
   Trap 前回のまとめ
     命令の実行に失敗した場合の「わな」仕掛ける
     システムコールの呼び出しは特殊な「わな」
     「わな」はCPUの処理過程で発生する
   Interrupt
     CPUの処理に関係なく、外部からの「割り込み」
     主に、処理の完了時に「割り込み」
     テレタイプ、紙テープ、ラインプリンタ、磁気
     ディスク、時計
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
Teletype ?
Paper tape ?
Clocks – line and programmable
   Line Clock
     電源の周期から生成
     AC>降圧(トランス)>整流(ダイオード)>コンデンサ
     電源周波数のパルスを取り出せる
     50HZで20ms間隔
     昔の電気式デジタル時計はパルスxHZで1秒を生成
 Programmable   clock
     指定の間隔でパルスを発生
 PDP-11ではどちらかが必要
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
Clock
   外部にあるclockから毎秒50個のパルスがCPUに
    入る
   1パルス毎に割り込みベクタの処理を実行


    Clock

                    CPU
kwlp low.s
0568:
0569: .globl _clock
0570: kwlp: jsr r0,call; _clock

Cで書かれたclock()を呼ぶ
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--;
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--;
謎の変数
 u.u_time
 u.u_stime
 pp->p_time
 lbolt
 time[2]
 tout[2]
Callout 構造
struct callo
{
   int c_time;        /* ticks between events */
   int c_arg;         /* function argument */
   int (*c_func)();   /* function pointer */
} callout[NCALL];
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はこの後処
                                                     理される
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:   }
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個づつ
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で待ってるプロセ
                                     スを起こす


        今回はさらりと流す
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:   }
謎の変数 回答
 u.u_time     USER時間
 u.u_stime    SYSTEM時間
 pp->p_time   プロセス起動からの時間
 lbolt        毎秒60回++
 time[2]      1970年からの秒
 tout[2]      sleep(2)が起きる時間
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.
なぞは深まるばかり

次回は
user構造
proc構造
setpri
wakeup
おわり

Contenu connexe

Plus de magoroku Yamamoto (20)

Adk2012
Adk2012Adk2012
Adk2012
 
Android binder-ipc
Android binder-ipcAndroid binder-ipc
Android binder-ipc
 
V6 unix in okinawa
V6 unix in okinawaV6 unix in okinawa
V6 unix in okinawa
 
ぐだ生システム#2
ぐだ生システム#2ぐだ生システム#2
ぐだ生システム#2
 
ぐだ生って何
ぐだ生って何ぐだ生って何
ぐだ生って何
 
Android builders summit slide tour
Android builders summit slide tourAndroid builders summit slide tour
Android builders summit slide tour
 
第4回名古屋Android勉強会資料
第4回名古屋Android勉強会資料第4回名古屋Android勉強会資料
第4回名古屋Android勉強会資料
 
Poorman’s adk トレーナ
Poorman’s adk トレーナPoorman’s adk トレーナ
Poorman’s adk トレーナ
 
20分でわかった事にするパワーマネジメント
20分でわかった事にするパワーマネジメント20分でわかった事にするパワーマネジメント
20分でわかった事にするパワーマネジメント
 
Poormans sdk
Poormans sdkPoormans sdk
Poormans sdk
 
Ngk2011 b
Ngk2011 bNgk2011 b
Ngk2011 b
 
オレオレ家電
オレオレ家電オレオレ家電
オレオレ家電
 
V6read#4
V6read#4V6read#4
V6read#4
 
V6read#3
V6read#3V6read#3
V6read#3
 
Unixファイルシステムの歴史
Unixファイルシステムの歴史Unixファイルシステムの歴史
Unixファイルシステムの歴史
 
Pdp11 on-fpga
Pdp11 on-fpgaPdp11 on-fpga
Pdp11 on-fpga
 
ぐだ生システム再構成4
ぐだ生システム再構成4ぐだ生システム再構成4
ぐだ生システム再構成4
 
20分で理解する仮想記憶
20分で理解する仮想記憶20分で理解する仮想記憶
20分で理解する仮想記憶
 
Android のusb support
Android のusb supportAndroid のusb support
Android のusb support
 
Os真髄
Os真髄Os真髄
Os真髄
 

Dernier

[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 

Dernier (10)

[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 

V6read#2

  • 2. 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
  • 9. kwlp low.s 0568: 0569: .globl _clock 0570: kwlp: jsr r0,call; _clock Cで書かれたclock()を呼ぶ
  • 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--;
  • 12. 謎の変数  u.u_time  u.u_stime  pp->p_time  lbolt  time[2]  tout[2]
  • 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.