summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-04-13 06:48:58 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-04-18 08:20:16 +0200
commit709f38a97287ff1aa8e8c0668c2d066e711db87c (patch)
treee711e14275c58c0ee8483468fca804476db0fdbd /cpukit/score/src
parentscore: _User_extensions_Handler_initialization() (diff)
downloadrtems-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.c2
-rw-r--r--cpukit/score/src/userextaddset.c14
-rw-r--r--cpukit/score/src/userextiterate.c84
-rw-r--r--cpukit/score/src/userextremoveset.c9
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.