Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 607 Vote(s) - 3.51 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to check if the system supports "Monotonic Clock"?

#1
I need to handle timeout scenarios in code and want to use `clock_gettime(CLOCK_MONOTONIC)` if the system supports Monotonic Clock.

#ifdef CLOCK_MONOTONIC
clock_gettime(CLOCK_MONOTONIC, & spec);
#else
clock_gettime(CLOCK_REALTIME, & spec);
#endif

I'm not sure if this is enough. That's to say, is it possible that the system defines `CLOCK_MONOTONIC` by it does not really support monotonic clock? Or what's the reliable way to check if monotonic clock is supported?
Reply

#2
Per the letter of POSIX, you may in fact need a runtime test even if the constant `CLOCK_MONOTONIC` is defined. The official way to handle this is with the `_POSIX_MONOTONIC_CLOCK` "feature-test macro", but those macros have really complicated semantics: quoting

[To see links please register here]

,

> If a symbolic constant is not defined or is defined with the value -1, the option is not supported for compilation. If it is defined with a value greater than zero, the option shall always be supported when the application is executed. If it is defined with the value zero, the option shall be supported for compilation and might or might not be supported at runtime.

Translating that three-way distinction into code would give you something like this:

#if !defined _POSIX_MONOTONIC_CLOCK || _POSIX_MONOTONIC_CLOCK < 0
clock_gettime(CLOCK_REALTIME, &spec);
#elif _POSIX_MONOTONIC_CLOCK > 0
clock_gettime(CLOCK_MONOTONIC, &spec);
#else
if (clock_gettime(CLOCK_MONOTONIC, &spec))
clock_gettime(CLOCK_REALTIME, &spec));
#endif

But it's simpler and more readable if you just always do the runtime test when CLOCK_MONOTONIC itself is defined:

#ifdef CLOCK_MONOTONIC
if (clock_gettime(CLOCK_MONOTONIC, &spec))
#endif
clock_gettime(CLOCK_REALTIME, &spec);

This increases the size of your code by some trivial amount on current-generation OSes that do support `CLOCK_MONOTONIC`, but the readability benefits are worth it in my opinion.

There is also a pretty strong argument for using `CLOCK_MONOTONIC` unconditionally; you're more likely to find an OS that doesn't support `clock_gettime` at all (e.g. MacOS X still doesn't have it as far as I know) than an OS that has `clock_gettime` but not `CLOCK_MONOTONIC`.
Reply

#3
POSIX only requires that `CLOCK_REALTIME` be present, other clocks are optional.

If the monotonic clock is available, the macro `_POSIX_MONOTONIC_CLOCK` will be defined in `unistd.h` (according to the **Availability** section of the [man page][1])

[1]:

[To see links please register here]

Reply

#4
As shown in @zwol's answer, things really get a bit complicated and interesing ——

See the following simple program (`foo.c`):

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

int
main()
{
struct timespec spec;

printf("_POSIX_MONOTONIC_CLOCK = %d\n",
(int)_POSIX_MONOTONIC_CLOCK);
printf("sysconf(_SC_MONOTONIC_CLOCK) = %ld\n",
sysconf(_SC_MONOTONIC_CLOCK) );
printf("clock_gettime(CLOCK_MONOTONIC) = %d\n",
clock_gettime(CLOCK_MONOTONIC, & spec) );

return 0;
}

On Linux (Debian 9, x86_64):

<!-- language: none -->

[STEP 101] # uname -a
Linux debian9 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1 (2018-04-29) x86_64 GNU/Linux
[STEP 102] # gcc foo.c && ./a.out
_POSIX_MONOTONIC_CLOCK = 0
sysconf(_SC_MONOTONIC_CLOCK) = 200809
clock_gettime(CLOCK_MONOTONIC) = 0
[STEP 103] #

On macOS (10.13, High Sierra):

<!-- language: none -->

[STEP 201] $ uname -a
Darwin macbook.home 17.5.0 Darwin Kernel Version 17.5.0: Fri Apr 13 19:32:32 PDT 2018; root:xnu-4570.51.2~1/RELEASE_X86_64 x86_64
[STEP 202] $ cc foo.c && ./a.out
_POSIX_MONOTONIC_CLOCK = -1
sysconf(_SC_MONOTONIC_CLOCK) = -1
clock_gettime(CLOCK_MONOTONIC) = 0
[STEP 203] $

On FreeBSD (11.1, x86_64):

<!-- language: none -->

[STEP 301] # uname -a
FreeBSD freebsd 11.1-RELEASE FreeBSD 11.1-RELEASE #0 r321309: Fri Jul 21 02:08:28 UTC 2017 [email protected]:/usr/obj/usr/src/sys/GENERIC amd64
[STEP 302] # cc foo.c && ./a.out
_POSIX_MONOTONIC_CLOCK = 200112
sysconf(_SC_MONOTONIC_CLOCK) = 200112
clock_gettime(CLOCK_MONOTONIC) = 0
[STEP 303] #

The result on macOS really surprised me. `sysconf()` returns `-1` but `clock_gettime(CLOCK_MONOTONIC)` succeeds! Not sure if this indicate macOS is not POSIX compliant. Anyway it proves **runtime checking with `sysconf()` is not reliable!**

Finally I'm going with this:

int
Clock_gettime(struct timespec * spec)
{
static bool firstime = true;
static clockid_t clock = CLOCK_REALTIME;

if (firstime) {
firstime = false;
#ifdef CLOCK_MONOTONIC
if (clock_gettime(CLOCK_MONOTONIC, spec) == 0) {
clock = CLOCK_MONOTONIC;
return 0;
}
#endif
}

return clock_gettime(clock, spec);
}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through