how to suspend current running thread from within exception level handler

Joel Sherrill joel.sherrill at OARcorp.com
Tue May 1 19:24:05 UTC 2012


First you are violating the RTEMS API badly and going into
the SuperCore which is not allowed.

I think you need to carefully consider each state the system
and CPU can be in when you get to this point.

+ exception during RTEMS initialization
+ exception during a task
+ exception during an ISR

And you have to consider whether this exception handler
is being registered as an RTEMS interrupt handler or not.

If not registered as an RTEMS interrupt handler, then
you can't make RTEMS calls during this at all. That
limits your options considerably to change a task state.

If registered as an RTEMS interrupt handler, then
rtems_interrupt_is_in_process() will always return true.
That's an issue.

rtems_task_suspend() is safe from an ISR  and should be
used instead of the score routines you are calling.

When in an RTEMS interrupt handler, you are always
in a thread dispatching disabled critical section.  If you
interrupted an RTEMS dispatching disabled section,
then the value of (dispatch disable count - isr nest level) > 0.

When you get to this point, your options are generally
very limited. You can attempt to suspend the task and
continue. But if inside RTEMS, the system is dead at this
point.

If you didn't get an exception while in a thread and outside
RTEMS, I am betting you can't do anything except halt or
reset.

Most of this can be done via the public API and those that can't
are open points for discussion for additions.

It is also worth considering that the states above I defined
are true across all ports and BSPs. Thus a framework
for an exception handler may make a lot of sense here.
There are not many options and it would be relatively
easy to make those available to the BSP author. The
decision of:

+ during initialization
+ inside RTEMS at task level
+ outside RTEMS at task level
+ during ISR

Is portable.

--joel


On 05/01/2012 02:08 PM, Hill, Jeffrey O wrote:
> Hi,
>
> I am writing a last chance RTEMS exception handler function for the nios2 processor. In this function I attempt to suspend the current running thread, and switch to the next runable thread. Here is the (probably naïve) code I tried to write to accomplish that aim, but I don't know if it's even close to correct. Any comments from the gurus?
>
>          if ( !_States_Is_suspended ( _Thread_Executing->current_state ) ) {
>              _Thread_Suspend ( _Thread_Executing );
>              /*
>               * we cant call _Thread_Dispatch here because interrupts
>               * are currently disabled
>               */
> #if 0
>              if ( !_Thread_Dispatch_in_critical_section() ) {
>                  _CPU_ISR_Enable( isrCookie );
>                  _Thread_Dispatch();
>                  _CPU_ISR_Disable( isrCookie );
>              }
> #endif
>          }
>
> Attached is also the current state of the (somewhat) complete last chance exception handler for context. When I attach with the debugger after the fault has already occurred I don't appear to see the faulting thread in the thread list whereas I can at least sometimes see the faulting thread if the debugger is already attached when the exception happens (in that situation my last chance exception handler doesn't run).
>
> Thanks for your help,
>
> Jeff
>
> static void __Exception_Handler_Last_Resort ( uint32_t cause, CPU_Exception_frame * pefr )
> {
>      printk ( "\n" );
>      printk ( "\07" ); /* ding */
>      printk (
>          "**** Unexpected nios2 \"%s\" exception\07\n",
>          _Nios2_Exception_Cause_Name ( cause ) );
>      static const char * const pCloseMsg =
>          "*****************************************************************\n";
>      if ( _ISR_Is_in_progress () ) {
>          printk (
>          "**** Executing in an interrupt service routine, halting processor\n" );
>          printk ( pCloseMsg );
>          _CPU_Fatal_halt(0xECC0);
>      }
>      else if ( _Thread_Executing ) {
>          char threadName[32]; /* maybe only needs to be 4 characters */
>          const char * pName;
>          {
>              uint32_t isrCookie;
>              _CPU_ISR_Disable( isrCookie );
>              pName = _Objects_Get_name_as_string (
>                                  _Thread_Executing->Object.id,
>                                  sizeof ( threadName ), threadName );
>              _CPU_ISR_Enable( isrCookie );
>          }
>          if ( ! pName ) {
>              pName = "anonymous";
>          }
>          printk ( "**** Suspending thread \"%s\"\n", pName );
>          printk ( pCloseMsg );
>          /*
>           * I am operating under the assumption that interrupts are locked
>           * out while the exception handler is running so this code would
>           * need to change if that situation changes.
>           */
>          if ( !_States_Is_suspended ( _Thread_Executing->current_state ) ) {
>              _Thread_Suspend ( _Thread_Executing );
>              /*
>               * we cant call _Thread_Dispatch here because interrupts
>               * are currently disabled
>               */
> #if 0
>              if ( !_Thread_Dispatch_in_critical_section() ) {
>                  _CPU_ISR_Enable( isrCookie );
>                  _Thread_Dispatch();
>                  _CPU_ISR_Disable( isrCookie );
>              }
> #endif
>          }
>      }
>      else {
>          printk ( "**** Multitasking hasn't started, halting processor\n" );
>          printk ( pCloseMsg );
>          _CPU_Fatal_halt(0xECC0);
>      }
> }
>
> _______________________________________________
> rtems-users mailing list
> rtems-users at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-users


-- 
Joel Sherrill, Ph.D.             Director of Research&   Development
joel.sherrill at OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
     Support Available             (256) 722-9985





More information about the users mailing list