From 2d1bb43b7f8831fc92cb39afbbc78330254f692c Mon Sep 17 00:00:00 2001 From: Alex Manuskin Date: Fri, 19 Oct 2018 19:11:46 +0300 Subject: [PATCH 1/2] FreeBSD adding temperature sensors * Add temperature sensors to freeBSD --- psutil/_psbsd.py | 16 +++++++++++++++ psutil/_psutil_bsd.c | 2 ++ psutil/arch/freebsd/specific.c | 36 ++++++++++++++++++++++++++++++++++ psutil/arch/freebsd/specific.h | 1 + 4 files changed, 55 insertions(+) diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py index 7f4bcb6de..f288403aa 100644 --- a/psutil/_psbsd.py +++ b/psutil/_psbsd.py @@ -432,6 +432,22 @@ def sensors_battery(): secsleft = minsleft * 60 return _common.sbattery(percent, secsleft, power_plugged) + def sensors_temperatures(): + """Return systemp temperatures""" + ret = dict() + ret["coretemp"] = list() + num_cpus = cpu_count_logical() + try: + for cpu in range(num_cpus): + current, tjmax = cext.sensors_temperatures(cpu) + name = "Core {}".format(cpu) + ret["coretemp"].append( + _common.shwtemp(name, current, tjmax, tjmax)) + except NotImplementedError: + return None + + return ret + # ===================================================================== # --- other system functions diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c index 4e91c02ed..ae1993e37 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_temperatures", psutil_sensors_temperatures, METH_VARARGS, + "Return temperatures information."}, #endif // --- others diff --git a/psutil/arch/freebsd/specific.c b/psutil/arch/freebsd/specific.c index 177ac8a6b..1963b9153 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 SYSCTLTEMP(t) ((int)((t + 270)) - 3000) / 10 #ifndef _PATH_DEVNULL #define _PATH_DEVNULL "/dev/null" #endif @@ -1010,3 +1011,38 @@ psutil_sensors_battery(PyObject *self, PyObject *args) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } + + +/* + * Return temperature information. + */ +PyObject * +psutil_sensors_temperatures(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, ¤t, &size, NULL, 0)) + goto error; + current = SYSCTLTEMP(current); + + sprintf(sensor, "dev.cpu.%d.coretemp.tjmax", core); + if (sysctlbyname(sensor, &tjmax, &size, NULL, 0)) + goto error; + tjmax = SYSCTLTEMP(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 0df66eccb..ad4abaf15 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_temperatures(PyObject* self, PyObject* args); #endif From 703f3dc484f338eaa66d8e6242efdfe9f0383aa0 Mon Sep 17 00:00:00 2001 From: Alex Manuskin Date: Fri, 2 Nov 2018 10:40:26 +0200 Subject: [PATCH 2/2] Add tests for sensors_temperatures on freeBSD --- psutil/_psbsd.py | 22 ++++++++++++---------- psutil/_psutil_bsd.c | 4 ++-- psutil/arch/freebsd/specific.c | 14 +++++++------- psutil/arch/freebsd/specific.h | 2 +- psutil/tests/test_bsd.py | 17 +++++++++++++++++ psutil/tests/test_contracts.py | 4 ++-- 6 files changed, 41 insertions(+), 22 deletions(-) diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py index f288403aa..cae975c00 100644 --- a/psutil/_psbsd.py +++ b/psutil/_psbsd.py @@ -11,6 +11,7 @@ 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 @@ -433,18 +434,19 @@ def sensors_battery(): return _common.sbattery(percent, secsleft, power_plugged) def sensors_temperatures(): - """Return systemp temperatures""" - ret = dict() - ret["coretemp"] = list() + "Return CPU cores temperatures if available, else an empty dict." + ret = defaultdict(list) num_cpus = cpu_count_logical() - try: - for cpu in range(num_cpus): - current, tjmax = cext.sensors_temperatures(cpu) - name = "Core {}".format(cpu) + 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, tjmax, tjmax)) - except NotImplementedError: - return None + _common.shwtemp(name, current, high, high)) + except NotImplementedError: + pass return ret diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c index ae1993e37..6b366f13b 100644 --- a/psutil/_psutil_bsd.c +++ b/psutil/_psutil_bsd.c @@ -981,8 +981,8 @@ PsutilMethods[] = { #if defined(PSUTIL_FREEBSD) {"sensors_battery", psutil_sensors_battery, METH_VARARGS, "Return battery information."}, - {"sensors_temperatures", psutil_sensors_temperatures, METH_VARARGS, - "Return temperatures 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 1963b9153..14be26b36 100644 --- a/psutil/arch/freebsd/specific.c +++ b/psutil/arch/freebsd/specific.c @@ -31,7 +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 SYSCTLTEMP(t) ((int)((t + 270)) - 3000) / 10 +#define DECIKELVIN_2_CELCIUS(t) (t - 2731) / 10 #ifndef _PATH_DEVNULL #define _PATH_DEVNULL "/dev/null" #endif @@ -1014,10 +1014,10 @@ psutil_sensors_battery(PyObject *self, PyObject *args) { /* - * Return temperature information. + * Return temperature information for a given CPU core number. */ PyObject * -psutil_sensors_temperatures(PyObject *self, PyObject *args) { +psutil_sensors_cpu_temperature(PyObject *self, PyObject *args) { int current; int tjmax; int core; @@ -1029,13 +1029,13 @@ psutil_sensors_temperatures(PyObject *self, PyObject *args) { sprintf(sensor, "dev.cpu.%d.temperature", core); if (sysctlbyname(sensor, ¤t, &size, NULL, 0)) goto error; - current = SYSCTLTEMP(current); + 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)) - goto error; - tjmax = SYSCTLTEMP(tjmax); - + tjmax = 0; + tjmax = DECIKELVIN_2_CELCIUS(tjmax); return Py_BuildValue("ii", current, tjmax); diff --git a/psutil/arch/freebsd/specific.h b/psutil/arch/freebsd/specific.h index ad4abaf15..cb71ff612 100644 --- a/psutil/arch/freebsd/specific.h +++ b/psutil/arch/freebsd/specific.h @@ -29,5 +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_temperatures(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 7846c1ca2..df43a023e 100755 --- a/psutil/tests/test_bsd.py +++ b/psutil/tests/test_bsd.py @@ -427,6 +427,23 @@ def test_sensors_battery_no_battery(self): 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 d936eaf88..8ff41e5b3 100755 --- a/psutil/tests/test_contracts.py +++ b/psutil/tests/test_contracts.py @@ -119,7 +119,7 @@ def test_cpu_freq(self): 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 @@ def test_fetch_all(self): 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: