Subject: possible race condition on p->p_flag?
To: None <tech-kern@NetBSD.ORG>
From: Bill Sommerfeld <sommerfeld@orchard.arlington.ma.us>
List: tech-kern
Date: 06/15/1998 23:07:20
So, I was just looking at select() and poll(). I think I see what
looks like a potential race..

in short, they do a:

retry:
	p->p_flag |= P_SELECT;
	{sel,poll}scan()
	splhigh()
	if ((p->p_flag & P_SELECT) == 0) {
		splx()
		goto retry;
	}		
	tsleep();
	splx()
	goto retry;

while selwakeup() does a
	
	if (p->p_flag & P_SELECT)
		p->p_flag &= ~P_SELECT;

maybe i'm just paranoid, but on those architectures which lack
set/clear-bit-in memory instructions (e.g, most RISCs),
	p->p_flag

presumably turns into (pseudo-code):

	r1 = p->p_flag
	r1 |= P_SELECT
	p->p_flag = r1

If an interrupt comes in in the middle of this, other interrupt-side
code which changes the value of p->p_flag will have its changes
un-done on return from interrupt..

I haven't done an exhaustive search through the codebase for this but
i'd be surprised if *something* else in the kernel doesn't try to set
or clear a bit in p_flag at interrupt level..

Am I being too paranoid?  What am I missing?  

					- Bill