tags:

views:

121

answers:

6

I have a particular function (well, set of functions) that I want to start every 400ms. I'm not much of a C programmer, and so anything outside of the standard libraries is a mystery to me, as well as quite a bit within them.

My first thought is to use nanosleep to pause execution for 400ms in some sort of loop, but this of course doesn't take into account the execution time of the code I will be running. If I could measure it, and if it seemed fairly certain that it ran for the same approximate duration after 10 or 20 tests, I could then nanosleep() for the difference. This wouldn't be perfect, of course... but it might be close enough for a first try.

How do I measure the execution time of a C function? Or is there a better way to do this altogether, and what keywords do I need to be googling for?

+3  A: 

You should be able to use settimer

int setitimer(int which, const struct itimerval *value,
              struct itimerval *ovalue);

Just put the code that you want to execute every 400ms inside the SIGALRM handler. This way you don't need to account for the time that your code takes to run, which could potentially vary. I'm not sure what happens if the signal handler doesn't return before the next signal is generated.

An outline of what some of the code might look like is shown below.

void periodic_fuc(int signal_num)
{
  ...
  signam(SIGALRM, periodic_func);
}

int main(...)
{
  struct itimerval timerval = {0};

  signal(SIGALRM, periodic_func);      
  ...
  timerval.it_interval.tv_usec = 400000;
  timerval.it_value.tv_usec = 400000; // Wait 400ms for first trigger
  settimer(ITIMER_REAL, &timerval, NULL);

  while (!exit)
    sleep(1);
  return 0;
}
torak
`pause()` is better than `sleep(1)` there.
caf
+1  A: 

Take a look at gprof. It allows you to quickly recompile your code and generate information on which functions are being called and what is taking up the most time in your program.

Michael Mior
This is probably a much better alternative than to spray around a lot of timer calls inside the code. People should get themselves used to run debuggers and profilers rather than jotting lots of debug strings in their code.
Alek
A: 

You could use gettimeofday() or clock_gettime() before and after the functions to time, and then calculate the delta between the two times.

Jonathan Leffler
A: 

For Linux, you can use gettimeofday. Call gettimeofday at the start of the function. Run whatever you have to run. Then get the end time and figure out how much longer you have to sleep. Then call usleep for the appropriate number of microseconds.

Jonathan Sternberg
A: 

Look at POSIX timers. Here is some documentation at HP.

You can do the same functions as with setitimer, but you also have timer_getoverrun() to let you know if you missed any timer events during your function.

Zan Lynx
+1  A: 

I concur with torak about using setitimer(). However, since it's not clear if the interval is restarted when the SIGALRM handler exits, and you're really not supposed to do much work in a signal handler anyway, it's better to just have it set a flag, and do the work in the main routine:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>

volatile sig_atomic_t wakeup = 0;

void alarm_handler(int signal_num)
{
    wakeup = 1;
}

int main()
{
    struct itimerval timerval = { 0 };
    struct sigaction sigact = { 0 };
    int finished = 0;

    timerval.it_interval.tv_usec = 400000;
    timerval.it_value.tv_usec = 400000;

    sigact.sa_handler = alarm_handler;

    sigaction(SIGALRM, &sigact, NULL);
    setitimer(ITIMER_REAL, &timerval, NULL);

    while (!finished)
    {
        /* Wait for alarm wakeup */
        while (!wakeup)
            pause();
        wakeup = 0;

        /* Code here... */
        printf("(Wakeup)\n");
    }

    return 0;
}
caf