summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel@rtems.org>2017-12-05 09:54:56 -0600
committerJoel Sherrill <joel@rtems.org>2017-12-06 12:48:45 -0600
commitd2711c37f1f189863bd679064cd37a7b0f700494 (patch)
tree9de0996bf13494274a61cf200a51edb1dbee154b
parentconfdefs: Replace RTEMS 4.12 with 5.1 (diff)
downloadrtems-d2711c37f1f189863bd679064cd37a7b0f700494.tar.bz2
taskmode.c: Ensure all error checking is done before modifying executing
Also use single conditional expressions to simplify error checking. Combined, this all resulted in a block of SMP enabled error checking. Updates #3000.
-rw-r--r--cpukit/rtems/src/taskmode.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c
index a345409f2a..91b16a565e 100644
--- a/cpukit/rtems/src/taskmode.c
+++ b/cpukit/rtems/src/taskmode.c
@@ -43,6 +43,31 @@ rtems_status_code rtems_task_mode(
if ( !previous_mode_set )
return RTEMS_INVALID_ADDRESS;
+#if defined( RTEMS_SMP )
+ /*
+ * When in SMP, you cannot disable preemption for a thread or
+ * alter its interrupt level. It must be fully preemptible with
+ * all interrupts enabled.
+ */
+ if ( rtems_configuration_is_smp_enabled() ) {
+ if ( mask & RTEMS_PREEMPT_MASK ) {
+ if ( !_Modes_Is_preempt( mode_set ) ) {
+ return RTEMS_NOT_IMPLEMENTED;
+ }
+ }
+
+ if ( mask & RTEMS_INTERRUPT_MASK ) {
+ return RTEMS_NOT_IMPLEMENTED;
+ }
+ }
+#endif
+
+ /*
+ * Complete all error checking before doing any operations which
+ * impact the executing thread. There should be no errors returned
+ * past this point.
+ */
+
executing = _Thread_Get_executing();
api = executing->API_Extensions[ THREAD_API_RTEMS ];
asr = &api->Signal;
@@ -63,18 +88,18 @@ rtems_status_code rtems_task_mode(
* These are generic thread scheduling characteristics.
*/
preempt_enabled = false;
+#if !defined( RTEMS_SMP )
if ( mask & RTEMS_PREEMPT_MASK ) {
-#if defined( RTEMS_SMP )
if ( rtems_configuration_is_smp_enabled() &&
!_Modes_Is_preempt( mode_set ) ) {
return RTEMS_NOT_IMPLEMENTED;
}
-#endif
bool is_preempt_enabled = _Modes_Is_preempt( mode_set );
preempt_enabled = !executing->is_preemptible && is_preempt_enabled;
executing->is_preemptible = is_preempt_enabled;
}
+#endif
if ( mask & RTEMS_TIMESLICE_MASK ) {
if ( _Modes_Is_timeslice(mode_set) ) {
@@ -88,8 +113,11 @@ rtems_status_code rtems_task_mode(
/*
* Set the new interrupt level
*/
- if ( mask & RTEMS_INTERRUPT_MASK )
+#if !defined( RTEMS_SMP )
+ if ( mask & RTEMS_INTERRUPT_MASK ) {
_Modes_Set_interrupt_level( mode_set );
+ }
+#endif
/*
* This is specific to the RTEMS API