Re: interrupts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 9/20/05, Gaurav Dhiman <gaurav4lkg@xxxxxxxxx> wrote:
On 9/20/05, Manu Anand <manu.anand@xxxxxxxxx> wrote:
>
>
> On 9/20/05, raja <vnagaraju@xxxxxxxxxxxx> wrote:
> > actually i am writing a module to sense the timer interrupt.
> > Any way for every clock tick the timer updates the system time.I want to
> > find out the process's information that was running at the time the
> > timer interrupt occures.
>
>
> Hi Raja:
>
> Am I write in assuming that u want ur module to sort of hook on to timer
> interrupt? The idea being that ur module should also be invoked when the
> timer interrupt handler is invoked.
>
> In that case, the approach you've followed will not work. Timer interrupt is
> not shared.
>
> When the kernel receives the interrupt, it invokes sequentially each
> reqistered handler on the line. However in your case the call
>
> request_irq(TIMER_INTERRUPT,
> timer_interrupt_handler,SA_SHIRQ,DEVICE_NAME,&devNo);
>
> will fail since the IRQ line is already registered for timer interrupt in an
> exclusive non-shared( specified using SA_INTERRUPT

Manu, I think it will not matter. Actually if we see the code which
invokes the registered handlers for any IRQ line ( handle_IRQ_event()
function ), we will come to know that there is only one special
handling for SA_INTERRUPT flag. If this flag is not set for the first
handler, then the interrupts are enable on local CPU. It does not
block the invocation of other handlers in the IRQ handler's list.


Hi Gaurav:

Initial entry point of interrupts in the kernel is do_IRQ().  The signature of do_IRQ is

fastcall unsigned int do_IRQ(struct pt_regs *regs)

This guy is called after disabling all interrupts on local processor. This is because of the fastcall directive. So interrupts are disabled before do_IRQ calls handle_IRQ_event().

In handle_IRQ_event() we check whether the flag specified was SA_INTERRUPT. Incase it was, we don't do anything. Otherwise we enable the interrupts, call handlers and diable interrupts again before exiting. We are disabling interrupts yet again because do_IRQ() function expects to have local interrupts disabled. So, in essence, what you achieve is that if SA_SHIRQ or SA_SAMPLE_RANDOM is specified, the handlers are executed with interrupts enabled and when SA_INTERRUPT is specified the handlers are executed with local interrupts diabled.

Come to think of it.. If the handling is same, then why do we have different flags?


 

If we also see the function implementation of request_irq(), we do not
do any handling for ~SA_SHIRQ flag in that function, so this is also
not the function which can restrict us to register our handler for non
shared interrupt line.


request_irq() calls setup_irq(). setup_irq()  checks the old flags of the interrupt line and don't let u share the interrupt line if the old flags don't allow it. Here is the relevant code from http://lxr.linux.no/source/kernel/irq/manage.c#L153


    if ((old = *p) != NULL) {
        /* Can't share interrupts unless both agree to */
        if (!(old->flags & new->flags & SA_SHIRQ)) {
            spin_unlock_irqrestore(&desc->lock,flags);
            return -EBUSY;
        }

        /* add new interrupt at end of irq queue */
        do {
            p = &old->next;
            old = *p;
        } while (old);
        shared = 1;
    }

Manu
PS: Don't post complete functions. Give a ref from lxr.linux.no

 

here is the definition of request_irq() function and handle_IRQ_event() function

==========================================
78 fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
79                                 struct irqaction *action)
80 {
81         int ret, retval = 0, status = 0;
82
83         if (!(action->flags & SA_INTERRUPT))
84                 local_irq_enable();
85
86         do {
87                 ret = action->handler(irq, action->dev_id, regs);

here we are simply invoking the registered handlers for specified IRQ
line one by one

88                 if (ret == IRQ_HANDLED)
89                         status |= action->flags;
90                 retval |= ret;
91                 action = "">92         } while (action);
93
94         if (status & SA_SAMPLE_RANDOM)
95                 add_interrupt_randomness(irq);
96         local_irq_disable();
97
98         return retval;
99 }



