#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 300 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: termianted 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, fp); if (!s) { if (!feof(fp)) { printf("%s: termianted 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; 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; //printf("[%s]\n", s); /* 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 (i == 0) printf("%d:%d<---", irq->nr, atoi(s)); */ irq->number[i] = atoi(s); while (isdigit(*s)) s++; } while (isblank(*s)) s++; temp = strchr(s,' '); if (!temp) temp = s + strlen(s); //printf("![%s]\n", s); strncpy(irq->type, s, temp-s > MAX_NAME ? MAX_NAME : temp-s); s = temp; while (isblank(*s)) s++; //printf("[%s]\n",s); 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", NULL}; void get_delta(struct snapshot *b, struct snapshot *n) { struct irq *p_old,*q_old, *p_new, *q_new; int i, delta; char *p; p_old = b->irq; p_new = n->irq; printf("-----------------------------------------------------------\n"); printf("irq cpu: delta avg/s max/s driver\n"); 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 %s\n", p_old->name, i, delta, p_new->avg[i] / MAX_SLEEP, p_new->max[i] / MAX_SLEEP, p_old->drivers); } } 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; cpu_count = get_cpu_count(); if (cpu_count == 0) return; cnt = MAX_CNT; before = get_snapshot(cpu_count); while (cnt--) { sleep(MAX_SLEEP); now = get_snapshot(cpu_count); get_delta(before ,now); cleanup(before); before = now; if (cnt - 1 == 0 && MAX_CNT == -1) cnt = MAX_CNT; } cleanup(before); return; return cnt; }