Changeset 709f38a in rtems


Ignore:
Timestamp:
Apr 13, 2016, 4:48:58 AM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
4cf41fd
Parents:
0a97ba5b
git-author:
Sebastian Huber <sebastian.huber@…> (04/13/16 04:48:58)
git-committer:
Sebastian Huber <sebastian.huber@…> (04/18/16 06:20:16)
Message:

score: Use chain iterator for user extensions

Add a lock and use a chain iterator for safe iteration during concurrent
user extension addition and removal.

Ensure that dynamically added thread delete and fatal extensions are
called in reverse order.

Update #2555.
Update #2692.

Files:
4 added
8 edited

Legend:

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

    r0a97ba5b r709f38a  
    4848
    4949struct Scheduler_Node;
     50
     51struct User_extensions_Iterator;
    5052
    5153#ifdef __cplusplus
     
    900902
    901903  /**
     904   * @brief LIFO list of user extensions iterators.
     905   */
     906  struct User_extensions_Iterator *last_user_extensions_iterator;
     907
     908  /**
    902909   * @brief Variable length array of user extension pointers.
    903910   *
  • cpukit/score/include/rtems/score/userextimpl.h

    r0a97ba5b r709f38a  
    2020
    2121#include <rtems/score/userext.h>
     22#include <rtems/score/isrlock.h>
    2223#include <rtems/score/chainimpl.h>
    2324#include <rtems/score/percpu.h>
     
    3738
    3839/**
     40 * @brief Chain iterator for dynamic user extensions.
     41 *
     42 * Since user extensions may delete or restart the executing thread, we must
     43 * clean up registered iterators.
     44 *
     45 * @see _User_extensions_Iterate(), _User_extensions_Destroy_iterators() and
     46 *   Thread_Control::last_user_extensions_iterator.
     47 */
     48typedef struct User_extensions_Iterator {
     49  Chain_Iterator                   Iterator;
     50  struct User_extensions_Iterator *previous;
     51} User_extensions_Iterator;
     52
     53typedef struct {
     54  /**
     55   * @brief Active dynamically added user extensions.
     56   */
     57  Chain_Control Active;
     58
     59  /**
     60   * @brief Chain iterator registration.
     61   */
     62  Chain_Iterator_registry Iterators;
     63
     64  /**
     65   * @brief Lock to protect User_extensions_List::Active and
     66   * User_extensions_List::Iterators.
     67   */
     68  ISR_LOCK_MEMBER( Lock )
     69} User_extensions_List;
     70
     71/**
    3972 * @brief List of active extensions.
    4073 */
    41 extern Chain_Control _User_extensions_List;
     74extern User_extensions_List _User_extensions_List;
    4275
    4376/**
     
    154187 *
    155188 * @param[in, out] arg The argument passed to the visitor.
    156  * @param[in] visitor is the visitor for each extension.
     189 * @param[in] visitor The visitor for each extension.
     190 * @param[in] direction The iteration direction for dynamic extensions.
    157191 */
    158192void _User_extensions_Iterate(
    159   void                    *arg,
    160   User_extensions_Visitor  visitor
     193  void                     *arg,
     194  User_extensions_Visitor   visitor,
     195  Chain_Iterator_direction  direction
    161196);
    162197
     
    172207  User_extensions_Thread_create_context ctx = { created, true };
    173208
    174   _User_extensions_Iterate( &ctx, _User_extensions_Thread_create_visitor );
     209  _User_extensions_Iterate(
     210    &ctx,
     211    _User_extensions_Thread_create_visitor,
     212    CHAIN_ITERATOR_FORWARD
     213  );
    175214
    176215  return ctx.ok;
     
    181220  _User_extensions_Iterate(
    182221    deleted,
    183     _User_extensions_Thread_delete_visitor
     222    _User_extensions_Thread_delete_visitor,
     223    CHAIN_ITERATOR_BACKWARD
    184224  );
    185225}
     
    189229  _User_extensions_Iterate(
    190230    started,
    191     _User_extensions_Thread_start_visitor
     231    _User_extensions_Thread_start_visitor,
     232    CHAIN_ITERATOR_FORWARD
    192233  );
    193234}
     
    197238  _User_extensions_Iterate(
    198239    restarted,
    199     _User_extensions_Thread_restart_visitor
     240    _User_extensions_Thread_restart_visitor,
     241    CHAIN_ITERATOR_FORWARD
    200242  );
    201243}
     
    205247  _User_extensions_Iterate(
    206248    executing,
    207     _User_extensions_Thread_begin_visitor
     249    _User_extensions_Thread_begin_visitor,
     250    CHAIN_ITERATOR_FORWARD
    208251  );
    209252}
     
    240283  _User_extensions_Iterate(
    241284    executing,
    242     _User_extensions_Thread_exitted_visitor
     285    _User_extensions_Thread_exitted_visitor,
     286    CHAIN_ITERATOR_FORWARD
    243287  );
    244288}
     
    252296  User_extensions_Fatal_context ctx = { source, is_internal, error };
    253297
    254   _User_extensions_Iterate( &ctx, _User_extensions_Fatal_visitor );
     298  _User_extensions_Iterate(
     299    &ctx,
     300    _User_extensions_Fatal_visitor,
     301    CHAIN_ITERATOR_BACKWARD
     302  );
    255303}
    256304
     
    261309  _User_extensions_Iterate(
    262310    executing,
    263     _User_extensions_Thread_terminate_visitor
    264   );
     311    _User_extensions_Thread_terminate_visitor,
     312    CHAIN_ITERATOR_FORWARD
     313  );
     314}
     315
     316static inline void _User_extensions_Acquire( ISR_lock_Context *lock_context )
     317{
     318  _ISR_lock_ISR_disable_and_acquire(
     319    &_User_extensions_List.Lock,
     320    lock_context
     321  );
     322}
     323
     324static inline void _User_extensions_Release( ISR_lock_Context *lock_context )
     325{
     326  _ISR_lock_Release_and_ISR_enable(
     327    &_User_extensions_List.Lock,
     328    lock_context
     329  );
     330}
     331
     332static inline void _User_extensions_Destroy_iterators(
     333  Thread_Control *the_thread
     334)
     335{
     336  ISR_lock_Context          lock_context;
     337  User_extensions_Iterator *iter;
     338
     339  _User_extensions_Acquire( &lock_context );
     340
     341  iter = the_thread->last_user_extensions_iterator;
     342
     343  while ( iter != NULL ) {
     344    _Chain_Iterator_destroy( &iter->Iterator );
     345    iter = iter->previous;
     346  }
     347
     348  _User_extensions_Release( &lock_context );
    265349}
    266350
  • cpukit/score/src/threadrestart.c

    r0a97ba5b r709f38a  
    9898
    9999  _User_extensions_Thread_delete( the_thread );
     100  _User_extensions_Destroy_iterators( the_thread );
    100101  _ISR_lock_Destroy( &the_thread->Keys.Lock );
    101102  _Scheduler_Node_destroy( _Scheduler_Get( the_thread ), the_thread );
     
    256257      executing->Life.state = THREAD_LIFE_NORMAL;
    257258
     259      _User_extensions_Destroy_iterators( executing );
    258260      _Thread_Load_environment( executing );
    259261      _Thread_Restart_self( executing );
  • cpukit/score/src/userextaddset.c

    r0a97ba5b r709f38a  
    2121
    2222#include <rtems/score/userextimpl.h>
    23 #include <rtems/score/objectimpl.h>
    2423#include <rtems/score/percpu.h>
    25 #include <rtems/score/sysstate.h>
    2624
    2725void _User_extensions_Add_set(
     
    2927)
    3028{
    31   _Assert(
    32     _Objects_Allocator_is_owner()
    33       || _System_state_Is_before_multitasking( _System_state_Get() )
     29  ISR_lock_Context lock_context;
     30
     31  _User_extensions_Acquire( &lock_context );
     32  _Chain_Append_unprotected(
     33    &_User_extensions_List.Active,
     34    &the_extension->Node
    3435  );
    35 
    36   _Chain_Append_unprotected( &_User_extensions_List, &the_extension->Node );
     36  _User_extensions_Release( &lock_context );
    3737
    3838  /*
  • cpukit/score/src/userextiterate.c

    r0a97ba5b r709f38a  
    88
    99/*
    10  * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
     10 * Copyright (c) 2012, 2016 embedded brains GmbH.  All rights reserved.
    1111 *
    1212 *  embedded brains GmbH
    13  *  Obere Lagerstr. 30
     13 *  Dornierstr. 4
    1414 *  82178 Puchheim
    1515 *  Germany
     
    2828#include <rtems/score/userextimpl.h>
    2929
    30 CHAIN_DEFINE_EMPTY( _User_extensions_List );
     30#include <pthread.h>
     31
     32User_extensions_List _User_extensions_List = {
     33  CHAIN_INITIALIZER_EMPTY( _User_extensions_List.Active ),
     34  CHAIN_ITERATOR_REGISTRY_INITIALIZER( _User_extensions_List.Iterators )
     35#if defined(RTEMS_SMP)
     36  ,
     37  ISR_LOCK_INITIALIZER( "User Extensions List" )
     38#endif
     39};
    3140
    3241void _User_extensions_Thread_create_visitor(
     
    140149
    141150void _User_extensions_Iterate(
    142   void                    *arg,
    143   User_extensions_Visitor  visitor
    144 )
    145 {
    146   Thread_Control *executing = _Thread_Get_executing();
    147   const User_extensions_Table *callouts_current =
    148     rtems_configuration_get_user_extension_table();
    149   const User_extensions_Table *callouts_end =
    150     callouts_current + rtems_configuration_get_number_of_initial_extensions();
    151   const Chain_Node *node;
    152   const Chain_Node *tail;
     151  void                     *arg,
     152  User_extensions_Visitor   visitor,
     153  Chain_Iterator_direction  direction
     154)
     155{
     156  Thread_Control              *executing;
     157  const User_extensions_Table *callouts_current;
     158  const User_extensions_Table *callouts_end;
     159  const Chain_Node            *end;
     160  Chain_Node                  *node;
     161  User_extensions_Iterator     iter;
     162  ISR_lock_Context             lock_context;
     163
     164  executing = _Thread_Get_executing();
     165
     166  callouts_current = rtems_configuration_get_user_extension_table();
     167  callouts_end = callouts_current
     168    + rtems_configuration_get_number_of_initial_extensions();
    153169
    154170  while ( callouts_current != callouts_end ) {
     
    158174  }
    159175
    160   node = _Chain_Immutable_first( &_User_extensions_List );
    161   tail = _Chain_Immutable_tail( &_User_extensions_List );
    162   while ( node != tail ) {
    163     const User_extensions_Control *extension =
    164       (const User_extensions_Control *) node;
    165 
    166     (*visitor)( executing, arg, &extension->Callouts );
    167 
    168     node = _Chain_Immutable_next( node );
    169   }
    170 }
     176  if ( direction == CHAIN_ITERATOR_FORWARD ) {
     177    end = _Chain_Immutable_tail( &_User_extensions_List.Active );
     178  } else {
     179    end = _Chain_Immutable_head( &_User_extensions_List.Active );
     180  }
     181
     182  _User_extensions_Acquire( &lock_context );
     183
     184  _Chain_Iterator_initialize(
     185    &_User_extensions_List.Active,
     186    &_User_extensions_List.Iterators,
     187    &iter.Iterator,
     188    direction
     189  );
     190
     191  if ( executing != NULL ) {
     192    iter.previous = executing->last_user_extensions_iterator;
     193    executing->last_user_extensions_iterator = &iter;
     194  }
     195
     196  while ( ( node = _Chain_Iterator_next( &iter.Iterator ) ) != end ) {
     197    const User_extensions_Control *extension;
     198
     199    _Chain_Iterator_set_position( &iter.Iterator, node );
     200
     201    _User_extensions_Release( &lock_context );
     202
     203    extension = (const User_extensions_Control *) node;
     204    ( *visitor )( executing, arg, &extension->Callouts );
     205
     206    _User_extensions_Acquire( &lock_context );
     207  }
     208
     209  if ( executing != NULL ) {
     210    executing->last_user_extensions_iterator = iter.previous;
     211  }
     212
     213  _Chain_Iterator_destroy( &iter.Iterator );
     214
     215  _User_extensions_Release( &lock_context );
     216}
  • cpukit/score/src/userextremoveset.c

    r0a97ba5b r709f38a  
    2121
    2222#include <rtems/score/userextimpl.h>
    23 #include <rtems/score/objectimpl.h>
    2423#include <rtems/score/percpu.h>
    2524
     
    2827)
    2928{
    30   _Assert( _Objects_Allocator_is_owner() );
     29  ISR_lock_Context lock_context;
    3130
     31  _User_extensions_Acquire( &lock_context );
     32  _Chain_Iterator_registry_update(
     33    &_User_extensions_List.Iterators,
     34    &the_extension->Node
     35  );
    3236  _Chain_Extract_unprotected( &the_extension->Node );
     37  _User_extensions_Release( &lock_context );
    3338
    3439  /*
  • testsuites/sptests/Makefile.am

    r0a97ba5b r709f38a  
    3434    spsem_err02 sptask_err01 spevent_err03 sptask_err03 sptask_err02 \
    3535    sptask_err04 spclock_err01
     36_SUBDIRS += spextensions01
    3637_SUBDIRS += spsysinit01
    3738if HAS_SMP
  • testsuites/sptests/configure.ac

    r0a97ba5b r709f38a  
    4747# Explicitly list all Makefiles here
    4848AC_CONFIG_FILES([Makefile
     49spextensions01/Makefile
    4950sptimerserver01/Makefile
    5051spsysinit01/Makefile
Note: See TracChangeset for help on using the changeset viewer.