Checking the Time

I tend to keep the lessons on this blog specific to the standard C library, C99 release. Yet every so often a newer function draws my attention, which may not be standard but can still be useful. Case in point is the clock_gettime() function, which subscriber M.Stumpfl mentioned in a previous post.

The clock_gettime() function is part of a family of time.h functions, including clock_getres() and clock_settime(). As these are newer functions, they may require linking in the rt library for older C compilers.

Like the time() function, clock_gettime() returns the number of seconds in the Unix Epoch, the time elapsed since midnight January 1, 1970. It also includes the number of nanoseconds elapsed since the last second. This makes the function far more precise than time(), which tracks only seconds (a time_t value).

Here is the function’s man page format:

int clock_gettime(clockid_t clockid, struct timespec *tp);

The clockid value is a constant representing a clock to examine. The constant CLOCK_REALTIME serves as the system clock. In my earlier post, M.Stumpfl used the CLOCK_MONOTONIC constant, which isn’t affected by jumps that occur in the system clock. But CLOCK_MONOTONIC‘s values represent the number of seconds elapsed since the system was last booted, not the Epoch value.

The second argument is the address of a timespec structure. This structure has two members:

struct timespec {
    time_t   tv_sec;        /* seconds */
    long     tv_nsec;       /* nanoseconds */
};

Member tv_sec is the time_t value, the number of seconds elapsed since the Epoch. Member tv_nsec is the number of nanoseconds (billionths of a second) that have passed since the last clock tick. It’s this second value that adds such precision to the clock_gettime() function.

The following code shows the clock_gettime() function in action, outputting the current values retrieved from the system clock:

2023_05_06-Lesson-a.c

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

int main()
{
    struct timespec res;

    clock_gettime(CLOCK_REALTIME,&res);
    printf("Seconds: %lu\nNanoseconds: %lu\n",
            res.tv_sec,
            res.tv_nsec
          );

    return(0);
}

The function is called with the CLOCK_REALTIME argument, using the system clock. The timespec structure res holds the values returned, which are output in the printf() statement. The %lu (long unsigned) placeholder is used for both values. Here is the output:

Seconds: 1682175617
Nanoseconds: 242989728

The Seconds value is the Unix Epoch, the same value that would be returned from the time() function. The value I’m more interested in is Nanoseconds. Obviously, billionths of seconds are going to fly by more quickly than your reservation time at the Apple Store Genius Bar.

To monitor the nanosecond progress, I updated the code as shown below.

2023_05_06-Lesson-b.c

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

int main()
{
    struct timespec res;
    int count;

    /* loop to read nanosecond values */
    count = 20;
    while( count-- )
    {
        clock_gettime(CLOCK_REALTIME,&res);
        printf("%lu\n",res.tv_nsec);
    }

    return(0);
}

A while loop repeats 20 times, each iteration calling the clock_gettime() function and outputting only the nanosecond value. Here’s the output:

196619560
196697155
196699640
196700626
196701428
196702211
196702990
196703773
196704726
196705564
196706410
196707235
196708010
196708788
196709578
196710346
196711292
196712156
196713012
196713861

These values aren’t consecutive because it takes the computer longer than a nanosecond to output text to the terminal. But if you modify the code to output more values, you see the nanosecond numbers “flip over” with each passing second. Doing so generates a lot of output.

In next week’s Lesson, I continue my fascination with the clock_gettime() function and its nanosecond values.

2 thoughts on “Checking the Time

  1. I have to admit: seing oneʼs name mentioned online for the first time does feel special – thank you for mentioning my small contribution on this blog site!

    Anyway, I agree that the clock_gettime() functions are useful enough to warrant the (small) additional complexity they might add to oneʼs build setup.

    While you mention “rt.so” just one small addition, if I may: as the man pages note, it may also be necessary to define _POSIX_C_SOURCE to a value of 199309L (or higher) — either by #defineʼing this preprocessor macro before any header files are included, or alternatively by passing it to (g)cc via itʼs -D argument.

  2. Good point, sorry that I omitted that info. And thanks for contributing! I put my email address in my books to get such feedback, which helps me guide the blog.

Leave a Reply