Re: Upgradeable read locks for USB (was: Re: Kernel locks)

Linus Torvalds (torvalds@transmeta.com)
Thu, 8 Jan 1998 16:34:12 -0800 (PST)


On Fri, 9 Jan 1998, Iñaky Pérez González wrote:
>
> I've seen this on the kernel and reminded one of my FIXMEs on
> the USB code: upgradeable read locks. There's code which needs to
> perform checks and lookup tables before doing stuff, and it is quite
> ugly to have a write lock on hold until you decide if the real write
> operation is going to be done or not.
>
> I have tried to do it myself and got lost in record time. Is
> it that complicate or I am really *nerd*?

It _is_ complicated, but the fix is so simple that it's embarrassing. To
add upgradable read locks of a sort to the list of spinlocks you can do
this:

#define get_upgrade_lock(rw) \
asm volatile("\n1:\t" \
"lock ; btsl $31,%0\n\t" \
"jc 2f\n" \
".section .text.lock,\"ax\"\n" \
"2:\tcmp $0,%0\n\t" \
"js 2b\n\t" \
"jmp 1b\n" \
".previous" \
:"=m" (__dummy_lock(&(rw)->lock)))

#define do_upgrade_lock(rw) \
do { /* nothing */ \
} while ((rw)->lock & 0x7fffffff)

#define update_unlock(rw) \
write_unlock(rw)

Now, admittedly the above may not be optimal for all conditions (it won't
let in any new readers while somebody has a upgrade lock: that is often
the behaviour you want, but if reading is _far_ more common than writing
then it is sometimes advantageous to allow normal readers in even after
somebody got a update lock). But it sure is simple.

Usage is something like:

get_upgrade_lock(&rw_lock)

.. read the lock freely here - there may be other readers concurrent ..

if (needs_to_write) {
do_upgrade_lock(&rw_lock);
.. now we can write ..
}
update_unlock(&rw_lock);

(ie you don't _have_ to upgrade the lock if you don't want to, but you can
still unlock with the same generic unlock version).

NOTE NOTE NOTE! The above has not been compiled, much less tested. It
might not work. As usual, it should be fairly close to working, and it
might work as-is, but be careful, and be ready to debug it. (And you'd
need to add the irq-safe versions too).

If the above does work for people (or it works after a few fixes) and
somebody decides that he wants to use upgrade locks, send me a patch back
with the (possibly fixed) code.

Linus