log.c void end_op(void)

トップページ
jupiteroak.hatenablog.com


log.c
https://github.com/mit-pdos/xv6-public/blob/master/log.c#L145

void end_op(void)
{
  int do_commit = 0;

  acquire(&log.lock);
  log.outstanding -= 1;
  if(log.committing)
    panic("log.committing");
  if(log.outstanding == 0){
    do_commit = 1;
    log.committing = 1;
  } else {
    // begin_op() may be waiting for log space,
    // and decrementing log.outstanding has decreased
    // the amount of reserved space.
    wakeup(&log);
  }
  release(&log.lock);

  if(do_commit){
    // call commit w/o holding locks, since not allowed
    // to sleep with locks.
    commit();
    acquire(&log.lock);
    log.committing = 0;
    wakeup(&log);
    release(&log.lock);
  }
}

end_op関数は、ロギングの終了処理を行います。


処理の内容

クリティカルセクションの入口を定める

acquire(&log.lock);

log構造体(ログに関する情報を記述したデータ構造)を排他制御するために、aquire関数を呼び出してロックを取得し、クリティカルセクションの入口とします。

トランザクション内で管理されているファイルシステム関連のシステムコールの数をディクリメントする

log.outstanding -= 1;

未完了であるファイルシステム関連のシステムコールのカウントを1つ減らします。

commit処理が実行準備中である場合はメッセージを出力する

 if(log.committing)
    panic("log.committing");

commit処理が実行準備中である場合は、panic関数を呼び出してメッセージを出力します。

トランザクション内で管理されているファイルシステム関連のシステムコールがない場合はコミット処理の実行準備をする

if(log.outstanding == 0){
    do_commit = 1;
    log.committing = 1;
  } else {

log.outstanding == 0 が真となる場合→未完了であるファイルシステム関連のシステムコールの数が0になった場合は、do_commit(commit処理を行うためのフラグ)とlog.committing(commit処理が実行準備中であることを示すフラグ)に1を設定します。

トランザクション内で管理されているファイルシステム関連のシステムコールが残っている場合はロギングを保留していたプロセスを実行可能状態にする

 } else {
    // begin_op() may be waiting for log space,
    // and decrementing log.outstanding has decreased
    // the amount of reserved space.
    wakeup(&log);
  }

log.outstanding == 0 が偽となる場合→未完了であるファイルシステム関連のシステムコールの数が0ではない場合は、wakeup関数を呼び出して、begin_op関数を呼び出して休止状態になっていたプロセス(begin_op関数を呼び出した時に、ログスペースに書き込むブロック数が多すぎるために休止状態になったプロセス)を実行可能状態(p->state = RUNNABLE)にします。

クリティカルセクションの出口を定める

release(&log.lock);

release関数を呼び出して取得していたロックを解放し、クリティカルセクションの出口とします。

コミット処理を行う

if(do_commit){
    ...


  }

do_commit(commit処理を行うためのフラグ)が1の時は、commit関数を呼び出してトランザクションを完了させます。

コミット関数を呼び出す

commit();

コミット関数を呼び出して、ロギングにおけるトランザクションの完了となるコミット処理を行います。

クリティカルセクションの入口を定める

 acquire(&log.lock);

log構造体(ログに関する情報を記述したデータ構造)を排他制御するために、acquire関数を呼び出してロックを取得し、クリティカルセクションの入口とします。

log.committingを0にする

log.committing = 0; 

commit関数の処理が終了したので、log.committing(commit処理が実行準備中であることを示すフラグ)に0を設定します。

ロギングを保留していたプロセスを実行可能状態にする

wakeup(&log);

wakeup関数を呼び出して、begin_op関数を呼び出して休止状態になっていたプロセス(begin_op関数を呼び出した時に、他のプロセスがcommit処理の実行準備中だったために休止状態になっていたプロセス)を、実行可能状態(p->state = RUNNABLE)にします。

クリティカルセクションの出口を定める

release(&log.lock);

release関数を呼び出して取得していたロックを解放し、クリティカルセクションの出口とします。