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関数は、ロギングの終了処理を行います。
処理の内容
- クリティカルセクションの入口を定める
- トランザクション内で管理されているファイルシステム関連のシステムコールの数をディクリメントする
- commit処理が実行準備中である場合はメッセージを出力する
- トランザクション内で管理されているファイルシステム関連のシステムコールがない場合はコミット処理の実行準備をする
- トランザクション内で管理されているファイルシステム関連のシステムコールが残っている場合はロギングを保留していたプロセスを実行可能状態にする
- クリティカルセクションの出口を定める
- コミット処理を行う
クリティカルセクションの入口を定める
acquire(&log.lock);
log構造体(ログに関する情報を記述したデータ構造)を排他制御するために、aquire関数を呼び出してロックを取得し、クリティカルセクションの入口とします。
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)にします。
コミット処理を行う
if(do_commit){ ... }
do_commit(commit処理を行うためのフラグ)が1の時は、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)にします。