[PATCH 1/3] posix: Prevent pthread_setspecific from returning EAGAIN.

Christian Mauderer christian.mauderer at embedded-brains.de
Fri Mar 21 11:07:27 UTC 2014


From: Christian Mauderer <Christian.Mauderer at embedded-brains.de>

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.
---
 cpukit/posix/src/keysetspecific.c         | 59 ++++++++++++++++++-------------
 testsuites/psxtests/psxkey05/init.c       |  8 +++++
 testsuites/psxtests/psxkey05/psxkey05.doc |  1 +
 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 c6e2d30..9afd35c 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 155a9f5..4cc1ed5 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 f4359d6..e27dddf 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 89127af..9956501 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 ***
-- 
1.8.4.5




More information about the devel mailing list