Changeset 73ebf9a in rtems


Ignore:
Timestamp:
May 14, 2021, 12:54:42 PM (5 weeks ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
98cb84e
Parents:
b9083c55
git-author:
Sebastian Huber <sebastian.huber@…> (05/14/21 12:54:42)
git-committer:
Sebastian Huber <sebastian.huber@…> (05/14/21 14:56:03)
Message:

rtems: Fix task restart within interrupt context

rtems_task_restart() may be called from within interrupt context. So
checking only that the thread to restart is equal to the executing
thread is insufficient to determine a self restart. We have to also
check that no ISR is in progress. Merge _Thread_Restart_other() and
_Thread_Restart_self() into one _Thread_Restart() since they share a lot
of common code.

Close #4412.

Location:
cpukit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpukit/include/rtems/score/threadimpl.h

    rb9083c55 r73ebf9a  
    272272
    273273/**
    274  * @brief Restarts the currently executing thread.
    275  *
    276  * @param[in, out] executing The currently executing thread.
    277  * @param entry The start entry information for @a executing.
    278  * @param lock_context The lock context.
    279  */
    280 RTEMS_NO_RETURN void _Thread_Restart_self(
    281   Thread_Control                 *executing,
    282   const Thread_Entry_information *entry,
    283   ISR_lock_Context               *lock_context
    284 );
    285 
    286 /**
    287274 * @brief Restarts the thread.
    288275 *
     
    297284 * @retval STATUS_INCORRECT_STATE The thread was dormant.
    298285 */
    299 Status_Control _Thread_Restart_other(
     286Status_Control _Thread_Restart(
    300287  Thread_Control                 *the_thread,
    301288  const Thread_Entry_information *entry,
  • cpukit/rtems/src/taskrestart.c

    rb9083c55 r73ebf9a  
    4949  entry = the_thread->Start.Entry;
    5050  entry.Kinds.Numeric.argument = argument;
    51 
    52   if ( the_thread == _Thread_Executing ) {
    53     _Thread_Restart_self( the_thread, &entry, &lock_context );
    54     RTEMS_UNREACHABLE();
    55   }
    56 
    57   status = _Thread_Restart_other( the_thread, &entry, &lock_context );
     51  status = _Thread_Restart( the_thread, &entry, &lock_context );
    5852
    5953  return _Status_Get( status );
  • cpukit/score/src/threadrestart.c

    rb9083c55 r73ebf9a  
    66 * @brief This source file contains the implementation of _Thread_Cancel(),
    77 *   _Thread_Change_life(), _Thread_Close(), _Thread_Exit(), _Thread_Join(),
    8  *   _Thread_Kill_zombies(), _Thread_Restart_other(), _Thread_Restart_self(),
    9  *   and _Thread_Set_life_protection().
     8 *   _Thread_Kill_zombies(), _Thread_Restart(), and _Thread_Set_life_protection().
    109 */
    1110
     
    518517}
    519518
    520 Status_Control _Thread_Restart_other(
     519Status_Control _Thread_Restart(
    521520  Thread_Control                 *the_thread,
    522521  const Thread_Entry_information *entry,
     
    526525  Thread_Life_state    previous;
    527526  Per_CPU_Control     *cpu_self;
     527  Thread_Life_state    ignored_life_states;
    528528  Thread_queue_Context queue_context;
    529529
     
    533533    _Thread_State_release( the_thread, lock_context );
    534534    return STATUS_INCORRECT_STATE;
     535  }
     536
     537  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
     538
     539  if (
     540    the_thread == _Per_CPU_Get_executing( cpu_self ) &&
     541    !_ISR_Is_in_progress()
     542  ) {
     543    ignored_life_states = THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED;
     544  } else {
     545    ignored_life_states = 0;
    535546  }
    536547
     
    540551    0,
    541552    THREAD_LIFE_RESTARTING,
    542     0
    543   );
    544 
    545   cpu_self = _Thread_Dispatch_disable_critical( lock_context );
     553    ignored_life_states
     554  );
    546555
    547556  if ( _Thread_Is_life_change_allowed( previous ) ) {
     
    574583}
    575584
    576 void _Thread_Restart_self(
    577   Thread_Control                 *executing,
    578   const Thread_Entry_information *entry,
    579   ISR_lock_Context               *lock_context
    580 )
    581 {
    582   Per_CPU_Control      *cpu_self;
    583   Thread_queue_Context  queue_context;
    584 
    585   _Assert(
    586     _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
    587   );
    588   _Assert(
    589     executing->current_state == STATES_READY
    590       || executing->current_state == STATES_SUSPENDED
    591   );
    592 
    593   _Thread_queue_Context_initialize( &queue_context );
    594   _Thread_queue_Context_clear_priority_updates( &queue_context );
    595   _Thread_State_acquire_critical( executing, lock_context );
    596 
    597   executing->Start.Entry = *entry;
    598   _Thread_Change_life_locked(
    599     executing,
    600     0,
    601     THREAD_LIFE_RESTARTING,
    602     THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED
    603   );
    604 
    605   cpu_self = _Thread_Dispatch_disable_critical( lock_context );
    606   _Thread_State_release( executing, lock_context );
    607 
    608   _Thread_Wait_acquire_default( executing, lock_context );
    609   _Thread_Priority_change(
    610     executing,
    611     &executing->Real_priority,
    612     executing->Start.initial_priority,
    613     false,
    614     &queue_context
    615   );
    616   _Thread_Wait_release_default( executing, lock_context );
    617 
    618   _Thread_Priority_update( &queue_context );
    619   _Thread_Dispatch_direct_no_return( cpu_self );
    620   RTEMS_UNREACHABLE();
    621 }
    622 
    623585Thread_Life_state _Thread_Change_life(
    624586  Thread_Life_state clear,
Note: See TracChangeset for help on using the changeset viewer.