Interrupts Disabled After First Context Switch

Ian Caddy ianc at goanna.iinet.net.au
Fri Jan 6 01:25:11 UTC 2006


Hi Kevin,

Which version of RTEMS are you running.  We have been looking through 
watchdoginsert.c for another problem and in my version, which is from 
4.6.5 there is no _ISR_Disable( level ) after the restart.

That definitely looks wrong to me.  You can not have 2 disables without 
an enable in between them.  In fact looking through that code, if the 
restart is invoked, you will get more _ISR_Disable( level ) than just 
the 2 as well.

The cpukit/score/src/watchdoginsert.c in the 4.6.5 release is correct if 
you want to have a look at that.

regards,

Ian Caddy


Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
> I'm not sure this is a bug but I tracked down my problem to
> _Watchdog_Insert().  Below is the relevant code snippet. Upon entering
> watchdog insert the routine disables interrupts.  This sets my interrupt
> level to 15 ( which blocks all interrupts ).  The returned interrupt
> level from the _ISR_Disable() call shows that the previous interrupt
> level to be zero.  This is correct.  It then disables the interrupts
> again right after the restart label.  Since the interrupt level is
> current 15 the returned interrupt level from the _ISR_Disable() is now
> 15.  When it finally enables interrupts at the end, the level is set to
> 15 masking all interrupts. To fix the problem I commented out the
> _ISR_Disable() right below the restart label.  Is this a bug or is rtems
> intended to work this way?
> 
> void _Watchdog_Insert(
>   Chain_Control         *header,
>   Watchdog_Control      *the_watchdog
> )
> {
>   ISR_Level          level;
>   Watchdog_Control  *after;
>   unsigned32         insert_isr_nest_level;
>   Watchdog_Interval  delta_interval;
> 
> 
>   insert_isr_nest_level   = _ISR_Nest_level;
> 
> 	_ISR_Disable( level );
> 
>   /*
>    *  Check to see if the watchdog has just been inserted by a
>    *  higher priority interrupt.  If so, abandon this insert.
>    */
> 
>   if ( the_watchdog->state != WATCHDOG_INACTIVE ) {
>     _ISR_Enable( level );
>     return;
>   }
> 
>   the_watchdog->state = WATCHDOG_BEING_INSERTED;
> 
>   _Watchdog_Sync_count++;
> 
> restart:
>   delta_interval = the_watchdog->initial;
> 
>   _ISR_Disable( level ); //I commented this Disable to fix problem
> 
> for ( after = _Watchdog_First( header ) ;
>         ;
>         after = _Watchdog_Next( after ) ) {
> 
>      if ( delta_interval == 0 || !_Watchdog_Next( after ) )
>        break;
> 
>      if ( delta_interval < after->delta_interval ) {
>        after->delta_interval -= delta_interval;
>        break;
>      }
> 
>      delta_interval -= after->delta_interval;
> 
>      /*
>       *  If you experience problems comment out the _ISR_Flash line.
>       *  3.2.0 was the first release with this critical section
> redesigned.
>       *  Under certain circumstances, the PREVIOUS critical section
> algorithm
>       *  used around this flash point allowed interrupts to execute
>       *  which violated the design assumptions.  The critical section
>       *  mechanism used here WAS redesigned to address this.
>       */
> 
>      _ISR_Flash( level );
> 
>      if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
>        goto exit_insert;
>      }
> 
>      if ( _Watchdog_Sync_level > insert_isr_nest_level ) {
>        _Watchdog_Sync_level = insert_isr_nest_level;
>        goto restart;
>      }
>   }
> 
>   _Watchdog_Activate( the_watchdog );
> 
>   the_watchdog->delta_interval = delta_interval;
> 
>   _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node
> );
> 
>   the_watchdog->start_time = _Watchdog_Ticks_since_boot;
> 
> exit_insert:
>   _Watchdog_Sync_level = insert_isr_nest_level;
>   _Watchdog_Sync_count--;
>   _ISR_Enable( level );
> }
> 
> 
> 
> Kevin Kirspel
> Osmetech 
> 235 Hembree Park Drive
> Roswell GA, 30076
> 770-510-4444 x4568
> 
> 
> -----Original Message-----
> From: Joel Sherrill <joel at OARcorp.com>
> [mailto:joel.sherrill at OARcorp.com] 
> Sent: Thursday, January 05, 2006 4:44 PM
> To: Kirspel, Kevin {Engineering - Osmetech CCD}
> Cc: rtems-users at rtems.com
> Subject: Re: Interrupts Disabled After First Context Switch
> 
> Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
> 
>>During _Thread_Dispatch() I was printing the state of the SR register.
> 
> I
> 
>>found that by the third context switch the interrupts were disabled
>>going into _Thread_Dispatch().  So when _ISR_Disable() is called it
>>returns the SR register with interrupts disabled.  Since the
>>_ISR_Enable() routine just sets the SR register with the given level,
>>interrupts are disabled even after the _ISR_Enable() call.  Is it
>>possible to enter the _Thread_Dispatch() routine while interrupts are
>>disable ( i.e. _ISR_Disable() was called prior to _Thread_Dispatch()
> 
> )?
> 
> Yes.  Interrupt level is maintained across context switches on a per 
> thread basis.
> 
> I suspect that the third context switch you see is actually from 
> __ISR_Dispatch and that the level is somehow not being maintained across
> 
> a preemption from ISR.
> 
> The sequence should be something like this for your test:
> 
>    (1) 1st context switch (initialization to 1st thread)
>    (2) 1st thread to IDLE (wake after)
>      ... clock tick isrs
>    (3) IDLE to 1st thread FROM ISR!!
> 
> The FROM ISR on (3) is critical.  That puts you through the tail of 
> __ISR_Handler and possibly needing some magic.  On other CPUs, that
> code is tricky.  The SH code is straightforward but might be missing
> something on the SH3/4.
> 
> 
> 
>>Kevin Kirspel
>>Osmetech 
>>235 Hembree Park Drive
>>Roswell GA, 30076
>>770-510-4444 x4568
>>
>>
>>-----Original Message-----
>>From: Joel Sherrill <joel at OARcorp.com>
>>[mailto:joel.sherrill at OARcorp.com] 
>>Sent: Thursday, January 05, 2006 1:04 PM
>>To: Kirspel, Kevin {Engineering - Osmetech CCD}
>>Cc: rtems-users at rtems.com
>>Subject: Re: Interrupts Disabled After First Context Switch
>>
>>Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
>>
>>
>>>1) Renesas SH-3 but it's pretty much the same as the SH-4.
>>>
>>>2) the rtems_interrupt_disable() routine returns the value in the SR
>>>register of the sh-3/4.  The SR register contains a BL bit that masks
>>>interrupts.  It also contains an interrupt level mask that prevents
>>
>>any
>>
>>
>>>interrupt lower than the level in the SR register from executing.  The
>>>SH4 port sets the interrupt level to 15 to mask all interrupts (
>>>rtems_interrupt_disable ).  Upon the printf statement below, the
>>>interrupt level in the SR register is set to 15 masking all
>>
>>interrupts.
>>
>>
>>>3)Yes.
>>>
>>>Case 1: using interrupt mask level 15 to disable interrupts. (
>>
>>interrupt
>>
>>
>>>masks bits are bits 4-7 which is 0 before and F after).
>>>INT BEFORE: 0x40001000
>>>INT AFTER:  0x400011F1
>>>
>>>Case 2: using interrupt BL bit to disable interrupts. ( interrupt BL
>>
>>bit
>>
>>
>>>is bit 28 which is 0 before and 1 after).
>>>INT BEFORE: 0x40001000
>>>INT AFTER:  0x50001101
>>
>>
>>Is BL implicitly modified by an interrupt?  I don't know the SH well 
>>enough to trace the code in my head but since you are doing a 
>>delaying/blocking wake_after, there will be a context switch to IDLE, 
>>then some clock tick ISRs, then a preempt of IDLE via the
> 
> __ISR_Handler
> 
>>routine in cpu_asm.c.  If the BL bit is not preserved across the (a) 
>>context switch or (b) interrupt preemption, then it might be what you 
>>are seeing.
>>
>>I do not think it is (a) because that is a simple load/store of the
> 
> sr.
> 
>>The __ISR_Handler code is always tricky to get right but I don't see
> 
> how
> 
>>it could be messed up either.
>>
>>To eliminate some possibilities and assuming this is a single task
> 
> test,
> 
>>change the wake after(100) to wake after(0).  And do not print until 
>>after all of the interrupt level changes.  I suspect it is the
> 
> interrupt
> 
>>context switch somehow.  Just a guess.
>>
>>
>>
>>
>>
>>>Kevin Kirspel
>>>Osmetech 
>>>235 Hembree Park Drive
>>>Roswell GA, 30076
>>>770-510-4444 x4568
>>>
>>>
>>>-----Original Message-----
>>>From: Joel Sherrill <joel at OARcorp.com>
>>>[mailto:joel.sherrill at OARcorp.com] 
>>>Sent: Thursday, January 05, 2006 11:20 AM
>>>To: Kirspel, Kevin {Engineering - Osmetech CCD}
>>>Cc: rtems-users at rtems.com
>>>Subject: Re: Interrupts Disabled After First Context Switch
>>>
>>>Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
>>>
>>>
>>>
>>>>Upon entering a task, the interrupts at the hardware level are
>>>
>>>enabled.
>>>
>>>
>>>
>>>>After a call to rtems_task_wake_after() the interrupts are disabled
>>>
>>>and
>>>
>>>
>>>
>>>>remain disabled while the task is running.  What part of the code
>>>
>>>should
>>>
>>>
>>>
>>>>I look at to diagnose this issue? It seems that interrupts get
>>>
>>>disabled
>>>
>>>
>>>
>>>>before the task switch is performed.
>>>>
>>>>The code sample below illustrates what I am doing. At the first
>>>>printf(), the interrupts are enabled.  After the second printf(), the
>>>>interrupts are disabled.
>>>>
>>>>rtems_task GUITask ( rtems_task_argument ignored )
>>>>{
>>>>//Local Varaibles
>>>>rtems_interrupt_level level;
>>>>
>>>>/* Wait 100ms til everyone is up and running */
>>>>rtems_interrupt_disable(level);
>>>>rtems_interrupt_enable(level);
>>>>printf( "\r\nINT BEFORE: %08lX", level );
>>>>rtems_task_wake_after( 10 );
>>>>rtems_interrupt_disable(level);
>>>>rtems_interrupt_enable(level);
>>>>printf ( "\r\nINT AFTER: %08lX", level );
>>>>}
>>>
>>>
>>>I have more questions than answers.
>>>
>>>rtems_interrupt_enable/disable are implemented as inline assembly 
>>>language routines.  They are port specific which leads to
>>>
>>>(1) Which CPU are you using?
>>>
>>>There is no guarantee on the contents of level after calling enable
>>>so
>>>
>>>(2) are you sure they are really off?
>>>
>>>(3) can you print out the status register or whatever it is on this
>>
>>CPU 
>>
>>
>>>and we really check?
>>>
>>>
>>>
>>>
>>>>Kevin Kirspel
>>>>Osmetech 
>>>>235 Hembree Park Drive
>>>>Roswell GA, 30076
>>>>770-510-4444 x4568
>>>>
>>>>
>>>
>>>
>>>
>>
> 
> 

-- 
Ian Caddy
Goanna Technologies Pty Ltd
+61 8 9221 1860




More information about the users mailing list