itimer expiration - c

I was using a periodic timer and taking times between when two SIGALRM signals are received. what I observed was that itimer might expires a little before or little after the time I set. e.g. if I set it for 1m sec , it might expires at 0.9998msec or 1.0023msec.
Shouldn't the timer expiration would always be greater than what is set? less time taken is what I dont understand.
here's my code:
enter code here
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <stdlib.h>
#include <time.h>
#define INTERVAL 1000
struct timespec ti[100];
int s=0;
void ex(int i)
{int d=0;
struct timespec t[100],s1,s2;
for(d=0;d<99;d++)
{
s1= ti[d];
s2= ti[d+1];
printf("%u:%u\t%u:%u\t", s1.tv_sec, s1.tv_nsec, s2.tv_sec, s2.tv_nsec);
if ((s2.tv_nsec- s1.tv_nsec)<0) {
t[d].tv_sec = s2.tv_sec-s1.tv_sec-1;
t[d].tv_nsec = 1000000000 +s2.tv_nsec -s1.tv_nsec;
} else {
t[d].tv_sec = s2.tv_sec-s1.tv_sec;
t[d].tv_nsec = s2.tv_nsec-s1.tv_nsec;
}
printf("%u:%u\n",t[d].tv_sec,t[d].tv_nsec);
}
exit(0);
}
void alarm_wakeup (int i)
{
clock_gettime(CLOCK_MONOTONIC, &ti[s]);
s++;
if(s==100)
{ ex(0);
}
}
void main ()
{
struct itimerval tout_val;
tout_val.it_interval.tv_sec = 0;
tout_val.it_interval.tv_usec = INTERVAL;
tout_val.it_value.tv_sec = 0;
tout_val.it_value.tv_usec = INTERVAL;
setitimer(ITIMER_REAL, &tout_val,0);
signal(SIGALRM,alarm_wakeup); /* set the Alarm signal capture */
signal(SIGINT,ex);
while (1)
{
}
}

When the timer expires, the signal is raised and the timer is rescheduled.
However, there can be a delay between the signal being raised and the signal being handled - if the process isn't running already, it has to be rescheduled. This means that there is a potentially variable delay between the actual expiration of the timer and when the clock_gettime() call in your signal handler runs.
If this delay before the clock_gettime() call is higher one iteration than the next, then the time between the clock_gettime() calls will be slightly less than 1ms even though there was a 1ms gap between the subsequent timer expiries.
In diagrammatic form:
time: 0ms...............1ms...............2ms...............3ms
timer expiry: X X X X
signal handler runs: S S S S
You can see that the longer delay before the second signal handler ran made the third signal appear to be "early", even though the underlying timer was not.

Related

Would pausing sleep for a second be better than constantly calling the time function to see if the next second had passed

#include <time.h>
#include <iostream>
void TemperatureCtrl(float curTemp, float TargetTemp, float errTemp);
float TemperatureGet();
int direction = 0;
int main()
{
float CurTemp;
time_t tim = 0;
struct tm ttm;
time_t tim2 = 0;
while (1)
{
time(&tim2);
if (tim != tim2)
{
tim = tim2;
localtime_r(&tim, &ttm);
CurTemp = TemperatureGet();
printf("%02d:%02d:%02d Temp:%.1f℃\r\n", ttm.tm_hour, ttm.tm_min, ttm.tm_sec, CurTemp);
TemperatureCtrl(CurTemp, 23.0, 0.5);
}
}
}
maybe used sleep(1000) is better ?
Use sleep () to pause for a second and let the thread hang for a second. It will be better for CPU usage.
maybe used sleep(1000) is better?
Yes.
Calling sleep will suspend the current thread for a specified time interval. Other threads could take the CPU to do their work, it's more efficient.
Constantly calling the time function is too inefficient. The current thread occupies the CPU, but there is no meaningful work to do.

Linux C ignore event for x seconds

