File: cpu.cpp

package info (click to toggle)
powersave 0.15.20-3
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 4,360 kB
  • ctags: 610
  • sloc: sh: 10,767; cpp: 5,264; ansic: 1,495; makefile: 342
file content (149 lines) | stat: -rw-r--r-- 2,868 bytes parent folder | download
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
#include "cpu.h"
#include "powerlib.h"

#include <sstream>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#define SYSFS_FILES "/sys/devices/system/cpu/"

using namespace std;

CPU::CPU(int id) : _cpu_base(id)
{
	ostringstream strstr;
	strstr << SYSFS_FILES << "cpu" << _cpu_base << "/online";
	ONLINE_FILE = strstr.str();
}

int CPU::enable()
{
	if (online())
		return 0;

	pDebug(DBG_INFO, "Trying to enable CPU %d", _cpu_base);
	if (!write_line(ONLINE_FILE.c_str(), "1")) {
		pDebug(DBG_DEBUG, "Unable to open file: %s\n", ONLINE_FILE.c_str());
		return -1;
	}
	
	pDebug(DBG_INFO, "Set CPU %d online", _cpu_base);

	if (!online()) {
		pDebug(DBG_WARN, "Onlined CPU, but request was not accepted: %s\n",
		       ONLINE_FILE.c_str());
		return -1;
	}

	return 1;
}

int CPU::disable()
{
	if (!online())
		return 0;

	if (_cpu_base == 0) {
		pDebug(DBG_DEBUG, "CPU 0 can't be offlined.");
		return -1;
	}
	
	pDebug(DBG_INFO, "Trying to disable CPU %d", _cpu_base);
	if (!write_line(ONLINE_FILE.c_str(), "0")) {
		pDebug(DBG_DEBUG, "Unable to open file: %s\n",
		       ONLINE_FILE.c_str());
		return -1;
	}

	pDebug(DBG_INFO, "Set CPU %d offline", _cpu_base);
	if (online()) {
		pDebug(DBG_WARN, "Offlined CPU, but request was not accepted: %s\n",
		       ONLINE_FILE.c_str());
		return -1;
	}

	return 1;
}

bool CPU::online()
{
	if (!hotpluggable())
		return true;

	char online_str[2];

	if (!read_line(ONLINE_FILE.c_str(), online_str, 2)) {
		pDebug(DBG_DEBUG, "Unable to open file: %s\n", ONLINE_FILE.c_str());
		return false;
	}
	
	int online = atoi(online_str);

	if (!online)
		return false;
	
	return true;
}

bool CPU::hotpluggable()
{
	if (access(ONLINE_FILE.c_str(), F_OK) < 0)
		return false;
	return true;
}

int CPU::enableAll()
{
	// start with CPU 1, because CPU 0 is always online atm
	int i = 1;

	while (true) {
		CPU cpu(i);
		if (!cpu.hotpluggable())
			break;
		cpu.enable();
		i++;
	} 

	pDebug(DBG_DEBUG, "Found %d hotpluggable CPUs in system", i);
	return i;
}


bool CPU::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 CPU::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;
}