* Added a new magical value for each activity in file.
A format change can now hit only one activity instead of
the whole file.
- * Added hugepages utilization statistics to sar.
+ * Added CPU average clock frequency statistics to sar and sadc.
+ * Added hugepages utilization statistics to sar and sadc.
* [Ivana Varekova]: Moved manual pages to $prefix/share/man
instead of $prefix/man.
* [Ivana Varekova]: Fixed configure's --disable-man-group option.
* sar manual page updated.
* DTD and XSD documents updated.
* Made sysstat git aware.
+ * CREDITS file updated.
2010/09/12: Version 9.1.5 - Sebastien Godard (sysstat <at> orange.fr)
* Added voltage inputs statistics to sar and sadc.
Urban Widmark <urban@sve[...].se>
Yu Yongcong <yuyc@cn.[...].com>
Peter Zaitsev <pz@spy[...].ru>
+ Zhen Zhang <furykerry@gma[...].com>
--
Sebastien Godard (sysstat <at> orange.fr) is the author and the current
/* Voltage inputs */
struct activity pwr_in_act = {
.id = A_PWR_IN,
- .options = AO_CLOSE_MARKUP,
+ .options = AO_NULL,
.magic = ACTIVITY_MAGIC_BASE,
#ifdef SOURCE_SADC
.f_count = wrap_get_in_nr,
.bitmap = NULL
};
+/* CPU weighted frequency */
+struct activity pwr_wghfreq_act = {
+ .id = A_PWR_WGHFREQ,
+ .options = AO_CLOSE_MARKUP,
+ .magic = ACTIVITY_MAGIC_BASE,
+#ifdef SOURCE_SADC
+ .f_count = wrap_get_cpu_nr,
+ .f_count2 = wrap_get_freq_nr,
+ .f_read = wrap_read_time_in_state,
+#endif
+#ifdef SOURCE_SAR
+ .f_print = print_pwr_wghfreq_stats,
+ .f_print_avg = print_pwr_wghfreq_stats,
+#endif
+#ifdef SOURCE_SADF
+ .f_render = render_pwr_wghfreq_stats,
+ .f_xml_print = xml_print_pwr_wghfreq_stats,
+ .hdr_line = "CPU;wghMHz",
+ .name = "A_PWR_WGHFREQ",
+#endif
+ .nr = -1,
+ .nr2 = 1,
+ .fsize = STATS_PWR_WGHFREQ_SIZE,
+ .msize = STATS_PWR_WGHFREQ_SIZE,
+ .opt_flags = 0,
+ .buf = {NULL, NULL, NULL},
+ .bitmap = &cpu_bitmap
+};
+
+
/*
* Array of activities.
*/
&pwr_fan_act,
&pwr_temp_act,
&pwr_in_act,
- &huge_act
+ &huge_act,
+ &pwr_wghfreq_act
};
#define K_UTC "UTC"
/* Files */
-#define STAT "/proc/stat"
-#define UPTIME "/proc/uptime"
-#define PPARTITIONS "/proc/partitions"
-#define DISKSTATS "/proc/diskstats"
-#define INTERRUPTS "/proc/interrupts"
-#define MEMINFO "/proc/meminfo"
-#define SYSFS_BLOCK "/sys/block"
-#define SYSFS_DEVCPU "/sys/devices/system/cpu"
-#define S_STAT "stat"
-#define DEVMAP_DIR "/dev/mapper"
+#define STAT "/proc/stat"
+#define UPTIME "/proc/uptime"
+#define PPARTITIONS "/proc/partitions"
+#define DISKSTATS "/proc/diskstats"
+#define INTERRUPTS "/proc/interrupts"
+#define MEMINFO "/proc/meminfo"
+#define SYSFS_BLOCK "/sys/block"
+#define SYSFS_DEVCPU "/sys/devices/system/cpu"
+#define SYSFS_TIME_IN_STATE "cpufreq/stats/time_in_state"
+#define S_STAT "stat"
+#define DEVMAP_DIR "/dev/mapper"
#define MAX_FILE_LEN 256
#define MAX_PF_NAME 1024
-.TH SAR 1 "SEPTEMBER 2010" Linux "Linux User's Manual" -*- nroff -*-
+.TH SAR 1 "OCTOBER 2010" Linux "Linux User's Manual" -*- nroff -*-
.SH NAME
sar \- Collect, report, or save system activity information.
.SH SYNOPSIS
Possible keywords are
.BR CPU ,
.BR FAN ,
+.BR FREQ ,
.BR IN
and
.BR TEMP .
With the
.B CPU
-keyword, statistics about CPU clock frequency are reported.
+keyword, statistics about CPU are reported.
The following value is displayed:
.B MHz
.RS
.RS
-CPU clock frequency in MHz.
+Instantaneous CPU clock frequency in MHz.
.RE
With the
Sensor device name.
.RE
+With the
+.B FREQ
+keyword, statistics about CPU clock frequency are reported.
+The following value is displayed:
+
+.B wghMHz
+.RS
+Weighted average CPU clock frequency in MHz.
+Note that the cpufreq-stats driver must be compiled in the
+kernel for this option to work.
+.RE
+
With the
.B IN
keyword, statistics about voltage inputs are reported.
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: sysstat <at> orange.fr\n"
-"POT-Creation-Date: 2010-09-18 15:03+0200\n"
+"POT-Creation-Date: 2010-10-23 15:32+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "sysstat version %s\n"
msgstr ""
-#: ioconf.c:490 rd_stats.c:72 rd_stats.c:1848 sa_common.c:1052 sadc.c:593
-#: sadc.c:602 sadc.c:662
+#: ioconf.c:490 rd_stats.c:72 rd_stats.c:2145 sa_common.c:1057 sadc.c:607
+#: sadc.c:616 sadc.c:676
#, c-format
msgid "Cannot open %s: %s\n"
msgstr ""
"ALL } ] [ -V ]\n"
msgstr ""
-#: mpstat.c:530 pidstat.c:1806 sar.c:361
+#: mpstat.c:530 pidstat.c:1806 sar.c:362
msgid "Average:"
msgstr ""
"[ -p { <pid> [,...] | SELF | ALL } ] [ -T { TASK | CHILD | ALL } ]\n"
msgstr ""
-#: pidstat.c:199 sar.c:979
+#: pidstat.c:199 sar.c:989
#, c-format
msgid "Requested activities not available\n"
msgstr ""
-#: rd_stats.c:1894
+#: rd_stats.c:2191
#, c-format
msgid "Cannot handle so many processors!\n"
msgstr ""
"Current sysstat version can no longer read the format of this file (%#x)\n"
msgstr ""
-#: sa_common.c:1135
+#: sa_common.c:1164
#, c-format
msgid "Requested activities not available in file %s\n"
msgstr ""
"[ -S { INT | DISK | IPV6 | POWER | SNMP | XDISK | ALL | XALL } ]\n"
msgstr ""
-#: sadc.c:206
+#: sadc.c:207
#, c-format
msgid "Cannot write data to system activity file: %s\n"
msgstr ""
-#: sadc.c:480
+#: sadc.c:494
#, c-format
msgid "Cannot write system activity file header: %s\n"
msgstr ""
-#: sadc.c:756
+#: sadc.c:775
#, c-format
msgid "Cannot append data to that file (%s)\n"
msgstr ""
msgid "List of activities:\n"
msgstr ""
+#: sadf.c:638
+#, c-format
+msgid "\t[Unknown activity format]"
+msgstr ""
+
#: sar.c:104
#, c-format
msgid ""
"\t-m { <keyword> [,...] | ALL }\n"
"\t\tPower management statistics\n"
"\t\tKeywords are:\n"
-"\t\tCPU\tCPU clock frequency\n"
+"\t\tCPU\tCPU instantaneous clock frequency\n"
"\t\tFAN\tFans speed\n"
+"\t\tFREQ\tCPU average clock frequency\n"
"\t\tIN\tVoltage inputs\n"
"\t\tTEMP\tDevices temperature\n"
msgstr ""
-#: sar.c:140
+#: sar.c:141
#, c-format
msgid ""
"\t-n { <keyword> [,...] | ALL }\n"
"\t\tUDP6\tUDP traffic\t(v6)\n"
msgstr ""
-#: sar.c:161
+#: sar.c:162
#, c-format
msgid "\t-q\tQueue length and load average statistics\n"
msgstr ""
-#: sar.c:162
+#: sar.c:163
#, c-format
msgid "\t-r\tMemory utilization statistics\n"
msgstr ""
-#: sar.c:163
+#: sar.c:164
#, c-format
msgid "\t-R\tMemory statistics\n"
msgstr ""
-#: sar.c:164
+#: sar.c:165
#, c-format
msgid "\t-S\tSwap space utilization statistics\n"
msgstr ""
-#: sar.c:165
+#: sar.c:166
#, c-format
msgid ""
"\t-u [ ALL ]\n"
"\t\tCPU utilization statistics\n"
msgstr ""
-#: sar.c:167
+#: sar.c:168
#, c-format
msgid "\t-v\tKernel table statistics\n"
msgstr ""
-#: sar.c:168
+#: sar.c:169
#, c-format
msgid "\t-w\tTask creation and system switching statistics\n"
msgstr ""
-#: sar.c:169
+#: sar.c:170
#, c-format
msgid "\t-W\tSwapping statistics\n"
msgstr ""
-#: sar.c:170
+#: sar.c:171
#, c-format
msgid "\t-y\tTTY device statistics\n"
msgstr ""
-#: sar.c:213
+#: sar.c:214
#, c-format
msgid "End of data collecting unexpected\n"
msgstr ""
-#: sar.c:781
+#: sar.c:783
#, c-format
msgid "Invalid data format\n"
msgstr ""
-#: sar.c:785
+#: sar.c:787
#, c-format
msgid "Using a wrong data collector from a different sysstat version\n"
msgstr ""
-#: sar.c:805
+#: sar.c:811
#, c-format
msgid "Inconsistent input data\n"
msgstr ""
-#: sar.c:1226
+#: sar.c:1236
#, c-format
msgid "-f and -o options are mutually exclusive\n"
msgstr ""
-#: sar.c:1232
+#: sar.c:1242
#, c-format
msgid "Not reading from a system activity file (use -f option)\n"
msgstr ""
-#: sar.c:1333
+#: sar.c:1343
#, c-format
msgid "Cannot find the data collector (%s)\n"
msgstr ""
{
stub_print_huge_stats(a, prev, curr, itv, TRUE);
}
+
+/*
+ ***************************************************************************
+ * Display CPU weighted frequency statistics. This function is used to
+ * display instantaneous and average statistics.
+ *
+ * IN:
+ * @a Activity structure with statistics.
+ * @prev Index in array where stats used as reference are.
+ * @curr Index in array for current sample statistics.
+ * @dispavg True if displaying average statistics.
+ ***************************************************************************
+ */
+void print_pwr_wghfreq_stats(struct activity *a, int prev, int curr,
+ unsigned long long itv)
+{
+ int i, k;
+ struct stats_pwr_wghfreq *spc, *spp, *spc_k, *spp_k;
+ unsigned long long tis, tisfreq;
+
+ if (dis) {
+ printf("\n%-11s CPU wghMHz\n",
+ timestamp[!curr]);
+ }
+
+ for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+
+ /*
+ * The size of a->buf[...] CPU structure may be different from the default
+ * sizeof(struct stats_pwr_wghfreq) value if data have been read from a file!
+ * That's why we don't use a syntax like:
+ * spc = (struct stats_pwr_wghfreq *) a->buf[...] + i;
+ */
+ spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr] + i * a->msize * a->nr2);
+ spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[prev] + i * a->msize * a->nr2);
+
+ /*
+ * Note: a->nr is in [1, NR_CPUS + 1].
+ * Bitmap size is provided for (NR_CPUS + 1) CPUs.
+ * Anyway, NR_CPUS may vary between the version of sysstat
+ * used by sadc to create a file, and the version of sysstat
+ * used by sar to read it...
+ */
+
+ /* Should current CPU (including CPU "all") be displayed? */
+ if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+
+ /* Yes: Display it */
+ printf("%-11s", timestamp[curr]);
+
+ if (!i) {
+ /* This is CPU "all" */
+ printf(" all");
+ }
+ else {
+ printf(" %3d", i - 1);
+ }
+
+ tisfreq = 0;
+ tis = 0;
+
+ for (k = 0; k < a->nr2; k++) {
+
+ spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
+ if (!spc_k->freq)
+ break;
+ spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
+
+ tisfreq += (spc_k->freq / 1000) *
+ (spc_k->time_in_state - spp_k->time_in_state);
+ tis += (spc_k->time_in_state - spp_k->time_in_state);
+ }
+
+ /* Display weighted frequency for current CPU */
+ printf(" %9.2f\n", tis ? ((double) tisfreq) / tis : 0.0);
+ }
+ }
+}
(struct activity *, int, int, unsigned long long);
extern __print_funct_t print_huge_stats
(struct activity *, int, int, unsigned long long);
+extern __print_funct_t print_pwr_wghfreq_stats
+ (struct activity *, int, int, unsigned long long);
/* Functions used to display average statistics */
extern __print_funct_t print_avg_memory_stats
0.0);
}
+/*
+ ***************************************************************************
+ * Display weighted CPU frequency statistics in selected format.
+ *
+ * IN:
+ * @a Activity structure with statistics.
+ * @isdb Flag, true if db printing, false if ppc printing.
+ * @pre Prefix string for output entries
+ * @curr Index in array for current sample statistics.
+ * @itv Interval of time in jiffies.
+ ***************************************************************************
+ */
+__print_funct_t render_pwr_wghfreq_stats(struct activity *a, int isdb, char *pre,
+ int curr, unsigned long long itv)
+{
+ int i, k;
+ struct stats_pwr_wghfreq *spc, *spp, *spc_k, *spp_k;
+ unsigned long long tis, tisfreq;
+ int pt_newlin
+ = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
+
+ for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+
+ spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr] + i * a->msize * a->nr2);
+ spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[!curr] + i * a->msize * a->nr2);
+
+ /* Should current CPU (including CPU "all") be displayed? */
+ if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+
+ /* Yes... */
+ tisfreq = 0;
+ tis = 0;
+
+ for (k = 0; k < a->nr2; k++) {
+
+ spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
+ if (!spc_k->freq)
+ break;
+ spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
+
+ tisfreq += (spc_k->freq / 1000) *
+ (spc_k->time_in_state - spp_k->time_in_state);
+ tis += (spc_k->time_in_state - spp_k->time_in_state);
+ }
+
+ if (!i) {
+ /* This is CPU "all" */
+ render(isdb, pre, pt_newlin,
+ "all\twghMHz",
+ "-1", NULL,
+ NOVAL,
+ tis ? ((double) tisfreq) / tis : 0.0);
+ }
+ else {
+ render(isdb, pre, pt_newlin,
+ "cpu%d\twghMHz",
+ "%d", cons(iv, i - 1, NOVAL),
+ NOVAL,
+ tis ? ((double) tisfreq) / tis : 0.0);
+ }
+ }
+ }
+}
+
/*
***************************************************************************
* Print tabulations
xprintf(tab, "</hugepages>");
}
+
+/*
+ ***************************************************************************
+ * Display weighted CPU frequency statistics in XML.
+ *
+ * IN:
+ * @a Activity structure with statistics.
+ * @curr Index in array for current sample statistics.
+ * @tab Indentation in XML output.
+ * @itv Interval of time in jiffies.
+ ***************************************************************************
+ */
+__print_funct_t xml_print_pwr_wghfreq_stats(struct activity *a, int curr, int tab,
+ unsigned long long itv)
+{
+ int i, k;
+ struct stats_pwr_wghfreq *spc, *spp, *spc_k, *spp_k;
+ unsigned long long tis, tisfreq;
+ char cpuno[8];
+
+ if (!IS_SELECTED(a->options) || (a->nr <= 0))
+ goto close_xml_markup;
+
+ xml_markup_power_management(tab, OPEN_XML_MARKUP);
+ tab++;
+
+ xprintf(tab++, "<cpu-weighted-frequency unit=\"MHz\">");
+
+ for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+
+ spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr] + i * a->msize * a->nr2);
+ spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[!curr] + i * a->msize * a->nr2);
+
+ /* Should current CPU (including CPU "all") be displayed? */
+ if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+
+ /* Yes... */
+ tisfreq = 0;
+ tis = 0;
+
+ for (k = 0; k < a->nr2; k++) {
+
+ spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
+ if (!spc_k->freq)
+ break;
+ spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
+
+ tisfreq += (spc_k->freq / 1000) *
+ (spc_k->time_in_state - spp_k->time_in_state);
+ tis += (spc_k->time_in_state - spp_k->time_in_state);
+ }
+
+ if (!i) {
+ /* This is CPU "all" */
+ strcpy(cpuno, "all");
+ }
+ else {
+ sprintf(cpuno, "%d", i - 1);
+ }
+
+ xprintf(tab, "<cpuwfreq number=\"%s\" "
+ "weighted-frequency=\"%.2f\"/>",
+ cpuno,
+ tis ? ((double) tisfreq) / tis : 0.0);
+ }
+ }
+
+ xprintf(--tab, "</cpu-weighted-frequency>");
+ tab--;
+
+close_xml_markup:
+ if (CLOSE_MARKUP(a->options)) {
+ xml_markup_power_management(tab, CLOSE_XML_MARKUP);
+ }
+}
(struct activity *, int, char *, int, unsigned long long);
extern __print_funct_t render_huge_stats
(struct activity *, int, char *, int, unsigned long long);
+extern __print_funct_t render_pwr_wghfreq_stats
+ (struct activity *, int, char *, int, unsigned long long);
/* Functions used to display statistics in XML */
extern void xprintf
(struct activity *, int, int, unsigned long long);
extern __print_funct_t xml_print_huge_stats
(struct activity *, int, int, unsigned long long);
+extern __print_funct_t xml_print_pwr_wghfreq_stats
+ (struct activity *, int, int, unsigned long long);
#endif /* _PRF_STATS_H */
fclose(fp);
}
+/*
+ ***************************************************************************
+ * Read CPU frequency statistics.
+ *
+ * IN:
+ * @st_pwr_cpufreq Structure where stats will be saved.
+ * @nbr Total number of CPU (including cpu "all").
+ *
+ * OUT:
+ * @st_pwr_cpufreq Structure with statistics.
+ ***************************************************************************
+ */
+void read_cpuinfo(struct stats_pwr_cpufreq *st_pwr_cpufreq, int nbr)
+{
+ FILE *fp;
+ struct stats_pwr_cpufreq *st_pwr_cpufreq_i;
+ char line[1024];
+ int proc_nb = 0, nr = 0;
+ unsigned int ifreq, dfreq;
+
+ if ((fp = fopen(CPUINFO, "r")) == NULL)
+ return;
+
+ st_pwr_cpufreq->cpufreq = 0;
+
+ while (fgets(line, 1024, fp) != NULL) {
+
+ if (!strncmp(line, "processor\t", 10)) {
+ sscanf(strchr(line, ':') + 1, "%d", &proc_nb);
+ }
+
+ else if (!strncmp(line, "cpu MHz\t", 8)) {
+ sscanf(strchr(line, ':') + 1, "%u.%u", &ifreq, &dfreq);
+
+ if (proc_nb < (nbr - 1)) { /* FIXME: quelle reaction pour un kernel non SMP 1 proc? */
+ /* Save current CPU frequency */
+ st_pwr_cpufreq_i = st_pwr_cpufreq + proc_nb + 1;
+ st_pwr_cpufreq_i->cpufreq = ifreq * 100 + dfreq / 10;
+
+ /* Also save it to compute an average CPU frequency */
+ st_pwr_cpufreq->cpufreq += st_pwr_cpufreq_i->cpufreq;
+ nr++;
+ }
+ }
+ }
+
+ fclose(fp);
+
+ if (nr) {
+ /* Compute average CPU frequency for this machine */
+ st_pwr_cpufreq->cpufreq /= nr;
+ }
+}
+
+/*
+ ***************************************************************************
+ * Read fan statistics.
+ *
+ * IN:
+ * @st_pwr_fan Structure where stats will be saved.
+ * @nbr Total number of fans.
+ *
+ * OUT:
+ * @st_pwr_fan Structure with statistics.
+ ***************************************************************************
+ */
+void read_fan(struct stats_pwr_fan *st_pwr_fan, int nbr)
+{
+#ifdef HAVE_SENSORS
+ int count = 0;
+ const sensors_chip_name *chip;
+ const sensors_feature *feature;
+ const sensors_subfeature *sub;
+ struct stats_pwr_fan *st_pwr_fan_i;
+ int chip_nr = 0;
+ int i, j;
+
+ memset(st_pwr_fan, 0, STATS_PWR_FAN_SIZE);
+ int err = 0;
+
+ while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
+ i = 0;
+ while ((feature = sensors_get_features(chip, &i))) {
+ if ((feature->type == SENSORS_FEATURE_FAN) && (count < nbr)) {
+ j = 0;
+ st_pwr_fan_i = st_pwr_fan + count;
+ sensors_snprintf_chip_name(st_pwr_fan_i->device, MAX_SENSORS_DEV_LEN, chip);
+
+ while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
+ if ((sub->type == SENSORS_SUBFEATURE_FAN_INPUT) &&
+ (sub->flags & SENSORS_MODE_R)) {
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_fan_i->rpm))) {
+ st_pwr_fan_i->rpm = 0;
+ }
+ }
+ else if ((sub->type == SENSORS_SUBFEATURE_FAN_MIN)) {
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_fan_i->rpm_min))) {
+ st_pwr_fan_i->rpm_min = 0;
+ }
+ }
+ }
+ count++;
+ }
+ }
+ }
+#endif /* HAVE_SENSORS */
+}
+
+/*
+ ***************************************************************************
+ * Read device temperature statistics.
+ *
+ * IN:
+ * @st_pwr_temp Structure where stats will be saved.
+ * @nbr Total number of fans.
+ *
+ * OUT:
+ * @st_pwr_temp Structure with statistics.
+ ***************************************************************************
+ */
+void read_temp(struct stats_pwr_temp *st_pwr_temp, int nbr)
+{
+#ifdef HAVE_SENSORS
+ int count = 0;
+ const sensors_chip_name *chip;
+ const sensors_feature *feature;
+ const sensors_subfeature *sub;
+ struct stats_pwr_temp *st_pwr_temp_i;
+ int chip_nr = 0;
+ int i, j;
+
+ memset(st_pwr_temp, 0, STATS_PWR_TEMP_SIZE);
+ int err = 0;
+
+ while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
+ i = 0;
+ while ((feature = sensors_get_features(chip, &i))) {
+ if ((feature->type == SENSORS_FEATURE_TEMP) && (count < nbr)) {
+ j = 0;
+ st_pwr_temp_i = st_pwr_temp + count;
+ sensors_snprintf_chip_name(st_pwr_temp_i->device, MAX_SENSORS_DEV_LEN, chip);
+
+ while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
+ if ((sub->type == SENSORS_SUBFEATURE_TEMP_INPUT) &&
+ (sub->flags & SENSORS_MODE_R)) {
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp))) {
+ st_pwr_temp_i->temp = 0;
+ }
+ }
+ else if ((sub->type == SENSORS_SUBFEATURE_TEMP_MIN)) {
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp_min))) {
+ st_pwr_temp_i->temp_min = 0;
+ }
+ }
+ else if ((sub->type == SENSORS_SUBFEATURE_TEMP_MAX)) {
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp_max))) {
+ st_pwr_temp_i->temp_max = 0;
+ }
+ }
+ }
+ count++;
+ }
+ }
+ }
+#endif /* HAVE_SENSORS */
+}
+
+/*
+ ***************************************************************************
+ * Read voltage inputs statistics.
+ *
+ * IN:
+ * @st_pwr_in Structure where stats will be saved.
+ * @nbr Total number of voltage inputs.
+ *
+ * OUT:
+ * @st_pwr_in Structure with statistics.
+ ***************************************************************************
+ */
+void read_in(struct stats_pwr_in *st_pwr_in, int nbr)
+{
+#ifdef HAVE_SENSORS
+ int count = 0;
+ const sensors_chip_name *chip;
+ const sensors_feature *feature;
+ const sensors_subfeature *sub;
+ struct stats_pwr_in *st_pwr_in_i;
+ int chip_nr = 0;
+ int i, j;
+
+ memset(st_pwr_in, 0, STATS_PWR_IN_SIZE);
+ int err = 0;
+
+ while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
+ i = 0;
+ while ((feature = sensors_get_features(chip, &i))) {
+ if ((feature->type == SENSORS_FEATURE_IN) && (count < nbr)) {
+ j = 0;
+ st_pwr_in_i = st_pwr_in + count;
+ sensors_snprintf_chip_name(st_pwr_in_i->device, MAX_SENSORS_DEV_LEN, chip);
+
+ while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
+ if ((sub->type == SENSORS_SUBFEATURE_IN_INPUT) &&
+ (sub->flags & SENSORS_MODE_R)) {
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in))) {
+ st_pwr_in_i->in = 0;
+ }
+ }
+ else if ((sub->type == SENSORS_SUBFEATURE_IN_MIN)) {
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in_min))) {
+ st_pwr_in_i->in_min = 0;
+ }
+ }
+ else if ((sub->type == SENSORS_SUBFEATURE_IN_MAX)) {
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in_max))) {
+ st_pwr_in_i->in_max = 0;
+ }
+ }
+ }
+ count++;
+ }
+ }
+ }
+#endif /* HAVE_SENSORS */
+}
+
+/*
+ ***************************************************************************
+ * Read hugepages statistics from /proc/meminfo.
+ *
+ * IN:
+ * @st_huge Structure where stats will be saved.
+ *
+ * OUT:
+ * @st_huge Structure with statistics.
+ ***************************************************************************
+ */
+void read_meminfo_huge(struct stats_huge *st_huge)
+{
+ FILE *fp;
+ char line[128];
+ unsigned long szhkb = 0;
+
+ if ((fp = fopen(MEMINFO, "r")) == NULL)
+ return;
+
+ while (fgets(line, 128, fp) != NULL) {
+
+ if (!strncmp(line, "HugePages_Total:", 16)) {
+ /* Read the total number of huge pages */
+ sscanf(line + 16, "%lu", &st_huge->tlhkb);
+ }
+ else if (!strncmp(line, "HugePages_Free:", 15)) {
+ /* Read the number of free huge pages */
+ sscanf(line + 15, "%lu", &st_huge->frhkb);
+ }
+ else if (!strncmp(line, "Hugepagesize:", 13)) {
+ /* Read the default size of a huge page in kB */
+ sscanf(line + 13, "%lu", &szhkb);
+ }
+ }
+
+ fclose(fp);
+
+ /* We want huge pages stats in kB and not expressed in a number of pages */
+ st_huge->tlhkb *= szhkb;
+ st_huge->frhkb *= szhkb;
+}
+
+/*
+ ***************************************************************************
+ * Read CPU average frequencies statistics.
+ *
+ * IN:
+ * @st_pwr_wghfreq Structure where stats will be saved.
+ * @cpu_nr CPU number for which time_in_state date will be read.
+ * @nbr Total number of states (frequencies).
+ *
+ * OUT:
+ * @st_pwr_wghfreq Structure with statistics.
+ ***************************************************************************
+ */
+void read_time_in_state(struct stats_pwr_wghfreq *st_pwr_wghfreq, int cpu_nr, int nbr)
+{
+ FILE *fp;
+ struct stats_pwr_wghfreq *st_pwr_wghfreq_j;
+ char filename[MAX_PF_NAME];
+ char line[128];
+ int j = 0;
+ unsigned long freq;
+ unsigned long long time_in_state;
+
+ snprintf(filename, MAX_PF_NAME, "%s/cpu%d/%s",
+ SYSFS_DEVCPU, cpu_nr, SYSFS_TIME_IN_STATE);
+ if ((fp = fopen(filename, "r")) == NULL)
+ return;
+
+ while (fgets(line, 128, fp) != NULL) {
+
+ sscanf(line, "%lu %llu", &freq, &time_in_state);
+
+ if (j < nbr) {
+ /* Save current frequency and time */
+ st_pwr_wghfreq_j = st_pwr_wghfreq + j;
+ st_pwr_wghfreq_j->freq = freq;
+ st_pwr_wghfreq_j->time_in_state = time_in_state;
+ j++;
+ }
+ }
+
+ fclose(fp);
+}
+
/*
***************************************************************************
* Read machine uptime, independently of the number of processors.
return;
sscanf(line, "%lu.%lu", &up_sec, &up_cent);
- *uptime = (unsigned long long) up_sec * HZ + (unsigned long long) up_cent * HZ / 100;
+ *uptime = (unsigned long long) up_sec * HZ +
+ (unsigned long long) up_cent * HZ / 100;
fclose(fp);
if ((fp = fopen(STAT, "r")) == NULL)
return 0;
-
+
while (fgets(line, 8192, fp) != NULL) {
if (!strncmp(line, "intr ", 5)) {
-
+
while (pos < strlen(line)) {
in++;
pos += strcspn(line + pos + 1, " ") + 1;
}
fclose(fp);
-
+
return in;
}
int get_disk_nr(unsigned int f)
{
int disk_nr;
-
+
/*
* Partitions are taken into account by sar -d only with
* kernels 2.6.25 and later.
}
fclose(fp);
-
+
if (line) {
free(line);
}
return irq;
}
-/*
- ***************************************************************************
- * Read CPU frequency statistics.
- *
- * IN:
- * @st_pwr_cpufreq Structure where stats will be saved.
- * @nbr Total number of CPU (including cpu "all").
- *
- * OUT:
- * @st_pwr_cpufreq Structure with statistics.
- ***************************************************************************
- */
-void read_cpuinfo(struct stats_pwr_cpufreq *st_pwr_cpufreq, int nbr)
-{
- FILE *fp;
- struct stats_pwr_cpufreq *st_pwr_cpufreq_i;
- char line[1024];
- int proc_nb = 0, nr = 0;
- unsigned int ifreq, dfreq;
-
- if ((fp = fopen(CPUINFO, "r")) == NULL)
- return;
-
- st_pwr_cpufreq->cpufreq = 0;
-
- while (fgets(line, 1024, fp) != NULL) {
-
- if (!strncmp(line, "processor\t", 10)) {
- sscanf(strchr(line, ':') + 1, "%d", &proc_nb);
- }
-
- else if (!strncmp(line, "cpu MHz\t", 8)) {
- sscanf(strchr(line, ':') + 1, "%u.%u", &ifreq, &dfreq);
-
- if (proc_nb < (nbr - 1)) {
- /* Save current CPU frequency */
- st_pwr_cpufreq_i = st_pwr_cpufreq + proc_nb + 1;
- st_pwr_cpufreq_i->cpufreq = ifreq * 100 + dfreq / 10;
-
- /* Also save it to compute an average CPU frequency */
- st_pwr_cpufreq->cpufreq += st_pwr_cpufreq_i->cpufreq;
- nr++;
- }
- }
- }
-
- fclose(fp);
-
- if (nr) {
- /* Compute average CPU frequency for this machine */
- st_pwr_cpufreq->cpufreq /= nr;
- }
-}
-
#ifdef HAVE_SENSORS
/*
***************************************************************************
#endif /* HAVE_SENSORS */
}
-/*
- ***************************************************************************
- * Read fan statistics.
- *
- * IN:
- * @st_pwr_fan Structure where stats will be saved.
- * @nbr Total number of fans.
- *
- * OUT:
- * @st_pwr_fan Structure with statistics.
- ***************************************************************************
- */
-void read_fan(struct stats_pwr_fan *st_pwr_fan, int nbr)
-{
-#ifdef HAVE_SENSORS
- int count = 0;
- const sensors_chip_name *chip;
- const sensors_feature *feature;
- const sensors_subfeature *sub;
- struct stats_pwr_fan *st_pwr_fan_i;
- int chip_nr = 0;
- int i, j;
-
- memset(st_pwr_fan, 0, STATS_PWR_FAN_SIZE);
- int err = 0;
-
- while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
- i = 0;
- while ((feature = sensors_get_features(chip, &i))) {
- if ((feature->type == SENSORS_FEATURE_FAN) && (count < nbr)) {
- j = 0;
- st_pwr_fan_i = st_pwr_fan + count;
- sensors_snprintf_chip_name(st_pwr_fan_i->device, MAX_SENSORS_DEV_LEN, chip);
-
- while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
- if ((sub->type == SENSORS_SUBFEATURE_FAN_INPUT) &&
- (sub->flags & SENSORS_MODE_R)) {
- if ((err = sensors_get_value(chip, sub->number, &st_pwr_fan_i->rpm))) {
- st_pwr_fan_i->rpm = 0;
- }
- }
- else if ((sub->type == SENSORS_SUBFEATURE_FAN_MIN)) {
- if ((err = sensors_get_value(chip, sub->number, &st_pwr_fan_i->rpm_min))) {
- st_pwr_fan_i->rpm_min = 0;
- }
- }
- }
- count++;
- }
- }
- }
-#endif /* HAVE_SENSORS */
-}
-
/*
***************************************************************************
* Count the number of temperature sensors on the machine.
}
-/*
- ***************************************************************************
- * Read device temperature statistics.
- *
- * IN:
- * @st_pwr_temp Structure where stats will be saved.
- * @nbr Total number of fans.
- *
- * OUT:
- * @st_pwr_temp Structure with statistics.
- ***************************************************************************
- */
-void read_temp(struct stats_pwr_temp *st_pwr_temp, int nbr)
-{
-#ifdef HAVE_SENSORS
- int count = 0;
- const sensors_chip_name *chip;
- const sensors_feature *feature;
- const sensors_subfeature *sub;
- struct stats_pwr_temp *st_pwr_temp_i;
- int chip_nr = 0;
- int i, j;
-
- memset(st_pwr_temp, 0, STATS_PWR_TEMP_SIZE);
- int err = 0;
-
- while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
- i = 0;
- while ((feature = sensors_get_features(chip, &i))) {
- if ((feature->type == SENSORS_FEATURE_TEMP) && (count < nbr)) {
- j = 0;
- st_pwr_temp_i = st_pwr_temp + count;
- sensors_snprintf_chip_name(st_pwr_temp_i->device, MAX_SENSORS_DEV_LEN, chip);
-
- while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
- if ((sub->type == SENSORS_SUBFEATURE_TEMP_INPUT) &&
- (sub->flags & SENSORS_MODE_R)) {
- if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp))) {
- st_pwr_temp_i->temp = 0;
- }
- }
- else if ((sub->type == SENSORS_SUBFEATURE_TEMP_MIN)) {
- if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp_min))) {
- st_pwr_temp_i->temp_min = 0;
- }
- }
- else if ((sub->type == SENSORS_SUBFEATURE_TEMP_MAX)) {
- if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp_max))) {
- st_pwr_temp_i->temp_max = 0;
- }
- }
- }
- count++;
- }
- }
- }
-#endif /* HAVE_SENSORS */
-}
-
/*
***************************************************************************
* Count the number of voltage inputs on the machine.
/*
***************************************************************************
- * Read voltage inputs statistics.
- *
- * IN:
- * @st_pwr_in Structure where stats will be saved.
- * @nbr Total number of voltage inputs.
- *
- * OUT:
- * @st_pwr_in Structure with statistics.
- ***************************************************************************
- */
-void read_in(struct stats_pwr_in *st_pwr_in, int nbr)
-{
-#ifdef HAVE_SENSORS
- int count = 0;
- const sensors_chip_name *chip;
- const sensors_feature *feature;
- const sensors_subfeature *sub;
- struct stats_pwr_in *st_pwr_in_i;
- int chip_nr = 0;
- int i, j;
-
- memset(st_pwr_in, 0, STATS_PWR_IN_SIZE);
- int err = 0;
-
- while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
- i = 0;
- while ((feature = sensors_get_features(chip, &i))) {
- if ((feature->type == SENSORS_FEATURE_IN) && (count < nbr)) {
- j = 0;
- st_pwr_in_i = st_pwr_in + count;
- sensors_snprintf_chip_name(st_pwr_in_i->device, MAX_SENSORS_DEV_LEN, chip);
-
- while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
- if ((sub->type == SENSORS_SUBFEATURE_IN_INPUT) &&
- (sub->flags & SENSORS_MODE_R)) {
- if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in))) {
- st_pwr_in_i->in = 0;
- }
- }
- else if ((sub->type == SENSORS_SUBFEATURE_IN_MIN)) {
- if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in_min))) {
- st_pwr_in_i->in_min = 0;
- }
- }
- else if ((sub->type == SENSORS_SUBFEATURE_IN_MAX)) {
- if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in_max))) {
- st_pwr_in_i->in_max = 0;
- }
- }
- }
- count++;
- }
- }
- }
-#endif /* HAVE_SENSORS */
-}
-
-/*
- ***************************************************************************
- * Read hugepages statistics from /proc/meminfo.
- *
- * IN:
- * @st_huge Structure where stats will be saved.
+ * Count number of possible frequencies for CPU#0.
*
- * OUT:
- * @st_huge Structure with statistics.
+ * RETURNS:
+ * Number of frequencies.
***************************************************************************
*/
-void read_meminfo_huge(struct stats_huge *st_huge)
+int get_freq_nr(void)
{
FILE *fp;
+ char filename[MAX_PF_NAME];
char line[128];
- unsigned long szhkb = 0;
+ int freq = 0;
- if ((fp = fopen(MEMINFO, "r")) == NULL)
- return;
+ snprintf(filename, MAX_PF_NAME, "%s/cpu0/%s",
+ SYSFS_DEVCPU, SYSFS_TIME_IN_STATE);
+ if ((fp = fopen(filename, "r")) == NULL)
+ return 0; /* No time_in_state file for CPU#0 */
while (fgets(line, 128, fp) != NULL) {
-
- if (!strncmp(line, "HugePages_Total:", 16)) {
- /* Read the total number of huge pages */
- sscanf(line + 16, "%lu", &st_huge->tlhkb);
- }
- else if (!strncmp(line, "HugePages_Free:", 15)) {
- /* Read the number of free huge pages */
- sscanf(line + 15, "%lu", &st_huge->frhkb);
- }
- else if (!strncmp(line, "Hugepagesize:", 13)) {
- /* Read the default size of a huge page in kB */
- sscanf(line + 13, "%lu", &szhkb);
- }
+ freq++;
}
fclose(fp);
- /* We want huge pages stats in kB and not expressed in a number of pages */
- st_huge->tlhkb *= szhkb;
- st_huge->frhkb *= szhkb;
+ return freq;
}
#define STATS_HUGE_SIZE (sizeof(struct stats_memory))
+/*
+ * Structure for weighted CPU frequency statistics.
+ * In activity buffer: First structure is for global CPU utilisation ("all").
+ * Following structures are for each individual CPU (0, 1, etc.)
+ */
+struct stats_pwr_wghfreq {
+ unsigned long long time_in_state __attribute__ ((aligned (16)));
+ unsigned long freq __attribute__ ((aligned (16)));
+};
+
+#define STATS_PWR_WGHFREQ_SIZE (sizeof(struct stats_pwr_wghfreq))
+
/*
***************************************************************************
* Prototypes for functions used to read system statistics
read_in(struct stats_pwr_in *, int);
extern void
read_meminfo_huge(struct stats_huge *);
+extern void
+ read_time_in_state(struct stats_pwr_wghfreq *, int, int);
/*
***************************************************************************
get_temp_nr(void);
extern int
get_in_nr(void);
+extern int
+ get_freq_nr(void);
#endif /* _RD_STATS_H */
*/
/* Number of activities */
-#define NR_ACT 34
+#define NR_ACT 35
/* Activities */
#define A_CPU 1
#define A_PWR_TEMP 32
#define A_PWR_IN 33
#define A_HUGE 34
+#define A_PWR_WGHFREQ 35
/* Macro used to flag an activity that should be collected */
#define K_FAN "FAN"
#define K_TEMP "TEMP"
#define K_IN "IN"
+#define K_FREQ "FREQ"
/* sadc program */
#define SADC "sadc"
#define NR_IFACE_PREALLOC 2
#define NR_SERIAL_PREALLOC 2
#define NR_DISK_PREALLOC 3
+#define NR_FREQ_PREALLOC 0
#define UTSNAME_LEN 65
#define TIMESTAMP_LEN 16
wrap_get_temp_nr(struct activity *);
extern __nr_t
wrap_get_in_nr(struct activity *);
+extern __nr_t
+ wrap_get_freq_nr(struct activity *);
/* Functions used to read activities statistics */
extern __read_funct_t
wrap_read_in(struct activity *);
extern __read_funct_t
wrap_read_meminfo_huge(struct activity *);
+extern __read_funct_t
+ wrap_read_time_in_state(struct activity *);
/* Other functions */
extern void
else if (!strcmp(t, K_TEMP)) {
SELECT_ACTIVITY(A_PWR_TEMP);
}
+ else if (!strcmp(t, K_FREQ)) {
+ SELECT_ACTIVITY(A_PWR_WGHFREQ);
+ }
else if (!strcmp(t, K_ALL)) {
SELECT_ACTIVITY(A_PWR_CPUFREQ);
SELECT_ACTIVITY(A_PWR_FAN);
SELECT_ACTIVITY(A_PWR_IN);
SELECT_ACTIVITY(A_PWR_TEMP);
+ SELECT_ACTIVITY(A_PWR_WGHFREQ);
}
else
return 1;
extern unsigned int flags;
extern struct record_header record_hdr;
-/*
- ***************************************************************************
- * Count number of interrupts that are in /proc/stat file.
- * Truncate the number of different individual interrupts to NR_IRQS.
- *
- * IN:
- * @a Activity structure.
- *
- * RETURNS:
- * Number of interrupts, including total number of interrupts.
- * Value in [0, NR_IRQS + 1].
- ***************************************************************************
- */
-__nr_t wrap_get_irq_nr(struct activity *a)
-{
- __nr_t n;
-
- if ((n = get_irq_nr()) > (a->bitmap->b_size + 1)) {
- n = a->bitmap->b_size + 1;
- }
-
- return n;
-}
-
-/*
- ***************************************************************************
- * Find number of serial lines that support tx/rx accounting
- * in /proc/tty/driver/serial file.
- *
- * IN:
- * @a Activity structure.
- *
- * RETURNS:
- * Number of serial lines supporting tx/rx accouting + a pre-allocation
- * constant.
- ***************************************************************************
- */
-__nr_t wrap_get_serial_nr(struct activity *a)
-{
- __nr_t n = 0;
-
- if ((n = get_serial_nr()) > 0)
- return n + NR_SERIAL_PREALLOC;
-
- return 0;
-}
-
-/*
- ***************************************************************************
- * Find number of interfaces (network devices) that are in /proc/net/dev
- * file.
- *
- * IN:
- * @a Activity structure.
- *
- * RETURNS:
- * Number of network interfaces + a pre-allocation constant.
- ***************************************************************************
- */
-__nr_t wrap_get_iface_nr(struct activity *a)
-{
- __nr_t n = 0;
-
- if ((n = get_iface_nr()) > 0)
- return n + NR_IFACE_PREALLOC;
-
- return 0;
-}
-
-/*
- ***************************************************************************
- * Compute number of CPU structures to allocate.
- *
- * IN:
- * @a Activity structure.
- *
- * RETURNS:
- * Number of structures (value in [1, NR_CPUS + 1]).
- * 1 means that there is only one proc and non SMP kernel.
- * 2 means one proc and SMP kernel.
- * Etc.
- ***************************************************************************
- */
-__nr_t wrap_get_cpu_nr(struct activity *a)
-{
- return (get_cpu_nr(a->bitmap->b_size) + 1);
-}
-
-/*
- ***************************************************************************
- * Get number of devices in /proc/diskstats.
- * Always done, since disk stats must be read at least for sar -b
- * if not for sar -d.
- *
- * IN:
- * @a Activity structure.
- *
- * RETURNS:
- * Number of devices + a pre-allocation constant.
- ***************************************************************************
- */
-__nr_t wrap_get_disk_nr(struct activity *a)
-{
- __nr_t n = 0;
- unsigned int f = COLLECT_PARTITIONS(a->opt_flags);
-
- if ((n = get_disk_nr(f)) > 0)
- return n + NR_DISK_PREALLOC;
-
- return 0;
-}
-
/*
***************************************************************************
* Read CPU statistics.
return;
}
-/*
- ***************************************************************************
- * Get number of fan structures to allocate.
- *
- * IN:
- * @a Activity structure.
- *
- * RETURNS:
- * Number of structures.
- ***************************************************************************
- */
-__nr_t wrap_get_fan_nr(struct activity *a)
-{
- return (get_fan_nr());
-}
-
/*
***************************************************************************
* Read fan statistics.
/*
***************************************************************************
- * Get number of temp structures to allocate.
+ * Read temperature statistics.
*
* IN:
* @a Activity structure.
*
- * RETURNS:
- * Number of structures.
+ * OUT:
+ * @a Activity structure with statistics.
***************************************************************************
*/
-__nr_t wrap_get_temp_nr(struct activity *a)
+__read_funct_t wrap_read_temp(struct activity *a)
{
- return (get_temp_nr());
+ struct stats_pwr_temp *st_pwr_temp
+ = (struct stats_pwr_temp *) a->_buf0;
+
+ /* Read temperature stats */
+ read_temp(st_pwr_temp, a->nr);
+
+ return;
}
/*
***************************************************************************
- * Read temperature statistics.
+ * Read voltage input statistics.
*
* IN:
* @a Activity structure.
* @a Activity structure with statistics.
***************************************************************************
*/
-__read_funct_t wrap_read_temp(struct activity *a)
+__read_funct_t wrap_read_in(struct activity *a)
{
- struct stats_pwr_temp *st_pwr_temp
- = (struct stats_pwr_temp *) a->_buf0;
+ struct stats_pwr_in *st_pwr_in
+ = (struct stats_pwr_in *) a->_buf0;
- /* Read temperature stats */
- read_temp(st_pwr_temp, a->nr);
+ /* Read voltage input stats */
+ read_in(st_pwr_in, a->nr);
return;
}
return;
}
+/*
+ ***************************************************************************
+ * Read weighted CPU frequency statistics.
+ *
+ * IN:
+ * @a Activity structure.
+ *
+ * OUT:
+ * @a Activity structure with statistics.
+ ***************************************************************************
+ */
+__read_funct_t wrap_read_time_in_state(struct activity *a)
+{
+ __nr_t cpu = 0;
+ int j;
+ struct stats_pwr_wghfreq *st_pwr_wghfreq
+ = (struct stats_pwr_wghfreq *) a->_buf0;
+ struct stats_pwr_wghfreq *st_pwr_wghfreq_i, *st_pwr_wghfreq_j, *st_pwr_wghfreq_all_j;
+
+ while (cpu < (a->nr - 1)) {
+ /* Read current CPU time-in-state data */
+ st_pwr_wghfreq_i = st_pwr_wghfreq + (cpu + 1) * a->nr2;
+ read_time_in_state(st_pwr_wghfreq_i, cpu, a->nr2);
+
+ /* Also save data for CPU 'all' */
+ for (j = 0; j < a->nr2; j++) {
+ st_pwr_wghfreq_j = st_pwr_wghfreq_i + j; /* CPU #cpu, state #j */
+ st_pwr_wghfreq_all_j = st_pwr_wghfreq + j; /* CPU #all, state #j */
+ if (!cpu) {
+ /* Assume that possible frequencies are the same for all CPUs */
+ st_pwr_wghfreq_all_j->freq = st_pwr_wghfreq_j->freq;
+ }
+ st_pwr_wghfreq_all_j->time_in_state += st_pwr_wghfreq_j->time_in_state;
+ }
+ cpu++;
+ }
+
+ /* Special processing for non SMP kernels: Only CPU 'all' is available */
+ if (a->nr == 1) {
+ read_time_in_state(st_pwr_wghfreq, 0, a->nr2);
+ }
+ else {
+ for (j = 0; j < a->nr2; j++) {
+ st_pwr_wghfreq_all_j = st_pwr_wghfreq + j; /* CPU #all, state #j */
+ st_pwr_wghfreq_all_j->time_in_state /= (a->nr - 1);
+ }
+ }
+
+ return;
+}
+
+/*
+ ***************************************************************************
+ * Count number of interrupts that are in /proc/stat file.
+ * Truncate the number of different individual interrupts to NR_IRQS.
+ *
+ * IN:
+ * @a Activity structure.
+ *
+ * RETURNS:
+ * Number of interrupts, including total number of interrupts.
+ * Value in [0, NR_IRQS + 1].
+ ***************************************************************************
+ */
+__nr_t wrap_get_irq_nr(struct activity *a)
+{
+ __nr_t n;
+
+ if ((n = get_irq_nr()) > (a->bitmap->b_size + 1)) {
+ n = a->bitmap->b_size + 1;
+ }
+
+ return n;
+}
+
+/*
+ ***************************************************************************
+ * Find number of serial lines that support tx/rx accounting
+ * in /proc/tty/driver/serial file.
+ *
+ * IN:
+ * @a Activity structure.
+ *
+ * RETURNS:
+ * Number of serial lines supporting tx/rx accouting + a pre-allocation
+ * constant.
+ ***************************************************************************
+ */
+__nr_t wrap_get_serial_nr(struct activity *a)
+{
+ __nr_t n = 0;
+
+ if ((n = get_serial_nr()) > 0)
+ return n + NR_SERIAL_PREALLOC;
+
+ return 0;
+}
+
+/*
+ ***************************************************************************
+ * Find number of interfaces (network devices) that are in /proc/net/dev
+ * file.
+ *
+ * IN:
+ * @a Activity structure.
+ *
+ * RETURNS:
+ * Number of network interfaces + a pre-allocation constant.
+ ***************************************************************************
+ */
+__nr_t wrap_get_iface_nr(struct activity *a)
+{
+ __nr_t n = 0;
+
+ if ((n = get_iface_nr()) > 0)
+ return n + NR_IFACE_PREALLOC;
+
+ return 0;
+}
+
+/*
+ ***************************************************************************
+ * Compute number of CPU structures to allocate.
+ *
+ * IN:
+ * @a Activity structure.
+ *
+ * RETURNS:
+ * Number of structures (value in [1, NR_CPUS + 1]).
+ * 1 means that there is only one proc and non SMP kernel.
+ * 2 means one proc and SMP kernel.
+ * Etc.
+ ***************************************************************************
+ */
+__nr_t wrap_get_cpu_nr(struct activity *a)
+{
+ return (get_cpu_nr(a->bitmap->b_size) + 1);
+}
+
+/*
+ ***************************************************************************
+ * Get number of devices in /proc/diskstats.
+ * Always done, since disk stats must be read at least for sar -b
+ * if not for sar -d.
+ *
+ * IN:
+ * @a Activity structure.
+ *
+ * RETURNS:
+ * Number of devices + a pre-allocation constant.
+ ***************************************************************************
+ */
+__nr_t wrap_get_disk_nr(struct activity *a)
+{
+ __nr_t n = 0;
+ unsigned int f = COLLECT_PARTITIONS(a->opt_flags);
+
+ if ((n = get_disk_nr(f)) > 0)
+ return n + NR_DISK_PREALLOC;
+
+ return 0;
+}
+
+/*
+ ***************************************************************************
+ * Get number of fan structures to allocate.
+ *
+ * IN:
+ * @a Activity structure.
+ *
+ * RETURNS:
+ * Number of structures.
+ ***************************************************************************
+ */
+__nr_t wrap_get_fan_nr(struct activity *a)
+{
+ return (get_fan_nr());
+}
+
+/*
+ ***************************************************************************
+ * Get number of temp structures to allocate.
+ *
+ * IN:
+ * @a Activity structure.
+ *
+ * RETURNS:
+ * Number of structures.
+ ***************************************************************************
+ */
+__nr_t wrap_get_temp_nr(struct activity *a)
+{
+ return (get_temp_nr());
+}
+
/*
***************************************************************************
* Get number of voltage input structures to allocate.
/*
***************************************************************************
- * Read voltage input statistics.
+ * Count number of possible frequencies for CPU#0.
*
* IN:
- * @a Activity structure.
+ * @a Activity structure.
*
- * OUT:
- * @a Activity structure with statistics.
+ * RETURNS:
+ * Number of CPU frequencies + a pre-allocation constant.
***************************************************************************
*/
-__read_funct_t wrap_read_in(struct activity *a)
+__nr_t wrap_get_freq_nr(struct activity *a)
{
- struct stats_pwr_in *st_pwr_in
- = (struct stats_pwr_in *) a->_buf0;
+ __nr_t n = 0;
- /* Read voltage input stats */
- read_in(st_pwr_in, a->nr);
+ if ((n = get_freq_nr()) > 0)
+ return n + NR_FREQ_PREALLOC;
- return;
+ return 0;
}
COLLECT_ACTIVITY(A_PWR_CPUFREQ);
COLLECT_ACTIVITY(A_PWR_FAN);
COLLECT_ACTIVITY(A_PWR_TEMP);
+ COLLECT_ACTIVITY(A_PWR_WGHFREQ);
}
else if (!strcmp(p, K_ALL) || !strcmp(p, K_XALL)) {
/* Select all activities */
fprintf(stderr, _("\t-m { <keyword> [,...] | ALL }\n"
"\t\tPower management statistics\n"
"\t\tKeywords are:\n"
- "\t\tCPU\tCPU clock frequency\n"
+ "\t\tCPU\tCPU instantaneous clock frequency\n"
"\t\tFAN\tFans speed\n"
+ "\t\tFREQ\tCPU average clock frequency\n"
"\t\tIN\tVoltage inputs\n"
"\t\tTEMP\tDevices temperature\n"));
fprintf(stderr, _("\t-n { <keyword> [,...] | ALL }\n"
brk CDATA #REQUIRED
ovrun CDATA #REQUIRED
>
-<!ELEMENT power-management (cpu-frequency, fan-speed, temperature, voltage-input)>
+<!ELEMENT power-management (cpu-frequency, fan-speed, temperature, voltage-input, cpu-weighted-frequency,)>
<!ELEMENT cpu-frequency (cpufreq+)>
<!ATTLIST cpu-frequency
unit CDATA #REQUIRED
number CDATA #REQUIRED
frequency CDATA #REQUIRED
>
+<!ELEMENT cpu-weighted-frequency (cpuwfreq+)>
+<!ATTLIST cpu-weighted-frequency
+ unit CDATA #REQUIRED
+>
+<!ELEMENT cpuwfreq EMPTY>
+<!ATTLIST cpuwfreq
+ number CDATA #REQUIRED
+ weighted-frequency CDATA #REQUIRED
+>
<!ELEMENT fan-speed (fanspd+)>
<!ATTLIST fan-speed
unit CDATA #REQUIRED
</xs:restriction>
</xs:simpleType>
+ <xs:element name="cpu-weighted-frequency" type="cpu-weighted-frequency-type"></xs:element>
+
+ <xs:complexType name="cpu-weighted-frequency-type">
+ <xs:sequence>
+ <xs:element name="cpuwfreq" type="cpuwfreq-type" minOccurs="1"></xs:element>
+ </xs:sequence>
+ <xs:attribute name="unit" type="frequnit-type"></xs:attribute>
+ </xs:complexType>
+
<xs:element name="fan-speed" type="fan-speed-type"></xs:element>
<xs:complexType name="fan-speed-type">
<xs:attribute name="frequency" type="hundredth-type"></xs:attribute>
</xs:complexType>
+ <xs:element name="cpuwfreq" type="cpuwfreq-type"></xs:element>
+
+ <xs:complexType name="cpuwfreq-type">
+ <xs:attribute name="number" type="xs:string"></xs:attribute>
+ <xs:attribute name="weighted-frequency" type="hundredth-type"></xs:attribute>
+ </xs:complexType>
+
<xs:element name="fan" type="fan-type"></xs:element>
<xs:complexType name="fan-type">
<xs:element name="fan-speed" type="fan-speed-type"></xs:element>
<xs:element name="temperature" type="temperature-type"></xs:element>
<xs:element name="voltage-input" type="voltage-input-type"></xs:element>
+ <xs:element name="cpu-weighted-frequency" type="cpu-weighted-frequency-type"></xs:element>
</xs:sequence>
</xs:complexType>