I have the following arduino code:
uint32_t hold_time=600000;
uint32_t curr_time;
uint32_t last_event;
bool on_hold=false;
beginning of main loop
curr_time = millis();
if (on_hold && curr_time - last_event >= hold_time) {
on_hold = false;
}
...
if (!on_hold)
{
run the function();
on_hold = true; // Ignore this function for 1 minute
}
This basically will execute the main loop many times but the run_the_function(); only when it is unlocked so in this example once in every minute. I would like to accomplish the same in standard POSIX C which works on BSDs as well.
Since you asked for POSIX, I will give you POSIX. This is a sample code that is able to run a timer without using pthreads, but only through OS provided timers. It runs a specific function every 2 seconds. You can configure it to make it run every 60 seconds, if you prefer. I have comment thoroughly the code, and I hope it is easy enough to understand:
#include <stdlib.h> // For declaration of exit
#include <stdio.h> // For printf function
#include <signal.h> // Will be used for the signal callbacks
#include <time.h> // Timer and current time stuff
#define TIMER_SECONDS 2 // To test more rapidly I will wait
// only for 2 seconds instead of a minute...
int counter = 0; // Whe want to call the timer a limited number
// of time for this example
// BEFORE READING THIS, READ THE MAIN:
// This function is your "run_the_function" callback. As for now,
// it has no arguments and returns nothing. It asks to the system the current
// time and prints it, just to check if the timer works. It uses **printf**
// and this should be avoided in signal handlers!
static void run_the_function() {
time_t rawtime; // This is the current time variable
struct tm * timeinfo; // This is a strut that contains the time
// broken down to its components
time( &rawtime ); // To get from the system the current time
timeinfo = localtime ( &rawtime ); // For splitting the time in its components
printf("Timer CALLED %d times :: %s", ++counter, asctime(timeinfo));
}
// BEFORE READING THIS, READ THE MAIN
// This is the signal handler, a function that is called when the timer
// signals that has finished to count
static void timer_callback(int sig, siginfo_t *si, void *uc) {
run_the_function();
}
int main() {
timer_t timer_id; // An unique identifier for the timer that you are creating
struct itimerspec intervals; // Specify the intervals for the timer that we are creating
struct sigevent timer_event; // The structure that handles the event generated by the timer
struct sigaction timer_action; // The action for the timer event
// First you need to implement the action to do when the timer reaches zero,
// then you need to say that you want an event for a timer that reaches zero,
// and only at the end you set the timer.
// The function "sigaction" connects your timer event to the timer signal SIGRTMIN.
// The timer_event.sigev_signo instructs to create an EVENT for the signal SIGRTMIN, and
// for that event you prepared a custom action.
// The timer sends the SIGRTMIN signal every time it reaches zero, and when you
// create it, you connect it to the timer_event.
// Now we define what is the action to perform
timer_action.sa_flags = SA_SIGINFO; // The action to perform is to run a callback
timer_action.sa_sigaction = timer_callback; // The callback is "timer_callback"
sigemptyset(&timer_action.sa_mask); // And we are initializing the event structure
if (sigaction(SIGRTMIN, &timer_action, NULL) < 0) // We are binding this action
exit(1); // to a timer event (SIGRTMIN)
timer_event.sigev_notify = SIGEV_SIGNAL; // Instruct the event that it is related to
// a signal.
timer_event.sigev_signo = SIGRTMIN; // Instruct the event that the signal to track is SIGRTMIN
// At this point we are ready to create the timer, that uses the REAL TIME CLOCK of your
// system. When it reaches zero it raise a timer_event, and it also sets the id of the
// created timer.
if (timer_create(CLOCK_REALTIME, &timer_event, &timer_id) < 0)
exit(1);
// We now need to define the times for the timer. Intervals is composed by
// two structure: it_value, that contains the current time (or the starting time
// for the first run of your timer) and it_intervals, the time at which it will be
// reset after completing one lap. If you set it_interval to zero, the timer runs only
// one time. If you set it_value to zero, the timer does not run.
intervals.it_value.tv_sec = TIMER_SECONDS;
intervals.it_value.tv_nsec = 0;
intervals.it_interval.tv_sec = TIMER_SECONDS;
intervals.it_interval.tv_nsec = 0;
// Let's setup the time and the interval of the timer, so that it starts...
if (timer_settime(timer_id, 0, &intervals, NULL) < 0)
exit(1);
// And now we have only to wait for the timer... Easy, isn't it?
printf("Let's go!\n");
while(counter < 5) { /* Do your stuff here*/ };
return 0;
}
You need to compile it with:
gcc test.c -lrt -o test
and run it with:
./test
Let's go!
Timer CALLED 1 times :: Thu May 3 15:48:29 2018
Timer CALLED 2 times :: Thu May 3 15:48:31 2018
Timer CALLED 3 times :: Thu May 3 15:48:33 2018
Timer CALLED 4 times :: Thu May 3 15:48:35 2018
Timer CALLED 5 times :: Thu May 3 15:48:37 2018

Run code for x amount of time

To preface, I am on a Unix (linux) system using gcc.
What I am stuck on is how to accurately implement a way to run a section of code for a certain amount of time.
Here is an example of something I have been working with:
struct timeb start, check;
int64_t duration = 10000;
int64_t elapsed = 0;
ftime(&start);
while ( elapsed < duration ) {
// do a set of tasks
ftime(&check);
elapsed += ((check.time - start.time) * 1000) + (check.millitm - start.millitm);
}
I was thinking this would have carried on for 10000ms or 10 seconds, but it didn't, almost instantly. I was basing this off other questions such as How to get the time elapsed in C in milliseconds? (Windows) . But then I thought that if upon the first call of ftime, the struct is time = 1, millitm = 999 and on the second call time = 2, millitm = 01 it would be calculating the elapsed time as being 1002 milliseconds. Is there something I am missing?
Also the suggestions in the various stackoverflow questions, ftime() and gettimeofday(), are listed as deprecated or legacy.
I believe I could convert the start time into milliseconds, and the check time into millseconds, then subtract start from check. But milliseconds since the epoch requires 42 bits and I'm trying to keep everything in the loop as efficient as possible.
What approach could I take towards this?
Code is incorrect calculating elapsed time.
// elapsed += ((check.time - start.time) * 1000) + (check.millitm - start.millitm);
elapsed = ((check.time - start.time) * (int64_t)1000) + (check.millitm - start.millitm);
There is some concern about check.millitm - start.millitm. On systems with struct timeb *tp, it can be expected that the millitm will be promoted to int before subtraction occurs. So the difference will be in the range [-1000 ... 1000].
struct timeb {
time_t time;
unsigned short millitm;
short timezone;
short dstflag;
};
IMO, more robust code would handle ms conversion in a separate helper function. This matches OP's "I believe I could convert the start time into milliseconds, and the check time into millseconds, then subtract start from check."
int64_t timeb_to_ms(struct timeb *t) {
return (int64_t)t->time * 1000 + t->millitm;
}
struct timeb start, check;
ftime(&start);
int64_t start_ms = timeb_to_ms(&start);
int64_t duration = 10000 /* ms */;
int64_t elapsed = 0;
while (elapsed < duration) {
// do a set of tasks
struct timeb check;
ftime(&check);
elapsed = timeb_to_ms(&check) - start_ms;
}
If you want efficiency, let the system send you a signal when a timer expires.
Traditionally, you can set a timer with a resolution in seconds with the alarm(2) syscall.
The system then sends you a SIGALRM when the timer expires. The default disposition of that signal is to terminate.
If you handle the signal, you can longjmp(2) from the handler to another place.
I don't think it gets much more efficient than SIGALRM + longjmp (with an asynchronous timer, your code basically runs undisturbed without having to do any extra checks or calls).
Below is an example for you:
#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
static jmp_buf jmpbuf;
void hndlr();
void loop();
int main(){
/*sisv_signal handlers get reset after a signal is caught and handled*/
if(SIG_ERR==sysv_signal(SIGALRM,hndlr)){
perror("couldn't set SIGALRM handler");
return 1;
}
/*the handler will jump you back here*/
setjmp(jmpbuf);
if(0>alarm(3/*seconds*/)){
perror("couldn't set alarm");
return 1;
}
loop();
return 0;
}
void hndlr(){
puts("Caught SIGALRM");
puts("RESET");
longjmp(jmpbuf,1);
}
void loop(){
int i;
for(i=0; ; i++){
//print each 100-milionth iteration
if(0==i%100000000){
printf("%d\n", i);
}
}
}
If alarm(2) isn't enough, you can use timer_create(2) as EOF suggests.

How to know if a timer has ended in C

I need to be able to start multiple timers simultaneously and know specifically if a timer has stopped or is still going.
#define RESEND_TIMEOUT 5
void timerCreate();
void timer_start(timer_t * timer, uint32 timeout);
bool timer_complete(timer_t * timer);
int main() {
timer_t resend_timer = timerCreate();
timer_start(&resend_timer, RESEND_TIMEOUT);
while(1) {
if (timer_complete(&resend_timer))
break;
}
}
void timer_start(timer_t * timer, uint32_t timeout)
{
printf("timer starting\n");
struct itimerspec it_val;
it_val.it_value.tv_sec = timeout;
it_val.it_value.tv_nsec = 0;
// timer expires once
it_val.it_interval.tv_sec = 0;
it_val.it_interval.tv_nsec = 0;
if (timer_settime(*timer, 0, &it_val, NULL) == -1) {
errExit("Could not set timeout");
}
}
// return true if timer ended
bool timer_complete(timer_t * timer)
{
if(timer_getoverrun(*timer) == 0)
return false;
else
return true;
}
I never break out of the loop. Why can't I get the overrun of the timer (it always returns 0, which means the timer has not passed its expiration)? Yet when I add a signal handler, I know that the timer expires.
I want to try timer_gettime(timer_t timerid, struct itimerspec *curr_value) inside of my timer_complete function to see if the remaining time is 0, but how can I pass the curr_value argument without having a global variable?
Last but not least, I have tried with the TIMER_ABSTIME flag when arming the timer with timer_settime. From the manpage of int timer_settime(timer_t timerid, int flags,
const struct itimerspec *new_value,
struct itimerspec * old_value):
By default, the initial expiration time specified in
new_value->it_value is interpreted relative to the current time on
the timer's clock at the time of the call. This can be modified by
specifying TIMER_ABSTIME in flags, in which case new_value->it_value
is interpreted as an absolute value as measured on the timer's clock;
that is, the timer will expire when the clock value reaches the value
specified by new_value->it_value. If the specified absolute time has
already passed, then the timer expires immediately, and the overrun
count (see timer_getoverrun(2)) will be set correctly.
I never break out of the loop. Why can't I get the overrun of the timer (it always returns 0, which means the timer has not passed its expiration)?
No, it means you had no overruns.
The OS is not going to queue timer signals even if you specify realtime signals. Overun tells you how many signals would have been queued if the wood chuck didn't chuck signals.
So consider you set a timer to go off once every second. But for some reason you didn't handle the signal. Say you had it blocked for 5 seconds. The overrun count is going to be 4 - the signal you will/are processing and the 4 you missed.
In your case you set a one-time timer to go off after "timeout" seconds. The signal was delivered. There will be no more signals hence overrun is always going to be 0, as it should be.

