コードはにあり、他の誰かがロックを取得しよう_spin_lock_contested
とした_spin_lock_quick
ときに呼び出されます。
count = atomic_fetchadd_int(&spin->counta, 1);
if (__predict_false(count != 0)) {
_spin_lock_contested(spin, ident, count);
}
コンテストがない場合、count
(以前の値)はであるはずですが0
、そうではありません。このcount
値は_spin_lock_contested
、value
パラメーターとしてに渡されます。value
次に、これはif
OPから確認されます。
/*
* WARNING! Caller has already incremented the lock. We must
* increment the count value (from the inline's fetch-add)
* to match.
*
* Handle the degenerate case where the spinlock is flagged SHARED
* with only our reference. We can convert it to EXCLUSIVE.
*/
if (value == (SPINLOCK_SHARED | 1) - 1) {
if (atomic_cmpset_int(&spin->counta, SPINLOCK_SHARED | 1, 1))
return;
}
これvalue
はの以前の値でspin->counta
あり、後者はすでに1ずつインクリメントされていることを念頭に置いて、spin->counta
等しいことが期待されますvalue + 1
(その間に何かが変更されない限り)。
したがって、spin->counta == SPINLOCK_SHARED | 1
(の前提条件atomic_cmpset_int
)かどうかのチェックはvalue + 1 == SPINLOCK_SHARED | 1
、value == (SPINLOCK_SHARED | 1) - 1
(再度、当面何も変更されていない場合)と書き換えられるifのチェックに対応します。
ながらvalue == (SPINLOCK_SHARED | 1) - 1
のように書き換えることができvalue == SPINLOCK_SHARED
、それは比較の意図を明確にすること、であるとして残っている(すなわち。テスト値とインクリメント前の値を比較します)。
またはまぁ。答えは:明快さとコードの一貫性のためです。