310 int request_irq(unsigned int irq,
311                 irqreturn_t (*handler)(int, void *, struct pt_regs *),
312                 unsigned long irqflags, const char * devname, void *dev_id)
313 {
314         struct irqaction * action;
315         int retval;
316
317         /*
318          * Sanity-check: shared interrupts must pass in a real dev-ID,
319          * otherwise we'll have trouble later trying to figure out
320          * which interrupt is which (messes up the interrupt freeing
321          * logic etc).
322          */
323         if ((irqflags & SA_SHIRQ) && !dev_id)
324                 return -EINVAL;

check if shared IRQ, but device id is not given, return error, no
check for non shared IRQs done in this function

325         if (irq >= NR_IRQS)
326                 return -EINVAL;
327         if (!handler)
328                 return -EINVAL;
329
330         action = "" irqaction), GFP_ATOMIC);
331         if (!action)
332                 return -ENOMEM;
333
334         action->handler = handler;
335         action->flags = irqflags;
336         cpus_clear(action->mask);
337         action->name = devname;
338         action->next = NULL;
339         action->dev_id = dev_id;
340
341         retval = setup_irq(irq, action);
342         if (retval)
343                 kfree(action);
344
345         return retval;
346 }
==========================================

-Gaurav

> // Check out
> http://lxr.linux.no/source/arch/i386/mach-default/setup.c#L74
> static struct
> irqaction irq0 =
> { timer_interrupt, SA_INTERRUPT,
> CPU_MASK_NONE, "timer", NULL, NULL};
>
> Your approach is valid for interrupts specified with SA_SHIRQ flag.
>
>
> Manu
>
>
>
>
> > I have registered my handler that prints simply a message when ever the
> > timer interrupt occures.But it is not working.It is not printing any
> > message.
> >
> > I am listing my code below.Will you please help me
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > #ifndef __KERNEL__
> >         #define __KERNEL__
> > #endif
> >
> > #ifndef MODULE
> >         #define MODULE
> > #endif
> >
> > #include <linux/kernel.h>
> > #include <linux/init.h>
> > #include <linux/module.h>
> > #include <linux/fs.h>
> > #include <linux/interrupt.h>
> >
> > MODULE_AUTHOR("RAJA");
> > MODULE_DESCRIPTION("TIMER INTERRUPT");
> > MODULE_LICENSE("GPL");
> >
> > #define DEVICE_NAME "timer_interrupt"
> > #define TIMER_INTERRUPT 0
> > static int __init init_timer_interrupt(void);
> > static void __exit exit_timer_interrupt(void);
> >
> > static irqreturn_t timer_interrupt_handler(unsigned
> int,void *, struct
> > pt_regs *);
> >
> > int devNo;
> > struct file_operations fops = {};
> >
> > static irqreturn_t timer_interrupt_handler(unsigned int
> irq,void *data,
> > struct pt_regs *regs)
> > {
> >         printk("Timer Interrupt Occured\n");
> >         return 0;
> > }
> >
> > static int __init init_timer_interrupt()
> > {
> >         printk("Entered Into init_timer\n");
> >         devNo = register_chrdev(0,DEVICE_NAME,&fops);
> >
> >
> request_irq(TIMER_INTERRUPT,timer_interrupt_handler,SA_SHIRQ,DEVICE_NAME,&devNo);
> >         printk("Exited From init_timer\n");
> >         return 0;
> > }
> >
> > static void __exit exit_timer_interrupt()
> > {
> >         printk("Entered Into exit_timer\n");
> >         unregister_chrdev(devNo,DEVICE_NAME);
> >         free_irq(TIMER_INTERRUPT,&devNo);
> >         printk("Exited From exit_timer\n");
> > }
> >
> > module_init(init_timer_interrupt);
> > module_exit(exit_timer_interrupt);
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > On Tue, 2005-09-20 at 17:02 +0500, Fawad Lateef wrote:
> > > On 9/20/05, raja < vnagaraju@xxxxxxxxxxxx> wrote:
> > > > yaa.
> > > > I have checked /proc/interrupts.
> > > > But there it is given the interrupt numbers.
> > > >
> > > > actually the requirement is i am writing a module that it senses when
> > > > ever the interrupt occures and prints the interrupt number.
> > > >
> > > > Will you please help me.
> > > >
> > > >
> > >
> > > What sort of module you are writing ?? How you are going to sense
> > > interrupts when they occurs ?? I think for getting signal through the
> > > call-backed function from the kernel you have to register your
> > > interrupt handlers, so that you can be notified by the kernel ........
> > >
> > > Or hack into the kernel, to get notified for each interrupt, but AFAIK
> > > your module can't get every single interrupt until you register them
> > > with the kernel ........
> > >
> > > Correct me if I m wrong !!!!
> > >
> > >
> >
> >
> > --
> > Kernelnewbies: Help each other learn about the Linux kernel.
> > Archive:       http://mail.nl.linux.org/kernelnewbies/
> > FAQ:           http://kernelnewbies.org/faq/
> >
> >
>
>


--
- Gaurav
my blog: http://lkdp.blogspot.com/
--


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux