summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-12-21 14:27:22 -0800
committerGiampaolo Rodola <g.rodola@gmail.com>2020-12-21 14:27:22 -0800
commit7e7449d51b3a388bdd3a078ca279ecbb3ab53bb0 (patch)
tree52a636fe552f34f13f5cb6602f9b08ec68b19b64
parentfe6e09fc158dfc947a6a2de0e45681e5b7ca25a9 (diff)
parent9906ffa432116cba3ebacc4010c1bde15ea1bcc2 (diff)
downloadpsutil-7e7449d51b3a388bdd3a078ca279ecbb3ab53bb0.tar.gz
merge from master
-rw-r--r--psutil/__init__.py2
-rw-r--r--psutil/_psosx.py5
-rw-r--r--psutil/_psutil_osx.c151
-rw-r--r--psutil/arch/osx/cpu.c151
-rw-r--r--psutil/arch/osx/cpu.h14
-rwxr-xr-xpsutil/tests/test_system.py30
-rwxr-xr-xsetup.py1
7 files changed, 194 insertions, 160 deletions
diff --git a/psutil/__init__.py b/psutil/__init__.py
index f8c0ba98..63f77e63 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -1598,7 +1598,7 @@ def cpu_count(kind="logical", **_kwargs):
return None
n = _psplatform.cpu_count_cores()
elif kind == "sockets":
- # Availability: Linux, TODO
+ # Availability: Linux, Windows, macOS
if not hasattr(_psplatform, "cpu_count_sockets"):
return None
n = _psplatform.cpu_count_sockets()
diff --git a/psutil/_psosx.py b/psutil/_psosx.py
index d948cc15..9cfb2d15 100644
--- a/psutil/_psosx.py
+++ b/psutil/_psosx.py
@@ -164,6 +164,11 @@ def cpu_count_cores():
return cext.cpu_count_cores()
+def cpu_count_sockets():
+ """Return the number of physical sockets on the motherboard."""
+ return cext.cpu_count_sockets()
+
+
def cpu_stats():
ctx_switches, interrupts, soft_interrupts, syscalls, traps = \
cext.cpu_stats()
diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c
index b5aa7653..47b5393f 100644
--- a/psutil/_psutil_osx.c
+++ b/psutil/_psutil_osx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
@@ -14,7 +14,6 @@
#include <stdio.h>
#include <utmpx.h>
#include <sys/sysctl.h>
-#include <sys/vmmeter.h>
#include <libproc.h>
#include <sys/proc_info.h>
#include <netinet/tcp_fsm.h>
@@ -22,13 +21,7 @@
#include <net/if_dl.h>
#include <pwd.h>
#include <unistd.h>
-
#include <mach/mach.h>
-#include <mach/task.h>
-#include <mach/mach_init.h>
-#include <mach/host_info.h>
-#include <mach/mach_host.h>
-#include <mach/mach_traps.h>
#include <mach/mach_vm.h>
#include <mach/shared_region.h>
@@ -45,6 +38,7 @@
#include "_psutil_common.h"
#include "_psutil_posix.h"
#include "arch/osx/process_info.h"
+#include "arch/osx/cpu.h"
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
@@ -354,50 +348,6 @@ psutil_proc_environ(PyObject *self, PyObject *args) {
/*
- * Return the number of logical CPUs in the system.
- * XXX this could be shared with BSD.
- */
-static PyObject *
-psutil_cpu_count_logical(PyObject *self, PyObject *args) {
- /*
- int mib[2];
- int ncpu;
- size_t len;
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof(ncpu);
-
- if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1)
- Py_RETURN_NONE; // mimic os.cpu_count()
- else
- return Py_BuildValue("i", ncpu);
- */
- int num;
- size_t size = sizeof(int);
-
- if (sysctlbyname("hw.logicalcpu", &num, &size, NULL, 2))
- Py_RETURN_NONE; // mimic os.cpu_count()
- else
- return Py_BuildValue("i", num);
-}
-
-
-/*
- * Return the number of CPU cores in the system.
- */
-static PyObject *
-psutil_cpu_count_cores(PyObject *self, PyObject *args) {
- int num;
- size_t size = sizeof(int);
-
- if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0))
- Py_RETURN_NONE; // mimic os.cpu_count()
- else
- return Py_BuildValue("i", num);
-}
-
-
-/*
* Indicates if the given virtual address on the given architecture is in the
* shared VM region.
*/
@@ -588,36 +538,6 @@ psutil_swap_mem(PyObject *self, PyObject *args) {
/*
- * Return a Python tuple representing user, kernel and idle CPU times
- */
-static PyObject *
-psutil_cpu_times(PyObject *self, PyObject *args) {
- mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
- kern_return_t error;
- host_cpu_load_info_data_t r_load;
-
- mach_port_t host_port = mach_host_self();
- error = host_statistics(host_port, HOST_CPU_LOAD_INFO,
- (host_info_t)&r_load, &count);
- if (error != KERN_SUCCESS) {
- return PyErr_Format(
- PyExc_RuntimeError,
- "host_statistics(HOST_CPU_LOAD_INFO) syscall failed: %s",
- mach_error_string(error));
- }
- mach_port_deallocate(mach_task_self(), host_port);
-
- return Py_BuildValue(
- "(dddd)",
- (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK,
- (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
- (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
- (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
- );
-}
-
-
-/*
* Return a Python list of tuple representing per-cpu times
*/
static PyObject *
@@ -684,40 +604,6 @@ error:
/*
- * Retrieve CPU frequency. Note: all of these are static vendor values
- * that never change.
- */
-static PyObject *
-psutil_cpu_freq(PyObject *self, PyObject *args) {
- unsigned int curr;
- int64_t min = 0;
- int64_t max = 0;
- int mib[2];
- size_t len = sizeof(curr);
- size_t size = sizeof(min);
-
- // also availble as "hw.cpufrequency" but it's deprecated
- mib[0] = CTL_HW;
- mib[1] = HW_CPU_FREQ;
-
- if (sysctl(mib, 2, &curr, &len, NULL, 0) < 0)
- return PyErr_SetFromOSErrnoWithSyscall("sysctl(HW_CPU_FREQ)");
-
- if (sysctlbyname("hw.cpufrequency_min", &min, &size, NULL, 0))
- psutil_debug("sysct('hw.cpufrequency_min') failed (set to 0)");
-
- if (sysctlbyname("hw.cpufrequency_max", &max, &size, NULL, 0))
- psutil_debug("sysctl('hw.cpufrequency_min') failed (set to 0)");
-
- return Py_BuildValue(
- "IKK",
- curr / 1000 / 1000,
- min / 1000 / 1000,
- max / 1000 / 1000);
-}
-
-
-/*
* Return a Python float indicating the system boot time expressed in
* seconds since the epoch.
*/
@@ -1635,37 +1521,6 @@ error:
/*
- * Return CPU statistics.
- */
-static PyObject *
-psutil_cpu_stats(PyObject *self, PyObject *args) {
- struct vmmeter vmstat;
- kern_return_t ret;
- mach_msg_type_number_t count = sizeof(vmstat) / sizeof(integer_t);
- mach_port_t mport = mach_host_self();
-
- ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)&vmstat, &count);
- if (ret != KERN_SUCCESS) {
- PyErr_Format(
- PyExc_RuntimeError,
- "host_statistics(HOST_VM_INFO) failed: %s",
- mach_error_string(ret));
- return NULL;
- }
- mach_port_deallocate(mach_task_self(), mport);
-
- return Py_BuildValue(
- "IIIII",
- vmstat.v_swtch, // ctx switches
- vmstat.v_intr, // interrupts
- vmstat.v_soft, // software interrupts
- vmstat.v_syscall, // syscalls
- vmstat.v_trap // traps
- );
-}
-
-
-/*
* Return battery information.
*/
static PyObject *
@@ -1791,6 +1646,8 @@ static PyMethodDef mod_methods[] = {
"Return number of logical CPUs on the system"},
{"cpu_count_cores", psutil_cpu_count_cores, METH_VARARGS,
"Return number of CPU cores on the system"},
+ {"cpu_count_sockets", psutil_cpu_count_sockets, METH_VARARGS,
+ "Return number of CPU sockets on the motherboard"},
{"virtual_mem", psutil_virtual_mem, METH_VARARGS,
"Return system virtual memory stats"},
{"swap_mem", psutil_swap_mem, METH_VARARGS,
diff --git a/psutil/arch/osx/cpu.c b/psutil/arch/osx/cpu.c
new file mode 100644
index 00000000..e6f72a8a
--- /dev/null
+++ b/psutil/arch/osx/cpu.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/*
+System-wide CPU related functions.
+
+Original code was refactored and moved from psutil/_psutil_osx.c in 2020
+right before a4c0a0eb0d2a872ab7a45e47fcf37ef1fde5b012.
+For reference, here's the git history with original implementations:
+
+- CPU count logical: 3d291d425b856077e65163e43244050fb188def1
+- CPU count physical: 4263e354bb4984334bc44adf5dd2f32013d69fba
+- CPU times: 32488bdf54aed0f8cef90d639c1667ffaa3c31c7
+- CPU stat: fa00dfb961ef63426c7818899340866ced8d2418
+- CPU frequency: 6ba1ac4ebfcd8c95fca324b15606ab0ec1412d39
+*/
+
+#include <Python.h>
+#include <sys/sysctl.h>
+#include <sys/vmmeter.h>
+
+#include <mach/mach_error.h>
+#include <mach/mach_host.h>
+#include <mach/mach_port.h>
+
+#include "../../_psutil_common.h"
+#include "../../_psutil_posix.h"
+
+
+PyObject *
+psutil_cpu_count_logical(PyObject *self, PyObject *args) {
+ int num;
+ size_t size = sizeof(int);
+
+ if (sysctlbyname("hw.logicalcpu", &num, &size, NULL, 2))
+ Py_RETURN_NONE; // mimic os.cpu_count()
+ else
+ return Py_BuildValue("i", num);
+}
+
+
+PyObject *
+psutil_cpu_count_cores(PyObject *self, PyObject *args) {
+ int num;
+ size_t size = sizeof(int);
+
+ if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0))
+ Py_RETURN_NONE; // mimic os.cpu_count()
+ else
+ return Py_BuildValue("i", num);
+}
+
+
+PyObject *
+psutil_cpu_count_sockets(PyObject *self, PyObject *args) {
+ int value;
+ size_t size = sizeof(value);
+
+ if (sysctlbyname("hw.packages", &value, &size, NULL, 2))
+ Py_RETURN_NONE; // mimic os.cpu_count()
+ else
+ return Py_BuildValue("i", value);
+}
+
+
+PyObject *
+psutil_cpu_times(PyObject *self, PyObject *args) {
+ mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
+ kern_return_t error;
+ host_cpu_load_info_data_t r_load;
+
+ mach_port_t host_port = mach_host_self();
+ error = host_statistics(host_port, HOST_CPU_LOAD_INFO,
+ (host_info_t)&r_load, &count);
+ if (error != KERN_SUCCESS) {
+ return PyErr_Format(
+ PyExc_RuntimeError,
+ "host_statistics(HOST_CPU_LOAD_INFO) syscall failed: %s",
+ mach_error_string(error));
+ }
+ mach_port_deallocate(mach_task_self(), host_port);
+
+ return Py_BuildValue(
+ "(dddd)",
+ (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK,
+ (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
+ (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
+ (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
+ );
+}
+
+
+PyObject *
+psutil_cpu_stats(PyObject *self, PyObject *args) {
+ struct vmmeter vmstat;
+ kern_return_t ret;
+ mach_msg_type_number_t count = sizeof(vmstat) / sizeof(integer_t);
+ mach_port_t mport = mach_host_self();
+
+ ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)&vmstat, &count);
+ if (ret != KERN_SUCCESS) {
+ PyErr_Format(
+ PyExc_RuntimeError,
+ "host_statistics(HOST_VM_INFO) failed: %s",
+ mach_error_string(ret));
+ return NULL;
+ }
+ mach_port_deallocate(mach_task_self(), mport);
+
+ return Py_BuildValue(
+ "IIIII",
+ vmstat.v_swtch, // ctx switches
+ vmstat.v_intr, // interrupts
+ vmstat.v_soft, // software interrupts
+ vmstat.v_syscall, // syscalls
+ vmstat.v_trap // traps
+ );
+}
+
+
+PyObject *
+psutil_cpu_freq(PyObject *self, PyObject *args) {
+ unsigned int curr;
+ int64_t min = 0;
+ int64_t max = 0;
+ int mib[2];
+ size_t len = sizeof(curr);
+ size_t size = sizeof(min);
+
+ // also availble as "hw.cpufrequency" but it's deprecated
+ mib[0] = CTL_HW;
+ mib[1] = HW_CPU_FREQ;
+
+ if (sysctl(mib, 2, &curr, &len, NULL, 0) < 0)
+ return PyErr_SetFromOSErrnoWithSyscall("sysctl(HW_CPU_FREQ)");
+
+ if (sysctlbyname("hw.cpufrequency_min", &min, &size, NULL, 0))
+ psutil_debug("sysct('hw.cpufrequency_min') failed (set to 0)");
+
+ if (sysctlbyname("hw.cpufrequency_max", &max, &size, NULL, 0))
+ psutil_debug("sysctl('hw.cpufrequency_min') failed (set to 0)");
+
+ return Py_BuildValue(
+ "IKK",
+ curr / 1000 / 1000,
+ min / 1000 / 1000,
+ max / 1000 / 1000);
+}
diff --git a/psutil/arch/osx/cpu.h b/psutil/arch/osx/cpu.h
new file mode 100644
index 00000000..40be1117
--- /dev/null
+++ b/psutil/arch/osx/cpu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+
+PyObject *psutil_cpu_count_logical(PyObject *self, PyObject *args);
+PyObject *psutil_cpu_count_cores(PyObject *self, PyObject *args);
+PyObject *psutil_cpu_count_sockets(PyObject *self, PyObject *args);
+PyObject *psutil_cpu_times(PyObject *self, PyObject *args);
+PyObject *psutil_cpu_freq(PyObject *self, PyObject *args);
+PyObject *psutil_cpu_stats(PyObject *self, PyObject *args);
diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py
index 4044e468..317a0ea8 100755
--- a/psutil/tests/test_system.py
+++ b/psutil/tests/test_system.py
@@ -303,13 +303,14 @@ class TestMemoryAPIs(PsutilTestCase):
assert mem.sout >= 0, mem
-class TestCpuAPIs(PsutilTestCase):
+class TestCpuCount(PsutilTestCase):
- def test_cpu_count(self):
+ def test_base(self):
kinds = ("logical", "cores", "sockets", "numa", "usable")
for kind in kinds:
n = psutil.cpu_count(kind=kind)
if n is not None:
+ self.assertIsInstance(n, int)
with self.subTest(kind):
self.assertGreaterEqual(n, 1)
@@ -321,7 +322,7 @@ class TestCpuAPIs(PsutilTestCase):
psutil.cpu_count(kind='xxx')
self.assertIn(str(kinds), str(cm.exception))
- def test_cpu_count_consistency(self):
+ def test_consistency(self):
logical = psutil.cpu_count("logical")
cores = psutil.cpu_count("cores")
sockets = psutil.cpu_count("sockets")
@@ -341,7 +342,7 @@ class TestCpuAPIs(PsutilTestCase):
if sockets is not None:
self.assertGreaterEqual(cores, sockets)
- def test_cpu_count_deprecation(self):
+ def test_deprecation(self):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
self.assertEqual(psutil.cpu_count(logical=True),
@@ -363,7 +364,7 @@ class TestCpuAPIs(PsutilTestCase):
psutil.cpu_count(True)
assert ws
- def test_cpu_count_cores(self):
+ def test_cores(self):
logical = psutil.cpu_count()
cores = psutil.cpu_count(logical=False)
if cores is None:
@@ -374,19 +375,18 @@ class TestCpuAPIs(PsutilTestCase):
self.assertGreaterEqual(cores, 1)
self.assertGreaterEqual(logical, cores)
- def test_cpu_count_none(self):
+ def test_return_none(self):
# https://github.com/giampaolo/psutil/issues/1085
for val in (-1, 0, None):
with mock.patch('psutil._psplatform.cpu_count_logical',
return_value=val) as m:
self.assertIsNone(psutil.cpu_count())
assert m.called
- with mock.patch('psutil._psplatform.cpu_count_cores',
- return_value=val) as m:
- self.assertIsNone(psutil.cpu_count(logical=False))
- assert m.called
- def test_cpu_times(self):
+
+class TestCpuTimes(PsutilTestCase):
+
+ def test_base(self):
# Check type, value >= 0, str().
total = 0
times = psutil.cpu_times()
@@ -415,7 +415,7 @@ class TestCpuAPIs(PsutilTestCase):
# msg="%s %s" % (new_t, last_t))
# last = new
- def test_cpu_times_time_increases(self):
+ def test_time_increases(self):
# Make sure time increases between calls.
t1 = sum(psutil.cpu_times())
stop_at = time.time() + GLOBAL_TIMEOUT
@@ -483,6 +483,9 @@ class TestCpuAPIs(PsutilTestCase):
self.assertAlmostEqual(
getattr(base, field), getattr(summed_values, field), delta=1)
+
+class TestCpuPercent(PsutilTestCase):
+
def _test_cpu_percent(self, percent, last_ret, new_ret):
try:
self.assertIsInstance(percent, float)
@@ -545,6 +548,9 @@ class TestCpuAPIs(PsutilTestCase):
for percent in cpu:
self._test_cpu_percent(percent, None, None)
+
+class TestOtherCPUFunctions(PsutilTestCase):
+
def test_cpu_stats(self):
# Tested more extensively in per-platform test modules.
infos = psutil.cpu_stats()
diff --git a/setup.py b/setup.py
index 90c79c7c..fcf89ae6 100755
--- a/setup.py
+++ b/setup.py
@@ -189,6 +189,7 @@ elif MACOS:
sources=sources + [
'psutil/_psutil_osx.c',
'psutil/arch/osx/process_info.c',
+ 'psutil/arch/osx/cpu.c',
],
define_macros=macros,
extra_link_args=[