Re: rt_task_unblock() POSIX alternative
Petr Červenka
grugh at centrum.cz
Thu Apr 9 17:00:09 CEST 2020
> BTW:
> Why do you think nothing can interrupt a read() from a timerfd?
> If read() blocks on a timerfd the calling thread will be put into
> interruptable sleep.
"I" was not able to send a signal to the task and interrupt it.
Here is an example. Please let me know, how to improve it to interrupt the read() before its timeout:
#include <math.h>
#include <pthread.h>
#include <stdint.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/timerfd.h>
#include <unistd.h>
#define AUTO_KILL
#define SECOND 1000000000l // ns
#define PERIOD (5 * SECOND) // ns
#define SLEEP (1 * SECOND) // ns
using namespace std;
static pid_t mainTask_pid;
static pthread_t task;
static int timer_fd;
static bool end = false;
void signalHandler(int signal) {
int err;
printf("Signal handler: %d\n", signal);
end = true;
err = pthread_kill(task, SIGINT);
if (err != 0) {
printf("pthread_kill failed: %d (%s)\n", err, strerror(-err));
}
printf("Signal handler end\n");
}
void timediff (struct timespec *result, const struct timespec *t1, const struct timespec *t2) {
result->tv_sec = t2->tv_sec - t1->tv_sec;
result->tv_nsec = t2->tv_nsec - t1->tv_nsec;
if (result->tv_nsec >= SECOND) {
result->tv_nsec -= SECOND;
result->tv_sec++;
}
if (result->tv_nsec < 0) {
result->tv_nsec += SECOND;
result->tv_sec--;
}
}
static void *taskHandler(void *cookie) {
int err;
printf("Task started\n");
signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
// Get current time
struct timespec start;
clock_gettime(CLOCK_MONOTONIC, &start);
// Set task period
timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
struct itimerspec timer_conf;
timer_conf.it_value.tv_sec = start.tv_sec;
timer_conf.it_value.tv_nsec = start.tv_nsec;
timer_conf.it_interval.tv_sec = PERIOD / SECOND;
timer_conf.it_interval.tv_nsec = PERIOD % SECOND;
printf("Set period: %.3gs\n", timer_conf.it_interval.tv_sec + (double) timer_conf.it_interval.tv_nsec / SECOND);
err = timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &timer_conf, NULL);
if (err != 0) {
printf("timerfd_settime failed: %d (%s)\n", err, strerror(-err));
return NULL;
}
// Main cycle
while (!end) {
// Wait next period
uint64_t ticks;
::read(timer_fd, &ticks, sizeof (ticks));
// Get current time
struct timespec now, result;
clock_gettime(CLOCK_MONOTONIC, &now);
// Printf wait time
timediff(&result, &start, &now);
printf("Task livind: %.3gs\n", result.tv_sec + (double) result.tv_nsec / SECOND);
start = now;
}
::close(timer_fd);
printf("Task ended\n");
}
/*
*
*/
int main(int argc, char** argv) {
unsigned long overruns;
int err;
mlockall(MCL_CURRENT | MCL_FUTURE);
// Setup signal handler
signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
// Get current process ID
mainTask_pid = getpid();
// Make main task real-time (prio 1)
sched_param param;
memset(¶m, 0, sizeof(param));
param.sched_priority = 1;
err = sched_setscheduler(mainTask_pid, SCHED_FIFO, ¶m);
if (err != 0) {
printf("sched_setscheduler failed: %d (%s)\n", err, strerror(-err));
goto sched_setscheduler_err;
}
// Create new task (prio 2)
pthread_attr_t tattr;
pthread_attr_init(&tattr);
pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&tattr, SCHED_FIFO);
memset(¶m, 0, sizeof (param));
param.sched_priority = 2;
pthread_attr_setschedparam(&tattr, ¶m);
err = pthread_create(&task, &tattr, taskHandler, NULL);
if (err != 0) {
printf("pthread_create failed: %d (%s)\n", err, strerror(-err));
goto pthread_create_err;
}
#ifndef AUTO_KILL
printf("Press ^C to stop!\n");
do {
pause();
} while(!end);
#else
usleep(SLEEP / 1000);
// Call of signal handler
err = kill(0, SIGINT); // THE ONLY ONE WHICH WORKS !!!
//err = kill(getpid(), SIGINT);
//err = kill(mainTask_pid, SIGINT);
//err = pthread_kill(pthread_self(), SIGINT);
//err = pthread_kill(task, SIGINT);
if (err != 0) {
printf("pthread_kill failed: %d (%s)\n", err, strerror(-err));
}
#endif
printf("Waiting for join\n");
//pthread_cancel(task);
pthread_join(task, NULL);
pthread_create_err:
sched_setaffinity_err:
sched_setscheduler_err:
return 0;
}
More information about the Xenomai
mailing list