]> Zhao Yanbai Git Server - minix.git/commitdiff
Fixed a bug in interrupt handling code when removing a handler in case of
authorCristiano Giuffrida <cristiano@minix3.org>
Tue, 16 Mar 2010 10:20:36 +0000 (10:20 +0000)
committerCristiano Giuffrida <cristiano@minix3.org>
Tue, 16 Mar 2010 10:20:36 +0000 (10:20 +0000)
a shared IRQ.

kernel/system/do_irqctl.c

index 7656e2586da2998cf6e57740e2b18af15b62998e..67d414802910854a34f949d01add64cdbea76bbd 100644 (file)
@@ -81,22 +81,32 @@ PUBLIC int do_irqctl(struct proc * caller, message * m_ptr)
        }
     }
 
-      /* Find a free IRQ hook for this mapping. */
-      hook_ptr = NULL;
-      for (irq_hook_id=0; irq_hook_id<NR_IRQ_HOOKS; irq_hook_id++) {
-          if (irq_hooks[irq_hook_id].proc_nr_e == NONE) {      
-              hook_ptr = &irq_hooks[irq_hook_id];      /* free hook */
-              break;
-          }
-      }
-      if (hook_ptr == NULL) return(ENOSPC);
-
       /* When setting a policy, the caller must provide an identifier that
        * is returned on the notification message if a interrupt occurs.
        */
       notify_id = (unsigned) m_ptr->IRQ_HOOK_ID;
       if (notify_id > CHAR_BIT * sizeof(irq_id_t) - 1) return(EINVAL);
 
+      /* Try to find an existing mapping to override. */
+      hook_ptr = NULL;
+      for (i=0; !hook_ptr && i<NR_IRQ_HOOKS; i++) {
+          if (irq_hooks[i].proc_nr_e == m_ptr->m_source
+              && irq_hooks[i].notify_id == notify_id) {
+              irq_hook_id = i;
+              hook_ptr = &irq_hooks[irq_hook_id];      /* existing hook */
+              rm_irq_handler(&irq_hooks[irq_hook_id]);
+          }
+      }
+
+      /* If there is nothing to override, find a free hook for this mapping. */
+      for (i=0; !hook_ptr && i<NR_IRQ_HOOKS; i++) {
+          if (irq_hooks[i].proc_nr_e == NONE) {
+              irq_hook_id = i;
+              hook_ptr = &irq_hooks[irq_hook_id];      /* free hook */
+          }
+      }
+      if (hook_ptr == NULL) return(ENOSPC);
+
       /* Install the handler. */
       hook_ptr->proc_nr_e = m_ptr->m_source;   /* process to notify */         
       hook_ptr->notify_id = notify_id;         /* identifier to pass */