All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
@ 2006-02-07  9:04 Dmitry Adamushko
  2006-02-07  9:58 ` Wolfgang Grandegger
  0 siblings, 1 reply; 25+ messages in thread
From: Dmitry Adamushko @ 2006-02-07  9:04 UTC (permalink / raw)
  To: xenomai, Jan Kiszka


[-- Attachment #1.1: Type: text/plain, Size: 765 bytes --]

Hi,

this is the final set of patches against the SVN trunk of 2006-02-03.

It addresses mostly remarks concerning naming (XN_ISR_ISA -> XN_ISR_EDGE), a
few cleanups and updated comments.

Functionally, the support for shared interrupts (a few flags) to the rtdm
(Jan's patch) and native skin.
In the later case, rt_intr_create() now contains the 6-th argument, namely
"int mode".

Now I'm waiting for the test results from Jan (the previous patch-set
remains to be suitable for testing too in case you are using it already).
Upon success, the new code is ready for merging.

the patches have to be applied as follows :
- shirq-base
- shirq-v8
- shirq-proc
- shirq-edge
- shirq-ext

Happy testing ! :)

--
Best regards,
Dmitry Adamushko

[-- Attachment #1.2: Type: text/html, Size: 874 bytes --]

[-- Attachment #2: shirq-base.patch --]
[-- Type: application/octet-stream, Size: 10137 bytes --]

diff -urp xenomai-CVS/include/native/intr.h xenomai-shirq-base/include/native/intr.h
--- xenomai-CVS/include/native/intr.h	2005-11-01 23:37:45.000000000 +0100
+++ xenomai-shirq-base/include/native/intr.h	2006-02-03 15:39:03.000000000 +0100
@@ -71,8 +71,6 @@ typedef struct rt_intr {
 
     rt_handle_t handle;	/* !< Handle in registry -- zero if unregistered. */
 
-    char name[XNOBJECT_NAME_LEN]; /* !< Symbolic name. */
-
 #if defined(__KERNEL__) && defined(CONFIG_XENO_OPT_PERVASIVE)
 
     int mode;		/* !< Interrupt control mode. */
@@ -101,6 +99,7 @@ int __native_intr_pkg_init(void);
 void __native_intr_pkg_cleanup(void);
 
 int rt_intr_create(RT_INTR *intr,
+		   const char *name,
 		   unsigned irq,
 		   rt_isr_t isr,
 		   rt_iack_t iack);
@@ -122,7 +121,7 @@ extern "C" {
 #endif
 
 int rt_intr_bind(RT_INTR *intr,
-		 unsigned irq,
+		 const char *name,
 		 RTIME timeout);
 
 static inline int rt_intr_unbind (RT_INTR *intr)
@@ -133,6 +132,7 @@ static inline int rt_intr_unbind (RT_INT
 }
 
 int rt_intr_create(RT_INTR *intr,
+		   const char *name,
 		   unsigned irq,
 		   int mode);
 
diff -urp xenomai-CVS/include/nucleus/intr.h xenomai-shirq-base/include/nucleus/intr.h
--- xenomai-CVS/include/nucleus/intr.h	2005-11-01 23:37:45.000000000 +0100
+++ xenomai-shirq-base/include/nucleus/intr.h	2006-02-03 15:39:03.000000000 +0100
@@ -42,6 +42,8 @@ typedef struct xnintr {
 
     void *cookie;	/* !< User-defined cookie value. */
 
+    char name[XNOBJECT_NAME_LEN]; /* !< Symbolic name. */
+
 } xnintr_t;
 
 extern xnintr_t nkclock;
@@ -55,6 +57,7 @@ void xnintr_clock_handler(void);
     /* Public interface. */
 
 int xnintr_init(xnintr_t *intr,
+		const char *name,
 		unsigned irq,
 		xnisr_t isr,
 		xniack_t iack,
diff -urp xenomai-CVS/include/rtdm/rtdm_driver.h xenomai-shirq-base/include/rtdm/rtdm_driver.h
--- xenomai-CVS/include/rtdm/rtdm_driver.h	2006-01-25 02:40:14.000000000 +0100
+++ xenomai-shirq-base/include/rtdm/rtdm_driver.h	2006-02-03 15:39:03.000000000 +0100
@@ -741,7 +741,7 @@ static inline int rtdm_irq_request(rtdm_
                                    const char *device_name,
                                    void *arg)
 {
-    xnintr_init(irq_handle, irq_no, handler, NULL, flags);
+    xnintr_init(irq_handle, device_name, irq_no, handler, NULL, flags);
     return xnintr_attach(irq_handle, arg);
 }
 
diff -urp xenomai-CVS/ksrc/nucleus/intr.c xenomai-shirq-base/ksrc/nucleus/intr.c
--- xenomai-CVS/ksrc/nucleus/intr.c	2006-02-02 12:17:23.000000000 +0100
+++ xenomai-shirq-base/ksrc/nucleus/intr.c	2006-02-03 15:39:03.000000000 +0100
@@ -42,7 +42,7 @@ static void xnintr_irq_handler(unsigned 
 			       void *cookie);
 
 /*! 
- * \fn int xnintr_init (xnintr_t *intr,unsigned irq,xnisr_t isr,xniack_t iack,xnflags_t flags)
+ * \fn int xnintr_init (xnintr_t *intr,const char *name,unsigned irq,xnisr_t isr,xniack_t iack,xnflags_t flags)
  * \brief Initialize an interrupt object.
  *
  * Associates an interrupt object with an IRQ line.
@@ -82,6 +82,9 @@ static void xnintr_irq_handler(unsigned 
  * descriptor must always be valid while the object is active
  * therefore it must be allocated in permanent memory.
  *
+ * @param name An ASCII string standing for the symbolic name of the
+ * interrupt object.
+ *
  * @param irq The hardware interrupt channel associated with the
  * interrupt object. This value is architecture-dependent. An
  * interrupt object must then be attached to the hardware interrupt
@@ -120,6 +123,7 @@ static void xnintr_irq_handler(unsigned 
  */
 
 int xnintr_init (xnintr_t *intr,
+		 const char *name,
 		 unsigned irq,
 		 xnisr_t isr,
 		 xniack_t iack,
@@ -130,6 +134,7 @@ int xnintr_init (xnintr_t *intr,
     intr->iack = iack;
     intr->cookie = NULL;
     intr->hits = 0;
+    xnobject_copy_name(intr->name,name);
 
     return 0;
 }
diff -urp xenomai-CVS/ksrc/nucleus/pod.c xenomai-shirq-base/ksrc/nucleus/pod.c
--- xenomai-CVS/ksrc/nucleus/pod.c	2006-01-29 12:34:29.000000000 +0100
+++ xenomai-shirq-base/ksrc/nucleus/pod.c	2006-02-03 15:39:03.000000000 +0100
@@ -3044,7 +3044,7 @@ unlock_and_exit:
        attached directly by the arch-dependent layer
        (xnarch_start_timer). */
 
-    xnintr_init(&nkclock,0,tickhandler,NULL,0);
+    xnintr_init(&nkclock,NULL,0,tickhandler,NULL,0);
 
     __setbits(nkpod->status,XNTIMED);
 
diff -urp xenomai-CVS/ksrc/skins/native/intr.c xenomai-shirq-base/ksrc/skins/native/intr.c
--- xenomai-CVS/ksrc/skins/native/intr.c	2005-11-29 15:15:54.000000000 +0100
+++ xenomai-shirq-base/ksrc/skins/native/intr.c	2006-02-03 15:39:03.000000000 +0100
@@ -119,7 +119,7 @@ static RT_OBJECT_PROCNODE __intr_pnode =
 #endif /* CONFIG_XENO_NATIVE_EXPORT_REGISTRY */
 
 /*! 
- * \fn int rt_intr_create (RT_INTR *intr,unsigned irq,rt_isr_t isr,rt_iack_t iack)
+ * \fn int rt_intr_create (RT_INTR *intr,const char *name,unsigned irq,rt_isr_t isr,rt_iack_t iack)
  * \brief Create an interrupt object from kernel space.
  *
  * Initializes and associates an interrupt object with an IRQ line. In
@@ -155,6 +155,11 @@ static RT_OBJECT_PROCNODE __intr_pnode =
  * be valid while the object is active therefore it must be allocated
  * in permanent memory.
  *
+ * @param name An ASCII string standing for the symbolic name of the
+ * interrupt object. When non-NULL and non-empty, this string is copied
+ * to a safe place into the descriptor, and passed to the registry package
+ * if enabled for indexing the created interrupt objects.
+ *
  * @param irq The hardware interrupt channel associated with the
  * interrupt object. This value is architecture-dependent.
  *
@@ -205,6 +210,7 @@ static RT_OBJECT_PROCNODE __intr_pnode =
  */
 
 int rt_intr_create (RT_INTR *intr,
+		    const char *name,
 		    unsigned irq,
 		    rt_isr_t isr,
 		    rt_iack_t iack)
@@ -215,7 +221,7 @@ int rt_intr_create (RT_INTR *intr,
     if (xnpod_asynch_p())
 	return -EPERM;
 
-    xnintr_init(&intr->intr_base,irq,isr,iack,0);
+    xnintr_init(&intr->intr_base,name,irq,isr,iack,0);
 #if defined(__KERNEL__) && defined(CONFIG_XENO_OPT_PERVASIVE)
     xnsynch_init(&intr->synch_base,XNSYNCH_PRIO);
     intr->pending = 0;
@@ -228,7 +234,6 @@ int rt_intr_create (RT_INTR *intr,
     xnlock_get_irqsave(&nklock,s);
     appendq(&__xeno_intr_q,&intr->link);
     xnlock_put_irqrestore(&nklock,s);
-    snprintf(intr->name,sizeof(intr->name),"irq%u",irq);
 
     err = xnintr_attach(&intr->intr_base,intr);
 
@@ -238,7 +243,7 @@ int rt_intr_create (RT_INTR *intr,
        half-baked objects... */
 
     if (!err)
-	err = rt_registry_enter(intr->name,intr,&intr->handle,&__intr_pnode);
+	err = rt_registry_enter(intr->intr_base.name,intr,&intr->handle,&__intr_pnode);
 #endif /* CONFIG_XENO_OPT_NATIVE_REGISTRY */
 
     if (err)
@@ -492,7 +497,7 @@ int rt_intr_inquire (RT_INTR *intr,
         goto unlock_and_exit;
         }
     
-    strcpy(info->name,intr->name);
+    strcpy(info->name,intr->intr_base.name);
     info->hits = intr->intr_base.hits;
     info->irq = intr->intr_base.irq;
 
diff -urp xenomai-CVS/ksrc/skins/native/syscall.c xenomai-shirq-base/ksrc/skins/native/syscall.c
--- xenomai-CVS/ksrc/skins/native/syscall.c	2006-01-31 19:35:45.000000000 +0100
+++ xenomai-shirq-base/ksrc/skins/native/syscall.c	2006-02-03 15:39:03.000000000 +0100
@@ -2894,6 +2894,7 @@ EXPORT_SYMBOL(rt_intr_handler);
 
 /*
  * int __rt_intr_create(RT_INTR_PLACEHOLDER *ph,
+ *			const char *name,
  *                      unsigned irq,
  *                      int mode)
  */
@@ -2901,6 +2902,7 @@ EXPORT_SYMBOL(rt_intr_handler);
 static int __rt_intr_create (struct task_struct *curr, struct pt_regs *regs)
 
 {
+    char name[XNOBJECT_NAME_LEN];
     RT_INTR_PLACEHOLDER ph;
     int err, mode;
     RT_INTR *intr;
@@ -2909,11 +2911,22 @@ static int __rt_intr_create (struct task
     if (!__xn_access_ok(curr,VERIFY_WRITE,__xn_reg_arg1(regs),sizeof(ph)))
 	return -EFAULT;
 
+    if (__xn_reg_arg2(regs))
+	{
+	if (!__xn_access_ok(curr,VERIFY_READ,__xn_reg_arg2(regs),sizeof(name)))
+	    return -EFAULT;
+
+	__xn_strncpy_from_user(curr,name,(const char __user *)__xn_reg_arg2(regs),sizeof(name) - 1);
+	name[sizeof(name) - 1] = '\0';
+	}
+    else
+	*name = '\0';
+
     /* Interrupt line number. */
-    irq = (unsigned)__xn_reg_arg2(regs);
+    irq = (unsigned)__xn_reg_arg3(regs);
 
     /* Interrupt control mode. */
-    mode = (int)__xn_reg_arg3(regs);
+    mode = (int)__xn_reg_arg4(regs);
 
     if (mode & ~(I_AUTOENA|I_PROPAGATE))
 	return -EINVAL;
@@ -2923,7 +2936,7 @@ static int __rt_intr_create (struct task
     if (!intr)
 	return -ENOMEM;
 
-    err = rt_intr_create(intr,irq,&rt_intr_handler,NULL);
+    err = rt_intr_create(intr,name,irq,&rt_intr_handler,NULL);
 
     if (err == 0)
 	{
diff -urp xenomai-CVS/ksrc/skins/posix/intr.c xenomai-shirq-base/ksrc/skins/posix/intr.c
--- xenomai-CVS/ksrc/skins/posix/intr.c	2006-01-03 21:41:36.000000000 +0100
+++ xenomai-shirq-base/ksrc/skins/posix/intr.c	2006-02-03 15:39:03.000000000 +0100
@@ -27,7 +27,7 @@ int pse51_intr_attach (struct pse51_inte
     int err;
     spl_t s;
 
-    xnintr_init(&intr->intr_base,irq,isr,iack,0);
+    xnintr_init(&intr->intr_base,NULL,irq,isr,iack,0);
 
 #if defined(__KERNEL__) && defined(CONFIG_XENO_OPT_PERVASIVE)
     xnsynch_init(&intr->synch_base,XNSYNCH_PRIO);
diff -urp xenomai-CVS/src/skins/native/intr.c xenomai-shirq-base/src/skins/native/intr.c
--- xenomai-CVS/src/skins/native/intr.c	2005-11-01 23:37:45.000000000 +0100
+++ xenomai-shirq-base/src/skins/native/intr.c	2006-02-03 15:39:03.000000000 +0100
@@ -24,24 +24,22 @@
 extern int __native_muxid;
 
 int rt_intr_create (RT_INTR *intr,
+		    const char *name,
 		    unsigned irq,
 		    int mode)
 {
-    return XENOMAI_SKINCALL3(__native_muxid,
+    return XENOMAI_SKINCALL4(__native_muxid,
 			     __native_intr_create,
 			     intr,
+			     name,
 			     irq,
 			     mode);
 }
 
 int rt_intr_bind (RT_INTR *intr,
-		  unsigned irq,
+		  const char *name,
 		  RTIME timeout)
 {
-    char name[XNOBJECT_NAME_LEN];
-
-    snprintf(name,sizeof(name),"irq%u",irq);
-
     return XENOMAI_SKINCALL3(__native_muxid,
 			     __native_intr_bind,
 			     intr,

[-- Attachment #3: shirq-v8.patch --]
[-- Type: application/octet-stream, Size: 12687 bytes --]

diff -urp xenomai-shirq-base/include/asm-generic/hal.h xenomai-shirq-v8/include/asm-generic/hal.h
--- xenomai-shirq-base/include/asm-generic/hal.h	2006-02-02 12:17:23.000000000 +0100
+++ xenomai-shirq-v8/include/asm-generic/hal.h	2006-02-03 15:41:50.000000000 +0100
@@ -64,6 +64,7 @@
 #define RTHAL_NR_CPUS		IPIPE_NR_CPUS
 #define RTHAL_ROOT_PRIO		IPIPE_ROOT_PRIO
 #define RTHAL_NR_FAULTS		IPIPE_NR_FAULTS
+#define RTHAL_NR_IRQS		IPIPE_NR_IRQS
 
 #define RTHAL_SERVICE_IPI0	IPIPE_SERVICE_IPI0
 #define RTHAL_SERVICE_VECTOR0	IPIPE_SERVICE_VECTOR0
diff -urp xenomai-shirq-base/include/asm-generic/system.h xenomai-shirq-v8/include/asm-generic/system.h
--- xenomai-shirq-base/include/asm-generic/system.h	2006-02-02 12:17:23.000000000 +0100
+++ xenomai-shirq-v8/include/asm-generic/system.h	2006-02-03 15:41:50.000000000 +0100
@@ -101,6 +101,8 @@ typedef struct { volatile unsigned long 
 
 #define XNARCH_NR_CPUS               RTHAL_NR_CPUS
 
+#define XNARCH_TIMER_IRQ	     RTHAL_TIMER_IRQ
+
 #define XNARCH_ROOT_STACKSZ   0	/* Only a placeholder -- no stack */
 
 #define XNARCH_PROMPT "Xenomai: "
@@ -470,6 +472,16 @@ static inline unsigned long long xnarch_
 
 #ifdef XENO_INTR_MODULE
 
+#define XNARCH_NR_IRQS		     RTHAL_NR_IRQS
+
+static inline unsigned long xnarch_critical_enter(void (*synch)(void)) {
+    return rthal_critical_enter(synch);
+}
+
+static inline void xnarch_critical_exit(unsigned long flags) {
+    return rthal_critical_exit(flags);
+}
+
 static inline int xnarch_hook_irq (unsigned irq,
 				   rthal_irq_handler_t handler,
 				   rthal_irq_ackfn_t ackfn,
diff -urp xenomai-shirq-base/include/asm-i386/hal.h xenomai-shirq-v8/include/asm-i386/hal.h
--- xenomai-shirq-base/include/asm-i386/hal.h	2006-01-31 14:09:47.000000000 +0100
+++ xenomai-shirq-v8/include/asm-i386/hal.h	2006-02-03 15:41:50.000000000 +0100
@@ -139,6 +139,9 @@ static inline __attribute_const__ unsign
 #define RTHAL_APIC_TIMER_VECTOR    RTHAL_SERVICE_VECTOR3
 #define RTHAL_APIC_TIMER_IPI       RTHAL_SERVICE_IPI3
 #define RTHAL_APIC_ICOUNT          ((RTHAL_TIMER_FREQ + HZ/2)/HZ)
+#define RTHAL_TIMER_IRQ 	   RTHAL_APIC_TIMER_IPI
+#else  /* !CONFIG_X86_LOCAL_APIC */
+#define RTHAL_TIMER_IRQ		   RTHAL_8254_IRQ
 #endif /* CONFIG_X86_LOCAL_APIC */
 
 #define RTHAL_NMICLK_FREQ	RTHAL_CPU_FREQ
diff -urp xenomai-shirq-base/include/asm-sim/system.h xenomai-shirq-v8/include/asm-sim/system.h
--- xenomai-shirq-base/include/asm-sim/system.h	2006-02-02 12:17:23.000000000 +0100
+++ xenomai-shirq-v8/include/asm-sim/system.h	2006-02-03 15:41:50.000000000 +0100
@@ -75,6 +75,9 @@ typedef unsigned long xnlock_t;
 
 #define XNARCH_NR_CPUS              1
 
+/* Should be equal to the value used for creating the mvmtimer object (mvm_start_timer). */
+#define XNARCH_TIMER_IRQ	    1
+
 #define XNARCH_DEFAULT_TICK         10000000 /* ns, i.e. 10ms */
 #define XNARCH_HOST_TICK            0 /* No host ticking service. */
 
@@ -365,6 +368,16 @@ void mvm_tcl_build_pendq(mvm_tcl_listobj
 typedef void (*rthal_irq_handler_t)(unsigned, void *);
 typedef int (*rthal_irq_ackfn_t)(unsigned);
 
+#define XNARCH_NR_IRQS		     MVM_IRQ_LEVELS
+
+static inline unsigned long xnarch_critical_enter(void (*synch)(void)) {
+    return 0;
+}
+
+static inline void xnarch_critical_exit(unsigned long flags) {
+    return;
+}
+
 static inline int xnarch_hook_irq (unsigned irq,
 				   rthal_irq_handler_t handler,
 				   rthal_irq_ackfn_t ackfn, /* Ignored. */
diff -urp xenomai-shirq-base/include/asm-uvm/system.h xenomai-shirq-v8/include/asm-uvm/system.h
--- xenomai-shirq-base/include/asm-uvm/system.h	2006-02-02 12:17:23.000000000 +0100
+++ xenomai-shirq-v8/include/asm-uvm/system.h	2006-02-03 15:41:50.000000000 +0100
@@ -74,6 +74,8 @@ typedef unsigned long xnlock_t;
 
 #define XNARCH_NR_CPUS             1
 
+#define XNARCH_TIMER_IRQ	   0
+
 #define XNARCH_DEFAULT_TICK        1000000 /* ns, i.e. 1ms */
 #define XNARCH_SIG_RESTART         SIGUSR1
 #define XNARCH_HOST_TICK           0	/* No host ticking service */
@@ -270,6 +272,16 @@ void xnarch_sync_irq (void) /* Synchroni
 typedef void (*rthal_irq_handler_t)(unsigned, void *);
 typedef int (*rthal_irq_ackfn_t)(unsigned);
 
+#define XNARCH_NR_IRQS		     0
+
+static inline unsigned long xnarch_critical_enter(void (*synch)(void)) {
+    return 0;
+}
+
+static inline void xnarch_critical_exit(unsigned long flags) {
+    return;
+}
+
 static inline int xnarch_hook_irq (unsigned irq,
 				   rthal_irq_handler_t handler,
 				   rthal_irq_ackfn_t ackfn,
diff -urp xenomai-shirq-base/include/nucleus/intr.h xenomai-shirq-v8/include/nucleus/intr.h
--- xenomai-shirq-base/include/nucleus/intr.h	2006-02-03 15:39:03.000000000 +0100
+++ xenomai-shirq-v8/include/nucleus/intr.h	2006-02-03 15:41:50.000000000 +0100
@@ -26,21 +26,31 @@
 #define XN_ISR_CHAINED   0x1
 #define XN_ISR_ENABLE    0x2
 
+/* Creation flags. */
+#define XN_ISR_SHARED	 0x1
+
+/* Operational flags. */
+#define XN_ISR_ATTACHED	 0x100
+
 #if defined(__KERNEL__) || defined(__XENO_UVM__) || defined(__XENO_SIM__)
 
 struct xnintr;
 
 typedef struct xnintr {
 
-    unsigned irq;	/* !< IRQ number. */
+    struct xnintr *next;
 
     xnisr_t isr;	/* !< Interrupt service routine. */
 
-    xniack_t iack;	/* !< Interrupt acknowledge routine. */
+    void *cookie;	/* !< User-defined cookie value. */
 
     unsigned long hits;	/* !< Number of receipts (since attachment). */
 
-    void *cookie;	/* !< User-defined cookie value. */
+    xnflags_t flags; 	/* !< Creation flags. */
+
+    unsigned irq;	/* !< IRQ number. */
+
+    xniack_t iack;	/* !< Interrupt acknowledge routine. */
 
     char name[XNOBJECT_NAME_LEN]; /* !< Symbolic name. */
 
@@ -52,6 +62,8 @@ extern xnintr_t nkclock;
 extern "C" {
 #endif
 
+int xnintr_mount(void);
+
 void xnintr_clock_handler(void);
 
     /* Public interface. */
diff -urp xenomai-shirq-base/ksrc/nucleus/intr.c xenomai-shirq-v8/ksrc/nucleus/intr.c
--- xenomai-shirq-base/ksrc/nucleus/intr.c	2006-02-03 15:39:03.000000000 +0100
+++ xenomai-shirq-v8/ksrc/nucleus/intr.c	2006-02-05 19:26:15.000000000 +0100
@@ -41,6 +41,57 @@ xnintr_t nkclock;
 static void xnintr_irq_handler(unsigned irq,
 			       void *cookie);
 
+typedef struct xnintr_shirq {
+
+    xnintr_t *handlers;
+    
+#ifdef CONFIG_SMP
+    atomic_counter_t active;
+#endif /* CONFIG_SMP */
+
+} xnintr_shirq_t;
+
+static xnintr_shirq_t xnshirqs[XNARCH_NR_IRQS];
+
+#ifdef CONFIG_SMP
+
+static inline void xnintr_shirq_lock(xnintr_shirq_t *shirq)
+{
+    xnarch_atomic_inc(&shirq->active);
+}
+
+static inline void xnintr_shirq_unlock(xnintr_shirq_t *shirq)
+{
+    xnarch_atomic_dec(&shirq->active);
+}
+
+static inline void xnintr_shirq_spin(xnintr_shirq_t *shirq)
+{
+    while (xnarch_atomic_get(&shirq->active))
+	cpu_relax();
+}
+
+#else /* !CONFIG_SMP */
+
+static inline void xnintr_shirq_lock(xnintr_shirq_t *shirq) {}
+static inline void xnintr_shirq_unlock(xnintr_shirq_t *shirq) {}
+static inline void xnintr_shirq_spin(xnintr_shirq_t *shirq) {}
+
+#endif /* CONFIG_SMP */
+
+int xnintr_mount(void)
+{
+    int i;
+    for (i = 0; i < XNARCH_NR_IRQS; ++i)
+	{
+	xnshirqs[i].handlers = NULL;
+#ifdef CONFIG_SMP
+	atomic_set(&xnshirqs[i].active,0);
+#endif /* CONFIG_SMP */
+	}
+    return 0;
+}
+
 /*! 
  * \fn int xnintr_init (xnintr_t *intr,const char *name,unsigned irq,xnisr_t isr,xniack_t iack,xnflags_t flags)
  * \brief Initialize an interrupt object.
@@ -134,6 +185,8 @@ int xnintr_init (xnintr_t *intr,
     intr->iack = iack;
     intr->cookie = NULL;
     intr->hits = 0;
+    intr->flags = flags;
+    intr->next = NULL;
     xnobject_copy_name(intr->name,name);
 
     return 0;
@@ -169,7 +222,8 @@ int xnintr_init (xnintr_t *intr,
 int xnintr_destroy (xnintr_t *intr)
 
 {
-    return xnintr_detach(intr);
+    xnintr_detach(intr);
+    return 0;
 }
 
 /*! 
@@ -209,9 +263,62 @@ int xnintr_destroy (xnintr_t *intr)
 int xnintr_attach (xnintr_t *intr,
 		   void *cookie)
 {
+    xnintr_shirq_t *shirq;
+    xnintr_t *prev, **p;
+    unsigned long flags;
+    int err = 0;
+
+    if (intr->irq >= XNARCH_NR_IRQS)
+	return -EINVAL;
+
     intr->hits = 0;
+    intr->next = NULL;
     intr->cookie = cookie;
-    return xnarch_hook_irq(intr->irq,&xnintr_irq_handler,intr->iack,intr);
+    shirq = &xnshirqs[intr->irq];
+
+    flags = xnarch_critical_enter(NULL);
+
+    if (__testbits(intr->flags,XN_ISR_ATTACHED))
+	{
+	err = -EPERM;
+	goto unlock_and_exit;
+	}
+
+    p = &shirq->handlers;
+
+    if ((prev = *p) != NULL)
+	{
+	/* Check on whether the shared mode is allowed. */
+	if (!(prev->flags & intr->flags & XN_ISR_SHARED) || (prev->iack != intr->iack))
+	    {
+	    err = -EBUSY;
+	    goto unlock_and_exit;
+	    }
+
+	/* Get a position at the end of the list to insert the new element. */
+	while (prev)
+	    {
+	    p = &prev->next;
+	    prev = *p;
+	    }
+	}
+    else
+	{
+	/* Initialize the corresponding interrupt channel */
+	err = xnarch_hook_irq(intr->irq,&xnintr_irq_handler,intr->iack,NULL);
+	if (err)
+	    goto unlock_and_exit;
+	}
+
+    __setbits(intr->flags,XN_ISR_ATTACHED);
+
+    /* Add a given interrupt object. */
+    *p = intr;
+
+unlock_and_exit:
+
+    xnarch_critical_exit(flags);
+    return err;
 }
 
 /*! 
@@ -246,7 +353,52 @@ int xnintr_attach (xnintr_t *intr,
 int xnintr_detach (xnintr_t *intr)
 
 {
-    return xnarch_release_irq(intr->irq);
+    xnintr_shirq_t *shirq;
+    unsigned long flags;
+    xnintr_t *e, **p;
+    int err = 0;
+
+    if (intr->irq >= XNARCH_NR_IRQS)
+	return -EINVAL;
+
+    shirq = &xnshirqs[intr->irq];
+
+    flags = xnarch_critical_enter(NULL);
+
+    if (!__testbits(intr->flags,XN_ISR_ATTACHED))
+	{
+	xnarch_critical_exit(flags);
+	return -EPERM;
+	}
+
+    __clrbits(intr->flags,XN_ISR_ATTACHED);
+
+    p = &shirq->handlers;
+
+    while ((e = *p) != NULL)
+	{
+	if (e == intr)
+	    {
+	    /* Remove a given interrupt object from the list. */
+	    if ((*p = e->next) == NULL)
+		err = xnarch_release_irq(intr->irq);
+    
+	    xnarch_critical_exit(flags);
+
+	    /* The idea here is to keep a detached interrupt object valid as long
+	       as the corresponding irq handler is running. This is one of the requirements
+	       to iterate over the xnintr_shirq_t::handlers list in xnintr_irq_handler()
+	       in a lockless way. */
+	    xnintr_shirq_spin(shirq);
+	    return err;
+	    }
+	p = &e->next;
+	}
+
+    xnarch_critical_exit(flags);
+
+    xnlogerr("Attempted to detach a non previously attached interrupt object");
+    return err;
 }
 
 /*! 
@@ -355,17 +507,41 @@ static void xnintr_irq_handler (unsigned
 
 {
     xnsched_t *sched = xnpod_current_sched();
-    xnintr_t *intr = (xnintr_t *)cookie;
-    int s;
+    xnintr_shirq_t *shirq;
+    xnintr_t *intr;
+    int s = 0;
 
     xnarch_memory_barrier();
 
     xnltt_log_event(xeno_ev_ienter,irq);
 
     ++sched->inesting;
-    s = intr->isr(intr);
+
+    if (irq == XNARCH_TIMER_IRQ)
+	{
+	intr = (xnintr_t*)cookie;
+	s = intr->isr(intr);
+	++intr->hits;
+	}
+    else
+	{
+	shirq = &xnshirqs[irq];
+
+	xnintr_shirq_lock(shirq);
+	intr = shirq->handlers;
+
+	while (intr)
+	    {
+	    s |= intr->isr(intr);
+	    ++intr->hits;
+
+	    intr = intr->next;
+	    }
+
+	xnintr_shirq_unlock(shirq);
+	}
+
     --sched->inesting;
-    ++intr->hits;
 
     if (s & XN_ISR_ENABLE)
 	xnarch_end_irq(irq);
@@ -389,6 +565,7 @@ static void xnintr_irq_handler (unsigned
     xnltt_log_event(xeno_ev_iexit,irq);
 }
 
+
 /*@}*/
 
 EXPORT_SYMBOL(xnintr_attach);
diff -urp xenomai-shirq-base/ksrc/nucleus/module.c xenomai-shirq-v8/ksrc/nucleus/module.c
--- xenomai-shirq-base/ksrc/nucleus/module.c	2005-11-30 10:36:33.000000000 +0100
+++ xenomai-shirq-v8/ksrc/nucleus/module.c	2006-02-03 15:41:50.000000000 +0100
@@ -713,6 +713,8 @@ int __init __xeno_sys_init (void)
     xnpod_init_proc();
 #endif /* CONFIG_PROC_FS */
 
+    xnintr_mount();
+
 #ifdef CONFIG_LTT
     xnltt_mount();
 #endif /* CONFIG_LTT */
diff -urp xenomai-shirq-base/ksrc/nucleus/pod.c xenomai-shirq-v8/ksrc/nucleus/pod.c
--- xenomai-shirq-base/ksrc/nucleus/pod.c	2006-02-03 15:39:03.000000000 +0100
+++ xenomai-shirq-v8/ksrc/nucleus/pod.c	2006-02-03 15:41:50.000000000 +0100
@@ -3040,11 +3040,10 @@ unlock_and_exit:
 
     /* The clock interrupt does not need to be attached since the
        timer service will handle the arch-dependent setup. The IRQ
-       number (arg #2) is not used since the IRQ source will be
-       attached directly by the arch-dependent layer
+       source will be attached directly by the arch-dependent layer
        (xnarch_start_timer). */
 
-    xnintr_init(&nkclock,NULL,0,tickhandler,NULL,0);
+    xnintr_init(&nkclock,NULL,XNARCH_TIMER_IRQ,tickhandler,NULL,0);
 
     __setbits(nkpod->status,XNTIMED);
 

[-- Attachment #4: shirq-proc.patch --]
[-- Type: application/octet-stream, Size: 5108 bytes --]

diff -urp xenomai-shirq-v8/include/nucleus/intr.h xenomai-shirq-proc/include/nucleus/intr.h
--- xenomai-shirq-v8/include/nucleus/intr.h	2006-02-03 15:41:50.000000000 +0100
+++ xenomai-shirq-proc/include/nucleus/intr.h	2006-02-03 15:51:32.000000000 +0100
@@ -66,6 +66,8 @@ int xnintr_mount(void);
 
 void xnintr_clock_handler(void);
 
+int xnintr_irq_proc(unsigned int irq, char *str);
+
     /* Public interface. */
 
 int xnintr_init(xnintr_t *intr,
diff -urp xenomai-shirq-v8/ksrc/arch/generic/hal.c xenomai-shirq-proc/ksrc/arch/generic/hal.c
--- xenomai-shirq-v8/ksrc/arch/generic/hal.c	2006-02-02 12:17:23.000000000 +0100
+++ xenomai-shirq-proc/ksrc/arch/generic/hal.c	2006-02-03 15:51:32.000000000 +0100
@@ -697,45 +697,6 @@ static int hal_read_proc (char *page,
     return len;
 }
 
-static int irq_read_proc (char *page,
-			  char **start,
-			  off_t off,
-			  int count,
-			  int *eof,
-			  void *data)
-{
-    int len = 0, cpu, irq;
-    char *p = page;
-
-    p += sprintf(p,"IRQ ");
-
-    for_each_online_cpu(cpu) {
-	p += sprintf(p,"        CPU%d",cpu);
-    }
-
-    for (irq = 0; irq < IPIPE_NR_IRQS; irq++) {
-
-	if (rthal_irq_handler(&rthal_domain, irq) == NULL)
-	    continue;
-
-	p += sprintf(p,"\n%3d:",irq);
-
-	for_each_online_cpu(cpu) {
-	    p += sprintf(p,"%12lu",rthal_cpudata_irq_hits(&rthal_domain,cpu,irq));
-	}
-    }
-
-    p += sprintf(p,"\n");
-
-    len = p - page - off;
-    if (len <= off + count) *eof = 1;
-    *start = page + off;
-    if (len > count) len = count;
-    if (len < 0) len = 0;
-
-    return len;
-}
-
 static int faults_read_proc (char *page,
 			     char **start,
 			     off_t off,
@@ -862,12 +823,6 @@ static int rthal_proc_register (void)
 		  NULL,
 		  rthal_proc_root);
 
-    __rthal_add_proc_leaf("irq",
-		  &irq_read_proc,
-		  NULL,
-		  NULL,
-		  rthal_proc_root);
-
     __rthal_add_proc_leaf("faults",
 		  &faults_read_proc,
 		  NULL,
@@ -890,7 +845,6 @@ static void rthal_proc_unregister (void)
 {
     rthal_nmi_proc_unregister();
     remove_proc_entry("hal",rthal_proc_root);
-    remove_proc_entry("irq",rthal_proc_root);
     remove_proc_entry("faults",rthal_proc_root);
     remove_proc_entry("apc",rthal_proc_root);
     remove_proc_entry("xenomai",NULL);
diff -urp xenomai-shirq-v8/ksrc/nucleus/intr.c xenomai-shirq-proc/ksrc/nucleus/intr.c
--- xenomai-shirq-v8/ksrc/nucleus/intr.c	2006-02-05 19:26:15.000000000 +0100
+++ xenomai-shirq-proc/ksrc/nucleus/intr.c	2006-02-05 19:26:37.000000000 +0100
@@ -537,7 +537,6 @@ static void xnintr_irq_handler (unsigned
 
 	    intr = intr->next;
 	    }
-
 	xnintr_shirq_unlock(shirq);
 	}
 
@@ -565,6 +564,35 @@ static void xnintr_irq_handler (unsigned
     xnltt_log_event(xeno_ev_iexit,irq);
 }
 
+int xnintr_irq_proc(unsigned int irq, char *str)
+{
+    xnintr_shirq_t *shirq;
+    xnintr_t *intr;
+    char *p = str;
+
+    shirq = &xnshirqs[irq];
+
+    xnintr_shirq_lock(shirq);
+    intr = shirq->handlers;
+
+    if (intr)
+	p += sprintf(p, "        ");
+
+    while (intr)
+	{
+	if (*(intr->name))
+	    p += sprintf(p, " %s,", intr->name);
+
+	intr = intr->next;
+	}
+
+    xnintr_shirq_unlock(shirq);
+
+    if (p != str)
+	--p;
+
+    return p - str;
+}
 
 /*@}*/
 
diff -urp xenomai-shirq-v8/ksrc/nucleus/module.c xenomai-shirq-proc/ksrc/nucleus/module.c
--- xenomai-shirq-v8/ksrc/nucleus/module.c	2006-02-03 15:41:50.000000000 +0100
+++ xenomai-shirq-proc/ksrc/nucleus/module.c	2006-02-03 15:51:32.000000000 +0100
@@ -526,6 +526,48 @@ static int timer_read_proc (char *page,
     return len;
 }
 
+static int irq_read_proc (char *page,
+			  char **start,
+			  off_t off,
+			  int count,
+			  int *eof,
+			  void *data)
+{
+    int len = 0, cpu, irq;
+    char *p = page;
+
+    p += sprintf(p,"IRQ ");
+
+    for_each_online_cpu(cpu) {
+	p += sprintf(p,"        CPU%d",cpu);
+    }
+
+    for (irq = 0; irq < RTHAL_NR_IRQS; irq++) {
+
+	if (rthal_irq_handler(&rthal_domain, irq) == NULL)
+	    continue;
+
+	p += sprintf(p,"\n%3d:",irq);
+
+	for_each_online_cpu(cpu) {
+	    p += sprintf(p,"%12lu",rthal_cpudata_irq_hits(&rthal_domain,cpu,irq));
+	}
+
+	p += xnintr_irq_proc(irq, p); 
+    }
+
+    p += sprintf(p,"\n");
+
+    len = p - page - off;
+    if (len <= off + count) *eof = 1;
+    *start = page + off;
+    if (len > count) len = count;
+    if (len < 0) len = 0;
+
+    return len;
+}
+
+
 static struct proc_dir_entry *add_proc_leaf (const char *name,
 					     read_proc_t rdproc,
 					     write_proc_t wrproc,
@@ -614,6 +656,12 @@ void xnpod_init_proc (void)
 		  NULL,
 		  rthal_proc_root);
 
+    add_proc_leaf("irq",
+		  &irq_read_proc,
+		  NULL,
+		  NULL,
+		  rthal_proc_root);
+
 #ifdef CONFIG_XENO_OPT_PERVASIVE
     iface_proc_root = create_proc_entry("interfaces",
 					S_IFDIR,
@@ -633,6 +681,7 @@ void xnpod_delete_proc (void)
 
     remove_proc_entry("interfaces",rthal_proc_root);
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
+    remove_proc_entry("irq",rthal_proc_root);
     remove_proc_entry("timer",rthal_proc_root);
     remove_proc_entry("version",rthal_proc_root);
     remove_proc_entry("latency",rthal_proc_root);

[-- Attachment #5: shirq-edge.patch --]
[-- Type: application/octet-stream, Size: 3384 bytes --]

diff -urp xenomai-shirq-proc/include/nucleus/intr.h xenomai-shirq-edge/include/nucleus/intr.h
--- xenomai-shirq-proc/include/nucleus/intr.h	2006-02-03 15:51:32.000000000 +0100
+++ xenomai-shirq-edge/include/nucleus/intr.h	2006-02-03 15:57:17.000000000 +0100
@@ -25,9 +25,11 @@
 #define XN_ISR_HANDLED   0x0
 #define XN_ISR_CHAINED   0x1
 #define XN_ISR_ENABLE    0x2
+#define XN_ISR_NOINT	 0x4
 
 /* Creation flags. */
 #define XN_ISR_SHARED	 0x1
+#define XN_ISR_EDGE	 0x2
 
 /* Operational flags. */
 #define XN_ISR_ATTACHED	 0x100
diff -urp xenomai-shirq-proc/ksrc/nucleus/intr.c xenomai-shirq-edge/ksrc/nucleus/intr.c
--- xenomai-shirq-proc/ksrc/nucleus/intr.c	2006-02-05 19:26:37.000000000 +0100
+++ xenomai-shirq-edge/ksrc/nucleus/intr.c	2006-02-05 19:26:55.000000000 +0100
@@ -41,6 +41,9 @@ xnintr_t nkclock;
 static void xnintr_irq_handler(unsigned irq,
 			       void *cookie);
 
+static void xnintr_edgeirq_handler(unsigned irq,
+			       void *cookie);
+
 typedef struct xnintr_shirq {
 
     xnintr_t *handlers;
@@ -289,7 +292,8 @@ int xnintr_attach (xnintr_t *intr,
     if ((prev = *p) != NULL)
 	{
 	/* Check on whether the shared mode is allowed. */
-	if (!(prev->flags & intr->flags & XN_ISR_SHARED) || (prev->iack != intr->iack))
+	if (!(prev->flags & intr->flags & XN_ISR_SHARED) || (prev->iack != intr->iack)
+	    || ((prev->flags & XN_ISR_EDGE) != (intr->flags & XN_ISR_EDGE)))
 	    {
 	    err = -EBUSY;
 	    goto unlock_and_exit;
@@ -305,7 +309,12 @@ int xnintr_attach (xnintr_t *intr,
     else
 	{
 	/* Initialize the corresponding interrupt channel */
-	err = xnarch_hook_irq(intr->irq,&xnintr_irq_handler,intr->iack,NULL);
+	void (*handler)(unsigned, void *) = &xnintr_irq_handler;
+
+	if (intr->flags & XN_ISR_EDGE)
+	    handler = &xnintr_edgeirq_handler;
+
+	err = xnarch_hook_irq(intr->irq,handler,intr->iack,NULL);
 	if (err)
 	    goto unlock_and_exit;
 	}
@@ -564,6 +573,70 @@ static void xnintr_irq_handler (unsigned
     xnltt_log_event(xeno_ev_iexit,irq);
 }
 
+#define MAX_EDGEIRQ_COUNTER		128
+
+static void xnintr_edgeirq_handler (unsigned irq, void *cookie)
+
+{
+    xnsched_t *sched = xnpod_current_sched();
+    xnintr_shirq_t *shirq;
+    xnintr_t *intr, *end = NULL;
+    int s = 0, handled = 0, counter = 0;
+
+    xnarch_memory_barrier();
+
+    xnltt_log_event(xeno_ev_ienter,irq);
+
+    ++sched->inesting;
+
+    shirq = &xnshirqs[irq];
+
+    xnintr_shirq_lock(shirq);
+    intr = shirq->handlers;
+
+    while (intr != end)
+	{
+	int ret = intr->isr(intr);
+
+	if (!(ret & XN_ISR_NOINT))
+	    {
+	    handled = 1;
+	    end = NULL;
+	    s |= ret;
+	    }
+	else if (end == NULL)
+	    end = intr;
+
+	if (!counter++)
+	    ++intr->hits;
+
+	if (!(intr = intr->next))
+	    intr = shirq->handlers;
+
+	if (counter > MAX_EDGEIRQ_COUNTER)
+	    break;
+	}
+
+    xnintr_shirq_unlock(shirq);
+
+    --sched->inesting;
+
+    /* If we encounter this case, the line is non-usable any more. */
+    if (counter > MAX_EDGEIRQ_COUNTER)
+	xnlogerr("xnintr_edgeirq_handler() : failed to get the IRQ%d line free.\n", irq);
+
+    if (s & XN_ISR_ENABLE)
+	xnarch_end_irq(irq);
+
+    if (s & XN_ISR_CHAINED)
+	xnarch_chain_irq(irq);
+
+    if (sched->inesting == 0 && xnsched_resched_p())
+	xnpod_schedule();
+
+    xnltt_log_event(xeno_ev_iexit,irq);
+}
+
 int xnintr_irq_proc(unsigned int irq, char *str)
 {
     xnintr_shirq_t *shirq;

[-- Attachment #6: shirq-ext.patch --]
[-- Type: application/octet-stream, Size: 7403 bytes --]

diff -urp xenomai-shirq-edge/include/native/intr.h xenomai-shirq-ext/include/native/intr.h
--- xenomai-shirq-edge/include/native/intr.h	2006-02-03 15:39:03.000000000 +0100
+++ xenomai-shirq-ext/include/native/intr.h	2006-02-06 14:07:56.000000000 +0100
@@ -50,9 +50,14 @@ typedef struct rt_intr_placeholder {
 
 #define XENO_INTR_MAGIC 0x55550a0a
 
+/* Creation flags. */
+#define I_SHARED	XN_ISR_SHARED
+#define I_EDGE		XN_ISR_EDGE
+
 #define RT_INTR_HANDLED XN_ISR_HANDLED
 #define RT_INTR_CHAINED XN_ISR_CHAINED
 #define RT_INTR_ENABLE  XN_ISR_ENABLE
+#define RT_INTR_NOINT	XN_ISR_NOINT
 
 #define I_DESC(xintr)  ((RT_INTR *)(xintr)->cookie)
 
@@ -102,7 +107,8 @@ int rt_intr_create(RT_INTR *intr,
 		   const char *name,
 		   unsigned irq,
 		   rt_isr_t isr,
-		   rt_iack_t iack);
+		   rt_iack_t iack,
+		   int mode);
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
 int rt_intr_handler(xnintr_t *cookie);
diff -urp xenomai-shirq-edge/include/nucleus/intr.h xenomai-shirq-ext/include/nucleus/intr.h
--- xenomai-shirq-edge/include/nucleus/intr.h	2006-02-03 15:57:17.000000000 +0100
+++ xenomai-shirq-ext/include/nucleus/intr.h	2006-02-06 15:34:24.000000000 +0100
@@ -40,7 +40,7 @@ struct xnintr;
 
 typedef struct xnintr {
 
-    struct xnintr *next;
+    struct xnintr *next; /* !< Next object in the IRQ-sharing chain. */
 
     xnisr_t isr;	/* !< Interrupt service routine. */
 
diff -urp xenomai-shirq-edge/include/rtdm/rtdm_driver.h xenomai-shirq-ext/include/rtdm/rtdm_driver.h
--- xenomai-shirq-edge/include/rtdm/rtdm_driver.h	2006-02-03 15:39:03.000000000 +0100
+++ xenomai-shirq-ext/include/rtdm/rtdm_driver.h	2006-02-06 15:20:39.000000000 +0100
@@ -693,6 +693,17 @@ typedef unsigned long               rtdm
 
 typedef xnintr_t                    rtdm_irq_t;
 
+/*!
+ * @anchor RTDM_IRQTYPE_xxx   @name RTDM_IRQTYPE_xxx
+ * Interrupt registrations flags
+ * @{
+ */
+/** Enable IRQ-sharing with other real-time drivers */
+#define RTDM_IRQTYPE_SHARED         XN_ISR_SHARED
+/** Additional flag to enable IRQ-sharing of edge-triggered interrupts */
+#define RTDM_IRQTYPE_EDGE	    XN_ISR_EDGE
+/** @} */
+
 /**
  * Interrupt handler
  *
@@ -702,7 +713,6 @@ typedef xnintr_t                    rtdm
  */
 typedef int (*rtdm_irq_handler_t)(rtdm_irq_t *irq_handle);
 
-
 /*!
  * @anchor RTDM_IRQ_xxx   @name RTDM_IRQ_xxx
  * Return flags of interrupt handlers
@@ -712,6 +722,8 @@ typedef int (*rtdm_irq_handler_t)(rtdm_i
 #define RTDM_IRQ_PROPAGATE          XN_ISR_CHAINED
 /** Re-enable interrupt line on return */
 #define RTDM_IRQ_ENABLE             XN_ISR_ENABLE
+/** Denote unhandled interrupt */
+#define RTDM_IRQ_NOINT		    XN_ISR_NOINT
 /** @} */
 
 /**
diff -urp xenomai-shirq-edge/ksrc/nucleus/intr.c xenomai-shirq-ext/ksrc/nucleus/intr.c
--- xenomai-shirq-edge/ksrc/nucleus/intr.c	2006-02-05 19:26:55.000000000 +0100
+++ xenomai-shirq-ext/ksrc/nucleus/intr.c	2006-02-06 15:27:47.000000000 +0100
@@ -159,9 +159,13 @@ int xnintr_mount(void)
  * the interrupt has been properly acknowledged. If @a iack is NULL,
  * the default routine will be used instead.
  *
- * @param flags A set of creation flags affecting the operation. Since
- * no flags are currently defined, zero should be passed for this
- * parameter.
+ * @param flags A set of creation flags affecting the operation. The
+ * valid flags are:
+ *
+ * - XN_ISR_SHARED enables IRQ-sharing with other interrupt objects.
+ *
+ * - XN_ISR_EDGE is an additional flag need to be set together with XN_ISR_SHARED
+ * to enable IRQ-sharing of edge-triggered interrupts.
  *
  * @return No error condition being defined, 0 is always returned.
  *
diff -urp xenomai-shirq-edge/ksrc/skins/native/intr.c xenomai-shirq-ext/ksrc/skins/native/intr.c
--- xenomai-shirq-edge/ksrc/skins/native/intr.c	2006-02-03 15:39:03.000000000 +0100
+++ xenomai-shirq-ext/ksrc/skins/native/intr.c	2006-02-06 15:21:33.000000000 +0100
@@ -119,7 +119,7 @@ static RT_OBJECT_PROCNODE __intr_pnode =
 #endif /* CONFIG_XENO_NATIVE_EXPORT_REGISTRY */
 
 /*! 
- * \fn int rt_intr_create (RT_INTR *intr,const char *name,unsigned irq,rt_isr_t isr,rt_iack_t iack)
+ * \fn int rt_intr_create (RT_INTR *intr,const char *name,unsigned irq,rt_isr_t isr,rt_iack_t iack,int mode)
  * \brief Create an interrupt object from kernel space.
  *
  * Initializes and associates an interrupt object with an IRQ line. In
@@ -178,6 +178,14 @@ static RT_OBJECT_PROCNODE __intr_pnode =
  * the interrupt has been properly acknowledged. If @a iack is NULL,
  * the default routine will be used instead.
  *
+ * @param mode The interrupt object creation mode. The following flags can be
+ * OR'ed into this bitmask, each of them affecting the new interrupt object:
+ *
+ * - I_SHARED enables IRQ-sharing with other interrupt objects.
+ *
+ * - I_EDGE is an additional flag need to be set together with I_SHARED
+ * to enable IRQ-sharing of edge-triggered interrupts.
+ *
  * @return 0 is returned upon success. Otherwise:
  *
  * - -ENOMEM is returned if the system fails to get enough dynamic
@@ -213,7 +221,8 @@ int rt_intr_create (RT_INTR *intr,
 		    const char *name,
 		    unsigned irq,
 		    rt_isr_t isr,
-		    rt_iack_t iack)
+		    rt_iack_t iack,
+		    int mode)
 {
     int err;
     spl_t s;
@@ -221,7 +230,7 @@ int rt_intr_create (RT_INTR *intr,
     if (xnpod_asynch_p())
 	return -EPERM;
 
-    xnintr_init(&intr->intr_base,name,irq,isr,iack,0);
+    xnintr_init(&intr->intr_base,name,irq,isr,iack,mode);
 #if defined(__KERNEL__) && defined(CONFIG_XENO_OPT_PERVASIVE)
     xnsynch_init(&intr->synch_base,XNSYNCH_PRIO);
     intr->pending = 0;
diff -urp xenomai-shirq-edge/ksrc/skins/native/snippets/user_irq.c xenomai-shirq-ext/ksrc/skins/native/snippets/user_irq.c
--- xenomai-shirq-edge/ksrc/skins/native/snippets/user_irq.c	2005-11-01 23:37:45.000000000 +0100
+++ xenomai-shirq-ext/ksrc/skins/native/snippets/user_irq.c	2006-02-06 15:29:21.000000000 +0100
@@ -33,7 +33,7 @@ int main (int argc, char *argv[])
 
     /* ... */
 
-    err = rt_intr_create(&intr_desc,IRQ_NUMBER,I_AUTOENA);
+    err = rt_intr_create(&intr_desc,"MyIrq",IRQ_NUMBER,I_AUTOENA);
 
     /* ... */
 
diff -urp xenomai-shirq-edge/ksrc/skins/native/syscall.c xenomai-shirq-ext/ksrc/skins/native/syscall.c
--- xenomai-shirq-edge/ksrc/skins/native/syscall.c	2006-02-03 15:39:03.000000000 +0100
+++ xenomai-shirq-ext/ksrc/skins/native/syscall.c	2006-02-06 14:02:34.000000000 +0100
@@ -2936,7 +2936,7 @@ static int __rt_intr_create (struct task
     if (!intr)
 	return -ENOMEM;
 
-    err = rt_intr_create(intr,name,irq,&rt_intr_handler,NULL);
+    err = rt_intr_create(intr,name,irq,&rt_intr_handler,NULL,0);
 
     if (err == 0)
 	{
diff -urp xenomai-shirq-edge/ksrc/skins/rtdm/drvlib.c xenomai-shirq-ext/ksrc/skins/rtdm/drvlib.c
--- xenomai-shirq-edge/ksrc/skins/rtdm/drvlib.c	2006-01-30 19:47:13.000000000 +0100
+++ xenomai-shirq-ext/ksrc/skins/rtdm/drvlib.c	2006-02-05 19:48:02.000000000 +0100
@@ -1200,7 +1200,7 @@ EXPORT_SYMBOL(rtdm_mutex_unlock);
  * @param[in,out] irq_handle IRQ handle
  * @param[in] irq_no Line number of the addressed IRQ
  * @param[in] handler Interrupt handler
- * @param[in] flags Currently unused, pass 0
+ * @param[in] flags Registration flags, see @ref RTDM_IRQTYPE_xxx for details
  * @param[in] device_name Optional device name to show up in real-time IRQ
  * lists (not yet implemented)
  * @param[in] arg Pointer to be passed to the interrupt handler on invocation

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-07  9:04 [Xenomai-core] [Combo-PATCH] Shared interrupts (final) Dmitry Adamushko
@ 2006-02-07  9:58 ` Wolfgang Grandegger
  2006-02-07 17:58   ` Jan Kiszka
  2006-02-07 19:24   ` Dmitry Adamushko
  0 siblings, 2 replies; 25+ messages in thread
