Source
/* Check if GetActiveProcessorGroupCount() is available. See comments in get_cpu_num_win32() for details. */
/*
** Zabbix
** Copyright (C) 2001-2023 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
/* 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: find 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"),