Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/power/cpupower/utils/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  cpufreq-set.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
 */



#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>

#include <getopt.h>

#include "cpufreq.h"
#include "cpuidle.h"
#include "helpers/helpers.h"

#define NORM_FREQ_LEN 32

static struct option set_opts[] = {
 {"min",  required_argument, NULL, 'd'},
 {"max",  required_argument, NULL, 'u'},
 {"governor", required_argument, NULL, 'g'},
 {"freq", required_argument, NULL, 'f'},
 {"related", no_argument,  NULL, 'r'},
 { },
};

static void print_error(void)
{
 printf(_("Error setting new values. Common errors:\n"
   "- Do you have proper administration rights? (super-user?)\n"
   "- Is the governor you requested available and modprobed?\n"
   "- Trying to set an invalid policy?\n"
   "- Trying to set a specific frequency, but userspace governor is not available,\n"
   " for example because of hardware which cannot be set to a specific frequency\n"
   " or because the userspace governor isn't loaded?\n"));
};

struct freq_units {
 char  *str_unit;
 int  power_of_ten;
};

const struct freq_units def_units[] = {
 {"hz", -3},
 {"khz", 0}, /* default */
 {"mhz", 3},
 {"ghz", 6},
 {"thz", 9},
 {NULL, 0}
};

static void print_unknown_arg(void)
{
 printf(_("invalid or unknown argument\n"));
}

static unsigned long string_to_frequency(const char *str)
{
 char normalized[NORM_FREQ_LEN];
 const struct freq_units *unit;
 const char *scan;
 char *end;
 unsigned long freq;
 int power = 0, match_count = 0, i, cp, pad;

 while (*str == '0')
  str++;

 for (scan = str; isdigit(*scan) || *scan == '.'; scan++) {
  if (*scan == '.' && match_count == 0)
   match_count = 1;
  else if (*scan == '.' && match_count == 1)
   return 0;
 }

 if (*scan) {
  match_count = 0;
  for (unit = def_units; unit->str_unit; unit++) {
   for (i = 0;
        scan[i] && tolower(scan[i]) == unit->str_unit[i];
        ++i)
    continue;
   if (scan[i])
    continue;
   match_count++;
   power = unit->power_of_ten;
  }
  if (match_count != 1)
   return 0;
 }

 /* count the number of digits to be copied */
 for (cp = 0; isdigit(str[cp]); cp++)
  continue;

 if (str[cp] == '.') {
  while (power > -1 && isdigit(str[cp+1])) {
   cp++;
   power--;
  }
 }
 if (power >= -1) {  /* not enough => pad */
  pad = power + 1;
 } else {   /* too much => strip */
  pad = 0;
  cp += power + 1;
 }
 /* check bounds */
 if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1)
  return 0;

 /* copy digits */
 for (i = 0; i < cp; i++, str++) {
  if (*str == '.')
   str++;
  normalized[i] = *str;
 }
 /* and pad */
 for (; i < cp + pad; i++)
  normalized[i] = '0';

 /* round up, down ? */
 match_count = (normalized[i-1] >= '5');
 /* and drop the decimal part */
 normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */

 /* final conversion (and applying rounding) */
 errno = 0;
 freq = strtoul(normalized, &end, 10);
 if (errno)
  return 0;
 else {
  if (match_count && freq != ULONG_MAX)
   freq++;
  return freq;
 }
}

static int do_new_policy(unsigned int cpu, struct cpufreq_policy *new_pol)
{
 struct cpufreq_policy *cur_pol = cpufreq_get_policy(cpu);
 int ret;

 if (!cur_pol) {
  printf(_("wrong, unknown or unhandled CPU?\n"));
  return -EINVAL;
 }

 if (!new_pol->min)
  new_pol->min = cur_pol->min;

 if (!new_pol->max)
  new_pol->max = cur_pol->max;

 if (!new_pol->governor)
  new_pol->governor = cur_pol->governor;

 ret = cpufreq_set_policy(cpu, new_pol);

 cpufreq_put_policy(cur_pol);

 return ret;
}


