hello all, On my Intel Pentium 4 with linux-2.6.23-rc8-rt1, I am getting : Interrupt Latency result ------------------------ MAX latency : 12.570 micro-seconds MIN latency : 3.352 micro-seconds AVG latency : 4.190 micro-seconds Total Samples : 32583 Please review this interrupt latency module and give your feedback. Thank you, Jaswinder Singh.
/* * Interrupt latency test module * * (C) 2007 Jaswinder Singh <jaswinderlinuxrt@xxxxxxxxx> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public Licence Version * 2 as published by the Free Software Foundation. * */ #include <linux/module.h> #include <linux/init.h> #include <linux/bcd.h> #include <asm/time.h> //#define DBG_IRQ_LAT /* debug interrupt latency test */ #define TEST_COUNT 20000 /* loop to get max timer count */ /* getting global time from 8254 */ #define READ_CNT0(var) do {var = inb(0x40); var |= (inb(0x40) << 8);} while (0) #ifdef DBG_IRQ_LAT #define TEST_CNT 50 static long lat_val[TEST_CNT]; #endif static volatile long count_c0; static long max_c0 = 0; static long cnt_c0 = 0; static long lat_max = 0; static long lat_min = 100000000; static unsigned long irq_cnt = 0; static unsigned long lat_avg = 0; static void irq_lat_hdr(void) { READ_CNT0(count_c0); count_c0 = (max_c0 - count_c0); if (count_c0 > lat_max) lat_max = count_c0; if (count_c0 < lat_min) lat_min = count_c0; lat_avg = lat_avg + count_c0; #ifdef DBG_IRQ_LAT if (irq_cnt < TEST_CNT) { lat_val[irq_cnt] = count_c0; } #endif irq_cnt++; } /* get maximum timer count */ static long get_max_ticks(void) { unsigned long max_ticks = 0; while(cnt_c0 < TEST_COUNT) { READ_CNT0(count_c0); if (count_c0 > max_ticks) max_ticks = count_c0; cnt_c0++; } #ifdef DBG_IRQ_LAT printk("max %lu cnt %lu\n", max_ticks, cnt_c0); #endif return max_ticks; } static int __init irq_lat_init(void) { printk("*************************************\n"); printk("* Interrupt Latency module loaded *\n"); printk("* When you remove this module you *\n"); printk("* will get interrupt latency result *\n"); printk("*************************************\n"); max_c0 = get_max_ticks(); irq_lat_ptr = irq_lat_hdr; /* Install interrupt handler */ return 0; } static void __exit irq_lat_exit(void) { unsigned long nanosecs = 1000000000; irq_lat_ptr = NULL; /* Uninstall interrupt handler */ nanosecs = (nanosecs/CLOCK_TICK_RATE); lat_avg = lat_avg/irq_cnt; printk("Interrupt Latency result\n"); printk("------------------------\n"); #ifdef DBG_IRQ_LAT for (count_c0 = 0; count_c0 < TEST_CNT; count_c0++) printk("%lu: %lu\n", count_c0, lat_val[count_c0]); printk("CLOCK_TICK_RATE: %d TICK: %lu\n", CLOCK_TICK_RATE, nanosecs); printk("MAX latency : %lu ticks\n", lat_max); printk("MIN latency : %lu ticks\n", lat_min); printk("AVG latency : %lu ticks\n", lat_avg); #endif printk("MAX latency : %lu.%03lu micro-seconds\n", (nanosecs * lat_max)/1000, (nanosecs * lat_max) % 1000); printk("MIN latency : %lu.%03lu micro-seconds\n", (nanosecs * lat_min)/1000, (nanosecs * lat_min) % 1000); printk("AVG latency : %lu.%03lu micro-seconds\n", (nanosecs * lat_avg)/1000, (nanosecs * lat_avg) % 1000); printk("Total Samples : %lu\n", irq_cnt); } module_init(irq_lat_init); module_exit(irq_lat_exit); MODULE_LICENSE("GPL");
obj-name := irq_latency obj-m := $(obj-name).o KDIR := $(HOME)/linux-$(shell uname -r) PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -rf *.ko *.o *.mod.c .*.cmd Mod* .tmp_versions
diff -urN linux-2.6.23-rc8-rt1_org/arch/i386/kernel/time.c linux-2.6.23-rc8-rt1/arch/i386/kernel/time.c --- linux-2.6.23-rc8-rt1_org/arch/i386/kernel/time.c 2007-10-20 11:24:17.000000000 +0530 +++ linux-2.6.23-rc8-rt1/arch/i386/kernel/time.c 2007-10-20 11:30:31.000000000 +0530 @@ -150,6 +150,10 @@ } EXPORT_SYMBOL(profile_pc); +/* Interrupt latency pointer */ +irqlatptr irq_lat_ptr = NULL; +EXPORT_SYMBOL(irq_lat_ptr); + /* * This is the same as the above, except we _also_ save the current * Time Stamp Counter value at the time of the timer interrupt, so that @@ -173,6 +177,10 @@ } #endif + /* Interrupt latency pointer */ + if (irq_lat_ptr) + irq_lat_ptr(); + do_timer_interrupt_hook(); if (MCA_bus) { diff -urN linux-2.6.23-rc8-rt1_org/include/asm-i386/time.h linux-2.6.23-rc8-rt1/include/asm-i386/time.h --- linux-2.6.23-rc8-rt1_org/include/asm-i386/time.h 2007-10-20 11:24:46.000000000 +0530 +++ linux-2.6.23-rc8-rt1/include/asm-i386/time.h 2007-10-20 11:27:35.000000000 +0530 @@ -4,6 +4,10 @@ #include <linux/efi.h> #include "mach_time.h" +/* interrupt latency pointer */ +typedef void (*irqlatptr)(void); +extern irqlatptr irq_lat_ptr; + static fastcall inline unsigned long native_get_wallclock(void) { unsigned long retval;