Concord - C Discord API library
A Discord API wrapper library written in C
clock.h
Go to the documentation of this file.
1/* Clocks (v1)
2 * Portable Snippets - https://github.com/nemequ/portable-snippets
3 * Created by Evan Nemerson <evan@nemerson.com>
4 *
5 * To the extent possible under law, the authors have waived all
6 * copyright and related or neighboring rights to this code. For
7 * details, see the Creative Commons Zero 1.0 Universal license at
8 * https://creativecommons.org/publicdomain/zero/1.0/
9 */
10
11#if !defined(PSNIP_CLOCK_H)
12#define PSNIP_CLOCK_H
13
14/* For maximum portability include the exact-int module from
15 portable snippets. */
16#if !defined(psnip_uint64_t) || !defined(psnip_int32_t) || \
17 !defined(psnip_uint32_t) || !defined(psnip_int32_t)
18# include <stdint.h>
19# if !defined(psnip_int64_t)
20# define psnip_int64_t int64_t
21# endif
22# if !defined(psnip_uint64_t)
23# define psnip_uint64_t uint64_t
24# endif
25# if !defined(psnip_int32_t)
26# define psnip_int32_t int32_t
27# endif
28# if !defined(psnip_uint32_t)
29# define psnip_uint32_t uint32_t
30# endif
31#endif
32
33#if !defined(PSNIP_CLOCK_STATIC_INLINE)
34# if defined(__GNUC__)
35# define PSNIP_CLOCK__COMPILER_ATTRIBUTES __attribute__((__unused__))
36# else
37# define PSNIP_CLOCK__COMPILER_ATTRIBUTES
38# endif
39
40# define PSNIP_CLOCK__FUNCTION PSNIP_CLOCK__COMPILER_ATTRIBUTES static
41#endif
42
44 /* This clock provides the current time, in units since 1970-01-01
45 * 00:00:00 UTC not including leap seconds. In other words, UNIX
46 * time. Keep in mind that this clock doesn't account for leap
47 * seconds, and can go backwards (think NTP adjustments). */
49 /* The CPU time is a clock which increases only when the current
50 * process is active (i.e., it doesn't increment while blocking on
51 * I/O). */
53 /* Monotonic time is always running (unlike CPU time), but it only
54 ever moves forward unless you reboot the system. Things like NTP
55 adjustments have no effect on this clock. */
57};
58
62};
63
64/* Methods we support: */
65
66#define PSNIP_CLOCK_METHOD_CLOCK_GETTIME 1
67#define PSNIP_CLOCK_METHOD_TIME 2
68#define PSNIP_CLOCK_METHOD_GETTIMEOFDAY 3
69#define PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER 4
70#define PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME 5
71#define PSNIP_CLOCK_METHOD_CLOCK 6
72#define PSNIP_CLOCK_METHOD_GETPROCESSTIMES 7
73#define PSNIP_CLOCK_METHOD_GETRUSAGE 8
74#define PSNIP_CLOCK_METHOD_GETSYSTEMTIMEPRECISEASFILETIME 9
75#define PSNIP_CLOCK_METHOD_GETTICKCOUNT64 10
76
77#include <assert.h>
78
79#if defined(HEDLEY_UNREACHABLE)
80# define PSNIP_CLOCK_UNREACHABLE() HEDLEY_UNREACHABLE()
81#else
82# define PSNIP_CLOCK_UNREACHABLE() assert(0)
83#endif
84
85/* Choose an implementation */
86
87/* #undef PSNIP_CLOCK_WALL_METHOD */
88/* #undef PSNIP_CLOCK_CPU_METHOD */
89/* #undef PSNIP_CLOCK_MONOTONIC_METHOD */
90
91/* We want to be able to detect the libc implementation, so we include
92 <limits.h> (<features.h> isn't available everywhere). */
93#if defined(__unix__) || defined(__unix) || defined(__linux__)
94# include <limits.h>
95# include <unistd.h>
96#endif
97
98#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
99/* glibc 2.17+ and FreeBSD are known to work without librt. If you
100 * know of others please let us know so we can add them. */
101# if \
102 (defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17))) || \
103 (defined(__FreeBSD__)) || \
104 !defined(PSNIP_CLOCK_NO_LIBRT)
105/* Even though glibc unconditionally sets _POSIX_TIMERS, it doesn't
106 actually declare the relevant APIs unless _POSIX_C_SOURCE >=
107 199309L, and if you compile in standard C mode (e.g., c11 instead
108 of gnu11) _POSIX_C_SOURCE will be unset by default. */
109# if _POSIX_C_SOURCE >= 199309L
110# define PSNIP_CLOCK_HAVE_CLOCK_GETTIME
111# endif
112# endif
113#endif
114
115#if defined(_WIN32)
116# if !defined(PSNIP_CLOCK_CPU_METHOD)
117# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_GETPROCESSTIMES
118# endif
119# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
120# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
121# endif
122#endif
123
124#if defined(__MACH__) && !defined(__gnu_hurd__)
125# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
126# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
127# endif
128#endif
129
130#if defined(PSNIP_CLOCK_HAVE_CLOCK_GETTIME)
131# include <time.h>
132# if !defined(PSNIP_CLOCK_WALL_METHOD)
133# if defined(CLOCK_REALTIME_PRECISE)
134# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
135# define PSNIP_CLOCK_CLOCK_GETTIME_WALL CLOCK_REALTIME_PRECISE
136# elif !defined(__sun)
137# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
138# define PSNIP_CLOCK_CLOCK_GETTIME_WALL CLOCK_REALTIME
139# endif
140# endif
141# if !defined(PSNIP_CLOCK_CPU_METHOD)
142# if defined(_POSIX_CPUTIME) || defined(CLOCK_PROCESS_CPUTIME_ID)
143# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
144# define PSNIP_CLOCK_CLOCK_GETTIME_CPU CLOCK_PROCESS_CPUTIME_ID
145# elif defined(CLOCK_VIRTUAL)
146# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
147# define PSNIP_CLOCK_CLOCK_GETTIME_CPU CLOCK_VIRTUAL
148# endif
149# endif
150# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
151# if defined(_POSIX_MONOTONIC_CLOCK) || defined(CLOCK_MONOTONIC)
152# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
153# define PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC CLOCK_MONOTONIC
154# endif
155# endif
156#endif
157
158#if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L)
159# if !defined(PSNIP_CLOCK_WALL_METHOD)
160# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_GETTIMEOFDAY
161# endif
162#endif
163
164#if !defined(PSNIP_CLOCK_WALL_METHOD)
165# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_TIME
166#endif
167
168#if !defined(PSNIP_CLOCK_CPU_METHOD)
169# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK
170#endif
171
172/* Primarily here for testing. */
173#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) && defined(PSNIP_CLOCK_REQUIRE_MONOTONIC)
174# error No monotonic clock found.
175#endif
176
177/* Implementations */
178
179#if \
180 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
181 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
182 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
183 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \
184 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \
185 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \
186 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_TIME)) || \
187 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME)) || \
188 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_TIME))
189# include <time.h>
190#endif
191
192#if \
193 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) || \
194 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) || \
195 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY))
196# include <sys/time.h>
197#endif
198
199#if \
200 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
201 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
202 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
203 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \
204 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \
205 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64))
206# include <windows.h>
207#endif
208
209#if \
210 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE)) || \
211 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE)) || \
212 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE))
213# include <sys/time.h>
214# include <sys/resource.h>
215#endif
216
217#if \
218 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) || \
219 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) || \
220 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME))
221# include <CoreServices/CoreServices.h>
222# include <mach/mach.h>
223# include <mach/mach_time.h>
224#endif
225
226/*** Implementations ***/
227
228#define PSNIP_CLOCK_NSEC_PER_SEC ((psnip_uint32_t) (1000000000ULL))
229
230#if \
231 (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
232 (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
233 (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME))
235psnip_clock__clock_getres (clockid_t clk_id) {
236 struct timespec res;
237 int r;
238
239 r = clock_getres(clk_id, &res);
240 if (r != 0)
241 return 0;
242
243 return (psnip_uint32_t) (PSNIP_CLOCK_NSEC_PER_SEC / res.tv_nsec);
244}
245
247psnip_clock__clock_gettime (clockid_t clk_id, struct PsnipClockTimespec* res) {
248 struct timespec ts;
249
250 if (clock_gettime(clk_id, &ts) != 0)
251 return -10;
252
253 res->seconds = (psnip_uint64_t) (ts.tv_sec);
254 res->nanoseconds = (psnip_uint64_t) (ts.tv_nsec);
255
256 return 0;
257}
258#endif
259
261psnip_clock_wall_get_precision (void) {
262#if !defined(PSNIP_CLOCK_WALL_METHOD)
263 return 0;
264#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
265 return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_WALL);
266#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY
267 return 1000000;
268#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME
269 return 1;
270#else
271 return 0;
272#endif
273}
274
276psnip_clock_wall_get_time (struct PsnipClockTimespec* res) {
277 (void) res;
278
279#if !defined(PSNIP_CLOCK_WALL_METHOD)
280 return -2;
281#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
282 return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_WALL, res);
283#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME
284 res->seconds = (uint64_t) time(NULL);
285 res->nanoseconds = 0;
286#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY
287 struct timeval tv;
288
289 if (gettimeofday(&tv, NULL) != 0)
290 return -6;
291
292 res->seconds = tv.tv_sec;
293 res->nanoseconds = tv.tv_usec * 1000;
294#else
295 return -2;
296#endif
297
298 return 0;
299}
300
302psnip_clock_cpu_get_precision (void) {
303#if !defined(PSNIP_CLOCK_CPU_METHOD)
304 return 0;
305#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
306 return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_CPU);
307#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK
308 return CLOCKS_PER_SEC;
309#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES
310 return PSNIP_CLOCK_NSEC_PER_SEC / 100;
311#else
312 return 0;
313#endif
314}
315
317psnip_clock_cpu_get_time (struct PsnipClockTimespec* res) {
318#if !defined(PSNIP_CLOCK_CPU_METHOD)
319 (void) res;
320 return -2;
321#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
322 return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_CPU, res);
323#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK
324 clock_t t = clock();
325 if (t == ((clock_t) -1))
326 return -5;
327 res->seconds = t / CLOCKS_PER_SEC;
328 res->nanoseconds = (t % CLOCKS_PER_SEC) * (PSNIP_CLOCK_NSEC_PER_SEC / CLOCKS_PER_SEC);
329#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES
330 FILETIME CreationTime, ExitTime, KernelTime, UserTime;
331 LARGE_INTEGER date, adjust;
332
333 if (!GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime))
334 return -7;
335
336 /* http://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ */
337 date.HighPart = UserTime.dwHighDateTime;
338 date.LowPart = UserTime.dwLowDateTime;
339 adjust.QuadPart = 11644473600000 * 10000;
340 date.QuadPart -= adjust.QuadPart;
341
342 res->seconds = date.QuadPart / 10000000;
343 res->nanoseconds = (date.QuadPart % 10000000) * (PSNIP_CLOCK_NSEC_PER_SEC / 100);
344#elif PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE
345 struct rusage usage;
346 if (getrusage(RUSAGE_SELF, &usage) != 0)
347 return -8;
348
349 res->seconds = usage.ru_utime.tv_sec;
350 res->nanoseconds = tv.tv_usec * 1000;
351#else
352 (void) res;
353 return -2;
354#endif
355
356 return 0;
357}
358
360psnip_clock_monotonic_get_precision (void) {
361#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
362 return 0;
363#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
364 return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC);
365#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
366 static mach_timebase_info_data_t tbi = { 0, };
367 if (tbi.denom == 0)
368 mach_timebase_info(&tbi);
369 return (psnip_uint32_t) (tbi.numer / tbi.denom);
370#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64
371 return 1000;
372#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
373 LARGE_INTEGER Frequency;
374 QueryPerformanceFrequency(&Frequency);
375 return (psnip_uint32_t) ((Frequency.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC) ? PSNIP_CLOCK_NSEC_PER_SEC : Frequency.QuadPart);
376#else
377 return 0;
378#endif
379}
380
382psnip_clock_monotonic_get_time (struct PsnipClockTimespec* res) {
383#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
384 (void) res;
385 return -2;
386#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
387 return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC, res);
388#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
389 psnip_uint64_t nsec = mach_absolute_time();
390 static mach_timebase_info_data_t tbi = { 0, };
391 if (tbi.denom == 0)
392 mach_timebase_info(&tbi);
393 nsec *= ((psnip_uint64_t) tbi.numer) / ((psnip_uint64_t) tbi.denom);
394 res->seconds = nsec / PSNIP_CLOCK_NSEC_PER_SEC;
396#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
397 LARGE_INTEGER t, f;
398 if (QueryPerformanceCounter(&t) == 0)
399 return -12;
400
401 QueryPerformanceFrequency(&f);
402 res->seconds = t.QuadPart / f.QuadPart;
403 res->nanoseconds = t.QuadPart % f.QuadPart;
404 if (f.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC)
405 res->nanoseconds /= f.QuadPart / PSNIP_CLOCK_NSEC_PER_SEC;
406 else
407 res->nanoseconds *= PSNIP_CLOCK_NSEC_PER_SEC / f.QuadPart;
408#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64
409 const ULONGLONG msec = GetTickCount64();
410 res->seconds = msec / 1000;
411 res->nanoseconds = sec % 1000;
412#else
413 return -2;
414#endif
415
416 return 0;
417}
418
419/* Returns the number of ticks per second for the specified clock.
420 * For example, a clock with millisecond precision would return 1000,
421 * and a clock with 1 second (such as the time() function) would
422 * return 1.
423 *
424 * If the requested clock isn't available, it will return 0.
425 * Hopefully this will be rare, but if it happens to you please let us
426 * know so we can work on finding a way to support your system.
427 *
428 * Note that different clocks on the same system often have a
429 * different precisions.
430 */
432psnip_clock_get_precision (enum PsnipClockType clock_type) {
433 switch (clock_type) {
435 return psnip_clock_monotonic_get_precision ();
437 return psnip_clock_cpu_get_precision ();
439 return psnip_clock_wall_get_precision ();
440 }
441
443 return 0;
444}
445
446/* Set the provided timespec to the requested time. Returns 0 on
447 * success, or a negative value on failure. */
449psnip_clock_get_time (enum PsnipClockType clock_type, struct PsnipClockTimespec* res) {
450 assert(res != NULL);
451
452 switch (clock_type) {
454 return psnip_clock_monotonic_get_time (res);
456 return psnip_clock_cpu_get_time (res);
458 return psnip_clock_wall_get_time (res);
459 }
460
461 return -1;
462}
463
464#endif /* !defined(PSNIP_CLOCK_H) */
#define psnip_uint64_t
Definition: clock.h:23
#define PSNIP_CLOCK__FUNCTION
Definition: clock.h:40
#define psnip_uint32_t
Definition: clock.h:29
#define PSNIP_CLOCK_NSEC_PER_SEC
Definition: clock.h:228
#define PSNIP_CLOCK_UNREACHABLE()
Definition: clock.h:82
PsnipClockType
Definition: clock.h:43
@ PSNIP_CLOCK_TYPE_WALL
Definition: clock.h:48
@ PSNIP_CLOCK_TYPE_CPU
Definition: clock.h:52
@ PSNIP_CLOCK_TYPE_MONOTONIC
Definition: clock.h:56
Definition: clock.h:59
uint64_t seconds
Definition: clock.h:60
uint64_t nanoseconds
Definition: clock.h:61