Merge branch 'collectd-5.8' into collectd-5.9
authorFlorian Forster <octo@collectd.org>
Fri, 15 Nov 2019 09:44:26 +0000 (10:44 +0100)
committerFlorian Forster <octo@collectd.org>
Fri, 15 Nov 2019 09:44:26 +0000 (10:44 +0100)
1  2 
src/turbostat.c

diff --combined src/turbostat.c
@@@ -37,8 -37,8 +37,8 @@@
  
  #include "collectd.h"
  
 -#include "common.h"
  #include "plugin.h"
 +#include "utils/common/common.h"
  #include "utils_time.h"
  
  #include "msr-index.h"
  
  #define PLUGIN_NAME "turbostat"
  
 +typedef enum affinity_policy_enum {
 +  policy_restore_affinity, /* restore cpu affinity to whatever it was before */
 +  policy_allcpus_affinity  /* do not restore affinity, set to all cpus */
 +} affinity_policy_t;
 +
 +/* the default is to set cpu affinity to all cpus */
 +static affinity_policy_t affinity_policy = policy_allcpus_affinity;
 +
  /*
   * This tool uses the Model-Specific Registers (MSRs) present on Intel
   * processors.
   *
   * This value is automatically set if mperf or aperf go backward
   */
 -static _Bool aperf_mperf_unstable;
 +static bool aperf_mperf_unstable;
  
  /*
   * If set, use kernel logical core numbering for all "per core" metrics.
   */
 -static _Bool config_lcn;
 +static bool config_lcn;
  
  /*
   * Bitmask of the list of core C states supported by the processor.
@@@ -86,7 -78,7 +86,7 @@@
   */
  static unsigned int do_core_cstate;
  static unsigned int config_core_cstate;
 -static _Bool apply_config_core_cstate;
 +static bool apply_config_core_cstate;
  
  /*
   * Bitmask of the list of pacages C states supported by the processor.
   */
  static unsigned int do_pkg_cstate;
  static unsigned int config_pkg_cstate;
 -static _Bool apply_config_pkg_cstate;
 +static bool apply_config_pkg_cstate;
  
  /*
   * Boolean indicating if the processor supports 'I/O System-Management Interrupt
   * counter'
   */
 -static _Bool do_smi;
 -static _Bool config_smi;
 -static _Bool apply_config_smi;
 +static bool do_smi;
 +static bool config_smi;
 +static bool apply_config_smi;
  
  /*
   * Boolean indicating if the processor supports 'Digital temperature sensor'
   * might be wrong
   *  - Temperatures above the tcc_activation_temp are not recorded
   */
 -static _Bool do_dts;
 -static _Bool config_dts;
 -static _Bool apply_config_dts;
 +static bool do_dts;
 +static bool config_dts;
 +static bool apply_config_dts;
  
  /*
   * Boolean indicating if the processor supports 'Package thermal management'
   * might be wrong
   *  - Temperatures above the tcc_activation_temp are not recorded
   */
 -static _Bool do_ptm;
 -static _Bool config_ptm;
 -static _Bool apply_config_ptm;
 +static bool do_ptm;
 +static bool config_ptm;
 +static bool apply_config_ptm;
  
  /*
   * Thermal Control Circuit Activation Temperature as configured by the user.
   */
  static unsigned int tcc_activation_temp;
  
 +static unsigned int do_power_fields;
 +#define UFS_PLATFORM (1 << 0)
 +#define TURBO_PLATFORM (1 << 1)
 +#define PSTATES_PLATFORM (1 << 2)
 +
  static unsigned int do_rapl;
  static unsigned int config_rapl;
 -static _Bool apply_config_rapl;
 +static bool apply_config_rapl;
  static double rapl_energy_units;
 +static double rapl_power_units;
  
  #define RAPL_PKG (1 << 0)
  /* 0x610 MSR_PKG_POWER_LIMIT */
  /* 0x611 MSR_PKG_ENERGY_STATUS */
 +/* 0x614 MSR_PKG_POWER_INFO */
  #define RAPL_DRAM (1 << 1)
  /* 0x618 MSR_DRAM_POWER_LIMIT */
  /* 0x619 MSR_DRAM_ENERGY_STATUS */
