I'm tired of these being in a separate directory
authorDavid Schleef <ds@schleef.org>
Sat, 1 Dec 2001 01:15:35 +0000 (01:15 +0000)
committerDavid Schleef <ds@schleef.org>
Sat, 1 Dec 2001 01:15:35 +0000 (01:15 +0000)
comedi/rt_pend_tq.c [new file with mode: 0644]
comedi/rt_pend_tq.h [new file with mode: 0644]

diff --git a/comedi/rt_pend_tq.c b/comedi/rt_pend_tq.c
new file mode 100644 (file)
index 0000000..ff08ed7
--- /dev/null
@@ -0,0 +1,98 @@
+/* rt_pend_tq.c */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/comedidev.h>   // for rt spinlocks
+#include "rt_pend_tq.h"
+#ifdef CONFIG_COMEDI_RTAI
+#include <rtai.h>
+#endif
+#ifdef CONFIG_COMEDI_RTL
+#include <rtl_core.h>
+#endif
+
+#ifdef standalone
+#include <linux/module.h>
+#define rt_pend_tq_init init_module
+#define rt_pend_tq_cleanup cleanup_module
+#endif
+
+volatile static struct rt_pend_tq rt_pend_tq[RT_PEND_TQ_SIZE];
+volatile static struct rt_pend_tq * volatile rt_pend_head= rt_pend_tq,
+       * volatile rt_pend_tail = rt_pend_tq;
+int rt_pend_tq_irq=0;
+spinlock_t rt_pend_tq_lock = SPIN_LOCK_UNLOCKED;
+
+// WARNING: following code not checked against race conditions yet.
+#define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
+#define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
+
+int rt_pend_call(void (*func)(int arg1, void * arg2), int arg1, void * arg2)
+{
+       unsigned long flags;
+
+       if(func==NULL)
+               return -EINVAL;
+       if(rt_pend_tq_irq<=0)
+               return -ENODEV;
+       comedi_spin_lock_irqsave(&rt_pend_tq_lock, flags);
+       INC_CIRCULAR_PTR(rt_pend_head,rt_pend_tq,RT_PEND_TQ_SIZE);
+       if(rt_pend_head==rt_pend_tail) {
+               // overflow, we just refuse to take this request
+               DEC_CIRCULAR_PTR(rt_pend_head,rt_pend_tq,RT_PEND_TQ_SIZE);
+               comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags);
+               return -EAGAIN;
+       }
+       rt_pend_head->func=func;
+       rt_pend_head->arg1=arg1;
+       rt_pend_head->arg2=arg2;
+       comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags);
+#ifdef CONFIG_COMEDI_RTAI
+       rt_pend_linux_srq(rt_pend_tq_irq);
+#endif
+#ifdef CONFIG_COMEDI_RTL
+       rtl_global_pend_irq(rt_pend_tq_irq);
+#endif
+       return 0;
+}
+
+#ifdef CONFIG_COMEDI_RTAI
+void rt_pend_irq_handler(void)
+#endif
+#ifdef CONFIG_COMEDI_RTL
+void rt_pend_irq_handler(int irq, void *dev, struct pt_regs * regs)
+#endif
+{
+       while(rt_pend_head!=rt_pend_tail) {
+               INC_CIRCULAR_PTR(rt_pend_tail,rt_pend_tq,RT_PEND_TQ_SIZE);
+               rt_pend_tail->func(rt_pend_tail->arg1,rt_pend_tail->arg2);
+       }
+}
+
+int rt_pend_tq_init(void)
+{
+       rt_pend_head=rt_pend_tail=rt_pend_tq;
+#ifdef CONFIG_COMEDI_RTAI
+       rt_pend_tq_irq=rt_request_srq(0,rt_pend_irq_handler,NULL);
+#endif
+#ifdef CONFIG_COMEDI_RTL
+       rt_pend_tq_irq=rtl_get_soft_irq(rt_pend_irq_handler,"rt_pend_irq");
+#endif
+       if(rt_pend_tq_irq>0)
+               printk("rt_pend_tq: RT bottom half scheduler initialized OK\n");
+       else
+               printk("rt_pend_tq: rtl_get_soft_irq failed\n");
+       return 0;
+}
+
+void rt_pend_tq_cleanup(void)
+{
+       printk("rt_pend_tq: unloading\n");
+#ifdef CONFIG_COMEDI_RTAI
+       rt_free_srq(rt_pend_tq_irq);
+#endif
+#ifdef CONFIG_COMEDI_RTL
+       free_irq(rt_pend_tq_irq,NULL);
+#endif
+}
+
diff --git a/comedi/rt_pend_tq.h b/comedi/rt_pend_tq.h
new file mode 100644 (file)
index 0000000..5475a0c
--- /dev/null
@@ -0,0 +1,9 @@
+#define RT_PEND_TQ_SIZE 16
+struct rt_pend_tq {
+       void (*func)(int arg1, void * arg2);
+       int arg1;
+       void *arg2;
+} ;
+extern int rt_pend_call(void (*func)(int arg1, void * arg2), int arg1, void * arg2);
+extern int rt_pend_tq_init(void);
+extern void rt_pend_tq_cleanup(void);