From: Wolfgang Grandegger @ 2006-02-07  9:58 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Hello,

Dmitry Adamushko wrote:
> 
> Hi,
> 
> this is the final set of patches against the SVN trunk of 2006-02-03.
> 
> It addresses mostly remarks concerning naming (XN_ISR_ISA -> 
> XN_ISR_EDGE), a few cleanups and updated comments.
> 
> Functionally, the support for shared interrupts (a few flags) to the 
> rtdm (Jan's patch) and native skin.
> In the later case, rt_intr_create() now contains the 6-th argument, 
> namely "int mode".
> 
> Now I'm waiting for the test results from Jan (the previous patch-set 
> remains to be suitable for testing too in case you are using it 
> already). Upon success, the new code is ready for merging.
> 
> the patches have to be applied as follows :
> - shirq-base
> - shirq-v8
> - shirq-proc
> - shirq-edge
> - shirq-ext
> 
> Happy testing ! :)

My concern is code size. I see that the patches add substantial amount 
of code to the ISR. What about make this feature configurable?

Wolfgang.

> -- 
> Best regards,
> Dmitry Adamushko
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Xenomai-core mailing list
> Xenomai-core@domain.hid
> https://mail.gna.org/listinfo/xenomai-core



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-07  9:58 ` Wolfgang Grandegger
@ 2006-02-07 17:58   ` Jan Kiszka
  2006-02-08  7:26     ` Wolfgang Grandegger
  2006-02-08 10:57     ` Philippe Gerum
  2006-02-07 19:24   ` Dmitry Adamushko
  1 sibling, 2 replies; 25+ messages in thread
From: Jan Kiszka @ 2006-02-07 17:58 UTC (permalink / raw)
  To: Wolfgang Grandegger, Dmitry Adamushko; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1847 bytes --]

Wolfgang Grandegger wrote:
> Hello,
> 
> Dmitry Adamushko wrote:
>>
>> Hi,
>>
>> this is the final set of patches against the SVN trunk of 2006-02-03.
>>
>> It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>> XN_ISR_EDGE), a few cleanups and updated comments.
>>
>> Functionally, the support for shared interrupts (a few flags) to the

Not directly your fault: the increasing number of return flags for IRQ
handlers makes me worry that they are used correctly. I can figure out
what they mean (not yet that clearly from the docs), but does someone
else understand all this:

- RT_INTR_HANDLED
- RT_INTR_CHAINED
- RT_INTR_ENABLE
- RT_INTR_NOINT

or

- RTDM_IRQ_PROPAGATE
- RTDM_IRQ_ENABLE
- RTDM_IRQ_NOINT

Third-party comments / suggestions welcome as well. Maybe I'm too
pessimistic.

>> rtdm (Jan's patch) and native skin.
>> In the later case, rt_intr_create() now contains the 6-th argument,
>> namely "int mode".
>>
>> Now I'm waiting for the test results from Jan (the previous patch-set
>> remains to be suitable for testing too in case you are using it
>> already). Upon success, the new code is ready for merging.

Trying to manage the priority list of someone else is tricky - I hope we
can see something soon, but I cannot promise anything.

>>
>> the patches have to be applied as follows :
>> - shirq-base
>> - shirq-v8
>> - shirq-proc
>> - shirq-edge
>> - shirq-ext
>>
>> Happy testing ! :)
> 
> My concern is code size. I see that the patches add substantial amount
> of code to the ISR. What about make this feature configurable?
> 

I would vote for the (already scheduled?) extension to register an
optimised IRQ trampoline in case there is actually no sharing taking
place. This would also make the "if (irq == XNARCH_TIMER_IRQ)" path
obsolete.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-07  9:58 ` Wolfgang Grandegger
  2006-02-07 17:58   ` Jan Kiszka
@ 2006-02-07 19:24   ` Dmitry Adamushko
  1 sibling, 0 replies; 25+ messages in thread
From: Dmitry Adamushko @ 2006-02-07 19:24 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1143 bytes --]

On 07/02/06, Wolfgang Grandegger <wg@domain.hid> wrote:
>
> Hello,
>
> > [skip-skip-skip]
> > Happy testing ! :)
>
> My concern is code size. I see that the patches add substantial amount
> of code to the ISR. What about make this feature configurable?


Yes, I though about making the new stuff optionally configurable.

But another option would be to leave the xnintr_irq_handler() as it was
before and to introduce a separate handler for the shared interrupts.
edge-triggeres interrupts already have the distinct handler
(xnintr_edgeirq_handler()).

I guess the additional code in xnintr_attach/detach() and a few (~1 for UP
and ~2 for SMP) KBs of data are not that critical taking into account where
and how they are used, both latency and cache-wise.


Wolfgang.
>
> > --
> > Best regards,
> > Dmitry Adamushko
> >
> >
> > ------------------------------------------------------------------------
> >
> > _______________________________________________
> > Xenomai-core mailing list
> > Xenomai-core@domain.hid
> > https://mail.gna.org/listinfo/xenomai-core
>
>

--
Best regards,
Dmitry Adamushko

[-- Attachment #2: Type: text/html, Size: 1759 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-07 17:58   ` Jan Kiszka
@ 2006-02-08  7:26     ` Wolfgang Grandegger
  2006-02-08  8:24       ` Jan Kiszka
  2006-02-08 10:57     ` Philippe Gerum
  1 sibling, 1 reply; 25+ messages in thread
From: Wolfgang Grandegger @ 2006-02-08  7:26 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Wolfgang Grandegger wrote:
>> Hello,
>>
>> Dmitry Adamushko wrote:
>>> Hi,
>>>
>>> this is the final set of patches against the SVN trunk of 2006-02-03.
>>>
>>> It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>>> XN_ISR_EDGE), a few cleanups and updated comments.
>>>
>>> Functionally, the support for shared interrupts (a few flags) to the
> 
> Not directly your fault: the increasing number of return flags for IRQ
> handlers makes me worry that they are used correctly. I can figure out
> what they mean (not yet that clearly from the docs), but does someone
> else understand all this:
> 
> - RT_INTR_HANDLED
> - RT_INTR_CHAINED
> - RT_INTR_ENABLE
> - RT_INTR_NOINT
> 
> or
> 
> - RTDM_IRQ_PROPAGATE
> - RTDM_IRQ_ENABLE
> - RTDM_IRQ_NOINT
> 
> Third-party comments / suggestions welcome as well. Maybe I'm too
> pessimistic.
> 
>>> rtdm (Jan's patch) and native skin.
>>> In the later case, rt_intr_create() now contains the 6-th argument,
>>> namely "int mode".
>>>
>>> Now I'm waiting for the test results from Jan (the previous patch-set
>>> remains to be suitable for testing too in case you are using it
>>> already). Upon success, the new code is ready for merging.
> 
> Trying to manage the priority list of someone else is tricky - I hope we
> can see something soon, but I cannot promise anything.
> 
>>> the patches have to be applied as follows :
>>> - shirq-base
>>> - shirq-v8
>>> - shirq-proc
>>> - shirq-edge
>>> - shirq-ext
>>>
>>> Happy testing ! :)
>> My concern is code size. I see that the patches add substantial amount
>> of code to the ISR. What about make this feature configurable?
>>
> 
> I would vote for the (already scheduled?) extension to register an
> optimised IRQ trampoline in case there is actually no sharing taking
> place. This would also make the "if (irq == XNARCH_TIMER_IRQ)" path
> obsolete.

I still prefer configuration options as they also allow to reduce the 
overall code size (less cache refills and TLB misses). And shared 
interrupts are for x86 only (approximately), I think. Unfortunately, I 
don't have the time to follow all the details of the rapid Xenomai 
development and can't therefore judge what is really necessary.

Wolfgang.

> Jan
> 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-08  7:26     ` Wolfgang Grandegger
@ 2006-02-08  8:24       ` Jan Kiszka
  2006-02-08 10:12         ` Dmitry Adamushko
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Kiszka @ 2006-02-08  8:24 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 2529 bytes --]

Wolfgang Grandegger wrote:
> Jan Kiszka wrote:
>> Wolfgang Grandegger wrote:
>>> Hello,
>>>
>>> Dmitry Adamushko wrote:
>>>> Hi,
>>>>
>>>> this is the final set of patches against the SVN trunk of 2006-02-03.
>>>>
>>>> It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>>>> XN_ISR_EDGE), a few cleanups and updated comments.
>>>>
>>>> Functionally, the support for shared interrupts (a few flags) to the
>>
>> Not directly your fault: the increasing number of return flags for IRQ
>> handlers makes me worry that they are used correctly. I can figure out
>> what they mean (not yet that clearly from the docs), but does someone
>> else understand all this:
>>
>> - RT_INTR_HANDLED
>> - RT_INTR_CHAINED
>> - RT_INTR_ENABLE
>> - RT_INTR_NOINT
>>
>> or
>>
>> - RTDM_IRQ_PROPAGATE
>> - RTDM_IRQ_ENABLE
>> - RTDM_IRQ_NOINT
>>
>> Third-party comments / suggestions welcome as well. Maybe I'm too
>> pessimistic.
>>
>>>> rtdm (Jan's patch) and native skin.
>>>> In the later case, rt_intr_create() now contains the 6-th argument,
>>>> namely "int mode".
>>>>
>>>> Now I'm waiting for the test results from Jan (the previous patch-set
>>>> remains to be suitable for testing too in case you are using it
>>>> already). Upon success, the new code is ready for merging.
>>
>> Trying to manage the priority list of someone else is tricky - I hope we
>> can see something soon, but I cannot promise anything.
>>
>>>> the patches have to be applied as follows :
>>>> - shirq-base
>>>> - shirq-v8
>>>> - shirq-proc
>>>> - shirq-edge
>>>> - shirq-ext
>>>>
>>>> Happy testing ! :)
>>> My concern is code size. I see that the patches add substantial amount
>>> of code to the ISR. What about make this feature configurable?
>>>
>>
>> I would vote for the (already scheduled?) extension to register an
>> optimised IRQ trampoline in case there is actually no sharing taking
>> place. This would also make the "if (irq == XNARCH_TIMER_IRQ)" path
>> obsolete.
> 
> I still prefer configuration options as they also allow to reduce the
> overall code size (less cache refills and TLB misses). And shared
> interrupts are for x86 only (approximately), I think. Unfortunately, I

Ok, that's a good argument. Then make the whole IRQ-sharing stuff
compile-time configurable and see how much we can save.

> don't have the time to follow all the details of the rapid Xenomai
> development and can't therefore judge what is really necessary.
> 
> Wolfgang.
> 

Jan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-08  8:24       ` Jan Kiszka
@ 2006-02-08 10:12         ` Dmitry Adamushko
  0 siblings, 0 replies; 25+ messages in thread
From: Dmitry Adamushko @ 2006-02-08 10:12 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai


[-- Attachment #1.1: Type: text/plain, Size: 876 bytes --]

On 08/02/06, Jan Kiszka <kiszka@domain.hid> wrote:

> I still prefer configuration options as they also allow to reduce the
> > overall code size (less cache refills and TLB misses). And shared
> > interrupts are for x86 only (approximately), I think. Unfortunately, I
>
> Ok, that's a good argument. Then make the whole IRQ-sharing stuff
> compile-time configurable and see how much we can save.



Anyway, I agree that the code which is supposed to be used by only a
fraction of users (Jan is only interested so far? and esp. in that
"brain-damaged" edge-triggered stuff) and which is a bit too heavy to
guarantee a close-to-zero-overhead should be made optional.

Ok, let's go for it upon getting the test results.

Enclosed a small optimization to reduce the code in (optional in future)
ISR.


Jan
>
>
>


--
Best regards,
Dmitry Adamushko

[-- Attachment #1.2: Type: text/html, Size: 1407 bytes --]

[-- Attachment #2: shirq-v9.patch --]
[-- Type: application/octet-stream, Size: 2467 bytes --]

diff -urp xenomai-shirq-ext/include/nucleus/intr.h xenomai-shirq-v9/include/nucleus/intr.h
--- xenomai-shirq-ext/include/nucleus/intr.h	2006-02-06 15:34:24.000000000 +0100
+++ xenomai-shirq-v9/include/nucleus/intr.h	2006-02-08 09:28:36.000000000 +0100
@@ -66,6 +66,8 @@ extern "C" {
 
 int xnintr_mount(void);
 
+void xnintr_clock_attach(xnintr_t *intr);
+void xnintr_clock_detach(xnintr_t *intr);
 void xnintr_clock_handler(void);
 
 int xnintr_irq_proc(unsigned int irq, char *str);
diff -urp xenomai-shirq-ext/ksrc/nucleus/intr.c xenomai-shirq-v9/ksrc/nucleus/intr.c
--- xenomai-shirq-ext/ksrc/nucleus/intr.c	2006-02-06 15:27:47.000000000 +0100
+++ xenomai-shirq-v9/ksrc/nucleus/intr.c	2006-02-08 09:27:29.000000000 +0100
@@ -502,6 +502,16 @@ xnarch_cpumask_t xnintr_affinity (xnintr
     return xnarch_set_irq_affinity(intr->irq,cpumask);
 }
 
+void xnintr_clock_attach(xnintr_t *intr)
+{
+    xnshirqs[intr->irq].handlers = intr;
+}
+
+void xnintr_clock_detach(xnintr_t *intr)
+{
+    xnshirqs[intr->irq].handlers = NULL;
+}
+
 /* Low-level clock irq handler. */
 
 void xnintr_clock_handler (void)
@@ -530,28 +540,19 @@ static void xnintr_irq_handler (unsigned
 
     ++sched->inesting;
 
-    if (irq == XNARCH_TIMER_IRQ)
-	{
-	intr = (xnintr_t*)cookie;
-	s = intr->isr(intr);
-	++intr->hits;
-	}
-    else
-	{
-	shirq = &xnshirqs[irq];
+    shirq = &xnshirqs[irq];
 
-	xnintr_shirq_lock(shirq);
-	intr = shirq->handlers;
+    xnintr_shirq_lock(shirq);
+    intr = shirq->handlers;
 
-	while (intr)
-	    {
-	    s |= intr->isr(intr);
-	    ++intr->hits;
+    while (intr)
+        {
+        s |= intr->isr(intr);
+        ++intr->hits;
 
-	    intr = intr->next;
-	    }
-	xnintr_shirq_unlock(shirq);
-	}
+        intr = intr->next;
+        }
+    xnintr_shirq_unlock(shirq);
 
     --sched->inesting;
 
diff -urp xenomai-shirq-ext/ksrc/nucleus/pod.c xenomai-shirq-v9/ksrc/nucleus/pod.c
--- xenomai-shirq-ext/ksrc/nucleus/pod.c	2006-02-03 15:41:50.000000000 +0100
+++ xenomai-shirq-v9/ksrc/nucleus/pod.c	2006-02-08 09:21:16.000000000 +0100
@@ -3044,6 +3044,7 @@ unlock_and_exit:
        (xnarch_start_timer). */
 
     xnintr_init(&nkclock,NULL,XNARCH_TIMER_IRQ,tickhandler,NULL,0);
+    xnintr_clock_attach(&nkclock);
 
     __setbits(nkpod->status,XNTIMED);
 
@@ -3130,6 +3131,8 @@ void xnpod_stop_timer (void)
 	xntimer_set_aperiodic_mode();
         }
 
+    xnintr_clock_detach(&nkclock);
+
  unlock_and_exit:
 
     xnlock_put_irqrestore(&nklock,s);


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-07 17:58   ` Jan Kiszka
  2006-02-08  7:26     ` Wolfgang Grandegger
@ 2006-02-08 10:57     ` Philippe Gerum
  2006-02-09  8:30       ` Anders Blomdell
  1 sibling, 1 reply; 25+ messages in thread
From: Philippe Gerum @ 2006-02-08 10:57 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Wolfgang Grandegger wrote:
> 
>>Hello,
>>
>>Dmitry Adamushko wrote:
>>
>>>Hi,
>>>
>>>this is the final set of patches against the SVN trunk of 2006-02-03.
>>>
>>>It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>>>XN_ISR_EDGE), a few cleanups and updated comments.
>>>
>>>Functionally, the support for shared interrupts (a few flags) to the
> 
> 
> Not directly your fault: the increasing number of return flags for IRQ
> handlers makes me worry that they are used correctly. I can figure out
> what they mean (not yet that clearly from the docs), but does someone
> else understand all this:
> 
> - RT_INTR_HANDLED

ISR says it has handled the IRQ, and does not want any propagation to take place 
down the pipeline. IOW, the IRQ processing stops there.

> - RT_INTR_CHAINED

ISR says it wants the IRQ to be propagated down the pipeline. Nothing is said 
about the fact that the last ISR did or did not handle the IRQ locally; this is 
irrelevant.

> - RT_INTR_ENABLE

ISR requests the interrupt dispatcher to re-enable the IRQ line upon return 
(cumulable with HANDLED/CHAINED).

> - RT_INTR_NOINT
> 

This new one comes from Dmitry's patch for shared IRQ support AFAICS. It would 
mean to continue processing the chain of handlers because the last ISR invoked was 
not concerned by the outstanding IRQ.

> or
> 
> - RTDM_IRQ_PROPAGATE
> - RTDM_IRQ_ENABLE
> - RTDM_IRQ_NOINT
> 
> Third-party comments / suggestions welcome as well. Maybe I'm too
> pessimistic.
> 
> 
>>>rtdm (Jan's patch) and native skin.
>>>In the later case, rt_intr_create() now contains the 6-th argument,
>>>namely "int mode".
>>>
>>>Now I'm waiting for the test results from Jan (the previous patch-set
>>>remains to be suitable for testing too in case you are using it
>>>already). Upon success, the new code is ready for merging.
> 
> 
> Trying to manage the priority list of someone else is tricky - I hope we
> can see something soon, but I cannot promise anything.
> 
> 
>>>the patches have to be applied as follows :
>>>- shirq-base
>>>- shirq-v8
>>>- shirq-proc
>>>- shirq-edge
>>>- shirq-ext
>>>
>>>Happy testing ! :)
>>
>>My concern is code size. I see that the patches add substantial amount
>>of code to the ISR. What about make this feature configurable?
>>
> 
> 
> I would vote for the (already scheduled?) extension to register an
> optimised IRQ trampoline in case there is actually no sharing taking
> place. This would also make the "if (irq == XNARCH_TIMER_IRQ)" path
> obsolete.

I support that. Shared interrupts should be handled properly by Xeno since such - 
I'd say "last resort" - configuration could be needed; this said, we should not 
see this as the rule but rather as the exception, since this is basically required 
to solve some underlying hw limitations wrt interrupt management, and definitely 
has a significant cost on processing each shared IRQ wrt determinism.

Incidentally, there is an interesting optimization on the project's todo list that 
would allow non-RT interrupts to be masked at IC level when the Xenomai domain is 
active. We could do that on any arch with civilized interrupt management, and that 
would prevent any asynchronous diversion from the critical code when Xenomai is 
running RT tasks (kernel or user-space). Think of this as some hw-controlled 
interrupt shield. Since this feature requires to be able to individually mask each 
interrupt source at IC level, there should be no point in sharing fully vectored 
interrupts in such a configuration anyway. This fact also pleads for having the 
shared IRQ support as a build-time option.

> 
> Jan
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Xenomai-core mailing list
> Xenomai-core@domain.hid
> https://mail.gna.org/listinfo/xenomai-core


-- 

Philippe.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-08 10:57     ` Philippe Gerum
@ 2006-02-09  8:30       ` Anders Blomdell
  2006-02-09  9:11         ` Jan Kiszka
  2006-02-09  9:59         ` Philippe Gerum
  0 siblings, 2 replies; 25+ messages in thread
From: Anders Blomdell @ 2006-02-09  8:30 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai

Philippe Gerum wrote:
> Jan Kiszka wrote:
> 
>> Wolfgang Grandegger wrote:
>>
>>> Hello,
>>>
>>> Dmitry Adamushko wrote:
>>>
>>>> Hi,
>>>>
>>>> this is the final set of patches against the SVN trunk of 2006-02-03.
>>>>
>>>> It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>>>> XN_ISR_EDGE), a few cleanups and updated comments.
>>>>
>>>> Functionally, the support for shared interrupts (a few flags) to the
>>
>>
>>
>> Not directly your fault: the increasing number of return flags for IRQ
>> handlers makes me worry that they are used correctly. I can figure out
>> what they mean (not yet that clearly from the docs), but does someone
>> else understand all this:
>>
>> - RT_INTR_HANDLED
> 
> 
> ISR says it has handled the IRQ, and does not want any propagation to 
> take place down the pipeline. IOW, the IRQ processing stops there.
This says that the interrupt will be ->end'ed at some later time (perhaps in the 
interrupt handler task)

>> - RT_INTR_CHAINED
> 
> 
> ISR says it wants the IRQ to be propagated down the pipeline. Nothing is 
> said about the fact that the last ISR did or did not handle the IRQ 
> locally; this is irrelevant.
This says that the interrupt will eventually be ->end'ed by some later stage in 
the pipeline.

>> - RT_INTR_ENABLE
> 
> 
> ISR requests the interrupt dispatcher to re-enable the IRQ line upon 
> return (cumulable with HANDLED/CHAINED).
This says that the interrupt will be ->end'ed when this interrupt handler returns.

> 
>> - RT_INTR_NOINT
>>
> 
> This new one comes from Dmitry's patch for shared IRQ support AFAICS. It 
> would mean to continue processing the chain of handlers because the last 
> ISR invoked was not concerned by the outstanding IRQ.
Sounds like RT_INTR_CHAINED, except that it's for the current pipeline stage?