@@@ -203,10 -188,6 +203,10 @@@ static struct pkg_data 
    uint32_t energy_dram;  /* MSR_DRAM_ENERGY_STATUS */
    uint32_t energy_cores; /* MSR_PP0_ENERGY_STATUS */
    uint32_t energy_gfx;   /* MSR_PP1_ENERGY_STATUS */
 +  uint32_t tdp;
 +  uint8_t turbo_enabled;
 +  uint8_t pstates_enabled;
 +  uint32_t uncore;
    unsigned int tcc_activation_temp;
    unsigned int pkg_temp_c;
  } * package_delta, *package_even, *package_odd;
  #define DELTA_COUNTERS thread_delta, core_delta, package_delta
  #define ODD_COUNTERS thread_odd, core_odd, package_odd
  #define EVEN_COUNTERS thread_even, core_even, package_even
 -static _Bool is_even = 1;
 +static bool is_even = true;
  
 -static _Bool allocated = 0;
 -static _Bool initialized = 0;
 +static bool allocated;
 +static bool initialized;
  
  #define GET_THREAD(thread_base, thread_no, core_no, pkg_no)                    \
    (thread_base + (pkg_no)*topology.num_cores * topology.num_threads +          \
  struct cpu_topology {
    unsigned int package_id;
    unsigned int core_id;
 -  _Bool first_core_in_package;
 -  _Bool first_thread_in_core;
 +  bool first_core_in_package;
 +  bool first_thread_in_core;
  };
  
  static struct topology {
@@@ -252,7 -233,6 +252,7 @@@ static const char *config_keys[] = 
      "TCCActivationTemp",
      "RunningAveragePowerLimit",
      "LogicalCoreNames",
 +    "RestoreAffinityPolicy",
  };
  static const int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
  
  /*
   * Open a MSR device for reading
   * Can change the scheduling affinity of the current process if multiple_read is
 - * 1
 + * true
   */
  static int __attribute__((warn_unused_result))
 -open_msr(unsigned int cpu, _Bool multiple_read) {
 +open_msr(unsigned int cpu, bool multiple_read) {
    char pathname[32];
    int fd;
  
@@@ -415,8 -395,6 +415,8 @@@ get_counters(struct thread_data *t, str
    if (do_rapl & RAPL_PKG) {
      READ_MSR(MSR_PKG_ENERGY_STATUS, &msr);
      p->energy_pkg = msr & 0xFFFFFFFF;
 +    READ_MSR(MSR_PKG_POWER_INFO, &msr);
 +    p->tdp = msr & 0x7FFF;
    }
    if (do_rapl & RAPL_CORES) {
      READ_MSR(MSR_PP0_ENERGY_STATUS, &msr);
      READ_MSR(MSR_IA32_PACKAGE_THERM_STATUS, &msr);
      p->pkg_temp_c = p->tcc_activation_temp - ((msr >> 16) & 0x7F);
    }
 +  if (do_power_fields & TURBO_PLATFORM) {
 +    READ_MSR(MSR_IA32_MISC_ENABLE, &msr);
 +    p->turbo_enabled = !((msr >> 38) & 0x1);
 +  }
 +  if (do_power_fields & PSTATES_PLATFORM) {
 +    READ_MSR(MSR_IA32_MISC_ENABLE, &msr);
 +    p->pstates_enabled = (msr >> 16) & 0x1;
 +  }
 +  if (do_power_fields & UFS_PLATFORM) {
 +    READ_MSR(MSR_UNCORE_FREQ_SCALING, &msr);
 +    p->uncore = msr & 0x1F;
 +  }
  
  out:
    close(msr_fd);
@@@ -476,11 -442,6 +476,11 @@@ static inline void delta_package(struc
    delta->energy_cores = new->energy_cores - old->energy_cores;
    delta->energy_gfx = new->energy_gfx - old->energy_gfx;
    delta->energy_dram = new->energy_dram - old->energy_dram;
 +  delta->tdp = new->tdp;
 +  delta->turbo_enabled = new->turbo_enabled;
 +  delta->pstates_enabled = new->pstates_enabled;
 +  delta->tcc_activation_temp = new->tcc_activation_temp;
 +  delta->uncore = new->uncore;
  }
  
  /*
@@@ -526,7 -487,7 +526,7 @@@ delta_thread(struct thread_data *delta
                "the entire interval. Fix this by running "
                "Linux-2.6.30 or later.");
  
 -      aperf_mperf_unstable = 1;
 +      aperf_mperf_unstable = true;
      }
    }
  
@@@ -666,11 -627,9 +666,11 @@@ static int submit_counters(struct threa
      turbostat_submit(name, "percent", "pc10", 100.0 * p->pc10 / t->tsc);
  
    if (do_rapl) {
 -    if (do_rapl & RAPL_PKG)
 +    if (do_rapl & RAPL_PKG) {
        turbostat_submit(name, "power", "pkg",
                         p->energy_pkg * rapl_energy_units / interval_float);
 +      turbostat_submit(name, "tdp", "pkg", p->tdp * rapl_power_units);
 +    }
      if (do_rapl & RAPL_CORES)
        turbostat_submit(name, "power", "cores",
                         p->energy_cores * rapl_energy_units / interval_float);
        turbostat_submit(name, "power", "DRAM",
                         p->energy_dram * rapl_energy_units / interval_float);
    }
 +
 +  if (do_power_fields & TURBO_PLATFORM) {
 +    turbostat_submit(name, "turbo_enabled", NULL, p->turbo_enabled);
 +  }
 +  if (do_power_fields & PSTATES_PLATFORM) {
 +    turbostat_submit(name, "pstates_enabled", NULL, p->pstates_enabled);
 +  }
 +  if (do_power_fields & UFS_PLATFORM) {
 +    turbostat_submit(name, "uncore_ratio", NULL, p->uncore);
 +  }
 +  turbostat_submit(name, "temperature", "tcc_activation",
 +                   p->tcc_activation_temp);
  done:
    return 0;
  }
@@@ -948,14 -895,14 +948,14 @@@ static int __attribute__((warn_unused_r
      switch (model) {
      /* Atom (partial) */
      case 0x27:
 -      do_smi = 0;
 +      do_smi = false;
        do_core_cstate = 0;
        do_pkg_cstate = (1 << 2) | (1 << 4) | (1 << 6);
        break;
      /* Silvermont */
      case 0x37: /* BYT */
      case 0x4D: /* AVN */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 1) | (1 << 6);
        do_pkg_cstate = (1 << 6);
        break;
                    Forest */
      case 0x1F: /* Core i7 and i5 Processor - Nehalem */
      case 0x2E: /* Nehalem-EX Xeon - Beckton */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 3) | (1 << 6);
        do_pkg_cstate = (1 << 3) | (1 << 6) | (1 << 7);
        break;
      case 0x25: /* Westmere Client - Clarkdale, Arrandale */
      case 0x2C: /* Westmere EP - Gulftown */
      case 0x2F: /* Westmere-EX Xeon - Eagleton */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 3) | (1 << 6);
        do_pkg_cstate = (1 << 3) | (1 << 6) | (1 << 7);
        break;
      /* Sandy Bridge */
      case 0x2A: /* SNB */
      case 0x2D: /* SNB Xeon */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
        do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
        break;
      /* Ivy Bridge */
      case 0x3A: /* IVB */
      case 0x3E: /* IVB Xeon */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
        do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
        break;
      case 0x3C: /* HSW */
      case 0x3F: /* HSW */
      case 0x46: /* HSW */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
        do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
        break;
      case 0x45: /* HSW */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
        do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7) | (1 << 8) |
                        (1 << 9) | (1 << 10);
        break;
 -    /* Broadwel */
 +    /* Broadwell */
      case 0x4F: /* BDW */
      case 0x56: /* BDX-DE */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
        do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
        break;
      case 0x3D: /* BDW */
 -      do_smi = 1;
 +      do_smi = true;
        do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
        do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7) | (1 << 8) |
                        (1 << 9) | (1 << 10);
        break;
      default:
 -      do_smi = 0;
 +      do_smi = false;
        do_core_cstate = 0;
        do_pkg_cstate = 0;
        break;
      case 0x45: /* HSW */
      case 0x46: /* HSW */
      case 0x3D: /* BDW */
 +    case 0x5E: /* SKL */
        do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX;
        break;
      case 0x3F: /* HSX */
      case 0x4F: /* BDX */
      case 0x56: /* BDX-DE */
        do_rapl = RAPL_PKG | RAPL_DRAM;
 +      do_power_fields = TURBO_PLATFORM | UFS_PLATFORM | PSTATES_PLATFORM;
        break;
      case 0x2D: /* SNB Xeon */
      case 0x3E: /* IVB Xeon */
        do_rapl = RAPL_PKG | RAPL_CORES | RAPL_DRAM;
 +      do_power_fields = TURBO_PLATFORM | PSTATES_PLATFORM;
        break;
      case 0x37: /* BYT */
      case 0x4D: /* AVN */
      if (get_msr(0, MSR_RAPL_POWER_UNIT, &msr))
        return 0;
  
 +    rapl_power_units = 1.0 / (1 << (msr & 0xF));
      if (model == 0x37)
        rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;
      else
