"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 }