The tot_num_intr field is a count of how many deliverable interrupts across all 
lines. When we move
to the scheme of blocking read for request and write for acking, it is possible 
that an interrupt
can happen during a small period that the interrupt is acked, but the read has 
not happended yet.
If it occurs, then the interrupt is not deliverable, so we cannot decrease the 
interrupts counter
and tot_num_intr, otherwise we lose interrupts. But not decreasing tot_num_intr 
causes an infinit
loop in intr_thread. Thus, instead, we remove the tot_num_intr cvounter, and 
count the number of
deliverable interrupts in intr_thread.

---
 device/intr.c   | 10 ++++------
 device/intr.h   |  1 -
 i386/i386/irq.c |  1 -
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/device/intr.c b/device/intr.c
index b60a6a28..ba86bc2d 100644
--- a/device/intr.c
+++ b/device/intr.c
@@ -98,7 +98,6 @@ deliver_user_intr (int id, void *dev_id, struct pt_regs *regs)
   __disable_irq (irqtab.irq[id]);
   e->n_unacked++;
   e->interrupts++;
-  irqtab.tot_num_intr++;
   splx(s);
 
   thread_wakeup ((event_t) &intr_thread);
@@ -182,15 +181,14 @@ intr_thread (void)
              printf("irq handler [%d]: removed entry %p\n", id, e);
              /* if e is the last handler registered for irq ID, then remove 
the linux irq handler */
              free_irq(id, e);
-             if (e->interrupts != 0)
-               irqtab.tot_num_intr -= e->interrupts;
              kfree ((vm_offset_t) e, sizeof (*e));
              e = next;
            }
        }
 
       /* Now check for interrupts */
-      while (irqtab.tot_num_intr)
+      int total = 0;
+      do
        {
          int del = 0;
 
@@ -210,8 +208,7 @@ intr_thread (void)
                  clear_wait (current_thread (), 0, 0);
                  id = e->id;
                  dst_port = e->dst_port;
-                 e->interrupts--;
-                 irqtab.tot_num_intr--;
+                 total += --e->interrupts;
 
                  splx (s);
                  deliver_intr (id, dst_port);
@@ -237,6 +234,7 @@ intr_thread (void)
              s = splhigh ();
            }
        }
+      while (total != 0);
       simple_unlock(&irqtab.lock);
       splx (s);
       thread_block (NULL);
diff --git a/device/intr.h b/device/intr.h
index b1c09e6c..d4f98ca3 100644
--- a/device/intr.h
+++ b/device/intr.h
@@ -44,7 +44,6 @@ struct irqdev {
 
   queue_head_t intr_queue;
   decl_simple_lock_data(, lock);/* a lock to protect the intr_queue */
-  int tot_num_intr; /* Total number of unprocessed interrupts */
 
   /* Machine dependent */
   irq_t irq[NINTR];
diff --git a/i386/i386/irq.c b/i386/i386/irq.c
index 4ef1c43f..78375b07 100644
--- a/i386/i386/irq.c
+++ b/i386/i386/irq.c
@@ -68,7 +68,6 @@ void irq_init()
   irqtab.irqdev_ack = irq_eoi;
   queue_init (&irqtab.intr_queue);
   simple_lock_init(&irqtab.lock);
-  irqtab.tot_num_intr = 0;
   for (int i = 0; i < NINTR; ++i)
     irqtab.irq[i] = i;
 }
-- 
2.28.0.rc1


Reply via email to