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


Reply via email to