[rtems commit] posix: Delete key/value if value is set to NULL

Sebastian Huber sebh at rtems.org
Fri Dec 12 12:18:48 UTC 2014


Module:    rtems
Branch:    master
Commit:    172e953147da1d82bf5a6746b2fe6112a9509ad7
Changeset: http://git.rtems.org/rtems/commit/?id=172e953147da1d82bf5a6746b2fe6112a9509ad7

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Dec 12 13:16:11 2014 +0100

posix: Delete key/value if value is set to NULL

---

 cpukit/posix/include/rtems/posix/keyimpl.h |  13 ++++
 cpukit/posix/src/keyfreememory.c           |   5 +-
 cpukit/posix/src/keysetspecific.c          | 107 +++++++++++++++++++----------
 testsuites/psxtests/psxkey02/init.c        |  19 +++++
 4 files changed, 106 insertions(+), 38 deletions(-)

diff --git a/cpukit/posix/include/rtems/posix/keyimpl.h b/cpukit/posix/include/rtems/posix/keyimpl.h
index 1dcfb4e..a5c80d6 100644
--- a/cpukit/posix/include/rtems/posix/keyimpl.h
+++ b/cpukit/posix/include/rtems/posix/keyimpl.h
@@ -17,6 +17,7 @@
  */
 
 #include <rtems/posix/key.h>
+#include <rtems/score/chainimpl.h>
 #include <rtems/score/freechain.h>
 #include <rtems/score/objectimpl.h>
 #include <rtems/score/percpu.h>
@@ -186,6 +187,18 @@ RTEMS_INLINE_ROUTINE RBTree_Node *_POSIX_Keys_Find(
   );
 }
 
+RTEMS_INLINE_ROUTINE void _POSIX_Keys_Free_key_value_pair(
+  POSIX_Keys_Key_value_pair *key_value_pair
+)
+{
+  _RBTree_Extract(
+    &_POSIX_Keys_Key_value_lookup_tree,
+    &key_value_pair->Key_value_lookup_node
+  );
+  _Chain_Extract_unprotected( &key_value_pair->Key_values_per_thread_node );
+  _POSIX_Keys_Key_value_pair_free( key_value_pair );
+}
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/cpukit/posix/src/keyfreememory.c b/cpukit/posix/src/keyfreememory.c
index 9f03f6b..8ae7fd0 100644
--- a/cpukit/posix/src/keyfreememory.c
+++ b/cpukit/posix/src/keyfreememory.c
@@ -51,9 +51,8 @@ void _POSIX_Keys_Free_memory(
   p = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( iter );
   while ( iter != NULL && p->key == key_id ) {
     next = _RBTree_Next( iter, RBT_RIGHT );
-    _RBTree_Extract( &_POSIX_Keys_Key_value_lookup_tree, iter );
-    _Chain_Extract_unprotected( &p->Key_values_per_thread_node );
-    _POSIX_Keys_Key_value_pair_free( p );
+
+    _POSIX_Keys_Free_key_value_pair( p );
 
     iter = next;
     p = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( iter );
diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c
index 427fff3..20e3042 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 */
diff --git a/testsuites/psxtests/psxkey02/init.c b/testsuites/psxtests/psxkey02/init.c
index 5734db7..23a392b 100644
--- a/testsuites/psxtests/psxkey02/init.c
+++ b/testsuites/psxtests/psxkey02/init.c
@@ -30,6 +30,7 @@ rtems_task Init(rtems_task_argument ignored)
   bool                    ok;
   rtems_resource_snapshot snapshot;
   void                   *greedy;
+  void                   *value;
 
   TEST_BEGIN();
 
@@ -40,6 +41,24 @@ rtems_task Init(rtems_task_argument ignored)
   eno = pthread_key_create( &key1, NULL );
   rtems_test_assert( eno == 0 );
 
+  eno = pthread_setspecific( key1, (void *) 1 );
+  rtems_test_assert( eno == 0 );
+
+  value = pthread_getspecific( key1 );
+  rtems_test_assert( value == (void *) 1 );
+
+  eno = pthread_setspecific( key1, NULL );
+  rtems_test_assert( eno == 0 );
+
+  value = pthread_getspecific( key1 );
+  rtems_test_assert( value == NULL );
+
+  eno = pthread_setspecific( key1, NULL );
+  rtems_test_assert( eno == 0 );
+
+  value = pthread_getspecific( key1 );
+  rtems_test_assert( value == NULL );
+
   puts( "Init - pthread_key_create - EAGAIN" );
   eno = pthread_key_create( &key2, NULL );
   rtems_test_assert( eno == EAGAIN );




More information about the vc mailing list