summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-02-26 10:33:36 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-05 11:36:19 +0100
commitb8a5abf3fafa9df7cc0354c0ada6192c38e78354 (patch)
treea20b108ecbf95fa3e401a8073d7f35603b4bf2e1 /cpukit/rtems
parentscore: Add and use PRIORITY_PSEUDO_ISR (diff)
downloadrtems-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')
-rw-r--r--cpukit/rtems/src/taskmode.c50
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;
}