All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anders Blomdell <anders.blomdell@domain.hid>
To: xenomai@xenomai.org
Subject: Re: [Xenomai-core] More on Shared interrupts
Date: Thu, 16 Feb 2006 17:05:25 +0100	[thread overview]
Message-ID: <43F4A2C5.8080909@domain.hid> (raw)
In-Reply-To: <43EB63D7.2080507@domain.hid>

Anders Blomdell wrote:
> For the last few days, I have tried to figure out a good way to share 
> interrupts between RT and non-RT domains. This has included looking 
> through Dmitry's patch, correcting bugs and testing what is possible in 
> my specific case. I'll therefore try to summarize at least a few of my 
> thoughts.
> 
> 1. When looking through Dmitry's patch I get the impression that the 
> iack handler has very little to do with each interrupt (the test 
> 'prev->iack != intr->iack' is a dead giveaway), but is more of a 
> domain-specific function (or perhaps even just a placeholder for the 
> hijacked Linux ack-function).
> 
> 
> 2. Somewhat inspired by the figure in "Life with Adeos", I have 
> identified the following cases:
> 
>   irq K  | ----------- | ---o    |   // Linux only
>   ...
>   irq L  | ---o        |         |   // RT-only
>   ...
>   irq M  | ---o------- | ---o    |   // Shared between domains
>   ...
>   irq N  | ---o---o--- |         |   // Shared inside single domain
>   ...
>   irq O  | ---o---o--- | ---o    |   // Shared between and inside single 
> domain
> 
> Xenomai currently handles the K & L cases, Dmitrys patch addresses the N 
> case, with edge triggered interrupts the M (and O after Dmitry's patch) 
> case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE 
> from the interrupt handler, for level triggered interrupt the M and O 
> cases can't be handled.
> 
> If one looks more closely at the K case (Linux only interrupt), it works 
> by when an interrupt occurs, the call to irq_end is postponed until the 
> Linux interrupt handler has run, i.e. further interrupts are disabled. 
> This can be seen as a lazy version of Philippe's idea of disabling all 
> non-RT interrupts until the RT-domain is idle, i.e. the interrupt is 
> disabled only if it indeed occurs.
> 
> If this idea should be generalized to the M (and O) case(s), one can't 
> rely on postponing the irq_end call (since the interrupt is still needed 
> in the RT-domain), but has to rely on some function that disables all 
> non-RT hardware that generates interrupts on that irq-line; such a 
> function naturally has to have intimate knowledge of all hardware that 
> can generate interrupts in order to be able to disable those interrupt 
> sources that are non-RT.
> 
> If we then take Jan's observation about the many (Linux-only) interrupts 
> present in an ordinary PC and add it to Philippe's idea of disabling all 
> non-RT interrupts while executing in the RT-domain, I think that the 
> following is a workable (and fairly efficient) way of handling this:
> 
> Add hardware dependent enable/disable functions, where the enable is 
> called just before normal execution in a domain starts (i.e. when 
> playing back interrupts, the disable is still in effect), and disable is 
> called when normal domain execution end. This does effectively handle 
> the K case above, with the added benefit that NO non-RT interrupts will 
> occur during RT execution.
> 
> In the 8259 case, the disable function could look something like:
> 
>   domain_irq_disable(uint irqmask) {
>     if (irqmask & 0xff00 != 0xff00) {
>       irqmask &= ~0x0004; // Cascaded interrupt is still needed
>       outb(irqmask >> 8, PIC_SLAVE_IMR);
>     }
>     outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> If we should extend this to handle the M (and O) case(s), the disable 
> function could look like:
> 
>   domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
>     int i;
> 
>     for (i = 0 ; i < MAX_IRQ ; i++) {
>       if (shared[i]) {
>         shared_irq_t *next = shared[i];
>         irqmask &= ~(1<<i);
>         while (next) {
>           next->disable();
>       next = next->next;
>         }
>       }
>     }
>     if (irqmask & 0xff00 != 0xff00) {
>       irqmask &= ~0x0004; // Cascaded interrupt is still needed
>       outb(irqmask >> 8, PIC_SLAVE_IMR);
>     }
>     outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> An obvious optimization of the above scheme, is to never call the 
> disable (or enable) function for the RT-domain, since there all 
> interrupt processing is protected by the hardware.
> 
> Comments, anyone?

OK, I have finally got around to do some interrupt timing tests on a PrPMC800 
(450 MHz PowerPC/G4)  with the following interrupt sources:

   3: 10 Khz watchdog interrupt (Linux)
  10: 100 Mbit/s ethernet (Linux)
  16: mailbox interrupt (RT) + UART (Linux)

I have measured interrupt latency, task latency (time from interrupt until a 
task signalled from interrupt handler has started) and the semaphore latency 
(time from task semaphore is signalled until task has started).

I have tested 4 different ways of handling shared Linux/RT interrupts:

   1. When UART interrupt occurs, disable further UART interrupts, signal low
      priority UART reenable task, return XN_ISR_ENABLE | XN_ISR_CHAINED.
      In low priority UART reenable task, reenable UART when Linux has handled
      the interrupt.

   2. Disable UART interrupts, and poll them at 1kHz from low priority RT task,
      and rthal_irq_host_pend them as they occur.

   3. Modified Xenomai, where non-RT interrupts are disabled when entering
      the RT domain, and enabled when entering the Linux domain.

   4. Modified Xenomai, where non-RT interrupts are disabled when interrupt
      occurs, and enabled when entering the Linux domain.

In case 3 & 4 interrupts are enabled/disabled with code like:

       if (enable) {
         // Enable Linux interrupts
         SET_HARRIER_XCSR_REG_16(FEMA, 0xc900); // UART
         rthal_irq_enable(3);
         rthal_irq_enable(10);
       } else {
         // Disable Linux interrupts
         SET_HARRIER_XCSR_REG_16(FEMA, 0xcf00); // UART
         rthal_irq_disable(3);
         rthal_irq_disable(10);
       }


The tests has been run with 5 different loads (measuring a 1 kHz mailbox interrupt):

   A. Idle
   B. 10 KHz watchdog
   C. UART @9600 baud (approx 1kHz)
   D. ping -f -l20
   E. compound load (watchdog + UART + ping)

The plots at http://www.control.lth.se/user/andersb/orca/timing_plots.html makes 
me draw the following conclusions (worst case task latency <= worst case 
interrupt latency + worst case semaphore latency, since their simultaneous 
probablity is lower):

   a. On an unloaded system (A), 3 & 4 are slightly worse (2 us), the main
      difference between the two being if the disabling is done before or
      after the mailbox IRQ handler is run.
   b. In all the single load cases (B, C, D) the modified kernels (3, 4) has
      comparable task latency as the unmodified kernels (1, 2), and lower
      interrupt latency and lower semaphore latency.
   c. In the compound load case, the modified kernels shows distinctly improved
      worst case interrupt latencies (15 us instead of 20 us), and the one with
      early disabled interrupts (4) has distinctly better semaphore latency.

Based on the above, I conclude that by disabling all non-RT interrupts early (4) 
timing is improved since the RT domain is hit by a maximum of one non-RT 
interrupt at a time, and on standard PC's with lots of non-RT interrupts the 
benefit would be even bigger. I also believe that the enable/disable code could 
be (somewhat) improved by only taking one write posting delay instead of two 
(these are in code called by rthal_irq_*able).

-- 

Regards

Anders Blomdell



  parent reply	other threads:[~2006-02-16 16:05 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-02-07  9:04 [Xenomai-core] [Combo-PATCH] Shared interrupts (final) Dmitry Adamushko
2006-02-07  9:58 ` Wolfgang Grandegger
2006-02-07 17:58   ` Jan Kiszka
2006-02-08  7:26     ` Wolfgang Grandegger
2006-02-08  8:24       ` Jan Kiszka
2006-02-08 10:12         ` Dmitry Adamushko
2006-02-08 10:57     ` Philippe Gerum
2006-02-09  8:30       ` Anders Blomdell
2006-02-09  9:11         ` Jan Kiszka
2006-02-09 10:07           ` Philippe Gerum
2006-02-09  9:59         ` Philippe Gerum
2006-02-09 10:19           ` Jan Kiszka
2006-02-09 11:11             ` Dmitry Adamushko
2006-02-09 15:46               ` [Xenomai-core] More on Shared interrupts Anders Blomdell
2006-02-09 16:39                 ` Jan Kiszka
2006-02-10  8:04                   ` Anders Blomdell
2006-02-10 13:59                 ` [Xenomai-core] " Philippe Gerum
2006-02-11 11:35                   ` Dmitry Adamushko
2006-02-13  7:49                     ` Anders Blomdell
2006-02-13 11:00                       ` Dmitry Adamushko
2006-02-14 17:46                     ` Philippe Gerum
2006-02-16 16:05                 ` Anders Blomdell [this message]
2006-02-09 11:14             ` [Xenomai-core] [Combo-PATCH] Shared interrupts (final) Philippe Gerum
2006-02-09 10:43           ` Anders Blomdell
2006-02-07 19:24   ` Dmitry Adamushko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=43F4A2C5.8080909@domain.hid \
    --to=anders.blomdell@domain.hid \
    --cc=xenomai@xenomai.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.