diff options
author | Christian Mauderer <Christian.Mauderer@embedded-brains.de> | 2014-03-21 12:07:27 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-03-24 08:31:49 +0100 |
commit | 01f2337432d6a0ac92a022161370955172bc95fc (patch) | |
tree | 7c4f5ec7ba02b7fc4ac188ef39cf4247f7189e4f | |
parent | librpc: Use POSIX key instead of task variables (diff) | |
download | rtems-01f2337432d6a0ac92a022161370955172bc95fc.tar.bz2 |
posix: Prevent pthread_setspecific from returning EAGAIN.
The man-page for pthread_setspecific does not define the EAGAIN return value.
Further without this patch it was not possible to set keys that have been
already set a new value.
Add test for setting a new value to a already set key.
-rw-r--r-- | cpukit/posix/src/keysetspecific.c | 59 | ||||
-rw-r--r-- | testsuites/psxtests/psxkey05/init.c | 8 | ||||
-rw-r--r-- | testsuites/psxtests/psxkey05/psxkey05.doc | 1 | ||||
-rw-r--r-- | testsuites/psxtests/psxkey05/psxkey05.scn | 2 |
4 files changed, 46 insertions, 24 deletions
diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c index 9b2271ed97..3284991edb 100644 --- a/cpukit/posix/src/keysetspecific.c +++ b/cpukit/posix/src/keysetspecific.c @@ -37,37 +37,48 @@ int pthread_setspecific( POSIX_Keys_Control *the_key; Objects_Locations location; POSIX_Keys_Key_value_pair *value_pair_ptr; + RBTree_Node *p; + POSIX_Keys_Key_value_pair search_node; the_key = _POSIX_Keys_Get( key, &location ); switch ( location ) { case OBJECTS_LOCAL: - 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_id = _Thread_Executing->Object.id; - value_pair_ptr->value = value; - if ( _RBTree_Insert( &_POSIX_Keys_Key_value_lookup_tree, - &(value_pair_ptr->Key_value_lookup_node) ) ) { - _Freechain_Put( (Freechain_Control *)&_POSIX_Keys_Keypool, - (void *) value_pair_ptr ); - _Objects_Put( &the_key->Object ); - - return EAGAIN; + search_node.key = key; + search_node.thread_id = _Thread_Executing->Object.id; + p = _RBTree_Find( &_POSIX_Keys_Key_value_lookup_tree, + &search_node.Key_value_lookup_node ); + + if ( p ) { + value_pair_ptr = _RBTree_Container_of( p, + POSIX_Keys_Key_value_pair, + Key_value_lookup_node ); + + value_pair_ptr->value = value; + } 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_id = _Thread_Executing->Object.id; + value_pair_ptr->value = 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() */ + (void) _RBTree_Insert( &_POSIX_Keys_Key_value_lookup_tree, + &(value_pair_ptr->Key_value_lookup_node) ); + + /** 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 + ); } - /** 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 - ); - _Objects_Put( &the_key->Object ); return 0; diff --git a/testsuites/psxtests/psxkey05/init.c b/testsuites/psxtests/psxkey05/init.c index 90fcb60e0c..9fdd968d50 100644 --- a/testsuites/psxtests/psxkey05/init.c +++ b/testsuites/psxtests/psxkey05/init.c @@ -52,6 +52,14 @@ rtems_task Init( rtems_task_argument ignored ) value = pthread_getspecific( key2 ); rtems_test_assert( *value == Data_array[1] ); + puts( "Init - key1 pthread_setspecific - OK" ); + sc = pthread_setspecific( key1, &Data_array[1] ); + rtems_test_assert( !sc ); + + puts( "Init - key1 pthread_getspecific - OK" ); + value = pthread_getspecific( key1 ); + rtems_test_assert( *value == Data_array[1] ); + puts( "Init - pthread key1 delete - OK" ); sc = pthread_key_delete( key1 ); rtems_test_assert( sc == 0 ); diff --git a/testsuites/psxtests/psxkey05/psxkey05.doc b/testsuites/psxtests/psxkey05/psxkey05.doc index 9e0d04ff85..90158eb3e2 100644 --- a/testsuites/psxtests/psxkey05/psxkey05.doc +++ b/testsuites/psxtests/psxkey05/psxkey05.doc @@ -20,3 +20,4 @@ directives: concepts: + Ensure that key data's operation(create, set, get and delete) under multikeys work. ++ Ensure that key can be set to a new value. diff --git a/testsuites/psxtests/psxkey05/psxkey05.scn b/testsuites/psxtests/psxkey05/psxkey05.scn index 89127af466..9956501387 100644 --- a/testsuites/psxtests/psxkey05/psxkey05.scn +++ b/testsuites/psxtests/psxkey05/psxkey05.scn @@ -8,6 +8,8 @@ Init - key1 pthread_setspecific - OK Init - key2 pthread_setspecific - OK Init - key1 pthread_getspecific - OK Init - key2 pthread_getspecific - OK +Init - key1 pthread_setspecific - OK +Init - key1 pthread_getspecific - OK Init - pthread key1 delete - OK Init - pthread key2 delete - OK *** END OF TEST KEY 05 *** |