"Fossies" - the Fresh Open Source Software Archive 
Member "xosview-1.23/linux/coretemp.cc" (11 Jul 2020, 11388 Bytes) of package /linux/misc/xosview-1.23.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "coretemp.cc" see the
Fossies "Dox" file reference documentation.
1 //
2 // Copyright (c) 2008-2014 by Tomi Tapper <tomi.o.tapper@jyu.fi>
3 //
4 // Read CPU temperature readings from /sys and display actual temperature.
5 // If actual >= high, actual temp changes color to indicate alarm.
6 //
7 // File based on linux/lmstemp.* by
8 // Copyright (c) 2000, 2006 by Leopold Toetsch <lt@toetsch.at>
9 //
10 // This file may be distributed under terms of the GPL
11 //
12 //
13
14 #include "coretemp.h"
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <glob.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <dirent.h>
22 #include <fstream>
23 #include <iostream>
24 #include <string>
25
26 #define PATH_SIZE 128
27
28 static const char SYS_HWMON[] = "/sys/class/hwmon";
29 static const char SYS_CORETEMP[] = "/sys/devices/platform/coretemp";
30 static const char SYS_VIATEMP[] = "/sys/devices/platform/via_cputemp";
31
32
33 CoreTemp::CoreTemp( XOSView *parent, const char *label, const char *caption, int pkg, int cpu )
34 : FieldMeter( parent, 3, label, caption, 1, 1, 1 ), _pkg(pkg), _cpu(cpu) {
35 metric_ = true;
36 _high = 0;
37 }
38
39 CoreTemp::~CoreTemp( void ) {
40
41 }
42
43 void CoreTemp::checkResources( void ) {
44 FieldMeter::checkResources();
45
46 _actcolor = parent_->allocColor( parent_->getResource( "coretempActColor" ) );
47 _highcolor = parent_->allocColor( parent_->getResource( "coretempHighColor") );
48 setfieldcolor( 0, _actcolor );
49 setfieldcolor( 1, parent_->getResource( "coretempIdleColor") );
50 setfieldcolor( 2, _highcolor );
51 priority_ = atoi( parent_->getResource( "coretempPriority" ) );
52 SetUsedFormat( parent_->getResource( "coretempUsedFormat" ) );
53
54 findSysFiles();
55 if ( _cpus.empty() ) { // should not happen at this point
56 std::cerr << "BUG: Could not determine sysfs file(s) for coretemp." << std::endl;
57 parent_->done(1);
58 }
59
60 // Get TjMax and use it for total, if available.
61 // Not found on k8temp and via-cputemp.
62 std::ifstream file;
63 std::string dummy = _cpus.front();
64 dummy.replace(dummy.find_last_of('_'), 6, "_crit");
65 file.open(dummy.c_str());
66 if ( file.good() ) {
67 file >> total_;
68 file.close();
69 total_ /= 1000.0;
70 }
71 else
72 total_ = atoi( parent_->getResourceOrUseDefault("coretempHighest", "100") );
73
74 // Use tTarget/tCtl (when maximum cooling needs to be turned on) as high,
75 // if found. On older Cores this MSR is empty and kernel sets this equal to
76 // tjMax. Not found on k8temp and via-cputemp. On k10temp this is fixed value.
77 char l[32];
78 dummy = _cpus.front();
79 dummy.replace(dummy.find_last_of('_'), 6, "_max");
80 file.open(dummy.c_str());
81 if ( file.good() ) {
82 file >> _high;
83 file.close();
84 _high /= 1000.0;
85 snprintf(l, 32, "ACT(\260C)/%d/%d", (int)_high, (int)total_);
86 }
87 else
88 _high = total_;
89
90 if (_high == total_) { // No tTarget/tCtl
91 // Use user-defined high, or "no high".
92 const char *high = parent_->getResourceOrUseDefault("coretempHigh", NULL);
93 if (high) {
94 _high = atoi(high);
95 snprintf(l, 32, "ACT(\260C)/%d/%d", (int)_high, (int)total_);
96 }
97 else
98 snprintf(l, 32, "ACT(\260C)/HIGH/%d", (int)total_);
99 }
100 legend(l);
101 }
102
103 /* Find absolute paths of files to be used. */
104 void CoreTemp::findSysFiles( void ) {
105 int cpu = 0;
106 unsigned int i = 0, cpucount = countCores(_pkg);
107 char name[PATH_SIZE];
108 std::string dummy;
109 std::ifstream file;
110 glob_t gbuf;
111 DIR *dir;
112 struct dirent *dent;
113 struct stat buf;
114
115 // Intel and VIA CPUs.
116 // Platform device sysfs node changed in kernel 3.15 -> try both paths.
117 snprintf(name, PATH_SIZE, "%s.%d/temp*_label", SYS_CORETEMP, _pkg);
118 glob(name, 0, NULL, &gbuf);
119 snprintf(name, PATH_SIZE, "%s.%d/hwmon/hwmon*/temp*_label", SYS_CORETEMP, _pkg);
120 glob(name, GLOB_APPEND, NULL, &gbuf);
121 snprintf(name, PATH_SIZE, "%s.%d/temp*_label", SYS_VIATEMP, _pkg);
122 glob(name, GLOB_APPEND, NULL, &gbuf);
123 snprintf(name, PATH_SIZE, "%s.%d/hwmon/hwmon*/temp*_label", SYS_VIATEMP, _pkg);
124 glob(name, GLOB_APPEND, NULL, &gbuf);
125 for (i = 0; i < gbuf.gl_pathc; i++) {
126 file.open(gbuf.gl_pathv[i]);
127 file >> dummy >> cpu; // "Core n" or "Physical id n"
128 file.close();
129 if ( strncmp(dummy.c_str(), "Core", 4) == 0 ) {
130 strcpy(strrchr(gbuf.gl_pathv[i], '_'), "_input");
131 if (_cpu < 0 || cpu == _cpu)
132 _cpus.push_back(gbuf.gl_pathv[i]);
133 }
134 }
135 globfree(&gbuf);
136 if ( !_cpus.empty() )
137 return;
138
139 // AMD CPUs.
140 if ( !(dir = opendir(SYS_HWMON)) ) {
141 std::cerr << "Can not open " << SYS_HWMON << " directory." << std::endl;
142 parent_->done(1);
143 return;
144 }
145 while ( (dent = readdir(dir)) ) {
146 if ( !strncmp(dent->d_name, ".", 1) ||
147 !strncmp(dent->d_name, "..", 2) )
148 continue;
149
150 snprintf(name, PATH_SIZE, "%s/%s/name", SYS_HWMON, dent->d_name);
151 file.open(name);
152 if (!file) {
153 // Older kernels place the name in device directory.
154 snprintf(name, PATH_SIZE, "%s/%s/device/name", SYS_HWMON, dent->d_name);
155 file.open(name);
156 if (!file)
157 continue;
158 }
159 file >> dummy;
160 file.close();
161
162 if ( strncmp(dummy.c_str(), "k8temp", 6) == 0 ||
163 strncmp(dummy.c_str(), "k10temp", 7) == 0 ) {
164 if (cpu++ != _pkg)
165 continue;
166 // K8 core has two sensors with index starting from 1
167 // K10 has only one sensor per physical CPU
168 if (_cpu < 0) { // avg or max
169 for (i = 1; i <= cpucount; i++) {
170 snprintf(name, PATH_SIZE, "%s/%s/temp%d_input",
171 SYS_HWMON, dent->d_name, i);
172 if (!( stat(name, &buf) == 0 && S_ISREG(buf.st_mode) ))
173 snprintf(name, PATH_SIZE, "%s/%s/device/temp%d_input",
174 SYS_HWMON, dent->d_name, i);
175 _cpus.push_back(name);
176 }
177 }
178 else { // single sensor
179 snprintf(name, PATH_SIZE, "%s/%s/temp%d_input",
180 SYS_HWMON, dent->d_name, _cpu + 1);
181 if (!( stat(name, &buf) == 0 && S_ISREG(buf.st_mode) ))
182 snprintf(name, PATH_SIZE, "%s/%s/device/temp%d_input",
183 SYS_HWMON, dent->d_name, i);
184 _cpus.push_back(name);
185 }
186 }
187 }
188 closedir(dir);
189 }
190
191 void CoreTemp::checkevent( void ) {
192 getcoretemp();
193 drawfields();
194 }
195
196 void CoreTemp::getcoretemp( void ) {
197 std::ifstream file;
198 double dummy;
199 fields_[0] = 0.0;
200
201 if (_cpu >= 0) { // only one core
202 file.open(_cpus.back().c_str());
203 if (!file) {
204 std::cerr << "Can not open file : " << _cpus.back().c_str() << std::endl;
205 parent_->done(1);
206 return;
207 }
208 file >> fields_[0];
209 file.close();
210 }
211 else if (_cpu == -1) { // average
212 for (uint i = 0; i < _cpus.size(); i++) {
213 file.open(_cpus[i].c_str());
214 if (!file) {
215 std::cerr << "Can not open file : " << _cpus[i].c_str() << std::endl;
216 parent_->done(1);
217 return;
218 }
219 file >> dummy;
220 file.close();
221 fields_[0] += dummy;
222 }
223 fields_[0] /= (double)_cpus.size();
224 }
225 else if (_cpu == -2) { // maximum
226 for (uint i = 0; i < _cpus.size(); i++) {
227 file.open(_cpus[i].c_str());
228 if (!file) {
229 std::cerr << "Can not open file : " << _cpus[i].c_str() << std::endl;
230 parent_->done(1);
231 return;
232 }
233 file >> dummy;
234 file.close();
235 if (dummy > fields_[0])
236 fields_[0] = dummy;
237 }
238 }
239 else { // should not happen
240 std::cerr << "Unknown CPU core number " << _cpu << " in coretemp." << std::endl;
241 parent_->done(1);
242 return;
243 }
244
245 fields_[0] /= 1000.0;
246 setUsed( fields_[0], total_ );
247
248 if (fields_[0] < 0)
249 fields_[0] = 0.0;
250 fields_[1] = _high - fields_[0];
251 if (fields_[1] < 0) { // alarm: T > high
252 fields_[1] = 0;
253 if (colors_[0] != _highcolor) {
254 setfieldcolor( 0, _highcolor );
255 drawlegend();
256 }
257 }
258 else {
259 if (colors_[0] != _actcolor) {
260 setfieldcolor( 0, _actcolor );
261 drawlegend();
262 }
263 }
264
265 fields_[2] = total_ - fields_[1] - fields_[0];
266 if (fields_[2] < 0)
267 fields_[2] = 0;
268 }
269
270 /* Count sensors available to coretemp in the given package. */
271 unsigned int CoreTemp::countCores( unsigned int pkg )
272 {
273 glob_t gbuf;
274 char s[PATH_SIZE];
275 unsigned int i, count = 0, cpu = 0;
276 DIR *dir;
277 struct dirent *dent;
278 struct stat buf;
279 std::string dummy;
280 std::ifstream file;
281
282 // Intel or VIA CPU.
283 // Platform device sysfs node changed in kernel 3.15 -> try both paths.
284 snprintf(s, PATH_SIZE, "%s.%d/temp*_label", SYS_CORETEMP, pkg);
285 glob(s, 0, NULL, &gbuf);
286 snprintf(s, PATH_SIZE, "%s.%d/hwmon/hwmon*/temp*_label", SYS_CORETEMP, pkg);
287 glob(s, GLOB_APPEND, NULL, &gbuf);
288 snprintf(s, PATH_SIZE, "%s.%d/temp*_label", SYS_VIATEMP, pkg);
289 glob(s, GLOB_APPEND, NULL, &gbuf);
290 snprintf(s, PATH_SIZE, "%s.%d/hwmon/hwmon*/temp*_label", SYS_VIATEMP, pkg);
291 glob(s, GLOB_APPEND, NULL, &gbuf);
292 // loop through paths in gbuf and check if it is a core or package
293 for (i = 0; i < gbuf.gl_pathc; i++) {
294 file.open(gbuf.gl_pathv[i]);
295 file >> dummy;
296 file.close();
297 if ( strncmp(dummy.c_str(), "Core", 4) == 0 )
298 count++;
299 }
300 globfree(&gbuf);
301 if (count > 0)
302 return count;
303
304 // AMD CPU.
305 if ( !(dir = opendir(SYS_HWMON)) )
306 return 0;
307 // loop through hwmon devices and when AMD sensor is found, count its inputs
308 while ( (dent = readdir(dir)) ) {
309 if ( !strncmp(dent->d_name, ".", 1) ||
310 !strncmp(dent->d_name, "..", 2) )
311 continue;
312 snprintf(s, PATH_SIZE, "%s/%s/name", SYS_HWMON, dent->d_name);
313 if (!( stat(s, &buf) == 0 && S_ISREG(buf.st_mode) ))
314 // Older kernels place the name in device directory.
315 snprintf(s, PATH_SIZE, "%s/%s/device/name", SYS_HWMON, dent->d_name);
316
317 file.open(s);
318 if ( file.good() ) {
319 file >> dummy;
320 file.close();
321 if ( strncmp(dummy.c_str(), "k8temp", 6) == 0 ||
322 strncmp(dummy.c_str(), "k10temp", 7) == 0 ) {
323 if (cpu++ < pkg)
324 continue;
325 snprintf(s, PATH_SIZE, "%s/%s/temp*_input", SYS_HWMON, dent->d_name);
326 glob(s, 0, NULL, &gbuf);
327 snprintf(s, PATH_SIZE, "%s/%s/device/temp*_input", SYS_HWMON, dent->d_name);
328 glob(s, GLOB_APPEND, NULL, &gbuf);
329 count += gbuf.gl_pathc;
330 globfree(&gbuf);
331 }
332 }
333 }
334 closedir(dir);
335 return count;
336 }
337
338 /* Count physical CPUs with sensors. */
339 unsigned int CoreTemp::countCpus( void )
340 {
341 glob_t gbuf;
342 char s[PATH_SIZE];
343 unsigned int count = 0;
344 DIR *dir;
345 struct dirent *dent;
346 struct stat buf;
347 std::string dummy;
348 std::ifstream file;
349
350 // Count Intel and VIA packages.
351 snprintf(s, PATH_SIZE, "%s.*", SYS_CORETEMP);
352 glob(s, 0, NULL, &gbuf);
353 snprintf(s, PATH_SIZE, "%s.*", SYS_VIATEMP);
354 glob(s, GLOB_APPEND, NULL, &gbuf);
355 count += gbuf.gl_pathc;
356 globfree(&gbuf);
357 if (count > 0)
358 return count;
359
360 // Count AMD packages.
361 if ( !(dir = opendir(SYS_HWMON)) )
362 return 0;
363 while ( (dent = readdir(dir)) ) {
364 if ( !strncmp(dent->d_name, ".", 1) ||
365 !strncmp(dent->d_name, "..", 2) )
366 continue;
367 snprintf(s, PATH_SIZE, "%s/%s/name", SYS_HWMON, dent->d_name);
368 if (!( stat(s, &buf) == 0 && S_ISREG(buf.st_mode) ))
369 // Older kernels place the name in device directory.
370 snprintf(s, PATH_SIZE, "%s/%s/device/name", SYS_HWMON, dent->d_name);
371 file.open(s);
372 if ( file.good() ) {
373 file >> dummy;
374 file.close();
375 if ( strncmp(dummy.c_str(), "k8temp", 6) == 0 ||
376 strncmp(dummy.c_str(), "k10temp", 7) == 0 )
377 count++;
378 }
379 }
380 closedir(dir);
381 return count;
382 }