[rtems commit] taskmode.c: Ensure all error checking is done before modifying executing

Joel Sherrill joel at rtems.org
Wed Dec 6 18:49:02 UTC 2017


Module:    rtems
Branch:    master
Commit:    d2711c37f1f189863bd679064cd37a7b0f700494
Changeset: http://git.rtems.org/rtems/commit/?id=d2711c37f1f189863bd679064cd37a7b0f700494

Author:    Joel Sherrill <joel at rtems.org>
Date:      Tue Dec  5 09:54:56 2017 -0600

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.

---

 cpukit/rtems/src/taskmode.c | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c
index a345409..91b16a5 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



More information about the vc mailing list