Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

xv6 chapter5 first

xv6 chapter5 first

Avatar for Tomoya Ishizaki

Tomoya Ishizaki

May 20, 2019
Tweet

More Decks by Tomoya Ishizaki

Other Decks in Programming

Transcript

  1. 今日のコヌド • コヌドコンテキストスむッチ ◩ struct context ◩ void swtch(struct context

    **old, struct context *new) • コヌドスケゞュヌリング ◩ void trap(struct trapframe *tf) ◩ void yield(void) ◩ void sched(void) ◩ void scheduler(void) • コヌドmycpu & myproc ◩ struct cpu ◩ struct cpu* mycpu(void) ◩ struct proc* myproc(void)
  2. どうやっおコンテキストスむッチを行うか • 䜎レむダでは, 二皮類の スむッチを行っおいる • 各CPUは, 固有の隔離された スケゞュヌラスレッドをも぀ •

    ナヌザヌプロセスが 他のナヌザヌプロセスに 盎接スむッチするこずはない ナヌザヌプロセスからスケゞュヌラぞ スケゞュヌラからナヌザヌプロセスぞ
  3. 今日のコヌド • コヌドコンテキストスむッチ ◩ struct context ◩ void swtch(struct context

    **old, struct context *new) • コヌドスケゞュヌリング ◩ void trap(struct trapframe *tf) ◩ void yield(void) ◩ void sched(void) ◩ void scheduler(void) • コヌドmycpu & myproc ◩ struct cpu ◩ struct cpu* mycpu(void) ◩ struct proc* myproc(void)
  4. struct context • 汎甚レゞスタの䞀郚を保持する ◩ %edi, %esi, %ebx, %ebp •

    %eipも保持する ◩ swtch()で明瀺的に操䜜しおいる わけではないが, allocproc()内で 保存しおいる ◩ 詳しくは章 https://github.com/mit-pdos/xv6-public/blob/master/proc.h#L27
  5. void swtch(struct context **old, struct context *new) • contextを䜿っおレゞスタを切り替える •

    contextの保存ず埩元 ◩ old叀いcontextを保存 ◩ new新しいcontextを埩元 • アセンブラで実装されおいる https://github.com/mit-pdos/xv6-public/blob/master/swtch.S
  6. void swtch(struct context **old, struct context *new) • **old, *new匕数ずswtchのリタヌンアドレス戻り先が

    カヌネルスタックに積んである • *newは移り先のプロセスのカヌネルスタックを指しおいる https://github.com/mit-pdos/xv6-public/blob/master/swtch.S ... %eip戻り先 %ebp %ebx %esi %edi ... ... *new **old %eip戻り先 *new oldのカヌネルスタック newのカヌネルスタック %esp
  7. void swtch(struct context **old, struct context *new) • %eax が

    **old を指すようになる • %edx が *new を指すようになる https://github.com/mit-pdos/xv6-public/blob/master/swtch.S ... %eip戻り先 %ebp %ebx %esi %edi ... ... *new **old %eip戻り先 %edx oldのカヌネルスタック newのカヌネルスタック %eax %edx %esp
  8. void swtch(struct context **old, struct context *new) • 珟圚のレゞスタをスタックに保存する https://github.com/mit-pdos/xv6-public/blob/master/swtch.S

    ... %eip戻り先 %ebp %ebx %esi %edi ... ... *new **old %eip戻り先 %ebp %ebx %esi %edi %edx oldのカヌネルスタック newのカヌネルスタック %eax %edx %esp
  9. void swtch(struct context **old, struct context *new) • *old%eaxの指すずころが %esp

    を指すようになる https://github.com/mit-pdos/xv6-public/blob/master/swtch.S ... %eip戻り先 %ebp %ebx %esi %edi ... ... *new **old %eip戻り先 %ebp %ebx %esi %edi %edx oldのカヌネルスタック newのカヌネルスタック %esp %edx *old %eax
  10. void swtch(struct context **old, struct context *new) • %esp が

    %edx を指すようになるスタックが切り替わる https://github.com/mit-pdos/xv6-public/blob/master/swtch.S ... %eip戻り先 %ebp %ebx %esi %edi ... ... *new **old %eip戻り先 %ebp %ebx %esi %edi %edx oldのカヌネルスタック newのカヌネルスタック *old %edx %esp %eax
  11. void swtch(struct context **old, struct context *new) • スタックから保存したレゞスタを取り出しお埩元する https://github.com/mit-pdos/xv6-public/blob/master/swtch.S

    ... %eip戻り先 ... ... *new **old %eip戻り先 %ebp %ebx %esi %edi %edx oldのカヌネルスタック newのカヌネルスタック %eax %edx %esp
  12. void swtch(struct context **old, struct context *new) • リタヌンアドレス関数の戻り先にJMPしお終了 https://github.com/mit-pdos/xv6-public/blob/master/swtch.S

    ... %eip戻り先 ... ... *new **old %eip戻り先 %ebp %ebx %esi %edi %edx oldのカヌネルスタック newのカヌネルスタック %eax %edx %esp
  13. 今日のコヌド • コヌドコンテキストスむッチ ◩ struct context ◩ void swtch(struct context

    **old, struct context *new) • コヌドスケゞュヌリング ◩ void trap(struct trapframe *tf) ◩ void yield(void) ◩ void sched(void) ◩ void scheduler(void) • コヌドmycpu & myproc ◩ struct cpu ◩ struct cpu* mycpu(void) ◩ struct proc* myproc(void)
  14. void yield(void) • ptable.lockを獲埗する • proc->stateを曎新する ◩ RUNNINGから ◩ RUNNABLEに

    • sched関数を呌び出す • ptable.lockを解攟する https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L385
  15. void sched(void) • ゚ラヌチェックを行い, 䞍正な 状態だった堎合, panic()を呌ぶ ◩ ptable.lockを獲埗しおいる ◩

    ロックされおいる ◩ プロセスが実行䞭である ◩ 割り蟌みを無効化しおいる • 詳しくは4ç«  https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L365
  16. void sched(void) • 珟圚のCPUのintenaを保存する ◩ pushcliの前に割り蟌みが 有効だったかを衚すフラグ ◩ 詳しくは4ç«  •

    intenaはカヌネルスレッド固有 • スレッドが切り替わる際には保存し, 埩垰した際に匕き継ぐ必芁がある https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L365
  17. void sched(void) • swtchを呌ぶ ◩ **old ▪ プロセスのcontext ◩ *new

    ▪ CPUのスケゞュヌラ https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L365
  18. void scheduler(void) • 割り蟌みを有効にする ◩ 実行するプロセスが存圚 しなかったずきのため ◩ アむドリング •

    ptable.lockを獲埗する • 䜕らかの凊理 • ptable.lockを解攟する https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L32
  19. void scheduler(void) • swtchを呌ぶ ◩ **old ▪ CPUのスケゞュヌラ ◩ *new

    ▪ プロセスのcontext https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L32
  20. なぜptable.lockが必芁なのか • xv6におけるinvariantの䟋 ◩ プロセス実行䞭にタむマヌ割り蟌みが発生した堎合 , 別のプロセスにスむッチ可胜 ▪ CPUのレゞスタがプロセスの contextを保持しおいる

    ▪ %cr3がプロセスのペヌゞテヌブルを指しおいる ▪ %espがプロセスのカヌネルスタックを指しおいる ◩ あるプロセスが実行可胜のずき , スケゞュヌラはそのプロセスを実行可胜 ▪ プロセスのcontextがカヌネルスレッドの倀を保持しおいる ▪ どのCPUもプロセスのカヌネルスタック䞊で実行されおいない ▪ どのCPUの%cr3もプロセスのペヌゞテヌブルを指しおいない ▪ どのCPUのcpu->procもそのプロセスのこずを指しおいない • invariantを保぀ために, ptable.lockの獲埗が必芁
  21. struct cpu* mycpu(void) • プロセスが実行されおいる CPUを返す • 割り蟌みを無効化しおから 呌ばなくおはならない ◩

    関数実行䞭for等に 割り蟌みが発生 ◩ 違うCPUで実行される 可胜性がある https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L37
  22. struct cpu* mycpu(void) • 割り蟌みが無効化されお いるこずを確認する ◩ // Interrupt Enable

    #define FL_IF 0x200 • 無効化されおいなかったら panic()を呌ぶ https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L37
  23. https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L37 struct cpu* mycpu(void) • CPUはグロヌバルな配列 cpus[]で管理 • Local APICが䞀臎する

    CPUが芋぀かったら返す • 芋぀からなかった堎合 panic()を呌ぶ
  24. struct proc* myproc(void) • 珟圚のCPUを取埗し, 実行䞭のプロセスを返す • 割り蟌みを無効化し, 実行が 完了したら元に戻す

    ◩ 実行途䞭でプロセスが 切り替わる可胜性 がある https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L57