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 <[EMAIL PROTECTED]>
 *
 * 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;

Reply via email to