solid: implement getter for the minimum CPU speed

cannot test it for the devinfo backend right now so it is on the TODO, for
the udev backend it ends up as being optimization because the check if the
frequency can be changed already reads cpuinfo_min_freq and
cpuinfo_max_freq files

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-03-17 05:35:17 +02:00
parent da0323350c
commit 9a33d048ba
11 changed files with 73 additions and 45 deletions

View file

@ -42,6 +42,12 @@ int Processor::number() const
return m_device->deviceProperty(DevinfoDevice::DeviceName).right(1).toInt();
}
int Processor::minSpeed() const
{
#warning implement
return 0;
}
int Processor::maxSpeed() const
{
int result = 0;

View file

@ -42,6 +42,7 @@ public:
virtual ~Processor();
virtual int number() const;
virtual int minSpeed() const;
virtual int maxSpeed() const;
virtual bool canChangeFrequency() const;
virtual Solid::Processor::InstructionSets instructionSets() const;

View file

@ -90,6 +90,7 @@
<property key="vendor">Acme Corporation</property>
<property key="parent">/org/kde/solid/fakehw/computer</property>
<property key="number">0</property>
<property key="minSpeed">1600</property>
<property key="maxSpeed">3200</property>
<property key="canChangeFrequency">true</property>
<property key="instructionSets">mmx,sse</property>
@ -100,6 +101,7 @@
<property key="vendor">Acme Corporation</property>
<property key="parent">/org/kde/solid/fakehw/computer</property>
<property key="number">1</property>
<property key="minSpeed">1600</property>
<property key="maxSpeed">3200</property>
<property key="canChangeFrequency">true</property>
</device>

View file

@ -38,6 +38,11 @@ int FakeProcessor::number() const
return fakeDevice()->property("number").toInt();
}
int FakeProcessor::minSpeed() const
{
return fakeDevice()->property("minSpeed").toInt();
}
int FakeProcessor::maxSpeed() const
{
return fakeDevice()->property("maxSpeed").toInt();

View file

@ -41,6 +41,7 @@ public:
public Q_SLOTS:
virtual int number() const;
virtual int minSpeed() const;
virtual int maxSpeed() const;
virtual bool canChangeFrequency() const;
virtual Solid::Processor::InstructionSets instructionSets() const;

View file

@ -22,14 +22,15 @@
#include "udevdevice.h"
#include "cpuinfo.h"
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QFile>
#include <QDir>
#include <qmath.h>
using namespace Solid::Backends::UDev;
Processor::Processor(UDevDevice *device)
: DeviceInterface(device),
m_canChangeFrequency(NotChecked),
m_minSpeed(-1),
m_maxSpeed(-1)
{
}
@ -48,43 +49,25 @@ int Processor::number() const
}
// NOTE: do not parse /proc/cpuinfo for "cpu MHz", that may be current not maximum speed
int Processor::minSpeed() const
{
if (m_minSpeed == -1) {
m_minSpeed = getCPUInfo("/cpufreq/cpuinfo_min_freq");
}
return m_minSpeed;
}
int Processor::maxSpeed() const
{
if (m_maxSpeed == -1) {
QFile cpuMaxFreqFile(m_device->deviceName() + prefix() + "/cpufreq/cpuinfo_max_freq");
if (cpuMaxFreqFile.open(QIODevice::ReadOnly)) {
qlonglong maxFreq = cpuMaxFreqFile.readAll().trimmed().toLongLong();
if (maxFreq > 0) {
// cpuinfo_max_freq is in kHz
m_maxSpeed = static_cast<int>(maxFreq / 1000);
} else {
m_maxSpeed = 0;
}
}
m_maxSpeed = getCPUInfo("/cpufreq/cpuinfo_max_freq");
}
return m_maxSpeed;
}
bool Processor::canChangeFrequency() const
{
if (m_canChangeFrequency == NotChecked) {
/* Note that cpufreq is the right information source here, rather than
* anything to do with throttling (ACPI T-states). */
m_canChangeFrequency = CannotChangeFreq;
QFile cpuMinFreqFile(m_device->deviceName() + prefix() + "/cpufreq/cpuinfo_min_freq");
QFile cpuMaxFreqFile(m_device->deviceName() + prefix() + "/cpufreq/cpuinfo_max_freq");
if (cpuMinFreqFile.open(QIODevice::ReadOnly) && cpuMaxFreqFile.open(QIODevice::ReadOnly)) {
qlonglong minFreq = cpuMinFreqFile.readAll().trimmed().toLongLong();
qlonglong maxFreq = cpuMaxFreqFile.readAll().trimmed().toLongLong();
if (minFreq > 0 && maxFreq > minFreq) {
m_canChangeFrequency = CanChangeFreq;
}
}
}
return m_canChangeFrequency == CanChangeFreq;
return (minSpeed() > 0 && maxSpeed() > 0);
}
Solid::Processor::InstructionSets Processor::instructionSets() const
@ -120,14 +103,25 @@ Solid::Processor::InstructionSets Processor::instructionSets() const
return cpuinstructions;
}
QString Processor::prefix() const
int Processor::getCPUInfo(const char* filename) const
{
const QLatin1String sysPrefix("/sysdev");
if (QDir(m_device->deviceName() + sysPrefix).exists()) {
return sysPrefix;
}
static const QLatin1String sysPrefix("/sysdev");
return QString();
QString cpuFreqFileName(m_device->deviceName());
if (QDir(cpuFreqFileName + sysPrefix).exists()) {
cpuFreqFileName.append(sysPrefix);
}
cpuFreqFileName.append(QLatin1String(filename));
QFile cpuFreqFile(cpuFreqFileName);
if (cpuFreqFile.open(QIODevice::ReadOnly)) {
const qlonglong value = cpuFreqFile.readAll().trimmed().toLongLong();
if (value > 0) {
// value is in kHz
return qRound(value / 1000);
}
}
return 0;
}
#include "backends/udev/moc_udevprocessor.cpp"

