[PATCH 13/13] rtems: Avoid potential recursion in ASR handling
Gedare Bloom
gedare at rtems.org
Thu Feb 18 17:49:26 UTC 2021
On Wed, Feb 17, 2021 at 12:30 PM Sebastian Huber
<sebastian.huber at embedded-brains.de> wrote:
>
> 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;
'prev' is unclear here, especially since we have "normal" as a
previous mode also. Maybe, 'asr_is_preemptible' is better?
> + 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;
ditto, just use 'asr_is_enabled' variable here.
> + asr->is_enabled = normal_asr_is_enabled;
> +
> + if (
> + normal_asr_is_enabled &&
> + !prev_asr_is_enabled &&
no indent, align
only indent within the compound expression if you have to break the
simple expression (e.g., breaking at an inequality comparison)
https://docs.rtems.org/branches/master/eng/coding-formatting.html#breaking-long-lines
willing to buy: style formatter.
> + asr->signals_pending != 0
> + ) {
> + _Thread_Append_post_switch_action( executing, action );
> + }
> }
>
> rtems_status_code rtems_signal_send(
> --
> 2.26.2
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list