[PATCH] score: Remove PRIORITY_PSEUDO_ISR thread priority

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Jul 15 08:43:54 UTC 2022


The uniprocessor schedulers had some special case logic for the
PRIORITY_PSEUDO_ISR priority.  Tasks with a priority of PRIORITY_PSEUDO_ISR
were allowed to preempt a not preemptible task.  If other higher priority task
are made ready while a PRIORITY_PSEUDO_ISR task preempts a not preemptible
task, then the other tasks run before the not preemptible task.  This made the
RTEMS_NO_PREEMPT mode ineffective.

Remove the PRIORITY_PSEUDO_ISR special case logic.  This simplifies the
uniprocessor schedulers.  Move the uniprocessor-specific scheduler support to
the new header file <rtems/score/scheduleruniimpl.h>.

Close #2365.
---
 cpukit/include/rtems/posix/priorityimpl.h     |   2 +-
 cpukit/include/rtems/score/priority.h         |   7 -
 cpukit/include/rtems/score/scheduleredfimpl.h |  19 +-
 cpukit/include/rtems/score/schedulerimpl.h    |  65 ------
 .../rtems/score/schedulerpriorityimpl.h       |  30 +--
 .../include/rtems/score/schedulersimpleimpl.h |  22 +-
 cpukit/include/rtems/score/scheduleruniimpl.h | 221 ++++++++++++++++++
 cpukit/rtems/src/timerserver.c                |   2 +-
 cpukit/score/src/mpci.c                       |   2 +-
 cpukit/score/src/scheduleredfblock.c          |   4 +-
 cpukit/score/src/scheduleredfchangepriority.c |   5 +-
 cpukit/score/src/scheduleredfschedule.c       |   5 +-
 cpukit/score/src/scheduleredfunblock.c        |  20 +-
 cpukit/score/src/scheduleredfyield.c          |   2 +-
 cpukit/score/src/schedulerpriorityblock.c     |   4 +-
 .../src/schedulerprioritychangepriority.c     |   5 +-
 cpukit/score/src/schedulerpriorityschedule.c  |   5 +-
 cpukit/score/src/schedulerpriorityunblock.c   |  16 +-
 cpukit/score/src/schedulerpriorityyield.c     |   5 +-
 cpukit/score/src/schedulersimpleblock.c       |   4 +-
 .../score/src/schedulersimplechangepriority.c |   5 +-
 cpukit/score/src/schedulersimpleschedule.c    |   5 +-
 cpukit/score/src/schedulersimpleunblock.c     |  20 +-
 cpukit/score/src/schedulersimpleyield.c       |   5 +-
 spec/build/cpukit/librtemscpu.yml             |   1 +
 testsuites/sptests/sptasknopreempt01/init.c   |  18 +-
 26 files changed, 295 insertions(+), 204 deletions(-)
 create mode 100644 cpukit/include/rtems/score/scheduleruniimpl.h

