"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.13.05/core-thermal-zone.c" (11 Oct 2021, 6617 Bytes) of package /linux/privat/stress-ng-0.13.05.tar.xz:


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 "core-thermal-zone.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.13.04_vs_0.13.05.

    1 /*
    2  * Copyright (C) 2013-2021 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 #if defined(STRESS_THERMAL_ZONES)
   28 
   29 /*
   30  *  stress_tz_type_instance()
   31  *  return the number of existing occurrences of
   32  *  a named type in the tz_info_list.
   33  */
   34 static uint32_t stress_tz_type_instance(
   35     stress_tz_info_t *tz_info_list,
   36     const char *type)
   37 {
   38     stress_tz_info_t *tz_info;
   39     uint32_t type_instance = 0;
   40 
   41     if (!type)
   42         return 0;
   43 
   44     for (tz_info = tz_info_list; tz_info; tz_info = tz_info->next) {
   45         if (!strcmp(type, tz_info->type))
   46             type_instance++;
   47     }
   48     return type_instance;
   49 }
   50 
   51 /*
   52  *  stress_tz_init()
   53  *  gather all thermal zones
   54  */
   55 int stress_tz_init(stress_tz_info_t **tz_info_list)
   56 {
   57     DIR *dir;
   58         struct dirent *entry;
   59     size_t i = 0;
   60 
   61     dir = opendir("/sys/class/thermal");
   62     if (!dir)
   63         return 0;
   64 
   65     while ((entry = readdir(dir)) != NULL) {
   66         char path[PATH_MAX];
   67         FILE *fp;
   68         stress_tz_info_t *tz_info;
   69 
   70         /* Ignore non TZ interfaces */
   71         if (strncmp(entry->d_name, "thermal_zone", 12))
   72             continue;
   73 
   74         /* Ensure we don't overstep the max limit of TZs */
   75         if (i >= STRESS_THERMAL_ZONES_MAX)
   76             break;
   77 
   78         if ((tz_info = calloc(1, sizeof(*tz_info))) == NULL) {
   79             pr_err("cannot allocate thermal information\n");
   80             (void)closedir(dir);
   81             return -1;
   82         }
   83         (void)snprintf(path, sizeof(path),
   84             "/sys/class/thermal/%s/type",
   85             entry->d_name);
   86 
   87         tz_info->path = strdup(entry->d_name);
   88         if (!tz_info->path) {
   89             free(tz_info);
   90             (void)closedir(dir);
   91             return -1;
   92         }
   93         tz_info->type = NULL;
   94         if ((fp = fopen(path, "r")) != NULL) {
   95             char type[128];
   96 
   97             if (fgets(type, sizeof(type), fp) != NULL) {
   98                 type[strcspn(type, "\n")] = '\0';
   99                 tz_info->type = strdup(type);
  100                 tz_info->type_instance = stress_tz_type_instance(*tz_info_list, type);
  101             }
  102             (void)fclose(fp);
  103         }
  104         if (!tz_info->type) {
  105             free(tz_info->path);
  106             free(tz_info);
  107             (void)closedir(dir);
  108             return -1;
  109         }
  110         tz_info->index = i++;
  111         tz_info->next = *tz_info_list;
  112         *tz_info_list = tz_info;
  113     }
  114 
  115     (void)closedir(dir);
  116     return 0;
  117 }
  118 
  119 /*
  120  *  stress_tz_free()
  121  *  free thermal zones
  122  */
  123 void stress_tz_free(stress_tz_info_t **tz_info_list)
  124 {
  125     stress_tz_info_t *tz_info = *tz_info_list;
  126 
  127     while (tz_info) {
  128         stress_tz_info_t *next = tz_info->next;
  129 
  130         free(tz_info->path);
  131         free(tz_info->type);
  132         free(tz_info);
  133         tz_info = next;
  134     }
  135 }
  136 
  137 /*
  138  *  stress_tz_get_temperatures()
  139  *  collect valid thermal_zones details
  140  */
  141 int stress_tz_get_temperatures(stress_tz_info_t **tz_info_list, stress_tz_t *tz)
  142 {
  143         stress_tz_info_t *tz_info;
  144 
  145     for (tz_info = *tz_info_list; tz_info; tz_info = tz_info->next) {
  146         char path[PATH_MAX];
  147         FILE *fp;
  148         const size_t i = tz_info->index;
  149 
  150         (void)snprintf(path, sizeof(path),
  151             "/sys/class/thermal/%s/temp",
  152             tz_info->path);
  153 
  154         tz->tz_stat[i].temperature = 0;
  155         if ((fp = fopen(path, "r")) != NULL) {
  156             if (fscanf(fp, "%" SCNu64,
  157                  &tz->tz_stat[i].temperature) != 1) {
  158                 tz->tz_stat[i].temperature = 0;
  159             }
  160             (void)fclose(fp);
  161         }
  162     }
  163     return 0;
  164 }
  165 
  166 /*
  167  *  stress_tz_compare()
  168  *  sort on type name and if type names are duplicated on
  169  *  type_instance value
  170  */
  171 static int stress_tz_compare(const void *p1, const void *p2)
  172 {
  173     const stress_tz_info_t *const *tz1 = (const stress_tz_info_t *const *)p1;
  174     const stress_tz_info_t *const *tz2 = (const stress_tz_info_t *const *)p2;
  175     int ret;
  176 
  177     ret = strcmp((*tz1)->type, (*tz2)->type);
  178     if (ret == 0)
  179         return (int)(*tz1)->type_instance - (int)(*tz2)->type_instance;
  180 
  181     return ret;
  182 }
  183 
  184 
  185 /*
  186  *  stress_tz_dump()
  187  *  dump thermal zone temperatures
  188  */
  189 void stress_tz_dump(FILE *yaml, stress_stressor_t *stressors_list)
  190 {
  191     bool no_tz_stats = true;
  192     stress_stressor_t *ss;
  193 
  194     pr_yaml(yaml, "thermal-zones:\n");
  195 
  196     for (ss = stressors_list; ss; ss = ss->next) {
  197         stress_tz_info_t *tz_info;
  198         int32_t  j;
  199         size_t i, n;
  200         uint64_t total = 0;
  201         uint32_t count = 0;
  202         bool dumped_heading = false;
  203         stress_tz_info_t **tz_infos;
  204 
  205         /* Find how many items in list */
  206         for (n = 0, tz_info = g_shared->tz_info; tz_info; tz_info = tz_info->next, n++)
  207             ;
  208 
  209         /*
  210          *  Allocate array, populate with tz_info and sort
  211          */
  212         tz_infos = calloc(n, sizeof(*tz_infos));
  213         if (!tz_infos) {
  214             pr_inf("thermal zones: cannot allocate memory to sort zones\n");
  215             return;
  216         }
  217         for (n = 0, tz_info = g_shared->tz_info; tz_info; tz_info = tz_info->next, n++)
  218             tz_infos[n] = tz_info;
  219 
  220         qsort(tz_infos, n, sizeof(*tz_infos), stress_tz_compare);
  221 
  222         for (i = 0; i < n; i++) {
  223             tz_info = tz_infos[i];
  224 
  225             for (j = 0; j < ss->started_instances; j++) {
  226                 const uint64_t temp =
  227                     ss->stats[j]->tz.tz_stat[tz_info->index].temperature;
  228                 /* Avoid crazy temperatures. e.g. > 250 C */
  229                 if (temp <= 250000) {
  230                     total += temp;
  231                     count++;
  232                 }
  233             }
  234 
  235             if (total) {
  236                 const double temp = ((double)total / count) / 1000.0;
  237                 char *munged = stress_munge_underscore(ss->stressor->name);
  238 
  239                 if (!dumped_heading) {
  240                     dumped_heading = true;
  241                     pr_inf("%s:\n", munged);
  242                     pr_yaml(yaml, "    - stressor: %s\n",
  243                         munged);
  244                 }
  245 
  246                 if (stress_tz_type_instance(g_shared->tz_info, tz_info->type) <= 1) {
  247                     pr_inf("%20s %7.2f C (%.2f K)\n",
  248                         tz_info->type, temp, temp + 273.15);
  249                     pr_yaml(yaml, "      %s: %7.2f\n",
  250                         tz_info->type, temp);
  251                 } else {
  252                     pr_inf("%20s%d %7.2f C (%.2f K)\n",
  253                         tz_info->type,
  254                         tz_info->type_instance,
  255                         temp, temp + 273.15);
  256                     pr_yaml(yaml, "      %s%d: %7.2f\n",
  257                         tz_info->type,
  258                         tz_info->type_instance,
  259                         temp);
  260                 }
  261                 no_tz_stats = false;
  262             }
  263         }
  264         if (total)
  265             pr_yaml(yaml, "\n");
  266 
  267         free(tz_infos);
  268     }
  269 
  270     if (no_tz_stats)
  271         pr_inf("thermal zone temperatures not available\n");
  272 }
  273 #endif