/************************************************************************** * Copyright (C) 2006 by Daniel Gollub * * * * Danny Kukawka * * , * * * * 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, , * \author Daniel Gollub, * \author * \date 2006 */ // include own header #include "hardware_cpu.h" #include "hardware_cpu.moc" // QT Header #include #include // system header #include #include /*! 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; TQDir tmp_dir; TQString 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; } TQString tmp_path = tmp_dir.absFilePath(cpu_path, true); while (tmp_dir.exists(tmp_path)) { int tmp = cpu_id; cpu_id++; cpu_path.replace(TQString::number(tmp), TQString::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]; TQString 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.ascii(), 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(TQString::number(cpu_id), TQString::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); 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); int fd; int maxfreq; char buf[15]; TQString 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.ascii(), 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(TQString::number(cpu_id), TQString::number(cpu_id+1)); } kdDebugFuncOut(trace); }