diff --git a/cpukit/include/rtems/posix/priorityimpl.h b/cpukit/include/rtems/posix/priorityimpl.h
index e391448372..ce26787294 100644
--- a/cpukit/include/rtems/posix/priorityimpl.h
+++ b/cpukit/include/rtems/posix/priorityimpl.h
@@ -84,7 +84,7 @@ RTEMS_INLINE_ROUTINE int _POSIX_Priority_Get_maximum(
  * Thus, SuperCore has priorities run in the opposite sense of the POSIX API.
  *
  * Let N be the maximum priority of this scheduler instance.   The SuperCore
- * priority zero is system reserved (PRIORITY_PSEUDO_ISR).  There are only
+ * priority zero is system reserved (PRIORITY_MINIMUM).  There are only
  * N - 1 POSIX API priority levels since a thread at SuperCore priority N would
  * never run because of the idle threads.  This is necessary because GNAT maps
  * the lowest Ada task priority to the lowest thread priority.  The lowest
diff --git a/cpukit/include/rtems/score/priority.h b/cpukit/include/rtems/score/priority.h
index 568e3c4e3e..6f6cc12bac 100644
--- a/cpukit/include/rtems/score/priority.h
+++ b/cpukit/include/rtems/score/priority.h
@@ -95,13 +95,6 @@ typedef uint64_t Priority_Control;
  */
 #define PRIORITY_MINIMUM      0
 
-/**
- * @brief The priority value of pseudo-ISR threads.
- *
- * Examples are the MPCI and timer server threads.
- */
-#define PRIORITY_PSEUDO_ISR   PRIORITY_MINIMUM
-
 /**
  * @brief The default lowest (least important) thread priority value.
  *
diff --git a/cpukit/include/rtems/score/scheduleredfimpl.h b/cpukit/include/rtems/score/scheduleredfimpl.h
index e0a07a8915..06a35ae95f 100644
--- a/cpukit/include/rtems/score/scheduleredfimpl.h
+++ b/cpukit/include/rtems/score/scheduleredfimpl.h
@@ -39,7 +39,7 @@
 #define _RTEMS_SCORE_SCHEDULEREDFIMPL_H
 
 #include <rtems/score/scheduleredf.h>
-#include <rtems/score/schedulerimpl.h>
+#include <rtems/score/scheduleruniimpl.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -216,30 +216,23 @@ RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Extract_body(
 }
 
 /**
- * @brief Schedules the next ready thread as the heir.
+ * @brief Gets the highest priority ready thread of the scheduler.
  *
- * @param scheduler The scheduler instance to schedule the minimum of the context of.
- * @param the_thread This parameter is not used.
- * @param force_dispatch Indicates whether the current heir is blocked even if it is
- *      not set as preemptible.
+ * @param scheduler is the scheduler.
  */
-RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body(
-  const Scheduler_Control *scheduler,
-  Thread_Control          *the_thread,
-  bool                     force_dispatch
+RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_EDF_Get_highest_ready(
+  const Scheduler_Control *scheduler
 )
 {
   Scheduler_EDF_Context *context;
   RBTree_Node           *first;
   Scheduler_EDF_Node    *node;
 
-  (void) the_thread;
-
   context = _Scheduler_EDF_Get_context( scheduler );
   first = _RBTree_Minimum( &context->Ready );
   node = RTEMS_CONTAINER_OF( first, Scheduler_EDF_Node, Node );
 
-  _Scheduler_Update_heir( node->Base.owner, force_dispatch );
+  return node->Base.owner;
 }
 
 /** @} */
diff --git a/cpukit/include/rtems/score/schedulerimpl.h b/cpukit/include/rtems/score/schedulerimpl.h
index 806cb4e145..33070651db 100644
--- a/cpukit/include/rtems/score/schedulerimpl.h
+++ b/cpukit/include/rtems/score/schedulerimpl.h
@@ -668,40 +668,6 @@ Status_Control _Scheduler_Set_affinity(
   const cpu_set_t *cpuset
 );
 
-/**
- * @brief Blocks the thread.
- *
- * @param scheduler The scheduler instance.
- * @param the_thread The thread to block.
- * @param node The corresponding scheduler node.
- * @param extract Method to extract the thread.
- * @param schedule Method for scheduling threads.
- */
-RTEMS_INLINE_ROUTINE void _Scheduler_Generic_block(
-  const Scheduler_Control *scheduler,
-  Thread_Control          *the_thread,
-  Scheduler_Node          *node,
-  void                  ( *extract )(
-                             const Scheduler_Control *,
-                             Thread_Control *,
-                             Scheduler_Node *
-                        ),
-  void                  ( *schedule )(
-                             const Scheduler_Control *,
-                             Thread_Control *,
-                             bool
-                        )
-)
-{
-  ( *extract )( scheduler, the_thread, node );
-
-  /* TODO: flash critical section? */
-
-  if ( _Thread_Is_heir( the_thread ) ) {
-    ( *schedule )( scheduler, the_thread, true );
-  }
-}
-
 /**
  * @brief Gets the number of processors of the scheduler.
  *
@@ -951,37 +917,6 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Discard_idle_thread(
 }
 #endif
 
-/**
- * @brief Updates the heir.
- *
- * @param[in, out] new_heir The new heir.
- * @param force_dispatch Indicates whether the dispatch happens also if the
- *      currently running thread is set as not preemptible.
- */
-RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir(
-  Thread_Control *new_heir,
-  bool            force_dispatch
-)
-{
-  Thread_Control *heir = _Thread_Heir;
-
-  if ( heir != new_heir && ( heir->is_preemptible || force_dispatch ) ) {
-#if defined(RTEMS_SMP)
-    /*
-     * We need this state only for _Thread_Get_CPU_time_used_locked().  Cannot
-     * use _Scheduler_Thread_change_state() since THREAD_SCHEDULER_BLOCKED to
-     * THREAD_SCHEDULER_BLOCKED state changes are illegal for the real SMP
-     * schedulers.
-     */
-    heir->Scheduler.state = THREAD_SCHEDULER_BLOCKED;
-    new_heir->Scheduler.state = THREAD_SCHEDULER_SCHEDULED;
-#endif
-    _Thread_Update_CPU_time_used( heir, _Thread_Get_CPU( heir ) );
-    _Thread_Heir = new_heir;
-    _Thread_Dispatch_necessary = true;
-  }
-}
-
 /**
  * @brief Sets a new scheduler.
  *
diff --git a/cpukit/include/rtems/score/schedulerpriorityimpl.h b/cpukit/include/rtems/score/schedulerpriorityimpl.h
index d8d226d6f1..06d2027a45 100644
--- a/cpukit/include/rtems/score/schedulerpriorityimpl.h
+++ b/cpukit/include/rtems/score/schedulerpriorityimpl.h
@@ -41,7 +41,7 @@
 #include <rtems/score/schedulerpriority.h>
 #include <rtems/score/chainimpl.h>
 #include <rtems/score/prioritybitmapimpl.h>
-#include <rtems/score/schedulerimpl.h>
+#include <rtems/score/scheduleruniimpl.h>
 #include <rtems/score/thread.h>
 
 #ifdef __cplusplus
@@ -231,33 +231,21 @@ RTEMS_INLINE_ROUTINE Chain_Node *_Scheduler_priority_Ready_queue_first(
 }
 
 /**
- * @brief Scheduling decision logic.
+ * @brief Gets the highest priority ready thread of the scheduler.
  *
- * This kernel routine implements scheduling decision logic
- * for priority-based scheduling.
- *
- * @param[in, out] scheduler The scheduler instance.
- * @param the_thread This parameter is unused.
- * @param force_dispatch Indicates whether the dispatch happens also if
- *      the currently executing thread is set as not preemptible.
+ * @param scheduler is the scheduler.
  */
-RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body(
-  const Scheduler_Control *scheduler,
-  Thread_Control          *the_thread,
-  bool                     force_dispatch
+RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_priority_Get_highest_ready(
+  const Scheduler_Control *scheduler
 )
 {
   Scheduler_priority_Context *context =
     _Scheduler_priority_Get_context( scheduler );
-  Thread_Control *heir = (Thread_Control *)
-    _Scheduler_priority_Ready_queue_first(
-      &context->Bit_map,
-      &context->Ready[ 0 ]
-    );
 
-  ( void ) the_thread;
-
-  _Scheduler_Update_heir( heir, force_dispatch );
+  return (Thread_Control *) _Scheduler_priority_Ready_queue_first(
+    &context->Bit_map,
+    &context->Ready[ 0 ]
+  );
 }
 
 /**
diff --git a/cpukit/include/rtems/score/schedulersimpleimpl.h b/cpukit/include/rtems/score/schedulersimpleimpl.h
index 2aaf0fe17e..2293433870 100644
--- a/cpukit/include/rtems/score/schedulersimpleimpl.h
+++ b/cpukit/include/rtems/score/schedulersimpleimpl.h
@@ -39,7 +39,7 @@
 
 #include <rtems/score/schedulersimple.h>
 #include <rtems/score/chainimpl.h>
-#include <rtems/score/schedulerimpl.h>
+#include <rtems/score/scheduleruniimpl.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -133,28 +133,18 @@ RTEMS_INLINE_ROUTINE void _Scheduler_simple_Extract(
 }
 
 /**
- * @brief Scheduling decision logic.
+ * @brief Gets the highest priority ready thread of the scheduler.
  *
- * This kernel routine implements scheduling decision logic for the simple scheduler.
- *
- * @param[in, out] scheduler The scheduler instance.
- * @param the_thread This parameter is unused.
- * @param force_dispatch Indicates whether the dispatch happens also if
- *      the currently executing thread is set as not preemptible.
+ * @param scheduler is the scheduler.
  */
-RTEMS_INLINE_ROUTINE void _Scheduler_simple_Schedule_body(
-  const Scheduler_Control *scheduler,
-  Thread_Control          *the_thread,
-  bool                     force_dispatch
+RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_simple_Get_highest_ready(
+  const Scheduler_Control *scheduler
 )
 {
   Scheduler_simple_Context *context =
     _Scheduler_simple_Get_context( scheduler );
-  Thread_Control *heir = (Thread_Control *) _Chain_First( &context->Ready );
-
-  ( void ) the_thread;
 
-  _Scheduler_Update_heir( heir, force_dispatch );
+  return (Thread_Control *) _Chain_First( &context->Ready );
 }
 
 /** @} */
diff --git a/cpukit/include/rtems/score/scheduleruniimpl.h b/cpukit/include/rtems/score/scheduleruniimpl.h
new file mode 100644
index 0000000000..faa719ce45
--- /dev/null
+++ b/cpukit/include/rtems/score/scheduleruniimpl.h
@@ -0,0 +1,221 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreScheduler
+ *
+ * @brief This header file provides interfaces of the supporting the
+ *   implementation of uniprocessor schedulers.
+ */
+
+/*
+ *  Copyright (C) 2010 Gedare Bloom.
+ *  Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *  Copyright (C) 2014, 2022 embedded brains GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTEMS_SCORE_SCHEDULERUNIIMPL_H
+#define _RTEMS_SCORE_SCHEDULERUNIIMPL_H
+
+#include <rtems/score/schedulerimpl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup RTEMSScoreScheduler
+ *
+ * @{
+ */
+
+/**
+ * @brief Updates the heir thread of the processor.
+ *
+ * @param[in, out] heir is the current heir thread.
+ * @param[in, out] new_heir is the new heir thread.
+ */
+RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Update_heir(
+  Thread_Control *heir,
+  Thread_Control *new_heir
+)
+{
+  _Assert( heir != new_heir );
+#if defined(RTEMS_SMP)
+  /*
+   * We need this state only for _Thread_Get_CPU_time_used_locked().  Cannot
+   * use _Scheduler_Thread_change_state() since THREAD_SCHEDULER_BLOCKED to
+   * THREAD_SCHEDULER_BLOCKED state changes are illegal for the real SMP
+   * schedulers.
+   */
+  heir->Scheduler.state = THREAD_SCHEDULER_BLOCKED;
+  new_heir->Scheduler.state = THREAD_SCHEDULER_SCHEDULED;
+#endif
+  _Thread_Update_CPU_time_used( heir, _Thread_Get_CPU( heir ) );
+  _Thread_Heir = new_heir;
+  _Thread_Dispatch_necessary = true;
+}
+
+/**
+ * @brief Updates the heir thread of the processor if the current heir is
+ *   not equal to the new heir thread.
+ *
+ * The update takes place even if the current heir thread is not preemptible.
+ *
+ * @param[in, out] new_heir is the new heir thread.
+ */
+RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Update_heir_if_necessary(
+  Thread_Control *new_heir
+)
+{
+  Thread_Control *heir = _Thread_Heir;
+
+  if ( heir != new_heir ) {
+    _Scheduler_uniprocessor_Update_heir( heir, new_heir );
+  }
+}
+
+/**
+ * @brief Updates the heir thread of the processor if the current heir thread
+ *   is preemptible.
+ *
+ * @param[in, out] heir is the current heir thread.
+ * @param[in, out] new_heir is the new heir thread.
+ */
+RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Update_heir_if_preemptible(
+  Thread_Control *heir,
+  Thread_Control *new_heir
+)
+{
+  if ( heir != new_heir && heir->is_preemptible ) {
+    _Scheduler_uniprocessor_Update_heir( heir, new_heir );
+  }
+}
+
+/**
+ * @brief Blocks the thread.
+ *
+ * @param scheduler is the scheduler.
+ * @param the_thread is the thread to block.
+ * @param node is the scheduler node of the thread.
+ * @param extract is the handler to extract the thread.
+ * @param get_highest_ready is the handler to get the highest ready thread.
+ */
+RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Block(
+  const Scheduler_Control *scheduler,
+  Thread_Control          *the_thread,
+  Scheduler_Node          *node,
+  void                  ( *extract )(
+                             const Scheduler_Control *,
+                             Thread_Control *,
+                             Scheduler_Node *
+                        ),
+  Thread_Control       *( *get_highest_ready )( const Scheduler_Control * )
+)
+{
+  ( *extract )( scheduler, the_thread, node );
+
+  /* TODO: flash critical section? */
+
+  if ( _Thread_Is_heir( the_thread ) ) {
+    Thread_Control *highest_ready;
+
+    highest_ready = ( *get_highest_ready )( scheduler );
+    _Scheduler_uniprocessor_Update_heir( _Thread_Heir, highest_ready );
+  }
+}
+
+/**
+ * @brief Schedule the unblocked thread if it is the highest ready thread.
+ *
+ * @param scheduler is the scheduler.
+ * @param the_thread is the thread.
+ * @param priority is the priority of the thread.
+ */
+RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Unblock(
+  const Scheduler_Control *scheduler,
+  Thread_Control          *the_thread,
+  Priority_Control         priority
+)
+{
+  Thread_Control *heir;
+
+  heir = _Thread_Heir;
+
+  /*
+   * If the thread is more important than the heir, then we have a new heir.
+   * This may or may not result in a context switch.  If the current heir
+   * thread is preemptible, then we need to do a context switch.
+   */
+  if ( priority < _Thread_Get_priority( heir ) ) {
+    _Scheduler_uniprocessor_Update_heir_if_preemptible( heir, the_thread );
+  }
+}
+
+/**
+ * @brief Schedules the highest ready thread if the current heir thread of the
+ * processor is preemptible.
+ *
+ * @param scheduler is the scheduler.
+ * @param get_highest_ready is the handler to get the highest ready thread.
+ */
+RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Schedule(
+  const Scheduler_Control *scheduler,
+  Thread_Control       *( *get_highest_ready )( const Scheduler_Control * )
+)
+{
+  Thread_Control *highest_ready;
+
+  highest_ready = ( *get_highest_ready )( scheduler );
+  _Scheduler_uniprocessor_Update_heir_if_preemptible(
+    _Thread_Heir,
+    highest_ready
+  );
+}
+
+/**
+ * @brief Yields to the highest ready thread.
+ *
+ * @param scheduler is the scheduler.
+ * @param get_highest_ready is the handler to get the highest ready thread.
+ */
+RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Yield(
+  const Scheduler_Control *scheduler,
+  Thread_Control       *( *get_highest_ready )( const Scheduler_Control * )
+)
+{
+  Thread_Control *highest_ready;
+
+  highest_ready = ( *get_highest_ready )( scheduler );
+  _Scheduler_uniprocessor_Update_heir_if_necessary( highest_ready );
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTEMS_SCORE_SCHEDULERUNIIMPL_H */
diff --git a/cpukit/rtems/src/timerserver.c b/cpukit/rtems/src/timerserver.c
index 5d863bd79c..e5242c82a5 100644
--- a/cpukit/rtems/src/timerserver.c
+++ b/cpukit/rtems/src/timerserver.c
@@ -173,7 +173,7 @@ static rtems_status_code _Timer_server_Initiate(
   }
 
   if ( priority == RTEMS_TIMER_SERVER_DEFAULT_PRIORITY ) {
-    priority = PRIORITY_PSEUDO_ISR;
+    priority = PRIORITY_MINIMUM;
   }
 
   /*
diff --git a/cpukit/score/src/mpci.c b/cpukit/score/src/mpci.c
index 3b525a2066..458031c794 100644
--- a/cpukit/score/src/mpci.c
+++ b/cpukit/score/src/mpci.c
@@ -162,7 +162,7 @@ static void _MPCI_Create_server( void )
   memset( &config, 0, sizeof( config ) );
   config.scheduler = &_Scheduler_Table[ 0 ];
   config.name = _Objects_Build_name( 'M', 'P', 'C', 'I' );
-  config.priority = PRIORITY_PSEUDO_ISR;
+  config.priority = PRIORITY_MINIMUM;
   config.is_fp = CPU_ALL_TASKS_ARE_FP;
   config.stack_size = _Stack_Minimum()
     + _MPCI_Configuration.extra_mpci_receive_server_stack
diff --git a/cpukit/score/src/scheduleredfblock.c b/cpukit/score/src/scheduleredfblock.c
index 56f7c9c021..cb7ab91450 100644
--- a/cpukit/score/src/scheduleredfblock.c
+++ b/cpukit/score/src/scheduleredfblock.c
@@ -47,11 +47,11 @@ void _Scheduler_EDF_Block(
   Scheduler_Node          *node
 )
 {
-  _Scheduler_Generic_block(
+  _Scheduler_uniprocessor_Block(
     scheduler,
     the_thread,
     node,
     _Scheduler_EDF_Extract_body,
-    _Scheduler_EDF_Schedule_body
+    _Scheduler_EDF_Get_highest_ready
   );
 }
diff --git a/cpukit/score/src/scheduleredfchangepriority.c b/cpukit/score/src/scheduleredfchangepriority.c
index 26ce1c348f..de17ca0fad 100644
--- a/cpukit/score/src/scheduleredfchangepriority.c
+++ b/cpukit/score/src/scheduleredfchangepriority.c
@@ -71,5 +71,8 @@ void _Scheduler_EDF_Update_priority(
 
   _Scheduler_EDF_Extract( context, the_node );
   _Scheduler_EDF_Enqueue( context, the_node, insert_priority );
-  _Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
+  _Scheduler_uniprocessor_Schedule(
+    scheduler,
+    _Scheduler_EDF_Get_highest_ready
+  );
 }
diff --git a/cpukit/score/src/scheduleredfschedule.c b/cpukit/score/src/scheduleredfschedule.c
index d0acea7a30..40c5ab2c06 100644
--- a/cpukit/score/src/scheduleredfschedule.c
+++ b/cpukit/score/src/scheduleredfschedule.c
@@ -46,5 +46,8 @@ void _Scheduler_EDF_Schedule(
   Thread_Control          *the_thread
 )
 {
-  _Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
+  _Scheduler_uniprocessor_Schedule(
+    scheduler,
+    _Scheduler_EDF_Get_highest_ready
+  );
 }
diff --git a/cpukit/score/src/scheduleredfunblock.c b/cpukit/score/src/scheduleredfunblock.c
index d6604686e3..4638eedf71 100644
--- a/cpukit/score/src/scheduleredfunblock.c
+++ b/cpukit/score/src/scheduleredfunblock.c
@@ -62,23 +62,5 @@ void _Scheduler_EDF_Unblock(
 
   the_node->priority = priority;
   _Scheduler_EDF_Enqueue( context, the_node, insert_priority );
-
-  /*
-   *  If the thread that was unblocked is more important than the heir,
-   *  then we have a new heir.  This may or may not result in a
-   *  context switch.
-   *
-   *  Normal case:
-   *    If the current thread is preemptible, then we need to do
-   *    a context switch.
-   *  Pseudo-ISR case:
-   *    Even if the thread isn't preemptible, if the new heir is
-   *    a pseudo-ISR system task, we need to do a context switch.
-   */
-  if ( priority < _Thread_Get_priority( _Thread_Heir ) ) {
-    _Scheduler_Update_heir(
-      the_thread,
-      priority == ( SCHEDULER_EDF_PRIO_MSB | PRIORITY_PSEUDO_ISR )
-    );
-  }
+  _Scheduler_uniprocessor_Unblock( scheduler, the_thread, priority );
 }
diff --git a/cpukit/score/src/scheduleredfyield.c b/cpukit/score/src/scheduleredfyield.c
index d83e1d9268..d38bea705a 100644
--- a/cpukit/score/src/scheduleredfyield.c
+++ b/cpukit/score/src/scheduleredfyield.c
@@ -55,5 +55,5 @@ void _Scheduler_EDF_Yield(
 
   _Scheduler_EDF_Extract( context, the_node );
   _Scheduler_EDF_Enqueue( context, the_node, the_node->priority );
-  _Scheduler_EDF_Schedule_body( scheduler, the_thread, true );
+  _Scheduler_uniprocessor_Yield( scheduler, _Scheduler_EDF_Get_highest_ready );
 }
diff --git a/cpukit/score/src/schedulerpriorityblock.c b/cpukit/score/src/schedulerpriorityblock.c
index 53636940dc..ffc7a3ad86 100644
--- a/cpukit/score/src/schedulerpriorityblock.c
+++ b/cpukit/score/src/schedulerpriorityblock.c
@@ -49,11 +49,11 @@ void _Scheduler_priority_Block(
   Scheduler_Node          *node
 )
 {
-  _Scheduler_Generic_block(
+  _Scheduler_uniprocessor_Block(
     scheduler,
     the_thread,
     node,
     _Scheduler_priority_Extract_body,
-    _Scheduler_priority_Schedule_body
+    _Scheduler_priority_Get_highest_ready
   );
 }
diff --git a/cpukit/score/src/schedulerprioritychangepriority.c b/cpukit/score/src/schedulerprioritychangepriority.c
index 8a059763de..3588a2ce42 100644
--- a/cpukit/score/src/schedulerprioritychangepriority.c
+++ b/cpukit/score/src/schedulerprioritychangepriority.c
@@ -96,5 +96,8 @@ void _Scheduler_priority_Update_priority(
     );
   }
 
-  _Scheduler_priority_Schedule_body( scheduler, the_thread, false );
+  _Scheduler_uniprocessor_Schedule(
+    scheduler,
+    _Scheduler_priority_Get_highest_ready
+  );
 }
diff --git a/cpukit/score/src/schedulerpriorityschedule.c b/cpukit/score/src/schedulerpriorityschedule.c
index bde749f9bc..bb7cf87399 100644
--- a/cpukit/score/src/schedulerpriorityschedule.c
+++ b/cpukit/score/src/schedulerpriorityschedule.c
@@ -46,5 +46,8 @@ void _Scheduler_priority_Schedule(
   Thread_Control          *the_thread
 )
 {
-  _Scheduler_priority_Schedule_body( scheduler, the_thread, false );
+  _Scheduler_uniprocessor_Schedule(
+    scheduler,
+    _Scheduler_priority_Get_highest_ready
+  );
 }
diff --git a/cpukit/score/src/schedulerpriorityunblock.c b/cpukit/score/src/schedulerpriorityunblock.c
index 190c126908..f9b6cabff7 100644
--- a/cpukit/score/src/schedulerpriorityunblock.c
+++ b/cpukit/score/src/schedulerpriorityunblock.c
@@ -76,19 +76,5 @@ void _Scheduler_priority_Unblock (
 
   /* TODO: flash critical section? */
 
-  /*
-   *  If the thread that was unblocked is more important than the heir,
-   *  then we have a new heir.  This may or may not result in a
-   *  context switch.
-   *
-   *  Normal case:
-   *    If the current thread is preemptible, then we need to do
-   *    a context switch.
-   *  Pseudo-ISR case:
-   *    Even if the thread isn't preemptible, if the new heir is
-   *    a pseudo-ISR system task, we need to do a context switch.
-   */
-  if ( priority < _Thread_Get_priority( _Thread_Heir ) ) {
-    _Scheduler_Update_heir( the_thread, priority == PRIORITY_PSEUDO_ISR );
-  }
+  _Scheduler_uniprocessor_Unblock( scheduler, the_thread, priority );
 }
diff --git a/cpukit/score/src/schedulerpriorityyield.c b/cpukit/score/src/schedulerpriorityyield.c
index 77fcecc418..adb443df94 100644
--- a/cpukit/score/src/schedulerpriorityyield.c
+++ b/cpukit/score/src/schedulerpriorityyield.c
@@ -59,5 +59,8 @@ void _Scheduler_priority_Yield(
     _Chain_Append_unprotected( ready_chain, &the_thread->Object.Node );
   }
 
-  _Scheduler_priority_Schedule_body( scheduler, the_thread, true );
+  _Scheduler_uniprocessor_Yield(
+    scheduler,
+    _Scheduler_priority_Get_highest_ready
+  );
 }
diff --git a/cpukit/score/src/schedulersimpleblock.c b/cpukit/score/src/schedulersimpleblock.c
index a8229d409f..dfd18df3a2 100644
--- a/cpukit/score/src/schedulersimpleblock.c
+++ b/cpukit/score/src/schedulersimpleblock.c
@@ -47,11 +47,11 @@ void _Scheduler_simple_Block(
   Scheduler_Node          *node
 )
 {
-  _Scheduler_Generic_block(
+  _Scheduler_uniprocessor_Block(
     scheduler,
     the_thread,
     node,
     _Scheduler_simple_Extract,
-    _Scheduler_simple_Schedule_body
+    _Scheduler_simple_Get_highest_ready
   );
 }
diff --git a/cpukit/score/src/schedulersimplechangepriority.c b/cpukit/score/src/schedulersimplechangepriority.c
index b4711dfd01..5c53c96fb3 100644
--- a/cpukit/score/src/schedulersimplechangepriority.c
+++ b/cpukit/score/src/schedulersimplechangepriority.c
@@ -60,5 +60,8 @@ void _Scheduler_simple_Update_priority(
 
   _Scheduler_simple_Extract( scheduler, the_thread, node );
   _Scheduler_simple_Insert( &context->Ready, the_thread, new_priority );
-  _Scheduler_simple_Schedule_body( scheduler, the_thread, false );
+  _Scheduler_uniprocessor_Schedule(
+    scheduler,
+    _Scheduler_simple_Get_highest_ready
+  );
 }
diff --git a/cpukit/score/src/schedulersimpleschedule.c b/cpukit/score/src/schedulersimpleschedule.c
index 4108fdaee8..83a3fed7fe 100644
--- a/cpukit/score/src/schedulersimpleschedule.c
+++ b/cpukit/score/src/schedulersimpleschedule.c
@@ -46,5 +46,8 @@ void _Scheduler_simple_Schedule(
   Thread_Control          *the_thread
 )
 {
-  _Scheduler_simple_Schedule_body( scheduler, the_thread, false );
+  _Scheduler_uniprocessor_Schedule(
+    scheduler,
+    _Scheduler_simple_Get_highest_ready
+  );
 }
diff --git a/cpukit/score/src/schedulersimpleunblock.c b/cpukit/score/src/schedulersimpleunblock.c
index 7791503d7a..436f20ac38 100644
--- a/cpukit/score/src/schedulersimpleunblock.c
+++ b/cpukit/score/src/schedulersimpleunblock.c
@@ -58,23 +58,5 @@ void _Scheduler_simple_Unblock(
   priority = _Thread_Get_priority( the_thread );
   insert_priority = SCHEDULER_PRIORITY_APPEND( priority );
   _Scheduler_simple_Insert( &context->Ready, the_thread, insert_priority );
-
-  /*
-   *  If the thread that was unblocked is more important than the heir,
-   *  then we have a new heir.  This may or may not result in a
-   *  context switch.
-   *
-   *  Normal case:
-   *    If the current thread is preemptible, then we need to do
-   *    a context switch.
-   *  Pseudo-ISR case:
-   *    Even if the thread isn't preemptible, if the new heir is
-   *    a pseudo-ISR system task, we need to do a context switch.
-   */
-  if ( priority < _Thread_Get_priority( _Thread_Heir ) ) {
-    _Scheduler_Update_heir(
-      the_thread,
-      priority == PRIORITY_PSEUDO_ISR
-    );
-  }
+  _Scheduler_uniprocessor_Unblock( scheduler, the_thread, priority );
 }
diff --git a/cpukit/score/src/schedulersimpleyield.c b/cpukit/score/src/schedulersimpleyield.c
index c25cceb8a7..ed8dd5b4cc 100644
--- a/cpukit/score/src/schedulersimpleyield.c
+++ b/cpukit/score/src/schedulersimpleyield.c
@@ -58,5 +58,8 @@ void _Scheduler_simple_Yield(
   insert_priority = (unsigned int) _Thread_Get_priority( the_thread );
   insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
   _Scheduler_simple_Insert( &context->Ready, the_thread, insert_priority );
-  _Scheduler_simple_Schedule_body( scheduler, the_thread, false );
+  _Scheduler_uniprocessor_Yield(
+    scheduler,
+    _Scheduler_simple_Get_highest_ready
+  );
 }
diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml
index 012a5db141..f89d2c0eac 100644
--- a/spec/build/cpukit/librtemscpu.yml
+++ b/spec/build/cpukit/librtemscpu.yml
@@ -395,6 +395,7 @@ install:
   - cpukit/include/rtems/score/schedulersmp.h
   - cpukit/include/rtems/score/schedulersmpimpl.h
   - cpukit/include/rtems/score/schedulerstrongapa.h
+  - cpukit/include/rtems/score/scheduleruniimpl.h
   - cpukit/include/rtems/score/semaphoreimpl.h
   - cpukit/include/rtems/score/smp.h
   - cpukit/include/rtems/score/smpbarrier.h
diff --git a/testsuites/sptests/sptasknopreempt01/init.c b/testsuites/sptests/sptasknopreempt01/init.c
index 617a44ade1..d92bd245e7 100644
--- a/testsuites/sptests/sptasknopreempt01/init.c
+++ b/testsuites/sptests/sptasknopreempt01/init.c
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 
 /*
- * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
+ * Copyright (C) 2015, 2022 embedded brains GmbH
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,12 +37,7 @@ static bool did_run;
 
 static void do_not_run(rtems_task_argument arg)
 {
-#if 0
   rtems_test_assert(0);
-#else
-  did_run = true;
-  rtems_task_suspend(RTEMS_SELF);
-#endif
 }
 
 static void test(void)
@@ -64,9 +59,9 @@ static void test(void)
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
   /*
-   * This will start a pseudo interrupt task pre-empting the non-preemtive
-   * executing task.  Later the high priority do_not_run() task is scheduled.
-   * See also https://devel.rtems.org/ticket/2365.
+   * This will start a task with a priority of PRIORITY_MINIMUM.  Check that
+   * this task and the test task did not preempt the current task.  See also
+   * https://devel.rtems.org/ticket/2365.
    */
   sc = rtems_timer_initiate_server(
     RTEMS_TIMER_SERVER_DEFAULT_PRIORITY,
@@ -75,8 +70,7 @@ static void test(void)
   );
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
-  /* This is probably a bug and not a feature */
-  rtems_test_assert(did_run);
+  rtems_test_assert(!did_run);
 
   sc = rtems_task_delete(task);
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
@@ -99,6 +93,8 @@ static void Init(rtems_task_argument arg)
 
 #define CONFIGURE_INIT_TASK_PRIORITY 2
 
+#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_NO_PREEMPT
+
 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
 
 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
-- 
2.35.3



More information about the devel mailing list