"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/core-ignite-cpu.c" (15 Mar 2019, 7479 Bytes) of package /linux/privat/stress-ng-0.09.56.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-ignite-cpu.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.51_vs_0.09.52.

    1 /*
    2  * Copyright (C) 2016-2019 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 typedef struct {
   28     const char *path;       /* Path of /sys control */
   29     const char *default_setting;    /* Default maximizing setting to use */
   30     size_t default_setting_len; /* Length of default setting */
   31     char *setting;          /* Original setting to restore it */
   32     size_t setting_len;     /* Length of setting */
   33     bool ignore;            /* true to ignore using this */
   34 } settings_t;
   35 
   36 typedef struct {
   37     uint64_t max_freq;      /* Max scaling frequency */
   38     uint64_t cur_freq;      /* Original scaling frequency */
   39     char cur_governor[128];     /* Original governor setting */
   40     bool set_failed;        /* True if we can't set the freq */
   41 } cpu_setting_t;
   42 
   43 static cpu_setting_t *cpu_settings; /* Array of cpu settings */
   44 
   45 static pid_t pid;           /* PID of ignite process */
   46 static bool enabled;            /* true if ignite process running */
   47 static uint32_t max_cpus;       /* max cpus configured */
   48 
   49 #define SETTING(path, default_setting)  \
   50     { path, default_setting, 0, NULL, 0, false }
   51 
   52 static settings_t settings[] = {
   53 #if defined(__linux__) && defined(STRESS_X86)
   54     /* x86 Intel P-State maximizing settings */
   55     SETTING("/sys/devices/system/cpu/intel_pstate/max_perf_pct", "100"),
   56     SETTING("/sys/devices/system/cpu/intel_pstate/no_turbo", "0"),
   57 #endif
   58     SETTING(NULL, NULL)
   59 };
   60 
   61 static int ignite_cpu_set(
   62     const uint32_t cpu,
   63     const uint64_t freq,
   64     const char *governor)
   65 {
   66     char path[PATH_MAX];
   67     int ret1 = 0, ret2 = 0;
   68 
   69     if (freq > 0) {
   70         char buffer[128];
   71 
   72         (void)snprintf(path, sizeof(path),
   73             "/sys/devices/system/cpu/cpu%" PRIu32
   74             "/cpufreq/scaling_setspeed", cpu);
   75         (void)snprintf(buffer, sizeof(buffer), "%" PRIu64 "\n", freq);
   76         ret1 = system_write(path, buffer, strlen(buffer));
   77     }
   78 
   79     if (*governor != '\0') {
   80         (void)snprintf(path, sizeof(path),
   81             "/sys/devices/system/cpu/cpu%" PRIu32
   82             "/cpufreq/scaling_governor", cpu);
   83         ret2 = system_write(path, governor, strlen(governor));
   84     }
   85 
   86     return ((ret1 < 0) || (ret2 < 0)) ? -1 : 0;
   87 }
   88 
   89 /*
   90  *  ignite_cpu_start()
   91  *  crank up the CPUs, start a child process to continually
   92  *  set the most demanding CPU settings
   93  */
   94 void ignite_cpu_start(void)
   95 {
   96     size_t i, n = 0;
   97 
   98     if (enabled)
   99         return;
  100 
  101     max_cpus = stress_get_processors_configured();
  102     if (max_cpus < 1)
  103         max_cpus = 1;   /* Has to have at least 1 cpu! */
  104     cpu_settings = calloc((size_t)max_cpus, sizeof(*cpu_settings));
  105     if (!cpu_settings) {
  106         pr_dbg("ignite-cpu: no cpu settings allocated\n");
  107     } else {
  108         uint32_t cpu;
  109         char buffer[128];
  110         char path[PATH_MAX];
  111 
  112         /*
  113          *  Gather per-cpu max scaling frequencies and governors
  114          */
  115         for (cpu = 0; cpu < max_cpus; cpu++) {
  116             int ret;
  117 
  118             /* Assume failed */
  119             cpu_settings[cpu].max_freq = 0;
  120             cpu_settings[cpu].set_failed = true;
  121 
  122             (void)memset(buffer, 0, sizeof(buffer));
  123             (void)snprintf(path, sizeof(path),
  124                 "/sys/devices/system/cpu/cpu%" PRIu32
  125                 "/cpufreq/scaling_max_freq", cpu);
  126             ret = system_read(path, buffer, sizeof(buffer));
  127             if (ret > 0) {
  128                 ret = sscanf(buffer, "%" SCNu64,
  129                     &cpu_settings[cpu].max_freq);
  130                 if (ret == 1)
  131                     cpu_settings[cpu].set_failed = false;
  132             }
  133 
  134             (void)memset(buffer, 0, sizeof(buffer));
  135             (void)snprintf(path, sizeof(path),
  136                 "/sys/devices/system/cpu/cpu%" PRIu32
  137                 "/cpufreq/scaling_cur_freq", cpu);
  138             ret = system_read(path, buffer, sizeof(buffer));
  139             if (ret > 0) {
  140                 ret = sscanf(buffer, "%" SCNu64,
  141                     &cpu_settings[cpu].cur_freq);
  142                 if (ret == 1)
  143                     cpu_settings[cpu].set_failed = false;
  144             }
  145 
  146             (void)memset(cpu_settings[cpu].cur_governor, 0,
  147                 sizeof(cpu_settings[cpu].cur_governor));
  148             (void)snprintf(path, sizeof(path),
  149                 "/sys/devices/system/cpu/cpu%" PRIu32
  150                 "/cpufreq/scaling_governor", cpu);
  151             ret = system_read(path, cpu_settings[cpu].cur_governor,
  152                       sizeof(cpu_settings[cpu].cur_governor));
  153             (void)ret;
  154         }
  155     }
  156 
  157     pid = -1;
  158     for (i = 0; settings[i].path; i++) {
  159         char buf[4096];
  160         int ret;
  161         size_t len;
  162 
  163         settings[i].ignore = true;
  164         ret = system_read(settings[i].path, buf, sizeof(buf) - 1);
  165         if (ret < 0)
  166             continue;
  167         buf[ret] = '\0';
  168         len = strlen(buf);
  169         if (len == 0)
  170             continue;
  171 
  172         settings[i].default_setting_len =
  173             strlen(settings[i].default_setting);
  174         /* If we can't update the setting, skip it */
  175         ret = system_write(settings[i].path,
  176             settings[i].default_setting,
  177             settings[i].default_setting_len);
  178         if (ret < 0) {
  179             pr_dbg("ignite-cpu: cannot set %s to %s, "
  180                 "errno=%d (%s)\n",
  181                 settings[i].path, settings[i].default_setting,
  182                 -ret, strerror(-ret));
  183             continue;
  184         }
  185 
  186         settings[i].setting = calloc(1, len + 1);
  187         if (!settings[i].setting)
  188             continue;
  189 
  190         (void)shim_strlcpy(settings[i].setting, buf, len);
  191         settings[i].setting_len = len;
  192         settings[i].ignore = false;
  193         n++;
  194     }
  195 
  196     if (n == 0)
  197         return;
  198 
  199     enabled = true;
  200 
  201     pid = fork();
  202     if (pid < 0) {
  203         pr_dbg("ignite-cpu: failed to start ignite cpu daemon, "
  204             "errno=%d (%s)\n", errno, strerror(errno));
  205         return;
  206     } else if (pid == 0) {
  207         /* Child */
  208 
  209         (void)setpgid(0, g_pgrp);
  210         stress_parent_died_alarm();
  211         stress_set_proc_name("stress-ng-ignite");
  212 
  213         while (g_keep_stressing_flag) {
  214 
  215             for (i = 0; settings[i].path; i++) {
  216                 if (settings[i].ignore)
  217                     continue;
  218                 (void)system_write(settings[i].path,
  219                     settings[i].default_setting,
  220                     settings[i].default_setting_len);
  221             }
  222 
  223             if (cpu_settings) {
  224                 uint32_t cpu;
  225 
  226                 /*
  227                  *  Attempt to crank CPUs up to max freq
  228                  */
  229                 for (cpu = 0; cpu < max_cpus; cpu++) {
  230                     int ret;
  231 
  232                     if (cpu_settings[cpu].set_failed)
  233                         continue;
  234 
  235                     ret = ignite_cpu_set(cpu,
  236                         cpu_settings[cpu].max_freq,
  237                         "performance");
  238                     if (ret < 0)
  239                         cpu_settings[cpu].set_failed = true;
  240                 }
  241             }
  242             (void)sleep(1);
  243         }
  244         _exit(0);
  245     } else {
  246         /* Parent */
  247         (void)setpgid(pid, g_pgrp);
  248     }
  249 }
  250 
  251 /*
  252  *  ignite_cpu_stop()
  253  *  stop updating settings and restore to original settings
  254  */
  255 void ignite_cpu_stop(void)
  256 {
  257     size_t i;
  258     int status;
  259 
  260     if (pid > -1) {
  261         (void)kill(pid, SIGTERM);
  262         (void)kill(pid, SIGKILL);
  263         (void)waitpid(pid, &status, 0);
  264     }
  265 
  266     if (cpu_settings) {
  267         uint32_t cpu;
  268 
  269         for (cpu = 0; cpu < max_cpus; cpu++) {
  270             ignite_cpu_set(cpu,
  271                 cpu_settings[cpu].cur_freq,
  272                 cpu_settings[cpu].cur_governor);
  273         }
  274         free(cpu_settings);
  275     }
  276 
  277     for (i = 0; settings[i].path; i++) {
  278         if (settings[i].ignore)
  279             continue;
  280 
  281         (void)system_write(settings[i].path, settings[i].setting,
  282             settings[i].setting_len);
  283         free(settings[i].setting);
  284         settings[i].setting = NULL;
  285         settings[i].ignore = true;
  286     }
  287     enabled = false;
  288 }