プログラムのパフォーマンス解析

ロック副作用を持った関数

NOTE(MUTEX_ACQUIRED_AS_SIDE_EFFECT(MutexExpr))

NOTE(READ_LOCK_ACQUIRED_AS_SIDE_EFFECT(RwlockExpr))

NOTE(WRITE_LOCK_ACQUIRED_AS_SIDE_EFFECT(RwlockExpr))

NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(LockExpr))

NOTE(LOCK_UPGRADED_AS_SIDE_EFFECT(RwlockExpr))

NOTE(LOCK_DOWNGRADED_AS_SIDE_EFFECT(RwlockExpr))

NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT)

NOTE(COMPETING_THREADS_AS_SIDE_EFFECT)

これらの注釈は、関数定義の外側でも内側でも使用可能です。各注釈は、関数が指定されたロックに対する指定された副作用を持っていること (つまり、関数の終了時において、ロックを関数への進入時とは異なる状態のままに意図的にしておくことなど) をロック lint に伝えます。最後の 2 つの注釈の場合は、副作用はロックについてのものではなく、並行性の状態についてのものとなります。

副作用として読み取り書き込みロックが獲得されることを記述する場合、そのロックが読み取りアクセス用または書き込みアクセス用のどちらかを指定する必要があります。

ロックが読み取り専用アクセス用に獲得された状態から読み取り書き込みアクセス用に獲得された状態に変化する場合、ロックは昇格したといいます。一方、逆方向の変化はロックの降格といいます。

ロック lint は、各関数について、ロックの副作用 (および並行性) を解析します。通常、関数は副作用を持たないとロック lint は考えます。そこで、コードにそうした効果を持たせる場合は、注釈を使ってその意図をロック lint に伝えなければなりません。そして、注釈に指定された副作用とは異なる副作用を持つことが判明すると、エラーメッセージが返されます。

この項で解説している注釈は、だいたい、関数の性質を指すものであり、コードの特定のポイントを指すものではありません。このため、これらの注釈は関数の先頭に記述することをお薦めします。たとえば、以下の 2 つの例の間に違いはありません。上の例の方が読みやすいということだけです。


foo() {
    NOTE(MUTEX_ACQUIRED_AS_SIDE_EFFECT(lock_foo))
    ...
    if (x && y) {
    ...
    }
}


foo() {
    ...
    if (x && y) {
    NOTE(MUTEX_ACQUIRED_AS_SIDE_EFFECT(lock_foo))
    ...
    }
}

関数がそうした副作用を持つ場合、その作用は関数内のどの経路においても同じでなければなりません。ロック lint は、指定された以外の副作用を持つ関数のパスの解析については拒否します。