EN JA
RMLOCK(9)
RMLOCK(9) FreeBSD Kernel Developer's Manual RMLOCK(9)

名称

rmlock, rm_init, rm_init_flags, rm_destroy, rm_rlock, rm_try_rlock, rm_wlock, rm_runlock, rm_wunlock, rm_wowned, rm_sleep, rm_assert, RM_SYSINITほとんどの読み込みアクセスパターンのために最適化されたカーネル読み込み側/書き込み側 (reader/writer) ロック

書式

#include < sys/param.h>
#include < sys/lock.h>
#include < sys/rmlock.h>

void
rm_init( struct rmlock *rm, const char *name);

void
rm_init_flags( struct rmlock *rm, const char *name, int opts);

void
rm_destroy( struct rmlock *rm);

void
rm_rlock( struct rmlock *rm, struct rm_priotracker* tracker);

int
rm_try_rlock( struct rmlock *rm, struct rm_priotracker* tracker);

void
rm_wlock( struct rmlock *rm);

void
rm_runlock( struct rmlock *rm, struct rm_priotracker* tracker);

void
rm_wunlock( struct rmlock *rm);

int
rm_wowned( const struct rmlock *rm);

int
rm_sleep( void *wchan, struct rmlock *rm, int priority, const char *wmesg, int timo);


options INVARIANTS
options INVARIANT_SUPPORT
void
rm_assert( struct rmlock *rm, int what);

#include < sys/kernel.h>

RM_SYSINIT( name, struct rmlock *rm, const char *desc, int opts);

解説

ほとんどの読み込みロックによって、複数のスレッドによって保護されたデータへの共有アクセスができるか、または単一のスレッドによって排他的なアクセスができます。共有アクセスがあるスレッドは、それらが保護されたデータを読み込めるだけであるので、 reader として知られています。排他的なアクセスがあるスレッドは、保護されたデータを変更することができるので、 writer として知られています。

ほとんどの読み込みロックは、読み込み側ロックとして使用されるほとんどの排他的ロックのために効率的になるように設計されていて、そのようなものとして、めったに変化しないデータを保護するために使用されるべきです。共用アクセスのためにロックされた後に排他的なロックを獲得することは、高価な操作です。

通常、ほとんどの読み込みロックは、 rwlock(9) ロックに似ていて、 rwlock(9) ロックとして同じロック順序規則に従います。ほとんどの読み込みロックには、ミューテックス (mutex) のような十分な優先権伝播があります。 rwlock(9) と異なり、ほとんどの読み込みロックは、読み込み側と書き込み側の両方に優先権を伝播します。これは、 rm_rlock() と rm_runlock() に供給される rm_priotracker 構造体の引数によって実装されます。読み込み側は、ロックが RM_RECURSE オプションで初期化されるなら、繰り返すことができます。しかしながら、書き込み側は、決して繰り返すことはできません。

スリープ可能なほとんどの読み込みロックは、 rm_init_flags(). に RM_SLEEPABLE を渡すことによって作成されます。通常のほんどの読み込みロックと異なり、スリープ可能なほとんどの読み込みロックは、 sx(9) ロックとして同じロックの順序規則に従います。スリープ可能なほとんどの読み込みロックは、書き込み側に優先権を伝播しませんが、それらは、読み込み側に優先権を伝播します。書き込み側は、ほとんどの読み込みロックを保持する間にスリープすることが許されますが、読み込み側は、そうではありません。 sx(9) ロックのような、他のスリープ可能なロックと異なり、読み込み側は、スリープを回避するために他のスリープ可能なロックで試みの操作を使用しなければなりません。

マクロと関数

