diff options
Diffstat (limited to 'cpukit/posix/src/key.c')
-rw-r--r-- | cpukit/posix/src/key.c | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/cpukit/posix/src/key.c b/cpukit/posix/src/key.c index 55c6590051..5a0886b980 100644 --- a/cpukit/posix/src/key.c +++ b/cpukit/posix/src/key.c @@ -20,14 +20,20 @@ #endif #include <rtems/config.h> +#include <rtems/sysinit.h> #include <rtems/posix/keyimpl.h> #include <rtems/score/chainimpl.h> #include <rtems/score/objectimpl.h> +#include <rtems/score/userextimpl.h> #include <rtems/score/wkspace.h> +Objects_Information _POSIX_Keys_Information; + RBTREE_DEFINE_EMPTY( _POSIX_Keys_Key_value_lookup_tree ); +Freechain_Control _POSIX_Keys_Keypool; + /** * @brief This routine compares the rbtree node by comparing POSIX key first * and comparing thread id second. @@ -112,10 +118,63 @@ POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_pair_allocate( void ) ); } +static void _POSIX_Keys_Run_destructors( Thread_Control *thread ) +{ + Chain_Control *chain; + POSIX_Keys_Key_value_pair *iter, *next; + void *value; + void (*destructor) (void *); + POSIX_Keys_Control *the_key; + Objects_Locations location; + + chain = &thread->Key_Chain; + iter = (POSIX_Keys_Key_value_pair *) _Chain_First( chain ); + while ( !_Chain_Is_tail( chain, &iter->Key_values_per_thread_node ) ) { + next = (POSIX_Keys_Key_value_pair *) + _Chain_Next( &iter->Key_values_per_thread_node ); + + the_key = _POSIX_Keys_Get( iter->key, &location ); + _Assert( location == OBJECTS_LOCAL ); + + /** + * remove key from rbtree and chain. + * here Chain_Node *iter can be convert to POSIX_Keys_Key_value_pair *, + * because Chain_Node is the first member of POSIX_Keys_Key_value_pair + * structure. + */ + _RBTree_Extract( + &_POSIX_Keys_Key_value_lookup_tree, + &iter->Key_value_lookup_node + ); + _Chain_Extract_unprotected( &iter->Key_values_per_thread_node ); + + destructor = the_key->destructor; + value = iter->value; + + _POSIX_Keys_Key_value_pair_free( iter ); + + _Objects_Put( &the_key->Object ); + + /** + * run key value's destructor if destructor and value are both non-null. + */ + if ( destructor != NULL && value != NULL ) + (*destructor)( value ); + + iter = next; + } +} + +static User_extensions_Control _POSIX_Keys_Extensions = { + .Callouts = { + .thread_terminate = _POSIX_Keys_Run_destructors + } +}; + /** * @brief This routine performs the initialization necessary for this manager. */ -void _POSIX_Key_Manager_initialization(void) +static void _POSIX_Keys_Manager_initialization(void) { _Objects_Initialize_information( &_POSIX_Keys_Information, /* object information table */ @@ -135,4 +194,12 @@ void _POSIX_Key_Manager_initialization(void) ); _POSIX_Keys_Initialize_keypool(); + + _User_extensions_Add_API_set( &_POSIX_Keys_Extensions ); } + +RTEMS_SYSINIT_ITEM( + _POSIX_Keys_Manager_initialization, + RTEMS_SYSINIT_POSIX_KEYS, + RTEMS_SYSINIT_ORDER_MIDDLE +); |