View file

@ -42,19 +42,15 @@ public:
virtual ~Processor();
virtual int number() const;
virtual int minSpeed() const;
virtual int maxSpeed() const;
virtual bool canChangeFrequency() const;
virtual Solid::Processor::InstructionSets instructionSets() const;
private:
enum CanChangeFrequencyEnum {
NotChecked,
CanChangeFreq,
CannotChangeFreq
};
mutable CanChangeFrequencyEnum m_canChangeFrequency;
mutable int m_minSpeed;
mutable int m_maxSpeed;
QString prefix() const;
int getCPUInfo(const char* filename) const;
};
}
}

View file

@ -46,6 +46,13 @@ namespace Ifaces
*/
virtual int number() const = 0;
/**
* Retrieves the minimum speed of the processor.
*
* @return the minimum speed in MHz
*/
virtual int minSpeed() const = 0;
/**
* Retrieves the maximum speed of the processor.
*

View file

@ -41,6 +41,12 @@ int Solid::Processor::number() const
return_SOLID_CALL(Ifaces::Processor *, d->backendObject(), 0, number());
}
int Solid::Processor::minSpeed() const
{
Q_D(const Processor);
return_SOLID_CALL(Ifaces::Processor *, d->backendObject(), 0, minSpeed());
}
int Solid::Processor::maxSpeed() const
{
Q_D(const Processor);

View file

@ -39,6 +39,7 @@ namespace Solid
Q_ENUMS(InstructionSet)
Q_FLAGS(InstructionSets)
Q_PROPERTY(int number READ number)
Q_PROPERTY(qulonglong minSpeed READ minSpeed)
Q_PROPERTY(qulonglong maxSpeed READ maxSpeed)
Q_PROPERTY(bool canChangeFrequency READ canChangeFrequency)
Q_PROPERTY(InstructionSets instructionSets READ instructionSets)
@ -98,6 +99,14 @@ namespace Solid
*/
int number() const;
/**
* Retrieves the minimum speed of the processor.
*
* @return the minimum speed in MHz, or 0 if the device can't be queried for this
* information.
*/
int minSpeed() const;
/**
* Retrieves the maximum speed of the processor.
*

View file

@ -61,6 +61,7 @@ void FakeHardwareTest::testFakeBackend()
QCOMPARE(processor->number(), 0);
QCOMPARE(processor->canChangeFrequency(), true);
QCOMPARE((int)processor->minSpeed(), 1600);
QCOMPARE((int)processor->maxSpeed(), 3200);
Solid::Processor::InstructionSets instructionsets;