Skip to content

Commit 98738b6

Browse files
committed
CPUUsage (Windows): detect perflib support dynamically based on OS version
1 parent 2e5769d commit 98738b6

File tree

3 files changed

+69
-46
lines changed

3 files changed

+69
-46
lines changed

src/common/init.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,6 @@ void ffListFeatures(void)
265265
#if FF_HAVE_EMBEDDED_PCIIDS
266266
"Embedded pciids\n"
267267
#endif
268-
#if FF_ENABLE_CPUUSAGE_PERFLIB
269-
"CPUUsage perflib\n"
270-
#endif
271268
""
272269
, stdout);
273270
}

src/detection/cpuusage/cpuusage_windows.c

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33

44
#include "util/mallocHelper.h"
55

6-
#if !FF_ENABLE_CPUUSAGE_PERFLIB
76
#include <ntstatus.h>
87
#include <winternl.h>
8+
#include <windows.h>
9+
#include <wchar.h>
10+
#include "util/windows/perflib_.h"
911

10-
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
12+
static const char* getInfoByNqsi(FFlist* cpuTimes)
1113
{
1214
ULONG size = 0;
1315
if(NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH)
@@ -36,49 +38,53 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
3638

3739
return NULL;
3840
}
39-
#else
40-
#include <windows.h>
41-
#include "util/windows/perflib_.h"
42-
#include <wchar.h>
4341

44-
static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
42+
static const char* getInfoByPerflib(FFlist* cpuTimes)
4543
{
46-
if (*phQuery != NULL)
44+
static HANDLE hQuery = NULL;
45+
46+
if (hQuery == NULL)
4747
{
48-
PerfCloseQueryHandle(*phQuery);
49-
*phQuery = NULL;
48+
struct FFPerfQuerySpec
49+
{
50+
PERF_COUNTER_IDENTIFIER Identifier;
51+
WCHAR Name[16];
52+
} querySpec = {
53+
.Identifier = {
54+
// Processor Information GUID
55+
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{383487a6-3676-4870-a4e7-d45b30c35629}\{b4fc721a-0378-476f-89ba-a5a79f810b36}
56+
.CounterSetGuid = { 0xb4fc721a, 0x0378, 0x476f, {0x89, 0xba, 0xa5, 0xa7, 0x9f, 0x81, 0x0b, 0x36} },
57+
.Size = sizeof(querySpec),
58+
.CounterId = PERF_WILDCARD_COUNTER, // https://learn.microsoft.com/en-us/windows/win32/perfctrs/using-the-perflib-functions-to-consume-counter-data
59+
.InstanceId = PERF_WILDCARD_COUNTER,
60+
},
61+
.Name = PERF_WILDCARD_INSTANCE,
62+
};
63+
64+
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS)
65+
{
66+
PerfCloseQueryHandle(hQuery);
67+
hQuery = INVALID_HANDLE_VALUE;
68+
return "PerfOpenQueryHandle() failed";
69+
}
70+
71+
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS)
72+
{
73+
PerfCloseQueryHandle(hQuery);
74+
hQuery = INVALID_HANDLE_VALUE;
75+
return "PerfAddCounters() failed";
76+
}
77+
78+
if (querySpec.Identifier.Status != ERROR_SUCCESS)
79+
{
80+
PerfCloseQueryHandle(hQuery);
81+
hQuery = INVALID_HANDLE_VALUE;
82+
return "PerfAddCounters() reports invalid identifier";
83+
}
5084
}
51-
}
5285

53-
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
54-
{
55-
struct FFPerfQuerySpec
56-
{
57-
PERF_COUNTER_IDENTIFIER Identifier;
58-
WCHAR Name[16];
59-
} querySpec = {
60-
.Identifier = {
61-
// Processor Information GUID
62-
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{383487a6-3676-4870-a4e7-d45b30c35629}\{b4fc721a-0378-476f-89ba-a5a79f810b36}
63-
.CounterSetGuid = { 0xb4fc721a, 0x0378, 0x476f, {0x89, 0xba, 0xa5, 0xa7, 0x9f, 0x81, 0x0b, 0x36} },
64-
.Size = sizeof(querySpec),
65-
.CounterId = PERF_WILDCARD_COUNTER, // https://learn.microsoft.com/en-us/windows/win32/perfctrs/using-the-perflib-functions-to-consume-counter-data
66-
.InstanceId = PERF_WILDCARD_COUNTER,
67-
},
68-
.Name = PERF_WILDCARD_INSTANCE,
69-
};
70-
71-
__attribute__((__cleanup__(ffPerfCloseQueryHandle)))
72-
HANDLE hQuery = NULL;
73-
74-
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS)
75-
return "PerfOpenQueryHandle() failed";
76-
77-
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS)
78-
return "PerfAddCounters() failed";
79-
80-
if (querySpec.Identifier.Status != ERROR_SUCCESS)
81-
return "PerfAddCounters() reports invalid identifier";
86+
if (hQuery == INVALID_HANDLE_VALUE)
87+
return "Init hQuery failed";
8288

8389
DWORD dataSize = 0;
8490
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
@@ -146,4 +152,23 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
146152

147153
return NULL;
148154
}
149-
#endif
155+
156+
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
157+
{
158+
#if __aarch64__
159+
static uint8_t winver = 10; // Assume Windows 10 or later for WoA
160+
#else
161+
static uint8_t winver = 0;
162+
if (winver == 0)
163+
winver = (uint8_t) ffStrbufToUInt(&instance.state.platform.sysinfo.release, 1);
164+
#endif
165+
166+
if (winver >= 10)
167+
{
168+
if (getInfoByPerflib(cpuTimes) == NULL) return NULL;
169+
ffListClear(cpuTimes);
170+
winver = 1; // Fall back to NQSI
171+
}
172+
173+
return getInfoByNqsi(cpuTimes);
174+
}

src/modules/cpuusage/cpuusage.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options)
2828
{
2929
sumValue += *percent;
3030

31-
#if FF_ENABLE_CPUUSAGE_PERFLIB
31+
#if WIN32
3232
// Windows may return values greater than 100%, cap them to 100%
3333
if (*percent > 100) *percent = 100;
3434
#endif
35+
3536
if (*percent > maxValue)
3637
{
3738
maxValue = *percent;
@@ -47,7 +48,7 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options)
4748
++index;
4849
}
4950
double avgValue = sumValue / (double) valueCount;
50-
#if FF_ENABLE_CPUUSAGE_PERFLIB
51+
#if WIN32
5152
// See above comment
5253
if (avgValue > 100) avgValue = 100;
5354
#endif

0 commit comments

Comments
 (0)