1

I'm having troubles understanding the timer values filled by setitimer. I have the following code

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

struct itimerval defaultTimer = {{0, 2}, {0, 2}};
struct itimerval disabledTimer = {{0, 0}, {0, 0}};


void busy_wait(int iterations)
{
    int count = 0;
    for (int i = 0; i < iterations; i++)
    {
        count++;
    }
}


int main()
{
    // ignore SIGVTALRM
    struct sigaction sa = { .sa_handler = SIG_IGN };
    sigaction(SIGVTALRM, &sa, NULL);

    if (setitimer(ITIMER_VIRTUAL, &defaultTimer, NULL) != 0)
    {
        return -1;
    }

    struct itimerval timer;

    while (true)
    {
        setitimer(ITIMER_VIRTUAL, &disabledTimer, &timer);
        setitimer(ITIMER_VIRTUAL, &timer, NULL);
        busy_wait(10000000);
        printf("timer.it_value: %lu.%lu\n", timer.it_value.tv_sec, timer.it_value.tv_usec);
        printf("timer.it_interval: %lu.%lu\n", timer.it_interval.tv_sec, timer.it_interval.tv_usec);
    }
}

As you see, I'm trying to "pause" the timer and immediately resume it. Running the code as it is generates output lines like these

timer.it_value: 0.4000
timer.it_interval: 0.4000

and nothing else. After the second call to setitimer inside the loop, shouldn't the timer struct hold the values of the current timer? If so, how come I can't see the values of timer.it_value decreasing?

Another weird thing, when removing the line busy_wait(10000000); in the loop, I see different increasing values for timer.it_value, for example

timer.it_value: 60.404000
timer.it_interval: 0.4000
...
timer.it_value: 489.256000
timer.it_interval: 0.4000
...
timer.it_value: 2391.108000
timer.it_interval: 0.4000

What do these numbers mean? according to the setitimer manual

Timers decrement from it_value to zero, generate a signal, and reset to it_interval.

but that is in contrast with the results I see here.
Besides, why is timer.it_interval.tv_usec has value 4000? shouldn't it be 2 just as I set it?

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
Jona
  • 669
  • 10
  • 18
  • Any particular reason you compile your code with a C++ compiler instead of a C one? – StoryTeller - Unslander Monica Apr 01 '17 at 11:28
  • I need to use setitimer in a project written in c++. Does it matter? And how could you tell the way I'm compiling? – Jona Apr 01 '17 at 11:31
  • 2
    It probably doesn't matter for the issue at hand, the behavior of the C API shouldn't change. But if one does such things unknowingly they may notice "oddities", since C and C++ are different languages, despite being easy to "glue" together at times. And I knew by the C++ specific inclusion of `cstdio`. Your code can only be compiled by a C++ compiler if that is included. – StoryTeller - Unslander Monica Apr 01 '17 at 11:35
  • 2
    BTW, the code misses to *completely* initialise `sa`. Change `struct sigaction sa;` to be `struct sigaction sa = {0}`; – alk Apr 01 '17 at 11:39
  • You also want to rename `wait()` to something like `my_wait()` as there is a C/POSIX function called `wait()` already. – alk Apr 01 '17 at 11:41
  • 1
    It appears to round up the values to multiples of 4000µs (linux). According to the manpage, delayed expiration is possible. I have no explanation for the increases in `.it_value`. – Petr Skocik Apr 01 '17 at 11:55
  • It appears the phenomenon only takes place with sufficient optimization on. The optimization optimizes out the busy-wait loop (same result if you comment it one) and then the successive setitimer calls increase the it_value by 4000, which appears to be the granularity of the timer (it_interval 1 rounds up to 4000, 4001 to 8000, 8001 to 12000, etc.). If the loop isn't optimized out (=>the timer gets a chance to run), the it_value values seem to increase by 4000 and wrapparound the rounded-up initially set value. – Petr Skocik Apr 01 '17 at 12:19
  • @PSkocik but why would setitimer increase it_value? according to the documentation it should **set** the timer to the one given as second argument (and not increment/add) – Jona Apr 01 '17 at 12:45

0 Answers0