bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2] irqdev: make deliver_user_intr return void


From: Junling Ma
Subject: [PATCH v2] irqdev: make deliver_user_intr return void
Date: Tue, 4 Aug 2020 14:05:03 -0700

This sets up the stage for making deliver_user_intr a linux irq handler, which 
does not have a
return value. So we make deliver_user_intr return void, and move the check for 
dead notification
port into intr_thread. Now deliver_user_intr does not touch main_intr_queue, 
and only the server
thread and intr_thread manupulate the queue, adn the manipulations have been 
protected by a lock.

---
 device/intr.c                    | 47 ++++++++++++--------------------
 device/intr.h                    |  2 +-
 linux/dev/arch/i386/kernel/irq.c | 14 ++--------
 3 files changed, 21 insertions(+), 42 deletions(-)

diff --git a/device/intr.c b/device/intr.c
index 705dc1c6..c98e5c39 100644
--- a/device/intr.c
+++ b/device/intr.c
@@ -27,6 +27,8 @@ extern struct irqdev irqtab;
 #define main_intr_queue irqtab.intr_queue
 static boolean_t deliver_intr (int id, ipc_port_t dst_port);
 
+extern void free_irq (unsigned int irq, void *dev_id);
+
 #define PROTECT(lock, critical_section) \
 {\
   simple_lock(&lock);\
@@ -82,9 +84,8 @@ irq_acknowledge (ipc_port_t receive_port)
   return D_SUCCESS;
 }
 
-/* This function can only be used in the interrupt handler. */
-static void
-queue_intr (struct irqdev *dev, int id, user_intr_t *e)
+void
+deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e)
 {
   /* Until userland has handled the IRQ in the driver, we have to keep it
    * disabled. Level-triggered interrupts would keep raising otherwise. */
@@ -99,29 +100,6 @@ queue_intr (struct irqdev *dev, int id, user_intr_t *e)
   thread_wakeup ((event_t) &intr_thread);
 }
 
-int
-deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e)
-{
-  /* The reference of the port was increased
-   * when the port was installed.
-   * If the reference is 1, it means the port should
-   * have been destroyed and I destroy it now. */
-  if (e->dst_port
-      && e->dst_port->ip_references == 1)
-    {
-      printf ("irq handler [%d]: release a dead delivery port %p entry %p\n", 
id, e->dst_port, e);
-      ipc_port_release (e->dst_port);
-      e->dst_port = MACH_PORT_NULL;
-      thread_wakeup ((event_t) &intr_thread);
-      return 0;
-    }
-  else
-    {
-      queue_intr (dev, id, e);
-      return 1;
-    }
-}
-
 /* insert an interrupt entry in the queue.
  * This entry exists in the queue until
  * the corresponding interrupt port is removed.*/
@@ -163,7 +141,7 @@ out:
 void
 intr_thread (void)
 {
-  user_intr_t *e;
+  user_intr_t *e, *next;
   int id;
   ipc_port_t dst_port;
 
@@ -178,7 +156,7 @@ intr_thread (void)
       simple_lock(&irqtab.lock);
       queue_iterate (&main_intr_queue, e, user_intr_t *, chain)
        {
-         if ((!e->dst_port || e->dst_port->ip_references == 1) && e->n_unacked)
+         while (e->dst_port->ip_references == 1)
            {
              printf ("irq handler [%d]: release dead delivery %d unacked irqs 
port %p entry %p\n", e->id, e->n_unacked, e->dst_port, e);
              /* The reference of the port was increased
@@ -188,11 +166,22 @@ intr_thread (void)
               * handling can trigger, and we will cleanup later after the Linux
               * handler is cleared. */
              /* TODO: rather immediately remove from Linux handler */
+             next = (user_intr_t *)queue_next(&e->chain);
+             id = irqtab.irq[e->id];
              while (e->n_unacked)
              {
-               __enable_irq (irqtab.irq[e->id]);
+               __enable_irq (id);
                e->n_unacked--;
              }
+             ipc_port_release(e->dst_port);
+             queue_remove (&main_intr_queue, e, user_intr_t *, chain);
+             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;
            }
        }
 
diff --git a/device/intr.h b/device/intr.h
index 54ddb331..55fc60dc 100644
--- a/device/intr.h
+++ b/device/intr.h
@@ -51,7 +51,7 @@ struct irqdev {
 };
 
 extern int install_user_intr_handler (struct irqdev *dev, int id, unsigned 
long flags, user_intr_t *e);
-extern int deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e);
+extern void deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e);
 extern user_intr_t *insert_intr_entry (struct irqdev *dev, int id, ipc_port_t 
receive_port);
 
 void intr_thread (void);
diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c
index 1e911f33..a01f7ab6 100644
--- a/linux/dev/arch/i386/kernel/irq.c
+++ b/linux/dev/arch/i386/kernel/irq.c
@@ -98,7 +98,6 @@ linux_intr (int irq)
 {
   struct pt_regs regs;
   struct linux_action *action = *(irq_action + irq);
-  struct linux_action **prev = &irq_action[irq];
   unsigned long flags;
 
   kstat.interrupts[irq]++;
@@ -113,18 +112,9 @@ linux_intr (int irq)
       // TODO I might need to check whether the interrupt belongs to
       // the current device. But I don't do it for now.
       if (action->user_intr)
-       {
-         if (!deliver_user_intr(&irqtab, irq, action->user_intr))
-         {
-           *prev = action->next;
-           linux_kfree(action);
-           action = *prev;
-           continue;
-         }
-       }
+        deliver_user_intr(&irqtab, irq, action->user_intr);
       else if (action->handler)
        action->handler (irq, action->dev_id, &regs);
-      prev = &action->next;
       action = action->next;
     }
 
@@ -255,7 +245,7 @@ install_user_intr_handler (struct irqdev *dev, int id, 
unsigned long flags,
   
   action->handler = NULL;
   action->next = NULL;
-  action->dev_id = NULL;
+  action->dev_id = user_intr;
   action->flags = SA_SHIRQ;
   action->user_intr = user_intr;
   
-- 
2.28.0.rc1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]