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

Linus Torvalds (torvalds@transmeta.com)
Sat, 10 Jan 1998 10:36:48 -0800 (PST)


On Sat, 10 Jan 1998, Joe Keane wrote:
>
> >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.
>
> But it's not the usual behavior; generally people assume that read and
> update locks don't conflict.

Note that my update locks don't conflict in one direction: the update lock
can be held while other read locks are active, it's just that new read
lockers cannot enter the critical region any more. Think of this as
optimizing for the case where we will upgrade to the write lock, and
you'll probably find that this is what you want some of the time.

> Ideally everyone would follow this protocol: obtain an update lock to
> look around, upgrade to a write lock right before writing something, or
> maybe downgrade to read lock if you know there will be no write.

I agree, allowing downgrading to a read lock might be a good idea. It's
also extremely simple with this implementation of update locks:

atomic_add(0x80000001,&(rw)->lock)

will do the right thing (subtle, subtle - it's actually dropping the high
bit which is the exclusive bit and incrementing the read count at the same
time: think of it as a subtract of 0x80000000 followed by an add of 1).
However, once downgraded to a read lock it really has to do a
"read_unlock()" rather than the "update_unlock()" (that wasn't true of
upgrading to a write-lock: update_unlock() worked as well as
write_unlock()).

Anyway, I certainly agree that these may not be the usual behaviour for an
update lock, but I also think that it is still reasonable (sometimes
probably the preferred) behaviour, and that the simplicity of implementing
it is preferable to doing traditional update locks.

Actually it wouldn't be all that hard to have two versions of the update
lock: one that prefers reading and one that prefers writing. My update
lock prefers writing, but I could do one that prefers reading: it wouldn't
be all that much different (I'd use bit 30 instead of 31 as the "update"
lock - that will automatically also lock out writers but wouldn't lock out
readers). HOWEVER, I can't easily make a lock that can share both
semantics at the same time depending on what you consider to be the more
likely case.

So do people think that the reader-prefering version would be better? I
don't want to have both because of the possibility of mixups (the code
might appear correct, but if somebody ever mixed them the results would be
unpredictable - you could get dead-locks if two different kinds of upgrade
locks were entered at the same time - they wouldn't be mutually exclusive
but upgrading to a write lock certainly _would_ be).

Linus