FreeBSDロックの分類と採用の指針

FreeBSDにおけるロックプリミティブは(FreeBSDに限らない話ではあるが)大きく分けると次の5つに分類できる。

  • mutex - 排他ロック
  • r/w lock(read/write lock) - 読み書き個別に排他するロック
  • rm lock(read mostly lock) - 読み込みの排他処理で性能が発揮される仕組みになっているr/w lock
  • waitchannels
  • semaphore

これをカテゴリに分類すると次の3つに分けられるという。

  • スピン(きわめて短いロック向き) - mutex
  • ブロック(短いロック向き) - mutex, r/w lock, rm lock
  • スリープ(長いロック向き) - s/x lock、lockmgr、condition variables、sleeping points、semaphore

通常使うのはブロックだ。特にmutexかr/w lockかどちらかが使われることになる。これらが適切ではないか適用できない場合にはほかのロックを使うことになる。ただしスリープロックを使う場合には注意が必要になる。スリープロック中にほかの特定のロックを組み合わせると問題が発生する。

これらロックを整理すると、だいたいは次の要領で採用するロックを決定すればいいという。

  • ブロックを基本的には採用する(mutex, r/w lock)
  • プロテクトパスがきわめて短い場合やブロックを適用できない場合にはスピンロックを使う
  • 複数のスリープにまたがってリソースコンシステンシを保つ必要がある場合はs/x lockを使う
  • 古いロック機構は使わない(lockmgr、sleeping points、semaphore)
  • ロックリカージョンは避ける

現在の実装には以前からあるものに関してはsemaphoreなど古いロック機構を使っているものがある。将来的にはこれらはほかの適切なロックに置き換え、古い機構そのものとともに削除すべきだと説明されている。

古い機構は削除してよりクリーンな状態へ

ロックの種類、その分類、採用すべきロックやその指針などは、FreeBSDカーネルに限らず参考になる内容だ。FreeBSDプロジェクトはカーネルからサブシステムに渡って、こうした地道なロック処理の改善を繰り替えして並列度の向上に努めている。同じくAsiaBSDCon 2009で発表したRafal Jaworowski氏もその取り組みの中で、FreeBSD 6よりも7の方がSMP性能がいいことを示しており、こうした取り組みが効果を発揮していることを示している。

将来のバージョンからはBKL、lockmgr, sleeping points, semaphoreなどのロック機構は完全に削除されることになるとみられる。代わりに使うのはmutexかr/w lockだ。またカーネル内部の開発ではithreadを活用するというのを覚えておきたい。