Keywords: log, spinlock, Linux
お久しぶりな日記です. 色々な人のサポートのおかげでなんとか卒業論文の発表が終わりました. が, 卒業論文本体の提出期限はもうちょっと先で, また, ある程度なら修正してもよいそうなので, もうちょっと卒業論文の作業を続けるつもり...な最近です.
その卒業論文の一部で, スピンロックのログを解析するツールを実装したんですが, スピンロックのログ情報解析なんてマニアックなことらしく, あんまり実装方法に関する情報がネット上に載ってません. なので今日は, 卒論では関係ない話だったので詳細は省きましたが, 同じようなことをしたい人がいたときのため, このスピンロックのログ解析ツールの実装方針について書きます(*1).
*1:
研究室の同期がパッチを投げてるので, 詳細な改変箇所を知りたい方は以下のURLから追っていって下さい.
[環境]
Linux Version & 26.1.6
CPUアーキテクチャ & SH4A
[実装方針]
1. ログ情報を記録する変数を宣言
include/linux/spinlock.hを開き, spinlock_t構造体の中にあるraw_lockspin_t構造体を変更して, ログ情報取得用の変数を追加します. spinlock_t構造体の中に直接変数を追加すると, 理由は分からないけれど, 挙動が不安定になるので(e.g. Segmentation Fault), raw_spinlock_tを改変しました.
2. スピンロック取得時にサイクル数を記録
kernel/spinlock.cのロック取得 & 解放関数を弄ります. 例えばspinlockの取得から解放までの時間したい場合, 以下の部分のlock取得時(*2)にサイクル数を取得する関数(*3)を呼びだし, 取得したサイクル数を1.で宣言した変数に書き込みます.
- lock try
- lock irq
- lock bh
- lock spin
- lock trybh
3. スピンロック解放時にログ情報を収集
2.と同様の方法で, ロックの解放関数を弄ります. 具体的には, 以下の部分を弄ります(*2).
- unlock irq
- unlock irqrestore
- unlock spin
- unlock bh
ロックの解放時に, spinlock_t *lockからrawlock_tの宣言した変数にアクセスし, ロック取得時の時間を取得します. その後, 例えばロック保持時間を知りたい場合, 現在の時間との差分を取って, 任意のログ情報収集用のデータ構造体に代入します.
4. ログ情報の出力方法
最後は, 取得したスピンロックのログ情報を出力する方法についてです. 色々な出力方法があると思いますが, 僕の場合は, Debug Filesystemを使いました. 理由は, spinlockの初期化を任意のタイミングで行いたかったからです. つまり, Debug Filesystemを読み込み, 全てのログ出力処理が終わった後に, ログ情報の初期化処理を行うようにさせました. なお, Debug Filesystemの使い方は, ネット上にサンプルプログラムがいくつかあると思うので, それらを参考にしてください.
以上です.
*2 改変を加える関数は, Linuxのバージョンに依存します. 2.6.16以外では, スピンロックの機構が大きく異なる可能性があるので, どのロック取得時/解放関数を弄るか再考が必要です.
*3 スピンロックの保持時間の単位はサイクル数[2^n]です[1]. したがって, xtimeやjiffies, gettimeofdayでは粒度が粗く, 正確な時間を計測できません. また, サイクル数を取得する方法はハードウェア依存の部分です. 僕の場合, CPUアーキテクチャがSHなので, arch/sh/kernel/timers/timer-tmu.cを参考にしてTMU(*4)のレジスタにアクセスし, サイクル数を計測しました.
*4 SuperHプロセッサの32ビットタイマユニット
[参考文献]
[1] F. Thomas and B. Sebastian, How to Deal With Lock Holder Preemption, Advanced Micro Devices Operating System Research Center, 2008
# やっぱしこのメモ, 卒論のAppendixにでも書こうかな...