9fans archive / 2000 / 08 / 108 / prev next
From: miller@ham...
Subject: Re: [9fans] Kernel question: i386 test-and-set problem
Date: Thu, 3 Aug 2000 13:00:39 GMT
> Things calling sleep/wakeup can and do perform such
> synchronization.
> ...
> Unfortunately, postnote is an asyncronous event often
> initiated by someone that's trying to stop something.
> It doesn't know about this external synchronization.
Thank you for patiently re-explaining -- now I see my mistake.
I misunderstood your scenario which showed the flaw in my
suggested algorithm: I thought it was the lock(r) in wakeup()
which might use an invalid r, but -- as you have shown --
there are higher level locks elsewhere in the kernel which
prevent any race between wakeup(r) and sleep(r)..free(r),
in both your version and mine. It's the lock(r) in my version
of postnote() which might go wrong, because of a race between
postnote() and wakeup(r)..free(r). Sorry for not reading
your posting carefully enough.
My sketched "proof" didn't take this race into account because
I hadn't realised that a Rendez could be deallocated. I think
it's not difficult to remedy, though.
You said "We don't know that p->r really points to a valid
Rendzvous structure", but in fact that's just what I want to
be able to guarantee, in order to make asynchronous postnote(p)
safe. Let's stipulate another invariant IPV(p) for each Proc p:
"if p->r is nonzero, then it points to a valid Rendez which
will not be deallocated without first setting p->r to zero".
To maintain this, after p sleeps on r there must be an assignment
of p->r=0 under control of p->rlock before r can be deallocated --
the lock is now necessary to prevent a race with another
process which is looking at p->r (e.g. in postnote).
I think we can do this in my wakeup() without lock ordering
problems, as follows:
wakeup(r): {wakeup condition is satisfied}
lock(r)
p = r->p
r->p = 0
unlock(r)
if p != 0
lock(p->rlock)
p->r = 0
ready(p)
unlock(p->rlock)
Strictly speaking this makes my original invariant IR(r)
invalid between the two locked sections; but we can redefine
S(p,r) to mean "Proc p is sleeping or committed to sleeping
on Rendez r, and no other proc is committed to waking p"
and I think everything then still works.
-- Richard