Hello,
 
 
Apparently, the code I shared with Gilles never made it to this forum. Anyway, the issue I'm having here is really a problem and it might be useful if some of you could try it out or comment on it. I might be making a silly programming error here, but the result is invariably erroneous operation or kernel crashes.
 
The program creates a file dump.txt and has two independent threads trying to access it and write a one or a zero there. Inside the writing routine, which is accessed by both threads, a check is made to see if the access is really locked. In my setup, I have tons of ALERTS popping up with this program, meaning that something is wrong with my use of mutex. Could anyone please check and see if a) it is correctly written and b) it fails as well on their machine. It would allow me to focus my actions on the Xenomai setup (which I keep frozen this instant, in order to keep a possible bug predictable) or on my own programming.
 
A second example is also included, which tries to achieve the same goal with a semaphore (initialized to 1). That seems to work, but under heavy load (tmax = 1.0e7), the kernel crashes.
 
Kernel: 2.6.15 Adeos: 1.1-03 gcc: 4.0.2 Ipipe tracing enabled
 
TIA
 
Jeroen.
 
 

/* TEST_MUTEX.C */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <math.h>
#include <values.h>

#include <sys/mman.h>

#include <native/task.h>
#include <native/mutex.h>
#include <native/sem.h>

int fd, err;
RT_MUTEX m;
RT_SEM s;
float tmax = 1.0e7;

#define CHECK(arg) check(arg, __LINE__)

int check(int r, int n)
{
    if (r != 0)
        fprintf(stderr, "L%d: %s.\n", n, strerror(-r));
    return(r);
}

void output(char c) {
    static int cnt = 0;
    int n;
    char buf[2];
    RT_MUTEX_INFO mutexinfo;
   
    buf[0] = c;
   
    if (cnt == 80) {
        buf[1] = '\n';
        n = 2;
        cnt = 0;
    }
    else {
        n = 1;
        cnt++;
    }
   
    CHECK(rt_mutex_inquire(&m, &mutexinfo));
    if (mutexinfo.lockcnt <= 0) {
        RT_TASK_INFO taskinfo;
        CHECK(rt_task_inquire(NULL, &taskinfo));
        fprintf(stderr, "ALERT: No lock! (lockcnt=%d) Offending task: %s\n",
                mutexinfo.lockcnt, taskinfo.name );
    }
  
    if (write(fd, buf, n) != n) {
        fprintf(stderr, "File write error.\n");
        CHECK(rt_sem_v(&s));
    }
   
}

void task0(void *arg)
{
    CHECK(rt_task_set_mode(T_PRIMARY, 0, NULL));
    while (1) {
        CHECK(rt_task_sleep((float)rand()*tmax/(float)RAND_MAX));
        CHECK(rt_mutex_lock(&m, TM_INFINITE));
        output('0');
        CHECK(rt_mutex_unlock(&m));
    }
}

void task1(void *arg)
{
    CHECK(rt_task_set_mode(T_PRIMARY, 0, NULL));
    while (1) {
        CHECK(rt_task_sleep((float)rand()*tmax/(float)RAND_MAX));
        CHECK(rt_mutex_lock(&m, TM_INFINITE));
        output('1');
        CHECK(rt_mutex_unlock(&m));
    }
}

void sighandler(int arg)
{
    CHECK(rt_sem_v(&s));
}

int main(int argc, char *argv[])
{
    RT_TASK t, t0, t1;
   
    if ((fd = open("dump.txt", O_CREAT | O_TRUNC | O_WRONLY)) < 0)
        fprintf(stderr, "File open error.\n");
    else {
        if (argc == 2) {
            tmax = atof(argv[1]);
            if (tmax == 0.0)
                tmax = 1.0e7;
        }
        if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0)
            printf("mlockall() error.\n");
       
        CHECK(rt_task_shadow(&t, "main", 1, T_FPU));

        CHECK(rt_timer_start(TM_ONESHOT));
       
        CHECK(rt_mutex_create(&m, "mutex"));
        CHECK(rt_sem_create(&s, "sem", 0, S_PRIO));

        signal(SIGINT, sighandler);
       
        CHECK(rt_task_create(&t0, "task0", 0, 30, T_FPU));
        CHECK(rt_task_start(&t0, task0, NULL));
        CHECK(rt_task_create(&t1, "task1", 0, 29, T_FPU));
        CHECK(rt_task_start(&t1, task1, NULL));

        printf("Running for %.2f seconds.\n", (float)MAXLONG/1.0e9);
        CHECK(rt_sem_p(&s, MAXLONG));
        signal(SIGINT, SIG_IGN);
       
        CHECK(rt_task_delete(&t1));
        CHECK(rt_task_delete(&t1));
        CHECK(rt_task_delete(&t0));
       
        CHECK(rt_sem_delete(&s));
        CHECK(rt_mutex_delete(&m));
       
        rt_timer_stop();
       
        close(fd);
    }
    return 0;
}

