Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Plasma
KSysGuard
Commits
bdeba27b
Commit
bdeba27b
authored
Aug 25, 2020
by
David Redondo
🏎
Browse files
Linux intel
parent
10be6f78
Changes
3
Hide whitespace changes
Inline
Side-by-side
plugins/global/cpu/cpu.cpp
View file @
bdeba27b
...
...
@@ -23,6 +23,8 @@
CpuObject
::
CpuObject
(
const
QString
&
id
,
const
QString
&
name
,
SensorContainer
*
parent
)
:
SensorObject
(
id
,
name
,
parent
)
,
m_frequency
{
nullptr
}
,
m_temperature
{
nullptr
}
{
auto
n
=
new
SensorProperty
(
QStringLiteral
(
"name"
),
i18nc
(
"@title"
,
"Name"
),
name
,
this
);
n
->
setVariantType
(
QVariant
::
String
);
...
...
plugins/global/cpu/linuxcpu.cpp
View file @
bdeba27b
...
...
@@ -4,7 +4,9 @@
#include
<KLocalizedString>
#ifdef HAVE_SENSORS
#include
<sensors/sensors.h>
#endif
#include
<SensorContainer.h>
...
...
@@ -21,9 +23,11 @@ static double readCpuFreq(const QString &cpuId, const QString &attribute, bool &
LinuxCpuObject
::
LinuxCpuObject
(
const
QString
&
id
,
const
QString
&
name
,
SensorContainer
*
parent
,
double
frequency
)
:
CpuObject
(
id
,
name
,
parent
)
,
m_sensorChipName
{
nullptr
}
,
m_temperatureSubfeature
{
-
1
}
{
if
(
m_frequency
)
{
m_frequency
->
setValue
(
frequency
);
m_frequency
->
setValue
(
frequency
);
bool
ok
;
const
double
max
=
readCpuFreq
(
id
,
"cpuinfo_max_freq"
,
ok
);
if
(
ok
)
{
...
...
@@ -36,6 +40,27 @@ LinuxCpuObject::LinuxCpuObject(const QString &id, const QString &name, SensorCon
}
}
void
LinuxCpuObject
::
setTemperatureSensor
(
const
sensors_chip_name
*
const
chipName
,
const
sensors_feature
*
const
feature
)
{
#ifdef HAVE_SENSORS
m_sensorChipName
=
chipName
;
const
sensors_subfeature
*
const
temperature
=
sensors_get_subfeature
(
chipName
,
feature
,
SENSORS_SUBFEATURE_TEMP_INPUT
);
if
(
temperature
)
{
m_temperatureSubfeature
=
temperature
->
number
;
}
// Typically temp_emergency > temp_crit > temp_max, but not every processor has them
// see https://www.kernel.org/doc/html/latest/hwmon/sysfs-interface.html
double
value
;
for
(
auto
subfeatureType
:
{
SENSORS_SUBFEATURE_TEMP_EMERGENCY
,
SENSORS_SUBFEATURE_TEMP_CRIT
,
SENSORS_SUBFEATURE_TEMP_MAX
})
{
const
sensors_subfeature
*
const
subfeature
=
sensors_get_subfeature
(
chipName
,
feature
,
subfeatureType
);
if
(
subfeature
&&
sensors_get_value
(
chipName
,
subfeature
->
number
,
&
value
)
==
0
)
{
m_temperature
->
setMax
(
value
);
break
;
}
}
#endif
}
void
LinuxCpuObject
::
update
(
unsigned
long
long
system
,
unsigned
long
long
user
,
unsigned
long
long
wait
,
unsigned
long
long
idle
)
{
// First calculate usages
...
...
@@ -68,9 +93,19 @@ void LinuxCpuObject::update(unsigned long long system, unsigned long long user,
}
if
(
ok
)
{
m_frequency
->
setValue
(
frequency
);
}
}
// FIXME Should we fall back to reading /proc/cpuinfo again when the above fails? Could have the
// frequency value changed even if the cpu apparently doesn't use CPUFreq?
// Third update temperature
#ifdef HAVE_SENSORS
if
(
m_sensorChipName
&&
m_temperatureSubfeature
!=
-
1
)
{
double
value
;
if
(
sensors_get_value
(
m_sensorChipName
,
m_temperatureSubfeature
,
&
value
)
==
0
)
{
m_temperature
->
setValue
(
value
);
}
}
#endif
}
LinuxCpuPluginPrivate
::
LinuxCpuPluginPrivate
(
CpuPlugin
*
q
)
...
...
@@ -82,15 +117,14 @@ LinuxCpuPluginPrivate::LinuxCpuPluginPrivate(CpuPlugin *q)
QHash
<
int
,
int
>
numCores
;
for
(
QByteArray
line
=
cpuinfo
.
readLine
();
!
line
.
isEmpty
();
line
=
cpuinfo
.
readLine
())
{
int
physicalId
=
-
1
;
int
processor
=
-
1
;
double
frequency
=
-
1
;
unsigned
int
processor
,
physicalId
,
coreId
;
double
frequency
=
0
;
// Processors are divided by empty lines
for
(;
(
physicalId
==
-
1
&&
processor
==
-
1
&&
frequency
==
-
1
)
||
line
!=
"
\n
"
;
line
=
cpuinfo
.
readLine
())
{
for
(;
line
!=
"
\n
"
;
line
=
cpuinfo
.
readLine
())
{
// we are interested in processor number as identifier for /proc/stat, physical id (the
// cpu the core belongs to) and the number of the core. However with hyperthreading
// multiple entries will have the same combination of physical id and core id. So we just
// count up the core number.
// count up the core number.
For mapping temperature both ids are still needed nonetheless.
const
int
delim
=
line
.
indexOf
(
":"
);
const
QByteArray
field
=
line
.
left
(
delim
).
trimmed
();
const
QByteArray
value
=
line
.
mid
(
delim
+
1
).
trimmed
();
...
...
@@ -98,12 +132,16 @@ LinuxCpuPluginPrivate::LinuxCpuPluginPrivate(CpuPlugin *q)
processor
=
value
.
toInt
();
}
else
if
(
field
==
"physical id"
)
{
physicalId
=
value
.
toInt
();
}
else
if
(
field
==
"core id"
)
{
coreId
=
value
.
toInt
();
}
else
if
(
field
==
"cpu MHz"
)
{
frequency
=
value
.
toDouble
();
}
}
const
QString
name
=
i18nc
(
"@title"
,
"CPU %1 Core %2"
).
arg
(
physicalId
+
1
).
arg
(
++
numCores
[
physicalId
]);
new
LinuxCpuObject
(
QStringLiteral
(
"cpu%1"
).
arg
(
processor
),
name
,
m_container
,
frequency
);
auto
cpu
=
new
LinuxCpuObject
(
QStringLiteral
(
"cpu%1"
).
arg
(
processor
),
name
,
m_container
,
frequency
);
qDebug
()
<<
physicalId
<<
coreId
<<
cpu
->
id
();
m_cpusBySystemIds
.
insert
({
physicalId
,
coreId
},
cpu
);
}
const
int
cores
=
m_container
->
objects
().
size
();
// Add total usage sensors
...
...
@@ -119,28 +157,6 @@ LinuxCpuPluginPrivate::LinuxCpuPluginPrivate(CpuPlugin *q)
addSensors
();
}
void
LinuxCpuPluginPrivate
::
addSensors
()
{
#ifdef HAVE_SENSORS
sensors_init
(
nullptr
);
int
number
=
0
;
while
(
sensors_chip_name
const
*
chipName
=
sensors_get_detected_chips
(
nullptr
,
&
number
))
{
char
name
[
100
];
sensors_snprintf_chip_name
(
name
,
100
,
chipName
);
qDebug
()
<<
name
<<
chipName
->
prefix
<<
"Bus("
<<
chipName
->
bus
.
nr
<<
chipName
->
bus
.
type
<<
")"
<<
chipName
->
addr
<<
chipName
->
path
;
int
featureNumber
=
0
;
while
(
sensors_feature
const
*
feature
=
sensors_get_features
(
chipName
,
&
featureNumber
))
{
qDebug
()
<<
'\t'
<<
feature
->
number
<<
sensors_get_label
(
chipName
,
feature
)
<<
feature
->
name
<<
feature
->
type
;
int
subfeatureNumber
=
0
;
while
(
sensors_subfeature
const
*
subfeature
=
sensors_get_all_subfeatures
(
chipName
,
feature
,
&
subfeatureNumber
))
{
qDebug
()
<<
"
\t\t
"
<<
subfeature
->
number
<<
subfeature
->
name
<<
subfeature
->
type
<<
subfeature
->
flags
<<
subfeature
->
mapping
;
}
}
}
#endif
}
void
LinuxCpuPluginPrivate
::
update
()
{
// Parse /proc/stat to get usage values. The format is described at
...
...
@@ -164,3 +180,58 @@ void LinuxCpuPluginPrivate::update()
cpu
->
update
(
system
+
irq
+
softirq
,
user
+
nice
,
iowait
+
steal
,
idle
);
}
}
void
LinuxCpuPluginPrivate
::
addSensors
()
{
#ifdef HAVE_SENSORS
sensors_init
(
nullptr
);
int
number
=
0
;
while
(
const
sensors_chip_name
*
const
chipName
=
sensors_get_detected_chips
(
nullptr
,
&
number
))
{
char
name
[
100
];
sensors_snprintf_chip_name
(
name
,
100
,
chipName
);
if
(
qstrcmp
(
chipName
->
prefix
,
"coretemp"
)
==
0
)
{
addSensorsIntel
(
chipName
);
}
}
#endif
}
// Documentation: https://www.kernel.org/doc/html/latest/hwmon/coretemp.html
void
LinuxCpuPluginPrivate
::
addSensorsIntel
(
const
sensors_chip_name
*
const
chipName
)
{
#ifdef HAVE_SENSORS
int
featureNumber
=
0
;
QHash
<
unsigned
int
,
sensors_feature
const
*>
coreFeatures
;
int
physicalId
=
-
1
;
while
(
sensors_feature
const
*
feature
=
sensors_get_features
(
chipName
,
&
featureNumber
))
{
const
char
*
const
sensorLabel
=
sensors_get_label
(
chipName
,
feature
);
unsigned
int
coreId
;
// First try to see if it's a core temperature because we should have more of those
if
(
std
::
sscanf
(
sensorLabel
,
"Core %d"
,
&
coreId
)
!=
0
)
{
coreFeatures
.
insert
(
coreId
,
feature
);
}
else
{
std
::
sscanf
(
sensorLabel
,
"Package id %d"
,
&
physicalId
);
}
}
if
(
physicalId
==
-
1
)
{
return
;
}
for
(
auto
feature
=
coreFeatures
.
cbegin
();
feature
!=
coreFeatures
.
cend
();
++
feature
)
{
if
(
m_cpusBySystemIds
.
contains
({
physicalId
,
feature
.
key
()}))
{
// When the cpu has hyperthreading we display multiple cores for each physical core.
// Naturally they share the same temperature sensor and have the same coreId.
auto
cpu_range
=
m_cpusBySystemIds
.
equal_range
({
physicalId
,
feature
.
key
()});
for
(
auto
cpu_it
=
cpu_range
.
first
;
cpu_it
!=
cpu_range
.
second
;
++
cpu_it
)
{
qDebug
()
<<
physicalId
<<
feature
.
key
()
<<
feature
.
value
()
->
name
;
(
*
cpu_it
)
->
setTemperatureSensor
(
chipName
,
feature
.
value
());
}
}
}
// int subfeatureNumber = 0;
// while (sensors_subfeature const * subfeature = sensors_get_all_subfeatures(chipName, feature, &subfeatureNumber)) {
// qDebug() << "\t\t" << subfeature->number << subfeature->name << subfeature->type << subfeature->flags << subfeature->mapping;
// }
// }
#endif
}
plugins/global/cpu/linuxcpu.h
View file @
bdeba27b
...
...
@@ -19,20 +19,29 @@
#ifndef LINUXCPU_H
#define LINUXCPU_H
#include
<QHash>
#include
"cpu.h"
#include
"cpuplugin_p.h"
struct
sensors_chip_name
;
struct
sensors_feature
;
class
LinuxCpuObject
:
public
CpuObject
{
public:
LinuxCpuObject
(
const
QString
&
id
,
const
QString
&
name
,
SensorContainer
*
parent
,
double
frequency
);
void
update
(
unsigned
long
long
system
,
unsigned
long
long
user
,
unsigned
long
long
wait
,
unsigned
long
long
idle
);
void
setTemperatureSensor
(
const
sensors_chip_name
*
const
chipName
,
const
sensors_feature
*
const
feature
);
private:
unsigned
long
long
m_totalTicks
;
unsigned
long
long
m_systemTicks
;
unsigned
long
long
m_userTicks
;
unsigned
long
long
m_waitTicks
;
const
sensors_chip_name
*
m_sensorChipName
;
int
m_temperatureSubfeature
;
};
class
LinuxCpuPluginPrivate
:
public
CpuPluginPrivate
{
...
...
@@ -41,6 +50,8 @@ public:
void
update
()
override
;
private:
void
addSensors
();
void
addSensorsIntel
(
const
sensors_chip_name
*
const
chipName
);
QMultiHash
<
QPair
<
unsigned
int
,
unsigned
int
>
,
LinuxCpuObject
*
const
>
m_cpusBySystemIds
;
};
#endif
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment