#詳細Linuxカーネル 5章 同期処理を読む
詳細Linuxカーネル 5章 同期処理を読む
Linuxではマルチプロセッサでの割込み・システムコール・例外発生時に、
同じ変数・メモリへのアクセスを適切に同期(順序付け)が必要になる。
5章ではそのためにの同期処理方法を説明している。
今回は、カーネルが使用している同期技法のスピンロックを読む。
スピンロック
スピンロックによる同期の実現は以下の
カーネルは共有しているデータへのアクセス時に資源確保しロックする。
アクセスが終わった時点でロックを解除する。
すでにロックされた状態だと、そのカーネルはロックが解除するまでループして待つ。
スピンロックでは、ロック開放の待ち時間はCPUを消費し続けるので、
無駄に見えるがカーネル資源の多くはロック時間が短いため問題ない。
スピンロックによるデットロックの対策は何かされているのか?
スピンロックの構造体 spinlock_t
スピンロックはspinlock_t
構造体で実現。
構造体の中身はraw_spinlock
構造体とデバッグ用の何か。
slock
:スピンロック状態を示す。1がロック開放状態。break_lock
:ロックによって待っているプロセスがいることを示す。
スピンロックの確保 spin_lock()
スピンロックを確保するための関数 spin_lock()
は、
spinlock_t
構造体のアドレスを引数にとる。
Spin_lock()
は raw_spin_lock()
->_raw_spin_lock()
ー>__raw_spin_lock()
-の順にコール/マクロ化され、実体は__raw_spin_lock
になる。
static inline void __raw_spin_lock(raw_spinlock_t *lock) { preempt_disable(); spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); }
preempt_disable()
をコール
カーネル内のプリエンプションを禁止(5.1章に書いているから後で読む)spin_acuore()
をコール
デバック用の関数っぽい。あとでみるLOCK_CONTENDED
のマクロを実行do_raw_spin_trylock
でスピンロックが取れているか確認。
実体はarch_spin_trylock
。ここでなにかしてるっぽい。
ここまでにするのか・・・
#define LOCK_CONTENDED(_lock, try, lock) \ do { \ if (!try(_lock)) { \ lock_contended(&(_lock)->dep_map, _RET_IP_); \ lock(_lock); \ } \ lock_acquired(&(_lock)->dep_map, _RET_IP_); \ } while (0)