/*************************************************************************************/ 

/* TEST_SEM.C */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <math.h>
#include <values.h>

#include <sys/mman.h>

#include <native/task.h>
#include <native/sem.h>

int fd, err;
RT_SEM s, m;
float tmax = 1.0e9;

#define CHECK(arg) check(arg, __LINE__)

int check(int r, int n)
{
    if (r != 0)
        fprintf(stderr, "L%d: %s.\n", n, strerror(-r));
    return(r);
}

void output(char c) {
    static int cnt = 0;
    int n;
    char buf[2];
    RT_SEM_INFO seminfo;
   
    buf[0] = c;
   
    if (cnt == 80) {
        buf[1] = '\n';
        n = 2;
        cnt = 0;
    }
    else {
        n = 1;
        cnt++;
    }
   
    CHECK(rt_sem_inquire(&m, &seminfo));
    if (seminfo.count != 0) {
        RT_TASK_INFO taskinfo;
        CHECK(rt_task_inquire(NULL, &taskinfo));
        fprintf(stderr, "ALERT: No lock! (count=%ld) Offending task: %s\n",
                seminfo.count, taskinfo.name);
    }
  
    if (write(fd, buf, n) != n) {
        fprintf(stderr, "File write error.\n");
        CHECK(rt_sem_v(&s));
    }
   
}

void task0(void *arg)
{
    CHECK(rt_task_set_mode(T_PRIMARY, 0, NULL));
    while (1) {
        CHECK(rt_task_sleep((float)rand()*tmax/(float)RAND_MAX));
        CHECK(rt_sem_p(&m, TM_INFINITE));
        output('0');
        CHECK(rt_sem_v(&m));
    }
}

void task1(void *arg)
{
    CHECK(rt_task_set_mode(T_PRIMARY, 0, NULL));
    while (1) {
        CHECK(rt_task_sleep((float)rand()*tmax/(float)RAND_MAX));
        CHECK(rt_sem_p(&m, TM_INFINITE));
        output('1');
        CHECK(rt_sem_v(&m));
    }
}

void sighandler(int arg)
{
    CHECK(rt_sem_v(&s));
}

int main(int argc, char *argv[])
{
    RT_TASK t, t0, t1;
   
    if ((fd = open("dump.txt", O_CREAT | O_TRUNC | O_WRONLY)) < 0)
        fprintf(stderr, "File open error.\n");
    else {
        if (argc == 2) {
            tmax = atof(argv[1]);
            if (tmax == 0.0)
                tmax = 1.0e7;
        }
        if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0)
            printf("mlockall() error.\n");
       
        CHECK(rt_task_shadow(&t, "main", 1, T_FPU));

        CHECK(rt_timer_start(TM_ONESHOT));
       
        CHECK(rt_sem_create(&m, "mutex", 1, S_PRIO));
        CHECK(rt_sem_create(&s, "sem", 0, S_PRIO));

        signal(SIGINT, sighandler);
       
        CHECK(rt_task_create(&t0, "task0", 0, 30, T_FPU));
        CHECK(rt_task_start(&t0, task0, NULL));
        CHECK(rt_task_create(&t1, "task1", 0, 29, T_FPU));
        CHECK(rt_task_start(&t1, task1, NULL));

        printf("Running for %.2f seconds.\n", (float)MAXLONG/1.0e9);
        CHECK(rt_sem_p(&s, MAXLONG));
        signal(SIGINT, SIG_IGN);
       
        CHECK(rt_task_delete(&t1));
        CHECK(rt_task_delete(&t1));
        CHECK(rt_task_delete(&t0));
       
        CHECK(rt_sem_delete(&s));
        CHECK(rt_sem_delete(&m));
       
        rt_timer_stop();
       
        close(fd);
    }
    return 0;
}

Reply via email to