Re: Kernel locks

Colin Plumb (colin@nyx.net)
Sun, 4 Jan 1998 03:06:09 -0700 (MST)


His Holiness Linus I sayeth:
> Note: you cannot "upgrade" a read-lock to a write-lock, so if you at _any_
> time need to do any changes (even if you don't do it every time), you have
> to get the write-lock at the very beginning. I could fairly easily add a
> primitive to create a "upgradeable" read-lock, but it hasn't been an issue
> yet. Tell me if you'd want one.

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