Starting Point for Clock_Monotonic

Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?

CLOCK_REALTIME represents the machine's best-guess as to the current wall-clock, time-of-day time. As Ignacio and MarkR say, this means that CLOCK_REALTIME can jump forwards and backwards as the system time-of-day clock is changed, including by NTP.

CLOCK_MONOTONIC represents the absolute elapsed wall-clock time since some arbitrary, fixed point in the past. It isn't affected by changes in the system time-of-day clock.

If you want to compute the elapsed time between two events observed on the one machine without an intervening reboot, CLOCK_MONOTONIC is the best option.

Note that on Linux, CLOCK_MONOTONIC does not measure time spent in suspend, although by the POSIX definition it should. You can use the Linux-specific CLOCK_BOOTTIME for a monotonic clock that keeps running during suspend.

Absolute time using monotonic clock

As @IwillnotexistIdonotexist implied, CLOCK_MONOTONIC has no specified starting point and you cannot reliably convert monotonic time to real time.

To quote the clock_gettime manpage, for CLOCK_MONOTONIC:

Clock that cannot be set and represents monotonic time since some
unspecified starting point

The only restriction is that the MONOTONIC time must be greater than the system's uptime (required in order to be monotonically increasing).

I expect that most implementations are indeed just clock-ticks since boot but nothing guarantees this.

Is CLOCK_MONOTONIC process (or thread) specific?

The answer Maxim and comments to that answered the second part of your question, I believe. To expand on the answer for the first part, POSIX 2008 states


If the Monotonic Clock option is supported, all implementations shall support a clock_id of CLOCK_MONOTONIC defined in <time.h>. This clock represents the monotonic clock for the system. For this clock, the value returned by clock_gettime() represents the amount of time (in seconds and nanoseconds) since an unspecified point in the past (for example, system start-up time, or the Epoch). This point does not change after system start-up time.

In particular, note "the monotonic clock for the system". That is, per-system and not per-process, it keeps ticking even though your process is not running. Also, "This point does not change after system start-up time.", which again implies that it keeps ticking regardless of whether a particular process is running or sleeping.

So, either you have found a bug in the Linux implementation, or more likely, in your test program.

What is the difference between CLOCK_MONOTONIC & CLOCK_MONOTONIC_RAW?

CLOCK_MONOTONIC never experiences discontinuities due to NTP time adjustments, but it does change in frequency as NTP learns what error exists between the local oscillator and the upstream servers.

CLOCK_MONOTONIC_RAW is simply the local oscillator, not disciplined by NTP. This could be very useful if you want to implement some other time synchronization algorithm against a clock which is not fighting you due to NTP. While ntpd (the reference implementation of NTP protocol and the most widespread NTP daemon) is reputed to be "gentle" with time adjustments, it's more accurate to say it's gentle with the absolute time. It's willing to slew the clock by 500ppm which is pretty dramatic if you're in a position to measure your clock frequency against some other standard.

The utility of CLOCK_MONOTONIC_RAW is going to be limited until facilities like pthread_timedwait_monotonic offer an option to use that timebase.

Monotonic Clock in C

Look at man timespec

There is written:

struct timespec {
time_t tv_sec;
long tv_nsec;
};

The tv_sec member is again the elapsed time in whole seconds.
The tv_nsec member represents the rest of the elapsed time in nanoseconds.

So tv_nsec is just the rest of the time not representable in whole seconds, so you need to subtract seconds and nanoseconds.

Subtracting timespecs

Also here https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.5/html_node/Elapsed-Time.html is presented "the best way" to subtract two values of type struct timeval, as follows:

(For struct timespec just substitute timespec for timeval, tv_nsec for tv_usec and 1000000000 for 1000000.)

It is often necessary to subtract two values of type struct timeval or struct timespec. Here is the best way to do this. It works even on some peculiar operating systems where the tv_sec member has an unsigned type.

/* Subtract the `struct timeval' values X and Y,
storing the result in RESULT.
Return 1 if the difference is negative, otherwise 0. */

int
timeval_subtract (result, x, y)
struct timeval *result, *x, *y;
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}

/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;

/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}


Related Topics



Leave a reply



Submit