1. The queue manipulated by two threads, the registration server and the intr_thread, so we need a lock to protect it. 2. To initialize the lock, we introduce a irq_init function in i386/i386/irq.[ch] and call it in device/device_init.c
--- device/device_init.c | 3 ++- device/intr.c | 26 ++++++++++++++++++++------ device/intr.h | 6 ++++-- i386/i386/irq.c | 16 ++++++++++++---- i386/i386/irq.h | 2 ++ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/device/device_init.c b/device/device_init.c index 794186ee..4e5109ff 100644 --- a/device/device_init.c +++ b/device/device_init.c @@ -41,7 +41,7 @@ #include <device/ds_routines.h> #include <device/net_io.h> #include <device/chario.h> - +#include <machine/irq.h> ipc_port_t master_device_port; @@ -60,6 +60,7 @@ device_service_create(void) net_io_init(); device_pager_init(); chario_init(); + irq_init(); (void) kernel_thread(kernel_task, io_done_thread, 0); (void) kernel_thread(kernel_task, net_thread, 0); diff --git a/device/intr.c b/device/intr.c index fbb9f495..705dc1c6 100644 --- a/device/intr.c +++ b/device/intr.c @@ -23,18 +23,31 @@ #ifndef MACH_XEN -queue_head_t main_intr_queue; +extern struct irqdev irqtab; +#define main_intr_queue irqtab.intr_queue static boolean_t deliver_intr (int id, ipc_port_t dst_port); +#define PROTECT(lock, critical_section) \ +{\ + simple_lock(&lock);\ + critical_section;\ + simple_unlock(&lock);\ +} + static user_intr_t * search_intr (struct irqdev *dev, ipc_port_t dst_port) { user_intr_t *e; - queue_iterate (dev->intr_queue, e, user_intr_t *, chain) + simple_lock(&dev->lock); + queue_iterate (&dev->intr_queue, e, user_intr_t *, chain) { if (e->dst_port == dst_port) - return e; + { + simple_unlock(&dev->lock); + return e; + } } + simple_unlock(&dev->lock); return NULL; } @@ -64,7 +77,7 @@ irq_acknowledge (ipc_port_t receive_port) if (irqtab.irqdev_ack) (*(irqtab.irqdev_ack)) (&irqtab, e->id); - __enable_irq (irqtab.irq[e->id]); + PROTECT(irqtab.lock, __enable_irq (irqtab.irq[e->id])); return D_SUCCESS; } @@ -139,7 +152,7 @@ insert_intr_entry (struct irqdev *dev, int id, ipc_port_t dst_port) new->interrupts = 0; new->n_unacked = 0; - queue_enter (dev->intr_queue, new, user_intr_t *, chain); + PROTECT(dev->lock, queue_enter (&dev->intr_queue, new, user_intr_t *, chain)); out: splx (s); if (free) @@ -153,7 +166,6 @@ intr_thread (void) user_intr_t *e; int id; ipc_port_t dst_port; - queue_init (&main_intr_queue); for (;;) { @@ -163,6 +175,7 @@ intr_thread (void) spl_t s = splhigh (); /* Check for aborted processes */ + 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) @@ -231,6 +244,7 @@ intr_thread (void) s = splhigh (); } } + simple_unlock(&irqtab.lock); splx (s); thread_block (NULL); } diff --git a/device/intr.h b/device/intr.h index cd3e0bce..54ddb331 100644 --- a/device/intr.h +++ b/device/intr.h @@ -42,14 +42,14 @@ struct irqdev { char *name; void (*irqdev_ack)(struct irqdev *dev, int id); - queue_head_t *intr_queue; + 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]; }; -extern queue_head_t main_intr_queue; 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 user_intr_t *insert_intr_entry (struct irqdev *dev, int id, ipc_port_t receive_port); @@ -57,6 +57,8 @@ extern user_intr_t *insert_intr_entry (struct irqdev *dev, int id, ipc_port_t re void intr_thread (void); kern_return_t irq_acknowledge (ipc_port_t receive_port); +void irq_init(void); + #endif /* MACH_XEN */ #endif diff --git a/i386/i386/irq.c b/i386/i386/irq.c index 35681191..4ef1c43f 100644 --- a/i386/i386/irq.c +++ b/i386/i386/irq.c @@ -60,8 +60,16 @@ __enable_irq (irq_t irq_nr) splx(s); } -struct irqdev irqtab = { - "irq", irq_eoi, &main_intr_queue, 0, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, -}; +struct irqdev irqtab; + +void irq_init() +{ + irqtab.name = "irq"; + 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; +} diff --git a/i386/i386/irq.h b/i386/i386/irq.h index d48a8e92..1ca105ef 100644 --- a/i386/i386/irq.h +++ b/i386/i386/irq.h @@ -22,6 +22,8 @@ typedef unsigned int irq_t; void __enable_irq (irq_t irq); void __disable_irq (irq_t irq); +void irq_init(); + extern struct irqdev irqtab; #endif -- 2.28.0.rc1