summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Manuskin <amanusk@protonmail.com>2018-11-03 16:06:13 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2018-11-03 07:06:13 -0700
commitbb5d032be76980a9e110f03f1203bd35fa85a793 (patch)
tree8341ee50730726aaaf86ca116e92c1f6fa7839e2
parent648d8ba39eff4867d461a45a77d1245e2a909234 (diff)
downloadpsutil-bb5d032be76980a9e110f03f1203bd35fa85a793.tar.gz
FreeBSD adding temperature sensors (WIP) (#1350)
FreeBSD: add temperature sensors
-rw-r--r--psutil/_psbsd.py18
-rw-r--r--psutil/_psutil_bsd.c2
-rw-r--r--psutil/arch/freebsd/specific.c36
-rw-r--r--psutil/arch/freebsd/specific.h1
-rwxr-xr-xpsutil/tests/test_bsd.py17
-rwxr-xr-xpsutil/tests/test_contracts.py4
6 files changed, 76 insertions, 2 deletions
diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py
index c2896cb7..0727dd2e 100644
--- a/psutil/_psbsd.py
+++ b/psutil/_psbsd.py
@@ -11,6 +11,7 @@ import os
import xml.etree.ElementTree as ET
from collections import namedtuple
from socket import AF_INET
+from collections import defaultdict
from . import _common
from . import _psposix
@@ -437,6 +438,23 @@ if FREEBSD:
secsleft = minsleft * 60
return _common.sbattery(percent, secsleft, power_plugged)
+ def sensors_temperatures():
+ "Return CPU cores temperatures if available, else an empty dict."
+ ret = defaultdict(list)
+ num_cpus = cpu_count_logical()
+ for cpu in range(num_cpus):
+ try:
+ current, high = cext.sensors_cpu_temperature(cpu)
+ if high <= 0:
+ high = None
+ name = "Core %s" % cpu
+ ret["coretemp"].append(
+ _common.shwtemp(name, current, high, high))
+ except NotImplementedError:
+ pass
+
+ return ret
+
# =====================================================================
# --- other system functions
diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c
index 4e91c02e..6b366f13 100644
--- a/psutil/_psutil_bsd.c
+++ b/psutil/_psutil_bsd.c
@@ -981,6 +981,8 @@ PsutilMethods[] = {
#if defined(PSUTIL_FREEBSD)
{"sensors_battery", psutil_sensors_battery, METH_VARARGS,
"Return battery information."},
+ {"sensors_cpu_temperature", psutil_sensors_cpu_temperature, METH_VARARGS,
+ "Return temperature information for a given CPU core number."},
#endif
// --- others
diff --git a/psutil/arch/freebsd/specific.c b/psutil/arch/freebsd/specific.c
index 177ac8a6..14be26b3 100644
--- a/psutil/arch/freebsd/specific.c
+++ b/psutil/arch/freebsd/specific.c
@@ -31,6 +31,7 @@
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
#define PSUTIL_BT2MSEC(bt) (bt.sec * 1000 + (((uint64_t) 1000000000 * (uint32_t) \
(bt.frac >> 32) ) >> 32 ) / 1000000)
+#define DECIKELVIN_2_CELCIUS(t) (t - 2731) / 10
#ifndef _PATH_DEVNULL
#define _PATH_DEVNULL "/dev/null"
#endif
@@ -1010,3 +1011,38 @@ error:
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
+
+
+/*
+ * Return temperature information for a given CPU core number.
+ */
+PyObject *
+psutil_sensors_cpu_temperature(PyObject *self, PyObject *args) {
+ int current;
+ int tjmax;
+ int core;
+ char sensor[26];
+ size_t size = sizeof(current);
+
+ if (! PyArg_ParseTuple(args, "i", &core))
+ return NULL;
+ sprintf(sensor, "dev.cpu.%d.temperature", core);
+ if (sysctlbyname(sensor, &current, &size, NULL, 0))
+ goto error;
+ current = DECIKELVIN_2_CELCIUS(current);
+
+ // Return -273 in case of faliure.
+ sprintf(sensor, "dev.cpu.%d.coretemp.tjmax", core);
+ if (sysctlbyname(sensor, &tjmax, &size, NULL, 0))
+ tjmax = 0;
+ tjmax = DECIKELVIN_2_CELCIUS(tjmax);
+
+ return Py_BuildValue("ii", current, tjmax);
+
+error:
+ if (errno == ENOENT)
+ PyErr_SetString(PyExc_NotImplementedError, "no temperature sensors");
+ else
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+}
diff --git a/psutil/arch/freebsd/specific.h b/psutil/arch/freebsd/specific.h
index 0df66ecc..cb71ff61 100644
--- a/psutil/arch/freebsd/specific.h
+++ b/psutil/arch/freebsd/specific.h
@@ -29,4 +29,5 @@ PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
PyObject* psutil_cpu_stats(PyObject* self, PyObject* args);
#if defined(PSUTIL_FREEBSD)
PyObject* psutil_sensors_battery(PyObject* self, PyObject* args);
+PyObject* psutil_sensors_cpu_temperature(PyObject* self, PyObject* args);
#endif
diff --git a/psutil/tests/test_bsd.py b/psutil/tests/test_bsd.py
index 7846c1ca..df43a023 100755
--- a/psutil/tests/test_bsd.py
+++ b/psutil/tests/test_bsd.py
@@ -427,6 +427,23 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
sysctl("hw.acpi.acline")
self.assertIsNone(psutil.sensors_battery())
+ # --- sensors_temperatures
+
+ def test_sensors_temperatures_against_sysctl(self):
+ num_cpus = psutil.cpu_count(True)
+ for cpu in range(num_cpus):
+ sensor = "dev.cpu.%s.temperature" % cpu
+ # sysctl returns a string in the format 46.0C
+ sysctl_result = int(float(sysctl(sensor)[:-1]))
+ self.assertAlmostEqual(
+ psutil.sensors_temperatures()["coretemp"][cpu].current,
+ sysctl_result, delta=10)
+
+ sensor = "dev.cpu.%s.coretemp.tjmax" % cpu
+ sysctl_result = int(float(sysctl(sensor)[:-1]))
+ self.assertEqual(
+ psutil.sensors_temperatures()["coretemp"][cpu].high,
+ sysctl_result)
# =====================================================================
# --- OpenBSD
diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py
index d936eaf8..8ff41e5b 100755
--- a/psutil/tests/test_contracts.py
+++ b/psutil/tests/test_contracts.py
@@ -119,7 +119,7 @@ class TestAvailability(unittest.TestCase):
def test_sensors_temperatures(self):
self.assertEqual(
- hasattr(psutil, "sensors_temperatures"), LINUX)
+ hasattr(psutil, "sensors_temperatures"), LINUX or FREEBSD)
def test_sensors_fans(self):
self.assertEqual(hasattr(psutil, "sensors_fans"), LINUX)
@@ -337,7 +337,7 @@ class TestFetchAllProcesses(unittest.TestCase):
self.assertEqual(err.name, p.name())
assert str(err)
assert err.msg
- except Exception as err:
+ except Exception:
s = '\n' + '=' * 70 + '\n'
s += "FAIL: test_%s (proc=%s" % (name, p)
if ret != default: