Signal notification and non-preempt problem

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Jul 18 11:09:45 UTC 2013


Hello,

in RTEMS there are three routines that can deliver signals to a thread: 
rtems_signal_send(), _POSIX_signals_Unblock_thread() and pthread_kill().

It is possible to send signals from an interrupt service routine.

Signal handler invocation is an unconditional side-effect of _Thread_Dispatch().

Since many interrupt prologues evaluate _Thread_Dispatch_necessary before they 
branch to _Thread_Dispatch() there is a special case in the signal notification 
path.  Here we have:

  if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
    _Thread_Dispatch_necessary = true;

Now we have the following problem.  Suppose we have a thread with non-preempt mode.

An interrupt happens and unblocks another thread with a higher priority.  The 
normal scheduler will do this:

void _Scheduler_priority_Unblock (
   Thread_Control          *the_thread
)
{
   _Scheduler_priority_Ready_queue_enqueue(the_thread);

   /* TODO: flash critical section? */

   /*
    *  If the thread that was unblocked is more important than the heir,
    *  then we have a new heir.  This may or may not result in a
    *  context switch.
    *
    *  Normal case:
    *    If the current thread is preemptible, then we need to do
    *    a context switch.
    *  Pseudo-ISR case:
    *    Even if the thread isn't preemptible, if the new heir is
    *    a pseudo-ISR system task, we need to do a context switch.
    */
   if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
     _Thread_Heir = the_thread;
     if ( _Thread_Executing->is_preemptible ||
         the_thread->current_priority == 0 )
       _Thread_Dispatch_necessary = true;
   }
}

The heir is updated, but _Thread_Dispatch_necessary remains unchanged!

Now suppose an interrupt happens and sends a signal to the executing thread. 
Now all conditions in

  if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
    _Thread_Dispatch_necessary = true;

are satisfied and _Thread_Dispatch_necessary is set to true.  This will result 
in _Thread_Dispatch() being called and a context switch is performed to the 
heir thread although the executing thread has the non-preempt mode!

Is this intentional?

-- 
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.huber at embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.



More information about the devel mailing list