Source
/* Check if GetActiveProcessorGroupCount() is available. See comments in get_cpu_num_win32() for details. */
/*
** Copyright (C) 2001-2025 Zabbix SIA
**
** This program is free software: you can redistribute it and/or modify it under the terms of
** the GNU Affero General Public License as published by the Free Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
** See the GNU Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License along with this program.
** If not, see <https://www.gnu.org/licenses/>.
**/
/* shortcut to avoid extra verbosity */
typedef PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX PSYS_LPI_EX;
/* pointer to GetLogicalProcessorInformationEx(), it's not guaranteed to be available */
typedef BOOL (WINAPI *GETLPIEX)(LOGICAL_PROCESSOR_RELATIONSHIP, PSYS_LPI_EX, PDWORD);
static GETLPIEX get_lpiex;
/******************************************************************************
* *
* Purpose: finds number of active logical CPUs *
* *
* Return value: number of CPUs or 0 on failure *
* *
******************************************************************************/
int get_cpu_num_win32(void)
{
/* pointer to GetActiveProcessorCount() */
typedef DWORD (WINAPI *GETACTIVEPC)(WORD);
ZBX_THREAD_LOCAL static GETACTIVEPC get_act;
SYSTEM_INFO sysInfo;
PSYS_LPI_EX buffer = NULL;
int cpu_count = 0;
/* The rationale for checking dynamically if specific functions are implemented */
/* in kernel32.lib is because these may not be available in certain Windows versions. */
/* E.g. GetActiveProcessorCount() is available from Windows 7 onward (and not in Windows Vista or XP) */
/* We can't resolve this using conditional compilation unless we release multiple agents */
/* targeting different sets of Windows APIs. */
/* First, let's try GetLogicalProcessorInformationEx() method. It's the most reliable way */
/* because it counts logical CPUs (aka threads) regardless of whether the application is */
/* 32 or 64-bit. GetActiveProcessorCount() may return incorrect value (e.g. 64 CPUs for systems */
/* with 128 CPUs) if executed under WoW64. */
if (NULL == get_lpiex)
{
get_lpiex = (GETLPIEX)GetProcAddress(GetModuleHandle(L"kernel32.dll"),
"GetLogicalProcessorInformationEx");
}
if (NULL != get_lpiex)