rm_init( struct rmlock *rm, const char *name)
ほとんどの読み込みロック rm 初期化します。 name 記述は、単にデバッグ目的のために使用されます。この関数は、ロックにおいて任意の他の操作の前に呼び出されなければなりません。
rm_init_flags( struct rmlock *rm, const char *name, int opts)
rm_init() に似て、1 組のオプションのフラグを付けて、ほとんどの読み込みロック rm を初期化します。 opts 引数は、次の 1 つ以上のフラグを含んでいます:
RM_NOWITNESS
このロックを無視するよう witness(4) に指示します。
RM_RECURSE
スレッドは、 rm のための共有ロックを再帰的に獲得することができます。
RM_SLEEPABLE
スリープ可能なほとんどの読み込みロックを作成します。
rm_rlock( struct rmlock *rm, struct rm_priotracker* tracker)
優先権の伝播のためのロックの読み込み所有者を追跡するために tracker を使用して、読み込み側 (reader) として rm をロックします。このデータ構造は、 rmlock によって内部的に使用されるだけであり、 rm_runlock() が呼び出されるまで、存続しなければなりません。読み込み側がスリープできないので、このデータ構造をスタックに割り付けることができます。任意のスレッドが排他的に、このロックを保持しているなら、現在のスレッドは、ブロックし、優先権は、排他的な所有者へ伝播されます。ロックが RM_RECURSE オプションで初期化されたなら、現在のスレッドに rm で既に獲得された読み込み側のアクセスがあるとき、 rm_rlock() 関数を呼び出すことができます。
rm_try_rlock( struct rmlock *rm, struct rm_priotracker* tracker)
読み込み側 (reader) として rm のロックを試みます。 rm_try_rlock() は、ロックが直ちに獲得できないなら、0 を返します。そうでなければ、ロックが獲得され、0 以外の値を返します。ロックが現在書き込み側 (writer) によって保持されていない間でさえ、 rm_try_rlock() が失敗するかもしれないことに注意してください。ロックが RM_RECURSE オプションで初期化されたなら、 rm_try_rlock() は、現在のスレッドに既に獲得された読み込み側のアクセスがあるなら、成功します。
rm_wlock( struct rmlock *rm)
書き込み側 (writer) として rm をロックします。ロックを共有する複数の所有者がいるなら、現在のスレッドは、ブロックします。 rm_wlock() 関数を再帰的に呼び出すことはできません。
rm_runlock( struct rmlock *rm, struct rm_priotracker* tracker)
この関数は、以前に rm_rlock() によって獲得された共有されたロックを解放します。 tracker 引数は、共有されたロックを獲得するために使用される tracker 引数とマッチしなければなりません。
rm_wunlock( struct rmlock *rm)
この関数は、以前に rm_wlock() によって獲得された排他的なロックを解放します。
rm_destroy( struct rmlock *rm)
この関数は、以前に rm_init() で初期化されたロックを破壊します。 rm ロックは、アンロックされていなければなりません。
rm_wowned( const struct rmlock *rm)
この関数は、現在のスレッドが rm で排他的なロックを所有しているなら、0 以外を返します。
rm_sleep( void *wchan, struct rmlock *rm, int priority, const char *wmesg, int timo)
この関数は、イベントを待つ間に、不可分に rm を解放します。 rm ロックは、排他的にロックされなければなりません。この関数へのパラメータのより詳しい情報については、 sleep(9) を参照してください。
rm_assert( struct rmlock *rm, int what)
この関数は、 rm ロックが what によって指定された状態であることをアサートします。アサーションが真でなく、カーネルが options INVARIANTSoptions INVARIANT_SUPPORT でコンパイルされているなら、カーネルは、パニックします。現在、次の基本的なアサーションがサポートされています:
RA_LOCKED
現在のスレッドが rm の共有または排他的なロックのいずれかを保持しているかをアサートします。
RA_RLOCKED
現在のスレッドが rm の共有されるロックを保持しているかをアサートします。
RA_WLOCKED
現在のスレッドが rm の排他的ロックを保持しているかをアサートします。
RA_UNLOCKED
現在のスレッドが rm の共有されるか、または排他的ロックのいずれかを保持しているかをアサートします。

さらに、次のオプションのフラグの 1 つは、 RA_LOCKED, RA_RLOCKED または RA_WLOCKED で指定されます:

RA_RECURSED
現在のスレッドが rm の再帰的なロックを保持しているかをアサートします。
RA_NOTRECURSED
現在のスレッドが rm の再帰的なロックを保持しないかをアサートします。

歴史

これらの関数は、 FreeBSD 7.0 で登場しました。

作者

rmlock 機能は、 Stephan Uphoff によって書かれました。このマニュアルページは、rwlock に関して Gleb Smirnoff によって書かれ、 Stephan Uphoff によって rmlock に反映するように変更されました。

バグ

rmlock 実装は、現在、単一のプロセッサシステムのために最適化されません。

rm_try_rlock() は、書き込み側がないときでさえ、一時的に失敗するかもしれませんが、別の読み込み側は、ローカル CPU で状態を更新します。

rmlock 実装は、システムのすべての rmlocks によって共有された CPU リストごとに 1 つを使用します。 rmlocks が一般的になるなら、CPU キューごとの複数のハッシュが、書き込み側ロックプロセスを早くするために必要であるかもしれません。

June 25, 2013 FreeBSD