9fans archive / 2000 / 08 / 74 /    prev next

From: miller@ham...
Subject: Re: [9fans] Kernel question: i386 test-and-set problem
Date: Wed, 2 Aug 2000 15:51:33 0100

> If it were at all possible for wakeup to be called with
> r already freed, the code would be wrong to begin with
> since r is an argument to wakeup.

For things to go wrong it's not necessary for wakeup to be
called after r is freed; what I said was "the free(r) and
malloc() could happen *while* or even before wakeup(r) runs".
It's sufficient to have sleep(r) and wakeup(r) racing on
two processors.  We could have this interleaving of events:

sleep(r) is called
  wakeup(r) is called
sleep tests wakeup condition, returns
  wakeup is delayed by an interrupt on its processor
caller of sleep deallocates structure containing r
some other process reallocates r and clobbers r->p
  wakeup resumes, dereferences r->p, ka-boom!

If you think sleep and wakeup are sufficiently interlocked
by higher level considerations that this can't happen,
then let's use your scenario with postnote, mutatis mutandis
to apply to the existing kernel algorithm:

process x calls postnote:
	postnote(p):
		p->notepending = 1
		lock(p->rlock)
		r = p->r
		if r != 0
			if(r->p == p && p->r == r)
				r->p = 0
				p->r = 0
				ready(p)
		unlock(p->rlock)

Immediately after the unlock(p->rlock) is executed,
process q calls wakeup

	process q:
		wakeup(r):    {wakeup condition is satisfied}
			coherence()
			p = r->p
			if p != 0
				lock(p->rlock)
				if (r->p == p && p->r == r)
				    r->p = 0
				    p->r = 0	
				    ready(p)
			    unlock(p->rlock)

During the call to coherence() process q is interrupted.
Process p now continues after the sleep:

	process p:
		sleep(r);
		free(r)

Process y now does

		xxx = malloc(234);
		xxx->a = 12;

And finally process q resumes, and loads and dereferences
r->p which is no longer vald.  ka-boom again.

-- Richard