diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-04-13 06:48:58 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-04-18 08:20:16 +0200 |
commit | 709f38a97287ff1aa8e8c0668c2d066e711db87c (patch) | |
tree | e711e14275c58c0ee8483468fca804476db0fdbd /cpukit/score/src/userextiterate.c | |
parent | score: _User_extensions_Handler_initialization() (diff) | |
download | rtems-709f38a97287ff1aa8e8c0668c2d066e711db87c.tar.bz2 |
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.
Diffstat (limited to 'cpukit/score/src/userextiterate.c')
-rw-r--r-- | cpukit/score/src/userextiterate.c | 84 |
1 files changed, 65 insertions, 19 deletions
diff --git a/cpukit/score/src/userextiterate.c b/cpukit/score/src/userextiterate.c index beeee9570b..6cb877452b 100644 --- a/cpukit/score/src/userextiterate.c +++ b/cpukit/score/src/userextiterate.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * Copyright (c) 2012, 2016 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rtems@embedded-brains.de> @@ -27,7 +27,16 @@ #include <rtems/config.h> #include <rtems/score/userextimpl.h> -CHAIN_DEFINE_EMPTY( _User_extensions_List ); +#include <pthread.h> + +User_extensions_List _User_extensions_List = { + CHAIN_INITIALIZER_EMPTY( _User_extensions_List.Active ), + CHAIN_ITERATOR_REGISTRY_INITIALIZER( _User_extensions_List.Iterators ) +#if defined(RTEMS_SMP) + , + ISR_LOCK_INITIALIZER( "User Extensions List" ) +#endif +}; void _User_extensions_Thread_create_visitor( Thread_Control *executing, @@ -139,17 +148,24 @@ void _User_extensions_Thread_terminate_visitor( } void _User_extensions_Iterate( - void *arg, - User_extensions_Visitor visitor + void *arg, + User_extensions_Visitor visitor, + Chain_Iterator_direction direction ) { - Thread_Control *executing = _Thread_Get_executing(); - const User_extensions_Table *callouts_current = - rtems_configuration_get_user_extension_table(); - const User_extensions_Table *callouts_end = - callouts_current + rtems_configuration_get_number_of_initial_extensions(); - const Chain_Node *node; - const Chain_Node *tail; + Thread_Control *executing; + const User_extensions_Table *callouts_current; + const User_extensions_Table *callouts_end; + const Chain_Node *end; + Chain_Node *node; + User_extensions_Iterator iter; + ISR_lock_Context lock_context; + + executing = _Thread_Get_executing(); + + callouts_current = rtems_configuration_get_user_extension_table(); + callouts_end = callouts_current + + rtems_configuration_get_number_of_initial_extensions(); while ( callouts_current != callouts_end ) { (*visitor)( executing, arg, callouts_current ); @@ -157,14 +173,44 @@ void _User_extensions_Iterate( ++callouts_current; } - node = _Chain_Immutable_first( &_User_extensions_List ); - tail = _Chain_Immutable_tail( &_User_extensions_List ); - while ( node != tail ) { - const User_extensions_Control *extension = - (const User_extensions_Control *) node; + if ( direction == CHAIN_ITERATOR_FORWARD ) { + end = _Chain_Immutable_tail( &_User_extensions_List.Active ); + } else { + end = _Chain_Immutable_head( &_User_extensions_List.Active ); + } + + _User_extensions_Acquire( &lock_context ); + + _Chain_Iterator_initialize( + &_User_extensions_List.Active, + &_User_extensions_List.Iterators, + &iter.Iterator, + direction + ); + + if ( executing != NULL ) { + iter.previous = executing->last_user_extensions_iterator; + executing->last_user_extensions_iterator = &iter; + } + + while ( ( node = _Chain_Iterator_next( &iter.Iterator ) ) != end ) { + const User_extensions_Control *extension; + + _Chain_Iterator_set_position( &iter.Iterator, node ); + + _User_extensions_Release( &lock_context ); - (*visitor)( executing, arg, &extension->Callouts ); + extension = (const User_extensions_Control *) node; + ( *visitor )( executing, arg, &extension->Callouts ); - node = _Chain_Immutable_next( node ); + _User_extensions_Acquire( &lock_context ); } + + if ( executing != NULL ) { + executing->last_user_extensions_iterator = iter.previous; + } + + _Chain_Iterator_destroy( &iter.Iterator ); + + _User_extensions_Release( &lock_context ); } |