Do the mode changes necessary for the ASR processing directly under protection of the thread state lock to avoid the recursive calls to thread dispatching done in rtems_task_mode().
Update #4244. --- cpukit/rtems/src/signalsend.c | 89 ++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 7 deletions(-) diff --git a/cpukit/rtems/src/signalsend.c b/cpukit/rtems/src/signalsend.c index 606ddfcb53..dd2f70ec53 100644 --- a/cpukit/rtems/src/signalsend.c +++ b/cpukit/rtems/src/signalsend.c @@ -21,7 +21,9 @@ #endif #include <rtems/rtems/signalimpl.h> +#include <rtems/rtems/modesimpl.h> #include <rtems/rtems/tasksdata.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/threaddispatch.h> #include <rtems/score/threadimpl.h> @@ -33,10 +35,17 @@ static void _Signal_Action_handler( ISR_lock_Context *lock_context ) { - RTEMS_API_Control *api; - ASR_Information *asr; - rtems_signal_set signal_set; - rtems_mode prev_mode; + RTEMS_API_Control *api; + ASR_Information *asr; + rtems_signal_set signal_set; + bool normal_is_preemptible; + uint32_t normal_cpu_time_budget; + Thread_CPU_budget_algorithms normal_budget_algorithm; + bool normal_asr_is_enabled; + uint32_t normal_isr_level; + uint32_t asr_isr_level; + bool prev_is_preemptible; + bool prev_asr_is_enabled; (void) action; @@ -48,16 +57,82 @@ static void _Signal_Action_handler( _Assert( signal_set != 0 ); asr->signals_pending = 0; - _Thread_State_release( executing, lock_context ); + /* Save normal mode */ + + normal_is_preemptible = executing->is_preemptible; + normal_asr_is_enabled = asr->is_enabled; + normal_cpu_time_budget = executing->cpu_time_budget; + normal_budget_algorithm = executing->budget_algorithm; + + /* Set mode for ASR processing */ + + executing->is_preemptible = _Modes_Is_preempt( asr->mode_set ); + asr->is_enabled = !_Modes_Is_asr_disabled( asr->mode_set ); + _Modes_Set_timeslice( executing, asr->mode_set ); + asr_isr_level = _Modes_Get_interrupt_level( asr->mode_set ); - rtems_task_mode( asr->mode_set, RTEMS_ALL_MODE_MASKS, &prev_mode ); + if ( executing->is_preemptible && !normal_is_preemptible ) { + Per_CPU_Control *cpu_self; + + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); + _Scheduler_Schedule( executing ); + _Thread_State_release( executing, lock_context ); + _Thread_Dispatch_direct( cpu_self ); + } else { + _Thread_State_release( executing, lock_context ); + } + + normal_isr_level = _ISR_Get_level(); + _ISR_Set_level( asr_isr_level ); /* Call the ASR handler in the ASR processing mode */ ( *asr->handler )( signal_set ); - rtems_task_mode( prev_mode, RTEMS_ALL_MODE_MASKS, &prev_mode ); + /* Restore normal mode */ + + _ISR_Set_level( normal_isr_level ); _Thread_State_acquire( executing, lock_context ); + + executing->cpu_time_budget = normal_cpu_time_budget ; + executing->budget_algorithm = normal_budget_algorithm ; + prev_is_preemptible = executing->is_preemptible; + executing->is_preemptible = normal_is_preemptible; + + /* + * We do the best to avoid recursion in the ASR processing. A well behaved + * application will disable ASR processing during ASR processing. In this + * case, ASR processing is currently disabled. We do now the thread dispatch + * necessary due to a re-enabled preemption mode. This helps to avoid doing + * the next round of ASR processing recursively in _Thread_Dispatch_direct(). + */ + if ( normal_is_preemptible && !prev_is_preemptible ) { + Per_CPU_Control *cpu_self; + + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); + _Scheduler_Schedule( executing ); + _Thread_State_release( executing, lock_context ); + _Thread_Dispatch_direct( cpu_self ); + _Thread_State_acquire( executing, lock_context ); + } + + /* + * Restore the normal ASR processing mode. If we enable ASR processing and + * there are pending signals, then add us as a post-switch action. The loop + * in _Thread_Run_post_switch_actions() will continue after our return and + * call us again. This avoids a recursion. + */ + + prev_asr_is_enabled = asr->is_enabled; + asr->is_enabled = normal_asr_is_enabled; + + if ( + normal_asr_is_enabled && + !prev_asr_is_enabled && + asr->signals_pending != 0 + ) { + _Thread_Append_post_switch_action( executing, action ); + } } rtems_status_code rtems_signal_send( -- 2.26.2 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel