Note that you can easil make one out of the available primitives if you want
one. You just need a spinlock and an rwlock.
rwlock_t xxx_lock = RW_LOCK_UNLOCKED;
spinlock_t xxx_update = SPIN_LOCK_UNLOCKED;
To read:
unsigned long flags;
read_lock_irqsave(&xxx_lock, flags);
.. critical section that only reads the info ...
read_unlock_irqrestore(&xxx_lock, flags);
To write:
spin_lock_irqsave(&xxx_update, flags);
if (change is permitted) {
write_lock(&xxx_lock);
... make modification to info ...
write_unlock(&xxx_lock);
}
spin_lock_irqrestore(&xxx_update, flags);
I.e. you can verify potentially expensive prerequisites (like finding
something in a linked list) without locking out readers until the
decision has been made to go ahead.
The classical example I know about is moving directories. You have to be
sure that the destination isn't a child of the directory being moved,
which involves walking the tree up from the destination, a potentially slow
operation. Actually changing the entries is comparatively fast.
Note that in this example, holding xxx_lock *or* xxx_update grants read
access, so *all* writers must grab xxx_update.
This version permits readers to enter while an update lock is held.
Another variant, which reduces write-lock contention in some cases,
bars new readers while the update lock is held, so it is more likely
that the upgrade will not block. This requires more cooperation from
the rwlock_t implementation.
-- -Colin