hrtimer repeating task in the Linux kernel

My goal is to create a recurring task in the linux kernel using the hrtimer struct. I would like it to recur every 500 ms.
However, I'm a little confused about how hrtimer works in the linux kernel (see linux/hrtimer.h). I know that the time is specified, and the callback should return either HRTIMER_RESTART or HRTIMER_NORESTART. I've found some sources online that state that the timer needs to be reset in the callback using the hrtimer_forward method. However, the sources I've seen are a little unclear on how adding the time works. Here's the code I have so far:
static struct hrtimer timer;
static enum hrtimer_restart timer_callback(struct hrtimer *timer)
{
printk(KERN_ERR "Callback\n");
//I know something needs to go here to reset the timer
return HRTIMER_RESTART;
}
static int init_timer(void)
{
ktime_t ktime;
unsigned long delay_in_ms = 500L;
printk(KERN_ERR "Timer being set up\n");
ktime = ktime_set(0,delay_in_ms*1E6L);
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
timer.function = &timer_callback;
printk(KERN_ERR "Timer starting to fire\n");
printk(KERN_ERR "in %ldms %ld\n", delay_in_ms, jiffies);
hrtimer_start(&timer, ktime, HRTIMER_MODE_REL);
return 0;
}
static void clean_load_balancing_timer(void)
{
int cancelled = hrtimer_cancel(&timer);
if (cancelled)
printk(KERN_ERR "Timer still running\n");
else
printk(KERN_ERR "Timer cancelled\n");
}
Can someone explain exactly how resetting the timer would work in the callback function? Thanks!
If you look in kernel/sched.c around line 170 in the function sched_rt_period_timer, you will see an example usage. The essential lines are
now = hrtimer_cb_get_time(timer);
overrun = hrtimer_forward(timer, now, rt_b->rt_period);
Now get's the timer's current time as a ktime_t and rt_b->rt_period is another ktime_t specifying the period at which to advance timer. The expiration time of the hrtimer will be continuously incremented by the period until it is greater than the current time. If it took more than one addition of the period to get the expiration time greater than the current time, the return value will greater than 1 (indicating more overrruns). It can be zero, if the timer expire didn't get advanced at all.
Reference: http://lwn.net/Articles/167897/
The API it uses is from a different version of the kernel so some of the arguments have changed. The basic idea is still the same.
Below is the simple solution,
#include <linux/slab.h>
#include <linux/time.h>
#include <asm/string.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#define NSEC_PER_MSEC 1000000L
static struct hrtimer hr_timer;
enum hrtimer_restart enHRTimer=HRTIMER_NORESTART;
s64 i64TimeInNsec = 500 * NSEC_PER_MSEC;
enum hrtimer_restart my_hrtimer_callback( struct hrtimer *timer )
{
hrtimer_forward(timer,hrtimer_cb_get_time(timer),ktime_set(0,i64TimeInNsec));
return enHRTimer;
}
void hrtimer_event_init_module(void)
{
ktime_t kt;
enHRTimer = HRTIMER_RESTART;
//HRT init
kt = ktime_set(0, i64TimeInNsec);
hrtimer_init( &hr_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
hrtimer_set_expires(&hr_timer, kt);
hr_timer.function = &my_hrtimer_callback;
hrtimer_start( &hr_timer, kt, HRTIMER_MODE_ABS);
}
void hrtimer_event_cleanup_module( void )
{
//Reset
hrtimer_cancel(&hr_timer);
enHRTimer = HRTIMER_NORESTART;
printk("HR-Timer module uninstalized\n");
}

Resources