Hi,
What happens is that the interrupt is still masked even after
intctrl_t::unmask() is called. It seems to me that the following
interleaving is happening:
A thread is finished handling an interrupt and try to unmask the irq by
calling intctrl_t::unmask():
if (redir[irq].entry.is_edge_triggered())
{
if (redir[irq].pending)
{
redir[irq].pending = false;
/**
* (1) INTERRUPT COMES HERE
**/
return true; // leave IRQ masked, since there was another pending
}
An interrupt comes in at (1) and executes the intctrl_t::handle_irq()
bool deliver = true;
// edge triggered IRQs are marked as pending if masked
if ( redir[irq].entry.is_edge_triggered() &&
redir[irq].entry.x.mask )
...
redir[irq].pending = true;
deliver = false;
}
Which resets the pending to true without delivering the interrupt.
Haohui
On 04/13/2010 02:20 AM, Jan Stoess wrote:
Hi Haohui,
There's no line 423 in api/v4/interrupt.cc in the current HG repo, I
am assuming you're referring to line 86.
Anyway, thanks for the patch. Before we commit the fix, can you
elaborate a little bit more on the race condition you're hitting? In
particular, I thought APIC redir entries are modified by one dedicated
CPU only -- the CPU the IRQ is routed to, so races should occur only
during IRQ migration. While I can imagine that there might be a race
at times, I am also wondering if we can get away without locking every
modification of a redirection entry.
Thanks!
-Jan
--
Jan Stoess
KIT/UKa System Architecture Group
Phone: +49 (721) 608-4056
Fax: +49 (721) 608-7664
http://os.ibds.kit.edu/stoess