gettimeofday() and ctx->cur_loop_time

The event manager keeps track of the current time in the cur_loop_time field of the Orchids context. When you want to reschedule an event to take place in, say, 5 seconds, it is tempting to write:

  heap_entry_t *he;

  /* ... */
  he->date = ctx->cur_loop_time + 5;
  register_rtaction(ctx, he);

This post explains why this is a bad idea, and how it should be done.

In brief, instead of using ctx->cur_loop_time, where ctx is your Orchids context, you should call gettimeofday(). This is not that slower. And this will solve an issue caused by your computer going to sleep (mostly laptops, but also virtualized sessions).

All right, so what is happening? The main Orchids loop is the function event_dispatcher_main_loop().  It first calls gettimeofday() to obtain the current time, and stores it into ctx->cur_loop_time. Then, it looks for rtcallbacks to handle before it calls select(). This rtcallback handling appears to be instantaneous: a small loop, calling functions that do not wait on any external event. So not much time will elapse and the current time of day will remain close to ctx->cur_loop_time;perhaps a few clock cycles, right?

In fact, no. If, in the middle of that, the computer goes to sleep mode, and is reawakened, say, one hour later, then ctx->cur_loop_time will be lagging by 3600 seconds behind the actual time.

As a consequence, imagine a task that is scheduled to take place every 5 seconds (this once happened with the save mechanism). When the computer is reawakened, it will then do that task 3600/5 = 720 times.  This will take 100% cpu time while it is catching up, causing some behavior that will look strange to the outside observer.

So, instead, call gettimeofday(). To illustrate this, look at the following rtcallback, using by mod_textfile to poll files every cfg->poll_period seconds:

static int rtaction_read_textfiles(orchids_t *ctx, heap_entry_t *he)
{
  mod_entry_t *mod;
  textfile_config_t *cfg;
  char	      eof;

  mod = (mod_entry_t *)he->data;
  cfg = (textfile_config_t *)mod->config;
  eof = textfile_callback(ctx, mod, NULL);
  gettimeofday(&he->date, NULL);
  /* It is a bad idea to 'optimize' the above by writing instead:
     he->date = ctx->cur_loop_time;
  */
  if (eof)
    he->date.tv_sec += cfg->poll_period;
  register_rtaction(ctx, he);
  return 0;
}

Calling gettimeofday() is actually fast, too. On modern architectures, this will not make any system call, most of the time.

I have seen a timing of 54 clock cycles reported here (read, 16 oct. 2015).

With the code that follows, on the Mac OS X 10.9.2 I am using while writing this, 100 million calls to gettimeofday() takes 5 seconds; in other words, one call takes about 50 ns. time(), by the way, is slower: 100 million calls takes 22 seconds, namely, one call to time() takes 220 ns.

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

void printTime(time_t now)
{
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);
    printf ("%s\n", buf);
}

int main(void)
{
   struct timeval tv;
   time_t tm;

   gettimeofday(&tv,NULL);
   printTime((time_t)tv.tv_sec);
   for(int i=0; i<100000000; i++)
        gettimeofday(&tv,NULL);
   gettimeofday(&tv,NULL);
   printTime((time_t)tv.tv_sec);

   printTime(time(NULL));
   for(int i=0; i<100000000; i++)
        tm=time(NULL);
   printTime(time(NULL));

   return 0;
}