This commit is contained in:
Connor 2017-09-14 10:19:16 -07:00 committed by GitHub
parent daafe529f3
commit 5bd84506a0

64
clock.h
View file

@ -6,15 +6,13 @@
* copyright and related or neighboring rights to this code. For * copyright and related or neighboring rights to this code. For
* details, see the Creative Commons Zero 1.0 Universal license at * details, see the Creative Commons Zero 1.0 Universal license at
* https://creativecommons.org/publicdomain/zero/1.0/ * https://creativecommons.org/publicdomain/zero/1.0/
*
* Modified by Connor Olding, 2017
*/ */
#if !defined(PSNIP_CLOCK_H) #if !defined(PSNIP_CLOCK_H)
#define PSNIP_CLOCK_H #define PSNIP_CLOCK_H
#if !defined(psnip_uint64_t)
# include "../exact-int/exact-int.h"
#endif
#if !defined(PSNIP_CLOCK_STATIC_INLINE) #if !defined(PSNIP_CLOCK_STATIC_INLINE)
# if defined(__GNUC__) # if defined(__GNUC__)
# define PSNIP_CLOCK__COMPILER_ATTRIBUTES __attribute__((__unused__)) # define PSNIP_CLOCK__COMPILER_ATTRIBUTES __attribute__((__unused__))
@ -42,8 +40,8 @@ enum PsnipClockType {
}; };
struct PsnipClockTimespec { struct PsnipClockTimespec {
psnip_uint64_t seconds; uint64_t seconds;
psnip_uint64_t nanoseconds; uint64_t nanoseconds;
}; };
/* Methods we support: */ /* Methods we support: */
@ -102,7 +100,7 @@ struct PsnipClockTimespec {
# endif # endif
#endif #endif
#if defined(__MACH__) && !defined(__gnu_hurd__) #if defined(__MACH__)
# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) # if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME # define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
# endif # endif
@ -190,7 +188,31 @@ struct PsnipClockTimespec {
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \ (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \ (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64))
# include <windows.h> typedef struct _FILETIME {
uint32_t dwLowDateTime;
uint32_t dwHighDateTime;
} FILETIME;
typedef union _LARGE_INTEGER {
struct {
uint32_t LowPart;
int32_t HighPart;
};
struct {
uint32_t LowPart;
int32_t HighPart;
} u;
int64_t QuadPart;
} LARGE_INTEGER;
void * __stdcall GetCurrentProcess(void);
int __stdcall QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
int __stdcall QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);
int __stdcall GetProcessTimes(
void *hProcess,
FILETIME *lpCreationTime,
FILETIME *lpExitTime,
FILETIME *lpKernelTime,
FILETIME *lpUserTime
);
#endif #endif
#if \ #if \
@ -212,13 +234,13 @@ struct PsnipClockTimespec {
/*** Implementations ***/ /*** Implementations ***/
#define PSNIP_CLOCK_NSEC_PER_SEC ((psnip_uint32_t) (1000000000ULL)) #define PSNIP_CLOCK_NSEC_PER_SEC ((uint32_t) (1000000000ULL))
#if \ #if \
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \ (defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \ (defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME))
PSNIP_CLOCK__FUNCTION psnip_uint32_t PSNIP_CLOCK__FUNCTION uint32_t
psnip_clock__clock_getres (clockid_t clk_id) { psnip_clock__clock_getres (clockid_t clk_id) {
struct timespec res; struct timespec res;
int r; int r;
@ -227,7 +249,7 @@ psnip_clock__clock_getres (clockid_t clk_id) {
if (r != 0) if (r != 0)
return 0; return 0;
return (psnip_uint32_t) (PSNIP_CLOCK_NSEC_PER_SEC / res.tv_nsec); return (uint32_t) (PSNIP_CLOCK_NSEC_PER_SEC / res.tv_nsec);
} }
PSNIP_CLOCK__FUNCTION int PSNIP_CLOCK__FUNCTION int
@ -237,14 +259,14 @@ psnip_clock__clock_gettime (clockid_t clk_id, struct PsnipClockTimespec* res) {
if (clock_gettime(clk_id, &ts) != 0) if (clock_gettime(clk_id, &ts) != 0)
return -10; return -10;
res->seconds = (psnip_uint64_t) (ts.tv_sec); res->seconds = (uint64_t) (ts.tv_sec);
res->nanoseconds = (psnip_uint64_t) (ts.tv_nsec); res->nanoseconds = (uint64_t) (ts.tv_nsec);
return 0; return 0;
} }
#endif #endif
PSNIP_CLOCK__FUNCTION psnip_uint32_t PSNIP_CLOCK__FUNCTION uint32_t
psnip_clock_wall_get_precision (void) { psnip_clock_wall_get_precision (void) {
#if !defined(PSNIP_CLOCK_WALL_METHOD) #if !defined(PSNIP_CLOCK_WALL_METHOD)
return 0; return 0;
@ -285,7 +307,7 @@ psnip_clock_wall_get_time (struct PsnipClockTimespec* res) {
return 0; return 0;
} }
PSNIP_CLOCK__FUNCTION psnip_uint32_t PSNIP_CLOCK__FUNCTION uint32_t
psnip_clock_cpu_get_precision (void) { psnip_clock_cpu_get_precision (void) {
#if !defined(PSNIP_CLOCK_CPU_METHOD) #if !defined(PSNIP_CLOCK_CPU_METHOD)
return 0; return 0;
@ -343,7 +365,7 @@ psnip_clock_cpu_get_time (struct PsnipClockTimespec* res) {
return 0; return 0;
} }
PSNIP_CLOCK__FUNCTION psnip_uint32_t PSNIP_CLOCK__FUNCTION uint32_t
psnip_clock_monotonic_get_precision (void) { psnip_clock_monotonic_get_precision (void) {
#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) #if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
return 0; return 0;
@ -353,13 +375,13 @@ psnip_clock_monotonic_get_precision (void) {
static mach_timebase_info_data_t tbi = { 0, }; static mach_timebase_info_data_t tbi = { 0, };
if (tbi.denom == 0) if (tbi.denom == 0)
mach_timebase_info(&tbi); mach_timebase_info(&tbi);
return (psnip_uint32_t) (tbi.numer / tbi.denom); return (uint32_t) (tbi.numer / tbi.denom);
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64 #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64
return 1000; return 1000;
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
LARGE_INTEGER Frequency; LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency); QueryPerformanceFrequency(&Frequency);
return (psnip_uint32_t) ((Frequency.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC) ? PSNIP_CLOCK_NSEC_PER_SEC : Frequency.QuadPart); return (uint32_t) ((Frequency.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC) ? PSNIP_CLOCK_NSEC_PER_SEC : Frequency.QuadPart);
#else #else
return 0; return 0;
#endif #endif
@ -373,11 +395,11 @@ psnip_clock_monotonic_get_time (struct PsnipClockTimespec* res) {
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC, res); return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC, res);
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
psnip_uint64_t nsec = mach_absolute_time(); uint64_t nsec = mach_absolute_time();
static mach_timebase_info_data_t tbi = { 0, }; static mach_timebase_info_data_t tbi = { 0, };
if (tbi.denom == 0) if (tbi.denom == 0)
mach_timebase_info(&tbi); mach_timebase_info(&tbi);
nsec *= ((psnip_uint64_t) tbi.numer) / ((psnip_uint64_t) tbi.denom); nsec *= ((uint64_t) tbi.numer) / ((uint64_t) tbi.denom);
res->seconds = nsec / PSNIP_CLOCK_NSEC_PER_SEC; res->seconds = nsec / PSNIP_CLOCK_NSEC_PER_SEC;
res->nanoseconds = nsec % PSNIP_CLOCK_NSEC_PER_SEC; res->nanoseconds = nsec % PSNIP_CLOCK_NSEC_PER_SEC;
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
@ -415,7 +437,7 @@ psnip_clock_monotonic_get_time (struct PsnipClockTimespec* res) {
* Note that different clocks on the same system often have a * Note that different clocks on the same system often have a
* different precisions. * different precisions.
*/ */
PSNIP_CLOCK__FUNCTION psnip_uint32_t PSNIP_CLOCK__FUNCTION uint32_t
psnip_clock_get_precision (enum PsnipClockType clock_type) { psnip_clock_get_precision (enum PsnipClockType clock_type) {
switch (clock_type) { switch (clock_type) {
case PSNIP_CLOCK_TYPE_MONOTONIC: case PSNIP_CLOCK_TYPE_MONOTONIC: