[rtems commit] score: Fix scheduler helping protocol

Sebastian Huber sebh at rtems.org
Mon May 11 07:21:06 UTC 2015


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Sun May 10 21:30:26 2015 +0200

score: Fix scheduler helping protocol

Account for priority changes of threads executing in a foreign
partition.  Exchange idle threads in case a victim node uses an idle
thread and the new scheduled node needs an idle thread.

---

 cpukit/score/include/rtems/score/mrspimpl.h        |   4 +-
 cpukit/score/include/rtems/score/schedulerimpl.h   |  84 +++-
 .../score/include/rtems/score/schedulersmpimpl.h   | 218 +++++----
 testsuites/smptests/smpmrsp01/init.c               | 224 ++++++++-
 testsuites/smptests/smpmrsp01/smpmrsp01.scn        | 504 +++++++++++----------
 5 files changed, 680 insertions(+), 354 deletions(-)

diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h
index c1e05e4..c40f41f 100644
--- a/cpukit/score/include/rtems/score/mrspimpl.h
+++ b/cpukit/score/include/rtems/score/mrspimpl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2014-2015 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -230,7 +230,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Obtain(
 )
 {
   MRSP_Status status;
-  const Scheduler_Control *scheduler = _Scheduler_Get( executing );
+  const Scheduler_Control *scheduler = _Scheduler_Get_own( executing );
   uint32_t scheduler_index = _Scheduler_Get_index( scheduler );
   Priority_Control initial_priority = executing->current_priority;
   Priority_Control ceiling_priority =
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index d11b2c5..212bace 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -10,7 +10,7 @@
 /*
  *  Copyright (C) 2010 Gedare Bloom.
  *  Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
- *  Copyright (c) 2014 embedded brains GmbH
+ *  Copyright (c) 2014-2015 embedded brains GmbH
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -950,6 +950,26 @@ void _Scheduler_Thread_change_resource_root(
   Thread_Control *root
 );
 
+RTEMS_INLINE_ROUTINE void _Scheduler_Set_idle_thread(
+  Scheduler_Node *node,
+  Thread_Control *idle
+)
+{
+  _Assert(
+    node->help_state == SCHEDULER_HELP_ACTIVE_OWNER
+      || node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL
+  );
+  _Assert( _Scheduler_Node_get_idle( node ) == NULL );
+  _Assert(
+    _Scheduler_Node_get_owner( node ) == _Scheduler_Node_get_user( node )
+  );
+
+  _Scheduler_Thread_set_node( idle, node );
+
+  _Scheduler_Node_set_user( node, idle );
+  node->idle = idle;
+}
+
 /**
  * @brief Use an idle thread for this scheduler node.
  *
@@ -970,45 +990,44 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Use_idle_thread(
 {
   Thread_Control *idle = ( *get_idle_thread )( context );
 
-  _Assert(
-    node->help_state == SCHEDULER_HELP_ACTIVE_OWNER
-      || node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL
-  );
-  _Assert( _Scheduler_Node_get_idle( node ) == NULL );
-  _Assert(
-    _Scheduler_Node_get_owner( node ) == _Scheduler_Node_get_user( node )
-  );
-
-  _Scheduler_Thread_set_node( idle, node );
-
-  _Scheduler_Node_set_user( node, idle );
-  node->idle = idle;
+  _Scheduler_Set_idle_thread( node, idle );
 
   return idle;
 }
 
+typedef enum {
+  SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE,
+  SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE,
+  SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK
+} Scheduler_Try_to_schedule_action;
+
 /**
  * @brief Try to schedule this scheduler node.
  *
  * @param[in] context The scheduler instance context.
  * @param[in] node The node which wants to get scheduled.
+ * @param[in] idle A potential idle thread used by a potential victim node.
  * @param[in] get_idle_thread Function to get an idle thread.
  *
  * @retval true This node can be scheduled.
  * @retval false Otherwise.
  */
-RTEMS_INLINE_ROUTINE bool _Scheduler_Try_to_schedule_node(
+RTEMS_INLINE_ROUTINE Scheduler_Try_to_schedule_action
+_Scheduler_Try_to_schedule_node(
   Scheduler_Context         *context,
   Scheduler_Node            *node,
+  Thread_Control            *idle,
   Scheduler_Get_idle_thread  get_idle_thread
 )
 {
-  bool schedule;
+  Scheduler_Try_to_schedule_action action;
   Thread_Control *owner;
   Thread_Control *user;
 
+  action = SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE;
+
   if ( node->help_state == SCHEDULER_HELP_YOURSELF ) {
-    return true;
+    return action;
   }
 
   owner = _Scheduler_Node_get_owner( node );
@@ -1018,32 +1037,33 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_Try_to_schedule_node(
     if ( user->Scheduler.state == THREAD_SCHEDULER_READY ) {
       _Scheduler_Thread_set_scheduler_and_node( user, node, owner );
     } else if ( owner->Scheduler.state == THREAD_SCHEDULER_BLOCKED ) {
-      _Scheduler_Use_idle_thread( context, node, get_idle_thread );
+      if ( idle != NULL ) {
+        action = SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE;
+      } else {
+        _Scheduler_Use_idle_thread( context, node, get_idle_thread );
+      }
     } else {
       _Scheduler_Node_set_user( node, owner );
     }
-
-    schedule = true;
   } else if ( node->help_state == SCHEDULER_HELP_ACTIVE_OWNER ) {
     if ( user->Scheduler.state == THREAD_SCHEDULER_READY ) {
       _Scheduler_Thread_set_scheduler_and_node( user, node, owner );
+    } else if ( idle != NULL ) {
+      action = SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE;
     } else {
       _Scheduler_Use_idle_thread( context, node, get_idle_thread );
     }
-
-    schedule = true;
   } else {
     _Assert( node->help_state == SCHEDULER_HELP_PASSIVE );
 
     if ( user->Scheduler.state == THREAD_SCHEDULER_READY ) {
       _Scheduler_Thread_set_scheduler_and_node( user, node, owner );
-      schedule = true;
     } else {
-      schedule = false;
+      action = SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK;
     }
   }
 
-  return schedule;
+  return action;
 }
 
 /**
@@ -1078,6 +1098,20 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Release_idle_thread(
   return idle;
 }
 
+RTEMS_INLINE_ROUTINE void _Scheduler_Exchange_idle_thread(
+  Scheduler_Node *needs_idle,
+  Scheduler_Node *uses_idle,
+  Thread_Control *idle
+)
+{
+  uses_idle->idle = NULL;
+  _Scheduler_Node_set_user(
+    uses_idle,
+    _Scheduler_Node_get_owner( uses_idle )
+  );
+  _Scheduler_Set_idle_thread( needs_idle, idle );
+}
+
 /**
  * @brief Block this scheduler node.
  *
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index e41c737..a395f2c 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -7,7 +7,7 @@
  */
 
 /*
- * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2013-2015 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -532,41 +532,76 @@ static inline Thread_Control *_Scheduler_SMP_Enqueue_to_scheduled(
   Scheduler_SMP_Allocate_processor  allocate_processor
 )
 {
-  Thread_Control *user = _Scheduler_Node_get_user( node );
-  Thread_Control *lowest_scheduled_user =
-    _Scheduler_Node_get_user( lowest_scheduled );
   Thread_Control *needs_help;
-  Thread_Control *idle;
+  Scheduler_Try_to_schedule_action action;
 
-  _Scheduler_SMP_Node_change_state(
-    _Scheduler_SMP_Node_downcast( lowest_scheduled ),
-    SCHEDULER_SMP_NODE_READY
-  );
-  _Scheduler_Thread_change_state(
-    lowest_scheduled_user,
-    THREAD_SCHEDULER_READY
-  );
-
-  _Scheduler_Thread_set_node( user, node );
-
-  _Scheduler_SMP_Allocate_processor(
+  action = _Scheduler_Try_to_schedule_node(
     context,
     node,
-    lowest_scheduled,
-    allocate_processor
+    _Scheduler_Node_get_idle( lowest_scheduled ),
+    _Scheduler_SMP_Get_idle_thread
   );
 
-  ( *insert_scheduled )( context, node );
-  ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
+  if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
+    Thread_Control *lowest_scheduled_user =
+      _Scheduler_Node_get_user( lowest_scheduled );
+    Thread_Control *idle;
 
-  idle = _Scheduler_Release_idle_thread(
-    context,
-    lowest_scheduled,
-    _Scheduler_SMP_Release_idle_thread
-  );
-  if ( idle == NULL ) {
-    needs_help = lowest_scheduled_user;
+    _Scheduler_SMP_Node_change_state(
+      _Scheduler_SMP_Node_downcast( lowest_scheduled ),
+      SCHEDULER_SMP_NODE_READY
+    );
+    _Scheduler_Thread_change_state(
+      lowest_scheduled_user,
+      THREAD_SCHEDULER_READY
+    );
+
+    _Scheduler_SMP_Allocate_processor(
+      context,
+      node,
+      lowest_scheduled,
+      allocate_processor
+    );
+
+    ( *insert_scheduled )( context, node );
+    ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
+
+    idle = _Scheduler_Release_idle_thread(
+      context,
+      lowest_scheduled,
+      _Scheduler_SMP_Release_idle_thread
+    );
+    if ( idle == NULL ) {
+      needs_help = lowest_scheduled_user;
+    } else {
+      needs_help = NULL;
+    }
+  } else if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE ) {
+    _Scheduler_SMP_Node_change_state(
+      _Scheduler_SMP_Node_downcast( lowest_scheduled ),
+      SCHEDULER_SMP_NODE_READY
+    );
+    _Scheduler_SMP_Node_change_state(
+      _Scheduler_SMP_Node_downcast( node ),
+      SCHEDULER_SMP_NODE_SCHEDULED
+    );
+
+    ( *insert_scheduled )( context, node );
+    ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
+
+    _Scheduler_Exchange_idle_thread(
+      node,
+      lowest_scheduled,
+      _Scheduler_Node_get_idle( lowest_scheduled )
+    );
+
+    needs_help = NULL;
   } else {
+    _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
+    _Scheduler_SMP_Node_change_state(
+      _Scheduler_SMP_Node_downcast( node ),
+      SCHEDULER_SMP_NODE_BLOCKED
+    );
     needs_help = NULL;
   }
 
@@ -660,7 +695,7 @@ static inline Thread_Control *_Scheduler_SMP_Enqueue_scheduled_ordered(
 {
   Thread_Control *needs_help;
 
-  while ( true ) {
+  do {
     Scheduler_Node *highest_ready = ( *get_highest_ready )( context, node );
 
     /*
@@ -671,55 +706,80 @@ static inline Thread_Control *_Scheduler_SMP_Enqueue_scheduled_ordered(
       ( *insert_scheduled )( context, node );
 
       needs_help = NULL;
+    } else {
+      Scheduler_Try_to_schedule_action action;
 
-      break;
-    } else if (
-      _Scheduler_Try_to_schedule_node(
+      action = _Scheduler_Try_to_schedule_node(
         context,
         highest_ready,
+        _Scheduler_Node_get_idle( node ),
         _Scheduler_SMP_Get_idle_thread
-      )
-    ) {
-      Thread_Control *user = _Scheduler_Node_get_user( node );
-      Thread_Control *idle;
-
-      _Scheduler_SMP_Node_change_state(
-        _Scheduler_SMP_Node_downcast( node ),
-        SCHEDULER_SMP_NODE_READY
       );
-      _Scheduler_Thread_change_state( user, THREAD_SCHEDULER_READY );
 
-      _Scheduler_SMP_Allocate_processor(
-        context,
-        highest_ready,
-        node,
-        allocate_processor
-      );
+      if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
+        Thread_Control *user = _Scheduler_Node_get_user( node );
+        Thread_Control *idle;
 
-      ( *insert_ready )( context, node );
-      ( *move_from_ready_to_scheduled )( context, highest_ready );
+        _Scheduler_SMP_Node_change_state(
+          _Scheduler_SMP_Node_downcast( node ),
+          SCHEDULER_SMP_NODE_READY
+        );
+        _Scheduler_Thread_change_state( user, THREAD_SCHEDULER_READY );
+
+        _Scheduler_SMP_Allocate_processor(
+          context,
+          highest_ready,
+          node,
+          allocate_processor
+        );
+
+        ( *insert_ready )( context, node );
+        ( *move_from_ready_to_scheduled )( context, highest_ready );
+
+        idle = _Scheduler_Release_idle_thread(
+          context,
+          node,
+          _Scheduler_SMP_Release_idle_thread
+        );
+        if ( idle == NULL ) {
+          needs_help = user;
+        } else {
+          needs_help = NULL;
+        }
+      } else if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE ) {
+        _Scheduler_SMP_Node_change_state(
+          _Scheduler_SMP_Node_downcast( node ),
+          SCHEDULER_SMP_NODE_READY
+        );
+        _Scheduler_SMP_Node_change_state(
+          _Scheduler_SMP_Node_downcast( highest_ready ),
+          SCHEDULER_SMP_NODE_SCHEDULED
+        );
+
+        ( *insert_ready )( context, node );
+        ( *move_from_ready_to_scheduled )( context, highest_ready );
+
+        _Scheduler_Exchange_idle_thread(
+          highest_ready,
+          node,
+          _Scheduler_Node_get_idle( node )
+        );
 
-      idle = _Scheduler_Release_idle_thread(
-        context,
-        node,
-        _Scheduler_SMP_Release_idle_thread
-      );
-      if ( idle == NULL ) {
-        needs_help = user;
-      } else {
         needs_help = NULL;
-      }
+      } else {
+        _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
 
-      break;
-    } else {
-      _Scheduler_SMP_Node_change_state(
-        _Scheduler_SMP_Node_downcast( highest_ready ),
-        SCHEDULER_SMP_NODE_BLOCKED
-      );
+        _Scheduler_SMP_Node_change_state(
+          _Scheduler_SMP_Node_downcast( highest_ready ),
+          SCHEDULER_SMP_NODE_BLOCKED
+        );
 
-      ( *extract_from_ready )( context, highest_ready );
+        ( *extract_from_ready )( context, highest_ready );
+
+        continue;
+      }
     }
-  }
+  } while ( false );
 
   return needs_help;
 }
@@ -740,16 +800,18 @@ static inline void _Scheduler_SMP_Schedule_highest_ready(
   Scheduler_SMP_Allocate_processor  allocate_processor
 )
 {
-  while ( true ) {
+  do {
     Scheduler_Node *highest_ready = ( *get_highest_ready )( context, victim );
+    Scheduler_Try_to_schedule_action action;
 
-    if (
-      _Scheduler_Try_to_schedule_node(
-        context,
-        highest_ready,
-        _Scheduler_SMP_Get_idle_thread
-      )
-    ) {
+    action = _Scheduler_Try_to_schedule_node(
+      context,
+      highest_ready,
+      NULL,
+      _Scheduler_SMP_Get_idle_thread
+    );
+
+    if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
       _Scheduler_SMP_Allocate_processor(
         context,
         highest_ready,
@@ -758,17 +820,19 @@ static inline void _Scheduler_SMP_Schedule_highest_ready(
       );
 
       ( *move_from_ready_to_scheduled )( context, highest_ready );
-
-      break;
     } else {
+      _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
+
       _Scheduler_SMP_Node_change_state(
         _Scheduler_SMP_Node_downcast( highest_ready ),
         SCHEDULER_SMP_NODE_BLOCKED
       );
 
       ( *extract_from_ready )( context, highest_ready );
+
+      continue;
     }
-  }
+  } while ( false );
 }
 
 /**
diff --git a/testsuites/smptests/smpmrsp01/init.c b/testsuites/smptests/smpmrsp01/init.c
index a1aae86..1f07904 100644
--- a/testsuites/smptests/smpmrsp01/init.c
+++ b/testsuites/smptests/smpmrsp01/init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2014-2015 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -74,7 +74,6 @@ typedef struct {
 } test_context;
 
 static test_context test_instance = {
-  .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
   .switch_lock = SMP_LOCK_INITIALIZER("test instance switch lock")
 };
 
@@ -87,6 +86,11 @@ static void busy_wait(void)
   }
 }
 
+static void barrier_init(test_context *ctx)
+{
+  _SMP_barrier_Control_initialize(&ctx->barrier);
+}
+
 static void barrier(test_context *ctx, SMP_barrier_State *bs)
 {
   _SMP_barrier_Wait(&ctx->barrier, bs, 2);
@@ -291,6 +295,7 @@ static void test_mrsp_obtain_and_release(test_context *ctx)
 
   change_prio(RTEMS_SELF, 3);
 
+  barrier_init(ctx);
   reset_switch_events(ctx);
 
   ctx->high_run[0] = false;
@@ -467,6 +472,219 @@ static void test_mrsp_obtain_and_release(test_context *ctx)
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 }
 
+static void obtain_after_migration_worker(rtems_task_argument arg)
+{
+  test_context *ctx = &test_instance;
+  rtems_status_code sc;
+  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
+
+  assert_prio(RTEMS_SELF, 3);
+
+  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  /* Worker done (K) */
+  barrier(ctx, &barrier_state);
+
+  while (true) {
+    /* Wait for termination */
+  }
+}
+
+static void obtain_after_migration_high(rtems_task_argument arg)
+{
+  test_context *ctx = &test_instance;
+  rtems_status_code sc;
+  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
+
+  assert_prio(RTEMS_SELF, 2);
+
+  sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  /* Obtain done (I) */
+  barrier(ctx, &barrier_state);
+
+  /* Ready to release (J) */
+  barrier(ctx, &barrier_state);
+
+  sc = rtems_semaphore_release(ctx->mrsp_ids[1]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_task_suspend(RTEMS_SELF);
+  rtems_test_assert(0);
+}
+
+static void test_mrsp_obtain_after_migration(test_context *ctx)
+{
+  rtems_status_code sc;
+  rtems_task_priority prio;
+  rtems_id scheduler_id;
+  SMP_barrier_State barrier_state;
+
+  puts("test MrsP obtain after migration");
+
+  change_prio(RTEMS_SELF, 3);
+
+  barrier_init(ctx);
+  reset_switch_events(ctx);
+
+  /* Create tasks */
+
+  sc = rtems_task_create(
+    rtems_build_name('H', 'I', 'G', '0'),
+    2,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &ctx->high_task_id[0]
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_create(
+    rtems_build_name('W', 'O', 'R', 'K'),
+    3,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &ctx->worker_ids[0]
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_set_scheduler(ctx->worker_ids[0], ctx->scheduler_ids[1]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  /* Create a MrsP semaphore objects */
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('M', 'R', 'S', 'P'),
+    1,
+    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
+      | RTEMS_BINARY_SEMAPHORE,
+    3,
+    &ctx->mrsp_ids[0]
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('M', 'R', 'S', 'P'),
+    1,
+    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
+      | RTEMS_BINARY_SEMAPHORE,
+    2,
+    &ctx->mrsp_ids[1]
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('M', 'R', 'S', 'P'),
+    1,
+    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
+      | RTEMS_BINARY_SEMAPHORE,
+    1,
+    &ctx->mrsp_ids[2]
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  prio = 4;
+  sc = rtems_semaphore_set_priority(
+    ctx->mrsp_ids[2],
+    ctx->scheduler_ids[1],
+    prio,
+    &prio
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  rtems_test_assert(prio == 1);
+
+  /* Check executing task parameters */
+
+  sc = rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(ctx->scheduler_ids[0] == scheduler_id);
+
+  assert_prio(RTEMS_SELF, 3);
+
+  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  assert_prio(RTEMS_SELF, 3);
+
+  /* Start other tasks */
+
+  sc = rtems_task_start(ctx->worker_ids[0], obtain_after_migration_worker, 0);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_start(ctx->high_task_id[0], obtain_after_migration_high, 0);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(rtems_get_current_processor() == 1);
+
+  /* Obtain done (I) */
+  _SMP_barrier_State_initialize(&barrier_state);
+  barrier(ctx, &barrier_state);
+
+  sc = rtems_task_suspend(ctx->high_task_id[0]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(rtems_get_current_processor() == 1);
+
+  /*
+   * Obtain second MrsP semaphore and ensure that we change the priority of our
+   * own scheduler node and not the one we are currently using.
+   */
+
+  sc = rtems_semaphore_obtain(ctx->mrsp_ids[2], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  assert_prio(RTEMS_SELF, 1);
+
+  rtems_test_assert(rtems_get_current_processor() == 1);
+
+  sc = rtems_semaphore_release(ctx->mrsp_ids[2]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_resume(ctx->high_task_id[0]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  /* Ready to release (J) */
+  barrier(ctx, &barrier_state);
+
+  rtems_test_assert(rtems_get_current_processor() == 1);
+
+  /* Prepare barrier for worker */
+  barrier_init(ctx);
+  _SMP_barrier_State_initialize(&barrier_state);
+
+  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(rtems_get_current_processor() == 0);
+
+  print_switch_events(ctx);
+
+  /* Worker done (K) */
+  barrier(ctx, &barrier_state);
+
+  sc = rtems_task_delete(ctx->worker_ids[0]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_delete(ctx->high_task_id[0]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_semaphore_delete(ctx->mrsp_ids[1]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_semaphore_delete(ctx->mrsp_ids[2]);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
 static void test_mrsp_flush_error(void)
 {
   rtems_status_code sc;
@@ -1034,6 +1252,7 @@ static void test_mrsp_various_block_and_unblock(test_context *ctx)
 
   change_prio(RTEMS_SELF, 4);
 
+  barrier_init(ctx);
   reset_switch_events(ctx);
 
   ctx->low_run[0] = false;
@@ -1637,6 +1856,7 @@ static void Init(rtems_task_argument arg)
   test_mrsp_deadlock_error(ctx);
   test_mrsp_multiple_obtain();
   test_mrsp_various_block_and_unblock(ctx);
+  test_mrsp_obtain_after_migration(ctx);
   test_mrsp_obtain_and_sleep_and_release(ctx);
   test_mrsp_obtain_and_release_with_help(ctx);
   test_mrsp_obtain_and_release(ctx);
diff --git a/testsuites/smptests/smpmrsp01/smpmrsp01.scn b/testsuites/smptests/smpmrsp01/smpmrsp01.scn
index 90184b5..19a4fbb 100644
--- a/testsuites/smptests/smpmrsp01/smpmrsp01.scn
+++ b/testsuites/smptests/smpmrsp01/smpmrsp01.scn
@@ -23,9 +23,17 @@ test MrsP various block and unblock
 [0] MAIN -> HIG0 (prio   2, node HIG0)
 [1] MAIN -> HIG1 (prio   2, node HIG1)
 [1] HIG1 -> MAIN (prio   3, node WORK)
-[0] HIG0 -> IDLE (prio   4, node MAIN)
-[1] MAIN -> WORK (prio   3, node WORK)
+[0] HIG0 -> IDLE (prio 255, node IDLE)
 [0] IDLE -> MAIN (prio   4, node MAIN)
+[1] MAIN -> WORK (prio   3, node WORK)
+test MrsP obtain after migration
+[1] IDLE -> WORK (prio   3, node WORK)
+[0] MAIN -> HIG0 (prio   2, node HIG0)
+[1] WORK -> MAIN (prio   3, node WORK)
+[0] HIG0 -> IDLE (prio   2, node HIG0)
+[0] IDLE -> HIG0 (prio   2, node HIG0)
+[1] MAIN -> WORK (prio   3, node WORK)
+[0] HIG0 -> MAIN (prio   3, node MAIN)
 test MrsP obtain and sleep and release
 [0] MAIN ->  RUN (prio   2, node  RUN)
 [0]  RUN -> MAIN (prio   1, node MAIN)
@@ -42,290 +50,290 @@ test MrsP obtain and release with help
 [0]  RUN -> IDLE (prio   2, node MAIN)
 [1] MAIN -> HELP (prio   2, node HELP)
 [1] HELP -> MAIN (prio   2, node HELP)
-[0] IDLE -> MAIN (prio   3, node MAIN)
+[0] IDLE -> MAIN (prio   1, node MAIN)
 [1] MAIN -> HELP (prio   2, node HELP)
 test MrsP obtain and release
 [1] IDLE -> WORK (prio   4, node WORK)
 [1] WORK -> MAIN (prio   3, node WORK)
 [0] MAIN -> HIG0 (prio   1, node HIG0)
-[1] MAIN -> WORK (prio   4, node WORK)
+[1] MAIN -> WORK (prio   3, node WORK)
 [0] HIG0 -> MAIN (prio   2, node MAIN)
 test MrsP load
 worker[0]
-  sleep = 53
-  timeout = 3445
-  obtain[0] = 7240
-  obtain[1] = 5484
-  obtain[2] = 12983
-  obtain[3] = 9453
-  obtain[4] = 16142
-  obtain[5] = 12509
-  obtain[6] = 16471
-  obtain[7] = 14380
-  obtain[8] = 16566
-  obtain[9] = 16192
-  obtain[10] = 14868
-  obtain[11] = 18208
-  obtain[12] = 12505
-  obtain[13] = 19995
-  obtain[14] = 11155
-  obtain[15] = 20684
-  obtain[16] = 7288
-  obtain[17] = 22252
-  obtain[18] = 6476
-  obtain[19] = 18299
-  obtain[20] = 5711
-  obtain[21] = 17063
-  obtain[22] = 4791
-  obtain[23] = 14655
-  obtain[24] = 3452
-  obtain[25] = 10565
-  obtain[26] = 2912
-  obtain[27] = 8142
-  obtain[28] = 2090
-  obtain[29] = 5086
-  obtain[30] = 1145
-  obtain[31] = 1946
-  cpu[0] = 378475
-  cpu[1] = 64814
-  cpu[2] = 132133
-  cpu[3] = 138047
+  sleep = 7
+  timeout = 1780
+  obtain[0] = 607
+  obtain[1] = 443
+  obtain[2] = 988
+  obtain[3] = 659
+  obtain[4] = 1169
+  obtain[5] = 846
+  obtain[6] = 1267
+  obtain[7] = 854
+  obtain[8] = 1016
+  obtain[9] = 1079
+  obtain[10] = 1165
+  obtain[11] = 1020
+  obtai[12] = 767
+  obtain[13] = 925
+  obtain[14] = 792
+  obtain[15] = 881
+  obtain[16] = 439
+  obtain[17] = 1007
+  obtain[18] = 243
+  obtain[19] = 853
+  obtain[20] = 210
+  obtain[21] = 445
+  obtain[22] = 247
+  obtain[23] = 497
+  obtain[24] = 102
+  obtain[25] = 580
+  obtain[26] = 90
+  obtain[27] = 186
+  obtain[28] = 74
+  obtain[29] = 139
+  obtain[30] = 68
+  obtain[31] = 98
+  cpu[0] = 27776
+  cpu[1] = 2795
+  cpu[2] = 4397
+  cpu[3] = 4551
 worker[1]
   sleep = 1
-  timeout = 6
-  obtain[0] = 19
-  obtain[1] = 8
-  obtain[2] = 15
-  obtain[3] = 24
-  obtain[4] = 20
-  obtain[5] = 19
-  obtain[6] = 14
-  obtain[7] = 40
-  obtain[8] = 45
-  obtain[9] = 20
+  timeout = 0
+  obtain[0] = 1
+  obtain[1] = 0
+  obtain[2] = 3
+  obtain[3] = 0
+  obtain[4] = 0
+  obtain[5] = 0
+  obtain[6] = 0
+  obtain[7] = 0
+  obtain[8] = 0
+  obtain[9] = 0
   obtain[10] = 0
-  obtain[11] = 48
-  obtain[12] = 13
-  obtain[13] = 57
-  obtain[14] = 30
-  obtain[15] = 48
-  obtain[16] = 36
-  obtain[17] = 36
-  obtain[18] = 19
-  obtain[19] = 20
-  obtain[20] = 42
-  obtain[21] = 44
-  obtain[22] = 23
+  obtain[11] = 0
+  obtain[12] = 0
+  obtain[13] = 0
+  obtain[14] = 0
+  obtain[15] = 0
+  obtain[16] = 0
+  obtain[17] = 0
+  obtain[18] = 0
+  obtain[19] = 0
+  obtain[20] = 0
+  obtain[21] = 0
+  obtain[22] = 0
   obtain[23] = 0
   obtain[24] = 0
-  obtain[25] = 26
+  obtain[25] = 0
   obtain[26] = 0
   obtain[27] = 0
   obtain[28] = 0
   obtain[29] = 0
   obtain[30] = 0
   obtain[31] = 0
-  cpu[0] = 650
-  cpu[1] = 92
-  cpu[2] = 379
-  cpu[3] = 212
+  cpu[0] = 9
+  cpu[1] = 0
+  cpu[2] = 0
+  cpu[3] = 0
 worker[2]
-  sleep = 51
-  timeout = 3731
-  obtain[0] = 7182
-  obtain[1] = 5663
-  obtain[2] = 12945
-  obtain[3] = 9229
-  obtain[4] = 15592
-  obtain[5] = 12125
-  obtain[6] = 16767
-  obtain[7] = 14480
-  obtain[8] = 16620
-  obtain[9] = 16098
-  obtain[10] = 16409
-  obtain[11] = 18109
-  obtain[12] = 12995
-  obtain[13] = 19452
-  obtain[14] = 10719
-  obtain[15] = 20024
-  obtain[16] = 7769
-  obtain[17] = 21913
-  obtain[18] = 6636
-  obtain[19] = 18524
-  obtain[20] = 5952
-  obtain[21] = 16411
-  obtain[22] = 5228
-  obtain[23] = 14456
-  obtain[24] = 4292
-  obtain[25] = 11143
-  obtain[26] = 3019
-  obtain[27] = 8023
-  obtain[28] = 2006
-  obtain[29] = 4664
-  obtain[30] = 1109
-  obtain[31] = 1976
-  cpu[0] = 65356
-  cpu[1] = 381723
-  cpu[2] = 133444
-  cpu[3] = 134588
+  sleep = 5
+  timeout = 2083
+  obtain[0] = 740
+  obtain[1] = 489
+  obtain[2] = 1232
+  obtain[3] = 732
+  obtain[4] = 1361
+  obtain[5] = 1070
+  obtain[6] = 1334
+  obtain[7] = 997
+  obtain[8] = 1418
+  obtain[9] = 1087
+  obtain[10] = 1005
+  obtain[11] = 1088
+  obtain[12] = 865
+  obtain[13] = 1279
+  obtain[14] = 698
+  obtain[15] = 1152
+  obtain[16] = 339
+  obtain[17] = 1347
+  obtain[18] = 340
+  obtain[19] = 723
+  obtain[20] = 295
+  obtain[21] = 933
+  obtain[22] = 223
+  obtain[23] = 633
+  obtain[24] = 236
+  obtain[25] = 405
+  obtain[26] = 140
+  obtain[27] = 261
+  obtain[28] = 70
+  obtain[29] = 157
+  obtain[30] = 89
+  obtain[31] = 71
+  cpu[0] = 1931
+  cpu[1] = 35336
+  cpu[2] = 4338
+  cpu[3] = 4018
 worker[3]
   sleep = 1
-  timeout = 11
-  obtain[0] = 11
-  obtain[1] = 6
-  obtain[2] = 33
-  obtain[3] = 20
-  obtain[4] = 10
-  obtain[5] = 10
-  obtain[6] = 28
-  obtain[7] = 18
-  obtain[8] = 27
-  obtain[9] = 40
-  obtain[10] = 33
-  obtain[11] = 36
-  obtain[12] = 26
+  timeout = 1
+  obtain[0] = 0
+  obtain[1] = 0
+  obtain[2] = 3
+  obtain[3] = 0
+  obtain[4] = 5
+  obtain[5] = 0
+  obtain[6] = 0
+  obtain[7] = 0
+  obtain[8] = 0
+  obtain[9] = 0
+  obtain[10] = 0
+  obtain[11] = 0
+  obtain[12] = 0
   obtain[13] = 0
-  obtain[14] = 15
-  obtain[15] = 16
+  obtain[14] = 0
+  obtain[15] = 0
   obtain[16] = 0
-  obtain[17] = 18
+  obtain[17] = 0
   obtain[18] = 0
-  obtain[19] = 42
+  obtain[19] = 0
   obtain[20] = 0
-  obtain[21] = 88
+  obtain[21] = 0
   obtain[22] = 0
-  obtain[23] = 24
+  obtain[23] = 0
   obtain[24] = 0
   obtain[25] = 0
   obtain[26] = 0
-  obtain[27] = 28
+  obtain[27] = 0
   obtain[28] = 0
   obtain[29] = 0
-  obtain[30] = 31
+  obtain[30] = 0
   obtain[31] = 0
-  cpu[0] = 136
-  cpu[1] = 573
-  cpu[2] = 291
-  cpu[3] = 121
+  cpu[0] = 0
+  cpu[1] = 14
+  cpu[2] = 0
+  cpu[3] = 3
 worker[4]
-  sleep = 47
-  timeout = 3278
-  obtain[0] = 7397
-  obtain[1] = 5723
-  obtain[2] = 13399
-  obtain[3] = 9018
-  obtain[4] = 16575
-  obtain[5] = 12731
-  obtain[6] = 16571
-  obtain[7] = 14376
-  obtain[8] = 16786
-  obtain[9] = 17022
-  obtain[10] = 15889
-  obtain[11] = 19338
-  obtain[12] = 13240
-  obtain[13] = 19055
-  obtain[14] = 11533
-  obtain[15] = 22667
-  obtain[16] = 7521
-  obtain[17] = 21826
-  obtain[18] = 6320
-  obtain[19] = 18522
-  obtain[20] = 6874
-  obtain[21] = 16498
-  obtain[22] = 4983
-  obtain[23] = 14210
-  obtain[24] = 4019
-  obtain[25] = 11510
-  obtain[26] = 3425
-  obtain[27] = 8809
-  obtain[28] = 2002
-  obtain[29] = 5197
-  obtain[30] = 996
-  obtain[31] = 2276
-  cpu[0] = 20729
-  cpu[1] = 19760
-  cpu[2] = 343613
-  cpu[3] = 348561
+  sleep = 9
+  timeout = 2196
+  obtain[0] = 896
+  obtain[1] = 565
+  obtain[2] = 1443
+  obtain[3] = 936
+  obtain[4] = 1506
+  obtain[5] = 1028
+  obtain[6] = 1541
+  obtain[7] = 1088
+  obtain[8] = 1683
+  obtain[9] = 1494
+  obtain[10] = 1283
+  obtain[11] = 1075
+  obtain[12] = 1101
+  obtain[13] = 1038
+  obtain[14] = 758
+  obtain[15] = 1300
+  obtain[16] = 350
+  obtain[17] = 1180
+  obtain[18] = 396
+  obtain[19] = 1171
+  obtain[20] = 232
+  obtain[21] = 767
+  obtain[22] = 336
+  obtain[23] = 470
+  obtain[24] = 196
+  obtain[25] = 461
+  obtain[26] = 148
+  obtain[27] = 394
+  obtain[28] = 68
+  obtain[29] = 259
+  obtain[30] = 80
+  obtain[31] = 54
+  cpu[0] = 725
+  cpu[1] = 1001
+  cpu[2] = 25845
+  cpu[3] = 23032
 worker[5]
-  sleep = 61
-  timeout = 3183
-  obtain[0] = 7291
-  obtain[1] = 5782
-  obtain[2] = 13633
-  obtain[3] = 9864
-  obtain[4] = 16465
-  obtain[5] = 12581
-  obtain[6] = 17135
-  obtain[7] = 14616
-  obtain[8] = 16524
-  obtain[9] = 16472
-  obtain[10] = 15194
-  obtain[11] = 18038
-  obtain[12] = 13801
-  obtain[13] = 19959
-  obtain[14] = 11693
-  obtain[15] = 20770
-  obtain[16] = 7328
-  obtain[17] = 23222
-  obtain[18] = 7186
-  obtain[19] = 19739
-  obtain[20] = 6584
-  obtain[21] = 17450
-  obtain[22] = 5241
-  obtain[23] = 14808
-  obtain[24] = 4287
-  obtain[25] = 11387
-  obtain[26] = 3367
-  obtain[27] = 8149
-  obtain[28] = 1887
-  obtain[29] = 4969
-  obtain[30] = 1123
-  obtain[31] = 1695
-  cpu[0] = 19504
-  cpu[1] = 20069
-  cpu[2] = 346015
-  cpu[3] = 350953
+  sleep = 8
+  timeout = 2062
+  obtain[0] = 754
+  obtain[1] = 540
+  obtain[2] = 1318
+  obtain[3] = 886
+  obtain[4] = 1396
+  obtain[5] = 1030
+  obtain[6] = 1556
+  obtain[7] = 1126
+  obtain[8] = 1338
+  obtain[9] = 1061
+  obtain[10] = 1173
+  obtain[11] = 1396
+  obtain[12] = 1130
+  obtain[13] = 1189
+  obtain[14] = 867
+  obtain[15] = 1290
+  obtain[16] = 339
+  obtain[17] = 1177
+  obtain[18] = 396
+  obtain[19] = 915
+  obtain[20] = 236
+  obtain[21] = 1084
+  obtain[22] = 146
+  obtain[23] = 699
+  obtain[24] = 185
+  obtain[25] = 562
+  obtain[26] = 120
+  obtain[27] = 423
+  obtain[28] = 153
+  obtain[29] = 347
+  obtain[30] = 28
+  obtain[31] = 250
+  cpu[0] = 911
+  cpu[1] = 1018
+  cpu[2] = 23145
+  cpu[3] = 25154
 worker[6]
   sleep = 1
-  timeout = 15
-  obtain[0] = 26
-  obtain[1] = 22
-  obtain[2] = 45
-  obtain[3] = 32
-  obtain[4] = 45
-  obtain[5] = 76
-  obtain[6] = 49
-  obtain[7] = 64
-  obtain[8] = 99
-  obtain[9] = 70
-  obtain[10] = 55
-  obtain[11] = 48
-  obtain[12] = 39
-  obtain[13] = 28
-  obtain[14] = 60
-  obtain[15] = 48
-  obtain[16] = 17
-  obtain[17] = 74
-  obtain[18] = 38
-  obtain[19] = 60
-  obtain[20] = 63
-  obtain[21] = 66
-  obtain[22] = 23
-  obtain[23] = 48
+  timeout = 3
+  obtain[0] = 3
+  obtain[1] = 0
+  obtain[2] = 3
+  obtain[3] = 0
+  obtain[4] = 0
+  obtain[5] = 6
+  obtain[6] = 0
+  obtain[7] = 8
+  obtain[8] = 3
+  obtain[9] = 0
+  obtain[10] = 0
+  obtain[11] = 0
+  obtain[12] = 13
+  obtain[13] = 0
+  obtain[14] = 0
+  obtain[15] = 0
+  obtain[16] = 2
+  obtain[17] = 0
+  obtain[18] = 0
+  obtain[19] = 0
+  obtain[20] = 0
+  obtain[21] = 0
+  obtain[22] = 0
+  obtain[23] = 0
   obtain[24] = 0
-  obtain[25] = 78
+  obtain[25] = 0
   obtain[26] = 0
-  obtain[27] = 43
+  obtain[27] = 0
   obtain[28] = 0
   obtain[29] = 0
   obtain[30] = 0
-  obtain[31] = 32
-  cpu[0] = 71
-  cpu[1] = 39
-  cpu[2] = 1333
-  cpu[3] = 1254
+  obtain[31] = 0
+  cpu[0] = 0
+  cpu[1] = 11
+  cpu[2] = 42
+  cpu[3] = 24
 worker[7]
-  sleep = 1
+  sleep = 0
   timeout = 0
   obtain[0] = 0
   obtain[1] = 0
@@ -361,10 +369,10 @@ worker[7]
   obtain[31] = 0
   cpu[0] = 0
   cpu[1] = 0
-  cpu[2] = 1
+  cpu[2] = 0
   cpu[3] = 0
-migrations[0] = 437361
-migrations[1] = 437363
-migrations[2] = 441234
-migrations[3] = 433487
+migrations[0] = 20731
+migrations[1] = 20731
+migrations[2] = 20366
+migrations[3] = 21099
 *** END OF TEST SMPMRSP 1 ***



More information about the vc mailing list