If I run the attached program, I get the following result:
[root]# ./mqtest2
CPU time limit exceeded
The kernel log contains:
Oct 25 14:13:03 kernel: invalid use of FPU in Xenomai context at 0x80492f6
If I change the WRITE_SIZE #define at the top of the program to 511 instead of
512, I do not get an error message, and the program works as expected.
I have tried this under two versions of Xenomai with the same result:
1) Xenomai 2.2.3 with the FPU patch posted here:
https://mail.gna.org/public/xenomai-help/2006-09/msg00157.html
(adeos-ipipe-2.6.17-i386-1.4-00.patch)
2) Xenomai 2.2.4 (adeos-ipipe-2.6.17-i386-1.5-00.patch)
Other details:
Linux version 2.6.17.13
AMD Athlon(tm)64 X2 Dual Core Processor 4400+
Fedora Core 5
SMP kernel
This is very similar to a problem I described last month that affected my
linux-2.4 system:
https://mail.gna.org/public/xenomai-help/2006-09/msg00143.html . Perhaps these
problems are related.
Does anyone see a problem with what I'm doing here? If not, can you reproduce
the problem?
Thanks,
Jeff
/* Standard includes */
#include <stdio.h>
#include <errno.h>
#include <pthread.h> /* POSIX threads and timers */
#include <stdlib.h> /* Exit status macros and atexit */
#include <signal.h> /* POSIX signals (sigaction) */
#include <sys/mman.h> /* Memory management (mlockall) */
#include <sys/stat.h> /* File creation modes (for mq_open) */
#include <mqueue.h> /* POSIX message queues */
#include <error.h> /* GNU error function */
#include <string.h> /* String manipulation (strlen) */
/* Constants */
#define STACK_SIZE 1024*1024*8
#define QUEUE_MSG_SIZE 1024
#define QUEUE_MAX_MSGS 10
#define QUEUE_NAME "/queue1"
#define PRIORITY 10
#define WRITE_SIZE 512
/* Global variables */
sig_atomic_t abort_program = 0;
pthread_t rt_thread;
mqd_t queue1;
mqd_t queue1_rt;
int count = 0;
char send_buffer[QUEUE_MSG_SIZE];
char receive_buffer[QUEUE_MSG_SIZE];
/* Real-time thread cleanup routines */
void rt_thread_cleanup_queue1_rt (void * arg)
{
mq_close(queue1_rt);
}
/* Real-time periodic thread code */
void * rt_loop(void * arg)
{
double f = 0.0;
/* Open the message queue */
queue1_rt = mq_open(QUEUE_NAME, O_WRONLY | O_NONBLOCK);
if (queue1_rt == (mqd_t) -1)
error(0, errno, "could not open message queue '%s'", QUEUE_NAME);
pthread_cleanup_push(rt_thread_cleanup_queue1_rt, NULL);
pthread_set_mode_np(0, PTHREAD_WARNSW);
/* Loop until the thread is cancelled */
while (1)
{
/* Count the number of times this loop is executed */
count++;
/* Sleep for 1 second */
{
struct timespec dt_ts;
dt_ts.tv_sec = 1;
dt_ts.tv_nsec = 0;
clock_nanosleep(CLOCK_REALTIME, 0, &dt_ts, NULL);
}
/* Send a message to the non-rt thread */
{
int err;
snprintf(send_buffer, QUEUE_MSG_SIZE, "count: %d %f", count, f);
err = mq_send(queue1_rt, send_buffer, WRITE_SIZE, PRIORITY);
if (err)
error(0, errno, "could not write to message queue '%s'",
QUEUE_NAME);
f = f + 0.1*count;
}
}
/* Clean up thread resources */
pthread_cleanup_pop(1);
return NULL;
}
/* Handle POSIX signals */
void signal_handler(int sig)
{
abort_program = 1;
}
/* Cleanup routines */
void cleanup_queue1(void)
{
/* Close the message queue */
mq_close(queue1);
/* Delete the message queue */
mq_unlink(QUEUE_NAME);
}
void cleanup_rt_thread(void)
{
/* Tell the real-time thread to terminate */
pthread_cancel(rt_thread);
/* Wait for the real-time thread to terminate */
pthread_join(rt_thread, NULL);
}
/* Main program */
int main(void)
{
int err;
/* Disable paging for this program's memory */
err = mlockall(MCL_CURRENT | MCL_FUTURE);
if (err)
error(EXIT_FAILURE, errno,
"could not disable memory paging for this program");
/* Set the scheduling policy of the main program */
{
struct sched_param sparam;
sparam.sched_priority = 0; /* Must be zero for SCHED_OTHER */
err = pthread_setschedparam(pthread_self(), SCHED_OTHER, &sparam);
if (err)
error(EXIT_FAILURE, err,
"error setting schedule parameters for main program");
}
/* Install POSIX signal handlers */
{
struct sigaction new_action;
int * sig_ptr;
int signals[] = {SIGTERM, SIGQUIT, SIGHUP, SIGINT, 0};
new_action.sa_handler = signal_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
for (sig_ptr = signals; *sig_ptr != 0; sig_ptr++)
{
err = sigaction(*sig_ptr, &new_action, NULL);
if (err)
error(EXIT_FAILURE, errno,
"could not install signal handler for signal %d", *sig_ptr);
}
}
/* Create a message queue */
{
struct mq_attr attr;
attr.mq_flags = 0;
attr.mq_maxmsg = QUEUE_MAX_MSGS;
attr.mq_msgsize = QUEUE_MSG_SIZE;
mq_unlink(QUEUE_NAME);
queue1 = mq_open(QUEUE_NAME, O_RDONLY | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR | S_IXUSR, &attr);
if (queue1 == (mqd_t) -1)
error(EXIT_FAILURE, errno, "could not create message queue '%s'",
QUEUE_NAME);
atexit(cleanup_queue1);
}
/* Create the real-time task */
{
pthread_attr_t attr;
size_t stacksize = STACK_SIZE;
struct sched_param sparam;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setstacksize (&attr, stacksize);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
sparam.sched_priority = 99; /* High priority */
pthread_attr_setschedparam(&attr, &sparam);
pthread_create(&rt_thread, &attr, &rt_loop, NULL);
pthread_attr_destroy(&attr);
if (err)
error(EXIT_FAILURE, err, "could not create thread");
atexit(cleanup_rt_thread);
}
/* Wait for program to be aborted with <ctrl-c> */
while(!abort_program)
{
int err;
/* Wait for data from the rt thread */
err = mq_receive(queue1, receive_buffer, QUEUE_MSG_SIZE, NULL);
if (err < 0)
error(0, errno, "error reading from message queue '%s'", QUEUE_NAME);
else
/* Print the message */
printf("received message: %s\n", receive_buffer);
}
/* Print the final loop count */
printf("final count = %d\n", count);
/* Cleanup is handled by atexit functions */
return EXIT_SUCCESS;
}
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help