diff options
Diffstat (limited to 'src/hardware_cpu.cpp')
-rw-r--r-- | src/hardware_cpu.cpp | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/hardware_cpu.cpp b/src/hardware_cpu.cpp new file mode 100644 index 0000000..c05e3ec --- /dev/null +++ b/src/hardware_cpu.cpp @@ -0,0 +1,312 @@ + /************************************************************************** + * 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 <qdir.h> +#include <qtimer.h> + +// system header +#include <fcntl.h> + +/*! The default constructor of the class CPUInfo */ +CPUInfo::CPUInfo() { + kdDebugFuncIn(trace); + + update_info_cpufreq_speed_changed = true; + numOfCPUs = -1; + + 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() { + kdDebugFuncIn(trace); + + int cpu_id=0; + QDir tmp_dir; + QString cpu_path = "/sys/devices/system/cpu/cpu0/"; +#ifdef FAKE_CPU + cpu_path.prepend("/tmp/foo"); +#endif + + // let check if we support cpufreq in general + if (tmp_dir.exists(tmp_dir.absFilePath(cpu_path + "cpufreq/scaling_cur_freq", true))) { + cpuFreqHW = true; + } else { + cpuFreqHW = false; + } + + QString tmp_path = tmp_dir.absFilePath(cpu_path, true); + + while (tmp_dir.exists(tmp_path)) { + int tmp = cpu_id; + + cpu_id++; + cpu_path.replace(QString::number(tmp), QString::number(cpu_id)); + tmp_path = tmp_dir.absFilePath(cpu_path, true); + } + + kdDebug() << "getCPUNum() return: '" << cpu_id << "'" << endl; + kdDebugFuncOut(trace); + return cpu_id; +} + +/*! + * 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); + + bool speed_changed = false; + int new_value = -1; + int fd; + char buf[15]; + QString cpu_device = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"; +#ifdef FAKE_CPU + cpu_device.prepend("/tmp/foo"); +#endif + + // 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 = getCPUNum(); + + for (int cpu_id=0; cpu_id < numOfCPUs; cpu_id++) { + + new_value = -1; + + fd = open(cpu_device, O_RDONLY); + if (read(fd, buf, 14) > 0){ + new_value = strtol(buf, NULL, 10)/1000; + close(fd); + } + else{ + close(fd); + speed_changed = true; + // CPU disabeld -> set Freq to -1 + cpufreq_speed.append(-1); + } + + if (new_value != cpufreq_speed[cpu_id]) { + speed_changed = true; + cpufreq_speed.append(new_value); + } + + cpu_device.replace(QString::number(cpu_id), QString::number(cpu_id+1)); + } + + 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); + + QString cpu_file = "/proc/cpuinfo"; +#ifdef FAKE_CPU + cpu_file.prepend("/tmp/foo"); +#endif + QFile cpu_info(cpu_file); + + // clear cpufreq list + cpufreq_speed.clear(); + + if ( !cpu_info.open(IO_ReadOnly) ) { + cpu_info.close(); + kdDebugFuncOut(trace); + return -1; + } + + QTextStream stream( &cpu_info ); + QString 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; + QFileInfo *fi; + QString cpu_dirname; + QString dir_acpi_processor = "/proc/acpi/processor/"; +#ifdef FAKE_CPU + dir_acpi_processor.prepend("/tmp/foo"); +#endif + + QDir d_throttling(dir_acpi_processor); + if (!d_throttling.exists()) { + kdDebugFuncOut(trace); + return false; + } + + d_throttling.setFilter( QDir::Dirs ); + d_throttling.setNameFilter("CPU*"); + + const QFileInfoList *list = d_throttling.entryInfoList(); + QFileInfoListIterator it( *list ); + + // clear throttling value list + cpu_throttling.clear(); + + while ((fi = it.current()) != 0 ) { + cpu_dirname = fi->fileName(); + + QString 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; + + QFile throttling(throttling_device); + + // open throttling state file + if ( throttling.open(IO_ReadOnly) ) { + QTextStream stream( &throttling ); + QString 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); + + int fd; + int maxfreq; + char buf[15]; + QString cpu_device_max = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"; +#ifdef FAKE_CPU + cpu_device_max.prepend("/tmp/foo"); +#endif + + cpufreq_max_speed.clear(); + + if (numOfCPUs == -1) + numOfCPUs = getCPUNum(); + +// while (!access(cpu_device_max, R_OK)) { + for (int cpu_id=0; cpu_id < numOfCPUs; cpu_id++) { + + fd = open(cpu_device_max, O_RDONLY); + if (read(fd, buf, 14) > 0){ + maxfreq = strtol(buf, NULL, 10)/1000; + cpufreq_max_speed.append(maxfreq); + close(fd); + } else { + cpufreq_max_speed.append(-1); + close(fd); + } + + cpu_device_max.replace(QString::number(cpu_id), QString::number(cpu_id+1)); + } + + kdDebugFuncOut(trace); +} |