Now for the quiz question (powerpc arch):

   1. Assume an edge triggered interrupt
   2. The RT-handler returns RT_INTR_ENABLE | RT_INTR_ENABLE (i.e. shared
      interrupt, but no problem since it's edge-triggered)
   3. Interrupt gets ->end'ed right after RT-handler has returned
   4. Linux interrupt eventually handler starts its ->end() handler:
         local_irq_save_hw(flags);
         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
           ipipe_irq_unlock(irq);
	// Next interrupt occurs here!
         __ipipe_std_irq_dtype[irq].end(irq);
         local_irq_restore_hw(flags);


Wouldn't this lead to a lost interrupt? Or am I overly paranoid?
My distinct feeling is that the return value should be a scalar and not a set!
>...
>> I would vote for the (already scheduled?) extension to register an
>> optimised IRQ trampoline in case there is actually no sharing taking
>> place. This would also make the "if (irq == XNARCH_TIMER_IRQ)" path
>> obsolete.
> 
> 
> I support that. Shared interrupts should be handled properly by Xeno 
> since such - I'd say "last resort" - configuration could be needed; this 
> said, we should not see this as the rule but rather as the exception, 
> since this is basically required to solve some underlying hw limitations 
> wrt interrupt management, and definitely has a significant cost on 
> processing each shared IRQ wrt determinism.
> 
> Incidentally, there is an interesting optimization on the project's todo 
> list 
Is this todo list accessible anywhere?

 > that would allow non-RT interrupts to be masked at IC level when
> the Xenomai domain is active. We could do that on any arch with 
> civilized interrupt management, and that would prevent any asynchronous 
> diversion from the critical code when Xenomai is running RT tasks 
> (kernel or user-space). Think of this as some hw-controlled interrupt 
> shield. Since this feature requires to be able to individually mask each 
> interrupt source at IC level, there should be no point in sharing fully 
> vectored interrupts in such a configuration anyway. This fact also 
> pleads for having the shared IRQ support as a build-time option.

-- 
Anders Blomdell


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-09  8:30       ` Anders Blomdell
@ 2006-02-09  9:11         ` Jan Kiszka
  2006-02-09 10:07           ` Philippe Gerum
  2006-02-09  9:59         ` Philippe Gerum
  1 sibling, 1 reply; 25+ messages in thread
From: Jan Kiszka @ 2006-02-09  9:11 UTC (permalink / raw)
  To: Anders Blomdell; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 4891 bytes --]

Anders Blomdell wrote:
> Philippe Gerum wrote:
>> Jan Kiszka wrote:
>>
>>> Wolfgang Grandegger wrote:
>>>
>>>> Hello,
>>>>
>>>> Dmitry Adamushko wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> this is the final set of patches against the SVN trunk of 2006-02-03.
>>>>>
>>>>> It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>>>>> XN_ISR_EDGE), a few cleanups and updated comments.
>>>>>
>>>>> Functionally, the support for shared interrupts (a few flags) to the
>>>
>>>
>>>
>>> Not directly your fault: the increasing number of return flags for IRQ
>>> handlers makes me worry that they are used correctly. I can figure out
>>> what they mean (not yet that clearly from the docs), but does someone
>>> else understand all this:
>>>
>>> - RT_INTR_HANDLED
>>
>>
>> ISR says it has handled the IRQ, and does not want any propagation to
>> take place down the pipeline. IOW, the IRQ processing stops there.
> This says that the interrupt will be ->end'ed at some later time
> (perhaps in the interrupt handler task)
> 
>>> - RT_INTR_CHAINED
>>
>>
>> ISR says it wants the IRQ to be propagated down the pipeline. Nothing
>> is said about the fact that the last ISR did or did not handle the IRQ
>> locally; this is irrelevant.
> This says that the interrupt will eventually be ->end'ed by some later
> stage in the pipeline.
> 
>>> - RT_INTR_ENABLE
>>
>>
>> ISR requests the interrupt dispatcher to re-enable the IRQ line upon
>> return (cumulable with HANDLED/CHAINED).
> This says that the interrupt will be ->end'ed when this interrupt
> handler returns.
> 
>>
>>> - RT_INTR_NOINT
>>>
>>
>> This new one comes from Dmitry's patch for shared IRQ support AFAICS.
>> It would mean to continue processing the chain of handlers because the
>> last ISR invoked was not concerned by the outstanding IRQ.
> Sounds like RT_INTR_CHAINED, except that it's for the current pipeline
> stage?
> 
> Now for the quiz question (powerpc arch):
> 
>   1. Assume an edge triggered interrupt
>   2. The RT-handler returns RT_INTR_ENABLE | RT_INTR_ENABLE (i.e. shared

Kind of redundant. What did you really mean?

>      interrupt, but no problem since it's edge-triggered)
>   3. Interrupt gets ->end'ed right after RT-handler has returned
>   4. Linux interrupt eventually handler starts its ->end() handler:
>         local_irq_save_hw(flags);
>         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
>           ipipe_irq_unlock(irq);
>     // Next interrupt occurs here!
>         __ipipe_std_irq_dtype[irq].end(irq);
>         local_irq_restore_hw(flags);
> 
> 
> Wouldn't this lead to a lost interrupt? Or am I overly paranoid?
> My distinct feeling is that the return value should be a scalar and not
> a set!

That's a good idea: only provide valid and reasonable flag combinations
to the user!

>> ...
>>> I would vote for the (already scheduled?) extension to register an
>>> optimised IRQ trampoline in case there is actually no sharing taking
>>> place. This would also make the "if (irq == XNARCH_TIMER_IRQ)" path
>>> obsolete.
>>
>>
>> I support that. Shared interrupts should be handled properly by Xeno
>> since such - I'd say "last resort" - configuration could be needed;
>> this said, we should not see this as the rule but rather as the
>> exception, since this is basically required to solve some underlying
>> hw limitations wrt interrupt management, and definitely has a
>> significant cost on processing each shared IRQ wrt determinism.
>>
>> Incidentally, there is an interesting optimization on the project's
>> todo list 
> Is this todo list accessible anywhere?

I did not know of such interesting plans as well. Maybe we should start
using more of the feature GNA provide to us (task lists?)...

> 
>> that would allow non-RT interrupts to be masked at IC level when
>> the Xenomai domain is active. We could do that on any arch with
>> civilized interrupt management, and that would prevent any
>> asynchronous diversion from the critical code when Xenomai is running
>> RT tasks (kernel or user-space). Think of this as some hw-controlled
>> interrupt shield. Since this feature requires to be able to
>> individually mask each interrupt source at IC level, there should be
>> no point in sharing fully vectored interrupts in such a configuration
>> anyway. This fact also pleads for having the shared IRQ support as a
>> build-time option.
> 

This concept sound really thrilling. I already wondered if this is
possible after seeing how many non-RT IRQ stubs can hit between an RT
event and the RT task invocation: HD, network, keyboard, mouse, sound,
graphic card - and if you are "lucky", a lot of them chain up at the
same time. But I thought that such disabling is too costly for being
used at every domain switch. Is it not?

Jan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-09  8:30       ` Anders Blomdell
  2006-02-09  9:11         ` Jan Kiszka
@ 2006-02-09  9:59         ` Philippe Gerum
  2006-02-09 10:19           ` Jan Kiszka
  2006-02-09 10:43           ` Anders Blomdell
  1 sibling, 2 replies; 25+ messages in thread
From: Philippe Gerum @ 2006-02-09  9:59 UTC (permalink / raw)
  To: Anders Blomdell; +Cc: xenomai

Anders Blomdell wrote:
> Philippe Gerum wrote:
> 
>> Jan Kiszka wrote:
>>
>>> Wolfgang Grandegger wrote:
>>>
>>>> Hello,
>>>>
>>>> Dmitry Adamushko wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> this is the final set of patches against the SVN trunk of 2006-02-03.
>>>>>
>>>>> It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>>>>> XN_ISR_EDGE), a few cleanups and updated comments.
>>>>>
>>>>> Functionally, the support for shared interrupts (a few flags) to the
>>>
>>>
>>>
>>>
>>> Not directly your fault: the increasing number of return flags for IRQ
>>> handlers makes me worry that they are used correctly. I can figure out
>>> what they mean (not yet that clearly from the docs), but does someone
>>> else understand all this:
>>>
>>> - RT_INTR_HANDLED
>>
>>
>>
>> ISR says it has handled the IRQ, and does not want any propagation to 
>> take place down the pipeline. IOW, the IRQ processing stops there.
> 
> This says that the interrupt will be ->end'ed at some later time 
> (perhaps in the interrupt handler task)
> 

The ISR may end the IRQ before returning, or leave it to the nucleus upon return 
by adding the ENABLE bit.

>>> - RT_INTR_CHAINED
>>
>>
>>
>> ISR says it wants the IRQ to be propagated down the pipeline. Nothing 
>> is said about the fact that the last ISR did or did not handle the IRQ 
>> locally; this is irrelevant.
> 
> This says that the interrupt will eventually be ->end'ed by some later 
> stage in the pipeline.
> 
>>> - RT_INTR_ENABLE
>>
>>
>>
>> ISR requests the interrupt dispatcher to re-enable the IRQ line upon 
>> return (cumulable with HANDLED/CHAINED).
> 

This is wrong; we should only associate this to HANDLED; sorry.

> This says that the interrupt will be ->end'ed when this interrupt 
> handler returns.
> 
>>
>>> - RT_INTR_NOINT
>>>
>>
>> This new one comes from Dmitry's patch for shared IRQ support AFAICS. 
>> It would mean to continue processing the chain of handlers because the 
>> last ISR invoked was not concerned by the outstanding IRQ.
> 
> Sounds like RT_INTR_CHAINED, except that it's for the current pipeline 
> stage?
> 

Basically, yes.

> Now for the quiz question (powerpc arch):
> 
>   1. Assume an edge triggered interrupt
>   2. The RT-handler returns RT_INTR_ENABLE | RT_INTR_ENABLE (i.e. shared
>      interrupt, but no problem since it's edge-triggered)

( Assuming RT_INTR_CHAINED | RT_INTR_ENABLE )

>   3. Interrupt gets ->end'ed right after RT-handler has returned
>   4. Linux interrupt eventually handler starts its ->end() handler:
>         local_irq_save_hw(flags);
>         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
>           ipipe_irq_unlock(irq);
>     // Next interrupt occurs here!

It can't occur here: hw interrupts are off after local_irq_save_hw, and unlocking 
some IRQ does not flush the IRQ log.

>         __ipipe_std_irq_dtype[irq].end(irq);
>         local_irq_restore_hw(flags);
> 
> 
> Wouldn't this lead to a lost interrupt? Or am I overly paranoid?

This could happen, yep. Actually, this would be a possible misuse of the ISR 
return values.
If one chains the handler Adeos-wise, it is expected to leave the IC in its 
original state wrt the processed interrupt. CHAINED should be seen as mutually 
exclusive with ENABLE.

> My distinct feeling is that the return value should be a scalar and not 
> a set!
> 

To sum up, the valid return values are HANDLED, HANDLED | ENABLE (*), HANDLED | 
CHAINED and CHAINED. It's currently a set because I once thought that the 
"handled" indication (or lack of) could be a valuable information to gather at 
nucleus level to detect unhandled RT interrupts. Fact is that we currently don't 
use this information, though. IOW, we could indeed define some enum and have a 
scalar there instead of a set; or we could just leave this as a set, but whine 
when detecting the invalid ENABLE | CHAINED combination.

(*) because the handler does not necessary know how to ->end() the current IRQ at 
IC level, but Xenomai always does.

>> ...
>>
>>> I would vote for the (already scheduled?) extension to register an
>>> optimised IRQ trampoline in case there is actually no sharing taking
>>> place. This would also make the "if (irq == XNARCH_TIMER_IRQ)" path
>>> obsolete.
>>
>>
>>
>> I support that. Shared interrupts should be handled properly by Xeno 
>> since such - I'd say "last resort" - configuration could be needed; 
>> this said, we should not see this as the rule but rather as the 
>> exception, since this is basically required to solve some underlying 
>> hw limitations wrt interrupt management, and definitely has a 
>> significant cost on processing each shared IRQ wrt determinism.
>>
>> Incidentally, there is an interesting optimization on the project's 
>> todo list 
> 
> Is this todo list accessible anywhere?
> 

There's a roadmap for v2.1 that has been posted to the -core list in 
October/November. Aside of that, the todos are not maintained in a centralized and 
accessible way yet. We could perhaps use GNA's task manager for that 
(http://gna.org/task/?group=xenomai), even if not to the full extent of its features.

>  > that would allow non-RT interrupts to be masked at IC level when
> 
>> the Xenomai domain is active. We could do that on any arch with 
>> civilized interrupt management, and that would prevent any 
>> asynchronous diversion from the critical code when Xenomai is running 
>> RT tasks (kernel or user-space). Think of this as some hw-controlled 
>> interrupt shield. Since this feature requires to be able to 
>> individually mask each interrupt source at IC level, there should be 
>> no point in sharing fully vectored interrupts in such a configuration 
>> anyway. This fact also pleads for having the shared IRQ support as a 
>> build-time option.
> 
> 


-- 

Philippe.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-09  9:11         ` Jan Kiszka
@ 2006-02-09 10:07           ` Philippe Gerum
  0 siblings, 0 replies; 25+ messages in thread
From: Philippe Gerum @ 2006-02-09 10:07 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Anders Blomdell wrote:
> 
>>Philippe Gerum wrote:
>>
>>>Jan Kiszka wrote:
>>>
>>>
>>>>Wolfgang Grandegger wrote:
>>>>
>>>>
>>>>>Hello,
>>>>>
>>>>>Dmitry Adamushko wrote:
>>>>>
>>>>>
>>>>>>Hi,
>>>>>>
>>>>>>this is the final set of patches against the SVN trunk of 2006-02-03.
>>>>>>
>>>>>>It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>>>>>>XN_ISR_EDGE), a few cleanups and updated comments.
>>>>>>
>>>>>>Functionally, the support for shared interrupts (a few flags) to the
>>>>
>>>>
>>>>
>>>>Not directly your fault: the increasing number of return flags for IRQ
>>>>handlers makes me worry that they are used correctly. I can figure out
>>>>what they mean (not yet that clearly from the docs), but does someone
>>>>else understand all this:
>>>>
>>>>- RT_INTR_HANDLED
>>>
>>>
>>>ISR says it has handled the IRQ, and does not want any propagation to
>>>take place down the pipeline. IOW, the IRQ processing stops there.
>>
>>This says that the interrupt will be ->end'ed at some later time
>>(perhaps in the interrupt handler task)
>>
>>
>>>>- RT_INTR_CHAINED
>>>
>>>
>>>ISR says it wants the IRQ to be propagated down the pipeline. Nothing
>>>is said about the fact that the last ISR did or did not handle the IRQ
>>>locally; this is irrelevant.
>>
>>This says that the interrupt will eventually be ->end'ed by some later
>>stage in the pipeline.
>>
>>
>>>>- RT_INTR_ENABLE
>>>
>>>
>>>ISR requests the interrupt dispatcher to re-enable the IRQ line upon
>>>return (cumulable with HANDLED/CHAINED).
>>
>>This says that the interrupt will be ->end'ed when this interrupt
>>handler returns.
>>
>>
>>>>- RT_INTR_NOINT
>>>>
>>>
>>>This new one comes from Dmitry's patch for shared IRQ support AFAICS.
>>>It would mean to continue processing the chain of handlers because the
>>>last ISR invoked was not concerned by the outstanding IRQ.
>>
>>Sounds like RT_INTR_CHAINED, except that it's for the current pipeline
>>stage?
>>
>>Now for the quiz question (powerpc arch):
>>
>>  1. Assume an edge triggered interrupt
>>  2. The RT-handler returns RT_INTR_ENABLE | RT_INTR_ENABLE (i.e. shared
> 
> 
> Kind of redundant. What did you really mean?
> 
> 
>>     interrupt, but no problem since it's edge-triggered)
>>  3. Interrupt gets ->end'ed right after RT-handler has returned
>>  4. Linux interrupt eventually handler starts its ->end() handler:
>>        local_irq_save_hw(flags);
>>        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
>>          ipipe_irq_unlock(irq);
>>    // Next interrupt occurs here!
>>        __ipipe_std_irq_dtype[irq].end(irq);
>>        local_irq_restore_hw(flags);
>>
>>
>>Wouldn't this lead to a lost interrupt? Or am I overly paranoid?
>>My distinct feeling is that the return value should be a scalar and not
>>a set!
> 
> 
> That's a good idea: only provide valid and reasonable flag combinations
> to the user!
> 
> 
>>>...
>>>
>>>>I would vote for the (already scheduled?) extension to register an
>>>>optimised IRQ trampoline in case there is actually no sharing taking
>>>>place. This would also make the "if (irq == XNARCH_TIMER_IRQ)" path
>>>>obsolete.
>>>
>>>
>>>I support that. Shared interrupts should be handled properly by Xeno
>>>since such - I'd say "last resort" - configuration could be needed;
>>>this said, we should not see this as the rule but rather as the
>>>exception, since this is basically required to solve some underlying
>>>hw limitations wrt interrupt management, and definitely has a
>>>significant cost on processing each shared IRQ wrt determinism.
>>>
>>>Incidentally, there is an interesting optimization on the project's
>>>todo list 
>>
>>Is this todo list accessible anywhere?
> 
> 
> I did not know of such interesting plans as well. Maybe we should start
> using more of the feature GNA provide to us (task lists?)...
> 
> 
>>>that would allow non-RT interrupts to be masked at IC level when
>>>the Xenomai domain is active. We could do that on any arch with
>>>civilized interrupt management, and that would prevent any
>>>asynchronous diversion from the critical code when Xenomai is running
>>>RT tasks (kernel or user-space). Think of this as some hw-controlled
>>>interrupt shield. Since this feature requires to be able to
>>>individually mask each interrupt source at IC level, there should be
>>>no point in sharing fully vectored interrupts in such a configuration
>>>anyway. This fact also pleads for having the shared IRQ support as a
>>>build-time option.
>>
> 
> This concept sound really thrilling. I already wondered if this is
> possible after seeing how many non-RT IRQ stubs can hit between an RT
> event and the RT task invocation: HD, network, keyboard, mouse, sound,
> graphic card - and if you are "lucky", a lot of them chain up at the
> same time. But I thought that such disabling is too costly for being
> used at every domain switch. Is it not?
>

It all depends on the underlying arch. I started to think about this when working
with the Blackfin, which provides an efficient and fine-grained control over the 
interrupt system (hey, it's a DSP after all). Anders recently brought up the issue 
too, waking up the sleeper. Of course, one would not want to try that with a 8259 
chip over x86...

> Jan
> 
> 


-- 

Philippe.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-09  9:59         ` Philippe Gerum
@ 2006-02-09 10:19           ` Jan Kiszka
  2006-02-09 11:11             ` Dmitry Adamushko
  2006-02-09 11:14             ` [Xenomai-core] [Combo-PATCH] Shared interrupts (final) Philippe Gerum
  2006-02-09 10:43           ` Anders Blomdell
  1 sibling, 2 replies; 25+ messages in thread
From: Jan Kiszka @ 2006-02-09 10:19 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1335 bytes --]

Philippe Gerum wrote:
> Anders Blomdell wrote:
> 
>> My distinct feeling is that the return value should be a scalar and
>> not a set!
>>
> 
> To sum up, the valid return values are HANDLED, HANDLED | ENABLE (*),
> HANDLED | CHAINED and CHAINED. It's currently a set because I once
> thought that the "handled" indication (or lack of) could be a valuable
> information to gather at nucleus level to detect unhandled RT
> interrupts. Fact is that we currently don't use this information,