static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol,
  unsigned long freq, unsigned int pc)
{
 switch (pc) {
 case 0:
  return cpufreq_set_frequency(cpu, freq);

 case 1:
  /* if only one value of a policy is to be changed, we can
 * use a "fast path".
 */

  if (new_pol->min)
   return cpufreq_modify_policy_min(cpu, new_pol->min);
  else if (new_pol->max)
   return cpufreq_modify_policy_max(cpu, new_pol->max);
  else if (new_pol->governor)
   return cpufreq_modify_policy_governor(cpu,
       new_pol->governor);

 default:
  /* slow path */
  return do_new_policy(cpu, new_pol);
 }
}

int cmd_freq_set(int argc, char **argv)
{
 extern char *optarg;
 extern int optind, opterr, optopt;
 int ret = 0, cont = 1;
 int double_parm = 0, related = 0, policychange = 0;
 unsigned long freq = 0;
 char gov[20];
 unsigned int cpu;

 struct cpufreq_policy new_pol = {
  .min = 0,
  .max = 0,
  .governor = NULL,
 };

 /* parameter parsing */
 do {
  ret = getopt_long(argc, argv, "d:u:g:f:r", set_opts, NULL);
  switch (ret) {
  case '?':
   print_unknown_arg();
   return -EINVAL;
  case -1:
   cont = 0;
   break;
  case 'r':
   if (related)
    double_parm++;
   related++;
   break;
  case 'd':
   if (new_pol.min)
    double_parm++;
   policychange++;
   new_pol.min = string_to_frequency(optarg);
   if (new_pol.min == 0) {
    print_unknown_arg();
    return -EINVAL;
   }
   break;
  case 'u':
   if (new_pol.max)
    double_parm++;
   policychange++;
   new_pol.max = string_to_frequency(optarg);
   if (new_pol.max == 0) {
    print_unknown_arg();
    return -EINVAL;
   }
   break;
  case 'f':
   if (freq)
    double_parm++;
   freq = string_to_frequency(optarg);
   if (freq == 0) {
    print_unknown_arg();
    return -EINVAL;
   }
   break;
  case 'g':
   if (new_pol.governor)
    double_parm++;
   policychange++;
   if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) {
    print_unknown_arg();
    return -EINVAL;
   }
   if ((sscanf(optarg, "%19s", gov)) != 1) {
    print_unknown_arg();
    return -EINVAL;
   }
   new_pol.governor = gov;
   break;
  }
 } while (cont);

 /* parameter checking */
 if (double_parm) {
  printf("the same parameter was passed more than once\n");
  return -EINVAL;
 }

 if (freq && policychange) {
  printf(_("the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
    "-g/--governor parameters\n"));
  return -EINVAL;
 }

 if (!freq && !policychange) {
  printf(_("At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
    "-g/--governor must be passed\n"));
  return -EINVAL;
 }

 /* Default is: set all CPUs */
 if (bitmask_isallclear(cpus_chosen))
  bitmask_setall(cpus_chosen);

 /* Also set frequency settings for related CPUs if -r is passed */
 if (related) {
  for (cpu = bitmask_first(cpus_chosen);
       cpu <= bitmask_last(cpus_chosen); cpu++) {
   struct cpufreq_affected_cpus *cpus;

   if (!bitmask_isbitset(cpus_chosen, cpu) ||
       cpupower_is_cpu_online(cpu) != 1)
    continue;

   cpus = cpufreq_get_related_cpus(cpu);
   if (!cpus)
    break;
   while (cpus->next) {
    bitmask_setbit(cpus_chosen, cpus->cpu);
    cpus = cpus->next;
   }
   /* Set the last cpu in related cpus list */
   bitmask_setbit(cpus_chosen, cpus->cpu);
   cpufreq_put_related_cpus(cpus);
  }
 }

 get_cpustate();

 /* loop over CPUs */
 for (cpu = bitmask_first(cpus_chosen);
      cpu <= bitmask_last(cpus_chosen); cpu++) {

  if (!bitmask_isbitset(cpus_chosen, cpu) ||
      cpupower_is_cpu_online(cpu) != 1)
   continue;

  printf(_("Setting cpu: %d\n"), cpu);
  ret = do_one_cpu(cpu, &new_pol, freq, policychange);
  if (ret) {
   print_error();
   return ret;
  }
 }

 print_offline_cpus();

 return 0;
}

Messung V0.5
C=97 H=97 G=96

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.