Changeset 7fe6d60 in rtems


Ignore:
Timestamp:
07/15/22 07:16:04 (9 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
4f94d47
Parents:
0a1d2d7
git-author:
Sebastian Huber <sebastian.huber@…> (07/15/22 07:16:04)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/26/22 09:26:22)
Message:

score: Remove PRIORITY_PSEUDO_ISR thread priority

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.

Files:
1 added
25 edited

Legend:

Unmodified
Added
Removed
  • cpukit/include/rtems/posix/priorityimpl.h

    r0a1d2d7 r7fe6d60  
    8585 *
    8686 * Let N be the maximum priority of this scheduler instance.   The SuperCore
    87  * priority zero is system reserved (PRIORITY_PSEUDO_ISR).  There are only
     87 * priority zero is system reserved (PRIORITY_MINIMUM).  There are only
    8888 * N - 1 POSIX API priority levels since a thread at SuperCore priority N would
    8989 * never run because of the idle threads.  This is necessary because GNAT maps
  • cpukit/include/rtems/score/priority.h

    r0a1d2d7 r7fe6d60  
    9797
    9898/**
    99  * @brief The priority value of pseudo-ISR threads.
    100  *
    101  * Examples are the MPCI and timer server threads.
    102  */
    103 #define PRIORITY_PSEUDO_ISR   PRIORITY_MINIMUM
    104 
    105 /**
    10699 * @brief The default lowest (least important) thread priority value.
    107100 *
  • cpukit/include/rtems/score/scheduleredfimpl.h

    r0a1d2d7 r7fe6d60  
    4040
    4141#include <rtems/score/scheduleredf.h>
    42 #include <rtems/score/schedulerimpl.h>
     42#include <rtems/score/scheduleruniimpl.h>
    4343
    4444#ifdef __cplusplus
     
    217217
    218218/**
    219  * @brief Schedules the next ready thread as the heir.
    220  *
    221  * @param scheduler The scheduler instance to schedule the minimum of the context of.
    222  * @param the_thread This parameter is not used.
    223  * @param force_dispatch Indicates whether the current heir is blocked even if it is
    224  *      not set as preemptible.
    225  */
    226 RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body(
    227   const Scheduler_Control *scheduler,
    228   Thread_Control          *the_thread,
    229   bool                     force_dispatch
     219 * @brief Gets the highest priority ready thread of the scheduler.
     220 *
     221 * @param scheduler is the scheduler.
     222 */
     223RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_EDF_Get_highest_ready(
     224  const Scheduler_Control *scheduler
    230225)
    231226{
     
    234229  Scheduler_EDF_Node    *node;
    235230
    236   (void) the_thread;
    237 
    238231  context = _Scheduler_EDF_Get_context( scheduler );
    239232  first = _RBTree_Minimum( &context->Ready );
    240233  node = RTEMS_CONTAINER_OF( first, Scheduler_EDF_Node, Node );
    241234
    242   _Scheduler_Update_heir( node->Base.owner, force_dispatch );
     235  return node->Base.owner;
    243236}
    244237
  • cpukit/include/rtems/score/schedulerimpl.h

    r0a1d2d7 r7fe6d60  
    670670
    671671/**
    672  * @brief Blocks the thread.
    673  *
    674  * @param scheduler The scheduler instance.
    675  * @param the_thread The thread to block.
    676  * @param node The corresponding scheduler node.
    677  * @param extract Method to extract the thread.
    678  * @param schedule Method for scheduling threads.
    679  */
    680 RTEMS_INLINE_ROUTINE void _Scheduler_Generic_block(
    681   const Scheduler_Control *scheduler,
    682   Thread_Control          *the_thread,
    683   Scheduler_Node          *node,
    684   void                  ( *extract )(
    685                              const Scheduler_Control *,
    686                              Thread_Control *,
    687                              Scheduler_Node *
    688                         ),
    689   void                  ( *schedule )(
    690                              const Scheduler_Control *,
    691                              Thread_Control *,
    692                              bool
    693                         )
    694 )
    695 {
    696   ( *extract )( scheduler, the_thread, node );
    697 
    698   /* TODO: flash critical section? */
    699 
    700   if ( _Thread_Is_heir( the_thread ) ) {
    701     ( *schedule )( scheduler, the_thread, true );
    702   }
    703 }
    704 
    705 /**
    706672 * @brief Gets the number of processors of the scheduler.
    707673 *
     
    951917}
    952918#endif
    953 
    954 /**
    955  * @brief Updates the heir.
    956  *
    957  * @param[in, out] new_heir The new heir.
    958  * @param force_dispatch Indicates whether the dispatch happens also if the
    959  *      currently running thread is set as not preemptible.
    960  */
    961 RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir(
    962   Thread_Control *new_heir,
    963   bool            force_dispatch
    964 )
    965 {
    966   Thread_Control *heir = _Thread_Heir;
    967 
    968   if ( heir != new_heir && ( heir->is_preemptible || force_dispatch ) ) {
    969 #if defined(RTEMS_SMP)
    970     /*
    971      * We need this state only for _Thread_Get_CPU_time_used_locked().  Cannot
    972      * use _Scheduler_Thread_change_state() since THREAD_SCHEDULER_BLOCKED to
    973      * THREAD_SCHEDULER_BLOCKED state changes are illegal for the real SMP
    974      * schedulers.
    975      */
    976     heir->Scheduler.state = THREAD_SCHEDULER_BLOCKED;
    977     new_heir->Scheduler.state = THREAD_SCHEDULER_SCHEDULED;
    978 #endif
    979     _Thread_Update_CPU_time_used( heir, _Thread_Get_CPU( heir ) );
    980     _Thread_Heir = new_heir;
    981     _Thread_Dispatch_necessary = true;
    982   }
    983 }
    984919
    985920/**
  • cpukit/include/rtems/score/schedulerpriorityimpl.h

    r0a1d2d7 r7fe6d60  
    4242#include <rtems/score/chainimpl.h>
    4343#include <rtems/score/prioritybitmapimpl.h>
    44 #include <rtems/score/schedulerimpl.h>
     44#include <rtems/score/scheduleruniimpl.h>
    4545#include <rtems/score/thread.h>
    4646
     
    232232
    233233/**
    234  * @brief Scheduling decision logic.
    235  *
    236  * This kernel routine implements scheduling decision logic
    237  * for priority-based scheduling.
    238  *
    239  * @param[in, out] scheduler The scheduler instance.
    240  * @param the_thread This parameter is unused.
    241  * @param force_dispatch Indicates whether the dispatch happens also if
    242  *      the currently executing thread is set as not preemptible.
    243  */
    244 RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body(
    245   const Scheduler_Control *scheduler,
    246   Thread_Control          *the_thread,
    247   bool                     force_dispatch
     234 * @brief Gets the highest priority ready thread of the scheduler.
     235 *
     236 * @param scheduler is the scheduler.
     237 */
     238RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_priority_Get_highest_ready(
     239  const Scheduler_Control *scheduler
    248240)
    249241{
    250242  Scheduler_priority_Context *context =
    251243    _Scheduler_priority_Get_context( scheduler );
    252   Thread_Control *heir = (Thread_Control *)
    253     _Scheduler_priority_Ready_queue_first(
    254       &context->Bit_map,
    255       &context->Ready[ 0 ]
    256     );
    257 
    258   ( void ) the_thread;
    259 
    260   _Scheduler_Update_heir( heir, force_dispatch );
     244
     245  return (Thread_Control *) _Scheduler_priority_Ready_queue_first(
     246    &context->Bit_map,
     247    &context->Ready[ 0 ]
     248  );
    261249}
    262250
  • cpukit/include/rtems/score/schedulersimpleimpl.h

    r0a1d2d7 r7fe6d60  
    4040#include <rtems/score/schedulersimple.h>
    4141#include <rtems/score/chainimpl.h>
    42 #include <rtems/score/schedulerimpl.h>
     42#include <rtems/score/scheduleruniimpl.h>
    4343
    4444#ifdef __cplusplus
     
    134134
    135135/**
    136  * @brief Scheduling decision logic.
     136 * @brief Gets the highest priority ready thread of the scheduler.
    137137 *
    138  * This kernel routine implements scheduling decision logic for the simple scheduler.
    139  *
    140  * @param[in, out] scheduler The scheduler instance.
    141  * @param the_thread This parameter is unused.
    142  * @param force_dispatch Indicates whether the dispatch happens also if
    143  *      the currently executing thread is set as not preemptible.
     138 * @param scheduler is the scheduler.
    144139 */
    145 RTEMS_INLINE_ROUTINE void _Scheduler_simple_Schedule_body(
    146   const Scheduler_Control *scheduler,
    147   Thread_Control          *the_thread,
    148   bool                     force_dispatch
     140RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_simple_Get_highest_ready(
     141  const Scheduler_Control *scheduler
    149142)
    150143{
    151144  Scheduler_simple_Context *context =
    152145    _Scheduler_simple_Get_context( scheduler );
    153   Thread_Control *heir = (Thread_Control *) _Chain_First( &context->Ready );
    154146
    155   ( void ) the_thread;
    156 
    157   _Scheduler_Update_heir( heir, force_dispatch );
     147  return (Thread_Control *) _Chain_First( &context->Ready );
    158148}
    159149
  • cpukit/rtems/src/timerserver.c

    r0a1d2d7 r7fe6d60  
    174174
    175175  if ( priority == RTEMS_TIMER_SERVER_DEFAULT_PRIORITY ) {
    176     priority = PRIORITY_PSEUDO_ISR;
     176    priority = PRIORITY_MINIMUM;
    177177  }
    178178
  • cpukit/score/src/mpci.c

    r0a1d2d7 r7fe6d60  
    163163  config.scheduler = &_Scheduler_Table[ 0 ];
    164164  config.name = _Objects_Build_name( 'M', 'P', 'C', 'I' );
    165   config.priority = PRIORITY_PSEUDO_ISR;
     165  config.priority = PRIORITY_MINIMUM;
    166166  config.is_fp = CPU_ALL_TASKS_ARE_FP;
    167167  config.stack_size = _Stack_Minimum()
  • cpukit/score/src/scheduleredfblock.c

    r0a1d2d7 r7fe6d60  
    4848)
    4949{
    50   _Scheduler_Generic_block(
     50  _Scheduler_uniprocessor_Block(
    5151    scheduler,
    5252    the_thread,
    5353    node,
    5454    _Scheduler_EDF_Extract_body,
    55     _Scheduler_EDF_Schedule_body
     55    _Scheduler_EDF_Get_highest_ready
    5656  );
    5757}
  • cpukit/score/src/scheduleredfchangepriority.c

    r0a1d2d7 r7fe6d60  
    7272  _Scheduler_EDF_Extract( context, the_node );
    7373  _Scheduler_EDF_Enqueue( context, the_node, insert_priority );
    74   _Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
     74  _Scheduler_uniprocessor_Schedule(
     75    scheduler,
     76    _Scheduler_EDF_Get_highest_ready
     77  );
    7578}
  • cpukit/score/src/scheduleredfschedule.c

    r0a1d2d7 r7fe6d60  
    4747)
    4848{
    49   _Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
     49  _Scheduler_uniprocessor_Schedule(
     50    scheduler,
     51    _Scheduler_EDF_Get_highest_ready
     52  );
    5053}
  • cpukit/score/src/scheduleredfunblock.c

    r0a1d2d7 r7fe6d60  
    6363  the_node->priority = priority;
    6464  _Scheduler_EDF_Enqueue( context, the_node, insert_priority );
    65 
    66   /*
    67    *  If the thread that was unblocked is more important than the heir,
    68    *  then we have a new heir.  This may or may not result in a
    69    *  context switch.
    70    *
    71    *  Normal case:
    72    *    If the current thread is preemptible, then we need to do
    73    *    a context switch.
    74    *  Pseudo-ISR case:
    75    *    Even if the thread isn't preemptible, if the new heir is
    76    *    a pseudo-ISR system task, we need to do a context switch.
    77    */
    78   if ( priority < _Thread_Get_priority( _Thread_Heir ) ) {
    79     _Scheduler_Update_heir(
    80       the_thread,
    81       priority == ( SCHEDULER_EDF_PRIO_MSB | PRIORITY_PSEUDO_ISR )
    82     );
    83   }
     65  _Scheduler_uniprocessor_Unblock( scheduler, the_thread, priority );
    8466}
  • cpukit/score/src/scheduleredfyield.c

    r0a1d2d7 r7fe6d60  
    5656  _Scheduler_EDF_Extract( context, the_node );
    5757  _Scheduler_EDF_Enqueue( context, the_node, the_node->priority );
    58   _Scheduler_EDF_Schedule_body( scheduler, the_thread, true );
     58  _Scheduler_uniprocessor_Yield( scheduler, _Scheduler_EDF_Get_highest_ready );
    5959}
  • cpukit/score/src/schedulerpriorityblock.c

    r0a1d2d7 r7fe6d60  
    5050)
    5151{
    52   _Scheduler_Generic_block(
     52  _Scheduler_uniprocessor_Block(
    5353    scheduler,
    5454    the_thread,
    5555    node,
    5656    _Scheduler_priority_Extract_body,
    57     _Scheduler_priority_Schedule_body
     57    _Scheduler_priority_Get_highest_ready
    5858  );
    5959}
  • cpukit/score/src/schedulerprioritychangepriority.c

    r0a1d2d7 r7fe6d60  
    9797  }
    9898
    99   _Scheduler_priority_Schedule_body( scheduler, the_thread, false );
     99  _Scheduler_uniprocessor_Schedule(
     100    scheduler,
     101    _Scheduler_priority_Get_highest_ready
     102  );
    100103}
  • cpukit/score/src/schedulerpriorityschedule.c

    r0a1d2d7 r7fe6d60  
    4747)
    4848{
    49   _Scheduler_priority_Schedule_body( scheduler, the_thread, false );
     49  _Scheduler_uniprocessor_Schedule(
     50    scheduler,
     51    _Scheduler_priority_Get_highest_ready
     52  );
    5053}
  • cpukit/score/src/schedulerpriorityunblock.c

    r0a1d2d7 r7fe6d60  
    7777  /* TODO: flash critical section? */
    7878
    79   /*
    80    *  If the thread that was unblocked is more important than the heir,
    81    *  then we have a new heir.  This may or may not result in a
    82    *  context switch.
    83    *
    84    *  Normal case:
    85    *    If the current thread is preemptible, then we need to do
    86    *    a context switch.
    87    *  Pseudo-ISR case:
    88    *    Even if the thread isn't preemptible, if the new heir is
    89    *    a pseudo-ISR system task, we need to do a context switch.
    90    */
    91   if ( priority < _Thread_Get_priority( _Thread_Heir ) ) {
    92     _Scheduler_Update_heir( the_thread, priority == PRIORITY_PSEUDO_ISR );
    93   }
     79  _Scheduler_uniprocessor_Unblock( scheduler, the_thread, priority );
    9480}
  • cpukit/score/src/schedulerpriorityyield.c

    r0a1d2d7 r7fe6d60  
    6060  }
    6161
    62   _Scheduler_priority_Schedule_body( scheduler, the_thread, true );
     62  _Scheduler_uniprocessor_Yield(
     63    scheduler,
     64    _Scheduler_priority_Get_highest_ready
     65  );
    6366}
  • cpukit/score/src/schedulersimpleblock.c

    r0a1d2d7 r7fe6d60  
    4848)
    4949{
    50   _Scheduler_Generic_block(
     50  _Scheduler_uniprocessor_Block(
    5151    scheduler,
    5252    the_thread,
    5353    node,
    5454    _Scheduler_simple_Extract,
    55     _Scheduler_simple_Schedule_body
     55    _Scheduler_simple_Get_highest_ready
    5656  );
    5757}
  • cpukit/score/src/schedulersimplechangepriority.c

    r0a1d2d7 r7fe6d60  
    6161  _Scheduler_simple_Extract( scheduler, the_thread, node );
    6262  _Scheduler_simple_Insert( &context->Ready, the_thread, new_priority );
    63   _Scheduler_simple_Schedule_body( scheduler, the_thread, false );
     63  _Scheduler_uniprocessor_Schedule(
     64    scheduler,
     65    _Scheduler_simple_Get_highest_ready
     66  );
    6467}
  • cpukit/score/src/schedulersimpleschedule.c

    r0a1d2d7 r7fe6d60  
    4747)
    4848{
    49   _Scheduler_simple_Schedule_body( scheduler, the_thread, false );
     49  _Scheduler_uniprocessor_Schedule(
     50    scheduler,
     51    _Scheduler_simple_Get_highest_ready
     52  );
    5053}
  • cpukit/score/src/schedulersimpleunblock.c

    r0a1d2d7 r7fe6d60  
    5959  insert_priority = SCHEDULER_PRIORITY_APPEND( priority );
    6060  _Scheduler_simple_Insert( &context->Ready, the_thread, insert_priority );
    61 
    62   /*
    63    *  If the thread that was unblocked is more important than the heir,
    64    *  then we have a new heir.  This may or may not result in a
    65    *  context switch.
    66    *
    67    *  Normal case:
    68    *    If the current thread is preemptible, then we need to do
    69    *    a context switch.
    70    *  Pseudo-ISR case:
    71    *    Even if the thread isn't preemptible, if the new heir is
    72    *    a pseudo-ISR system task, we need to do a context switch.
    73    */
    74   if ( priority < _Thread_Get_priority( _Thread_Heir ) ) {
    75     _Scheduler_Update_heir(
    76       the_thread,
    77       priority == PRIORITY_PSEUDO_ISR
    78     );
    79   }
     61  _Scheduler_uniprocessor_Unblock( scheduler, the_thread, priority );
    8062}
  • cpukit/score/src/schedulersimpleyield.c

    r0a1d2d7 r7fe6d60  
    5959  insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
    6060  _Scheduler_simple_Insert( &context->Ready, the_thread, insert_priority );
    61   _Scheduler_simple_Schedule_body( scheduler, the_thread, false );
     61  _Scheduler_uniprocessor_Yield(
     62    scheduler,
     63    _Scheduler_simple_Get_highest_ready
     64  );
    6265}
  • spec/build/cpukit/librtemscpu.yml

    r0a1d2d7 r7fe6d60  
    397397  - cpukit/include/rtems/score/schedulersmpimpl.h
    398398  - cpukit/include/rtems/score/schedulerstrongapa.h
     399  - cpukit/include/rtems/score/scheduleruniimpl.h
    399400  - cpukit/include/rtems/score/semaphoreimpl.h
    400401  - cpukit/include/rtems/score/smp.h
  • testsuites/sptests/sptasknopreempt01/init.c

    r0a1d2d7 r7fe6d60  
    22
    33/*
    4  * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
     4 * Copyright (C) 2015, 2022 embedded brains GmbH
    55 *
    66 * Redistribution and use in source and binary forms, with or without
     
    3838static void do_not_run(rtems_task_argument arg)
    3939{
    40 #if 0
    4140  rtems_test_assert(0);
    42 #else
    43   did_run = true;
    44   rtems_task_suspend(RTEMS_SELF);
    45 #endif
    4641}
    4742
     
    6560
    6661  /*
    67    * This will start a pseudo interrupt task pre-empting the non-preemtive
    68    * executing task.  Later the high priority do_not_run() task is scheduled.
    69    * See also https://devel.rtems.org/ticket/2365.
     62   * This will start a task with a priority of PRIORITY_MINIMUM.  Check that
     63   * this task and the test task did not preempt the current task.  See also
     64   * https://devel.rtems.org/ticket/2365.
    7065   */
    7166  sc = rtems_timer_initiate_server(
     
    7671  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
    7772
    78   /* This is probably a bug and not a feature */
    79   rtems_test_assert(did_run);
     73  rtems_test_assert(!did_run);
    8074
    8175  sc = rtems_task_delete(task);
     
    10094#define CONFIGURE_INIT_TASK_PRIORITY 2
    10195
     96#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_NO_PREEMPT
     97
    10298#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
    10399
Note: See TracChangeset for help on using the changeset viewer.