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