--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+/*
+*/
+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;
+}