* [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 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 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 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: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 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
* [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
* 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
* 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-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
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.