Le code se trouve dans _spin_lock_contested
, qui est appelé à partir du _spin_lock_quick
moment où quelqu'un d'autre tente d'obtenir le verrou:
count = atomic_fetchadd_int(&spin->counta, 1);
if (__predict_false(count != 0)) {
_spin_lock_contested(spin, ident, count);
}
S'il n'y a pas de concours, alors count
(la valeur précédente) devrait l'être 0
, mais ce n'est pas le cas. Cette count
valeur est transmise en tant que paramètre à en _spin_lock_contested
tant que value
paramètre. Ceci value
est ensuite vérifié avec if
l'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;
}
En gardant à l'esprit que value
c'est la valeur précédente de spin->counta
, et que celle-ci a déjà été incrémentée de 1, nous nous attendons spin->counta
à égaler value + 1
(sauf si quelque chose a changé entre-temps).
Donc, vérifier si spin->counta == SPINLOCK_SHARED | 1
(la condition préalable de atomic_cmpset_int
) correspond à vérifier si value + 1 == SPINLOCK_SHARED | 1
, qui peut être réécrit comme value == (SPINLOCK_SHARED | 1) - 1
(encore une fois, si rien n'a changé entre-temps).
Bien qu'il value == (SPINLOCK_SHARED | 1) - 1
puisse être réécrit tel value == SPINLOCK_SHARED
quel, il reste tel quel, pour clarifier l'intention de la comparaison (c'est-à-dire comparer la valeur précédente incrémentée avec la valeur de test).
Ou iow. la réponse semble être: pour la clarté et la cohérence du code.