But it is required for the edge-triggered case to detect when the IRQ
line was at least shortly released. I guess Dmitry introduced that NOINT
just because HANDLED equals 0 so far. As I would say HANDLED == !NOINT,
we could avoid this new flag by just making HANDLED non-zero.

> though. IOW, we could indeed define some enum and have a scalar there
> instead of a set; or we could just leave this as a set, but whine when
> detecting the invalid ENABLE | CHAINED combination.

In combination with the change above and some doc improvement ("valid
combinations are: ..."), I could also live with keeping the flags. The
advantage were that we wouldn't break existing applications.

> 
> (*) because the handler does not necessary know how to ->end() the
> current IRQ at IC level, but Xenomai always does.
> 

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-09  9:59         ` Philippe Gerum
  2006-02-09 10:19           ` Jan Kiszka
@ 2006-02-09 10:43           ` Anders Blomdell
  1 sibling, 0 replies; 25+ messages in thread
From: Anders Blomdell @ 2006-02-09 10:43 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai

Philippe Gerum wrote:
> Anders Blomdell wrote:
> 
>> Philippe Gerum wrote:
>>
>>> Jan Kiszka wrote:
>>>
>>>> Wolfgang Grandegger wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> Dmitry Adamushko wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> this is the final set of patches against the SVN trunk of 2006-02-03.
>>>>>>
>>>>>> It addresses mostly remarks concerning naming (XN_ISR_ISA ->
>>>>>> XN_ISR_EDGE), a few cleanups and updated comments.
>>>>>>
>>>>>> Functionally, the support for shared interrupts (a few flags) to the
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> Not directly your fault: the increasing number of return flags for IRQ
>>>> handlers makes me worry that they are used correctly. I can figure out
>>>> what they mean (not yet that clearly from the docs), but does someone
>>>> else understand all this:
>>>>
>>>> - RT_INTR_HANDLED
>>>
>>>
>>>
>>>
>>> ISR says it has handled the IRQ, and does not want any propagation to 
>>> take place down the pipeline. IOW, the IRQ processing stops there.
>>
>>
>> This says that the interrupt will be ->end'ed at some later time 
>> (perhaps in the interrupt handler task)
>>
> 
> The ISR may end the IRQ before returning, or leave it to the nucleus 
> upon return by adding the ENABLE bit.
> 
>>>> - RT_INTR_CHAINED
>>>
>>>
>>>
>>>
>>> ISR says it wants the IRQ to be propagated down the pipeline. Nothing 
>>> is said about the fact that the last ISR did or did not handle the 
>>> IRQ locally; this is irrelevant.
>>
>>
>> This says that the interrupt will eventually be ->end'ed by some later 
>> stage in the pipeline.
>>
>>>> - RT_INTR_ENABLE
>>>
>>>
>>>
>>>
>>> ISR requests the interrupt dispatcher to re-enable the IRQ line upon 
>>> return (cumulable with HANDLED/CHAINED).
>>
>>
> 
> This is wrong; we should only associate this to HANDLED; sorry.
> 
>> This says that the interrupt will be ->end'ed when this interrupt 
>> handler returns.
>>
>>>
>>>> - RT_INTR_NOINT
>>>>
>>>
>>> This new one comes from Dmitry's patch for shared IRQ support AFAICS. 
>>> It would mean to continue processing the chain of handlers because 
>>> the last ISR invoked was not concerned by the outstanding IRQ.
>>
>>
>> Sounds like RT_INTR_CHAINED, except that it's for the current pipeline 
>> stage?
>>
> 
> Basically, yes.
> 
>> Now for the quiz question (powerpc arch):
>>
>>   1. Assume an edge triggered interrupt
>>   2. The RT-handler returns RT_INTR_ENABLE | RT_INTR_ENABLE (i.e. shared
>>      interrupt, but no problem since it's edge-triggered)
> 
> 
> ( Assuming RT_INTR_CHAINED | RT_INTR_ENABLE )
> 
>>   3. Interrupt gets ->end'ed right after RT-handler has returned
>>   4. Linux interrupt eventually handler starts its ->end() handler:
>>         local_irq_save_hw(flags);
>>         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
>>           ipipe_irq_unlock(irq);
>>     // Next interrupt occurs here!
> 
> 
> It can't occur here: hw interrupts are off after local_irq_save_hw, and 
> unlocking some IRQ does not flush the IRQ log.
> 
>>         __ipipe_std_irq_dtype[irq].end(irq);
>>         local_irq_restore_hw(flags);
>>
>>
>> Wouldn't this lead to a lost interrupt? Or am I overly paranoid?
> 
> 
> This could happen, yep. Actually, this would be a possible misuse of the 
> ISR return values.
> If one chains the handler Adeos-wise, it is expected to leave the IC in 
> its original state wrt the processed interrupt. CHAINED should be seen 
> as mutually exclusive with ENABLE.
> 
>> My distinct feeling is that the return value should be a scalar and 
>> not a set!
>>
> 
> To sum up, the valid return values are HANDLED, HANDLED | ENABLE (*), 
> HANDLED | CHAINED and CHAINED. It's currently a set because I once 
> thought that the "handled" indication (or lack of) could be a valuable 
> information to gather at nucleus level to detect unhandled RT 
> interrupts. Fact is that we currently don't use this information, 
> though. IOW, we could indeed define some enum and have a scalar there 
> instead of a set; or we could just leave this as a set, but whine when 
> detecting the invalid ENABLE | CHAINED combination.

agile_programmer_mode_off();
realtime_programmer_hat_on();

I prefer programming errors to show up at compile time!

goto todays_work;

// Will never come here :-(
realtime_programmer_hat_off();
agile_programmer_mode_on();

-- 

Anders


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-09 10:19           ` Jan Kiszka
@ 2006-02-09 11:11             ` Dmitry Adamushko
  2006-02-09 15:46               ` [Xenomai-core] More on Shared interrupts Anders Blomdell
  2006-02-09 11:14             ` [Xenomai-core] [Combo-PATCH] Shared interrupts (final) Philippe Gerum
  1 sibling, 1 reply; 25+ messages in thread
From: Dmitry Adamushko @ 2006-02-09 11:11 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1666 bytes --]

On 09/02/06, Jan Kiszka <jan.kiszka@domain.hid> wrote:
>
> Philippe Gerum wrote:
> > Anders Blomdell wrote:
> >
> >> My distinct feeling is that the return value should be a scalar and
> >> not a set!
> >>
> >
> > To sum up, the valid return values are HANDLED, HANDLED | ENABLE (*),
> > HANDLED | CHAINED and CHAINED. It's currently a set because I once
> > thought that the "handled" indication (or lack of) could be a valuable
> > information to gather at nucleus level to detect unhandled RT
> > interrupts. Fact is that we currently don't use this information,
>
> But it is required for the edge-triggered case to detect when the IRQ
> line was at least shortly released. I guess Dmitry introduced that NOINT
> just because HANDLED equals 0 so far. As I would say HANDLED == !NOINT,
> we could avoid this new flag by just making HANDLED non-zero.


That's it.

I was about to make a comment on Philipe's list of possible return values,
but you outrun me.

HANDLED is 0 so we can not distinguish between HANDLED | CHAINED and CHAINED
cases. NOINT denotes explicitly the handler's answer "this IRQ is rised not
by my hw!" and it's needed (at least) for implementing the edge-triggered
irq sharing.

It's not necessary in case HANDLED becomes non-zero and, actually, HANDLED
is not necessary with NOINT.

As I may see, Philipe's list can be mapped as follows :

HANDLED  ->  0
HANDLED | ENABLE  ->  ENABLE
HANDLED | CHAINED ->  CHAINED
CHAINED                   ->  CHAINED | NOINT

and

NOINT as a separete use case (?). Could be useful at least for the
edge-triggered stuff.


--
Best regards,
Dmitry Adamushko

[-- Attachment #2: Type: text/html, Size: 2229 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] [Combo-PATCH] Shared interrupts (final)
  2006-02-09 10:19           ` Jan Kiszka
  2006-02-09 11:11             ` Dmitry Adamushko
@ 2006-02-09 11:14             ` Philippe Gerum
  1 sibling, 0 replies; 25+ messages in thread
From: Philippe Gerum @ 2006-02-09 11:14 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Philippe Gerum wrote:
> 
>>Anders Blomdell wrote:
>>
>>
>>>My distinct feeling is that the return value should be a scalar and
>>>not a set!
>>>
>>
>>To sum up, the valid return values are HANDLED, HANDLED | ENABLE (*),
>>HANDLED | CHAINED and CHAINED. It's currently a set because I once
>>thought that the "handled" indication (or lack of) could be a valuable
>>information to gather at nucleus level to detect unhandled RT
>>interrupts. Fact is that we currently don't use this information,
> 
> 
> But it is required for the edge-triggered case to detect when the IRQ
> line was at least shortly released. I guess Dmitry introduced that NOINT
> just because HANDLED equals 0 so far. As I would say HANDLED == !NOINT,
> we could avoid this new flag by just making HANDLED non-zero.
> 

Yes, we could. HANDLED is currently zero only because the nucleus does not care of 
the !handled case, yet.

> 
>>though. IOW, we could indeed define some enum and have a scalar there
>>instead of a set; or we could just leave this as a set, but whine when
>>detecting the invalid ENABLE | CHAINED combination.
> 
> 
> In combination with the change above and some doc improvement ("valid
> combinations are: ..."), I could also live with keeping the flags. The
> advantage were that we wouldn't break existing applications.
> 
> 
>>(*) because the handler does not necessary know how to ->end() the
>>current IRQ at IC level, but Xenomai always does.
>>
> 
> 
> Jan
> 


-- 

Philippe.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Xenomai-core] More on Shared interrupts
  2006-02-09 11:11             ` Dmitry Adamushko
@ 2006-02-09 15:46               ` Anders Blomdell
  2006-02-09 16:39                 ` Jan Kiszka
                                   ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Anders Blomdell @ 2006-02-09 15:46 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: Jan Kiszka, xenomai

For the last few days, I have tried to figure out a good way to share interrupts 
between RT and non-RT domains. This has included looking through Dmitry's patch, 
correcting bugs and testing what is possible in my specific case. I'll therefore 
try to summarize at least a few of my thoughts.

1. When looking through Dmitry's patch I get the impression that the iack 
handler has very little to do with each interrupt (the test 'prev->iack != 
intr->iack' is a dead giveaway), but is more of a domain-specific function (or 
perhaps even just a placeholder for the hijacked Linux ack-function).


2. Somewhat inspired by the figure in "Life with Adeos", I have identified the 
following cases:

   irq K  | ----------- | ---o    |   // Linux only
   ...
   irq L  | ---o        |         |   // RT-only
   ...
   irq M  | ---o------- | ---o    |   // Shared between domains
   ...
   irq N  | ---o---o--- |         |   // Shared inside single domain
   ...
   irq O  | ---o---o--- | ---o    |   // Shared between and inside single domain

Xenomai currently handles the K & L cases, Dmitrys patch addresses the N case, 
with edge triggered interrupts the M (and O after Dmitry's patch) case(s) might 
be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE from the interrupt 
handler, for level triggered interrupt the M and O cases can't be handled.

If one looks more closely at the K case (Linux only interrupt), it works by when 
an interrupt occurs, the call to irq_end is postponed until the Linux interrupt 
handler has run, i.e. further interrupts are disabled. This can be seen as a 
lazy version of Philippe's idea of disabling all non-RT interrupts until the 
RT-domain is idle, i.e. the interrupt is disabled only if it indeed occurs.

If this idea should be generalized to the M (and O) case(s), one can't rely on 
postponing the irq_end call (since the interrupt is still needed in the 
RT-domain), but has to rely on some function that disables all non-RT hardware 
that generates interrupts on that irq-line; such a function naturally has to 
have intimate knowledge of all hardware that can generate interrupts in order to 
be able to disable those interrupt sources that are non-RT.

If we then take Jan's observation about the many (Linux-only) interrupts present 
in an ordinary PC and add it to Philippe's idea of disabling all non-RT 
interrupts while executing in the RT-domain, I think that the following is a 
workable (and fairly efficient) way of handling this:

Add hardware dependent enable/disable functions, where the enable is called just 
before normal execution in a domain starts (i.e. when playing back interrupts, 
the disable is still in effect), and disable is called when normal domain 
execution end. This does effectively handle the K case above, with the added 
benefit that NO non-RT interrupts will occur during RT execution.

In the 8259 case, the disable function could look something like:

   domain_irq_disable(uint irqmask) {
     if (irqmask & 0xff00 != 0xff00) {
       irqmask &= ~0x0004; // Cascaded interrupt is still needed
       outb(irqmask >> 8, PIC_SLAVE_IMR);
     }
     outb(irqmask, PIC_MASTER_IMR);
   }

If we should extend this to handle the M (and O) case(s), the disable function 
could look like:

   domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
     int i;

     for (i = 0 ; i < MAX_IRQ ; i++) {
       if (shared[i]) {
         shared_irq_t *next = shared[i];
         irqmask &= ~(1<<i);
         while (next) {
           next->disable();
	  next = next->next;
         }
       }
     }
     if (irqmask & 0xff00 != 0xff00) {
       irqmask &= ~0x0004; // Cascaded interrupt is still needed
       outb(irqmask >> 8, PIC_SLAVE_IMR);
     }
     outb(irqmask, PIC_MASTER_IMR);
   }

An obvious optimization of the above scheme, is to never call the disable (or 
enable) function for the RT-domain, since there all interrupt processing is 
protected by the hardware.

Comments, anyone?

-- 

Anders



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] More on Shared interrupts
  2006-02-09 15:46               ` [Xenomai-core] More on Shared interrupts Anders Blomdell
@ 2006-02-09 16:39                 ` Jan Kiszka
  2006-02-10  8:04                   ` Anders Blomdell
  2006-02-10 13:59                 ` [Xenomai-core] " Philippe Gerum
  2006-02-16 16:05                 ` [Xenomai-core] " Anders Blomdell
  2 siblings, 1 reply; 25+ messages in thread
From: Jan Kiszka @ 2006-02-09 16:39 UTC (permalink / raw)
  To: Anders Blomdell; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 5518 bytes --]

