You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepowersave/src/hardware_cpu.cpp

291 lines
7.9 KiB

/**************************************************************************
* 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
*/
// 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);
}