This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Possible fix for interrupt latency problems on Arm


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, &regsave )
   ! 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]