Changeset 2e9c3d5 in rtems


Ignore:
Timestamp:
Mar 17, 2015, 3:28:50 PM (5 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
57947f1
Parents:
e02b20a3
git-author:
Sebastian Huber <sebastian.huber@…> (03/17/15 15:28:50)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/24/15 13:35:04)
Message:

score: Add thread priority change handler

Since the thread current priority change and thread queue requeue is
performed in one critical section it is possible to simplify the thread
queue requeue procedure. Add a thread queue agnostic thread priority
change handler so that we are able to use alternative thread queue
implementations.

Update #2273.

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • cpukit/score/include/rtems/score/thread.h

    re02b20a3 r2e9c3d5  
    375375#define THREAD_API_LAST  THREAD_API_POSIX
    376376
     377/**
     378 * @brief Priority change handler.
     379 *
     380 * @param[in] the_thread The thread.
     381 * @param[in] new_priority The new priority value.
     382 * @param[in] context The handler context.
     383 *
     384 * @see _Thread_Priority_set_change_handler().
     385 */
     386typedef void (*Thread_Priority_change_handler)(
     387  Thread_Control   *the_thread,
     388  Priority_Control  new_priority,
     389  void             *context
     390);
     391
     392/**
     393 * @brief Thread priority control.
     394 */
     395typedef struct {
     396  /**
     397   * @brief Generation of the current priority value.
     398   *
     399   * It is used in _Thread_Change_priority() to serialize the update of
     400   * priority related data structures.
     401   */
     402  uint32_t generation;
     403
     404  /**
     405   * @brief Priority change handler.
     406   *
     407   * Called by _Thread_Change_priority() to notify a thread about a priority
     408   * change.  In case this thread waits currently for a resource the handler
     409   * may adjust its data structures according to the new priority value.  This
     410   * handler must not be NULL, instead the default handler
     411   * _Thread_Priority_change_do_nothing() should be used in case nothing needs
     412   * to be done during a priority change.
     413   *
     414   * @see _Thread_Priority_set_change_handler() and
     415   * _Thread_Priority_restore_default_change_handler().
     416   */
     417  Thread_Priority_change_handler change_handler;
     418
     419  /**
     420   * @brief Context for priority change handler.
     421   *
     422   * @see _Thread_Priority_set_change_handler().
     423   */
     424  void *change_handler_context;
     425} Thread_Priority_control;
     426
    377427typedef struct Thread_Action Thread_Action;
    378428
     
    585635
    586636  /**
    587    * @brief Generation of the current priority value.
    588    *
    589    * It is used in _Thread_Change_priority() to serialize the update of
    590    * priority related data structures.
    591    */
    592   uint32_t                 priority_generation;
     637   * @brief Thread priority control.
     638   */
     639  Thread_Priority_control  Priority;
    593640
    594641  /** This field is the number of mutexes currently held by this thread. */
  • cpukit/score/include/rtems/score/threadimpl.h

    re02b20a3 r2e9c3d5  
    884884}
    885885
     886void _Thread_Priority_change_do_nothing(
     887  Thread_Control   *the_thread,
     888  Priority_Control  new_priority,
     889  void             *context
     890);
     891
     892/**
     893 * @brief Sets the thread priority change handler and its context.
     894 *
     895 * @param[in] the_thread The thread.
     896 * @param[in] new_handler The new handler.
     897 * @param[in] new_context The new handler context.
     898 */
     899RTEMS_INLINE_ROUTINE void _Thread_Priority_set_change_handler(
     900  Thread_Control                 *the_thread,
     901  Thread_Priority_change_handler  new_handler,
     902  void                           *new_context
     903)
     904{
     905  the_thread->Priority.change_handler = new_handler;
     906  the_thread->Priority.change_handler_context = new_context;
     907}
     908
     909/**
     910 * @brief Restores the thread priority change default handler and its context.
     911 *
     912 * @param[in] the_thread The thread.
     913 */
     914RTEMS_INLINE_ROUTINE void _Thread_Priority_restore_default_change_handler(
     915  Thread_Control *the_thread
     916)
     917{
     918  the_thread->Priority.change_handler = _Thread_Priority_change_do_nothing;
     919}
     920
    886921/**
    887922 * @brief The initial thread wait flags value set by _Thread_Initialize().
  • cpukit/score/include/rtems/score/threadqimpl.h

    re02b20a3 r2e9c3d5  
    267267
    268268/**
    269  *  @brief Invoked when a thread changes priority and is blocked.
    270  *
    271  *  This routine is invoked when a thread changes priority and is
    272  *  blocked on a thread queue.  If the queue is priority ordered,
    273  *  the_thread is removed from the_thread_queue and reinserted using
    274  *  its new priority.  This method has no impact on the state of the_thread
    275  *  or of any timeouts associated with this blocking.
    276  *
    277  *  @param[in] the_thread_queue pointer to a threadq header
    278  *  @param[in] the_thread pointer to a thread control block
    279  */
    280 void _Thread_queue_Requeue(
    281   Thread_queue_Control *the_thread_queue,
    282   Thread_Control       *the_thread
    283 );
    284 
    285 /**
    286269 * This routine is invoked to indicate that the specified thread queue is
    287270 * entering a critical section.
  • cpukit/score/src/threadchangepriority.c

    re02b20a3 r2e9c3d5  
    3939   */
    4040  if ( the_thread->current_priority != new_priority ) {
    41     uint32_t my_generation = the_thread->priority_generation + 1;
     41    uint32_t my_generation = the_thread->Priority.generation + 1;
    4242
    4343    the_thread->current_priority = new_priority;
    44     the_thread->priority_generation = my_generation;
     44    the_thread->Priority.generation = my_generation;
    4545
    46     _Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
     46    (*the_thread->Priority.change_handler)(
     47      the_thread,
     48      new_priority,
     49      the_thread->Priority.change_handler_context
     50    );
    4751
    4852    _ISR_Flash( level );
    4953
    50     if ( the_thread->priority_generation == my_generation ) {
     54    if ( the_thread->Priority.generation == my_generation ) {
    5155      if ( _States_Is_ready( the_thread->current_state ) ) {
    5256        _Scheduler_Change_priority(
  • cpukit/score/src/threadinitialize.c

    re02b20a3 r2e9c3d5  
    2929#include <rtems/score/cpusetimpl.h>
    3030#include <rtems/config.h>
     31
     32void _Thread_Priority_change_do_nothing(
     33  Thread_Control   *the_thread,
     34  Priority_Control  new_priority,
     35  void             *context
     36)
     37{
     38  /* Do nothing */
     39}
    3140
    3241bool _Thread_Initialize(
     
    199208  the_thread->resource_count          = 0;
    200209  the_thread->real_priority           = priority;
    201   the_thread->priority_generation     = 0;
     210  the_thread->Priority.generation     = 0;
     211  the_thread->Priority.change_handler = _Thread_Priority_change_do_nothing;
    202212  the_thread->Start.initial_priority  = priority;
    203213
  • cpukit/score/src/threadqenqueue.c

    re02b20a3 r2e9c3d5  
    7272    _Thread_MP_Free_proxy( the_thread );
    7373#endif
     74}
     75
     76static void _Thread_queue_Requeue_priority(
     77  Thread_Control   *the_thread,
     78  Priority_Control  new_priority,
     79  void             *context
     80)
     81{
     82  Thread_queue_Control *tq = context;
     83
     84  _Thread_queue_Enter_critical_section( tq );
     85  _RBTree_Extract( &tq->Queues.Priority, &the_thread->RBNode );
     86  _RBTree_Insert(
     87    &tq->Queues.Priority,
     88    &the_thread->RBNode,
     89    _Thread_queue_Compare_priority,
     90    false
     91  );
    7492}
    7593
     
    128146      );
    129147    } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */
     148      _Thread_Priority_set_change_handler(
     149        the_thread,
     150        _Thread_queue_Requeue_priority,
     151        the_thread_queue
     152      );
    130153      _RBTree_Insert(
    131154        &the_thread_queue->Queues.Priority,
     
    173196      &the_thread->RBNode
    174197    );
     198    _Thread_Priority_restore_default_change_handler( the_thread );
    175199  }
    176200
     
    222246    if ( first ) {
    223247      the_thread = THREAD_RBTREE_NODE_TO_THREAD( first );
     248      _Thread_Priority_restore_default_change_handler( the_thread );
    224249    }
    225250  }
     
    250275  return the_thread;
    251276}
    252 
    253 void _Thread_queue_Requeue(
    254   Thread_queue_Control *the_thread_queue,
    255   Thread_Control       *the_thread
    256 )
    257 {
    258   /*
    259    * Just in case the thread really wasn't blocked on a thread queue
    260    * when we get here.
    261    */
    262   if ( !the_thread_queue )
    263     return;
    264 
    265   /*
    266    * If queueing by FIFO, there is nothing to do. This only applies to
    267    * priority blocking discipline.
    268    */
    269   if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) {
    270     Thread_queue_Control *tq = the_thread_queue;
    271     ISR_Level             level;
    272 
    273     _ISR_Disable( level );
    274     if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
    275       _Thread_queue_Enter_critical_section( tq );
    276 
    277       /* extract the thread */
    278       _RBTree_Extract(
    279         &the_thread->Wait.queue->Queues.Priority,
    280         &the_thread->RBNode
    281       );
    282 
    283       /* enqueue the thread at the new priority */
    284       _RBTree_Insert(
    285         &the_thread_queue->Queues.Priority,
    286         &the_thread->RBNode,
    287         _Thread_queue_Compare_priority,
    288         false
    289       );
    290     }
    291     _ISR_Enable( level );
    292   }
    293 }
  • testsuites/sptests/spintrcritical23/init.c

    re02b20a3 r2e9c3d5  
    7171  rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
    7272  if (
    73     ctx->priority_generation != ctx->tcb->priority_generation
     73    ctx->priority_generation != ctx->tcb->Priority.generation
    7474      && scheduler_node_unchanged(ctx)
    7575  ) {
     
    114114  ctx->priority_task = priority_task;
    115115  ctx->priority_interrupt = priority_interrupt;
    116   ctx->priority_generation = ctx->tcb->priority_generation;
     116  ctx->priority_generation = ctx->tcb->Priority.generation;
    117117  memcpy(
    118118    &ctx->scheduler_node,
Note: See TracChangeset for help on using the changeset viewer.