diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-02-26 10:33:36 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-03-05 11:36:19 +0100 |
commit | b8a5abf3fafa9df7cc0354c0ada6192c38e78354 (patch) | |
tree | a20b108ecbf95fa3e401a8073d7f35603b4bf2e1 /cpukit/rtems/src | |
parent | score: Add and use PRIORITY_PSEUDO_ISR (diff) | |
download | rtems-b8a5abf3fafa9df7cc0354c0ada6192c38e78354.tar.bz2 |
score: Update _Thread_Heir only if necessary
Previously, the _Thread_Heir was updated unconditionally in case a new
heir was determined. The _Thread_Dispatch_necessary was only updated in
case the executing thread was preemptible or an internal thread was
unblocked. Change this to update the _Thread_Heir and
_Thread_Dispatch_necessary only in case the currently selected heir
thread is preemptible or a dispatch is forced. Move the schedule
decision into the change priority operation and use the schedule
operation only in rtems_task_mode() in case preemption is enabled or an
ASR dispatch is necessary. This is a behaviour change. Previously, the
RTEMS_NO_PREEMPT also prevented signal delivery in certain cases (not
always). Now, signal delivery is no longer influenced by
RTEMS_NO_PREEMPT. Since the currently selected heir thread is used to
determine if a new heir is chosen, non-preemptible heir threads
currently not executing now prevent a new heir. This may have an
application impact, see change test tm04. Document this change in sp04.
Update #2273.
Diffstat (limited to 'cpukit/rtems/src')
-rw-r--r-- | cpukit/rtems/src/taskmode.c | 50 |
1 files changed, 15 insertions, 35 deletions
diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c index eeb3e0fc7c..1056c6b11e 100644 --- a/cpukit/rtems/src/taskmode.c +++ b/cpukit/rtems/src/taskmode.c @@ -21,42 +21,10 @@ #include <rtems/rtems/tasks.h> #include <rtems/rtems/asrimpl.h> #include <rtems/rtems/modesimpl.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/threadimpl.h> #include <rtems/config.h> -static void _RTEMS_Tasks_Dispatch_if_necessary( - Thread_Control *executing, - bool needs_asr_dispatching -) -{ - if ( _Thread_Dispatch_is_enabled() ) { - bool dispatch_necessary = needs_asr_dispatching; - - /* - * FIXME: This locking approach is brittle. It only works since the - * current simple SMP scheduler has no support for the non-preempt mode. - */ -#if defined( RTEMS_SMP ) - ISR_Level level; - - _ISR_Disable_without_giant( level ); -#endif - - if ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) { - dispatch_necessary = true; - _Thread_Dispatch_necessary = dispatch_necessary; - } - -#if defined( RTEMS_SMP ) - _ISR_Enable_without_giant( level ); -#endif - - if ( dispatch_necessary ) { - _Thread_Dispatch(); - } - } -} - rtems_status_code rtems_task_mode( rtems_mode mode_set, rtems_mode mask, @@ -66,6 +34,7 @@ rtems_status_code rtems_task_mode( Thread_Control *executing; RTEMS_API_Control *api; ASR_Information *asr; + bool preempt_enabled; bool needs_asr_dispatching; rtems_mode old_mode; @@ -91,6 +60,7 @@ rtems_status_code rtems_task_mode( /* * These are generic thread scheduling characteristics. */ + preempt_enabled = false; if ( mask & RTEMS_PREEMPT_MASK ) { #if defined( RTEMS_SMP ) if ( rtems_configuration_is_smp_enabled() && @@ -98,8 +68,10 @@ rtems_status_code rtems_task_mode( return RTEMS_NOT_IMPLEMENTED; } #endif + bool is_preempt_enabled = _Modes_Is_preempt( mode_set ); - executing->is_preemptible = _Modes_Is_preempt( mode_set ); + preempt_enabled = !executing->is_preemptible && is_preempt_enabled; + executing->is_preemptible = is_preempt_enabled; } if ( mask & RTEMS_TIMESLICE_MASK ) { @@ -137,7 +109,15 @@ rtems_status_code rtems_task_mode( } } - _RTEMS_Tasks_Dispatch_if_necessary( executing, needs_asr_dispatching ); + if ( preempt_enabled || needs_asr_dispatching ) { + ISR_Level level; + + _Thread_Disable_dispatch(); + _ISR_Disable( level ); + _Scheduler_Schedule( executing ); + _ISR_Enable( level ); + _Thread_Enable_dispatch(); + } return RTEMS_SUCCESSFUL; } |