21#include <winpr/config.h>
23#include <winpr/assert.h>
24#include <winpr/sysinfo.h>
25#include <winpr/platform.h>
28#include "cpufeatures/cpu-features.h"
39#if defined(__MACOSX__)
40#include <CoreFoundation/CoreFoundation.h>
41#include <IOKit/ps/IOPowerSources.h>
42#include <IOKit/ps/IOPSKeys.h>
45#if defined(__FreeBSD__)
47#include <sys/sysctl.h>
51#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
53#elif !defined(__APPLE__)
55#include <sys/sysinfo.h>
60#define TAG WINPR_TAG("sysinfo")
62#define FILETIME_TO_UNIX_OFFSET_S 11644473600UL
64#if defined(__MACH__) && defined(__APPLE__)
66#include <mach/mach_time.h>
68static UINT64 scaleHighPrecision(UINT64 i, UINT32 numer, UINT32 denom)
70 UINT64 high = (i >> 32) * numer;
71 UINT64 low = (i & 0xffffffffull) * numer / denom;
72 UINT64 highRem = ((high % denom) << 32) / denom;
74 return (high << 32) + highRem + low;
77static UINT64 mac_get_time_ns(
void)
79 mach_timebase_info_data_t timebase = WINPR_C_ARRAY_INIT;
80 mach_timebase_info(&timebase);
81 UINT64 t = mach_absolute_time();
82 return scaleHighPrecision(t, timebase.numer, timebase.denom);
112#ifdef WINPR_HAVE_UNISTD_H
116#include <winpr/crt.h>
117#include <winpr/platform.h>
119#if defined(__MACOSX__) || defined(__IOS__)
120#include <sys/sysctl.h>
123static WORD GetProcessorArchitecture(
void)
125 WORD cpuArch = PROCESSOR_ARCHITECTURE_UNKNOWN;
127 AndroidCpuFamily family = android_getCpuFamily();
131 case ANDROID_CPU_FAMILY_ARM:
132 return PROCESSOR_ARCHITECTURE_ARM;
134 case ANDROID_CPU_FAMILY_X86:
135 return PROCESSOR_ARCHITECTURE_INTEL;
137 case ANDROID_CPU_FAMILY_MIPS:
138 return PROCESSOR_ARCHITECTURE_MIPS;
140 case ANDROID_CPU_FAMILY_ARM64:
141 return PROCESSOR_ARCHITECTURE_ARM64;
143 case ANDROID_CPU_FAMILY_X86_64:
144 return PROCESSOR_ARCHITECTURE_AMD64;
146 case ANDROID_CPU_FAMILY_MIPS64:
147 return PROCESSOR_ARCHITECTURE_MIPS64;
150 return PROCESSOR_ARCHITECTURE_UNKNOWN;
152#elif defined(__MACOSX__) || defined(__IOS__)
154 size_t len =
sizeof(val);
156 const int rc = sysctlbyname(
"hw.cputype", &val, &len,
nullptr, 0);
158 return PROCESSOR_ARCHITECTURE_UNKNOWN;
163 return PROCESSOR_ARCHITECTURE_INTEL;
164 case CPU_TYPE_X86_64:
165 return PROCESSOR_ARCHITECTURE_AMD64;
167 return PROCESSOR_ARCHITECTURE_ARM;
169 return PROCESSOR_ARCHITECTURE_ARM64;
170 case CPU_TYPE_ARM64_32:
171 return PROCESSOR_ARCHITECTURE_ARM;
173 return PROCESSOR_ARCHITECTURE_UNKNOWN;
177 cpuArch = PROCESSOR_ARCHITECTURE_ARM;
178#elif defined(_M_IX86)
179 cpuArch = PROCESSOR_ARCHITECTURE_INTEL;
180#elif defined(_M_MIPS64)
182 cpuArch = PROCESSOR_ARCHITECTURE_MIPS64;
183#elif defined(_M_MIPS)
184 cpuArch = PROCESSOR_ARCHITECTURE_MIPS;
185#elif defined(_M_ARM64)
186 cpuArch = PROCESSOR_ARCHITECTURE_ARM64;
187#elif defined(_M_AMD64)
188 cpuArch = PROCESSOR_ARCHITECTURE_AMD64;
190 cpuArch = PROCESSOR_ARCHITECTURE_PPC;
191#elif defined(_M_ALPHA)
192 cpuArch = PROCESSOR_ARCHITECTURE_ALPHA;
194 cpuArch = PROCESSOR_ARCHITECTURE_E2K;
199static DWORD GetNumberOfProcessors(
void)
203 return android_getCpuCount();
204#elif defined(__MACOSX__) || defined(__IOS__)
206 size_t len =
sizeof(val);
207 const int rc = sysctlbyname(
"hw.logicalcpu", &val, &len,
nullptr, 0);
209 numCPUs = WINPR_ASSERTING_INT_CAST(DWORD, val);
211 numCPUs = (DWORD)mpctl(MPC_GETNUMSPUS,
nullptr,
nullptr);
213 numCPUs = (DWORD)sysconf(_SC_NPROC_ONLN);
214#elif defined(_SC_NPROCESSORS_ONLN)
215 numCPUs = (DWORD)sysconf(_SC_NPROCESSORS_ONLN);
220static DWORD GetSystemPageSize(
void)
222 DWORD dwPageSize = 0;
223 long sc_page_size = -1;
224#if defined(_SC_PAGESIZE)
226 if (sc_page_size < 0)
227 sc_page_size = sysconf(_SC_PAGESIZE);
230#if defined(_SC_PAGE_SIZE)
232 if (sc_page_size < 0)
233 sc_page_size = sysconf(_SC_PAGE_SIZE);
237 if (sc_page_size > 0)
238 dwPageSize = (DWORD)sc_page_size;
240 if (dwPageSize < 4096)
249 WINPR_ASSERT(lpSystemInfo);
251 *lpSystemInfo = empty;
252 lpSystemInfo->DUMMYUNIONNAME.DUMMYSTRUCTNAME.wProcessorArchitecture =
253 GetProcessorArchitecture();
254 lpSystemInfo->dwPageSize = GetSystemPageSize();
255 lpSystemInfo->dwNumberOfProcessors = GetNumberOfProcessors();
260 GetSystemInfo(lpSystemInfo);
263void GetSystemTime(LPSYSTEMTIME lpSystemTime)
267 struct tm* stm =
nullptr;
268 WORD wMilliseconds = 0;
269 UINT64 now = winpr_GetUnixTimeNS();
270 ct = WINPR_TIME_NS_TO_S(now);
271 wMilliseconds = (WORD)(WINPR_TIME_NS_REM_MS(now));
272 stm = gmtime_r(&ct, &tres);
277 lpSystemTime->wYear = (WORD)(stm->tm_year + 1900);
278 lpSystemTime->wMonth = (WORD)(stm->tm_mon + 1);
279 lpSystemTime->wDayOfWeek = (WORD)stm->tm_wday;
280 lpSystemTime->wDay = (WORD)stm->tm_mday;
281 lpSystemTime->wHour = (WORD)stm->tm_hour;
282 lpSystemTime->wMinute = (WORD)stm->tm_min;
283 lpSystemTime->wSecond = (WORD)stm->tm_sec;
284 lpSystemTime->wMilliseconds = wMilliseconds;
288BOOL SetSystemTime(WINPR_ATTR_UNUSED CONST
SYSTEMTIME* lpSystemTime)
291 WLog_ERR(
"TODO",
"TODO: Implement");
295VOID GetLocalTime(LPSYSTEMTIME lpSystemTime)
299 struct tm* ltm =
nullptr;
300 WORD wMilliseconds = 0;
301 UINT64 now = winpr_GetUnixTimeNS();
302 ct = WINPR_TIME_NS_TO_S(now);
303 wMilliseconds = (WORD)(WINPR_TIME_NS_REM_MS(now));
304 ltm = localtime_r(&ct, &tres);
309 lpSystemTime->wYear = (WORD)(ltm->tm_year + 1900);
310 lpSystemTime->wMonth = (WORD)(ltm->tm_mon + 1);
311 lpSystemTime->wDayOfWeek = (WORD)ltm->tm_wday;
312 lpSystemTime->wDay = (WORD)ltm->tm_mday;
313 lpSystemTime->wHour = (WORD)ltm->tm_hour;
314 lpSystemTime->wMinute = (WORD)ltm->tm_min;
315 lpSystemTime->wSecond = (WORD)ltm->tm_sec;
316 lpSystemTime->wMilliseconds = wMilliseconds;
320BOOL SetLocalTime(WINPR_ATTR_UNUSED CONST
SYSTEMTIME* lpSystemTime)
323 WLog_ERR(
"TODO",
"TODO: Implement");
327VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
335 t.u64 = (winpr_GetUnixTimeNS() / 100ull) + FILETIME_TO_UNIX_OFFSET_S * 10000000ull;
336 *lpSystemTimeAsFileTime = t.ft;
339BOOL GetSystemTimeAdjustment(WINPR_ATTR_UNUSED PDWORD lpTimeAdjustment,
340 WINPR_ATTR_UNUSED PDWORD lpTimeIncrement,
341 WINPR_ATTR_UNUSED PBOOL lpTimeAdjustmentDisabled)
344 WLog_ERR(
"TODO",
"TODO: Implement");
348#ifdef CLOCK_MONOTONIC_RAW
349#define CLOCK_ID CLOCK_MONOTONIC_RAW
351#define CLOCK_ID CLOCK_MONOTONIC
354DWORD GetTickCount(
void)
356 return (DWORD)GetTickCount64();
360#if !defined(_WIN32) || defined(_UWP)
362#if defined(WITH_WINPR_DEPRECATED)
367BOOL GetVersionExA(LPOSVERSIONINFOA lpVersionInformation)
372 if ((lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOA)) ||
373 (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA)))
375 lpVersionInformation->dwMajorVersion = 10;
376 lpVersionInformation->dwMinorVersion = 0;
377 lpVersionInformation->dwBuildNumber = 0;
378 lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT;
379 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
381 if (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA))
383 LPOSVERSIONINFOEXA lpVersionInformationEx = (LPOSVERSIONINFOEXA)lpVersionInformation;
384 lpVersionInformationEx->wServicePackMajor = 0;
385 lpVersionInformationEx->wServicePackMinor = 0;
386 lpVersionInformationEx->wSuiteMask = 0;
387 lpVersionInformationEx->wProductType = VER_NT_WORKSTATION;
388 lpVersionInformationEx->wReserved = 0;
397 if ((lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOA)) ||
398 (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA)))
400 lpVersionInformation->dwMajorVersion = 6;
401 lpVersionInformation->dwMinorVersion = 1;
402 lpVersionInformation->dwBuildNumber = 7601;
403 lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT;
404 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
406 if (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA))
408 LPOSVERSIONINFOEXA lpVersionInformationEx = (LPOSVERSIONINFOEXA)lpVersionInformation;
409 lpVersionInformationEx->wServicePackMajor = 1;
410 lpVersionInformationEx->wServicePackMinor = 0;
411 lpVersionInformationEx->wSuiteMask = 0;
412 lpVersionInformationEx->wProductType = VER_NT_WORKSTATION;
413 lpVersionInformationEx->wReserved = 0;
423BOOL GetVersionExW(LPOSVERSIONINFOW lpVersionInformation)
425 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
426 return GetVersionExA((LPOSVERSIONINFOA)lpVersionInformation);
433#if !defined(_WIN32) || defined(_UWP)
435BOOL GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
438 LPSTR buffer =
nullptr;
439 if (!lpnSize || (*lpnSize > INT_MAX))
444 buffer = malloc(*lpnSize);
448 rc = GetComputerNameA(buffer, lpnSize);
450 if (rc && (*lpnSize > 0))
452 const SSIZE_T res = ConvertUtf8NToWChar(buffer, *lpnSize, lpBuffer, *lpnSize);
461BOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
465 SetLastError(ERROR_BAD_ARGUMENTS);
469 char hostname[256 + 1] = WINPR_C_ARRAY_INIT;
470 if (gethostname(hostname, ARRAYSIZE(hostname) - 1) == -1)
473 size_t length = strnlen(hostname, MAX_COMPUTERNAME_LENGTH);
474 const char* dot = strchr(hostname,
'.');
477 const size_t dotlen = WINPR_ASSERTING_INT_CAST(
size_t, (dot - hostname));
482 if ((*lpnSize <= (DWORD)length) || !lpBuffer)
484 SetLastError(ERROR_BUFFER_OVERFLOW);
485 *lpnSize = (DWORD)(length + 1);
489 strncpy(lpBuffer, hostname, length);
490 lpBuffer[length] =
'\0';
491 *lpnSize = (DWORD)length;
495BOOL GetComputerNameExA(COMPUTER_NAME_FORMAT NameType, LPSTR lpBuffer, LPDWORD lpnSize)
498 char hostname[256] = WINPR_C_ARRAY_INIT;
502 SetLastError(ERROR_BAD_ARGUMENTS);
506 if ((NameType == ComputerNameNetBIOS) || (NameType == ComputerNamePhysicalNetBIOS))
508 BOOL rc = GetComputerNameA(lpBuffer, lpnSize);
512 if (GetLastError() == ERROR_BUFFER_OVERFLOW)
513 SetLastError(ERROR_MORE_DATA);
519 if (gethostname(hostname,
sizeof(hostname)) == -1)
522 length = strnlen(hostname,
sizeof(hostname));
526 case ComputerNameDnsHostname:
527 case ComputerNameDnsDomain:
528 case ComputerNameDnsFullyQualified:
529 case ComputerNamePhysicalDnsHostname:
530 case ComputerNamePhysicalDnsDomain:
531 case ComputerNamePhysicalDnsFullyQualified:
532 if ((*lpnSize <= (DWORD)length) || !lpBuffer)
534 *lpnSize = (DWORD)(length + 1);
535 SetLastError(ERROR_MORE_DATA);
539 CopyMemory(lpBuffer, hostname, length);
540 lpBuffer[length] =
'\0';
541 *lpnSize = (DWORD)length;
551BOOL GetComputerNameExW(COMPUTER_NAME_FORMAT NameType, LPWSTR lpBuffer, LPDWORD lpnSize)
554 LPSTR lpABuffer =
nullptr;
558 SetLastError(ERROR_BAD_ARGUMENTS);
564 lpABuffer = calloc(*lpnSize,
sizeof(CHAR));
570 rc = GetComputerNameExA(NameType, lpABuffer, lpnSize);
572 if (rc && (*lpnSize > 0))
574 const SSIZE_T res = ConvertUtf8NToWChar(lpABuffer, *lpnSize, lpBuffer, *lpnSize);
582#if defined(__linux__)
584static BOOL sysinfo_read_sysfs_string(
const char* path,
char* buffer,
size_t size)
586 FILE* fp = fopen(path,
"r");
591 if (fgets(buffer, WINPR_ASSERTING_INT_CAST(
int, size), fp))
593 size_t len = strlen(buffer);
594 while ((len > 0) && ((buffer[len - 1] ==
'\n') || (buffer[len - 1] ==
'\r')))
595 buffer[--len] =
'\0';
600 WLog_ERR(TAG,
"error reading string in %s", path);
606static BOOL sysinfo_read_sysfs_int(
const char* path,
long long* value)
608 char buffer[64] = WINPR_C_ARRAY_INIT;
609 if (!sysinfo_read_sysfs_string(path, buffer,
sizeof(buffer)))
613 const long long v = strtoll(buffer, &end, 10);
625 DIR* dir = opendir(
"/sys/class/power_supply");
630 status->ACLineStatus = AC_LINE_ONLINE;
631 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
632 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
636 BOOL haveBattery = FALSE;
638 BOOL charging = FALSE;
639 long long percent = -1;
640 long long energyNow = -1;
641 long long energyFull = -1;
642 long long timeToEmpty = -1;
644 struct dirent* entry =
nullptr;
646 while ((entry = readdir(dir)) !=
nullptr)
648 char path[PATH_MAX] = WINPR_C_ARRAY_INIT;
649 char value[64] = WINPR_C_ARRAY_INIT;
652 if (entry->d_name[0] ==
'.')
655 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/type", entry->d_name);
656 if (!sysinfo_read_sysfs_string(path, value,
sizeof(value)))
659 if (strcmp(value,
"Battery") == 0)
661 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/present",
663 if (sysinfo_read_sysfs_int(path, &v) && (v == 0))
668 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/status",
670 if (sysinfo_read_sysfs_string(path, value,
sizeof(value)) &&
671 (strcmp(value,
"Charging") == 0))
674 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/capacity",
676 if (sysinfo_read_sysfs_int(path, &v))
679 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/time_to_empty_now",
681 if (sysinfo_read_sysfs_int(path, &v) && (v > 0))
688 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/energy_now",
690 (void)sysinfo_read_sysfs_int(path, &energyNow);
691 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/energy_full",
693 (void)sysinfo_read_sysfs_int(path, &energyFull);
695 if ((energyNow < 0) || (energyFull <= 0))
697 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/charge_now",
699 (void)sysinfo_read_sysfs_int(path, &energyNow);
700 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/charge_full",
702 (void)sysinfo_read_sysfs_int(path, &energyFull);
705 if ((energyNow >= 0) && (energyFull > 0))
706 percent = (energyNow * 100) / energyFull;
712 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/online",
714 if (sysinfo_read_sysfs_int(path, &v) && (v != 0))
722 status->ACLineStatus = AC_LINE_ONLINE;
723 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
724 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
728 status->ACLineStatus = (onAC || charging) ? AC_LINE_ONLINE : AC_LINE_OFFLINE;
732 flag |= BATTERY_FLAG_CHARGING;
738 status->BatteryLifePercent = (BYTE)percent;
741 flag |= BATTERY_FLAG_CRITICAL;
742 else if (percent <= 33)
743 flag |= BATTERY_FLAG_LOW;
744 else if (percent > 66)
745 flag |= BATTERY_FLAG_HIGH;
748 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
750 status->BatteryFlag = flag ? flag : BATTERY_FLAG_UNKNOWN;
753 status->BatteryLifeTime = (DWORD)timeToEmpty;
758#elif defined(__MACOSX__)
763 CFTypeRef blob = IOPSCopyPowerSourcesInfo();
766 WLog_ERR(TAG,
"unable to retrieve IOPSCopyPowerSourcesInfo()");
767 status->ACLineStatus = AC_LINE_ONLINE;
768 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
769 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
773 BOOL haveBattery = FALSE;
775 BOOL charging = FALSE;
777 int timeToEmptySeconds = -1;
779 CFArrayRef sources = IOPSCopyPowerSourcesList(blob);
782 const CFIndex count = CFArrayGetCount(sources);
783 for (CFIndex i = 0; i < count; i++)
785 CFDictionaryRef desc =
786 IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i));
790 CFBooleanRef isPresent = CFDictionaryGetValue(desc, CFSTR(kIOPSIsPresentKey));
791 if (isPresent && (CFBooleanGetValue(isPresent) ==
false))
794 CFStringRef stateStr = CFDictionaryGetValue(desc, CFSTR(kIOPSPowerSourceStateKey));
796 (CFStringCompare(stateStr, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo))
799 CFNumberRef curCapacity = CFDictionaryGetValue(desc, CFSTR(kIOPSCurrentCapacityKey));
800 CFNumberRef maxCapacity = CFDictionaryGetValue(desc, CFSTR(kIOPSMaxCapacityKey));
801 if (curCapacity && maxCapacity)
805 CFNumberGetValue(curCapacity, kCFNumberIntType, &cur);
806 CFNumberGetValue(maxCapacity, kCFNumberIntType, &max);
810 percent = (int)(((
long long)cur * 100) / max);
814 CFBooleanRef isCharging = CFDictionaryGetValue(desc, CFSTR(kIOPSIsChargingKey));
815 if (isCharging && CFBooleanGetValue(isCharging))
818 CFNumberRef timeToEmpty = CFDictionaryGetValue(desc, CFSTR(kIOPSTimeToEmptyKey));
822 CFNumberGetValue(timeToEmpty, kCFNumberIntType, &minutes);
824 timeToEmptySeconds = minutes * 60;
833 status->ACLineStatus = AC_LINE_ONLINE;
834 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
835 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
839 status->ACLineStatus = onAC ? AC_LINE_ONLINE : AC_LINE_OFFLINE;
843 flag |= BATTERY_FLAG_CHARGING;
849 status->BatteryLifePercent = (BYTE)percent;
852 flag |= BATTERY_FLAG_CRITICAL;
853 else if (percent <= 33)
854 flag |= BATTERY_FLAG_LOW;
855 else if (percent > 66)
856 flag |= BATTERY_FLAG_HIGH;
859 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
861 status->BatteryFlag = flag ? flag : BATTERY_FLAG_UNKNOWN;
863 if (timeToEmptySeconds > 0)
864 status->BatteryLifeTime = (DWORD)timeToEmptySeconds;
869#elif defined(__FreeBSD__)
871static BOOL sysinfo_sysctl_int(
const char* name,
int* value)
873 size_t len =
sizeof(*value);
874 return sysctlbyname(name, value, &len,
nullptr, 0) == 0;
880 if (!sysinfo_sysctl_int(
"hw.acpi.battery.units", &units) || (units <= 0))
882 status->ACLineStatus = AC_LINE_ONLINE;
883 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
884 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
889 (void)sysinfo_sysctl_int(
"hw.acpi.acline", &acline);
890 status->ACLineStatus =
891 (acline == 1) ? AC_LINE_ONLINE : ((acline == 0) ? AC_LINE_OFFLINE : AC_LINE_UNKNOWN);
894 (void)sysinfo_sysctl_int(
"hw.acpi.battery.life", &life);
897 (void)sysinfo_sysctl_int(
"hw.acpi.battery.time", &remaining);
902 (void)sysinfo_sysctl_int(
"hw.acpi.battery.state", &state);
906 flag |= BATTERY_FLAG_CHARGING;
908 flag |= BATTERY_FLAG_CRITICAL;
910 if ((life >= 0) && (life <= 100))
912 status->BatteryLifePercent = (BYTE)life;
913 if (!(flag & BATTERY_FLAG_CRITICAL))
916 flag |= BATTERY_FLAG_CRITICAL;
918 flag |= BATTERY_FLAG_LOW;
920 flag |= BATTERY_FLAG_HIGH;
924 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
926 status->BatteryFlag = flag ? flag : BATTERY_FLAG_UNKNOWN;
929 status->BatteryLifeTime = (DWORD)remaining * 60;
938 if (!lpSystemPowerStatus)
940 SetLastError(ERROR_BAD_ARGUMENTS);
946 lpSystemPowerStatus->ACLineStatus = AC_LINE_UNKNOWN;
947 lpSystemPowerStatus->BatteryFlag = BATTERY_FLAG_UNKNOWN;
948 lpSystemPowerStatus->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
949 lpSystemPowerStatus->SystemStatusFlag = 0;
950 lpSystemPowerStatus->BatteryLifeTime = BATTERY_LIFE_UNKNOWN;
951 lpSystemPowerStatus->BatteryFullLifeTime = BATTERY_LIFE_UNKNOWN;
953#if defined(__linux__) || defined(__MACOSX__) || defined(__FreeBSD__)
954 return sysinfo_get_power_status_platform(lpSystemPowerStatus);
956 WLog_WARN(TAG,
"GetSystemPowerStatus is not implemented on this platform, reporting "
957 "\"no battery, unknown state\"");
966DWORD GetTickCount(
void)
968 return (DWORD)GetTickCount64();
973#if (!defined(_WIN32)) || (defined(_WIN32) && (_WIN32_WINNT < 0x0600))
975ULONGLONG winpr_GetTickCount64(
void)
977 const UINT64 ns = winpr_GetTickCount64NS();
978 return WINPR_TIME_NS_TO_MS(ns);
983UINT64 winpr_GetTickCount64NS(
void)
986#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
987 struct timespec ts = WINPR_C_ARRAY_INIT;
989 if (clock_gettime(CLOCK_ID, &ts) == 0)
990 ticks = (WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_sec) * 1000000000ull) +
991 WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_nsec);
992#elif defined(__MACH__) && defined(__APPLE__)
993 ticks = mac_get_time_ns();
997 if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&li))
998 ticks = li.QuadPart * 1000000000ull / freq.QuadPart;
1000 struct timeval tv = WINPR_C_ARRAY_INIT;
1002 if (gettimeofday(&tv,
nullptr) == 0)
1003 ticks = (tv.tv_sec * 1000000000ull) + (tv.tv_usec * 1000ull);
1012 static UINT64 first = 0;
1013 static UINT64 uptime = 0;
1016 struct sysinfo info = WINPR_C_ARRAY_INIT;
1017 if (sysinfo(&info) == 0)
1020 uptime = 1000000000ull * info.uptime;
1024 ticks = ticks - first + uptime;
1029UINT64 winpr_GetUnixTimeNS(
void)
1037 } t = WINPR_C_ARRAY_INIT;
1038 GetSystemTimeAsFileTime(&t.ft);
1039 return (t.u64 - FILETIME_TO_UNIX_OFFSET_S * 10000000ull) * 100ull;
1040#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
1041 struct timespec ts = WINPR_C_ARRAY_INIT;
1042 if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
1044 return WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_sec) * 1000000000ull +
1045 WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_nsec);
1047 struct timeval tv = WINPR_C_ARRAY_INIT;
1048 if (gettimeofday(&tv,
nullptr) != 0)
1050 return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ull;
1057#if defined(__GNUC__)
1058#define xgetbv(_func_, _lo_, _hi_) \
1059 __asm__ __volatile__("xgetbv" : "=a"(_lo_), "=d"(_hi_) : "c"(_func_))
1060#elif defined(_MSC_VER)
1061#define xgetbv(_func_, _lo_, _hi_) \
1063 unsigned __int64 val = _xgetbv(_func_); \
1064 _lo_ = val & 0xFFFFFFFF; \
1065 _hi_ = (val >> 32); \
1069#define B_BIT_AVX2 (1 << 5)
1070#define B_BIT_AVX512F (1 << 16)
1071#define D_BIT_MMX (1 << 23)
1072#define D_BIT_SSE (1 << 25)
1073#define D_BIT_SSE2 (1 << 26)
1074#define D_BIT_3DN (1 << 30)
1076#define C_BIT_PCLMULQDQ (1 << 1)
1077#define C81_BIT_LZCNT (1 << 5)
1079#define C_BIT_3DNP (1 << 8)
1080#define C_BIT_SSSE3 (1 << 9)
1081#define C_BIT_SSE41 (1 << 19)
1082#define C_BIT_SSE42 (1 << 20)
1083#define C_BIT_FMA (1 << 12)
1084#define C_BIT_AES (1 << 25)
1085#define C_BIT_XGETBV (1 << 27)
1086#define C_BIT_AVX (1 << 28)
1087#define E_BIT_XMM (1 << 1)
1088#define E_BIT_YMM (1 << 2)
1089#define E_BITS_AVX (E_BIT_XMM | E_BIT_YMM)
1091static void cpuid(
unsigned info,
unsigned* eax,
unsigned* ebx,
unsigned* ecx,
unsigned* edx)
1094 *eax = *ebx = *ecx = *edx = 0;
1102 "xchg %%ebx, %%esi;"
1106 "xchg %%rbx, %%rsi;"
1108 :
"=a"(*eax),
"=S"(*ebx),
"=c"(*ecx),
"=d"(*edx)
1109 :
"a"(info),
"c"(0));
1110#elif defined(_MSC_VER)
1119#elif defined(_M_ARM) || defined(_M_ARM64)
1120#if defined(__linux__)
1122#define HWCAP_SWP (1 << 0)
1123#define HWCAP_HALF (1 << 1)
1124#define HWCAP_THUMB (1 << 2)
1125#define HWCAP_26BIT (1 << 3)
1126#define HWCAP_FAST_MULT (1 << 4)
1127#define HWCAP_FPA (1 << 5)
1128#define HWCAP_VFP (1 << 6)
1129#define HWCAP_EDSP (1 << 7)
1130#define HWCAP_JAVA (1 << 8)
1131#define HWCAP_IWMMXT (1 << 9)
1132#define HWCAP_CRUNCH (1 << 10)
1133#define HWCAP_THUMBEE (1 << 11)
1134#define HWCAP_NEON (1 << 12)
1135#define HWCAP_VFPv3 (1 << 13)
1136#define HWCAP_VFPv3D16 (1 << 14)
1137#define HWCAP_TLS (1 << 15)
1138#define HWCAP_VFPv4 (1 << 16)
1139#define HWCAP_IDIVA (1 << 17)
1140#define HWCAP_IDIVT (1 << 18)
1141#define HWCAP_VFPD32 (1 << 19)
1142#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
1147static unsigned GetARMCPUCaps(
void)
1150 int fd = open(
"/proc/self/auxv", O_RDONLY);
1164 num = read(fd, (
char*)&auxvec,
sizeof(auxvec));
1166 if (num < 1 || (auxvec.a_type == 0 && auxvec.a_val == 0))
1169 if (auxvec.a_type == AT_HWCAP)
1171 caps = auxvec.a_val;
1184#if defined(_M_ARM) || defined(_M_ARM64)
1186#include <sys/auxv.h>
1190BOOL IsProcessorFeaturePresent(DWORD ProcessorFeature)
1194 const uint64_t features = android_getCpuFeatures();
1195 const AndroidCpuFamily family = android_getCpuFamily();
1196 const BOOL isArm = (family == ANDROID_CPU_FAMILY_ARM) || (family == ANDROID_CPU_FAMILY_ARM64);
1197 const BOOL isX86 = (family == ANDROID_CPU_FAMILY_X86) || (family == ANDROID_CPU_FAMILY_X86_64);
1201 switch (ProcessorFeature)
1203 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1204 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
1205 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
1206 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1207 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1209 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
1210 return features & ANDROID_CPU_X86_FEATURE_SSSE3;
1211 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
1212 return features & ANDROID_CPU_X86_FEATURE_SSE4_1;
1213 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
1214 return features & ANDROID_CPU_X86_FEATURE_SSE4_2;
1215 case PF_AVX_INSTRUCTIONS_AVAILABLE:
1216 return features & ANDROID_CPU_X86_FEATURE_AVX;
1217 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
1218 return features & ANDROID_CPU_X86_FEATURE_AVX2;
1219 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
1221 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1228 switch (ProcessorFeature)
1230 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
1232 return features & ANDROID_CPU_ARM_FEATURE_NEON;
1235 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1240 WLog_WARN(TAG,
"Unsupported Android CPU family 0x%08" PRIx32, family);
1243#elif defined(_M_ARM) || defined(_M_ARM64)
1245 const unsigned long caps = getauxval(AT_HWCAP);
1247 switch (ProcessorFeature)
1249 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
1252 if (caps & HWCAP_NEON)
1258 if (caps & HWCAP_THUMB)
1261 case PF_ARM_VFP_32_REGISTERS_AVAILABLE:
1262 if (caps & HWCAP_VFPD32)
1265 case PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE:
1266 if ((caps & HWCAP_IDIVA) || (caps & HWCAP_IDIVT))
1270 if (caps & HWCAP_VFPv3)
1275 case PF_ARM_JAZELLE:
1276 if (caps & HWCAP_JAVA)
1282 if (caps & HWCAP_EDSP)
1288 if (caps & HWCAP_EDSP)
1294 if ((caps & HWCAP_IDIVT) || (caps & HWCAP_VFPv4))
1300 if (caps & HWCAP_THUMBEE)
1305 case PF_ARM_INTEL_WMMX:
1306 if (caps & HWCAP_IWMMXT)
1310 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1311 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
1312 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
1313 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1314 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1315 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
1316 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
1317 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
1318 case PF_AVX_INSTRUCTIONS_AVAILABLE:
1319 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
1320 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
1323 case PF_ARM_V8_INSTRUCTIONS_AVAILABLE:
1324 case PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE:
1325 case PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE:
1326 case PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE:
1327 case PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE:
1328 case PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE:
1329 case PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE:
1331 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1337 switch (ProcessorFeature)
1339 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1340 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
1341 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
1342 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1343 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1344 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
1345 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
1346 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
1347 case PF_AVX_INSTRUCTIONS_AVAILABLE:
1348 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
1349 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
1352 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
1358 case PF_ARM_V8_INSTRUCTIONS_AVAILABLE:
1359 case PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE:
1360 case PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE:
1361 case PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE:
1362 case PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE:
1363 case PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE:
1364 case PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE:
1366 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1373#if defined(_M_IX86_AMD64)
1379 cpuid(1, &a, &b, &c, &d);
1381 switch (ProcessorFeature)
1383 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1389 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
1395 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
1401 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1407 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1408 ret = __builtin_cpu_supports(
"sse3");
1411 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
1412 ret = __builtin_cpu_supports(
"ssse3");
1414 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
1415 ret = __builtin_cpu_supports(
"sse4.1");
1417 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
1418 ret = __builtin_cpu_supports(
"sse4.2");
1420 case PF_AVX_INSTRUCTIONS_AVAILABLE:
1421 ret = __builtin_cpu_supports(
"avx");
1423 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
1424 ret = __builtin_cpu_supports(
"avx2");
1426 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
1427 ret = __builtin_cpu_supports(
"avx512f");
1429 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
1430#if defined(__ARM_NEON__)
1435 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1444 switch (ProcessorFeature)
1446 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1452 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1458 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1474DWORD GetTickCountPrecise(
void)
1479 QueryPerformanceFrequency(&freq);
1480 QueryPerformanceCounter(¤t);
1481 return (DWORD)(current.QuadPart * 1000LL / freq.QuadPart);
1483 return GetTickCount();
1487BOOL IsProcessorFeaturePresentEx(DWORD ProcessorFeature)
1490#if defined(_M_ARM) || defined(_M_ARM64)
1493 caps = GetARMCPUCaps();
1495 switch (ProcessorFeature)
1497 case PF_EX_ARM_VFP1:
1498 if (caps & HWCAP_VFP)
1503 case PF_EX_ARM_VFP3D16:
1504 if (caps & HWCAP_VFPv3D16)
1509 case PF_EX_ARM_VFP4:
1510 if (caps & HWCAP_VFPv4)
1515 case PF_EX_ARM_IDIVA:
1516 if (caps & HWCAP_IDIVA)
1521 case PF_EX_ARM_IDIVT:
1522 if (caps & HWCAP_IDIVT)
1529#elif defined(_M_IX86_AMD64)
1534 cpuid(1, &a, &b, &c, &d);
1536 switch (ProcessorFeature)
1544 cpuid(0x80000001, &a81, &b81, &c81, &d81);
1546 if (c81 & C81_BIT_LZCNT)
1551 case PF_EX_3DNOW_PREFETCH:
1558 if (c & C_BIT_SSSE3)
1564 if (c & C_BIT_SSE41)
1570 if (c & C_BIT_SSE42)
1574#if defined(__GNUC__) || defined(_MSC_VER)
1581 case PF_EX_AVX_PCLMULQDQ:
1584 if (!(c & C_BIT_AVX))
1588 if (!(c & C_BIT_XGETBV))
1596 if ((e & E_BITS_AVX) == E_BITS_AVX)
1598 switch (ProcessorFeature)
1606 cpuid(7, &a, &b, &c, &d);
1607 switch (ProcessorFeature)
1615 if (b & B_BIT_AVX512F)
1636 case PF_EX_AVX_PCLMULQDQ:
1637 if (c & C_BIT_PCLMULQDQ)
1652#elif defined(_M_E2K)
1654 switch (ProcessorFeature)
mirrors the real Win32 SYSTEM_POWER_STATUS struct.