@@@ -1099,7 -1042,11 +1099,11 @@@ static int __attribute__((format(printf
  parse_int_file(const char *fmt, ...) {
    va_list args;
    char path[PATH_MAX];
+   char buf[256];
    int len;
+   value_t v;
+   char *c;
+   FILE *fp;
  
    va_start(args, fmt);
    len = vsnprintf(path, sizeof(path), fmt, args);
      return -1;
    }
  
-   value_t v;
-   if (parse_value_file(path, &v, DS_TYPE_DERIVE) != 0) {
+   fp = fopen(path, "r");
+   if (fp == NULL) {
+     ERROR("turbostat plugin: unable to open: '%s': %s", path, strerror(errno));
+     return -1;
+   }
+   if (fgets(buf, sizeof(buf), fp) == NULL) {
+     ERROR("turbostat plugin: unable to read: '%s': %s", path, strerror(errno));
+     fclose(fp);
+     return -1;
+   }
+   fclose(fp);
+   /* We only care about the first integer in the range */
+   c = strchr(buf, '-');
+   if (c != NULL)
+     *c = '\0';
+   c = strchr(buf, ',');
+   if (c != NULL)
+     *c = '\0';
+   strstripnewline(buf);
+   if (parse_value(buf, &v, DS_TYPE_DERIVE) != 0) {
      ERROR("turbostat plugin: Parsing \"%s\" failed.", path);
      return -1;
    }
@@@ -1283,7 -1251,7 +1308,7 @@@ static int __attribute__((warn_unused_r
      if (ret < 0)
        goto err;
      else if ((unsigned int)ret == i)
 -      cpu->first_core_in_package = 1;
 +      cpu->first_core_in_package = true;
  
      ret = get_threads_on_core(i);
      if (ret < 0)
      if (ret < 0)
        goto err;
      else if ((unsigned int)ret == i)
 -      cpu->first_thread_in_core = 1;
 +      cpu->first_thread_in_core = true;
  
      DEBUG("turbostat plugin: cpu %d pkg %d core %d\n", i, cpu->package_id,
            cpu->core_id);
@@@ -1394,8 -1362,8 +1419,8 @@@ static void initialize_counters(void) 
  }
  
  static void free_all_buffers(void) {
 -  allocated = 0;
 -  initialized = 0;
 +  allocated = false;
 +  initialized = false;
  
    CPU_FREE(cpu_present_set);
    cpu_present_set = NULL;
    package_delta = NULL;
  }
  
 -/**********************
 - * Collectd functions *
 - **********************/
 +  /**********************
 +   * Collectd functions *
 +   **********************/
  
  #define DO_OR_GOTO_ERR(something)                                              \
    do {                                                                         \
@@@ -1456,37 -1424,13 +1481,37 @@@ static int setup_all_buffers(void) 
    DO_OR_GOTO_ERR(for_all_cpus(set_temperature_target, EVEN_COUNTERS));
    DO_OR_GOTO_ERR(for_all_cpus(set_temperature_target, ODD_COUNTERS));
  
 -  allocated = 1;
 +  allocated = true;
    return 0;
  err:
    free_all_buffers();
    return ret;
  }
  
 +static int save_affinity(void) {
 +  if (affinity_policy == policy_restore_affinity) {
 +    /* Try to save the scheduling affinity, as it will be modified by
 +     * get_counters().
 +     */
 +    if (sched_getaffinity(0, cpu_saved_affinity_setsize,
 +                          cpu_saved_affinity_set) != 0)
 +      return -1;
 +  }
 +
 +  return 0;
 +}
 +
 +static void restore_affinity(void) {
 +  /* Let's restore the affinity to the value saved in save_affinity */
 +  if (affinity_policy == policy_restore_affinity)
 +    (void)sched_setaffinity(0, cpu_saved_affinity_setsize,
 +                            cpu_saved_affinity_set);
 +  else {
 +    /* reset the affinity to all present cpus */
 +    (void)sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
 +  }
 +}
 +
  static int turbostat_read(void) {
    int ret;
  
      }
    }
  
 -  /* Saving the scheduling affinity, as it will be modified by get_counters */
 -  if (sched_getaffinity(0, cpu_saved_affinity_setsize,
 -                        cpu_saved_affinity_set) != 0) {
 -    ERROR("turbostat plugin: Unable to save the CPU affinity");
 +  if (save_affinity() != 0) {
 +    ERROR("turbostat plugin: Unable to save the CPU affinity. Please read the "
 +          "docs about RestoreAffinityPolicy option.");
      return -1;
    }
  
      if ((ret = for_all_cpus(get_counters, EVEN_COUNTERS)) < 0)
        goto out;
      time_even = cdtime();
 -    is_even = 1;
 -    initialized = 1;
 +    is_even = true;
 +    initialized = true;
      ret = 0;
      goto out;
    }
      if ((ret = for_all_cpus(get_counters, ODD_COUNTERS)) < 0)
        goto out;
      time_odd = cdtime();
 -    is_even = 0;
 +    is_even = false;
      time_delta = time_odd - time_even;
      if ((ret = for_all_cpus_delta(ODD_COUNTERS, EVEN_COUNTERS)) < 0)
        goto out;
      if ((ret = for_all_cpus(get_counters, EVEN_COUNTERS)) < 0)
        goto out;
      time_even = cdtime();
 -    is_even = 1;
 +    is_even = true;
      time_delta = time_even - time_odd;
      if ((ret = for_all_cpus_delta(EVEN_COUNTERS, ODD_COUNTERS)) < 0)
        goto out;
    }
    ret = 0;
  out:
 -  /*
 -   * Let's restore the affinity
 -   * This might fail if the number of CPU changed, but we can't do anything in
 -   * that case..
 -   */
 -  (void)sched_setaffinity(0, cpu_saved_affinity_setsize,
 -                          cpu_saved_affinity_set);
 +  restore_affinity();
 +
    return ret;
  }
  
@@@ -1628,7 -1578,7 +1653,7 @@@ static int turbostat_config(const char 
        return -1;
      }
      config_core_cstate = (unsigned int)tmp_val;
 -    apply_config_core_cstate = 1;
 +    apply_config_core_cstate = true;
    } else if (strcasecmp("PackageCstates", key) == 0) {
      tmp_val = strtoul(value, &end, 0);
      if (*end != '\0' || tmp_val > UINT_MAX) {
        return -1;
      }
      config_pkg_cstate = (unsigned int)tmp_val;
 -    apply_config_pkg_cstate = 1;
 +    apply_config_pkg_cstate = true;
    } else if (strcasecmp("SystemManagementInterrupt", key) == 0) {
      config_smi = IS_TRUE(value);
 -    apply_config_smi = 1;
 +    apply_config_smi = true;
    } else if (strcasecmp("DigitalTemperatureSensor", key) == 0) {
      config_dts = IS_TRUE(value);
 -    apply_config_dts = 1;
 +    apply_config_dts = true;
    } else if (strcasecmp("PackageThermalManagement", key) == 0) {
      config_ptm = IS_TRUE(value);
 -    apply_config_ptm = 1;
 +    apply_config_ptm = true;
    } else if (strcasecmp("LogicalCoreNames", key) == 0) {
      config_lcn = IS_TRUE(value);
    } else if (strcasecmp("RunningAveragePowerLimit", key) == 0) {
        return -1;
      }
      config_rapl = (unsigned int)tmp_val;
 -    apply_config_rapl = 1;
 +    apply_config_rapl = true;
    } else if (strcasecmp("TCCActivationTemp", key) == 0) {
      tmp_val = strtoul(value, &end, 0);
      if (*end != '\0' || tmp_val > UINT_MAX) {
        return -1;
      }
      tcc_activation_temp = (unsigned int)tmp_val;
 +  } else if (strcasecmp("RestoreAffinityPolicy", key) == 0) {
 +    if (strcasecmp("Restore", value) == 0)
 +      affinity_policy = policy_restore_affinity;
 +    else if (strcasecmp("AllCPUs", value) == 0)
 +      affinity_policy = policy_allcpus_affinity;
 +    else {
 +      ERROR("turbostat plugin: Invalid RestoreAffinityPolicy '%s'", value);
 +      return -1;
 +    }
    } else {
      ERROR("turbostat plugin: Invalid configuration option '%s'", key);
      return -1;