From a57e334d7331b19fa27b84b7e823af0995b4d2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 7 Oct 2022 19:02:27 +0800 Subject: [PATCH] CpuUsage: support no wait detection on Windows --- CMakeLists.txt | 2 + src/common/time.h | 35 +++++++++++ src/detection/cpuUsage/cpuUsage.c | 58 +++++++++++++++++++ src/detection/cpuUsage/cpuUsage.h | 7 ++- .../cpuUsage/cpuUsage_nowait_windows.cpp | 26 +++++++++ src/modules/cpuUsage.c | 58 +------------------ 6 files changed, 127 insertions(+), 59 deletions(-) create mode 100644 src/common/time.h create mode 100644 src/detection/cpuUsage/cpuUsage.c create mode 100644 src/detection/cpuUsage/cpuUsage_nowait_windows.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bb027e73d..d91d298e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,6 +211,7 @@ set(LIBFASTFETCH_SRC src/detection/host/host.c src/detection/os/os.c src/detection/cpu/cpu.c + src/detection/cpuUsage/cpuUsage.c src/detection/gpu/gpu.c src/detection/memory/memory.c src/detection/font/font.c @@ -325,6 +326,7 @@ if(WIN_MSYS) src/detection/processes/processes_windows.cpp src/detection/disk/disk_windows.cpp src/detection/cpuUsage/cpuUsage_windows.c + src/detection/cpuUsage/cpuUsage_nowait_windows.cpp src/util/windows/wmi.cpp # Shared diff --git a/src/common/time.h b/src/common/time.h new file mode 100644 index 000000000..8b4dcd76e --- /dev/null +++ b/src/common/time.h @@ -0,0 +1,35 @@ +#pragma once + +#ifndef FF_INCLUDED_common_time +#define FF_INCLUDED_common_time + +#include +#if defined(_WIN32) || defined(__CYGWIN__) + #include + #include +#else + #include + #include +#endif + +static inline uint64_t ffTimeGetTick() //In msec +{ + #if defined(_WIN32) || defined(__CYGWIN__) + return GetTickCount64(); + #else + struct timeval timeNow; + gettimeofday(&timeNow, NULL); + return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000)); + #endif +} + +static inline void ffTimeSleep(uint32_t msec) +{ + #if defined(_WIN32) || defined(__CYGWIN__) + SleepEx(msec, TRUE); + #else + nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL); + #endif +} + +#endif diff --git a/src/detection/cpuUsage/cpuUsage.c b/src/detection/cpuUsage/cpuUsage.c new file mode 100644 index 000000000..61aaaf817 --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage.c @@ -0,0 +1,58 @@ +#include "fastfetch.h" +#include "cpuUsage.h" + +#ifndef FF_DETECTION_CPUUSAGE_NOWAIT + +#include "common/time.h" + +#include + +// We need to use uint64_t because sizeof(long) == 4 on Windows +const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll); + +static uint64_t inUseAll1, totalAll1, startTime; + +void ffPrepareCPUUsage() +{ + startTime = ffTimeGetTick(); + ffGetCpuUsageInfo(&inUseAll1, &totalAll1); +} + +const char* ffGetCpuUsageResult(double* result) +{ + const char* error = NULL; + if(startTime == 0) + { + error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1); + if(error) + return error; + ffTimeSleep(1000); + } + else + { + uint64_t duration = ffTimeGetTick() - startTime; + if(duration < 1000) + ffTimeSleep(1000 - (uint32_t) duration); + } + + uint64_t inUseAll2, totalAll2; + error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2); + if(error) + return error; + + *result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; + + return NULL; +} + +#else //FF_DETECTION_CPUUSAGE_NOWAIT + +const char* ffGetCpuUsageResultNoWait(double* result); + +void ffPrepareCPUUsage() {} + +const char* ffGetCpuUsageResult(double* result) { + return ffGetCpuUsageResultNoWait(result); +} + +#endif //FF_DETECTION_CPUUSAGE_NOWAIT diff --git a/src/detection/cpuUsage/cpuUsage.h b/src/detection/cpuUsage/cpuUsage.h index 131fb77f2..f1a963992 100644 --- a/src/detection/cpuUsage/cpuUsage.h +++ b/src/detection/cpuUsage/cpuUsage.h @@ -3,9 +3,10 @@ #ifndef FF_INCLUDED_detection_cpu_cpuUsage #define FF_INCLUDED_detection_cpu_cpuUsage -#include +#if defined(_WIN32) || defined(__CYGWIN__) + #define FF_DETECTION_CPUUSAGE_NOWAIT 1 +#endif -// We need to use uint64_t because sizeof(long) == 4 on Windows -const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll); +const char* ffGetCpuUsageResult(double* result); #endif diff --git a/src/detection/cpuUsage/cpuUsage_nowait_windows.cpp b/src/detection/cpuUsage/cpuUsage_nowait_windows.cpp new file mode 100644 index 000000000..19af6ffbe --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage_nowait_windows.cpp @@ -0,0 +1,26 @@ +extern "C" { +#include "cpuUsage.h" +} +#include "util/windows/wmi.hpp" + +extern "C" const char* ffGetCpuUsageResultNoWait(double* result) +{ + IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT LoadPercentage FROM Win32_Processor", nullptr); + if(!pEnumerator) + return "Query WMI service failed"; + + IWbemClassObject *pclsObj = NULL; + ULONG uReturn = 0; + + if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + { + pEnumerator->Release(); + return "No WMI result returned"; + } + + ffGetWmiObjReal(pclsObj, L"LoadPercentage", result); + + pclsObj->Release(); + pEnumerator->Release(); + return NULL; +} diff --git a/src/modules/cpuUsage.c b/src/modules/cpuUsage.c index 501072f7b..db8ea2e5d 100644 --- a/src/modules/cpuUsage.c +++ b/src/modules/cpuUsage.c @@ -2,74 +2,20 @@ #include "common/printing.h" #include "detection/cpuUsage/cpuUsage.h" -#if defined(_WIN32) || defined(__CYGWIN__) - #include - #include -#else - #include - #include -#endif - #define FF_CPU_USAGE_MODULE_NAME "CPU Usage" #define FF_CPU_USAGE_NUM_FORMAT_ARGS 1 -static inline uint64_t getTimeInMs() -{ - #if defined(_WIN32) || defined(__CYGWIN__) - return GetTickCount64(); - #else - struct timeval timeNow; - gettimeofday(&timeNow, NULL); - return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000)); - #endif -} - -static inline void sleepInMs(uint32_t msec) -{ - #if defined(_WIN32) || defined(__CYGWIN__) - SleepEx(msec, TRUE); - #else - nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL); - #endif -} - -static uint64_t inUseAll1, totalAll1, startTime; - -void ffPrepareCPUUsage() -{ - startTime = getTimeInMs(); - ffGetCpuUsageInfo(&inUseAll1, &totalAll1); -} - void ffPrintCPUUsage(FFinstance* instance) { - const char* error = NULL; - if(startTime == 0) - { - error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1); - if(error) - goto error; - sleepInMs(1000); - } - else - { - uint64_t duration = getTimeInMs() - startTime; - if(duration < 1000) - sleepInMs(1000 - (uint32_t) duration); - } - - uint64_t inUseAll2, totalAll2; - error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2); + double cpuPercent = 0.0/0.0; + const char* error = ffGetCpuUsageResult(&cpuPercent); if(error) { - error: ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpu, "%s", error); return; } - double cpuPercent = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; - if(instance->config.cpuUsage.outputFormat.length == 0) { ffPrintLogoAndKey(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsage.key);