1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
/***************************************************************************
* *
* Powersave Daemon *
* *
* Copyright (C) 2004,2005,2006 SUSE Linux Products GmbH *
* *
* Author(s): Holger Macht <hmacht@suse.de> *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License, or (at you *
* option) any later version. *
* *
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA *
* *
***************************************************************************/
#include <sstream>
#include "powerlib.h"
#include "cpufreq_interface.h"
#include "config_pm.h"
#include "cpu.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#ifdef CPUFREQ_MEASURE
unsigned long CPUFreq_Interface::polling_interval = 333;
time_t *CPUFreq_Interface::start_time = NULL;
#define MEASURE_LOG_FILE "/tmp/cpufreq.log"
#endif
CPUFreq_Interface::CPUFreq_Interface(list< int > cpu_list)
: CPU(*(cpu_list.begin()))
{
_cpu_cores = cpu_list;
// initialise variables
_cpu_max = 90;
_cpu_hysteresis = 5;
_high_cpu_limit = 0;
_consider_nice = 1;
_mode = _DYNAMIC;
ostringstream strstr;
strstr << SYSFS_FILES << "cpu" << _cpu_base << "/cpufreq/scaling_min_freq";
MIN_SPEED_FILE = strstr.str();
strstr.str("");
strstr << SYSFS_FILES << "cpu" << _cpu_base << "/cpufreq/scaling_max_freq";
MAX_SPEED_FILE = strstr.str();
strstr.str("");
strstr << SYSFS_FILES << "cpu" << _cpu_base << "/cpufreq/scaling_governor";
GOVERNOR_FILE = strstr.str();
strstr.str("");
strstr << SYSFS_FILES << "cpu" << _cpu_base << "/cpufreq/scaling_available_frequencies";
AVAILABLE_FREQS_FILE = strstr.str();
strstr.str("");
}
CPUFreq_Interface::~CPUFreq_Interface()
{
}
int CPUFreq_Interface::setMode(CPUFREQ_MODE mode)
{
_mode = mode;
if (online())
adjustSpeed();
return 0;
}
void CPUFreq_Interface::setConfigs(int max, int high_cpu, int hyster, int consider)
{
if (max < _cpu_hysteresis)
_cpu_max = _cpu_hysteresis;
else
_cpu_max = max;
int num_cpus = getCPUCount();
_cpu_max = max / num_cpus;
if (_cpu_max < 20)
_cpu_max = 20;
pDebug(DBG_INFO, "Adjusting CPU_HIGH_LIMIT depending on number of CPUs: "
"number of CPUs: %d, old CPU_HIGH_LIMIT: %d, new CPU_HIGH_LIMIT: %d",
num_cpus, max, _cpu_max);
if (high_cpu <= 0 || high_cpu > 100)
_high_cpu_limit = 0;
else
_high_cpu_limit = high_cpu;
if (hyster < 0)
_cpu_hysteresis = 5;
else
_cpu_hysteresis = hyster;
_consider_nice = consider;
if (online())
setConfig();
}
CPUFREQ_MODE CPUFreq_Interface::getMode()
{
return _mode;
}
int CPUFreq_Interface::setGovernor(const string &new_governor)
{
if (!online())
return 0;;
char governor[MAX_LINE_SIZE + 1];
if (!write_line(GOVERNOR_FILE.c_str(), "%s\n", new_governor.c_str()))
return -1;
// check if governor has been set
usleep(1000);
read_line(GOVERNOR_FILE.c_str(), governor, MAX_LINE_SIZE);
if (strstr(governor, new_governor.c_str()))
return 0;
else
return -1;
}
bool CPUFreq_Interface::read_line(const char *filename, char *line, unsigned len)
{
FILE *fp = fopen(filename, "r");
if (!fp) {
pDebug(DBG_ERR, "Could not open '%s': %s", filename, strerror(errno));
return false;
}
if ((!fgets(line, len, fp))) {
pDebug(DBG_ERR, "Could not read from '%s': %s", filename, strerror(errno));
fclose(fp);
return false;
}
fclose(fp);
return true;
}
bool CPUFreq_Interface::write_line(const char *filename, const char *fmt, ...)
{
FILE *fp = fopen(filename, "w+");
if (!fp) {
pDebug(DBG_WARN, "Could not open file for writing: %s; %s", filename, strerror(errno));
return false;
}
va_list ap;
va_start(ap, fmt); // get variable argument list passed
if (vfprintf(fp, fmt, ap) < 0) {
pDebug(DBG_WARN, "Could not write to file: %s", filename);
fclose(fp);
return false;
}
va_end(ap);
fclose(fp);
return true;
}
unsigned CPUFreq_Interface::read_value(const char *filename)
{
char line[MAX_LINE_SIZE];
if (!read_line(filename, line, sizeof line)) {
// we already throw an error in read_line()
return 0;
} else {
pDebug(DBG_INFO, "Value '%s' read from %s", line, filename);
return atoi(line);
}
}
|