mpstat: fix/improve handling of interrupt names

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-07-30 12:45:14 +02:00
parent 5e87c2ef15
commit 64c67891a2

View File

@ -28,8 +28,16 @@
/* Maximum number of interrupts */
#define NR_IRQS 256
#define NR_IRQCPU_PREALLOC 3
#define MAX_IRQ_LEN 16
#define MAX_IRQNAME_LEN 16
#define MAX_PF_NAME 512
/* sysstat 9.0.6 uses width 8, but newer code which also prints /proc/softirqs
* data needs more: "interrupts" in /proc/softirqs have longer names,
* most are up to 8 chars, one (BLOCK_IOPOLL) is even longer.
* We are printing headers in the " IRQNAME/s" form, experimentally
* anything smaller than 10 chars looks ugly for /proc/softirqs stats.
*/
#define INTRATE_SCRWIDTH 10
#define INTRATE_SCRWIDTH_STR "10"
/* System files */
#define SYSFS_DEVCPU "/sys/devices/system/cpu"
@ -54,7 +62,7 @@ typedef long idata_t;
struct stats_irqcpu {
unsigned interrupt;
char irq_name[MAX_IRQ_LEN];
char irq_name[MAX_IRQNAME_LEN];
};
struct stats_cpu {
@ -195,10 +203,23 @@ static void write_irqcpu_stats(struct stats_irqcpu *per_cpu_stats[],
/* Print header */
printf("\n%-11s CPU", prev_str);
for (j = 0; j < total_irqs; j++) {
p0 = &per_cpu_stats[current][j];
if (p0->irq_name[0] != '\0')
printf(" %8s/s", p0->irq_name);
{
/* A bit complex code to "buy back" space if one header is too wide.
* Here's how it looks like. BLOCK_IOPOLL eating too much,
* and latter headers use smaller width to compensate:
* ...BLOCK/s BLOCK_IOPOLL/s TASKLET/s SCHED/s HRTIMER/s RCU/s
* ... 2.32 0.00 0.01 17.58 0.14 141.96
*/
int expected_len = 0;
int printed_len = 0;
for (j = 0; j < total_irqs; j++) {
p0 = &per_cpu_stats[current][j];
if (p0->irq_name[0] != '\0') {
int n = (INTRATE_SCRWIDTH-3) - (printed_len - expected_len);
printed_len += printf(" %*s/s", n > 0 ? n : 0, skip_whitespace(p0->irq_name));
expected_len += INTRATE_SCRWIDTH;
}
}
}
bb_putchar('\n');
@ -247,7 +268,7 @@ static void write_irqcpu_stats(struct stats_irqcpu *per_cpu_stats[],
struct stats_irqcpu *p, *q;
p = &per_cpu_stats[current][(cpu - 1) * total_irqs + j];
q = &per_cpu_stats[prev][(cpu - 1) * total_irqs + offset];
printf(" %10.2f",
printf("%"INTRATE_SCRWIDTH_STR".2f",
(double)(p->interrupt - q->interrupt) / itv * G.hz);
} else {
printf(" N/A");
@ -574,10 +595,11 @@ static void get_irqs_from_interrupts(const char *fname,
ic = &per_cpu_stats[current][irq];
len = cp - buf;
if (len > sizeof(ic->irq_name)) {
len = sizeof(ic->irq_name);
if (len >= sizeof(ic->irq_name)) {
len = sizeof(ic->irq_name) - 1;
}
safe_strncpy(ic->irq_name, buf, len);
safe_strncpy(ic->irq_name, buf, len + 1);
//bb_error_msg("%s: irq%d:'%s' buf:'%s'", fname, irq, ic->irq_name, buf);
digit = isdigit(buf[len - 1]);
cp++;