Commit 10be6f78 authored by David Redondo's avatar David Redondo 🏎

introduce helper function for reading sysctl and read temperature on freebsd

parent 0f600bb5
......@@ -57,5 +57,10 @@ CpuObject::CpuObject(const QString &id, const QString &name, SensorContainer *pa
m_frequency->setDescription(i18nc("@info", "Current frequency of the CPU"));
m_frequency->setVariantType(QVariant::Double);
m_frequency->setUnit(KSysGuard::Unit::UnitMegaHertz);
m_temperature = new SensorProperty(QStringLiteral("temperature"), i18nc("@title", "Current Temperature"), this);
m_temperature->setShortName(i18nc("@title, Short for Current Temperatur", "Temperature"));
m_temperature->setVariantType(QVariant::Double);
m_temperature->setUnit(KSysGuard::Unit::UnitCelsius);
}
}
......@@ -34,7 +34,7 @@ protected:
SensorProperty *m_user;
SensorProperty *m_wait;
SensorProperty *m_frequency;
// TODO temperature
SensorProperty *m_temperature;
};
#endif
#include "freebsdcpu.h"
#include <algorithm>
#include <vector>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
......@@ -8,28 +11,42 @@
#include <SensorContainer.h>
template <typename T>
bool readSysctl(const char *name, T *buffer, size_t size = sizeof(T)) {
return sysctlbyname(name, buffer, &size, nullptr, 0) != -1;
}
FreeBsdCpuObject::FreeBsdCpuObject(const QString &id, const QString &name, SensorContainer *parent)
: CpuObject(id, name, parent)
{
// For min and max frequency we have to parse the values return by freq_levels because only
// minimum is exposed as a single value
size_t size;
const QByteArray levelsName = QByteArrayLiteral("dev.cpu.") + id.right(1).toLocal8Bit() + QByteArrayLiteral(".freq_levels");
if (sysctlbyname(levelsName, nullptr, &size, nullptr, 0) != -1) {
QByteArray freqLevels(size, Qt::Uninitialized);
if (sysctlbyname(levelsName, freqLevels.data(), &size, nullptr, 0) != -1) {
// The format is a list of pairs "frequency/power", see https://svnweb.freebsd.org/base/head/sys/kern/kern_cpu.c?revision=360464&view=markup#l1019
const QList<QByteArray> levels = freqLevels.split(' ');
int min = INT_MAX;
int max = 0;
for (const auto &level : levels) {
const int frequency = level.left(level.indexOf('/')).toInt();
min = std::min(frequency, min);
max = std::max(frequency, max);
if (id != QStringLiteral("all")) {
// For min and max frequency we have to parse the values return by freq_levels because only
// minimum is exposed as a single value
size_t size;
const QByteArray levelsName = QByteArrayLiteral("dev.cpu.") + id.right(1).toLocal8Bit() + QByteArrayLiteral(".freq_levels");
if (sysctlbyname(levelsName, nullptr, &size, nullptr, 0) != -1) {
QByteArray freqLevels(size, Qt::Uninitialized);
if (sysctlbyname(levelsName, freqLevels.data(), &size, nullptr, 0) != -1) {
// The format is a list of pairs "frequency/power", see https://svnweb.freebsd.org/base/head/sys/kern/kern_cpu.c?revision=360464&view=markup#l1019
const QList<QByteArray> levels = freqLevels.split(' ');
int min = INT_MAX;
int max = 0;
for (const auto &level : levels) {
const int frequency = level.left(level.indexOf('/')).toInt();
min = std::min(frequency, min);
max = std::max(frequency, max);
}
// value are already in MHz see cpufreq(4)
m_frequency->setMin(min);
m_frequency->setMax(max);
}
// value are already in MHz see cpufreq(4)
m_frequency->setMin(min);
m_frequency->setMax(max);
}
const QByteArray tjmax = QByteArrayLiteral("dev.cpu.") + id.right(1).toLocal8Bit() + QByteArrayLiteral(".coretemp.tjmax");
int maxTemperature;
size_t maxTemperatureSize = sizeof(maxTemperature);
// This is only availabel on Intel (using the coretemp driver)
if (readSysctl(tjmax.constData(), &maxTemperature)) {
m_temperature->setMax(maxTemperature);
}
}
}
......@@ -52,13 +69,22 @@ void FreeBsdCpuObject::update(long system, long user, long idle)
m_userTicks = user;
m_totalTicks = totalTicks;
if (id() == QStringLiteral("all")) {
return;
}
int frequency;
size_t frequencySize = sizeof(frequency);
const QByteArray name = QByteArrayLiteral("dev.cpu.") + id().right(1).toLocal8Bit() + QByteArrayLiteral(".freq");
if (sysctlbyname(name.constData(), &frequency, &frequencySize, nullptr, 0) != -1) {
const QByteArray prefix = QByteArrayLiteral("dev.cpu.") + id().right(1).toLocal8Bit();
const QByteArray freq = prefix + QByteArrayLiteral(".freq");
if (readSysctl(freq.constData(), &frequency)){
// value is already in MHz
m_frequency->setValue(frequency);
}
int temperature;
const QByteArray temp = prefix + QByteArrayLiteral(".temperature");
if (readSysctl(temp.constData(), &temperature)) {
m_temperature->setValue(temperature);
}
}
......@@ -66,10 +92,9 @@ FreeBsdCpuPluginPrivate::FreeBsdCpuPluginPrivate(CpuPlugin* q)
: CpuPluginPrivate(q)
{
// The values used here can be found in smp(4)
unsigned int numCpu;
size_t unsignedIntSize = sizeof(numCpu);
sysctl((int[]){CTL_HW, HW_NCPU}, 2, &numCpu, &unsignedIntSize, nullptr, 0);
for (unsigned int i = 0; i < numCpu; ++i) {
int numCpu;
readSysctl("hw.ncpu", &numCpu);
for (int i = 0; i < numCpu; ++i) {
new FreeBsdCpuObject(QStringLiteral("cpu%1").arg(i), i18nc("@title", "CPU %1", i + 1), m_container);
}
// TODO parse smp sysctl kern.sched.topology_spec xml to be able show names like "CPU 1 Core 2"
......@@ -92,8 +117,8 @@ void FreeBsdCpuPluginPrivate::update()
};
unsigned int numCores = m_container->objects().count() - 1;
std::vector<long> cp_times(numCores * CPUSTATES);
size_t cpTimesSize = sizeof(long) * numCores * CPUSTATES;
if (sysctlbyname("kern.cp_times", &cp_times[0], &cpTimesSize, nullptr, 0) != -1) {
size_t cpTimesSize = sizeof(long) * cp_times.size();
if (readSysctl("kern.cp_times", cp_times.data(), cpTimesSize)) {//, &cpTimesSize, nullptr, 0) != -1) {
for (unsigned int i = 0; i < numCores; ++i) {
auto cpu = static_cast<FreeBsdCpuObject*>(m_container->object(QStringLiteral("cpu%1").arg(i)));
updateCpu(cpu, &cp_times[CPUSTATES * i]);
......@@ -101,8 +126,7 @@ void FreeBsdCpuPluginPrivate::update()
}
// update total values
long cp_time[CPUSTATES];
size_t cpTimeSize = sizeof(long) * CPUSTATES;
if (sysctlbyname("kern.cp_times", cp_time, &cpTimeSize, nullptr, 0) != -1) {
if (readSysctl("kern.cp_time", &cp_time)) {
updateCpu(static_cast<FreeBsdCpuObject*>(m_container->object(QStringLiteral("all"))), cp_time);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment