|
|
|
/**************************************************************************
|
|
|
|
* Copyright (C) 2006 by Daniel Gollub *
|
|
|
|
* <dgollub@suse.de> *
|
|
|
|
* Danny Kukawka *
|
|
|
|
* <dkukawka@suse.de>, <danny.kukawka@web.de> *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of version 2 of the GNU General Public License *
|
|
|
|
* as published by the Free Software Foundation. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \file hardware_cpu.cpp
|
|
|
|
* \brief In this file can be found the CPU information related code.
|
|
|
|
* \author Danny Kukawka, <dkukawka@suse.de>, <danny.kukawka@web.de>
|
|
|
|
* \author Daniel Gollub, <dgollub@suse.de>
|
|
|
|
* \author
|
|
|
|
* \date 2006
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// include own header
|
|
|
|
#include "hardware_cpu.h"
|
|
|
|
#include "hardware_cpu.moc"
|
|
|
|
|
|
|
|
// QT Header
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
|
|
|
|
// system header
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
/*! The default constructor of the class CPUInfo */
|
|
|
|
CPUInfo::CPUInfo() {
|
|
|
|
kdDebugFuncIn(trace);
|
|
|
|
|
|
|
|
update_info_cpufreq_speed_changed = true;
|
|
|
|
numOfCPUs = -1;
|
|
|
|
|
|
|
|
m_hwdevices = TDEGlobal::hardwareDevices();
|
|
|
|
m_hwdevices->setBatteryUpdatesEnabled(true);
|
|
|
|
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! The default desctuctor of the class CPUInfo */
|
|
|
|
CPUInfo::~CPUInfo() {
|
|
|
|
kdDebugFuncIn(trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* This function counts all online/offline CPUS.
|
|
|
|
* Returns the total count of CPUs - _not_ the last CPU ID!
|
|
|
|
*/
|
|
|
|
int CPUInfo::getCPUNum() {
|
|
|
|
TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::CPU);
|
|
|
|
return hwlist.count();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* The function checks the current CPU Speed. The current cpu speed needs to be read out from
|
|
|
|
* sysfs and currently not be obtained through the daemon. If the CPUFreg changed the new value
|
|
|
|
* is set to \ref cpufreq_speed .
|
|
|
|
* \return Information if something changed or if there are errors as an interger value
|
|
|
|
* \retval -1 if there are error by reading from /sys/..
|
|
|
|
* \retval 0 if nothing changed
|
|
|
|
* \retval 1 if something changed
|
|
|
|
*/
|
|
|
|
int CPUInfo::checkCPUSpeed(){
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
|
|
|
|
TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::CPU);
|
|
|
|
|
|
|
|
bool speed_changed = false;
|
|
|
|
int new_value = -1;
|
|
|
|
|
|
|
|
// first check path for the kernel on-demand-govenour then
|
|
|
|
// for the use userspace case
|
|
|
|
update_info_cpufreq_speed_changed = false;
|
|
|
|
cpufreq_speed.clear();
|
|
|
|
|
|
|
|
if (numOfCPUs == -1) {
|
|
|
|
numOfCPUs = hwlist.count();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int cpu_id=0; cpu_id < numOfCPUs; cpu_id++) {
|
|
|
|
TDECPUDevice* cdevice = NULL;
|
|
|
|
TDEGenericDevice *hwdevice;
|
|
|
|
for (hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next()) {
|
|
|
|
TDECPUDevice* possiblecpu = static_cast<TDECPUDevice*>(hwdevice);
|
|
|
|
if (possiblecpu) {
|
|
|
|
if (possiblecpu->coreNumber() == cpu_id) {
|
|
|
|
cdevice = possiblecpu;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
new_value = -1;
|
|
|
|
|
|
|
|
if (cdevice) {
|
|
|
|
new_value = cdevice->frequency();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
speed_changed = true;
|
|
|
|
// CPU disabled -> set Freq to -1
|
|
|
|
cpufreq_speed.append(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_value != cpufreq_speed[cpu_id]) {
|
|
|
|
speed_changed = true;
|
|
|
|
cpufreq_speed.append(new_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (speed_changed) {
|
|
|
|
update_info_cpufreq_speed_changed = true;
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* The function checks the Speed of throttling CPU(s). The cpu speed needs to be read out from
|
|
|
|
* /proc/cpuinfo.
|
|
|
|
* \return Success or error while reading /proc/cpuinfo
|
|
|
|
* \retval 0 successful
|
|
|
|
* \retval -1 reading problem
|
|
|
|
*/
|
|
|
|
int CPUInfo::checkCPUSpeedThrottling() {
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
|
|
|
|
TQString cpu_file = "/proc/cpuinfo";
|
|
|
|
#ifdef FAKE_CPU
|
|
|
|
cpu_file.prepend("/tmp/foo");
|
|
|
|
#endif
|
|
|
|
TQFile cpu_info(cpu_file);
|
|
|
|
|
|
|
|
// clear cpufreq list
|
|
|
|
cpufreq_speed.clear();
|
|
|
|
|
|
|
|
if ( !cpu_info.open(IO_ReadOnly) ) {
|
|
|
|
cpu_info.close();
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQTextStream stream( &cpu_info );
|
|
|
|
TQString line;
|
|
|
|
|
|
|
|
while ( !stream.atEnd() ) {
|
|
|
|
line = stream.readLine();
|
|
|
|
|
|
|
|
if (line.startsWith("cpu MHz : ")) {
|
|
|
|
line.remove("cpu MHz : ");
|
|
|
|
line = line.remove(line.length() - 4, 4);
|
|
|
|
cpufreq_speed.append(line.toInt());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((int) cpufreq_speed.count() < numOfCPUs) {
|
|
|
|
cpufreq_speed.append(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
cpu_info.close();
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* The function gets the current throttling state of the CPU(s). The throttling state needs to be
|
|
|
|
* read out from /proc/acpi/processor/CPUX/throttling.
|
|
|
|
* \return boolean with info if throttling is supported
|
|
|
|
* \retval true if throttling is supported
|
|
|
|
* \retval false if not supported or on any other error
|
|
|
|
*/
|
|
|
|
bool CPUInfo::getCPUThrottlingState() {
|
|
|
|
kdDebugFuncIn(trace);
|
|
|
|
|
|
|
|
int id = 0;
|
|
|
|
TQFileInfo *fi;
|
|
|
|
TQString cpu_dirname;
|
|
|
|
TQString dir_acpi_processor = "/proc/acpi/processor/";
|
|
|
|
#ifdef FAKE_CPU
|
|
|
|
dir_acpi_processor.prepend("/tmp/foo");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TQDir d_throttling(dir_acpi_processor);
|
|
|
|
if (!d_throttling.exists()) {
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
d_throttling.setFilter( TQDir::Dirs );
|
|
|
|
d_throttling.setNameFilter("CPU*");
|
|
|
|
|
|
|
|
const TQFileInfoList *list = d_throttling.entryInfoList();
|
|
|
|
TQFileInfoListIterator it( *list );
|
|
|
|
|
|
|
|
// clear throttling value list
|
|
|
|
cpu_throttling.clear();
|
|
|
|
|
|
|
|
while ((fi = it.current()) != 0 ) {
|
|
|
|
cpu_dirname = fi->fileName();
|
|
|
|
|
|
|
|
TQString throttling_device = d_throttling.absPath();
|
|
|
|
throttling_device.append("/").append(cpu_dirname).append("/throttling");
|
|
|
|
|
|
|
|
kdDebug() << "Throttling state file for CPU" << id << " will be: " << throttling_device << endl;
|
|
|
|
|
|
|
|
TQFile throttling(throttling_device);
|
|
|
|
|
|
|
|
// open throttling state file
|
|
|
|
if ( throttling.open(IO_ReadOnly) ) {
|
|
|
|
TQTextStream stream( &throttling );
|
|
|
|
TQString line;
|
|
|
|
|
|
|
|
do {
|
|
|
|
line = stream.readLine();
|
|
|
|
} while (!line.startsWith(" *T") && !stream.atEnd() );
|
|
|
|
|
|
|
|
if (line.startsWith(" *T")) {
|
|
|
|
line = line.right(3);
|
|
|
|
line.remove("%");
|
|
|
|
cpu_throttling.append(line.toInt());
|
|
|
|
kdDebug () << "CPU " << id
|
|
|
|
<< ": cpu_throttling is set to: " << cpu_throttling[id] << endl;
|
|
|
|
} else {
|
|
|
|
cpu_throttling.append(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throttling.close();
|
|
|
|
++it; // next entry
|
|
|
|
id++; // count cpu id
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* The function gets the Max CPU Speed. The max cpu speed needs to be read out from
|
|
|
|
* sysfs and currently not be obtained through the daemon.
|
|
|
|
*/
|
|
|
|
void CPUInfo::getCPUMaxSpeed() {
|
|
|
|
kdDebugFuncIn(trace);
|
|
|
|
|
|
|
|
TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::CPU);
|
|
|
|
|
|
|
|
cpufreq_max_speed.clear();
|
|
|
|
|
|
|
|
if (numOfCPUs == -1) {
|
|
|
|
numOfCPUs = getCPUNum();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int cpu_id=0; cpu_id < numOfCPUs; cpu_id++) {
|
|
|
|
TDECPUDevice* cdevice = NULL;
|
|
|
|
TDEGenericDevice *hwdevice;
|
|
|
|
for (hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next()) {
|
|
|
|
TDECPUDevice* possiblecpu = static_cast<TDECPUDevice*>(hwdevice);
|
|
|
|
if (possiblecpu) {
|
|
|
|
if (possiblecpu->coreNumber() == cpu_id) {
|
|
|
|
cdevice = possiblecpu;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cdevice) {
|
|
|
|
cpufreq_max_speed.append(cdevice->maxFrequency());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cpufreq_max_speed.append(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
}
|