File indexing completed on 2024-05-12 17:00:14
0001 /* 0002 SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "linuxcpu.h" 0008 0009 #include <QFile> 0010 0011 #include <sensors/sensors.h> 0012 #include <systemstats/SensorsFeatureSensor.h> 0013 0014 static double readCpuFreq(const QString &cpuId, const QString &attribute, bool &ok) 0015 { 0016 ok = false; 0017 QFile file(QStringLiteral("/sys/devices/system/cpu/%1/cpufreq/").arg(cpuId) + attribute); 0018 bool open = file.open(QIODevice::ReadOnly); 0019 if (open) { 0020 // Remove trailing new line 0021 return file.readAll().chopped(1).toUInt(&ok) / 1000.0; // CPUFreq reports values in kHZ 0022 } 0023 return 0; 0024 } 0025 0026 LinuxCpuObject::LinuxCpuObject(const QString &id, const QString &name, double initialFrequency, KSysGuard::SensorContainer *parent) 0027 : CpuObject(id, name, parent) 0028 , m_initialFrequency(initialFrequency) 0029 { 0030 } 0031 0032 void LinuxCpuObject::makeTemperatureSensor(const sensors_chip_name * const chipName, const sensors_feature * const feature) 0033 { 0034 m_temperature = KSysGuard::makeSensorsFeatureSensor(QStringLiteral("temperature"), chipName, feature, this); 0035 } 0036 0037 void LinuxCpuObject::initialize() 0038 { 0039 CpuObject::initialize(); 0040 m_frequency->setValue(m_initialFrequency); 0041 bool ok; 0042 const double max = readCpuFreq(id(), QStringLiteral("cpuinfo_max_freq"), ok); 0043 if (ok) { 0044 m_frequency->setMax(max); 0045 } 0046 const double min = readCpuFreq(id(), QStringLiteral("cpuinfo_min_freq"), ok); 0047 if (ok) { 0048 m_frequency->setMin(min); 0049 } 0050 } 0051 0052 void LinuxCpuObject::makeSensors() 0053 { 0054 BaseCpuObject::makeSensors(); 0055 m_frequency = new KSysGuard::SensorProperty(QStringLiteral("frequency"), this); 0056 if (!m_temperature) { 0057 m_temperature = new KSysGuard::SensorProperty(QStringLiteral("temperature"), this); 0058 } 0059 } 0060 0061 void LinuxCpuObject::update(unsigned long long system, unsigned long long user, unsigned long long wait, unsigned long long idle) 0062 { 0063 if (!isSubscribed()) { 0064 return; 0065 } 0066 0067 // First update usages 0068 m_usageComputer.setTicks(system, user, wait, idle); 0069 0070 m_system->setValue(m_usageComputer.systemUsage); 0071 m_user->setValue(m_usageComputer.userUsage); 0072 m_wait->setValue(m_usageComputer.waitUsage); 0073 m_usage->setValue(m_usageComputer.totalUsage); 0074 0075 // Second try to get current frequency 0076 bool ok = false; 0077 // First try cpuinfo_cur_freq, it is the frequency the hardware runs at (https://www.kernel.org/doc/html/latest/admin-guide/pm/cpufreq.html) 0078 int frequency = readCpuFreq(id(), QStringLiteral("cpuinfo_cur_freq"), ok); 0079 if (!ok) { 0080 frequency = readCpuFreq(id(), QStringLiteral("scaling_cur_freq"), ok); 0081 } 0082 if (ok) { 0083 m_frequency->setValue(frequency); 0084 } 0085 // FIXME Should we fall back to reading /proc/cpuinfo again when the above fails? Could have the 0086 // frequency value changed even if the cpu apparently doesn't use CPUFreq? 0087 0088 // Third update temperature 0089 m_temperature->update(); 0090 } 0091 0092 void LinuxAllCpusObject::update(unsigned long long system, unsigned long long user, unsigned long long wait, unsigned long long idle) { 0093 m_usageComputer.setTicks(system, user, wait, idle); 0094 0095 m_system->setValue(m_usageComputer.systemUsage); 0096 m_user->setValue(m_usageComputer.userUsage); 0097 m_wait->setValue(m_usageComputer.waitUsage); 0098 m_usage->setValue(m_usageComputer.totalUsage); 0099 }