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;
170 return PROCESSOR_ARCHITECTURE_ARM64;
172#ifdef CPU_TYPE_ARM64_32
173 case CPU_TYPE_ARM64_32:
174 return PROCESSOR_ARCHITECTURE_ARM;
176#ifdef CPU_TYPE_POWERPC
177 case CPU_TYPE_POWERPC:
178 return PROCESSOR_ARCHITECTURE_PPC;
180#ifdef CPU_TYPE_POWERPC64
181 case CPU_TYPE_POWERPC64:
182 return PROCESSOR_ARCHITECTURE_PPC;
185 return PROCESSOR_ARCHITECTURE_UNKNOWN;
189 cpuArch = PROCESSOR_ARCHITECTURE_ARM;
190#elif defined(_M_IX86)
191 cpuArch = PROCESSOR_ARCHITECTURE_INTEL;
192#elif defined(_M_MIPS64)
194 cpuArch = PROCESSOR_ARCHITECTURE_MIPS64;
195#elif defined(_M_MIPS)
196 cpuArch = PROCESSOR_ARCHITECTURE_MIPS;
197#elif defined(_M_ARM64)
198 cpuArch = PROCESSOR_ARCHITECTURE_ARM64;
199#elif defined(_M_AMD64)
200 cpuArch = PROCESSOR_ARCHITECTURE_AMD64;
202 cpuArch = PROCESSOR_ARCHITECTURE_PPC;
203#elif defined(_M_ALPHA)
204 cpuArch = PROCESSOR_ARCHITECTURE_ALPHA;
206 cpuArch = PROCESSOR_ARCHITECTURE_E2K;
211static DWORD GetNumberOfProcessors(
void)
215 return android_getCpuCount();
216#elif defined(__MACOSX__) || defined(__IOS__)
218 size_t len =
sizeof(val);
219 const int rc = sysctlbyname(
"hw.logicalcpu", &val, &len,
nullptr, 0);
221 numCPUs = WINPR_ASSERTING_INT_CAST(DWORD, val);
223 numCPUs = (DWORD)mpctl(MPC_GETNUMSPUS,
nullptr,
nullptr);
225 numCPUs = (DWORD)sysconf(_SC_NPROC_ONLN);
226#elif defined(_SC_NPROCESSORS_ONLN)
227 numCPUs = (DWORD)sysconf(_SC_NPROCESSORS_ONLN);
232static DWORD GetSystemPageSize(
void)
234 DWORD dwPageSize = 0;
235 long sc_page_size = -1;
236#if defined(_SC_PAGESIZE)
238 if (sc_page_size < 0)
239 sc_page_size = sysconf(_SC_PAGESIZE);
242#if defined(_SC_PAGE_SIZE)
244 if (sc_page_size < 0)
245 sc_page_size = sysconf(_SC_PAGE_SIZE);
249 if (sc_page_size > 0)
250 dwPageSize = (DWORD)sc_page_size;
252 if (dwPageSize < 4096)
261 WINPR_ASSERT(lpSystemInfo);
263 *lpSystemInfo = empty;
264 lpSystemInfo->DUMMYUNIONNAME.DUMMYSTRUCTNAME.wProcessorArchitecture =
265 GetProcessorArchitecture();
266 lpSystemInfo->dwPageSize = GetSystemPageSize();
267 lpSystemInfo->dwNumberOfProcessors = GetNumberOfProcessors();
272 GetSystemInfo(lpSystemInfo);
275void GetSystemTime(LPSYSTEMTIME lpSystemTime)
279 struct tm* stm =
nullptr;
280 WORD wMilliseconds = 0;
281 UINT64 now = winpr_GetUnixTimeNS();
282 ct = WINPR_TIME_NS_TO_S(now);
283 wMilliseconds = (WORD)(WINPR_TIME_NS_REM_MS(now));
284 stm = gmtime_r(&ct, &tres);
289 lpSystemTime->wYear = (WORD)(stm->tm_year + 1900);
290 lpSystemTime->wMonth = (WORD)(stm->tm_mon + 1);
291 lpSystemTime->wDayOfWeek = (WORD)stm->tm_wday;
292 lpSystemTime->wDay = (WORD)stm->tm_mday;
293 lpSystemTime->wHour = (WORD)stm->tm_hour;
294 lpSystemTime->wMinute = (WORD)stm->tm_min;
295 lpSystemTime->wSecond = (WORD)stm->tm_sec;
296 lpSystemTime->wMilliseconds = wMilliseconds;
300BOOL SetSystemTime(WINPR_ATTR_UNUSED CONST
SYSTEMTIME* lpSystemTime)
303 WLog_ERR(
"TODO",
"TODO: Implement");
307VOID GetLocalTime(LPSYSTEMTIME lpSystemTime)
311 struct tm* ltm =
nullptr;
312 WORD wMilliseconds = 0;
313 UINT64 now = winpr_GetUnixTimeNS();
314 ct = WINPR_TIME_NS_TO_S(now);
315 wMilliseconds = (WORD)(WINPR_TIME_NS_REM_MS(now));
316 ltm = localtime_r(&ct, &tres);
321 lpSystemTime->wYear = (WORD)(ltm->tm_year + 1900);
322 lpSystemTime->wMonth = (WORD)(ltm->tm_mon + 1);
323 lpSystemTime->wDayOfWeek = (WORD)ltm->tm_wday;
324 lpSystemTime->wDay = (WORD)ltm->tm_mday;
325 lpSystemTime->wHour = (WORD)ltm->tm_hour;
326 lpSystemTime->wMinute = (WORD)ltm->tm_min;
327 lpSystemTime->wSecond = (WORD)ltm->tm_sec;
328 lpSystemTime->wMilliseconds = wMilliseconds;
332BOOL SetLocalTime(WINPR_ATTR_UNUSED CONST
SYSTEMTIME* lpSystemTime)
335 WLog_ERR(
"TODO",
"TODO: Implement");
339VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
347 t.u64 = (winpr_GetUnixTimeNS() / 100ull) + FILETIME_TO_UNIX_OFFSET_S * 10000000ull;
348 *lpSystemTimeAsFileTime = t.ft;
351BOOL GetSystemTimeAdjustment(WINPR_ATTR_UNUSED PDWORD lpTimeAdjustment,
352 WINPR_ATTR_UNUSED PDWORD lpTimeIncrement,
353 WINPR_ATTR_UNUSED PBOOL lpTimeAdjustmentDisabled)
356 WLog_ERR(
"TODO",
"TODO: Implement");
360#ifdef CLOCK_MONOTONIC_RAW
361#define CLOCK_ID CLOCK_MONOTONIC_RAW
363#define CLOCK_ID CLOCK_MONOTONIC
366DWORD GetTickCount(
void)
368 return (DWORD)GetTickCount64();
372#if !defined(_WIN32) || defined(_UWP)
374#if defined(WITH_WINPR_DEPRECATED)
379BOOL GetVersionExA(LPOSVERSIONINFOA lpVersionInformation)
384 if ((lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOA)) ||
385 (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA)))
387 lpVersionInformation->dwMajorVersion = 10;
388 lpVersionInformation->dwMinorVersion = 0;
389 lpVersionInformation->dwBuildNumber = 0;
390 lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT;
391 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
393 if (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA))
395 LPOSVERSIONINFOEXA lpVersionInformationEx = (LPOSVERSIONINFOEXA)lpVersionInformation;
396 lpVersionInformationEx->wServicePackMajor = 0;
397 lpVersionInformationEx->wServicePackMinor = 0;
398 lpVersionInformationEx->wSuiteMask = 0;
399 lpVersionInformationEx->wProductType = VER_NT_WORKSTATION;
400 lpVersionInformationEx->wReserved = 0;
409 if ((lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOA)) ||
410 (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA)))
412 lpVersionInformation->dwMajorVersion = 6;
413 lpVersionInformation->dwMinorVersion = 1;
414 lpVersionInformation->dwBuildNumber = 7601;
415 lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT;
416 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
418 if (lpVersionInformation->dwOSVersionInfoSize ==
sizeof(OSVERSIONINFOEXA))
420 LPOSVERSIONINFOEXA lpVersionInformationEx = (LPOSVERSIONINFOEXA)lpVersionInformation;
421 lpVersionInformationEx->wServicePackMajor = 1;
422 lpVersionInformationEx->wServicePackMinor = 0;
423 lpVersionInformationEx->wSuiteMask = 0;
424 lpVersionInformationEx->wProductType = VER_NT_WORKSTATION;
425 lpVersionInformationEx->wReserved = 0;
435BOOL GetVersionExW(LPOSVERSIONINFOW lpVersionInformation)
437 ZeroMemory(lpVersionInformation->szCSDVersion,
sizeof(lpVersionInformation->szCSDVersion));
438 return GetVersionExA((LPOSVERSIONINFOA)lpVersionInformation);
445#if !defined(_WIN32) || defined(_UWP)
447BOOL GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
450 LPSTR buffer =
nullptr;
451 if (!lpnSize || (*lpnSize > INT_MAX))
456 buffer = malloc(*lpnSize);
460 rc = GetComputerNameA(buffer, lpnSize);
462 if (rc && (*lpnSize > 0))
464 const SSIZE_T res = ConvertUtf8NToWChar(buffer, *lpnSize, lpBuffer, *lpnSize);
473BOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
477 SetLastError(ERROR_BAD_ARGUMENTS);
481 char hostname[256 + 1] = WINPR_C_ARRAY_INIT;
482 if (gethostname(hostname, ARRAYSIZE(hostname) - 1) == -1)
485 size_t length = strnlen(hostname, MAX_COMPUTERNAME_LENGTH);
486 const char* dot = strchr(hostname,
'.');
489 const size_t dotlen = WINPR_ASSERTING_INT_CAST(
size_t, (dot - hostname));
494 if ((*lpnSize <= (DWORD)length) || !lpBuffer)
496 SetLastError(ERROR_BUFFER_OVERFLOW);
497 *lpnSize = (DWORD)(length + 1);
501 strncpy(lpBuffer, hostname, length);
502 lpBuffer[length] =
'\0';
503 *lpnSize = (DWORD)length;
507BOOL GetComputerNameExA(COMPUTER_NAME_FORMAT NameType, LPSTR lpBuffer, LPDWORD lpnSize)
510 char hostname[256] = WINPR_C_ARRAY_INIT;
514 SetLastError(ERROR_BAD_ARGUMENTS);
518 if ((NameType == ComputerNameNetBIOS) || (NameType == ComputerNamePhysicalNetBIOS))
520 BOOL rc = GetComputerNameA(lpBuffer, lpnSize);
524 if (GetLastError() == ERROR_BUFFER_OVERFLOW)
525 SetLastError(ERROR_MORE_DATA);
531 if (gethostname(hostname,
sizeof(hostname)) == -1)
534 length = strnlen(hostname,
sizeof(hostname));
538 case ComputerNameDnsHostname:
539 case ComputerNameDnsDomain:
540 case ComputerNameDnsFullyQualified:
541 case ComputerNamePhysicalDnsHostname:
542 case ComputerNamePhysicalDnsDomain:
543 case ComputerNamePhysicalDnsFullyQualified:
544 if ((*lpnSize <= (DWORD)length) || !lpBuffer)
546 *lpnSize = (DWORD)(length + 1);
547 SetLastError(ERROR_MORE_DATA);
551 CopyMemory(lpBuffer, hostname, length);
552 lpBuffer[length] =
'\0';
553 *lpnSize = (DWORD)length;
563BOOL GetComputerNameExW(COMPUTER_NAME_FORMAT NameType, LPWSTR lpBuffer, LPDWORD lpnSize)
566 LPSTR lpABuffer =
nullptr;
570 SetLastError(ERROR_BAD_ARGUMENTS);
576 lpABuffer = calloc(*lpnSize,
sizeof(CHAR));
582 rc = GetComputerNameExA(NameType, lpABuffer, lpnSize);
584 if (rc && (*lpnSize > 0))
586 const SSIZE_T res = ConvertUtf8NToWChar(lpABuffer, *lpnSize, lpBuffer, *lpnSize);
594#if defined(__linux__)
596static BOOL sysinfo_read_sysfs_string(
const char* path,
char* buffer,
size_t size)
598 FILE* fp = fopen(path,
"r");
603 if (fgets(buffer, WINPR_ASSERTING_INT_CAST(
int, size), fp))
605 size_t len = strlen(buffer);
606 while ((len > 0) && ((buffer[len - 1] ==
'\n') || (buffer[len - 1] ==
'\r')))
607 buffer[--len] =
'\0';
612 WLog_ERR(TAG,
"error reading string in %s", path);
618static BOOL sysinfo_read_sysfs_int(
const char* path,
long long* value)
620 char buffer[64] = WINPR_C_ARRAY_INIT;
621 if (!sysinfo_read_sysfs_string(path, buffer,
sizeof(buffer)))
625 const long long v = strtoll(buffer, &end, 10);
637 DIR* dir = opendir(
"/sys/class/power_supply");
642 status->ACLineStatus = AC_LINE_ONLINE;
643 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
644 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
648 BOOL haveBattery = FALSE;
650 BOOL charging = FALSE;
651 long long percent = -1;
652 long long energyNow = -1;
653 long long energyFull = -1;
654 long long timeToEmpty = -1;
656 struct dirent* entry =
nullptr;
658 while ((entry = readdir(dir)) !=
nullptr)
660 char path[PATH_MAX] = WINPR_C_ARRAY_INIT;
661 char value[64] = WINPR_C_ARRAY_INIT;
664 if (entry->d_name[0] ==
'.')
667 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/type", entry->d_name);
668 if (!sysinfo_read_sysfs_string(path, value,
sizeof(value)))
671 if (strcmp(value,
"Battery") == 0)
673 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/present",
675 if (sysinfo_read_sysfs_int(path, &v) && (v == 0))
680 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/status",
682 if (sysinfo_read_sysfs_string(path, value,
sizeof(value)) &&
683 (strcmp(value,
"Charging") == 0))
686 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/capacity",
688 if (sysinfo_read_sysfs_int(path, &v))
691 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/time_to_empty_now",
693 if (sysinfo_read_sysfs_int(path, &v) && (v > 0))
700 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/energy_now",
702 (void)sysinfo_read_sysfs_int(path, &energyNow);
703 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/energy_full",
705 (void)sysinfo_read_sysfs_int(path, &energyFull);
707 if ((energyNow < 0) || (energyFull <= 0))
709 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/charge_now",
711 (void)sysinfo_read_sysfs_int(path, &energyNow);
712 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/charge_full",
714 (void)sysinfo_read_sysfs_int(path, &energyFull);
717 if ((energyNow >= 0) && (energyFull > 0))
718 percent = (energyNow * 100) / energyFull;
724 (void)snprintf(path,
sizeof(path) - 1,
"/sys/class/power_supply/%s/online",
726 if (sysinfo_read_sysfs_int(path, &v) && (v != 0))
734 status->ACLineStatus = AC_LINE_ONLINE;
735 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
736 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
740 status->ACLineStatus = (onAC || charging) ? AC_LINE_ONLINE : AC_LINE_OFFLINE;
744 flag |= BATTERY_FLAG_CHARGING;
750 status->BatteryLifePercent = (BYTE)percent;
753 flag |= BATTERY_FLAG_CRITICAL;
754 else if (percent <= 33)
755 flag |= BATTERY_FLAG_LOW;
756 else if (percent > 66)
757 flag |= BATTERY_FLAG_HIGH;
760 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
762 status->BatteryFlag = flag ? flag : BATTERY_FLAG_UNKNOWN;
765 status->BatteryLifeTime = (DWORD)timeToEmpty;
770#elif defined(__MACOSX__)
775 CFTypeRef blob = IOPSCopyPowerSourcesInfo();
778 WLog_ERR(TAG,
"unable to retrieve IOPSCopyPowerSourcesInfo()");
779 status->ACLineStatus = AC_LINE_ONLINE;
780 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
781 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
785 BOOL haveBattery = FALSE;
787 BOOL charging = FALSE;
789 int timeToEmptySeconds = -1;
791 CFArrayRef sources = IOPSCopyPowerSourcesList(blob);
794 const CFIndex count = CFArrayGetCount(sources);
795 for (CFIndex i = 0; i < count; i++)
797 CFDictionaryRef desc =
798 IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i));
802 CFBooleanRef isPresent = CFDictionaryGetValue(desc, CFSTR(kIOPSIsPresentKey));
803 if (isPresent && (CFBooleanGetValue(isPresent) ==
false))
806 CFStringRef stateStr = CFDictionaryGetValue(desc, CFSTR(kIOPSPowerSourceStateKey));
808 (CFStringCompare(stateStr, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo))
811 CFNumberRef curCapacity = CFDictionaryGetValue(desc, CFSTR(kIOPSCurrentCapacityKey));
812 CFNumberRef maxCapacity = CFDictionaryGetValue(desc, CFSTR(kIOPSMaxCapacityKey));
813 if (curCapacity && maxCapacity)
817 CFNumberGetValue(curCapacity, kCFNumberIntType, &cur);
818 CFNumberGetValue(maxCapacity, kCFNumberIntType, &max);
822 percent = (int)(((
long long)cur * 100) / max);
826 CFBooleanRef isCharging = CFDictionaryGetValue(desc, CFSTR(kIOPSIsChargingKey));
827 if (isCharging && CFBooleanGetValue(isCharging))
830 CFNumberRef timeToEmpty = CFDictionaryGetValue(desc, CFSTR(kIOPSTimeToEmptyKey));
834 CFNumberGetValue(timeToEmpty, kCFNumberIntType, &minutes);
836 timeToEmptySeconds = minutes * 60;
845 status->ACLineStatus = AC_LINE_ONLINE;
846 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
847 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
851 status->ACLineStatus = onAC ? AC_LINE_ONLINE : AC_LINE_OFFLINE;
855 flag |= BATTERY_FLAG_CHARGING;
861 status->BatteryLifePercent = (BYTE)percent;
864 flag |= BATTERY_FLAG_CRITICAL;
865 else if (percent <= 33)
866 flag |= BATTERY_FLAG_LOW;
867 else if (percent > 66)
868 flag |= BATTERY_FLAG_HIGH;
871 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
873 status->BatteryFlag = flag ? flag : BATTERY_FLAG_UNKNOWN;
875 if (timeToEmptySeconds > 0)
876 status->BatteryLifeTime = (DWORD)timeToEmptySeconds;
881#elif defined(__FreeBSD__)
883static BOOL sysinfo_sysctl_int(
const char* name,
int* value)
885 size_t len =
sizeof(*value);
886 return sysctlbyname(name, value, &len,
nullptr, 0) == 0;
892 if (!sysinfo_sysctl_int(
"hw.acpi.battery.units", &units) || (units <= 0))
894 status->ACLineStatus = AC_LINE_ONLINE;
895 status->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
896 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
901 (void)sysinfo_sysctl_int(
"hw.acpi.acline", &acline);
902 status->ACLineStatus =
903 (acline == 1) ? AC_LINE_ONLINE : ((acline == 0) ? AC_LINE_OFFLINE : AC_LINE_UNKNOWN);
906 (void)sysinfo_sysctl_int(
"hw.acpi.battery.life", &life);
909 (void)sysinfo_sysctl_int(
"hw.acpi.battery.time", &remaining);
914 (void)sysinfo_sysctl_int(
"hw.acpi.battery.state", &state);
918 flag |= BATTERY_FLAG_CHARGING;
920 flag |= BATTERY_FLAG_CRITICAL;
922 if ((life >= 0) && (life <= 100))
924 status->BatteryLifePercent = (BYTE)life;
925 if (!(flag & BATTERY_FLAG_CRITICAL))
928 flag |= BATTERY_FLAG_CRITICAL;
930 flag |= BATTERY_FLAG_LOW;
932 flag |= BATTERY_FLAG_HIGH;
936 status->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
938 status->BatteryFlag = flag ? flag : BATTERY_FLAG_UNKNOWN;
941 status->BatteryLifeTime = (DWORD)remaining * 60;
950 if (!lpSystemPowerStatus)
952 SetLastError(ERROR_BAD_ARGUMENTS);
958 lpSystemPowerStatus->ACLineStatus = AC_LINE_UNKNOWN;
959 lpSystemPowerStatus->BatteryFlag = BATTERY_FLAG_UNKNOWN;
960 lpSystemPowerStatus->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN;
961 lpSystemPowerStatus->SystemStatusFlag = 0;
962 lpSystemPowerStatus->BatteryLifeTime = BATTERY_LIFE_UNKNOWN;
963 lpSystemPowerStatus->BatteryFullLifeTime = BATTERY_LIFE_UNKNOWN;
965#if defined(__linux__) || defined(__MACOSX__) || defined(__FreeBSD__)
966 return sysinfo_get_power_status_platform(lpSystemPowerStatus);
968 WLog_WARN(TAG,
"GetSystemPowerStatus is not implemented on this platform, reporting "
969 "\"no battery, unknown state\"");
978DWORD GetTickCount(
void)
980 return (DWORD)GetTickCount64();
985#if (!defined(_WIN32)) || (defined(_WIN32) && (_WIN32_WINNT < 0x0600))
987ULONGLONG winpr_GetTickCount64(
void)
989 const UINT64 ns = winpr_GetTickCount64NS();
990 return WINPR_TIME_NS_TO_MS(ns);
995UINT64 winpr_GetTickCount64NS(
void)
998#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
999 struct timespec ts = WINPR_C_ARRAY_INIT;
1001 if (clock_gettime(CLOCK_ID, &ts) == 0)
1002 ticks = (WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_sec) * 1000000000ull) +
1003 WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_nsec);
1004#elif defined(__MACH__) && defined(__APPLE__)
1005 ticks = mac_get_time_ns();
1006#elif defined(_WIN32)
1009 if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&li))
1010 ticks = li.QuadPart * 1000000000ull / freq.QuadPart;
1012 struct timeval tv = WINPR_C_ARRAY_INIT;
1014 if (gettimeofday(&tv,
nullptr) == 0)
1015 ticks = (tv.tv_sec * 1000000000ull) + (tv.tv_usec * 1000ull);
1024 static UINT64 first = 0;
1025 static UINT64 uptime = 0;
1028 struct sysinfo info = WINPR_C_ARRAY_INIT;
1029 if (sysinfo(&info) == 0)
1032 uptime = 1000000000ull * info.uptime;
1036 ticks = ticks - first + uptime;
1041UINT64 winpr_GetUnixTimeNS(
void)
1049 } t = WINPR_C_ARRAY_INIT;
1050 GetSystemTimeAsFileTime(&t.ft);
1051 return (t.u64 - FILETIME_TO_UNIX_OFFSET_S * 10000000ull) * 100ull;
1052#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
1053 struct timespec ts = WINPR_C_ARRAY_INIT;
1054 if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
1056 return WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_sec) * 1000000000ull +
1057 WINPR_ASSERTING_INT_CAST(uint64_t, ts.tv_nsec);
1059 struct timeval tv = WINPR_C_ARRAY_INIT;
1060 if (gettimeofday(&tv,
nullptr) != 0)
1062 return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ull;
1069#if defined(__GNUC__)
1070#define xgetbv(_func_, _lo_, _hi_) \
1071 __asm__ __volatile__("xgetbv" : "=a"(_lo_), "=d"(_hi_) : "c"(_func_))
1072#elif defined(_MSC_VER)
1073#define xgetbv(_func_, _lo_, _hi_) \
1075 unsigned __int64 val = _xgetbv(_func_); \
1076 _lo_ = val & 0xFFFFFFFF; \
1077 _hi_ = (val >> 32); \
1081#define B_BIT_AVX2 (1 << 5)
1082#define B_BIT_AVX512F (1 << 16)
1083#define D_BIT_MMX (1 << 23)
1084#define D_BIT_SSE (1 << 25)
1085#define D_BIT_SSE2 (1 << 26)
1086#define D_BIT_3DN (1 << 30)
1088#define C_BIT_PCLMULQDQ (1 << 1)
1089#define C81_BIT_LZCNT (1 << 5)
1091#define C_BIT_3DNP (1 << 8)
1092#define C_BIT_SSSE3 (1 << 9)
1093#define C_BIT_SSE41 (1 << 19)
1094#define C_BIT_SSE42 (1 << 20)
1095#define C_BIT_FMA (1 << 12)
1096#define C_BIT_AES (1 << 25)
1097#define C_BIT_XGETBV (1 << 27)
1098#define C_BIT_AVX (1 << 28)
1099#define E_BIT_XMM (1 << 1)
1100#define E_BIT_YMM (1 << 2)
1101#define E_BITS_AVX (E_BIT_XMM | E_BIT_YMM)
1103static void cpuid(
unsigned info,
unsigned* eax,
unsigned* ebx,
unsigned* ecx,
unsigned* edx)
1106 *eax = *ebx = *ecx = *edx = 0;
1114 "xchg %%ebx, %%esi;"
1118 "xchg %%rbx, %%rsi;"
1120 :
"=a"(*eax),
"=S"(*ebx),
"=c"(*ecx),
"=d"(*edx)
1121 :
"a"(info),
"c"(0));
1122#elif defined(_MSC_VER)
1131#elif defined(_M_ARM) || defined(_M_ARM64)
1132#if defined(__linux__)
1134#define HWCAP_SWP (1 << 0)
1135#define HWCAP_HALF (1 << 1)
1136#define HWCAP_THUMB (1 << 2)
1137#define HWCAP_26BIT (1 << 3)
1138#define HWCAP_FAST_MULT (1 << 4)
1139#define HWCAP_FPA (1 << 5)
1140#define HWCAP_VFP (1 << 6)
1141#define HWCAP_EDSP (1 << 7)
1142#define HWCAP_JAVA (1 << 8)
1143#define HWCAP_IWMMXT (1 << 9)
1144#define HWCAP_CRUNCH (1 << 10)
1145#define HWCAP_THUMBEE (1 << 11)
1146#define HWCAP_NEON (1 << 12)
1147#define HWCAP_VFPv3 (1 << 13)
1148#define HWCAP_VFPv3D16 (1 << 14)
1149#define HWCAP_TLS (1 << 15)
1150#define HWCAP_VFPv4 (1 << 16)
1151#define HWCAP_IDIVA (1 << 17)
1152#define HWCAP_IDIVT (1 << 18)
1153#define HWCAP_VFPD32 (1 << 19)
1154#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
1159static unsigned GetARMCPUCaps(
void)
1162 int fd = open(
"/proc/self/auxv", O_RDONLY);
1176 num = read(fd, (
char*)&auxvec,
sizeof(auxvec));
1178 if (num < 1 || (auxvec.a_type == 0 && auxvec.a_val == 0))
1181 if (auxvec.a_type == AT_HWCAP)
1183 caps = auxvec.a_val;
1196#if defined(_M_ARM) || defined(_M_ARM64)
1198#include <sys/auxv.h>
1202BOOL IsProcessorFeaturePresent(DWORD ProcessorFeature)
1206 const uint64_t features = android_getCpuFeatures();
1207 const AndroidCpuFamily family = android_getCpuFamily();
1208 const BOOL isArm = (family == ANDROID_CPU_FAMILY_ARM) || (family == ANDROID_CPU_FAMILY_ARM64);
1209 const BOOL isX86 = (family == ANDROID_CPU_FAMILY_X86) || (family == ANDROID_CPU_FAMILY_X86_64);
1213 switch (ProcessorFeature)
1215 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1216 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
1217 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
1218 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1219 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1221 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
1222 return features & ANDROID_CPU_X86_FEATURE_SSSE3;
1223 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
1224 return features & ANDROID_CPU_X86_FEATURE_SSE4_1;
1225 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
1226 return features & ANDROID_CPU_X86_FEATURE_SSE4_2;
1227 case PF_AVX_INSTRUCTIONS_AVAILABLE:
1228 return features & ANDROID_CPU_X86_FEATURE_AVX;
1229 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
1230 return features & ANDROID_CPU_X86_FEATURE_AVX2;
1231 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
1233 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1240 switch (ProcessorFeature)
1242 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
1244 return features & ANDROID_CPU_ARM_FEATURE_NEON;
1247 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1252 WLog_WARN(TAG,
"Unsupported Android CPU family 0x%08" PRIx32, family);
1255#elif defined(_M_ARM) || defined(_M_ARM64)
1257 const unsigned long caps = getauxval(AT_HWCAP);
1259 switch (ProcessorFeature)
1261 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
1264 if (caps & HWCAP_NEON)
1270 if (caps & HWCAP_THUMB)
1273 case PF_ARM_VFP_32_REGISTERS_AVAILABLE:
1274 if (caps & HWCAP_VFPD32)
1277 case PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE:
1278 if ((caps & HWCAP_IDIVA) || (caps & HWCAP_IDIVT))
1282 if (caps & HWCAP_VFPv3)
1287 case PF_ARM_JAZELLE:
1288 if (caps & HWCAP_JAVA)
1294 if (caps & HWCAP_EDSP)
1300 if (caps & HWCAP_EDSP)
1306 if ((caps & HWCAP_IDIVT) || (caps & HWCAP_VFPv4))
1312 if (caps & HWCAP_THUMBEE)
1317 case PF_ARM_INTEL_WMMX:
1318 if (caps & HWCAP_IWMMXT)
1322 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1323 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
1324 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
1325 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1326 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1327 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
1328 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
1329 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
1330 case PF_AVX_INSTRUCTIONS_AVAILABLE:
1331 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
1332 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
1335 case PF_ARM_V8_INSTRUCTIONS_AVAILABLE:
1336 case PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE:
1337 case PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE:
1338 case PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE:
1339 case PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE:
1340 case PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE:
1341 case PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE:
1343 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1349 switch (ProcessorFeature)
1351 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1352 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
1353 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
1354 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1355 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1356 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
1357 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
1358 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
1359 case PF_AVX_INSTRUCTIONS_AVAILABLE:
1360 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
1361 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
1364 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
1370 case PF_ARM_V8_INSTRUCTIONS_AVAILABLE:
1371 case PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE:
1372 case PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE:
1373 case PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE:
1374 case PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE:
1375 case PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE:
1376 case PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE:
1378 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1385#if defined(_M_IX86_AMD64)
1391 cpuid(1, &a, &b, &c, &d);
1393 switch (ProcessorFeature)
1395 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1401 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
1407 case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
1413 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1419 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1420 ret = __builtin_cpu_supports(
"sse3");
1423 case PF_SSSE3_INSTRUCTIONS_AVAILABLE:
1424 ret = __builtin_cpu_supports(
"ssse3");
1426 case PF_SSE4_1_INSTRUCTIONS_AVAILABLE:
1427 ret = __builtin_cpu_supports(
"sse4.1");
1429 case PF_SSE4_2_INSTRUCTIONS_AVAILABLE:
1430 ret = __builtin_cpu_supports(
"sse4.2");
1432 case PF_AVX_INSTRUCTIONS_AVAILABLE:
1433 ret = __builtin_cpu_supports(
"avx");
1435 case PF_AVX2_INSTRUCTIONS_AVAILABLE:
1436 ret = __builtin_cpu_supports(
"avx2");
1438 case PF_AVX512F_INSTRUCTIONS_AVAILABLE:
1439 ret = __builtin_cpu_supports(
"avx512f");
1441 case PF_ARM_NEON_INSTRUCTIONS_AVAILABLE:
1442#if defined(__ARM_NEON__)
1447 WLog_WARN(TAG,
"feature 0x%08" PRIx32
" check not implemented", ProcessorFeature);
1456 switch (ProcessorFeature)
1458 case PF_MMX_INSTRUCTIONS_AVAILABLE:
1464 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
1470 case PF_SSE3_INSTRUCTIONS_AVAILABLE:
1486DWORD GetTickCountPrecise(
void)
1491 QueryPerformanceFrequency(&freq);
1492 QueryPerformanceCounter(¤t);
1493 return (DWORD)(current.QuadPart * 1000LL / freq.QuadPart);
1495 return GetTickCount();
1499BOOL IsProcessorFeaturePresentEx(DWORD ProcessorFeature)
1502#if defined(_M_ARM) || defined(_M_ARM64)
1505 caps = GetARMCPUCaps();
1507 switch (ProcessorFeature)
1509 case PF_EX_ARM_VFP1:
1510 if (caps & HWCAP_VFP)
1515 case PF_EX_ARM_VFP3D16:
1516 if (caps & HWCAP_VFPv3D16)
1521 case PF_EX_ARM_VFP4:
1522 if (caps & HWCAP_VFPv4)
1527 case PF_EX_ARM_IDIVA:
1528 if (caps & HWCAP_IDIVA)
1533 case PF_EX_ARM_IDIVT:
1534 if (caps & HWCAP_IDIVT)
1541#elif defined(_M_IX86_AMD64)
1546 cpuid(1, &a, &b, &c, &d);
1548 switch (ProcessorFeature)
1556 cpuid(0x80000001, &a81, &b81, &c81, &d81);
1558 if (c81 & C81_BIT_LZCNT)
1563 case PF_EX_3DNOW_PREFETCH:
1570 if (c & C_BIT_SSSE3)
1576 if (c & C_BIT_SSE41)
1582 if (c & C_BIT_SSE42)
1586#if defined(__GNUC__) || defined(_MSC_VER)
1593 case PF_EX_AVX_PCLMULQDQ:
1596 if (!(c & C_BIT_AVX))
1600 if (!(c & C_BIT_XGETBV))
1608 if ((e & E_BITS_AVX) == E_BITS_AVX)
1610 switch (ProcessorFeature)
1618 cpuid(7, &a, &b, &c, &d);
1619 switch (ProcessorFeature)
1627 if (b & B_BIT_AVX512F)
1648 case PF_EX_AVX_PCLMULQDQ:
1649 if (c & C_BIT_PCLMULQDQ)
1664#elif defined(_M_E2K)
1666 switch (ProcessorFeature)
mirrors the real Win32 SYSTEM_POWER_STATUS struct.