Znaleziono kod _spin_lock_contested
, który jest wywoływany, _spin_lock_quick
gdy ktoś inny próbuje uzyskać blokadę:
count = atomic_fetchadd_int(&spin->counta, 1);
if (__predict_false(count != 0)) {
_spin_lock_contested(spin, ident, count);
}
Jeśli nie ma konkursu, to count
(poprzednia wartość) powinna być 0
, ale tak nie jest. Ta count
wartość jest przekazywana jako parametr _spin_lock_contested
jako value
parametr. Jest value
to następnie sprawdzane za pomocą if
z PO:
/*
* 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;
}
Pamiętając o tym, że value
jest to poprzednia wartość spin->counta
, a ta ostatnia została już zwiększona o 1, spodziewamy spin->counta
się równości value + 1
(chyba że w międzyczasie coś się zmieniło).
Zatem sprawdzenie, czy spin->counta == SPINLOCK_SHARED | 1
(warunek wstępny atomic_cmpset_int
) odpowiada sprawdzeniu, czy value + 1 == SPINLOCK_SHARED | 1
można to przepisać jakovalue == (SPINLOCK_SHARED | 1) - 1
(ponownie, jeśli w międzyczasie nic się nie zmieniło).
Chociaż value == (SPINLOCK_SHARED | 1) - 1
można go przepisać jako value == SPINLOCK_SHARED
, pozostawia się tak, jak jest, aby wyjaśnić cel porównania (tj. Porównać zwiększoną poprzednią wartość z wartością testową).
Lub iow. odpowiedź wydaje się brzmieć: dla jasności i spójności kodu.