Changeset eec08ef in rtems


Ignore:
Timestamp:
06/15/16 04:59:57 (7 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
5, master
Children:
5a32c48
Parents:
6bab009
git-author:
Sebastian Huber <sebastian.huber@…> (06/15/16 04:59:57)
git-committer:
Sebastian Huber <sebastian.huber@…> (06/22/16 12:00:28)
Message:

posix: Rework sporadic server scheduling policy

Instead of lowering the priority in case the initial budget is consumed
raise the priority for each new period. Restore the normal priority
once the initial budget is consumed. This makes it later easier to
combine the high priority phase with temporary priority boosts (e.g. via
priority ceiling and inheritance).

Use the thread lock to protect the POSIX thread attributes instead of
the thread state lock. This makes it easier to change the thread
priority and keep the POSIX attributes consistent.

Fixes a false positive use of uninitialized variable warning.

Location:
cpukit
Files:
9 edited

Legend:

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

    r6bab009 reec08ef  
    6363
    6464  _Watchdog_Per_CPU_insert_relative(
    65     &api->Sporadic_timer,
     65    &api->Sporadic.Timer,
    6666    _Per_CPU_Get(),
    6767    _Timespec_To_ticks( &api->Attributes.schedparam.sched_ss_repl_period )
     
    8080  Thread_Control *the_thread
    8181);
    82 
    83 /**
    84  * This routine supports the sporadic scheduling algorithm.  It
    85  * is scheduled to be executed at the end of each replenishment
    86  * period.  In sporadic scheduling a thread will execute at a
    87  * high priority for a user specified amount of CPU time.  When
    88  * it exceeds that amount of CPU time, its priority is automatically
    89  * lowered. This TSR is executed when it is time to replenish
    90  * the thread's processor budget and raise its priority.
    91  *
    92  * @param[in] id is ignored
    93  * @param[in] argument is a pointer to the Thread_Control structure
    94  *            for the thread being replenished.
    95  */
    96 void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog );
    9782
    9883/**
  • cpukit/posix/include/rtems/posix/threadsup.h

    r6bab009 reec08ef  
    1919#define _RTEMS_POSIX_THREADSUP_H
    2020
    21 #include <rtems/score/coresem.h>
    22 #include <rtems/score/isrlock.h>
    2321#include <rtems/score/thread.h>
    24 #include <rtems/score/threadq.h>
    2522#include <rtems/score/watchdog.h>
    2623
     
    5148
    5249  /**
    53    * This is the timer which controls when the thread executes at
    54    * high and low priority when using the sporadic scheduler.
     50   * @brief Control block for the sporadic server scheduling policy.
    5551   */
    56   Watchdog_Control        Sporadic_timer;
     52  struct {
     53    /**
     54     * @brief This is the timer which controls when the thread executes at high
     55     * and low priority when using the sporadic server scheduling policy.
     56     */
     57    Watchdog_Control Timer;
     58
     59    /**
     60     * @brief The low priority when using the sporadic server scheduling
     61     * policy.
     62     */
     63    Priority_Control low_priority;
     64
     65    /**
     66     * @brief The high priority when using the sporadic server scheduling
     67     * policy.
     68     */
     69    Priority_Control high_priority;
     70  } Sporadic;
    5771
    5872  /** This is the set of signals which are currently unblocked. */
  • cpukit/posix/src/psxtransschedparam.c

    r6bab009 reec08ef  
    2222#include <errno.h>
    2323
    24 #include <rtems/system.h>
    2524#include <rtems/posix/pthreadimpl.h>
    26 #include <rtems/posix/priorityimpl.h>
    2725
    2826int _POSIX_Thread_Translate_sched_param(
     
    3331)
    3432{
    35   if ( !_POSIX_Priority_Is_valid( param->sched_priority ) )
    36     return EINVAL;
    37 
    3833  *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    3934  *budget_callout = NULL;
     
    6762      return EINVAL;
    6863
    69     if ( !_POSIX_Priority_Is_valid( param->sched_ss_low_priority ) )
    70       return EINVAL;
    71 
    7264    *budget_algorithm  = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
    7365    *budget_callout = _POSIX_Threads_Sporadic_budget_callout;
  • cpukit/posix/src/pthread.c

    r6bab009 reec08ef  
    8282};
    8383
    84 static bool _POSIX_Threads_Sporadic_budget_TSR_filter(
     84static bool _POSIX_Threads_Sporadic_timer_filter(
    8585  Thread_Control   *the_thread,
    86   Priority_Control *new_priority,
     86  Priority_Control *new_priority_p,
    8787  void             *arg
    8888)
    8989{
    90   the_thread->real_priority = *new_priority;
    91 
    92   /*
    93    * If holding a resource, then do not change it.
    94    *
    95    * If this would make them less important, then do not change it.
    96    */
    97   return !_Thread_Owns_resources( the_thread ) &&
    98     _Thread_Priority_less_than( the_thread->current_priority, *new_priority );
    99 }
    100 
    101 /*
    102  *  _POSIX_Threads_Sporadic_budget_TSR
    103  */
    104 void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog )
    105 {
    106   POSIX_API_Control  *api;
    107   Thread_Control     *the_thread;
    108   ISR_lock_Context    lock_context;
    109   Priority_Control    new_priority;
    110 
    111   api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic_timer );
     90  POSIX_API_Control *api;
     91  Priority_Control   current_priority;
     92  Priority_Control   new_priority;
     93
     94  api = arg;
     95
     96  new_priority = api->Sporadic.high_priority;
     97  *new_priority_p = new_priority;
     98
     99  current_priority = the_thread->current_priority;
     100  the_thread->real_priority = new_priority;
     101
     102  _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer );
     103  _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
     104
     105  return _Thread_Priority_less_than( current_priority, new_priority )
     106    || !_Thread_Owns_resources( the_thread );
     107}
     108
     109static void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog )
     110{
     111  POSIX_API_Control *api;
     112  Thread_Control    *the_thread;
     113
     114  api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic.Timer );
    112115  the_thread = api->thread;
    113 
    114   _Thread_State_acquire( the_thread, &lock_context );
    115 
    116   _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
    117   _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
    118 
    119   new_priority = _POSIX_Priority_To_core(
    120     api->Attributes.schedparam.sched_priority
    121   );
    122 
    123   _Thread_State_release( the_thread, &lock_context );
    124116
    125117  _Thread_Change_priority(
    126118    the_thread,
    127     new_priority,
    128     NULL,
    129     _POSIX_Threads_Sporadic_budget_TSR_filter,
     119    0,
     120    api,
     121    _POSIX_Threads_Sporadic_timer_filter,
    130122    true
    131123  );
     
    134126static bool _POSIX_Threads_Sporadic_budget_callout_filter(
    135127  Thread_Control   *the_thread,
    136   Priority_Control *new_priority,
     128  Priority_Control *new_priority_p,
    137129  void             *arg
    138130)
    139131{
    140   the_thread->real_priority = *new_priority;
    141 
    142   /*
    143    * If holding a resource, then do not change it.
    144    *
    145    * Make sure we are actually lowering it. If they have lowered it
    146    * to logically lower than sched_ss_low_priority, then we do not want to
    147    * change it.
    148    */
    149   return !_Thread_Owns_resources( the_thread ) &&
    150     _Thread_Priority_less_than( *new_priority, the_thread->current_priority );
    151 }
    152 
    153 /*
    154  *  _POSIX_Threads_Sporadic_budget_callout
    155  */
    156 void _POSIX_Threads_Sporadic_budget_callout(
    157   Thread_Control *the_thread
    158 )
    159 {
    160   POSIX_API_Control *api;
     132  POSIX_API_Control *api;
     133  Priority_Control   current_priority;
     134  Priority_Control   new_priority;
    161135
    162136  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     
    168142  the_thread->cpu_time_budget = UINT32_MAX;
    169143
     144  new_priority = api->Sporadic.low_priority;
     145  *new_priority_p = new_priority;
     146
     147  current_priority = the_thread->current_priority;
     148  the_thread->real_priority = new_priority;
     149
     150  return _Thread_Priority_less_than( current_priority, new_priority )
     151    || !_Thread_Owns_resources( the_thread );
     152}
     153
     154void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread )
     155{
    170156  _Thread_Change_priority(
    171157    the_thread,
    172     _POSIX_Priority_To_core(
    173       api->Attributes.schedparam.sched_ss_low_priority
    174     ),
     158    0,
    175159    NULL,
    176160    _POSIX_Threads_Sporadic_budget_callout_filter,
     
    218202  }
    219203
    220   _Watchdog_Preinitialize( &api->Sporadic_timer, _Per_CPU_Get_by_index( 0 ) );
    221   _Watchdog_Initialize(
    222     &api->Sporadic_timer,
    223     _POSIX_Threads_Sporadic_budget_TSR
    224   );
     204  _Watchdog_Preinitialize( &api->Sporadic.Timer, _Per_CPU_Get_by_index( 0 ) );
     205  _Watchdog_Initialize( &api->Sporadic.Timer, _POSIX_Threads_Sporadic_timer );
    225206
    226207  return true;
     
    237218
    238219  if ( api->Attributes.schedpolicy == SCHED_SPORADIC ) {
    239     _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
     220    _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer );
    240221  }
    241222
  • cpukit/posix/src/pthreadcreate.c

    r6bab009 reec08ef  
    6161  };
    6262  const pthread_attr_t               *the_attr;
    63   Priority_Control                    core_priority;
     63  int                                 low_prio;
     64  int                                 high_prio;
     65  Priority_Control                    core_low_prio;
     66  Priority_Control                    core_high_prio;
    6467  Thread_CPU_budget_algorithms        budget_algorithm;
    6568  Thread_CPU_budget_algorithm_callout budget_callout;
     
    7275  struct sched_param                  schedparam;
    7376  Objects_Name                        name;
    74   int                                 rc;
     77  int                                 error;
    7578  ISR_lock_Context                    lock_context;
    7679
     
    131134    return ENOTSUP;
    132135
    133   /*
    134    *  Interpret the scheduling parameters.
    135    */
    136   if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) )
    137     return EINVAL;
    138 
    139   core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );
    140 
    141   /*
    142    *  Set the core scheduling policy information.
    143    */
    144   rc = _POSIX_Thread_Translate_sched_param(
     136  error = _POSIX_Thread_Translate_sched_param(
    145137    schedpolicy,
    146138    &schedparam,
     
    148140    &budget_callout
    149141  );
    150   if ( rc )
    151     return rc;
     142  if ( error != 0 ) {
     143    return error;
     144  }
     145
     146  if ( schedpolicy == SCHED_SPORADIC ) {
     147    low_prio = schedparam.sched_ss_low_priority;
     148    high_prio = schedparam.sched_priority;
     149  } else {
     150    low_prio = schedparam.sched_priority;
     151    high_prio = low_prio;
     152  }
     153
     154  if ( !_POSIX_Priority_Is_valid( low_prio ) ) {
     155    return EINVAL;
     156  }
     157
     158  if ( !_POSIX_Priority_Is_valid( high_prio ) ) {
     159    return EINVAL;
     160  }
     161
     162  core_low_prio = _POSIX_Priority_To_core( low_prio );
     163  core_high_prio = _POSIX_Priority_To_core( high_prio );
    152164
    153165#if defined(RTEMS_SMP)
     
    187199    _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize),
    188200    is_fp,
    189     core_priority,
     201    core_high_prio,
    190202    true,                 /* preemptible */
    191203    budget_algorithm,
     
    227239
    228240  _POSIX_Threads_Copy_attributes( &api->Attributes, the_attr );
     241  api->Sporadic.low_priority = core_low_prio;
     242  api->Sporadic.high_priority = core_high_prio;
    229243
    230244  if ( schedpolicy == SCHED_SPORADIC ) {
  • cpukit/posix/src/pthreadgetschedparam.c

    r6bab009 reec08ef  
    4949  }
    5050
    51   _Thread_State_acquire_critical( the_thread, &lock_context );
     51  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    5252
    53   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     53  _Thread_Lock_acquire_default_critical( the_thread, &lock_context );
     54
    5455  *policy = api->Attributes.schedpolicy;
    5556  *param  = api->Attributes.schedparam;
     
    5859  );
    5960
    60   _Thread_State_release( the_thread, &lock_context );
     61  _Thread_Lock_release_default( the_thread, &lock_context );
    6162  return 0;
    6263}
  • cpukit/posix/src/pthreadsetschedparam.c

    r6bab009 reec08ef  
    2929#include <rtems/posix/priorityimpl.h>
    3030#include <rtems/score/threadimpl.h>
    31 #include <rtems/score/watchdogimpl.h>
    32 #include <rtems/config.h>
     31
     32typedef struct {
     33  int                                  policy;
     34  const struct sched_param            *param;
     35  Thread_CPU_budget_algorithms         budget_algorithm;
     36  Thread_CPU_budget_algorithm_callout  budget_callout;
     37  int                                  error;
     38} POSIX_Set_sched_param_context;
     39
     40static bool _POSIX_Set_sched_param_filter(
     41  Thread_Control   *the_thread,
     42  Priority_Control *new_priority_p,
     43  void             *arg
     44)
     45{
     46  POSIX_Set_sched_param_context *context;
     47  const struct sched_param      *param;
     48  POSIX_API_Control             *api;
     49  int                            low_prio;
     50  int                            high_prio;
     51  Priority_Control               core_low_prio;
     52  Priority_Control               core_high_prio;
     53  Priority_Control               current_priority;
     54
     55  context = arg;
     56  param = context->param;
     57
     58  if ( context->policy == SCHED_SPORADIC ) {
     59    low_prio = param->sched_ss_low_priority;
     60    high_prio = param->sched_priority;
     61  } else {
     62    low_prio = param->sched_priority;
     63    high_prio = low_prio;
     64  }
     65
     66  if ( !_POSIX_Priority_Is_valid( low_prio ) ) {
     67    context->error = EINVAL;
     68    return false;
     69  }
     70
     71  if ( !_POSIX_Priority_Is_valid( high_prio ) ) {
     72    context->error = EINVAL;
     73    return false;
     74  }
     75
     76  core_low_prio = _POSIX_Priority_To_core( low_prio );
     77  core_high_prio = _POSIX_Priority_To_core( high_prio );
     78
     79  *new_priority_p = core_high_prio;
     80
     81  current_priority = the_thread->current_priority;
     82  the_thread->real_priority = core_high_prio;
     83
     84  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     85
     86  _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer );
     87
     88  api->Attributes.schedpolicy = context->policy;
     89  api->Attributes.schedparam  = *param;
     90  api->Sporadic.low_priority  = core_low_prio;
     91  api->Sporadic.high_priority = core_high_prio;
     92
     93  the_thread->budget_algorithm = context->budget_algorithm;
     94  the_thread->budget_callout   = context->budget_callout;
     95
     96  if ( context->policy == SCHED_SPORADIC ) {
     97    _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
     98  } else {
     99    the_thread->cpu_time_budget =
     100      rtems_configuration_get_ticks_per_timeslice();
     101  }
     102
     103  context->error = 0;
     104  return _Thread_Priority_less_than( current_priority, core_high_prio )
     105    || !_Thread_Owns_resources( the_thread );
     106}
    33107
    34108int pthread_setschedparam(
     
    38112)
    39113{
    40   Thread_Control                      *the_thread;
    41   Per_CPU_Control                     *cpu_self;
    42   POSIX_API_Control                   *api;
    43   Thread_CPU_budget_algorithms         budget_algorithm;
    44   Thread_CPU_budget_algorithm_callout  budget_callout;
    45   int                                  eno;
    46   Priority_Control                     unused;
    47   ISR_lock_Context                     lock_context;
    48   Priority_Control                     new_priority;
    49 
    50   /*
    51    *  Check all the parameters
    52    */
     114  Thread_Control                *the_thread;
     115  Per_CPU_Control               *cpu_self;
     116  POSIX_Set_sched_param_context  context;
     117  ISR_lock_Context               lock_context;
     118  int                            error;
    53119
    54120  if ( param == NULL ) {
     
    56122  }
    57123
    58   eno = _POSIX_Thread_Translate_sched_param(
     124  error = _POSIX_Thread_Translate_sched_param(
    59125    policy,
    60126    param,
    61     &budget_algorithm,
    62     &budget_callout
     127    &context.budget_algorithm,
     128    &context.budget_callout
    63129  );
    64   if ( eno != 0 ) {
    65     return eno;
     130  if ( error != 0 ) {
     131    return error;
    66132  }
     133
     134  context.policy = policy;
     135  context.param = param;
    67136
    68137  the_thread = _Thread_Get( thread, &lock_context );
     
    72141  }
    73142
    74   /*
    75    *  Actually change the scheduling policy and parameters
    76    */
     143  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
     144  _ISR_lock_ISR_enable( &lock_context );
    77145
    78   cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    79   _Thread_State_acquire_critical( the_thread, &lock_context );
    80 
    81   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    82 
    83   if ( api->Attributes.schedpolicy == SCHED_SPORADIC ) {
    84     _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
    85   }
    86 
    87   api->Attributes.schedpolicy = policy;
    88   api->Attributes.schedparam  = *param;
    89 
    90   the_thread->budget_algorithm = budget_algorithm;
    91   the_thread->budget_callout   = budget_callout;
    92 
    93   switch ( policy ) {
    94     case SCHED_OTHER:
    95     case SCHED_FIFO:
    96     case SCHED_RR:
    97       the_thread->cpu_time_budget =
    98         rtems_configuration_get_ticks_per_timeslice();
    99       new_priority = _POSIX_Priority_To_core(
    100         api->Attributes.schedparam.sched_priority
    101       );
    102       break;
    103   }
    104 
    105   _Thread_State_release( the_thread, &lock_context );
    106 
    107   switch ( policy ) {
    108     case SCHED_OTHER:
    109     case SCHED_FIFO:
    110     case SCHED_RR:
    111       _Thread_Set_priority( the_thread, new_priority, &unused, false );
    112       break;
    113 
    114     case SCHED_SPORADIC:
    115       _POSIX_Threads_Sporadic_budget_TSR( &api->Sporadic_timer );
    116       break;
    117   }
     146  _Thread_Change_priority(
     147    the_thread,
     148    0,
     149    &context,
     150    _POSIX_Set_sched_param_filter,
     151    false
     152  );
    118153
    119154  _Thread_Dispatch_enable( cpu_self );
    120   return 0;
     155  return context.error;
    121156}
  • cpukit/posix/src/pthreadsetschedprio.c

    r6bab009 reec08ef  
    1818#include <rtems/score/threadimpl.h>
    1919
    20 int pthread_setschedprio( pthread_t thread, int prio )
     20typedef struct {
     21  int prio;
     22  int error;
     23} POSIX_Set_sched_prio_context;
     24
     25static bool _POSIX_Set_sched_prio_filter(
     26  Thread_Control   *the_thread,
     27  Priority_Control *new_priority_p,
     28  void             *arg
     29)
    2130{
    22   Thread_Control    *the_thread;
    23   Per_CPU_Control   *cpu_self;
    24   POSIX_API_Control *api;
    25   Priority_Control   unused;
    26   ISR_lock_Context   lock_context;
    27   Priority_Control   new_priority;
     31  POSIX_Set_sched_prio_context *context;
     32  int                           prio;
     33  POSIX_API_Control            *api;
     34  Priority_Control              current_priority;
     35  Priority_Control              new_priority;
     36
     37  context = arg;
     38  prio = context->prio;
    2839
    2940  if ( !_POSIX_Priority_Is_valid( prio ) ) {
    30     return EINVAL;
     41    context->error = EINVAL;
     42    return false;
    3143  }
    3244
    3345  new_priority = _POSIX_Priority_To_core( prio );
     46  *new_priority_p = new_priority;
     47
     48  current_priority = the_thread->current_priority;
     49  the_thread->real_priority = new_priority;
     50
     51  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     52
     53  api->Sporadic.high_priority = new_priority;
     54
     55  if ( api->Sporadic.low_priority < new_priority ) {
     56    api->Sporadic.low_priority  = new_priority;
     57  }
     58
     59  context->error = 0;
     60  return _Thread_Priority_less_than( current_priority, new_priority )
     61    || !_Thread_Owns_resources( the_thread );
     62}
     63
     64int pthread_setschedprio( pthread_t thread, int prio )
     65{
     66  Thread_Control               *the_thread;
     67  Per_CPU_Control              *cpu_self;
     68  POSIX_Set_sched_prio_context  context;
     69  ISR_lock_Context              lock_context;
     70
     71  context.prio = prio;
    3472
    3573  the_thread = _Thread_Get( thread, &lock_context );
     
    3977  }
    4078
    41   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     79  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
     80  _ISR_lock_ISR_enable( &lock_context );
    4281
    43   cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    44 
    45   _Thread_State_acquire_critical( the_thread, &lock_context );
    46   api->Attributes.schedparam.sched_priority = prio;
    47   _Thread_State_release( the_thread, &lock_context );
    48 
    49   _Thread_Set_priority( the_thread, new_priority, &unused, true );
     82  _Thread_Change_priority(
     83    the_thread,
     84    0,
     85    &context,
     86    _POSIX_Set_sched_prio_filter,
     87    true
     88  );
    5089
    5190  _Thread_Dispatch_enable( cpu_self );
    52   return 0;
     91  return context.error;
    5392}
  • cpukit/score/include/rtems/score/thread.h

    r6bab009 reec08ef  
    658658 *
    659659 * The thread lock protects the following thread variables
     660 *  - POSIX_API_Control::Attributes,
    660661 *  - Thread_Control::current_priority,
    661662 *  - Thread_Control::Wait::queue, and
     
    711712   * the following fields
    712713   *
    713    * - POSIX_API_Control::Attributes,
    714714   * - RTEMS_API_Control::Signal,
    715715   * - Thread_Control::budget_algorithm,
Note: See TracChangeset for help on using the changeset viewer.