log.c void begin_op(void)
トップページ
jupiteroak.hatenablog.com
log.c
https://github.com/mit-pdos/xv6-public/blob/master/log.c#L125
void begin_op(void) { acquire(&log.lock); while(1){ if(log.committing){ sleep(&log, &log.lock); } else if(log.lh.n + (log.outstanding+1)*MAXOPBLOCKS > LOGSIZE){ // this op might exhaust log space; wait for commit. sleep(&log, &log.lock); } else { log.outstanding += 1; release(&log.lock); break; } } }
begin_op関数は、ロギングの開始処理を行います。
処理の内容
クリティカルセクションの入口を定める
acquire(&log.lock);
log構造体(ログに関する情報を記述したデータ構造)を排他制御するために、acquire関数を呼び出してロックを取得し、クリティカルセクションの入口とします。
ロギングの状態に応じてロギングの開始・保留を判断する
while(1){ ... }
commit処理が実行準備中である場合
if(log.committing){ sleep(&log, &log.lock);
他のプロセスにおいてcommit処理が実行準備中である場合は、sleep関数を呼び出してプログラムの制御を別のプロセスに移します。
ログスペースに書き込むブロック数が多すぎる場合
} else if(log.lh.n + (log.outstanding+1)*MAXOPBLOCKS > LOGSIZE){ // this op might exhaust log space; wait for commit. sleep(&log, &log.lock);
トランザクションにおいて、ログスペースに書き込むブロック数の見積もりを行なっています。
現在トランザクションで管理中のブロック数(log.lh.n) + 未完了であるファイルシステム関連のシステムコールの数×MAXOPBLOCKSのブロック数が、ログスペースに保存することができるブロック数(LOGSIZE)を越える場合は、ログスペースを越える可能性があると判断し、sleep関数を呼び出して、プログラムの制御を別のプロセスに移します。
クリティカルセクションの出口を定める(上記2つ以外の場合)
} else { log.outstanding += 1; release(&log.lock); break;
上記2つ以外の場合は、未完了であるファイルシステム関連のシステムコールのカウントをインクリメントします。その後、取得したロックを解放してから、ループを脱出します。