Anders Blomdell wrote:
> For the last few days, I have tried to figure out a good way to share
> interrupts between RT and non-RT domains. This has included looking
> through Dmitry's patch, correcting bugs and testing what is possible in
> my specific case. I'll therefore try to summarize at least a few of my
> thoughts.
> 
> 1. When looking through Dmitry's patch I get the impression that the
> iack handler has very little to do with each interrupt (the test
> 'prev->iack != intr->iack' is a dead giveaway), but is more of a
> domain-specific function (or perhaps even just a placeholder for the
> hijacked Linux ack-function).
> 
> 
> 2. Somewhat inspired by the figure in "Life with Adeos", I have
> identified the following cases:
> 
>   irq K  | ----------- | ---o    |   // Linux only
>   ...
>   irq L  | ---o        |         |   // RT-only
>   ...
>   irq M  | ---o------- | ---o    |   // Shared between domains
>   ...
>   irq N  | ---o---o--- |         |   // Shared inside single domain
>   ...
>   irq O  | ---o---o--- | ---o    |   // Shared between and inside single
> domain
> 
> Xenomai currently handles the K & L cases, Dmitrys patch addresses the N
> case, with edge triggered interrupts the M (and O after Dmitry's patch)
> case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
> from the interrupt handler, for level triggered interrupt the M and O
> cases can't be handled.

I guess you mean it the other way around: for the edge-triggered
cross-domain case we would actually have to loop over both the RT and
the Linux handlers until we are sure, that the IRQ line was released once.

Luckily, I never saw such a scenario which were unavoidable (it hits you
with ISA hardware which tend to have nice IRQ jumpers or other means -
it's just that you often cannot divide several controllers on the same
extension card IRQ-wise apart).

> 
> If one looks more closely at the K case (Linux only interrupt), it works
> by when an interrupt occurs, the call to irq_end is postponed until the
> Linux interrupt handler has run, i.e. further interrupts are disabled.
> This can be seen as a lazy version of Philippe's idea of disabling all
> non-RT interrupts until the RT-domain is idle, i.e. the interrupt is
> disabled only if it indeed occurs.
> 
> If this idea should be generalized to the M (and O) case(s), one can't
> rely on postponing the irq_end call (since the interrupt is still needed
> in the RT-domain), but has to rely on some function that disables all
> non-RT hardware that generates interrupts on that irq-line; such a
> function naturally has to have intimate knowledge of all hardware that
> can generate interrupts in order to be able to disable those interrupt
> sources that are non-RT.
> 
> If we then take Jan's observation about the many (Linux-only) interrupts
> present in an ordinary PC and add it to Philippe's idea of disabling all
> non-RT interrupts while executing in the RT-domain, I think that the
> following is a workable (and fairly efficient) way of handling this:
> 
> Add hardware dependent enable/disable functions, where the enable is
> called just before normal execution in a domain starts (i.e. when
> playing back interrupts, the disable is still in effect), and disable is
> called when normal domain execution end. This does effectively handle
> the K case above, with the added benefit that NO non-RT interrupts will
> occur during RT execution.
> 
> In the 8259 case, the disable function could look something like:
> 
>   domain_irq_disable(uint irqmask) {
>     if (irqmask & 0xff00 != 0xff00) {
>       irqmask &= ~0x0004; // Cascaded interrupt is still needed
>       outb(irqmask >> 8, PIC_SLAVE_IMR);
>     }
>     outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> If we should extend this to handle the M (and O) case(s), the disable
> function could look like:
> 
>   domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
>     int i;
> 
>     for (i = 0 ; i < MAX_IRQ ; i++) {
>       if (shared[i]) {
>         shared_irq_t *next = shared[i];
>         irqmask &= ~(1<<i);
>         while (next) {
>           next->disable();
>       next = next->next;
>         }

This obviously means that all non-RT IRQ handlers sharing a line with
the RT domain would have to be registered in that shared[]-list. This
gets close to my old suggestion. Just raises the question how to
organise these interface, both on the RT and the Linux side.

>       }
>     }
>     if (irqmask & 0xff00 != 0xff00) {
>       irqmask &= ~0x0004; // Cascaded interrupt is still needed
>       outb(irqmask >> 8, PIC_SLAVE_IMR);
>     }
>     outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> An obvious optimization of the above scheme, is to never call the
> disable (or enable) function for the RT-domain, since there all
> interrupt processing is protected by the hardware.

Another point is to avoid that looping over disable handlers for IRQs of
the K case. Otherwise, too many device-specific disable handlers had to
be implemented even if only a single Linux device hogs a RT IRQ.

> 
> Comments, anyone?
> 

I see your need, we just have to keep in mind that we are currently
discussing the corner case (shared RT/non-RT IRQs) of the corner case
(shared RT IRQs). Whatever will be defined, the normal use case should
define how an efficient interface has to look like. Or we have to add a
lot of #ifdef's...

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] More on Shared interrupts
  2006-02-09 16:39                 ` Jan Kiszka
@ 2006-02-10  8:04                   ` Anders Blomdell
  0 siblings, 0 replies; 25+ messages in thread
From: Anders Blomdell @ 2006-02-10  8:04 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Anders Blomdell wrote:
> 
>>For the last few days, I have tried to figure out a good way to share
>>interrupts between RT and non-RT domains. This has included looking
>>through Dmitry's patch, correcting bugs and testing what is possible in
>>my specific case. I'll therefore try to summarize at least a few of my
>>thoughts.
>>
>>1. When looking through Dmitry's patch I get the impression that the
>>iack handler has very little to do with each interrupt (the test
>>'prev->iack != intr->iack' is a dead giveaway), but is more of a
>>domain-specific function (or perhaps even just a placeholder for the
>>hijacked Linux ack-function).
>>
>>
>>2. Somewhat inspired by the figure in "Life with Adeos", I have
>>identified the following cases:
>>
>>  irq K  | ----------- | ---o    |   // Linux only
>>  ...
>>  irq L  | ---o        |         |   // RT-only
>>  ...
>>  irq M  | ---o------- | ---o    |   // Shared between domains
>>  ...
>>  irq N  | ---o---o--- |         |   // Shared inside single domain
>>  ...
>>  irq O  | ---o---o--- | ---o    |   // Shared between and inside single
>>domain
>>
>>Xenomai currently handles the K & L cases, Dmitrys patch addresses the N
>>case, with edge triggered interrupts the M (and O after Dmitry's patch)
>>case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
>>from the interrupt handler, for level triggered interrupt the M and O
>>cases can't be handled.
> 
> 
> I guess you mean it the other way around: for the edge-triggered
> cross-domain case we would actually have to loop over both the RT and
> the Linux handlers until we are sure, that the IRQ line was released once.
I obviously has misunderstood edge triggered :-(

> Luckily, I never saw such a scenario which were unavoidable (it hits you
> with ISA hardware which tend to have nice IRQ jumpers or other means -
> it's just that you often cannot divide several controllers on the same
> extension card IRQ-wise apart).
> 
> 
>>If one looks more closely at the K case (Linux only interrupt), it works
>>by when an interrupt occurs, the call to irq_end is postponed until the
>>Linux interrupt handler has run, i.e. further interrupts are disabled.
>>This can be seen as a lazy version of Philippe's idea of disabling all
>>non-RT interrupts until the RT-domain is idle, i.e. the interrupt is
>>disabled only if it indeed occurs.
>>
>>If this idea should be generalized to the M (and O) case(s), one can't
>>rely on postponing the irq_end call (since the interrupt is still needed
>>in the RT-domain), but has to rely on some function that disables all
>>non-RT hardware that generates interrupts on that irq-line; such a
>>function naturally has to have intimate knowledge of all hardware that
>>can generate interrupts in order to be able to disable those interrupt
>>sources that are non-RT.
>>
>>If we then take Jan's observation about the many (Linux-only) interrupts
>>present in an ordinary PC and add it to Philippe's idea of disabling all
>>non-RT interrupts while executing in the RT-domain, I think that the
>>following is a workable (and fairly efficient) way of handling this:
>>
>>Add hardware dependent enable/disable functions, where the enable is
>>called just before normal execution in a domain starts (i.e. when
>>playing back interrupts, the disable is still in effect), and disable is
>>called when normal domain execution end. This does effectively handle
>>the K case above, with the added benefit that NO non-RT interrupts will
>>occur during RT execution.
>>
>>In the 8259 case, the disable function could look something like:
>>
>>  domain_irq_disable(uint irqmask) {
>>    if (irqmask & 0xff00 != 0xff00) {
>>      irqmask &= ~0x0004; // Cascaded interrupt is still needed
>>      outb(irqmask >> 8, PIC_SLAVE_IMR);
>>    }
>>    outb(irqmask, PIC_MASTER_IMR);
>>  }
>>
>>If we should extend this to handle the M (and O) case(s), the disable
>>function could look like:
>>
>>  domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
>>    int i;
>>
>>    for (i = 0 ; i < MAX_IRQ ; i++) {
>>      if (shared[i]) {
>>        shared_irq_t *next = shared[i];
>>        irqmask &= ~(1<<i);
>>        while (next) {
>>          next->disable();
>>      next = next->next;
>>        }
> 
> 
> This obviously means that all non-RT IRQ handlers sharing a line with
> the RT domain would have to be registered in that shared[]-list. This
> gets close to my old suggestion. Just raises the question how to
> organise these interface, both on the RT and the Linux side.
> 
> 
>>      }
>>    }
>>    if (irqmask & 0xff00 != 0xff00) {
>>      irqmask &= ~0x0004; // Cascaded interrupt is still needed
>>      outb(irqmask >> 8, PIC_SLAVE_IMR);
>>    }
>>    outb(irqmask, PIC_MASTER_IMR);
>>  }
>>
>>An obvious optimization of the above scheme, is to never call the
>>disable (or enable) function for the RT-domain, since there all
>>interrupt processing is protected by the hardware.
> 
> 
> Another point is to avoid that looping over disable handlers for IRQs of
> the K case. Otherwise, too many device-specific disable handlers had to
> be implemented even if only a single Linux device hogs a RT IRQ.
You only have to spin over those IRQ that are actually shared across domains 
(probably just a few in most cases), those IRQ that stays in one domain fets 
handled in the interrupt controller. Setting up the appropriate [per domain] 
lists can be done as irqhandlers gets registered/unregistred (which is usually 
quite seldom).

>>Comments, anyone?
>>
> 
> 
> I see your need, we just have to keep in mind that we are currently
> discussing the corner case (shared RT/non-RT IRQs) of the corner case
> (shared RT IRQs). Whatever will be defined, the normal use case should
> define how an efficient interface has to look like. Or we have to add a
> lot of #ifdef's...
My current need can simply be handled by disabling the UART interrupt and have a 
low priority RT task polling the interrupt and handing it over to Linux. It was 
just that I thought that now might be a good time to try to bring together those 
three somewhat overlapping issues:

   1. Shared RT-interrupts (which Dimitry has already done)
   2. Philippe's suggestion of disabling all interrupts for lower priority
      domains.
   3. Interrupts shared between domains

As previously said, my current needs are covered by #3, but since I have RT 
plans for some of my ordinary PCs as well, I feel that #2 is worth some effort 
as well. My feeling right now, is that execution time of #2 will be shorter than 
it takes to handle a single non-RT interrupt in the current codebase, and hence 
it ought to improve RT performance (avoiding I-cache pressure from non-RT 
handlers for instance), and #3 is a small addition once #2 is in place.


-- 

Anders


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Xenomai-core] Re: More on Shared interrupts
  2006-02-09 15:46               ` [Xenomai-core] More on Shared interrupts Anders Blomdell
  2006-02-09 16:39                 ` Jan Kiszka
@ 2006-02-10 13:59                 ` Philippe Gerum
  2006-02-11 11:35                   ` Dmitry Adamushko
  2006-02-16 16:05                 ` [Xenomai-core] " Anders Blomdell
  2 siblings, 1 reply; 25+ messages in thread
From: Philippe Gerum @ 2006-02-10 13:59 UTC (permalink / raw)
  To: Anders Blomdell; +Cc: Jan Kiszka, xenomai

Anders Blomdell wrote:
> For the last few days, I have tried to figure out a good way to share 
> interrupts between RT and non-RT domains. This has included looking 
> through Dmitry's patch, correcting bugs and testing what is possible in 
> my specific case. I'll therefore try to summarize at least a few of my 
> thoughts.
> 
> 1. When looking through Dmitry's patch I get the impression that the 
> iack handler has very little to do with each interrupt (the test 
> 'prev->iack != intr->iack' is a dead giveaway), but is more of a 
> domain-specific function (or perhaps even just a placeholder for the 
> hijacked Linux ack-function).
> 
> 
> 2. Somewhat inspired by the figure in "Life with Adeos", I have 
> identified the following cases:
> 
>   irq K  | ----------- | ---o    |   // Linux only
>   ...
>   irq L  | ---o        |         |   // RT-only
>   ...
>   irq M  | ---o------- | ---o    |   // Shared between domains
>   ...
>   irq N  | ---o---o--- |         |   // Shared inside single domain
>   ...
>   irq O  | ---o---o--- | ---o    |   // Shared between and inside single 
> domain
> 
> Xenomai currently handles the K & L cases, Dmitrys patch addresses the N 
> case, with edge triggered interrupts the M (and O after Dmitry's patch) 
> case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE 
> 

As you pointed out recently, using this combo for M (and thus O) might also be
unsafe, e.g. causing some implementation to send eoi twice or more (and the second
time while hw IRQs are off and the second IRQ is still pending) if more than a
single domain ends the current interrupt. This said, I've never tried that
actually, but this does seem a bit optimistic to always expect a proper behaviour
in this case (basically, it all depends on what "ending" the interrupt means hw-wise).

 > from the interrupt handler, for level triggered interrupt the M and O
> cases can't be handled.
> 
> If one looks more closely at the K case (Linux only interrupt), it works 
> by when an interrupt occurs, the call to irq_end is postponed until the 
> Linux interrupt handler has run, i.e. further interrupts are disabled. 
> This can be seen as a lazy version of Philippe's idea of disabling all 
> non-RT interrupts until the RT-domain is idle, i.e. the interrupt is 
> disabled only if it indeed occurs.
> 
> If this idea should be generalized to the M (and O) case(s), one can't 
> rely on postponing the irq_end call (since the interrupt is still needed 
> in the RT-domain), but has to rely on some function that disables all 
> non-RT hardware that generates interrupts on that irq-line; such a 
> function naturally has to have intimate knowledge of all hardware that 
> can generate interrupts in order to be able to disable those interrupt 
> sources that are non-RT.
> 
> If we then take Jan's observation about the many (Linux-only) interrupts 
> present in an ordinary PC and add it to Philippe's idea of disabling all 
> non-RT interrupts while executing in the RT-domain, I think that the 
> following is a workable (and fairly efficient) way of handling this:
> 
> Add hardware dependent enable/disable functions, where the enable is 
> called just before normal execution in a domain starts (i.e. when 
> playing back interrupts, the disable is still in effect), and disable is 
> called when normal domain execution end. This does effectively handle 
> the K case above, with the added benefit that NO non-RT interrupts will 
> occur during RT execution.

To do that, I'd suggest that we reuse the xnarch_enter_root/xnarch_leave_root 
hooks the nucleus calls when entering or leaving the Linux domain (i.e. to restart 
the RT activity). Sharing RT and non-RT interrupts are not that much an Adeos 
issue, but rather a Xenomai one, since only the latter knows that it must handle 
real-time constraints, and also knows about the xnintr abstraction we would have 
to use in order to handle the intra-domain shared IRQs.

> 
> In the 8259 case, the disable function could look something like:
> 
>   domain_irq_disable(uint irqmask) {
>     if (irqmask & 0xff00 != 0xff00) {
>       irqmask &= ~0x0004; // Cascaded interrupt is still needed
>       outb(irqmask >> 8, PIC_SLAVE_IMR);
>     }
>     outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> If we should extend this to handle the M (and O) case(s), the disable 
> function could look like:
> 
>   domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
>     int i;
> 
>     for (i = 0 ; i < MAX_IRQ ; i++) {
>       if (shared[i]) {
>         shared_irq_t *next = shared[i];
>         irqmask &= ~(1<<i);
>         while (next) {
>           next->disable();
>       next = next->next;
>         }
>       }
>     }
>     if (irqmask & 0xff00 != 0xff00) {
>       irqmask &= ~0x0004; // Cascaded interrupt is still needed
>       outb(irqmask >> 8, PIC_SLAVE_IMR);
>     }
>     outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> An obvious optimization of the above scheme, is to never call the 
> disable (or enable) function for the RT-domain, since there all 
> interrupt processing is protected by the hardware.
> 

I'm concerned by the fact that it would cost up to 3-5 us doing so on x86 just for
handling the cascaded PIC + the cost of each per-IRQ disable call fiddling with
the HW once again (maybe also through sluggish i/o port accesses), even more 
during bus saturation, and this intrinsic latency would be added to the fast path, 
before rescheduling a RT task pending for the incoming interrupt, e.g. after some 
idle time in the Linux domain. In the later case, which is the most frequent 
situation, we would not be able to save the disable call for Linux interrupts 
either since we would be switching domains to Xeno's.

I think that we should decouple the hw shield optimization from the RT/non-RT
sharing issue; if the latter one could be solved by the former, the former also
requires to have the appropriate IC hw in order to be efficient. However, we
should be able to deal even with a 8259 for handling the RT/non-RT sharing case.

Sticking with the inter-domain sharing issue and in the light of the process you 
described, I would rather go for using the shared acknowledge handling Adeos 
already provides, for which Xenomai's xnintr abstraction already provides support 
(i.e. xniack_t parameter). In short, both the Xenomai and Linux domains can 
already have their own IRQ acknowledge routine defined for any given interrupt, 
and have them called by priority order over the primary Adeos's handler that 
collects all raw/hw IRQs before loggin them (see the IPIPE_SHARED mode bit).

This way, every domain would have the opportunity to be polled for identifying the 
source of the interrupt and possibly tell the hw to stop spamming in case of 
level-triggered IRQs. This would require the per-domain ack handler to understand 
the logic of the attached devices wrt interrupt handling - maybe by incorporating 
the ack portion of Linux driver's ISR for the initiating device -, but I see no 
difference wrt calling disable routines as you described: those would also have to 
know how to deal with such hw anyway. The problem I see with level-triggered IRQs 
is that by definition, there is no common/generic way of clearing their cause.

This said, what we need for sure is Adeos preventing the regular Linux IRQ 
dispatcher (i.e. __do_IRQS) to end domain-shared IRQs, since we would rightfully 
assume that someone should have already done that early on.

> Comments, anyone?
> 

To sum up, interrupt handling is one of the worst PITA of the Known Universe, 
likely because or as a consequence of which it's one of least well-defined area in 
OS design. As such, I would preferably go for some minimalistic generic support of 
the IRQ sharing corner case (RT/RT and RT/non-RT, including the polarity issue), 
so that we don't adversely affect the regular fast path. For that to happen, we 
might first want to list more precisely the use cases we'd want to support, so 
that we could somewhat simplify the whole equation.

-- 

Philippe.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Xenomai-core] Re: More on Shared interrupts
  2006-02-10 13:59                 ` [Xenomai-core] " Philippe Gerum
@ 2006-02-11 11:35                   ` Dmitry Adamushko
  2006-02-13  7:49                     ` Anders Blomdell
  2006-02-14 17:46                     ` Philippe Gerum
  0 siblings, 2 replies; 25+ messages in thread
From: Dmitry Adamushko @ 2006-02-11 11:35 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 3109 bytes --]

> >
> >   irq K  | ----------- | ---o    |   // Linux only
> >   ...
> >   irq L  | ---o        |         |   // RT-only
> >   ...
> >   irq M  | ---o------- | ---o    |   // Shared between domains
> >   ...
> >   irq N  | ---o---o--- |         |   // Shared inside single domain
> >   ...
> >   irq O  | ---o---o--- | ---o    |   // Shared between and inside single
> > domain
> >
> > Xenomai currently handles the K & L cases, Dmitrys patch addresses the N
> > case, with edge triggered interrupts the M (and O after Dmitry's patch)
> > case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
> >
>
> As you pointed out recently, using this combo for M (and thus O) might
also be
> unsafe, e.g. causing some implementation to send eoi twice or more (and
the second
> time while hw IRQs are off and the second IRQ is still pending) if more
than a
> single domain ends the current interrupt. This said, I've never tried that
> actually, but this does seem a bit optimistic to always expect a proper
behaviour
> in this case (basically, it all depends on what "ending" the interrupt
means hw-wise).


Just to be sure I've got the things more or less clear. I feel there are
some holes in my understanding of the irq handling stuff, mainly hw-wise.

x86 + i8259A.

In this case, .end handler does nothing more than enabling the IRQ line.
The "eoi" is sent in .ack right after disabling the IRQ line.

Let's suppose we have the "M" case ("O" makes no difference here).

When the ISR handler in Linux domain gets control :

- the IRQ line is ON (it was already .end-ed in the primary domain in case
  of XN_ISR_ENABLE | XN_ISR_CHAINED ).

===
  Actually, it's possible to set IPIPE_PASS flag for
  the primary_domain.irqs[THIS_IRQ].control
  when THIS_IRQ is shared across domains. This way, there is no need
  to call propagate_irq() in xnintr_irq_handler(). Ok, it's not
  that important so far.
===

  This is not how it happens when the IRQ is only handled in the
  Linux domain. But the ISR is still serialized (need not to be
  reentrant) because do_IRQ() takes care of it (by means
  of RUNNING and PENDING flags).

So, I suppose, it's possible to use XN_ISR_ENABLE | XN_ISR_CHAINED in that
case?

In case of a pure Linux :

SMP : I/O APIC + local APICs. As I know, enabling/disabling
the IRQ line occurs (normally?) on per-local APIC basis. This said, when
the ISR is running on CPU_0 with the IRQ line disabled, nothing prevents
(probably, if the IRQ also was .ack-ed by that time?) the same IRQ from
being signaled on another CPU (even on a few).
In that case, it gets marked as PENDING and do_IRQ() on CPU_0 will run
handler_IRQ_events() - ISR handlers - once more.

Since PENDING is only a flag (not a counter), the fact that the IRQ was
signaled
is not lost but Linux can't know how much time it was signaled.
I guess, it's not true for devices that e.g. do not rise a new interrupt
until
the ISR handler does some special acknowledgement device-wise.

am I right?


--
Best regards,
Dmitry Adamushko

[-- Attachment #2: Type: text/html, Size: 3957 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Xenomai-core] Re: More on Shared interrupts
  2006-02-11 11:35                   ` Dmitry Adamushko
@ 2006-02-13  7:49                     ` Anders Blomdell
  2006-02-13 11:00                       ` Dmitry Adamushko
  2006-02-14 17:46                     ` Philippe Gerum
  1 sibling, 1 reply; 25+ messages in thread
From: Anders Blomdell @ 2006-02-13  7:49 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Dmitry Adamushko wrote:
> 
>  > >
>  > >   irq K  | ----------- | ---o    |   // Linux only
>  > >   ...
>  > >   irq L  | ---o        |         |   // RT-only
>  > >   ...
>  > >   irq M  | ---o------- | ---o    |   // Shared between domains
>  > >   ...
>  > >   irq N  | ---o---o--- |         |   // Shared inside single domain
>  > >   ...
>  > >   irq O  | ---o---o--- | ---o    |   // Shared between and inside 
> single
>  > > domain
>  > >
>  > > Xenomai currently handles the K & L cases, Dmitrys patch addresses 
> the N
>  > > case, with edge triggered interrupts the M (and O after Dmitry's patch)
>  > > case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
>  > >
>  >
>  > As you pointed out recently, using this combo for M (and thus O) 
> might also be
>  > unsafe, e.g. causing some implementation to send eoi twice or more 
> (and the second
>  > time while hw IRQs are off and the second IRQ is still pending) if 
> more than a
>  > single domain ends the current interrupt. This said, I've never tried 
> that
>  > actually, but this does seem a bit optimistic to always expect a 
> proper behaviour
>  > in this case (basically, it all depends on what "ending" the 
> interrupt means hw-wise).
> 
> 
> Just to be sure I've got the things more or less clear. I feel there are 
> some holes in my understanding of the irq handling stuff, mainly hw-wise.
> 
> x86 + i8259A.
> 
> In this case, .end handler does nothing more than enabling the IRQ line.
> The "eoi" is sent in .ack right after disabling the IRQ line.
> 
> Let's suppose we have the "M" case ("O" makes no difference here).
> 
> When the ISR handler in Linux domain gets control :
> 
> - the IRQ line is ON (it was already .end-ed in the primary domain in case
>   of XN_ISR_ENABLE | XN_ISR_CHAINED ).
> 
> ===
>   Actually, it's possible to set IPIPE_PASS flag for
>   the primary_domain.irqs[THIS_IRQ].control
>   when THIS_IRQ is shared across domains. This way, there is no need
>   to call propagate_irq() in xnintr_irq_handler(). Ok, it's not
>   that important so far.
> ===
> 
>   This is not how it happens when the IRQ is only handled in the
>   Linux domain. But the ISR is still serialized (need not to be
>   reentrant) because do_IRQ() takes care of it (by means
>   of RUNNING and PENDING flags).
> 
> So, I suppose, it's possible to use XN_ISR_ENABLE | XN_ISR_CHAINED in that
> case?
Yes, but only if you disable interrupts from the Linux device (i.e. via its 
control registers, not via the APIC), otherwise the RT-handler will spin since 
the interrupt will never get deasserted. Then you are faced with finding some 
place to reenble those interrupts right after the Linux interrupts-handler has run.

> 
> In case of a pure Linux :
> 
> SMP : I/O APIC + local APICs. As I know, enabling/disabling
> the IRQ line occurs (normally?) on per-local APIC basis. This said, when
> the ISR is running on CPU_0 with the IRQ line disabled, nothing prevents
> (probably, if the IRQ also was .ack-ed by that time?) the same IRQ from
> being signaled on another CPU (even on a few).
> In that case, it gets marked as PENDING and do_IRQ() on CPU_0 will run
> handler_IRQ_events() - ISR handlers - once more.
> 
> Since PENDING is only a flag (not a counter), the fact that the IRQ was 
> signaled
> is not lost but Linux can't know how much time it was signaled.
> I guess, it's not true for devices that e.g. do not rise a new interrupt 
> until
> the ISR handler does some special acknowledgement device-wise.
Since my knowledge of interrupts in SMPs is essentially nil, I'll have to pass 
on this one...


-- 
Best regards

Anders Blomdell


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Xenomai-core] Re: More on Shared interrupts
  2006-02-13  7:49                     ` Anders Blomdell
@ 2006-02-13 11:00                       ` Dmitry Adamushko
  0 siblings, 0 replies; 25+ messages in thread
From: Dmitry Adamushko @ 2006-02-13 11:00 UTC (permalink / raw)
  To: Anders Blomdell; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 3323 bytes --]

On 13/02/06, Anders Blomdell <anders.blomdell@domain.hid> wrote:
>
> Dmitry Adamushko wrote:
> >
> >  > >
> >  > >   irq K  | ----------- | ---o    |   // Linux only
> >  > >   ...
> >  > >   irq L  | ---o        |         |   // RT-only
> >  > >   ...
> >  > >   irq M  | ---o------- | ---o    |   // Shared between domains
> >  > >   ...
> >  > >   irq N  | ---o---o--- |         |   // Shared inside single domain
> >  > >   ...
> >  > >   irq O  | ---o---o--- | ---o    |   // Shared between and inside
> > single
> >  > > domain
> >  > >
> >  > > Xenomai currently handles the K & L cases, Dmitrys patch addresses
> > the N
> >  > > case, with edge triggered interrupts the M (and O after Dmitry's
> patch)
> >  > > case(s) might be handled by returning RT_INTR_CHAINED |
> RT_INTR_ENABLE
> >  > >
> >  >
> >  > As you pointed out recently, using this combo for M (and thus O)
> > might also be
> >  > unsafe, e.g. causing some implementation to send eoi twice or more
> > (and the second
> >  > time while hw IRQs are off and the second IRQ is still pending) if
> > more than a
> >  > single domain ends the current interrupt. This said, I've never tried
> > that
> >  > actually, but this does seem a bit optimistic to always expect a
> > proper behaviour
> >  > in this case (basically, it all depends on what "ending" the
> > interrupt means hw-wise).
> >
> >
> > Just to be sure I've got the things more or less clear. I feel there are
> > some holes in my understanding of the irq handling stuff, mainly
> hw-wise.
> >
> > x86 + i8259A.
> >
> > In this case, .end handler does nothing more than enabling the IRQ line.
> > The "eoi" is sent in .ack right after disabling the IRQ line.
> >
> > Let's suppose we have the "M" case ("O" makes no difference here).
> >
> > When the ISR handler in Linux domain gets control :
> >
> > - the IRQ line is ON (it was already .end-ed in the primary domain in
> case
> >   of XN_ISR_ENABLE | XN_ISR_CHAINED ).
> >
> > ===
> >   Actually, it's possible to set IPIPE_PASS flag for
> >   the primary_domain.irqs[THIS_IRQ].control
> >   when THIS_IRQ is shared across domains. This way, there is no need
> >   to call propagate_irq() in xnintr_irq_handler(). Ok, it's not
> >   that important so far.
> > ===
> >
> >   This is not how it happens when the IRQ is only handled in the
> >   Linux domain. But the ISR is still serialized (need not to be
> >   reentrant) because do_IRQ() takes care of it (by means
> >   of RUNNING and PENDING flags).
> >
> > So, I suppose, it's possible to use XN_ISR_ENABLE | XN_ISR_CHAINED in
> that
> > case?
> Yes, but only if you disable interrupts from the Linux device (i.e. via
> its
> control registers, not via the APIC), otherwise the RT-handler will spin
> since
> the interrupt will never get deasserted. Then you are faced with finding
> some
> place to reenble those interrupts right after the Linux interrupts-handler
> has run.


Thanks. I'm just missing what really happens between PIC and hw devices at
the time of CPU <--> PIC communication. Now it becomes clearer, nevertheless
I have to find some good hw-related overview (tried but failed so far).



--
> Best regards
>
> Anders Blomdell
>


--
Best regards,
Dmitry Adamushko

[-- Attachment #2: Type: text/html, Size: 4860 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Xenomai-core] Re: More on Shared interrupts
  2006-02-11 11:35                   ` Dmitry Adamushko
  2006-02-13  7:49                     ` Anders Blomdell
@ 2006-02-14 17:46                     ` Philippe Gerum
  1 sibling, 0 replies; 25+ messages in thread
From: Philippe Gerum @ 2006-02-14 17:46 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Dmitry Adamushko wrote:
> 
>  > >
>  > >   irq K  | ----------- | ---o    |   // Linux only
>  > >   ...
>  > >   irq L  | ---o        |         |   // RT-only
>  > >   ...
>  > >   irq M  | ---o------- | ---o    |   // Shared between domains
>  > >   ...
>  > >   irq N  | ---o---o--- |         |   // Shared inside single domain
>  > >   ...
>  > >   irq O  | ---o---o--- | ---o    |   // Shared between and inside 
> single
>  > > domain
>  > >
>  > > Xenomai currently handles the K & L cases, Dmitrys patch addresses 
> the N
>  > > case, with edge triggered interrupts the M (and O after Dmitry's patch)
>  > > case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
>  > >
>  >
>  > As you pointed out recently, using this combo for M (and thus O) 
> might also be
>  > unsafe, e.g. causing some implementation to send eoi twice or more 
> (and the second
>  > time while hw IRQs are off and the second IRQ is still pending) if 
> more than a
>  > single domain ends the current interrupt. This said, I've never tried 
> that
>  > actually, but this does seem a bit optimistic to always expect a 
> proper behaviour
>  > in this case (basically, it all depends on what "ending" the 
> interrupt means hw-wise).
> 
> 
> Just to be sure I've got the things more or less clear. I feel there are 
> some holes in my understanding of the irq handling stuff, mainly hw-wise.
> 
> x86 + i8259A.
> 
> In this case, .end handler does nothing more than enabling the IRQ line.
> The "eoi" is sent in .ack right after disabling the IRQ line.
> 
> Let's suppose we have the "M" case ("O" makes no difference here).
> 
> When the ISR handler in Linux domain gets control :
> 
> - the IRQ line is ON (it was already .end-ed in the primary domain in case
>   of XN_ISR_ENABLE | XN_ISR_CHAINED ).
> 
> ===
>   Actually, it's possible to set IPIPE_PASS flag for
>   the primary_domain.irqs[THIS_IRQ].control
>   when THIS_IRQ is shared across domains. This way, there is no need
>   to call propagate_irq() in xnintr_irq_handler(). Ok, it's not
>   that important so far.
> ===
> 
>   This is not how it happens when the IRQ is only handled in the
>   Linux domain. But the ISR is still serialized (need not to be
>   reentrant) because do_IRQ() takes care of it (by means
>   of RUNNING and PENDING flags).
> 
> So, I suppose, it's possible to use XN_ISR_ENABLE | XN_ISR_CHAINED in that
> case?
> 
> In case of a pure Linux :
> 
> SMP : I/O APIC + local APICs. As I know, enabling/disabling
> the IRQ line occurs (normally?) on per-local APIC basis. This said, when
> the ISR is running on CPU_0 with the IRQ line disabled, nothing prevents
> (probably, if the IRQ also was .ack-ed by that time?) the same IRQ from
> being signaled on another CPU (even on a few).
> In that case, it gets marked as PENDING and do_IRQ() on CPU_0 will run
> handler_IRQ_events() - ISR handlers - once more.
> 
> Since PENDING is only a flag (not a counter), the fact that the IRQ was 
> signaled
> is not lost but Linux can't know how much time it was signaled.
> I guess, it's not true for devices that e.g. do not rise a new interrupt 
> until
> the ISR handler does some special acknowledgement device-wise.
> 
> am I right?

Yes. Additionally, the uncertainty about the last issue is one of the reasons why 
Adeos keeps a count of pending IRQs, and not just a flag; the other being that we 
do want virtual interrupts to be counted and not just marked so that the software 
can rely on this.

> 
> 
> -- 
> Best regards,
> Dmitry Adamushko


-- 

Philippe.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Xenomai-core] More on Shared interrupts
  2006-02-09 15:46               ` [Xenomai-core] More on Shared interrupts Anders Blomdell
  2006-02-09 16:39                 ` Jan Kiszka
  2006-02-10 13:59                 ` [Xenomai-core] " Philippe Gerum
@ 2006-02-16 16:05                 ` Anders Blomdell
  2 siblings, 0 replies; 25+ messages in thread
From: Anders Blomdell @ 2006-02-16 16:05 UTC (permalink / raw)
  To: xenomai

Anders Blomdell wrote:
> For the last few days, I have tried to figure out a good way to share 
> interrupts between RT and non-RT domains. This has included looking 
> through Dmitry's patch, correcting bugs and testing what is possible in 
> my specific case. I'll therefore try to summarize at least a few of my 
> thoughts.
> 
> 1. When looking through Dmitry's patch I get the impression that the 
> iack handler has very little to do with each interrupt (the test 
> 'prev->iack != intr->iack' is a dead giveaway), but is more of a 
> domain-specific function (or perhaps even just a placeholder for the 
> hijacked Linux ack-function).
> 
> 
> 2. Somewhat inspired by the figure in "Life with Adeos", I have 
> identified the following cases:
> 
>   irq K  | ----------- | ---o    |   // Linux only
>   ...
>   irq L  | ---o        |         |   // RT-only
>   ...
>   irq M  | ---o------- | ---o    |   // Shared between domains
>   ...
>   irq N  | ---o---o--- |         |   // Shared inside single domain
>   ...
>   irq O  | ---o---o--- | ---o    |   // Shared between and inside single 
> domain
> 
> Xenomai currently handles the K & L cases, Dmitrys patch addresses the N 
> case, with edge triggered interrupts the M (and O after Dmitry's patch) 
> case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE 
> from the interrupt handler, for level triggered interrupt the M and O 
> cases can't be handled.
> 
> If one looks more closely at the K case (Linux only interrupt), it works 
> by when an interrupt occurs, the call to irq_end is postponed until the 
> Linux interrupt handler has run, i.e. further interrupts are disabled. 
> This can be seen as a lazy version of Philippe's idea of disabling all 
> non-RT interrupts until the RT-domain is idle, i.e. the interrupt is 
> disabled only if it indeed occurs.
> 
> If this idea should be generalized to the M (and O) case(s), one can't 
> rely on postponing the irq_end call (since the interrupt is still needed 
> in the RT-domain), but has to rely on some function that disables all 
> non-RT hardware that generates interrupts on that irq-line; such a 
> function naturally has to have intimate knowledge of all hardware that 
> can generate interrupts in order to be able to disable those interrupt 
> sources that are non-RT.
> 
> If we then take Jan's observation about the many (Linux-only) interrupts 
> present in an ordinary PC and add it to Philippe's idea of disabling all 
> non-RT interrupts while executing in the RT-domain, I think that the 
> following is a workable (and fairly efficient) way of handling this:
> 
> Add hardware dependent enable/disable functions, where the enable is 
> called just before normal execution in a domain starts (i.e. when 
> playing back interrupts, the disable is still in effect), and disable is 
> called when normal domain execution end. This does effectively handle 
> the K case above, with the added benefit that NO non-RT interrupts will 
> occur during RT execution.
> 
> In the 8259 case, the disable function could look something like:
> 
>   domain_irq_disable(uint irqmask) {
>     if (irqmask & 0xff00 != 0xff00) {
>       irqmask &= ~0x0004; // Cascaded interrupt is still needed
>       outb(irqmask >> 8, PIC_SLAVE_IMR);
>     }
>     outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> If we should extend this to handle the M (and O) case(s), the disable 
> function could look like:
> 
>   domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
>     int i;
> 
>     for (i = 0 ; i < MAX_IRQ ; i++) {
>       if (shared[i]) {
>         shared_irq_t *next = shared[i];
>         irqmask &= ~(1<<i);
>         while (next) {
>           next->disable();
>       next = next->next;
>         }
>       }
>     }
>     if (irqmask & 0xff00 != 0xff00) {
>       irqmask &= ~0x0004; // Cascaded interrupt is still needed
>       outb(irqmask >> 8, PIC_SLAVE_IMR);
>     }
>     outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> An obvious optimization of the above scheme, is to never call the 
> disable (or enable) function for the RT-domain, since there all 
> interrupt processing is protected by the hardware.
> 
> Comments, anyone?

OK, I have finally got around to do some interrupt timing tests on a PrPMC800 
(450 MHz PowerPC/G4)  with the following interrupt sources:

   3: 10 Khz watchdog interrupt (Linux)
  10: 100 Mbit/s ethernet (Linux)
  16: mailbox interrupt (RT) + UART (Linux)

I have measured interrupt latency, task latency (time from interrupt until a 
task signalled from interrupt handler has started) and the semaphore latency 
(time from task semaphore is signalled until task has started).

I have tested 4 different ways of handling shared Linux/RT interrupts:

   1. When UART interrupt occurs, disable further UART interrupts, signal low
      priority UART reenable task, return XN_ISR_ENABLE | XN_ISR_CHAINED.
      In low priority UART reenable task, reenable UART when Linux has handled
      the interrupt.

   2. Disable UART interrupts, and poll them at 1kHz from low priority RT task,
      and rthal_irq_host_pend them as they occur.

   3. Modified Xenomai, where non-RT interrupts are disabled when entering
      the RT domain, and enabled when entering the Linux domain.

   4. Modified Xenomai, where non-RT interrupts are disabled when interrupt
      occurs, and enabled when entering the Linux domain.

In case 3 & 4 interrupts are enabled/disabled with code like:

       if (enable) {
         // Enable Linux interrupts
         SET_HARRIER_XCSR_REG_16(FEMA, 0xc900); // UART
         rthal_irq_enable(3);
         rthal_irq_enable(10);
       } else {
         // Disable Linux interrupts
         SET_HARRIER_XCSR_REG_16(FEMA, 0xcf00); // UART
         rthal_irq_disable(3);
         rthal_irq_disable(10);
       }


The tests has been run with 5 different loads (measuring a 1 kHz mailbox interrupt):

   A. Idle
   B. 10 KHz watchdog
   C. UART @9600 baud (approx 1kHz)
   D. ping -f -l20
   E. compound load (watchdog + UART + ping)

The plots at http://www.control.lth.se/user/andersb/orca/timing_plots.html makes 
me draw the following conclusions (worst case task latency <= worst case 
interrupt latency + worst case semaphore latency, since their simultaneous 
probablity is lower):

   a. On an unloaded system (A), 3 & 4 are slightly worse (2 us), the main
      difference between the two being if the disabling is done before or
      after the mailbox IRQ handler is run.
   b. In all the single load cases (B, C, D) the modified kernels (3, 4) has
      comparable task latency as the unmodified kernels (1, 2), and lower
      interrupt latency and lower semaphore latency.
   c. In the compound load case, the modified kernels shows distinctly improved
      worst case interrupt latencies (15 us instead of 20 us), and the one with
      early disabled interrupts (4) has distinctly better semaphore latency.

Based on the above, I conclude that by disabling all non-RT interrupts early (4) 
timing is improved since the RT domain is hit by a maximum of one non-RT 
interrupt at a time, and on standard PC's with lots of non-RT interrupts the 
benefit would be even bigger. I also believe that the enable/disable code could 
be (somewhat) improved by only taking one write posting delay instead of two 
(these are in code called by rthal_irq_*able).

-- 

Regards

Anders Blomdell



^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2006-02-16 16:05 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-07  9:04 [Xenomai-core] [Combo-PATCH] Shared interrupts (final) Dmitry Adamushko
2006-02-07  9:58 ` Wolfgang Grandegger
2006-02-07 17:58   ` Jan Kiszka
2006-02-08  7:26     ` Wolfgang Grandegger
2006-02-08  8:24       ` Jan Kiszka
2006-02-08 10:12         ` Dmitry Adamushko
2006-02-08 10:57     ` Philippe Gerum
2006-02-09  8:30       ` Anders Blomdell
2006-02-09  9:11         ` Jan Kiszka
2006-02-09 10:07           ` Philippe Gerum
2006-02-09  9:59         ` Philippe Gerum
2006-02-09 10:19           ` Jan Kiszka
2006-02-09 11:11             ` Dmitry Adamushko
2006-02-09 15:46               ` [Xenomai-core] More on Shared interrupts Anders Blomdell
2006-02-09 16:39                 ` Jan Kiszka
2006-02-10  8:04                   ` Anders Blomdell
2006-02-10 13:59                 ` [Xenomai-core] " Philippe Gerum
2006-02-11 11:35                   ` Dmitry Adamushko
2006-02-13  7:49                     ` Anders Blomdell
2006-02-13 11:00                       ` Dmitry Adamushko
2006-02-14 17:46                     ` Philippe Gerum
2006-02-16 16:05                 ` [Xenomai-core] " Anders Blomdell
2006-02-09 11:14             ` [Xenomai-core] [Combo-PATCH] Shared interrupts (final) Philippe Gerum
2006-02-09 10:43           ` Anders Blomdell
2006-02-07 19:24   ` Dmitry Adamushko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.