This is the mail archive of the
ecos-discuss@sourceware.org
mailing list for the eCos project.
Re: Possible fix for interrupt latency problems on Arm
- From: Mike <mjs2 at ovus dot co dot uk>
- To: eCos Discussion <ecos-discuss at ecos dot sourceware dot org>
- Cc: Nick Garnett <nickg at ecoscentric dot com>
- Date: Thu, 03 Aug 2006 16:37:48 +0100
- Subject: Re: [ECOS] Possible fix for interrupt latency problems on Arm
- References: <44B7850A.4050508@ovus.co.uk> <44CDBFC1.1050909@televic.com> <m3ac6q6po2.fsf@xl5.calivar.com>
Nick Garnett wrote:
That change is not a good idea. It can introduce race conditions into
the system. I think you have been lucky so far.
Although interrupt_end() is entered with interrupts disabled, they
will be enabled to call DSRs, that's what
hal_interrupt_stack_call_pending_DSRs does. Interrupts will also be
re-enabled if a context switch is made. So interrupts will get turned
back on within a few microseconds of completing the ISR
Hi Nick,
Thanks for getting involved on this one! Prior to my mod, I was indeed
seeing interrupts being re-enabled in
hal_interrupt_stack_call_pending_DSRs. However, my problem was that this
call was being made some time after the interrupt, and resulted in me
seeing interrupts being disabled for up to 1.3ms, which was simply no good!
I had hoped that the copious use of HAL_DISABLE_INTERRUPTS() in the
functions called by interrupt_end() would have prevented any race
conditions. As far as I could determine the only impact of my mod would
be on the size of interrupt stack needed.
The reason I was hopeful that this was a good mod is that other
architectures do appear to re-enable ints before the interrupt_end() call.
For example the sparc code does:
! First restore the processor interrupt level to that interrupted
! (otherwise a task-switch runs at the current PIL) on the assumption
! that the ISR dealt with the interrupt source per se, so it is safe
! to unmask it, effectively:
or %l0, 0x0e0, %l7 ! original PSR and ET (+S,PS)
wr %l7, %psr ! and enable!
<omitted some code here>
! then call interrupt_end( isr_retcode, &intr_object, ®save )
! to unlock the scheduler and do any rescheduling that~s needed.
! argument 0 (isr_retcode) is already in place in %o0
sethi %hi(hal_interrupt_objects), %l7
or %l7, %lo(hal_interrupt_objects), %l7
ld [ %l7 + %l3 ], %o1
add %sp, 24 * 4, %o2 ! saved regset (maybe tiny)
.extern interrupt_end
call interrupt_end
Likewise for the 68k:
/* The interrupt_end routine will call the DSRs and
do */
/* rescheduling when it decrements the scheduler lock from 1
to */
/* zero. In this case, we do not want to have interrupts
masked */
/* while the DSRs run. Restore the interrupt mask to the
value */
/* prior to this interrupt. Do not completely unmask
all */
/* interrupts because this interrupt may be a nested interrupt.
We */
/* do not want to lower the interrupt mask on the lower
priority */
/*
interrupt. */
move.w (4*3)+int_pres_regs_sz+2(%sp),%d2
move.w %d2,%sr
/* If the interrupt mask was not previously zero, we want to
make */
/* sure that the DSRs to not run and no preemption occurs. Add
the */
/* value of the previous interrupt mask to the scheduler lock.
If */
/* the previous mask was zero, the scheduler lock will remain
at */
/* one and the interrupt end function will decrement it to
zero. */
/* Otherwise, we want to prevent the interrupt end function
from */
/* unlocking the scheduler. We do this because there is a
chance */
/* that someone had interrupts masked with the scheduler lock
at */
/* zero. If a higher priority interrupt occurs, we could
be */
/* running DSRs and doing preemption with the interrupts
masked! */
and.l #0x0700,%d2
lsr.l #8,%d2
add.l %d2,cyg_scheduler_sched_lock
.extern interrupt_end /* Call the
interrupt_end C */
jbsr interrupt_end /* routine. This routine
might */
/* preempt the
currently */
/* running
thread. */
Mike
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss