On Tue, Jan 18, 2000 at 06:15:44PM -0800, Robert Kavaler wrote:
> We have been using RTLinux for some time now, and I have been making
> changes to some of the prepackaged libraries, mainly rtl_fifo. I am
> presenting them here so that they may be incorporated into the kernel so
> that I don't have to constantly patch downloaded kernels. There are
> three changes that I made to the fifo stuff, and one to the posixio
> stuff:
>
> 1. Fixed a "bug" in rtf_put so that the return value is the number of
> bytes written (I think that this is an old bug but I only joined the
> newsgroup recently).
fixed in 2.0
> 2. Added a reference counter callback to the rt process that gets
> executed when a user opens and closes a fifo. I needed this in order to
> prevent a realtime module from being unloaded when a user has the fifo
> open. The logic in the fifo stuff doesn't handle this case, so I just
> wanted to prevent it from occuring. This callback is also useful to
> clean up after the user task exits, especially if the user task crashes.
I've been meaning to do this, good.
>
> 3. Filled in the posixio interface for rtl_fifo so that it does
> something reasonable instead of just returning 0.
Fixed in 2.0 I believe.
> 4. Added mmap and ioctl functions to the posix interface, if that makes
> sense.
What do they do?
>
> I also have a question regarding the both my reference counter callback
> and the standard fifo user callback. The way I see it implemented, the
> callbacks run at the linux kernel level and not the realtime kernel
> level. Thus, either callback can be interrupted by the realtime kernel
> and not run to completion until after the rt tasks are executed. Thus,
> the callback code is not actually synchonized to the realtime kernel.
> This seems like a problem. How can I synchonize the callback to a rt
> kernel task?
Can you be more precise about what you want?
The 2.0.pre1 has new RT callbacks with fifo, but perhaps this is not what you want?
>
> By the way, I am using the beta13 release of RTLinux with a 2.2.11
> kernel.
>
> Robert Kavaler
>
> Index: linux/rt-kernel/i386/beta13/rtl/include/rtl_fifo.h
> diff -u linux/rt-kernel/i386/beta13/rtl/include/rtl_fifo.h:1.1
>linux/rt-kernel/i386/beta13/rtl/include/rtl_fifo.h:1.5
> --- linux/rt-kernel/i386/beta13/rtl/include/rtl_fifo.h:1.1 Tue Aug 17 17:32:14
>1999
> +++ linux/rt-kernel/i386/beta13/rtl/include/rtl_fifo.h Tue Jan 18 16:51:24
>2000
> @@ -20,6 +20,18 @@
>
>
>
> +/* attach a reference counter callback to an RT-FIFO
> + *
> + * Used to allow modules to keep track of user tasks that have a fifo
> + * open so that they can prevent being unloaded. The callback
> + * ref_counter is called with inc = 1 when a user opens the fifo,
> + * -1 when the user closes a fifo.
> + */
> +extern int rtf_create_ref_counter(unsigned int fifo, /* RT-FIFO */
> + void (*ref_counter)(unsigned int fifo, int inc) /* function to be called */);
> +
> +
> +
> /* create an RT-FIFO
> *
> * An RT-FIFO \arg{fifo} is created with initial size of \arg{size}.
> Index: linux/rt-kernel/i386/beta13/rtl/include/arch-i386/rt_irq.h
> diff -u linux/rt-kernel/i386/beta13/rtl/include/arch-i386/rt_irq.h:1.1
>linux/rt-kernel/i386/beta13/rtl/include/arch-i386/rt_irq.h:1.2
> --- linux/rt-kernel/i386/beta13/rtl/include/arch-i386/rt_irq.h:1.1 Tue Aug 17
>17:32:14 1999
> +++ linux/rt-kernel/i386/beta13/rtl/include/arch-i386/rt_irq.h Mon Nov 29
>12:44:02 1999
> @@ -27,7 +27,7 @@
> return rtl_request_global_irq(irq, rtl_compat_irq_handler);
> }
>
> -extern int free_RTirq(unsigned int irq)
> +extern inline int free_RTirq(unsigned int irq)
> {
> return rtl_free_global_irq (irq);
> }
> Index: linux/rt-kernel/i386/beta13/rtl/fifos/rtl_fifo.c
> diff -u linux/rt-kernel/i386/beta13/rtl/fifos/rtl_fifo.c:1.1
>linux/rt-kernel/i386/beta13/rtl/fifos/rtl_fifo.c:1.5
> --- linux/rt-kernel/i386/beta13/rtl/fifos/rtl_fifo.c:1.1 Tue Aug 17 17:32:14
>1999
> +++ linux/rt-kernel/i386/beta13/rtl/fifos/rtl_fifo.c Tue Jan 18 16:49:49 2000
> @@ -42,6 +42,7 @@
> int start;
> int len;
> int (*user_handler) (unsigned int fifo);
> + void (*ref_counter)(unsigned int fifo, int inc);
> struct wait_queue *wait;
> struct tq_struct wake_up_task;
> };
> @@ -58,6 +59,7 @@
> #define RTF_BUF(minor) (RTF_ADDR(minor)->bufsize)
> #define RTF_START(minor) (RTF_ADDR(minor)->start)
> #define RTF_HANDLER(minor) (RTF_ADDR(minor)->user_handler)
> +#define RTF_REF_COUNTER(minor) (RTF_ADDR(minor)->ref_counter)
> #define RTF_LEN(minor) (RTF_ADDR(minor)->len)
> #define RTF_FREE(minor) (RTF_BUF(minor) - RTF_LEN(minor))
> #define RTF_WAIT(minor) (RTF_ADDR(minor)->wait)
> @@ -149,6 +151,7 @@
> RTF_SLEEPS(minor) = 0;
> RTF_USER_OPEN(minor) = 0;
> RTF_HANDLER(minor) = &default_user_handler;
> + RTF_REF_COUNTER(minor) = NULL;
>
> RTF_WAKE_UP_TASK(minor).next = 0;
> RTF_WAKE_UP_TASK(minor).sync = 0;
> @@ -189,6 +192,15 @@
> }
>
>
> +int rtf_create_ref_counter(unsigned int minor, void (*ref_counter)(unsigned int
>fifo, int inc))
> +{
> + if (minor >= RTF_NO || !RTF_OPEN(minor) || !ref_counter) {
> + return -EINVAL;
> + }
> + RTF_REF_COUNTER(minor) = ref_counter;
> + return 0;
> +}
> +
> /* these can be called from RT tasks and interrupt handlers */
> static void fifo_wake_sleepers(int );
>
> @@ -231,7 +243,7 @@
> }
> rtl_end_critical(interrupt_state);
> fifo_wake_sleepers(minor);
> - return count;
> + return written;
> }
>
>
> @@ -301,6 +313,9 @@
> RTF_USER_OPEN(minor) = 1;
>
> MOD_INC_USE_COUNT;
> + if(RTF_REF_COUNTER(minor)) {
> + (*RTF_REF_COUNTER(minor))(minor, 1);
> + }
> return 0;
> }
>
> @@ -316,6 +331,9 @@
> RTF_SLEEPS(minor) = 0;
> RTF_USER_OPEN(minor) = 0;
> MOD_DEC_USE_COUNT;
> + if(RTF_REF_COUNTER(minor)) {
> + (*RTF_REF_COUNTER(minor))(minor, -1);
> + }
> return 0;
> }
>
> @@ -520,15 +538,18 @@
>
> static int rtl_rtf_open (struct rtl_file *filp)
> {
> + int ret;
> +
> if (!(filp->f_flags & O_NONBLOCK)) {
> return -EACCES; /* TODO: implement blocking IO */
> }
> - return 0;
> + ret = rtf_create(RTL_MINOR_FROM_FILEPTR(filp), 2048);
> + return (ret == 0 || ret == -EBUSY) ? 0 : ret;
> }
>
> static int rtl_rtf_release (struct rtl_file *filp)
> {
> - return 0;
> + return rtf_destroy(RTL_MINOR_FROM_FILEPTR(filp));
> }
>
> static ssize_t rtl_rtf_write(struct rtl_file *filp, const char *buf, size_t count,
>loff_t* ppos)
> Index: linux/rt-kernel/i386/beta13/rtl/system/rtl_posixio.c
> diff -u linux/rt-kernel/i386/beta13/rtl/system/rtl_posixio.c:1.1
>linux/rt-kernel/i386/beta13/rtl/system/rtl_posixio.c:1.2
> --- linux/rt-kernel/i386/beta13/rtl/system/rtl_posixio.c:1.1 Tue Aug 17 17:32:16
>1999
> +++ linux/rt-kernel/i386/beta13/rtl/system/rtl_posixio.c Mon Aug 30 19:23:41
>1999
> @@ -15,7 +15,10 @@
> #include <linux/fcntl.h>
> #include <linux/errno.h>
> #include <linux/ctype.h>
> +#include <linux/mm.h>
>
> +#include <asm/io.h>
> +
> #include <rtl_posixio.h>
>
> #define MAX_RTL_FILES 128
> @@ -127,25 +130,55 @@
> ssize_t write(int fd, const void *buf, size_t count)
> {
> CHECKFD(fd);
> - return rtl_files[fd] . f_op -> write (&rtl_files[fd], buf, count, 0);
> + return (rtl_files[fd] . f_op -> write) ?
> + rtl_files[fd] . f_op -> write (&rtl_files[fd], buf, count, 0) :
> + -EINVAL;
> }
>
> ssize_t read(int fd, void *buf, size_t count)
> {
> CHECKFD(fd);
> - return rtl_files[fd] . f_op -> read (&rtl_files[fd], buf, count, 0);
> + return (rtl_files[fd] . f_op -> read) ?
> + rtl_files[fd] . f_op -> read (&rtl_files[fd], buf, count, 0) :
> + -EINVAL;
> }
>
> caddr_t mmap(void *start, size_t length, int prot , int flags, int fd, off_t
>offset)
> {
> - return (caddr_t) -EINVAL;
> + struct vm_area_struct vm;
> +
> + if ((unsigned int) (fd) >= MAX_RTL_FILES || !rtl_files[fd].f_op) {
> + return NULL;
> + }
> + if(rtl_files[fd] . f_op -> mmap == NULL || start != 0) {
> + return NULL;
> + }
> + vm . vm_offset = offset;
> + vm . vm_start = 0;
> + vm . vm_end = length;
> + if(rtl_files[fd] . f_op -> mmap (&rtl_files[fd], &vm) != 0) {
> + return NULL;
> + }
> + return (caddr_t) vm . vm_start;
> +
> +
> }
>
> -int munmap(void *start, size_t length)
> +int
> +munmap(void *start, size_t length)
> {
> - return -EINVAL;
> + iounmap(start);
> + return 0;
> }
>
> +int ioctl(int fd, unsigned int cmd, unsigned long arg)
> +{
> + CHECKFD(fd);
> +
> + return (rtl_files[fd] . f_op -> ioctl) ?
> + rtl_files[fd] . f_op -> ioctl (&rtl_files[fd], cmd, arg) :
> + -EINVAL;
> +}
>
> int init_module(void)
> {
--
---------------------------------------------------------
Victor Yodaiken
FSMLabs: www.fsmlabs.com www.rtlinux.com
FSMLabs is a servicemark and a service of
VJY Associates L.L.C, New Mexico.
--- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
----
For more information on Real-Time Linux see:
http://www.rtlinux.org/~rtlinux/