mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-12 23:07:21 +00:00
[common/client] platform: make timing waits portable
This commit is contained in:
@@ -22,9 +22,10 @@
|
||||
#define _H_LG_COMMON_EVENT_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TIMEOUT_INFINITE ((unsigned int)~0)
|
||||
#define TIMEOUT_INFINITE_NS UINT64_MAX
|
||||
|
||||
typedef struct LGEvent LGEvent;
|
||||
|
||||
@@ -38,8 +39,7 @@ bool lgResetEvent (LGEvent * handle);
|
||||
// for windows this is an event HANDLE
|
||||
LGEvent * lgWrapEvent(void * handle);
|
||||
|
||||
// Posix specific, not implmented/possible in windows
|
||||
bool lgWaitEventAbs(LGEvent * handle, struct timespec * ts);
|
||||
bool lgWaitEventNS (LGEvent * handle, unsigned int timeout);
|
||||
bool lgWaitEventDeadline(LGEvent * handle, uint64_t deadlineNs);
|
||||
bool lgWaitEventNS (LGEvent * handle, uint64_t timeoutNs);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,120 +20,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include "common/util.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
void windowsSetTimerResolution(void);
|
||||
NTSYSCALLAPI NTSTATUS NTAPI NtDelayExecution(
|
||||
_In_ BOOLEAN Alertable,
|
||||
_In_opt_ PLARGE_INTEGER DelayInterval
|
||||
);
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct LGTimer LGTimer;
|
||||
|
||||
static inline uint64_t microtime(void)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
static unsigned long div = 0;
|
||||
if (unlikely(div == 0))
|
||||
{
|
||||
LARGE_INTEGER freq = { .QuadPart = 0LL };
|
||||
QueryPerformanceFrequency(&freq);
|
||||
div = freq.QuadPart / 1000000LL;
|
||||
if(div == 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
return time.QuadPart / div;
|
||||
#else
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
return (uint64_t)time.tv_sec * 1000000LL + time.tv_nsec / 1000LL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void nsleep(uint64_t ns)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
LARGE_INTEGER interval = { .QuadPart = -(int64_t)(ns / 100LL) };
|
||||
NtDelayExecution(FALSE, &interval);
|
||||
#else
|
||||
const struct timespec ts =
|
||||
{
|
||||
.tv_sec = ns / 1000000000,
|
||||
.tv_nsec = ns % 1000000000,
|
||||
};
|
||||
nanosleep(&ts, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t nanotime(void)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
static double multiplier = 0.0;
|
||||
if (unlikely(!multiplier))
|
||||
{
|
||||
LARGE_INTEGER freq = { .QuadPart = 0LL };
|
||||
QueryPerformanceFrequency(&freq);
|
||||
if (freq.QuadPart == 0)
|
||||
abort();
|
||||
|
||||
multiplier = 1e9 / freq.QuadPart;
|
||||
}
|
||||
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
return (uint64_t) (time.QuadPart * multiplier);
|
||||
#else
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &time);
|
||||
return ((uint64_t)time.tv_sec * 1000000000LL) + time.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void tsDiff(struct timespec *diff, const struct timespec *left,
|
||||
const struct timespec *right)
|
||||
{
|
||||
diff->tv_sec = left->tv_sec - right->tv_sec;
|
||||
diff->tv_nsec = left->tv_nsec - right->tv_nsec;
|
||||
if (diff->tv_nsec < 0)
|
||||
{
|
||||
--diff->tv_sec;
|
||||
diff->tv_nsec += 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t __iter_div_u64_rem(uint64_t dividend, uint32_t divisor, uint64_t *remainder)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
while (dividend >= divisor) {
|
||||
/* The following asm() prevents the compiler from
|
||||
optimising this loop into a modulo operation. */
|
||||
asm("" : "+rm"(dividend));
|
||||
|
||||
dividend -= divisor;
|
||||
ret++;
|
||||
}
|
||||
|
||||
*remainder = dividend;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void tsAdd(struct timespec *a, uint64_t ns)
|
||||
{
|
||||
a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, 1000000000L, &ns);
|
||||
a->tv_nsec = ns;
|
||||
}
|
||||
void lgTimeInit(void);
|
||||
uint64_t microtime (void);
|
||||
uint64_t nanotime (void);
|
||||
void nsleep (uint64_t ns);
|
||||
|
||||
typedef bool (*LGTimerFn)(void * udata);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user