Код находится в _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
из ОП:
/*
* 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
(опять же, если за это время ничего не изменилось).
Хотя это value == (SPINLOCK_SHARED | 1) - 1
можно переписать как value == SPINLOCK_SHARED
, оно оставлено как есть, чтобы уточнить цель сравнения (т. Е. Сравнить увеличенное предыдущее значение с тестовым значением).
Или да. Ответ, кажется, для ясности и последовательности кода.