As developers, having an accurate sense of time is critical for building responsive and reliable applications. The gettimeofday() and settimeofday() functions in C provide interfaces to get and set the system time with high precision. In this comprehensive guide, we will explore how to use these functions effectively.

Overview of gettimeofday()

The gettimeofday() function is declared in sys/time.h header and used to retrieve the current system time with microsecond precision.

Here is its function prototype:

int gettimeofday(struct timeval *tv, struct timezone *tz);

It accepts two arguments:

  • struct timeval* tv: This is where the current time is returned. It contains two fields:
    • tv_sec: Seconds since UNIX epoch (Jan 1, 1970 00:00:00 UTC).
    • tv_usec: Microseconds from tv_sec.
  • struct timezone *tz: Timezone information. This is obsolete and should be set to NULL.

On success, gettimeofday() returns 0. On failure, it returns -1 and sets errno.

Here is an example usage:

#include <sys/time.h>

struct timeval tv;
gettimeofday(&tv, NULL);

time_t seconds = tv.tv_sec; 
suseconds_t microseconds = tv.tv_usec;

This retrieves the current time since UNIX epoch in seconds and microseconds.

Microsecond resolution

The key value of gettimeofday() is it provides microsecond resolution for the current time. This allows measuring precise elapsed times for code execution in applications like:

  • Benchmarking
  • Application profiling
  • Tracking response times
  • Financial trading systems

For example, we can benchmark a function like this:

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

// Returns elapsed time in microseconds 
long timer(struct timeval *start, struct timeval *end) {
  return (end->tv_sec - start->tv_sec) * 1000000L 
         + (end->tv_usec - start->tv_usec);
}

// Function to benchmark
void func() {
  int i;
  for (i = 0; i < 10000; i++) {
    // do some work
  }  
}

int main() {

  struct timeval start, end;

  gettimeofday(&start, NULL);

  func();

  gettimeofday(&end, NULL);

  long elapsed = timer(&start, &end);

  printf("Function took %ld microseconds", elapsed);

  return 0;
}

This kind of precision timing allows accurately measuring performance of code snippets and optimizing as needed.

POSIX standard

The gettimeofday() function is defined by POSIX, the Portable Operating System Interface. This means code using it can be easily ported across many platforms like Linux, macOS, BSD etc.

Conformant implementations in the POSIX standard must provide microsecond resolution and wide range to represent times for at least the next 250 years from the POSIX epoch (Jan 1, 1970 00:00:00 UTC).

Time sync and clock sources

To provide accurate current time, operating systems sync time from external reference clock sources like NTP pools. The system clock is then derived from the externally synced time.

On Linux, the default system clock CLOCK_REALTIME is synchronized from external reference and represents the wall clock time. gettimeofday() is based on this system clock.

Another available source is the monotonic clock (CLOCK_MONOTONIC) which always increases at a constant rate and is not adjusted or sync‘ed to external time source. This is useful to measure elapsed times without worrying about clock adjustments introducing inaccuracies.

Date conversions

While gettimeofday() provides UNIX timestamp in seconds, sometimes it needs to be converted human readable date formats.

Here is an example function using standard C date/time functions:

#include <time.h>

void display_date(struct timeval *tv) {

  time_t seconds = tv->tv_sec;

  struct tm *tm = localtime(&seconds);  

  printf("Current date/time: %d-%d-%d %d:%d:%d\n", 
     tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
     tm->tm_hour, tm->tm_min, tm->tm_sec); 

}

Some key date/time functions useful with gettimeofday() are:

  • localtime() – Converts timestamp to broken-down struct tm
  • gmtime() – Same as above but in UTC
  • strftime() – Formats date/time strings
  • mktime() – Converts broken-down struct tm back to timestamp

Implementations

There are a few variations in implementation of gettimeofday() to be aware of:

Linux

The Linux implementation uses vDSO (virtual dynamic shared object) to provide very fast and low overhead call to gettimeofday() for user space programs. It avoids the cost of syscall. It may not be supported in statically linked programs however.

macOS

Mac OS X 10.12+ has both a gettimeofday() and posix_gettimeofday(). The former provides basic second resolution, while the latter gives full microsecond precision.

Windows

Windows historically did not provide gettimeofday() but it is available as of Windows 8 and in the winsock2.h header. MinGW and Cygwin environments also provide their implementation.

So in summary, with some platform differences, gettimeofday() is widely available.

Common issues

Some common issues that arise when using gettimeofday():

  • Forgetting to pass address of struct timeval causing a segmentation fault.
  • No error checking leading to null times if system call fails.
  • Assuming it provides millisecond rather than microsecond resolution.
  • Not accounting for potential clock drift over longer time periods.

settimeofday()

Complementary to gettimeofday() is settimeofday(), which sets the system time and date.

It can be useful for:

  • Setting system clock to standard time servers
  • Reset system time manually
  • Testing time dependent application behaviour by manipulating clock

Here is the function prototype:

int settimeofday(const struct timeval *tv, const struct timezone *tz); 

It accepts two arguments:

  • struct timeval* tv – The time to set it to with seconds and microseconds
  • struct timezone* tz – Timezone (unused, set to NULL)

Here is an example:

struct timeval new_time;

new_time.tv_sec = 1674320142;  
new_time.tv_usec = 0;

settimeofday(&new_time, NULL);

This sets the system time to Jan 23, 2023 11:15:42AM UTC.

Do note only root/superuser can set time for most systems. So practical usage would need sudo privileges.

Additionally there may be limits to how drastically you can change the clock with a single call, to prevent large clock skews.

Conclusion

To summarize, gettimeofday() and settimeofday() give you portable and precise interfaces to get and manipulate system time in your C programs:

  • gettimeofday() retrieves current UNIX timestamp with microsecond resolution
  • settimeofday() sets system clock time, needing root privileges
  • Great for benchmarking, measuring performance, and testing
  • Handle platform specific implementation quirks
  • Pair with date/time functions for human readable strings

Accurate and robust sense timing is a critical need for many applications. Hopefully this guide provides a good overview and foundation for applying these functions effectively in your work.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *