Kod, başka bir kişi kilidi almaya çalışırken _spin_lock_contested
çağrılır _spin_lock_quick
:
count = atomic_fetchadd_int(&spin->counta, 1);
if (__predict_false(count != 0)) {
_spin_lock_contested(spin, ident, count);
}
Yarışma yoksa, count
(önceki değer) olmalı 0
, ama değil. Bu count
değer parametre olarak parametresi _spin_lock_contested
olarak geçirilir value
. Bu value
daha sonra OP'den kontrol edilir if
:
/*
* 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
Önceki değerin olduğunu spin->counta
ve ikincisinin zaten 1 arttırıldığını akılda tutarak, spin->counta
eşit olmayı bekliyoruz value + 1
(bu arada bir şey değişmedikçe).
Bu nedenle, spin->counta == SPINLOCK_SHARED | 1
(ön koşulunun atomic_cmpset_int
) value + 1 == SPINLOCK_SHARED | 1
yeniden yazılabilir olup olmadığını kontrol etmeye karşılık gelip gelmediğini kontrol etmek value == (SPINLOCK_SHARED | 1) - 1
(bu arada hiçbir şey değişmediyse).
İken value == (SPINLOCK_SHARED | 1) - 1
şekilde tekrar yazılabilir value == SPINLOCK_SHARED
, bu karşılaştırmanın niyet netleştirmek için, olduğu gibi kalan (yani. Test değeri ile artırılır önceki değerini karşılaştırmak için).
Veya iow. cevabın açıklık ve kod tutarlılığı için olduğu görülmektedir.