assert side effect |
mutex |
acquired in |
func ... |
assert side effect |
rwlock [read] |
acquired in |
func ... |
assert side effect |
lock |
released in |
func ... |
assert side effect |
rwlock |
upgraded in |
func ... |
assert side effect |
rwlock |
downgraded in |
func ... |
assert mutex|rwlock |
protects |
|
var ... |
assert mutex |
protects |
|
func ... |
assert rwlock |
protects |
[reads in] |
func ... |
assert order |
|
|
lock lock ... |
assert read only |
|
|
var ... |
assert rwlock |
covers |
|
lock ... |
これらのサブコマンドは、ロック lint に対して、チェックの対象となるアプリケーションにおいてロックおよび変数がどのようにアクセスおよび変更されることをプログラマが期待しているかを指示します。解析中には、そうしたアサーションの違反が報告されます。
1 つの変数について 2 回以上のアサートが行われている場合、最後の assert のみが有効となります。
副作用 (side effect) とは、ロックの状態が関数によって変化し、関数が制御を返す前に、その変化が復帰しないことを指します。関数にロックの副作用が含まれ、その副作用についてのアサーションが作成されていない場合、あるいは、実際の副作用がアサーションの内容と異なる場合、解析中に警告が発行されます。その後は、予期せぬ副作用はまったく起こらないものとして、解析は続行されます。
副作用には逆転と呼ばれる種類もあります。詳細については、 「ロックの逆転」、および「locks」または「funcs」サブコマンドを参照してください。
関数によってもたらされる副作用が呼び出しごとに異なる場合も (たとえば、条件付きの副作用など)、警告が発せられます。キーワード acquired in、released in、upgraded in、downgraded in は、関数についてアサートされているロック副作用の種類を明らかにします。これらのキーワードは、スレッドライブラリインタフェース、DDI および DKI カーネルファンクションを介して利用が可能な副作用に対応しています (「mutex(3T)」、「rwlock(3T)」、「mutex(9F)」、「rwlock(9F)」を 参照)。
rwlocks に対する副作用のアサーションは、オプション引数 read を取ります。read が付いている場合、その副作用は、その関数がそのロックに対して読み取りレベルのアクセスを獲得することになります。read がない場合は、書き込みレベルのアクセスを獲得することになります。
相互排他ロックが変数を保護しているとアサートした場合、相互排他ロックを保持せずにその変数がアクセスされた時点で必ずエラーとなります。読み取り書き込みロックが変数を保護しているとアサートした場合、読み取りアクセスに対するロックを保持せずにその変数を読み取ろうした時点、あるいは書き込みアクセスに対するロックを保持せずにその変数に書き込もうとした時点で必ずエラーとなります。どちらのロックが変数を保護しているかに関するその後のアサーションは、それ以前のアサーションを上書きします。つまり、解析中は、変数保護について、最後にアサートされたロックのみが常に使用されるということです。
相互排他ロックが関数を保護しているとアサートした場合、ロックを保持せずにその関数が呼び出された時点で必ずエラーとなります。ルート関数の場合、このアサーションが真である状態でルート関数が呼び出されたものとして、解析は実行されます。
読み取り書き込みロックが関数を保護しているとアサートした場合、書き込みアクセスに対するロックを保持せずにその関数が呼び出された時点で必ずエラーとなります。読み取り書き込みロックが関数の読み取りを保護しているとアサートした場合、読み取りアクセスに対するロックを保持せずにその関数が呼び出された時点で必ずエラーとなります。ルート関数の場合、このアサーションが真である状態でルート関数が呼び出されたものとして、解析は実行されます。
単独の assert ... protects サブコマンドに対する違反が多すぎて、出力が大量になることを防ぐため、指定されたアサーションの違反は最大 20 まで提示されます。この制限は、assert order サブコマンドには適用されません。
ロックがどのような順番で獲得されるべきかを、ロック lint に知らせます。見慣れたロックの順序を守っていれば、プログラムにデッドロックは起こらないと、ロック lint は想定します。このサブコマンドを使って、ロック lint にあらかじめ定めた順序を理解させ、その結果、解析中にその順序の違反が見つかると出力されます。
特定の変数に対して、アプリケーションは絶対に書き込みを行ってはいけないというアサーションを作成します。ロック lint は、そうした変数に対する書き込みを報告します。変数が書き込み禁止ではない限り、ロックが保持されていない状態で、変数の読み取りが行われると、エラーが発行されます。これは、ロック lint が、ほかのスレッドが同時にその変数へ書き込みを行う心配があると想定しているためです。
ロック lint に、階層的なロック関係が存在することを知らせます。特定の状況におけるパフォーマンスを改善するため、読み取り書き込みロックは、ほかのロック (相互排他あるいは読み取り書き込み) と組み合わせて使用されることがあります。
カバーと呼ばれる読み取り書き込みロックは、カバーされる側であるほかのロックが保持されている間、必ず保持されていなければなりません。これは、読み込みアクセスに対するカバーを保持していない間に、カバーされる側のロックを保持することは規則に反する (こうした表記規則の下では) ということです。
書き込みアクセスに対するカバーを保持している間は、カバーされる側のロックを保持せずに、カバーされる側のロックの 1 つによって保護された変数にアクセスすることが可能です。ほかのスレッドがカバーされる側のロックを保持することは不可能であるため (そのスレッドはカバーも保持していなければならないため)、こうした操作は可能となります。カバー上に集中した競合が存在しない限り、カバーされる側のロックを保持しないことによって節約される時間の分だけ、パフォーマンスは向上します。
assert rwlock covers を利用することで、カバーされる側のロックではなく、書き込みアクセスに対するカバーを保持しながらスレッドが変数にアクセスする場合に、ロック lint によるエラーメッセージの表示を防止できます。また、カバーが保持されていないときは、カバーされる側のロックは絶対に保持されていないというルールのチェックを可能にします。