Hello,

I observed a very special behaviour. it turns
up in RTLinux V2.2 and V3.0. I took the irqsema program
of the examples, added a new periodic thread that does nothing
else than calling pthread_wait_np() (refer to the appended code).
Then I used irq 9 instead of irq 14, which is coupled with a second
timer chip (8254) in our system, that can generate an interrupt every
2ms, for example. Additionally, a process (loop.c) running
in user space inverts a bit of the parallel port
interface and then goes to sleep (refer to appended code).

I overseved the following:
I first start loop.c. As expected, the signal is inverted every 10ms.
Then, I insert irqsema.o. As soon as I start my private timer with 2ms
period,
the signal is streched from 10 to 40ms! (equal to the period argument in
pthread_make_periodic_np
of process spin_thread in irqsema.c) This means that now process loop
only
is waked up every 40ms!?!? As soon as I turn of my private timer
interrupt, it is
again waked up every 10ms.

Things get even more strange if I leave out the pthread_make_periodic_np
call of
spin_thread. As soon as the timer generates an interrupt every 2ms,
process loop is never
waked up again, it seems that the linux scheduler does not run anymore.

The problems do not turn up if the timer interrupt only occurs every
200ms, for example.

Has anyone observed a similar behaviour? Have I a mistake in my program
or is it
maybe a RTLinux bug?

Thanks,
Stephan

==========================================================
diff irqsema.c irqsema.c.orig 

23c23
< int irq=9;
---
> int irq=14;
32d31
< pthread_t spin_thread;
37,46d35
< 
< void *my_thread(void *arg)
< {
<       while (1)
<               pthread_wait_np();
< 
<       return 0;
< }
< 
< 
125,130d113
<         /* create spin thread */
<         ret = pthread_create(&spin_thread,NULL,my_thread,NULL);
<       if (ret)
<               rtl_printf("failed to create thread: &d\n",ret);
<       pthread_make_periodic_np(spin_thread, gethrtime(), 40 * 1000 *
1000);
< 
147,148d129
<       pthread_cancel (spin_thread);
<       pthread_join (spin_thread, NULL);

==========================================================
irqsema.c:

/*
 * RTL irq test
 *
 * measures semaphore wakeup operation performance
 *
 *  (C) FSMLabs  2000. Michael Barabanov <[EMAIL PROTECTED]>
 *  Released under the GNU GENERAL PUBLIC LICENSE Version 2, June 1991
 *  Any use of this code must include this notice.
 */

#include <rtl.h>
#include <rtl_fifo.h>
#include <time.h>
#include <rtl_sched.h>
#include <rtl_sync.h>
#include <pthread.h>
#include <unistd.h>
#include <rtl_debug.h>
#include <errno.h>
#include <semaphore.h>
#include "common.h"

int irq=9;
int ntests=100;
int setfocus=0; /* 0 or 1 */

MODULE_PARM(irq,"i");
MODULE_PARM(ntests,"i");
MODULE_PARM(setfocus,"i");

pthread_t thread;
pthread_t spin_thread;
int fd_fifo;
hrtime_t irqtime;
sem_t irqsem;


void *my_thread(void *arg)
{
        while (1)
                pthread_wait_np();
        
        return 0;
}


unsigned int intr_handler(unsigned int irq, struct pt_regs *regs)
{
/*      rtl_printf("%d", rtl_getcpuid()); */
        irqtime = gethrtime();
        rtl_global_pend_irq (irq);
        sem_post(&irqsem);
        return 0;
}


void *thread_code(void *param) {

        hrtime_t diff;
        hrtime_t now;
        hrtime_t min_diff;
        hrtime_t max_diff;
        struct sample samp;
        int i;
        int cpu_id = rtl_getcpuid();

        rtl_printf ("Measurement task starts on CPU %d\n", cpu_id);

        fd_fifo = open("/dev/rtf0", O_NONBLOCK);
        if (fd_fifo < 0) {
                rtl_printf("/dev/rtf0 open returned %d\n", fd_fifo);
                return (void *) -1;
        }

        do {
                min_diff = 2000000000;
                max_diff = -2000000000;

                for (i = 0; i < ntests; i++) {
                        sem_wait (&irqsem);
                        now = gethrtime();

                        diff = now - irqtime;
                        if (diff < min_diff) {
                                min_diff = diff;
                        }
                        if (diff > max_diff) {
                                max_diff = diff;
                        }
                }

                samp.min = min_diff;
                samp.max = max_diff;
                write (fd_fifo, &samp, sizeof(samp));
        } while (1);
        return 0;
}


unsigned long oldaffinity;

int init_module(void)
{
        int ret;
        unsigned long affinity = 0; // = 1 << rtl_getcpuid();

        rtf_destroy(0);
        rtf_create(0, 4000);

        ret = rtl_request_irq (irq, intr_handler);
        if (ret) {
                rtl_printf("failed to get irq%d: %d\n", irq, ret);
        } else {
                rtl_printf("got irq%d\n", irq);
        }

        if (setfocus) {
                rtl_printf("setting irq%d distribution mask to %x\n", irq, affinity);
                rtl_irq_set_affinity (irq, &affinity, &oldaffinity);
        }
        sem_init (&irqsem, 1, 0);
        rtl_printf("RTL measurement module on CPU %d\n",rtl_getcpuid());
        pthread_create (&thread,  NULL, thread_code, (void *)1);

        /* create spin thread */
        ret = pthread_create(&spin_thread,NULL,my_thread,NULL);
        if (ret)
                rtl_printf("failed to create thread: &d\n",ret);
        pthread_make_periodic_np(spin_thread, gethrtime(), 40 * 1000 * 1000);

        return 0;
}


void cleanup_module(void)
{
        rtl_printf ("Removing module on CPU %d\n", rtl_getcpuid());

        rtl_free_irq (irq);
        if (setfocus) {
                rtl_irq_set_affinity (irq, &oldaffinity, NULL);
        }
        rtl_printf("freed irq%d\n", irq);

        pthread_cancel (thread);
        pthread_join (thread, NULL);
        pthread_cancel (spin_thread);
        pthread_join (spin_thread, NULL);
        sem_destroy (&irqsem);
        close(fd_fifo);
        rtf_destroy(0);
}

==========================================================
loop.c:

#include <asm/io.h>
#include <unistd.h>

#define LPT     0x378

unsigned char par[8];


void init_par(void)
{
        int i;

        ioperm(LPT, 4, 1);
        for (i=0; i<8; i++) {
                par[i] = 0;
        }
}


void set_par(int bit, int val)
{
        int i;
        unsigned char byte = 0;

        par[bit] = (val) ? 1<<bit : 0;
        for (i=0; i<8; i++) {
                byte |= par[i];
        }
        outb(byte, LPT);
}


int main()
{
        init_par();

        while (1) {
                set_par(0,1);
                usleep(0);
                set_par(0,0);
                usleep(0);
        }

        return 0;
}
-- [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/

Reply via email to