From 2a8419010a311ad2a5bf4754a7bc0aaeefb2929b Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 26 Jul 2011 10:47:55 -0400 Subject: [PATCH] read_intr: Add tool to show what interrupts are being used right now. --- root_image/Makefile | 1 + root_image/tools/Makefile | 1 + root_image/tools/read_intr/Makefile | 25 +++ root_image/tools/read_intr/read_intr.c | 262 +++++++++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 root_image/tools/read_intr/Makefile create mode 100644 root_image/tools/read_intr/read_intr.c diff --git a/root_image/Makefile b/root_image/Makefile index 20d36f9..66a918a 100644 --- a/root_image/Makefile +++ b/root_image/Makefile @@ -866,6 +866,7 @@ xtt-tools-install: directfb-install $(INSTALL_SCRIPT) tools/load_xen_modules/load_xen_modules userspace/usr/bin/ $(INSTALL_PROG) tools/iostat-2.2/iostat userspace/usr/bin/ $(INSTALL_PROG) tools/debug/test_gnt userspace/usr/bin/ + $(INSTALL_PROG) tools/read_intr/read_intr userspace/usr/bin/ $(INSTALL_PROG) tools/debug/fb_test userspace/usr/bin/ $(INSTALL_PROG) tools/crashme/crashme userspace/usr/bin/ $(INSTALL_PROG) tools/eatmem/eatmem userspace/usr/bin/ diff --git a/root_image/tools/Makefile b/root_image/tools/Makefile index d4c0173..fe9ebbf 100644 --- a/root_image/tools/Makefile +++ b/root_image/tools/Makefile @@ -6,6 +6,7 @@ SUBDIRS += eatmem SUBDIRS += crashme SUBDIRS += drfb_load SUBDIRS += drfb_test +SUBDIRS += read_intr .PHONY: all all: diff --git a/root_image/tools/read_intr/Makefile b/root_image/tools/read_intr/Makefile new file mode 100644 index 0000000..f1e75a4 --- /dev/null +++ b/root_image/tools/read_intr/Makefile @@ -0,0 +1,25 @@ +TARGETS-y := read_intr +TARGETS := $(TARGETS-y) + +INSTALL_BIN-y := read_intr +INSTALL_BIN := $(INSTALL_BIN-y) + + +.PHONY: all +all: build + +.PHONY: build +build: $(TARGETS) + +.PHONY: install +install: build + $(INSTALL_DIR) $(DESTDIR)$(BINDIR) + $(INSTALL_DIR) $(DESTDIR)$(SBINDIR) + +.PHONY: clean +clean: + $(RM) *.o $(TARGETS) *~ $(DEPS) + +%.o: %.c $(HDRS) Makefile + $(CC) -c $(CFLAGS) -o $@ $< + diff --git a/root_image/tools/read_intr/read_intr.c b/root_image/tools/read_intr/read_intr.c new file mode 100644 index 0000000..e698f4a --- /dev/null +++ b/root_image/tools/read_intr/read_intr.c @@ -0,0 +1,262 @@ +#include +#include +#include +/* +*/ +char *interrupts = "/proc/interrupts"; +static int DELTA = 30; +static int MAX_CNT = -1; +static int MAX_SLEEP = 5; +#define MAX_CPUS 64 +#define MAX_NAME 64 +#define MAX_LINE 400 +struct irq { + int nr; + char name[5]; + int number[MAX_CPUS]; + int avg[MAX_CPUS]; + int max[MAX_CPUS]; + char type[MAX_NAME]; + char drivers[MAX_NAME]; + struct irq *next; +}; +struct snapshot { + int cpu_cnt; + int cnt; + struct irq *irq; +}; +int get_cpu_count() +{ + FILE *fp; + int cpu_count; + char buf[MAX_LINE]; + char *s; + fp = fopen("/proc/cpuinfo","r"); + if (!fp) + return -1; + + cpu_count = 0; + // Get CPUs out of the way. + while (1) { + s = fgets(buf, MAX_LINE, fp); + if (!s) { + if (!feof(fp)) { + printf("%s: terminated before eof.\n", __FUNCTION__); + } + break; + } + if (strlen(buf) < 1) + continue; + if (buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; + + s = strchr(buf, ':'); + if (!s) + continue; + if (strncmp(buf,"processor", strlen("processor")) == 0) { + cpu_count ++; + } + } + fclose(fp); + return cpu_count; +} + +static struct snapshot * +get_snapshot(int cpu_count) +{ + FILE *fp; + int i; + char buf[MAX_LINE]; + char *s,*temp; + struct snapshot *now; + struct irq *irq; + + now = malloc(sizeof(struct snapshot)); + now->cpu_cnt = cpu_count; + now->irq = NULL; + fp = fopen(interrupts,"r"); + if (!fp) + return NULL; + + while (1) { + s = fgets(buf, MAX_LINE-1, fp); + if (!s) { + if (!feof(fp)) { + printf("%s: terminated before eof.\n", __FUNCTION__); + } + break; + } + if (strlen(buf) < 1) + continue; + if (buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; + // Skip the CPU0.. CPU1.. + s = buf; + while (s) { + char *p; + p = strstr(s, "CPU"); + if (!p) + break; + if (s-buf > MAX_LINE || s+4-buf >= MAX_LINE) { + printf("%s: Need bigger buffer!\n", __func__); + break; + } + s = strchr(s+3, ' '); + while (*s == ' ') + s++; + } + if (*s == '\0') + continue; + /* List re-order */ + irq = malloc(sizeof(struct irq)); + memset(irq, 0, sizeof(struct irq)); + irq->next = now->irq; + now->irq = irq; +#if VERBOSE + printf("[%s]\n", s); +#endif + /* Get IRQ, or the string value */ + temp = strchr(s,':'); + strncpy(irq->name, s, 4); + irq->nr = 0; + irq->nr = atoi(irq->name); + s = ++temp; + // For CPU count write values + for (i = 0; i < cpu_count; i++) { + while (isblank(*s)) + s++; +#if VERBOSE + if (i == 0) + printf("%d:%d<---", irq->nr, atoi(s)); +#endif + irq->number[i] = atoi(s); + while (isdigit(*s)) + s++; + } + while (isblank(*s)) + s++; + temp = strchr(s,' '); + if (!temp) + temp = s + strlen(s); +#if VERBOSE + printf("![%s]\n", s); +#endif + strncpy(irq->type, s, temp-s > MAX_NAME ? MAX_NAME : temp-s); + s = temp; + while (isblank(*s)) + s++; +#if VERBOSE + printf("[%s]\n",s); +#endif + strncpy(irq->drivers, s, strlen(s) >MAX_NAME ? MAX_NAME : strlen(s)); + + } +/* CPU0 CPU1 CPU2 CPU3 +16: 9 0 0 0 xen-pirq-ioapic-level uhci_hcd:usb3, nouveau, pata_jmicron +274: 47 0 0 0 xen-dyn-event pcifront +275: 0 0 0 0 xen-dyn-event vkbd +276: 54 0 0 0 xen-dyn-event eth0 +277: 324 21 0 0 xen-dyn-event hvc_console +*/ + fclose(fp); + + return now; + + +} +void cleanup(struct snapshot *now) { + + struct irq *p,*q; + + p = now->irq; + while (p) { + q = p->next; + free(p); + p = q; + } + free(now); +} + +static const char *blacklist[] = {"timer", "resched","interrupts", "call",NULL}; +void get_delta(struct snapshot *b, struct snapshot *n, unsigned long tick) +{ + struct irq *p_old,*q_old, *p_new, *q_new; + int i, delta; + char *p; + + p_old = b->irq; + p_new = n->irq; + while (p_new && p_old) { + q_old = p_old->next; + q_new = p_new->next; + + for (i = 0; blacklist[i]; i++) { + if (blacklist[i] == NULL) + break; + if (strncmp(blacklist[i], + p_old->drivers, + strlen(blacklist[i])) == 0) { + goto skip; + } + } + for (i = 0; i < b->cpu_cnt; i++) { + p_new->avg[i] = p_old->avg[i]; + p_new->max[i] = p_old->max[i]; + + delta = 0; + delta = p_new->number[i] - p_old->number[i]; + if ((delta == p_old->number[i]) || + delta == p_new->number[i]) + continue; + + if (delta < 0) { + printf("%s CPU%d going backwards (%d)!\n", p_old->name, i, delta); + continue; + } + p_new->avg[i] = (delta + p_old->avg[i]) / 2; + if (delta > p_new->max[i]) + p_new->max[i] = delta; + if (delta > DELTA) { + printf("%-5s %2d: %-5d %-5d %-5d %-20s %ldsec\n", + p_old->name, i, delta / MAX_SLEEP, + p_new->avg[i] / MAX_SLEEP, p_new->max[i] / MAX_SLEEP, + p_old->drivers, tick); + } + + } +skip: + p_old = q_old; + p_new = q_new; + } +} +int main(int argc, char *argv[]) +{ + struct snapshot *before, *now; + struct irq *p,*q; + int cnt; + int cpu_count; + unsigned long tick; + + cpu_count = get_cpu_count(); + if (cpu_count == 0) + return; + + cnt = MAX_CNT; + printf("-----------------------------------------------------------\n"); + printf("irq cpu: delta avg/s max/s driver time\n"); + before = get_snapshot(cpu_count); + tick = 0; + while (cnt--) { + sleep(MAX_SLEEP); + tick += MAX_SLEEP; + now = get_snapshot(cpu_count); + get_delta(before ,now, tick); + cleanup(before); + before = now; + if (cnt - 1 == 0 && MAX_CNT == -1) + cnt = MAX_CNT; + } + cleanup(before); + + return cnt; +} -- 2.39.5