diff options
Diffstat (limited to 'cpukit/posix/src/keysetspecific.c')
-rw-r--r-- | cpukit/posix/src/keysetspecific.c | 107 |
1 files changed, 72 insertions, 35 deletions
diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c index 427fff3d03..20e3042b4d 100644 --- a/cpukit/posix/src/keysetspecific.c +++ b/cpukit/posix/src/keysetspecific.c @@ -25,6 +25,67 @@ #include <errno.h> +static int _POSIX_Keys_Set_value( + pthread_key_t key, + const void *value, + POSIX_Keys_Control *the_key, + Thread_Control *executing, + RBTree_Node *rb_node +) +{ + POSIX_Keys_Key_value_pair *key_value_pair; + + if ( rb_node != NULL ) { + key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( rb_node ); + key_value_pair->value = RTEMS_DECONST( void *, value ); + } else { + key_value_pair = _POSIX_Keys_Key_value_pair_allocate(); + + if ( key_value_pair == NULL ) { + return ENOMEM; + } + + key_value_pair->key = key; + key_value_pair->thread = executing; + key_value_pair->value = RTEMS_DECONST( void *, value ); + + /* + * The insert can only go wrong if the same node is already in a unique + * tree. This has been already checked with the _RBTree_Find(). + */ + _RBTree_Insert( + &_POSIX_Keys_Key_value_lookup_tree, + &key_value_pair->Key_value_lookup_node, + _POSIX_Keys_Key_value_compare, + true + ); + + _Chain_Append_unprotected( + &executing->Key_Chain, + &key_value_pair->Key_values_per_thread_node + ); + } + + return 0; +} + +static int _POSIX_Keys_Delete_value( + pthread_key_t key, + POSIX_Keys_Control *the_key, + RBTree_Node *rb_node +) +{ + + if ( rb_node != NULL ) { + POSIX_Keys_Key_value_pair *key_value_pair = + POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( rb_node ); + + _POSIX_Keys_Free_key_value_pair( key_value_pair ); + } + + return 0; +} + /* * 17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165 */ @@ -34,52 +95,28 @@ int pthread_setspecific( const void *value ) { - POSIX_Keys_Control *the_key; - Objects_Locations location; - POSIX_Keys_Key_value_pair *value_pair_ptr; - RBTree_Node *p; - Thread_Control *executing; + POSIX_Keys_Control *the_key; + Objects_Locations location; + Thread_Control *executing; + RBTree_Node *rb_node; + int eno; the_key = _POSIX_Keys_Get( key, &location ); switch ( location ) { case OBJECTS_LOCAL: executing = _Thread_Executing; - p = _POSIX_Keys_Find( key, executing ); - if ( p != NULL ) { - value_pair_ptr = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( p ); - value_pair_ptr->value = RTEMS_DECONST( void *, value ); + rb_node = _POSIX_Keys_Find( key, executing ); + + if ( value != NULL ) { + eno = _POSIX_Keys_Set_value( key, value, the_key, executing, rb_node ); } else { - value_pair_ptr = _POSIX_Keys_Key_value_pair_allocate(); - - if ( !value_pair_ptr ) { - _Objects_Put( &the_key->Object ); - - return ENOMEM; - } - - value_pair_ptr->key = key; - value_pair_ptr->thread = executing; - value_pair_ptr->value = RTEMS_DECONST( void *, value ); - /* The insert can only go wrong if the same node is already in a unique - * tree. This has been already checked with the _RBTree_Find() */ - _RBTree_Insert( - &_POSIX_Keys_Key_value_lookup_tree, - &value_pair_ptr->Key_value_lookup_node, - _POSIX_Keys_Key_value_compare, - true - ); - - /** append rb_node to the thread API extension's chain */ - _Chain_Append_unprotected( - &_Thread_Executing->Key_Chain, - &value_pair_ptr->Key_values_per_thread_node - ); + eno = _POSIX_Keys_Delete_value( key, the_key, rb_node ); } _Objects_Put( &the_key->Object ); - return 0; + return eno; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never happen */ |