-/*
- * run func(cpu) on every cpu in /proc/stat
- * return max_cpu number
- */
-static int __attribute__((warn_unused_result))
-for_all_proc_cpus(int (func)(int))
-{
- FILE *fp;
- int cpu_num;
- int retval;
-
- fp = fopen("/proc/stat", "r");
- if (!fp) {
- ERROR("Failed to open /proc/stat");
- return -ERR_CANT_OPEN_FILE;
- }
-
- retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
- if (retval != 0) {
- ERROR("Failed to parse /proc/stat");
- fclose(fp);
- return -ERR_CANT_READ_PROC_STAT;
- }
-
- while (1) {
- retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
- if (retval != 1)
- break;
-
- retval = func(cpu_num);
- if (retval) {
- fclose(fp);
- return(retval);
- }
- }
- fclose(fp);
- return 0;
-}
-
-/*
- * count_cpus()
- * remember the last one seen, it will be the max
- */
-static int
-count_cpus(int cpu)
-{
- if (topo.max_cpu_num < cpu)
- topo.max_cpu_num = cpu;
-
- topo.num_cpus += 1;
- return 0;
-}
-static int
-mark_cpu_present(int cpu)
-{
- CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);
- return 0;
-}
-
-
-static void
-turbostat_submit (const char *plugin_instance,
- const char *type, const char *type_instance,
- gauge_t value)
-{
- value_list_t vl = VALUE_LIST_INIT;
- value_t v;
-
- v.gauge = value;
- vl.values = &v;
- vl.values_len = 1;
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
- sstrncpy (vl.plugin, PLUGIN_NAME, sizeof (vl.plugin));
- if (plugin_instance != NULL)
- sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- sstrncpy (vl.type, type, sizeof (vl.type));
- if (type_instance != NULL)
- sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
-
- plugin_dispatch_values (&vl);
-}
-
-/*
- * column formatting convention & formats
- * package: "pk" 2 columns %2d
- * core: "cor" 3 columns %3d
- * CPU: "CPU" 3 columns %3d
- * Pkg_W: %6.2
- * Cor_W: %6.2
- * GFX_W: %5.2
- * RAM_W: %5.2
- * GHz: "GHz" 3 columns %3.2
- * TSC: "TSC" 3 columns %3.2
- * SMI: "SMI" 4 columns %4d
- * percentage " %pc3" %6.2
- * Perf Status percentage: %5.2
- * "CTMP" 4 columns %4d
- */
-static int
-submit_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
-{
- char name[12];
- double interval_float;
-
- interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
-
- ssnprintf(name, sizeof(name), "cpu%02d", t->cpu_id);
-
- if (!aperf_mperf_unstable)
- turbostat_submit(name, "percent", "c0", 100.0 * t->mperf/t->tsc);
- if (!aperf_mperf_unstable)
- turbostat_submit(name, "percent", "c1", 100.0 * t->c1/t->tsc);
-
- /* GHz */
- if ((!aperf_mperf_unstable) || (!(t->aperf > t->tsc || t->mperf > t->tsc)))
- turbostat_submit(NULL, "frequency", name, 1.0 * t->tsc / 1000000000 * t->aperf / t->mperf / interval_float);
-
- /* SMI */
- turbostat_submit(NULL, "current", name, t->smi_count);
-
- /* print per-core data only for 1st thread in core */
- if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
- goto done;
-
- ssnprintf(name, sizeof(name), "core%02d", c->core_id);
-
- if (do_core_cstate & (1 << 3))
- turbostat_submit(name, "percent", "c3", 100.0 * c->c3/t->tsc);
- if (do_core_cstate & (1 << 6))
- turbostat_submit(name, "percent", "c6", 100.0 * c->c6/t->tsc);
- if (do_core_cstate & (1 << 7))
- turbostat_submit(name, "percent", "c7", 100.0 * c->c7/t->tsc);
-
- if (do_dts)
- turbostat_submit(NULL, "temperature", name, c->core_temp_c);
-
- /* print per-package data only for 1st core in package */
- if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
- goto done;
-
- ssnprintf(name, sizeof(name), "pkg%02d", p->package_id);
-
- if (do_ptm)
- turbostat_submit(NULL, "temperature", name, p->pkg_temp_c);
-
- if (do_pkg_cstate & (1 << 2))
- turbostat_submit(name, "percent", "pc2", 100.0 * p->pc2/t->tsc);
- if (do_pkg_cstate & (1 << 3))
- turbostat_submit(name, "percent", "pc3", 100.0 * p->pc3/t->tsc);
- if (do_pkg_cstate & (1 << 6))
- turbostat_submit(name, "percent", "pc6", 100.0 * p->pc6/t->tsc);
- if (do_pkg_cstate & (1 << 7))
- turbostat_submit(name, "percent", "pc7", 100.0 * p->pc7/t->tsc);
- if (do_pkg_cstate & (1 << 8))
- turbostat_submit(name, "percent", "pc8", 100.0 * p->pc8/t->tsc);
- if (do_pkg_cstate & (1 << 9))
- turbostat_submit(name, "percent", "pc9", 100.0 * p->pc9/t->tsc);
- if (do_pkg_cstate & (1 << 10))
- turbostat_submit(name, "percent", "pc10", 100.0 * p->pc10/t->tsc);
-
- if (do_rapl) {
- if (do_rapl & RAPL_PKG)
- turbostat_submit(name, "power", "Pkg_W", p->energy_pkg * rapl_energy_units / interval_float);
- if (do_rapl & RAPL_CORES)
- turbostat_submit(name, "power", "Cor_W", p->energy_cores * rapl_energy_units / interval_float);
- if (do_rapl & RAPL_GFX)
- turbostat_submit(name, "power", "GFX_W", p->energy_gfx * rapl_energy_units / interval_float);
- if (do_rapl & RAPL_DRAM)
- turbostat_submit(name, "power", "RAM_W", p->energy_dram * rapl_energy_units / interval_float);
- }
-done:
- return 0;
-}
-
-static int
-turbostat_read(user_data_t * not_used)
-{
- int ret;
-
- if (!allocated) {
- if ((ret = setup_all_buffers()) < 0)
- return ret;
- }
-
- if (for_all_proc_cpus(cpu_is_not_present)) {
- free_all_buffers();
- if ((ret = setup_all_buffers()) < 0)
- return ret;
- if (for_all_proc_cpus(cpu_is_not_present))
- return -ERR_CPU_NOT_PRESENT;
- }
-
- /* 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)
- return -ERR_CPU_SAVE_SCHED_AFFINITY;
-
- if (!initialized) {
- if ((ret = for_all_cpus(get_counters, EVEN_COUNTERS)) < 0)
- goto out;
- gettimeofday(&tv_even, (struct timezone *)NULL);
- is_even = 1;
- initialized = 1;
- ret = 0;
- goto out;
- }
-
- if (is_even) {
- if ((ret = for_all_cpus(get_counters, ODD_COUNTERS)) < 0)
- goto out;
- gettimeofday(&tv_odd, (struct timezone *)NULL);
- is_even = 0;
- timersub(&tv_odd, &tv_even, &tv_delta);
- if ((ret = for_all_cpus_delta(ODD_COUNTERS, EVEN_COUNTERS)) < 0)
- goto out;
- if ((ret = for_all_cpus(submit_counters, DELTA_COUNTERS)) < 0)
- goto out;
- } else {
- if ((ret = for_all_cpus(get_counters, EVEN_COUNTERS)) < 0)
- goto out;
- gettimeofday(&tv_even, (struct timezone *)NULL);
- is_even = 1;
- timersub(&tv_even, &tv_odd, &tv_delta);
- if ((ret = for_all_cpus_delta(EVEN_COUNTERS, ODD_COUNTERS)) < 0)
- goto out;
- if ((ret = for_all_cpus(submit_counters, DELTA_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);
- return ret;
-}
-
-static int __attribute__((warn_unused_result))
-check_dev_msr()
-{
- struct stat sb;
-
- if (stat("/dev/cpu/0/msr", &sb)) {
- ERROR("no /dev/cpu/0/msr, try \"# modprobe msr\"");
- return -ERR_NO_MSR;
- }
- return 0;
-}