summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY.rst11
-rw-r--r--MANIFEST.in1
-rw-r--r--appveyor.yml18
-rw-r--r--docs/index.rst17
-rw-r--r--psutil/_psutil_common.c2
-rw-r--r--psutil/_psutil_windows.c197
-rw-r--r--psutil/_pswindows.py2
-rw-r--r--psutil/arch/windows/glpi.h41
-rwxr-xr-xpsutil/tests/test_system.py7
-rwxr-xr-xpsutil/tests/test_windows.py48
10 files changed, 195 insertions, 149 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index 65cad58e..b5fad59c 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -15,6 +15,12 @@ XXXX-XX-XX
- 694_: [SunOS] cmdline() could be truncated at the 15th character when
reading it from /proc. An extra effort is made by reading it from process
address space first. (patch by Georg Sauthoff)
+- 771_: [Windows] cpu_count() (both logical and physical) return a wrong
+ (smaller) number on systems using process groups (> 64 cores).
+- 771_: [Windows] cpu_times(percpu=True) return fewer CPUs on systems using
+ process groups (> 64 cores).
+- 771_: [Windows] cpu_stats() and cpu_freq() may return incorrect results on
+ systems using process groups (> 64 cores).
- 1193_: [SunOS] Return uid/gid from /proc/pid/psinfo if there aren't
enough permissions for /proc/pid/cred. (patch by Georg Sauthoff)
- 1194_: [SunOS] Return nice value from psinfo as getpriority() doesn't
@@ -38,6 +44,11 @@ XXXX-XX-XX
- 1255_: [FreeBSD] swap_memory() stats were erroneously represented in KB.
(patch by Denis Krienbühl)
+**Backward compatibility**
+
+- 771_: [Windows] cpu_count(logical=False) on Windows XP and Vista is no
+ longer supported and returns None.
+
5.4.3
=====
diff --git a/MANIFEST.in b/MANIFEST.in
index 87d9bebb..85d1f21e 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -67,7 +67,6 @@ include psutil/arch/solaris/environ.c
include psutil/arch/solaris/environ.h
include psutil/arch/solaris/v10/ifaddrs.c
include psutil/arch/solaris/v10/ifaddrs.h
-include psutil/arch/windows/glpi.h
include psutil/arch/windows/inet_ntop.c
include psutil/arch/windows/inet_ntop.h
include psutil/arch/windows/ntextapi.h
diff --git a/appveyor.yml b/appveyor.yml
index f39053ad..436faadb 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -45,20 +45,13 @@ environment:
- PYTHON: "C:\\Python35-x64"
PYTHON_VERSION: "3.5.x"
PYTHON_ARCH: "64"
- ARCH: x86_64
- VS_VER: "2015"
- INSTANCENAME: "SQL2012SP1"
- PYTHON: "C:\\Python36-x64"
PYTHON_VERSION: "3.6.x"
PYTHON_ARCH: "64"
- ARCH: x86_64
- VS_VER: "2015"
- INSTANCENAME: "SQL2012SP1"
# Also build on a Python version not pre-installed by Appveyor.
# See: https://github.com/ogrisel/python-appveyor-demo/issues/10
-
# - PYTHON: "C:\\Python266"
# PYTHON_VERSION: "2.6.6"
# PYTHON_ARCH: "32"
@@ -71,20 +64,17 @@ install:
# - ps: (new-object net.webclient).DownloadFile('https://raw.github.com/pypa/pip/master/contrib/get-pip.py', 'C:/get-pip.py')
- "%WITH_COMPILER% %PYTHON%/python.exe -m pip --version"
- "%WITH_COMPILER% %PYTHON%/python.exe -m pip install --upgrade --user setuptools pip"
- - "%WITH_COMPILER% %PYTHON%/python.exe -m pip freeze"
- - "%WITH_COMPILER% %PYTHON%/python.exe setup.py build"
- - "%WITH_COMPILER% %PYTHON%/python.exe setup.py build build_ext -i"
- - "%WITH_COMPILER% %PYTHON%/python.exe setup.py develop"
- "%WITH_COMPILER% %PYTHON%/python.exe scripts/internal/winmake.py setup-dev-env"
+ - "%WITH_COMPILER% %PYTHON%/python.exe -m pip freeze"
+ - "%WITH_COMPILER% %PYTHON%/python.exe scripts/internal/winmake.py install"
build: off
test_script:
- - "%WITH_COMPILER% %PYTHON%/python -V"
- - "set PYTHONWARNINGS=all && set PSUTIL_TESTING=1 && set PSUTIL_DEBUG=1 && %WITH_COMPILER% %PYTHON%/python psutil/tests/__main__.py"
+ - "%WITH_COMPILER% %PYTHON%/python.exe scripts/internal/winmake.py test"
after_test:
- - "%WITH_COMPILER% %PYTHON%/python setup.py bdist_wheel"
+ - "%WITH_COMPILER% %PYTHON%/python.exe scripts/internal/winmake.py wheel"
artifacts:
- path: dist\*
diff --git a/docs/index.rst b/docs/index.rst
index 395fd688..548f361f 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -164,15 +164,11 @@ CPU
Return the number of logical CPUs in the system (same as
`os.cpu_count() <http://docs.python.org/3/library/os.html#os.cpu_count>`__
in Python 3.4) or ``None`` if undetermined.
- This number may not be equivalent to the number of CPUs the current process
- can actually use in case process CPU affinity has been changed or Linux
- cgroups are being used.
- The number of usable CPUs can be obtained with
- ``len(psutil.Process().cpu_affinity())``.
If *logical* is ``False`` return the number of physical cores only (hyper
- thread CPUs are excluded).
+ thread CPUs are excluded) or ``None`` if undetermined.
On OpenBSD and NetBSD ``psutil.cpu_count(logical=False)`` always return
- ``None``. Example on a system having 2 physical hyper-thread CPU cores:
+ ``None``.
+ Example on a system having 2 physical hyper-thread CPU cores:
>>> import psutil
>>> psutil.cpu_count()
@@ -180,7 +176,12 @@ CPU
>>> psutil.cpu_count(logical=False)
2
- Example returning the number of CPUs usable by the current process:
+ Note that this number is not equivalent to the number of CPUs the current
+ process can actually use.
+ That can vary in case process CPU affinity has been changed, Linux cgroups
+ are being used or on Windows systems using processor groups or having more
+ than 64 CPUs.
+ The number of usable CPUs can be obtained with:
>>> len(psutil.Process().cpu_affinity())
1
diff --git a/psutil/_psutil_common.c b/psutil/_psutil_common.c
index e08f011c..49b91c82 100644
--- a/psutil/_psutil_common.c
+++ b/psutil/_psutil_common.c
@@ -85,7 +85,7 @@ void
psutil_debug(const char* format, ...) {
va_list argptr;
va_start(argptr, format);
- fprintf(stderr, "psutil-dubug> ");
+ fprintf(stderr, "psutil-debug> ");
vfprintf(stderr, format, argptr);
fprintf(stderr, "\n");
va_end(argptr);
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index d39afb21..ae2e538a 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -38,10 +38,6 @@
#include "arch/windows/inet_ntop.h"
#include "arch/windows/services.h"
-#ifdef __MINGW32__
-#include "arch/windows/glpi.h"
-#endif
-
/*
* ============================================================================
@@ -63,8 +59,13 @@
Py_DECREF(_SOCK_STREAM);\
Py_DECREF(_SOCK_DGRAM);
-typedef BOOL (WINAPI *LPFN_GLPI)
- (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
+#if (_WIN32_WINNT >= 0x0601) // Windows 7
+typedef BOOL (WINAPI *PFN_GETLOGICALPROCESSORINFORMATIONEX)(
+ LOGICAL_PROCESSOR_RELATIONSHIP relationship,
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer,
+ PDWORD ReturnLength);
+static PFN_GETLOGICALPROCESSORINFORMATIONEX _GetLogicalProcessorInformationEx;
+#endif
// Fix for mingw32, see:
// https://github.com/giampaolo/psutil/issues/351#c2
@@ -196,6 +197,45 @@ psutil_get_nic_addresses() {
/*
+ * Return the number of logical, active CPUs. Return 0 if undetermined.
+ * See discussion at: https://bugs.python.org/issue33166#msg314631
+ */
+unsigned int
+psutil_get_num_cpus(int fail_on_err) {
+ unsigned int ncpus = 0;
+ SYSTEM_INFO sysinfo;
+ static DWORD(CALLBACK *_GetActiveProcessorCount)(WORD) = NULL;
+ HINSTANCE hKernel32;
+
+ // GetActiveProcessorCount is available only on 64 bit versions
+ // of Windows from Windows 7 onward.
+ // Windows Vista 64 bit and Windows XP doesn't have it.
+ hKernel32 = GetModuleHandleW(L"KERNEL32");
+ _GetActiveProcessorCount = (void*)GetProcAddress(
+ hKernel32, "GetActiveProcessorCount");
+
+ if (_GetActiveProcessorCount != NULL) {
+ ncpus = _GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
+ if ((ncpus == 0) && (fail_on_err == 1)) {
+ PyErr_SetFromWindowsErr(0);
+ }
+ }
+ else {
+ psutil_debug("GetActiveProcessorCount() not available; "
+ "using GetNativeSystemInfo()");
+ GetNativeSystemInfo(&sysinfo);
+ ncpus = (unsigned int)sysinfo.dwNumberOfProcessors;
+ if ((ncpus == 0) && (fail_on_err == 1)) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "GetNativeSystemInfo() failed to retrieve CPU count");
+ }
+ }
+ return ncpus;
+}
+
+
+/*
* ============================================================================
* Public Python API
* ============================================================================
@@ -553,55 +593,77 @@ psutil_proc_create_time(PyObject *self, PyObject *args) {
}
-
/*
- * Return the number of logical CPUs.
+ * Return the number of active, logical CPUs.
*/
static PyObject *
psutil_cpu_count_logical(PyObject *self, PyObject *args) {
- SYSTEM_INFO system_info;
- system_info.dwNumberOfProcessors = 0;
+ unsigned int ncpus;
- GetSystemInfo(&system_info);
- if (system_info.dwNumberOfProcessors == 0)
- Py_RETURN_NONE; // mimic os.cpu_count()
+ ncpus = psutil_get_num_cpus(0);
+ if (ncpus != 0)
+ return Py_BuildValue("I", ncpus);
else
- return Py_BuildValue("I", system_info.dwNumberOfProcessors);
+ Py_RETURN_NONE; // mimick os.cpu_count()
}
/*
- * Return the number of physical CPU cores.
+ * Return the number of physical CPU cores (hyper-thread CPUs count
+ * is excluded).
*/
+#if (_WIN32_WINNT < 0x0601) // < Windows 7 (namely Vista and XP)
+static PyObject *
+psutil_cpu_count_phys(PyObject *self, PyObject *args) {
+ // Note: we may have used GetLogicalProcessorInformation()
+ // but I don't want to prolong support for Windows XP and Vista.
+ // On such old systems psutil will compile but this API will
+ // just return None.
+ psutil_debug("Win < 7; cpu_count_phys() forced to None");
+ Py_RETURN_NONE;
+}
+#else // Windows >= 7
static PyObject *
psutil_cpu_count_phys(PyObject *self, PyObject *args) {
- LPFN_GLPI glpi;
DWORD rc;
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = NULL;
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ptr = NULL;
DWORD length = 0;
DWORD offset = 0;
- int ncpus = 0;
-
- glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")),
- "GetLogicalProcessorInformation");
- if (glpi == NULL)
+ DWORD ncpus = 0;
+
+ // GetLogicalProcessorInformationEx() is available from Windows 7
+ // onward. Differently from GetLogicalProcessorInformation()
+ // it supports process groups, meaning this is able to report more
+ // than 64 CPUs. See:
+ // https://bugs.python.org/issue33166
+ _GetLogicalProcessorInformationEx = \
+ (PFN_GETLOGICALPROCESSORINFORMATIONEX)GetProcAddress(
+ GetModuleHandle(TEXT("kernel32")),
+ "GetLogicalProcessorInformationEx");
+ if (_GetLogicalProcessorInformationEx == NULL) {
+ psutil_debug("failed loading GetLogicalProcessorInformationEx()");
goto return_none;
+ }
while (1) {
- rc = glpi(buffer, &length);
+ rc = _GetLogicalProcessorInformationEx(
+ RelationAll, buffer, &length);
if (rc == FALSE) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- if (buffer)
+ if (buffer) {
free(buffer);
- buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
- length);
+ }
+ buffer = \
+ (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(length);
if (NULL == buffer) {
PyErr_NoMemory();
return NULL;
}
}
else {
+ psutil_debug("GetLogicalProcessorInformationEx() returned ",
+ GetLastError());
goto return_none;
}
}
@@ -611,25 +673,30 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args) {
}
ptr = buffer;
- while (offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= length) {
- if (ptr->Relationship == RelationProcessorCore)
+ while (ptr->Size > 0 && offset + ptr->Size <= length) {
+ if (ptr->Relationship == RelationProcessorCore) {
ncpus += 1;
- offset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
- ptr++;
+ }
+ offset += ptr->Size;
+ ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)\
+ (((char*)ptr) + ptr->Size);
}
free(buffer);
- if (ncpus == 0)
- goto return_none;
- else
- return Py_BuildValue("i", ncpus);
+ if (ncpus != 0) {
+ return Py_BuildValue("I", ncpus);
+ }
+ else {
+ psutil_debug("GetLogicalProcessorInformationEx() count was 0");
+ Py_RETURN_NONE; // mimick os.cpu_count()
+ }
return_none:
- // mimic os.cpu_count()
if (buffer != NULL)
free(buffer);
Py_RETURN_NONE;
}
+#endif
/*
@@ -957,8 +1024,8 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
double idle, kernel, systemt, user, interrupt, dpc;
NTSTATUS status;
_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
- SYSTEM_INFO si;
UINT i;
+ unsigned int ncpus;
PyObject *py_tuple = NULL;
PyObject *py_retlist = PyList_New(0);
@@ -978,14 +1045,15 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
goto error;
}
- // retrives number of processors
- GetSystemInfo(&si);
+ // retrieves number of processors
+ ncpus = psutil_get_num_cpus(1);
+ if (ncpus == 0)
+ goto error;
// allocates an array of _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
// structures, one per processor
sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \
- malloc(si.dwNumberOfProcessors * \
- sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
+ malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
if (sppi == NULL) {
PyErr_NoMemory();
goto error;
@@ -995,8 +1063,7 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
status = NtQuerySystemInformation(
SystemProcessorPerformanceInformation,
sppi,
- si.dwNumberOfProcessors * sizeof
- (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
+ ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
NULL);
if (status != 0) {
PyErr_SetFromWindowsErr(0);
@@ -1006,7 +1073,7 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
// computes system global times summing each
// processor value
idle = user = kernel = interrupt = dpc = 0;
- for (i = 0; i < si.dwNumberOfProcessors; i++) {
+ for (i = 0; i < ncpus; i++) {
py_tuple = NULL;
user = (double)((HI_T * sppi[i].UserTime.HighPart) +
(LO_T * sppi[i].UserTime.LowPart));
@@ -3403,7 +3470,7 @@ psutil_cpu_stats(PyObject *self, PyObject *args) {
_SYSTEM_PERFORMANCE_INFORMATION *spi = NULL;
_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
_SYSTEM_INTERRUPT_INFORMATION *InterruptInformation = NULL;
- SYSTEM_INFO si;
+ unsigned int ncpus;
UINT i;
ULONG64 dpcs = 0;
ULONG interrupts = 0;
@@ -3421,13 +3488,14 @@ psutil_cpu_stats(PyObject *self, PyObject *args) {
goto error;
}
- // retrives number of processors
- GetSystemInfo(&si);
+ // retrieves number of processors
+ ncpus = psutil_get_num_cpus(1);
+ if (ncpus == 0)
+ goto error;
// get syscalls / ctx switches
spi = (_SYSTEM_PERFORMANCE_INFORMATION *) \
- malloc(si.dwNumberOfProcessors * \
- sizeof(_SYSTEM_PERFORMANCE_INFORMATION));
+ malloc(ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION));
if (spi == NULL) {
PyErr_NoMemory();
goto error;
@@ -3435,7 +3503,7 @@ psutil_cpu_stats(PyObject *self, PyObject *args) {
status = NtQuerySystemInformation(
SystemPerformanceInformation,
spi,
- si.dwNumberOfProcessors * sizeof(_SYSTEM_PERFORMANCE_INFORMATION),
+ ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION),
NULL);
if (status != 0) {
PyErr_SetFromWindowsErr(0);
@@ -3444,8 +3512,7 @@ psutil_cpu_stats(PyObject *self, PyObject *args) {
// get DPCs
InterruptInformation = \
- malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) *
- si.dwNumberOfProcessors);
+ malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) * ncpus);
if (InterruptInformation == NULL) {
PyErr_NoMemory();
goto error;
@@ -3454,20 +3521,19 @@ psutil_cpu_stats(PyObject *self, PyObject *args) {
status = NtQuerySystemInformation(
SystemInterruptInformation,
InterruptInformation,
- si.dwNumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION),
+ ncpus * sizeof(SYSTEM_INTERRUPT_INFORMATION),
NULL);
if (status != 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}
- for (i = 0; i < si.dwNumberOfProcessors; i++) {
+ for (i = 0; i < ncpus; i++) {
dpcs += InterruptInformation[i].DpcCount;
}
// get interrupts
sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \
- malloc(si.dwNumberOfProcessors * \
- sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
+ malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
if (sppi == NULL) {
PyErr_NoMemory();
goto error;
@@ -3476,15 +3542,14 @@ psutil_cpu_stats(PyObject *self, PyObject *args) {
status = NtQuerySystemInformation(
SystemProcessorPerformanceInformation,
sppi,
- si.dwNumberOfProcessors * sizeof
- (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
+ ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
NULL);
if (status != 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}
- for (i = 0; i < si.dwNumberOfProcessors; i++) {
+ for (i = 0; i < ncpus; i++) {
interrupts += sppi[i].InterruptCount;
}
@@ -3525,19 +3590,15 @@ psutil_cpu_freq(PyObject *self, PyObject *args) {
LPBYTE pBuffer = NULL;
ULONG current;
ULONG max;
- unsigned int num_cpus;
- SYSTEM_INFO system_info;
- system_info.dwNumberOfProcessors = 0;
+ unsigned int ncpus;
// Get the number of CPUs.
- GetSystemInfo(&system_info);
- if (system_info.dwNumberOfProcessors == 0)
- num_cpus = 1;
- else
- num_cpus = system_info.dwNumberOfProcessors;
+ ncpus = psutil_get_num_cpus(1);
+ if (ncpus == 0)
+ return NULL;
// Allocate size.
- size = num_cpus * sizeof(PROCESSOR_POWER_INFORMATION);
+ size = ncpus * sizeof(PROCESSOR_POWER_INFORMATION);
pBuffer = (BYTE*)LocalAlloc(LPTR, size);
if (! pBuffer)
return PyErr_SetFromWindowsErr(0);
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index ab727cba..18651d6c 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -288,7 +288,7 @@ def cpu_count_logical():
def cpu_count_physical():
- """Return the number of physical CPUs in the system."""
+ """Return the number of physical CPU cores in the system."""
return cext.cpu_count_phys()
diff --git a/psutil/arch/windows/glpi.h b/psutil/arch/windows/glpi.h
deleted file mode 100644
index 6f984837..00000000
--- a/psutil/arch/windows/glpi.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// mingw headers are missing this
-
-typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
- RelationProcessorCore,
- RelationNumaNode,
- RelationCache,
- RelationProcessorPackage,
- RelationGroup,
- RelationAll=0xffff
-} LOGICAL_PROCESSOR_RELATIONSHIP;
-
-typedef enum _PROCESSOR_CACHE_TYPE {
- CacheUnified,CacheInstruction,CacheData,CacheTrace
-} PROCESSOR_CACHE_TYPE;
-
-typedef struct _CACHE_DESCRIPTOR {
- BYTE Level;
- BYTE Associativity;
- WORD LineSize;
- DWORD Size;
- PROCESSOR_CACHE_TYPE Type;
-} CACHE_DESCRIPTOR,*PCACHE_DESCRIPTOR;
-
-typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
- ULONG_PTR ProcessorMask;
- LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
- union {
- struct {
- BYTE Flags;
- } ProcessorCore;
- struct {
- DWORD NodeNumber;
- } NumaNode;
- CACHE_DESCRIPTOR Cache;
- ULONGLONG Reserved[2];
- };
-} SYSTEM_LOGICAL_PROCESSOR_INFORMATION,*PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;
-
-WINBASEAPI WINBOOL WINAPI
-GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,
- PDWORD ReturnedLength); \ No newline at end of file
diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py
index 20b132a9..6081ea5a 100755
--- a/psutil/tests/test_system.py
+++ b/psutil/tests/test_system.py
@@ -268,8 +268,11 @@ class TestSystemAPIs(unittest.TestCase):
if "physical id" not in cpuinfo_data:
raise unittest.SkipTest("cpuinfo doesn't include physical id")
physical = psutil.cpu_count(logical=False)
- self.assertGreaterEqual(physical, 1)
- self.assertGreaterEqual(logical, physical)
+ if WINDOWS and sys.getwindowsversion()[:2] <= (6, 1): # <= Vista
+ self.assertIsNone(physical)
+ else:
+ self.assertGreaterEqual(physical, 1)
+ self.assertGreaterEqual(logical, physical)
def test_cpu_count_none(self):
# https://github.com/giampaolo/psutil/issues/1085
diff --git a/psutil/tests/test_windows.py b/psutil/tests/test_windows.py
index 32c46f67..ffa763d0 100755
--- a/psutil/tests/test_windows.py
+++ b/psutil/tests/test_windows.py
@@ -69,35 +69,57 @@ def wrap_exceptions(fun):
@unittest.skipIf(not WINDOWS, "WINDOWS only")
-class TestSystemAPIs(unittest.TestCase):
-
- def test_nic_names(self):
- out = sh('ipconfig /all')
- nics = psutil.net_io_counters(pernic=True).keys()
- for nic in nics:
- if "pseudo-interface" in nic.replace(' ', '-').lower():
- continue
- if nic not in out:
- self.fail(
- "%r nic wasn't found in 'ipconfig /all' output" % nic)
+class TestCpuAPIs(unittest.TestCase):
@unittest.skipIf('NUMBER_OF_PROCESSORS' not in os.environ,
'NUMBER_OF_PROCESSORS env var is not available')
- def test_cpu_count(self):
+ def test_cpu_count_vs_NUMBER_OF_PROCESSORS(self):
+ # Will likely fail on many-cores systems:
+ # https://stackoverflow.com/questions/31209256
num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
self.assertEqual(num_cpus, psutil.cpu_count())
- def test_cpu_count_2(self):
+ def test_cpu_count_vs_GetSystemInfo(self):
+ # Will likely fail on many-cores systems:
+ # https://stackoverflow.com/questions/31209256
sys_value = win32api.GetSystemInfo()[5]
psutil_value = psutil.cpu_count()
self.assertEqual(sys_value, psutil_value)
+ def test_cpu_count_logical_vs_wmi(self):
+ w = wmi.WMI()
+ proc = w.Win32_Processor()[0]
+ self.assertEqual(psutil.cpu_count(), proc.NumberOfLogicalProcessors)
+
+ def test_cpu_count_phys_vs_wmi(self):
+ w = wmi.WMI()
+ proc = w.Win32_Processor()[0]
+ self.assertEqual(psutil.cpu_count(logical=False), proc.NumberOfCores)
+
+ def test_cpu_count_vs_cpu_times(self):
+ self.assertEqual(psutil.cpu_count(),
+ len(psutil.cpu_times(percpu=True)))
+
def test_cpu_freq(self):
w = wmi.WMI()
proc = w.Win32_Processor()[0]
self.assertEqual(proc.CurrentClockSpeed, psutil.cpu_freq().current)
self.assertEqual(proc.MaxClockSpeed, psutil.cpu_freq().max)
+
+@unittest.skipIf(not WINDOWS, "WINDOWS only")
+class TestSystemAPIs(unittest.TestCase):
+
+ def test_nic_names(self):
+ out = sh('ipconfig /all')
+ nics = psutil.net_io_counters(pernic=True).keys()
+ for nic in nics:
+ if "pseudo-interface" in nic.replace(' ', '-').lower():
+ continue
+ if nic not in out:
+ self.fail(
+ "%r nic wasn't found in 'ipconfig /all' output" % nic)
+
def test_total_phymem(self):
w = wmi.WMI().Win32_ComputerSystem()[0]
self.assertEqual(int(w.TotalPhysicalMemory),