FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

GDBとISSを利用しながらプロセスがSwitchされる挙動を追い掛けていく

プロセスが開始される前に、xv6ではinitlog()が起動し、ログをディスクに書き込むための準備が行われる。

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

f:id:msyksphinz:20160209020231p:plain

  • proc.c
  if (first) {
    // Some initialization functions must be run in the context
    // of a regular process (e.g., they call sleep), and thus cannot
    // be run from main().
    first = 0;
    initlog();
  }

ディスクへのアクセスは通常時間がかかるため、ここでsleep()が呼び出され、プロセスの切り替えが行われる。

  // Wait for request to finish.
  while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){
    sleep(b, &idelock);
  }

sleep()は、次に実行されるべきプロセスを選択して、自分自身からコンテキストを切り替える関数だ。

// Atomically release lock and sleep on chan.
// Reacquires lock when awakened.
void
sleep(void *chan, struct spinlock *lk)
{
...
  // Go to sleep.
  proc->chan = chan;
  proc->state = SLEEPING;
  sched();

procには現在のプロセスのポインタが入っているのか?現在の状態を保存した後、sched()を呼び出してプロセス切り替えに入る。

  • proc.c
  swtch(&proc->context, cpu->scheduler);

sched()はさらにswtchを呼び出し、現在のプロセスのコンテキストを変更する。

swtchを呼び出したときに、cpu->scheduler()、つまりfinalizeforkを呼び出している。さらにtrapretを呼び出している。

  • trapasm.S
  lw $t0, 132($sp)
  lw $t1, 136($sp)
  lw $t2, 144($sp)
  mtc0 $t0, $COP0_EPC
  mtc0 $t1, $COP0_ERROREPC
  mtc0 $t2, $COP0_STATUS
...

  lw $sp, 112($sp)

  eret
  .set pop