diff options
Diffstat (limited to '')
-rw-r--r-- | winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c | 1 | ||||
-rw-r--r-- | winpr/libwinpr/sysinfo/sysinfo.c | 150 |
2 files changed, 107 insertions, 44 deletions
diff --git a/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c b/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c index d43b588..854c93a 100644 --- a/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c +++ b/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c @@ -73,6 +73,7 @@ #include <sys/system_properties.h> #include <unistd.h> #include <winpr/wtypes.h> +#include <winpr/debug.h> static pthread_once_t g_once; static int g_inited; diff --git a/winpr/libwinpr/sysinfo/sysinfo.c b/winpr/libwinpr/sysinfo/sysinfo.c index f12f4eb..bf81b8b 100644 --- a/winpr/libwinpr/sysinfo/sysinfo.c +++ b/winpr/libwinpr/sysinfo/sysinfo.c @@ -33,9 +33,43 @@ #include <fcntl.h> #endif +#if !defined(_WIN32) +#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L) +#include <time.h> +#elif !defined(__APPLE__) +#include <sys/time.h> +#include <sys/sysinfo.h> +#endif +#endif + #include "../log.h" #define TAG WINPR_TAG("sysinfo") +#define FILETIME_TO_UNIX_OFFSET_S 11644473600UL + +#if defined(__MACH__) && defined(__APPLE__) + +#include <mach/mach_time.h> + +static UINT64 scaleHighPrecision(UINT64 i, UINT32 numer, UINT32 denom) +{ + UINT64 high = (i >> 32) * numer; + UINT64 low = (i & 0xffffffffull) * numer / denom; + UINT64 highRem = ((high % denom) << 32) / denom; + high /= denom; + return (high << 32) + highRem + low; +} + +static UINT64 mac_get_time_ns(void) +{ + mach_timebase_info_data_t timebase = { 0 }; + mach_timebase_info(&timebase); + UINT64 t = mach_absolute_time(); + return scaleHighPrecision(t, timebase.numer, timebase.denom); +} + +#endif + /** * api-ms-win-core-sysinfo-l1-1-1.dll: * @@ -272,13 +306,14 @@ BOOL SetLocalTime(CONST SYSTEMTIME* lpSystemTime) VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { - ULARGE_INTEGER time64; - time64.u.HighPart = 0; - /* time represented in tenths of microseconds since midnight of January 1, 1601 */ - time64.QuadPart = time(NULL) + 11644473600LL; /* Seconds since January 1, 1601 */ - time64.QuadPart *= 10000000; /* Convert timestamp to tenths of a microsecond */ - lpSystemTimeAsFileTime->dwLowDateTime = time64.u.LowPart; - lpSystemTimeAsFileTime->dwHighDateTime = time64.u.HighPart; + union + { + UINT64 u64; + FILETIME ft; + } t; + + t.u64 = (winpr_GetUnixTimeNS() / 100ull) + FILETIME_TO_UNIX_OFFSET_S * 10000000ull; + *lpSystemTimeAsFileTime = t.ft; } BOOL GetSystemTimeAdjustment(PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement, @@ -294,25 +329,7 @@ BOOL GetSystemTimeAdjustment(PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement, DWORD GetTickCount(void) { - DWORD ticks = 0; -#ifdef __linux__ - struct timespec ts; - - if (!clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) - ticks = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); - -#else - /** - * FIXME: this is relative to the Epoch time, and we - * need to return a value relative to the system uptime. - */ - struct timeval tv; - - if (!gettimeofday(&tv, NULL)) - ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - -#endif - return ticks; + return GetTickCount64(); } #endif // _WIN32 @@ -553,35 +570,80 @@ DWORD GetTickCount(void) ULONGLONG winpr_GetTickCount64(void) { - ULONGLONG ticks = 0; -#if defined(__linux__) - struct timespec ts; + const UINT64 ns = winpr_GetTickCount64NS(); + return WINPR_TIME_NS_TO_MS(ns); +} - if (!clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) - ticks = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); +#endif +UINT64 winpr_GetTickCount64NS(void) +{ + UINT64 ticks = 0; +#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L) + struct timespec ts = { 0 }; + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0) + ticks = (ts.tv_sec * 1000000000ull) + ts.tv_nsec; +#elif defined(__MACH__) && defined(__APPLE__) + ticks = mac_get_time_ns(); #elif defined(_WIN32) - FILETIME ft; - ULARGE_INTEGER ul; - GetSystemTimeAsFileTime(&ft); - ul.LowPart = ft.dwLowDateTime; - ul.HighPart = ft.dwHighDateTime; - ticks = ul.QuadPart; + LARGE_INTEGER li = { 0 }; + LARGE_INTEGER freq = { 0 }; + if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&li)) + ticks = li.QuadPart * 1000000000ull / freq.QuadPart; #else - /** - * FIXME: this is relative to the Epoch time, and we - * need to return a value relative to the system uptime. - */ - struct timeval tv; + struct timeval tv = { 0 }; - if (!gettimeofday(&tv, NULL)) - ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + if (gettimeofday(&tv, NULL) == 0) + ticks = (tv.tv_sec * 1000000000ull) + (tv.tv_usec * 1000ull); + + /* We need to trick here: + * this function should return the system uptime, but we need higher resolution. + * so on first call get the actual timestamp along with the system uptime. + * + * return the uptime measured from now on (e.g. current measure - first measure + uptime at + * first measure) + */ + static UINT64 first = 0; + static UINT64 uptime = 0; + if (first == 0) + { + struct sysinfo info = { 0 }; + if (sysinfo(&info) == 0) + { + first = ticks; + uptime = 1000000000ull * info.uptime; + } + } + ticks = ticks - first + uptime; #endif return ticks; } +UINT64 winpr_GetUnixTimeNS(void) +{ +#if defined(_WIN32) + + union + { + UINT64 u64; + FILETIME ft; + } t = { 0 }; + GetSystemTimeAsFileTime(&t.ft); + return (t.u64 - FILETIME_TO_UNIX_OFFSET_S * 10000000ull) * 100ull; +#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L) + struct timespec ts = { 0 }; + if (clock_gettime(CLOCK_REALTIME, &ts) != 0) + return 0; + return ts.tv_sec * 1000000000ull + ts.tv_nsec; +#else + struct timeval tv = { 0 }; + if (gettimeofday(&tv, NULL) != 0) + return 0; + return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ull; #endif +} /* If x86 */ #ifdef _M_IX86_AMD64 |