0

I am wondering if there is a way to get every integer second in a c program. I tried to use 'gettimeofday' function to get the current time and then if the current fractional part of second falls into a region (say larger than 0.9 and smaller than 0.1), I rounded the current time into an integer. However, when I run the program, occasionally, there were a few seconds missed. Does anyone have a better solution?

Thanks

Toga
  • 19
  • 2

1 Answers1

0

I would suggest to use the alarm signal:

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

void timer_handler (int signum)
{
  struct timeval tval;
  gettimeofday(&tval, NULL);
  printf("Seconds: %ld\n",tval.tv_sec);
}

int main ()
{
  struct sigaction sa;
  struct itimerval timer;

  memset (&sa, 0, sizeof (sa));
  sa.sa_handler = &timer_handler;
  sigaction (SIGVTALRM, &sa, NULL);

  timer.it_value.tv_sec = 1;
  timer.it_value.tv_usec = 0;
  timer.it_interval.tv_sec = 1;
  timer.it_interval.tv_usec = 0;
  setitimer (ITIMER_VIRTUAL, &timer, NULL);

  while (1);
}

At my Mac (OS X 10.11.5) I get:

./alarm
Seconds: 1468937712
Seconds: 1468937713
Seconds: 1468937714
Seconds: 1468937715
Seconds: 1468937716
Seconds: 1468937717
Seconds: 1468937718
Seconds: 1468937719
Seconds: 1468937720

EDIT

The code above uses the virtual timer, that only ticks als long the thread is running (and thus relies on the busy loop the introduce the high load). Using the real timer allows for reduction of the load:

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

void timer_handler (int signum)
{
  struct timeval tval;
  printf("Foo");
  gettimeofday(&tval, NULL);
  printf("Seconds: %ld\n",tval.tv_sec);
}

int main ()
{
  struct sigaction sa;
  struct itimerval timer;
  sa.sa_mask=0;
  sa.sa_flags=0;


  memset (&sa, 0, sizeof (sa));
  sa.sa_handler = &timer_handler;
  sigaction (SIGALRM, &sa, NULL);

  timer.it_value.tv_sec = 1;
  timer.it_value.tv_usec = 0;
  timer.it_interval.tv_sec = 1;
  timer.it_interval.tv_usec = 0;
  setitimer (ITIMER_REAL, &timer, NULL);

  while (1){
    pthread_yield_np();
  }
}

This approach runs basically the timer handler only. Thus the OS shouldn't care to much about load. However, be aware that hard real-time guarantees one get by OS's real-time features only (if there are any).

Matthias
  • 8,018
  • 2
  • 27
  • 53
  • Great thanks for the code. I run the code for a short period of time and it works fine. I need to test a longer time span just in case there is no missing second. One problem is that this code takes too much CPU usage. I need to see if i can make it more efficient. – Toga Jul 21 '16 at 05:59
  • I run the code this time for a longer time. It turns out there are actually several missing second. Do you have any idea to enhance the code to output every second? – Toga Jul 21 '16 at 23:59
  • The time consuming part is the idle loop. I could imagine that the misses are due to a fairness decision of the OS. I'll edit my answer to reduce the load. – Matthias Jul 22 '16 at 15:37