scols_table_enable_export(table, out->pairs);
if (out->json)
- scols_table_set_name(table, _("interrupts"));
+ scols_table_set_name(table, "interrupts");
for (i = 0; i < out->ncolumns; i++) {
const struct colinfo *col = get_column_info(out, i);
stat->nr_active_cpu++;
}
+ stat->cpus = xcalloc(stat->nr_active_cpu, sizeof(struct irq_cpu));
+
/* parse each line of _PATH_PROC_INTERRUPTS */
while (getline(&line, &len, irqfile) >= 0) {
unsigned long count;
- int index, length;
+ size_t index;
+ int length;
tmp = strchr(line, ':');
if (!tmp)
tmp += 1;
for (index = 0; (index < stat->nr_active_cpu) && (tmp - line < length); index++) {
+ struct irq_cpu *cpu = &stat->cpus[index];
+
sscanf(tmp, " %10lu", &count);
curr->total += count;
+ cpu->total += count;
stat->total_irq += count;
+
tmp += 11;
}
fclose(irqfile);
free_stat:
free(stat->irq_info);
+ free(stat->cpus);
free(stat);
free(line);
return NULL;
}
free(stat->irq_info);
+ free(stat->cpus);
free(stat);
}
}
}
+struct libscols_table *get_scols_cpus_table(struct irq_output *out,
+ struct irq_stat *prev,
+ struct irq_stat *curr)
+{
+ struct libscols_table *table;
+ struct libscols_column *cl;
+ struct libscols_line *ln;
+ char colname[sizeof(stringify_value(LONG_MAX))];
+ size_t i;
+
+ if (prev) {
+ for (i = 0; i < curr->nr_active_cpu; i++) {
+ struct irq_cpu *pre = &prev->cpus[i];
+ struct irq_cpu *cur = &curr->cpus[i];
+
+ cur->delta = cur->total - pre->total;
+ }
+ }
+
+ table = scols_new_table();
+ if (!table) {
+ warn(_("failed to initialize output table"));
+ return NULL;
+ }
+ scols_table_enable_json(table, out->json);
+ scols_table_enable_noheadings(table, out->no_headings);
+ scols_table_enable_export(table, out->pairs);
+
+ if (out->json)
+ scols_table_set_name(table, _("cpu-interrupts"));
+ else
+ scols_table_new_column(table, "", 0, SCOLS_FL_RIGHT);
+
+ for (i = 0; i < curr->nr_active_cpu; i++) {
+ snprintf(colname, sizeof(colname), "cpu%zu", i);
+ cl = scols_table_new_column(table, colname, 0, SCOLS_FL_RIGHT);
+ if (cl == NULL) {
+ warnx(_("failed to initialize output column"));
+ goto err;
+ }
+ if (out->json)
+ scols_column_set_json_type(cl, SCOLS_JSON_STRING);
+ }
+
+ /* per cpu % of total */
+ ln = scols_table_new_line(table, NULL);
+ if (!ln) {
+ warn(_("failed to add line to output"));
+ goto err;
+ }
+ if (!out->json)
+ scols_line_set_data(ln, 0, "%irq:");
+
+ for (i = 0; i < curr->nr_active_cpu; i++) {
+ struct irq_cpu *cpu = &curr->cpus[i];
+ char *str;
+
+ xasprintf(&str, "%0.1f", (double)((long double) cpu->total / (long double) curr->total_irq * 100.0));
+ if (str && scols_line_refer_data(ln, i + 1, str) != 0)
+ goto err;
+ }
+
+ /* per cpu % of delta */
+ ln = scols_table_new_line(table, NULL);
+ if (!ln) {
+ warn(_("failed to add line to output"));
+ goto err;
+ }
+ if (!out->json)
+ scols_line_set_data(ln, 0, "%delta:");
+
+ for (i = 0; i < curr->nr_active_cpu; i++) {
+ struct irq_cpu *cpu = &curr->cpus[i];
+ char *str;
+
+ if (!curr->delta_irq)
+ continue;
+ xasprintf(&str, "%0.1f", (double)((long double) cpu->delta / (long double) curr->delta_irq * 100.0));
+ if (str && scols_line_refer_data(ln, i + 1, str) != 0)
+ goto err;
+ }
+
+ return table;
+ err:
+ scols_unref_table(table);
+ return NULL;
+}
+
struct libscols_table *get_scols_table(struct irq_output *out,
struct irq_stat *prev,
struct irq_stat **xstat,
unsigned long delta; /* delta count since previous update */
};
+struct irq_cpu {
+ unsigned long total;
+ unsigned long delta;
+};
struct irq_stat {
unsigned int nr_irq; /* number of irq vector */
unsigned int nr_irq_info; /* number of irq info */
struct irq_info *irq_info; /* array of irq_info */
- long nr_active_cpu; /* number of active cpu */
+ struct irq_cpu *cpus; /* array of irq_cpu */
+ size_t nr_active_cpu; /* number of active cpu */
unsigned long total_irq; /* total irqs */
unsigned long delta_irq; /* delta irqs */
};
+
typedef int (irq_cmp_t)(const struct irq_info *, const struct irq_info *);
/* output definition */
struct irq_stat **xstat,
int softirq);
+struct libscols_table *get_scols_cpus_table(struct irq_output *out,
+ struct irq_stat *prev,
+ struct irq_stat *curr);
+
#endif /* UTIL_LINUX_H_IRQ_COMMON */
static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
{
- struct libscols_table *table;
+ struct libscols_table *table, *cpus;
struct irq_stat *stat;
time_t now = time(NULL);
char timestr[64], *data, *data0, *p;
+ /* make irqs table */
table = get_scols_table(out, ctl->prev_stat, &stat, ctl->softirq);
if (!table) {
ctl->request_exit = 1;
return 1;
}
-
scols_table_enable_maxout(table, 1);
scols_table_enable_nowrap(table, 1);
scols_table_reduce_termwidth(table, 1);
- /* header in interactive mode */
+ /* make cpus table */
+ cpus = get_scols_cpus_table(out, ctl->prev_stat, stat);
+ scols_table_reduce_termwidth(cpus, 1);
+
+ /* print header */
move(0, 0);
strtime_iso(&now, ISO_TIMESTAMP, timestr, sizeof(timestr));
wprintw(ctl->win, _("irqtop | total: %ld delta: %ld | %s | %s\n\n"),
stat->total_irq, stat->delta_irq, ctl->hostname, timestr);
+ /* print cpus table */
+ scols_print_table_to_string(cpus, &data);
+ wprintw(ctl->win, "%s\n\n", data);
+ free(data);
+
+ /* print irqs table */
scols_print_table_to_string(table, &data0);
data = data0;
- /* print header in reverse mode */
p = strchr(data, '\n');
if (p) {
+ /* print header in reverse mode */
*p = '\0';
attron(A_REVERSE);
wprintw(ctl->win, "%s\n", data);