[EMAIL PROTECTED] wrote:
> 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?
These functions just call device specific functions. For the FIFOS there are no
device specific functions (although changing the size of
a FIFO should be an ioctl through the Posix interface). The main reason I use mmap is
to implement a driver for a PCI device that needs
its memory mapped. Obviously, if the mmap call has to call the kernel mmapper then it
can only be done during initialization (which is my
case). The reason I decided to implement mmap through the posix interface was because
I compile my module for use in either user space
(for debugging) or the real-time kernel.
>
>
> >
> > 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?
I want to be sure that the RT kernel does not interrupt while the callback is being
run.
>
>
> >
> > 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/