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 | |
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')
-rw-r--r-- | cpukit/score/src/threadrestart.c | 2 | ||||
-rw-r--r-- | cpukit/score/src/userextaddset.c | 14 | ||||
-rw-r--r-- | cpukit/score/src/userextiterate.c | 84 | ||||
-rw-r--r-- | cpukit/score/src/userextremoveset.c | 9 |
4 files changed, 81 insertions, 28 deletions
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c index 59754a86fb..13b4365b35 100644 --- a/cpukit/score/src/threadrestart.c +++ b/cpukit/score/src/threadrestart.c @@ -97,6 +97,7 @@ static void _Thread_Free( Thread_Control *the_thread ) _Objects_Get_information_id( the_thread->Object.id ); _User_extensions_Thread_delete( the_thread ); + _User_extensions_Destroy_iterators( the_thread ); _ISR_lock_Destroy( &the_thread->Keys.Lock ); _Scheduler_Node_destroy( _Scheduler_Get( the_thread ), the_thread ); _ISR_lock_Destroy( &the_thread->Timer.Lock ); @@ -255,6 +256,7 @@ void _Thread_Life_action_handler( executing->Life.state = THREAD_LIFE_NORMAL; + _User_extensions_Destroy_iterators( executing ); _Thread_Load_environment( executing ); _Thread_Restart_self( executing ); RTEMS_UNREACHABLE(); diff --git a/cpukit/score/src/userextaddset.c b/cpukit/score/src/userextaddset.c index f34ad0072f..19bbd361e9 100644 --- a/cpukit/score/src/userextaddset.c +++ b/cpukit/score/src/userextaddset.c @@ -20,20 +20,20 @@ #endif #include <rtems/score/userextimpl.h> -#include <rtems/score/objectimpl.h> #include <rtems/score/percpu.h> -#include <rtems/score/sysstate.h> void _User_extensions_Add_set( User_extensions_Control *the_extension ) { - _Assert( - _Objects_Allocator_is_owner() - || _System_state_Is_before_multitasking( _System_state_Get() ) - ); + ISR_lock_Context lock_context; - _Chain_Append_unprotected( &_User_extensions_List, &the_extension->Node ); + _User_extensions_Acquire( &lock_context ); + _Chain_Append_unprotected( + &_User_extensions_List.Active, + &the_extension->Node + ); + _User_extensions_Release( &lock_context ); /* * If a switch handler is present, append it to the switch chain. 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 ); } diff --git a/cpukit/score/src/userextremoveset.c b/cpukit/score/src/userextremoveset.c index 5b3fdd1aea..b25cc344b4 100644 --- a/cpukit/score/src/userextremoveset.c +++ b/cpukit/score/src/userextremoveset.c @@ -20,16 +20,21 @@ #endif #include <rtems/score/userextimpl.h> -#include <rtems/score/objectimpl.h> #include <rtems/score/percpu.h> void _User_extensions_Remove_set ( User_extensions_Control *the_extension ) { - _Assert( _Objects_Allocator_is_owner() ); + ISR_lock_Context lock_context; + _User_extensions_Acquire( &lock_context ); + _Chain_Iterator_registry_update( + &_User_extensions_List.Iterators, + &the_extension->Node + ); _Chain_Extract_unprotected( &the_extension->Node ); + _User_extensions_Release( &lock_context ); /* * If a switch handler is present, remove it. |