<div dir="ltr">Yeah, of course!<br><br>On Feb 23, 2013, at 10:52 PM, Joel Sherrill <<a href="mailto:joel.sherrill@oarcorp.com">joel.sherrill@oarcorp.com</a>> wrote:<br>
<br>
> Some quick comments. Reviewing on my Nexus 7 and I would love a client that let's you respond inline.<br>
><br>
> Object field in the data structure should be named with capitalisation.<br>
><br>
OK<br>
<div class="im">> Look for "DESCRIPTION". convert this and similar blocks to Doxygen.<br>
><br>
</div>Sorry, I don't quite understand it, does it mean add a @brief … line above "DESCRIPTION"?<br>
<div class="im">> Why was the manager initialization method renamed keys manager initialization? Others are singular.<br>
><br>
</div>I see, I'll change it back to singular.<br>
<div class="im">> New files should follow style with @file comment block.<br>
><br>
</div>Does this apply to file in test cases? I find other files under testsuites/psxtests/ has no such block.<br>
<div class="im">> No need for comment about disable dispatching above call to Get to convert from Id to pointer.<br>
><br>
</div>OK<br>
thanks,<br>
Zhongwei Yao</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Feb 25, 2013 at 12:28 AM, Joel Sherrill <span dir="ltr"><<a href="mailto:joel.sherrill@oarcorp.com" target="_blank">joel.sherrill@oarcorp.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I appear to have deleted the message I meant to reply to. :(<br>
<br>
It may have been to me directly since I can't find it in the archive.<br>
<br>
Can it be resent?  Thanks.<br>
<br>
--joel<div class="HOEnZb"><div class="h5"><br>
<br>
On 2/23/2013 8:52 AM, Joel Sherrill wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Some quick comments. Reviewing on my Nexus 7 and I would love a client that let's you respond inline.<br>
<br>
Object field in the data structure should be named with capitalization.<br>
<br>
Look for "DESCRIPTION". convert this and similar blocks to Doxygen.<br>
<br>
Why was the manager initialization method renamed keys manager initialization? Others are singular.<br>
<br>
New files should follow style with @file comment block.<br>
<br>
No need for comment about disable dispatching above call to Get to convert from Id to pointer.<br>
<br>
Gedare Bloom <<a href="mailto:gedare@rtems.org" target="_blank">gedare@rtems.org</a>> wrote:<br>
<br>
<br>
From: Zhongwei Yao <<a href="mailto:ashi08104@gmail.com" target="_blank">ashi08104@gmail.com</a>><br>
<br>
The POSIX Key manager is reimplemented with a red-black tree to store<br>
the keys and values. This code was contributed as part of GSOC 2012.<br>
---<br>
  cpukit/posix/include/rtems/<u></u>posix/key.h       |   54 ++++++++++++++++-----<br>
  cpukit/posix/include/rtems/<u></u>posix/threadsup.h |   10 ++++<br>
  cpukit/posix/inline/rtems/<u></u>posix/key.inl      |    2 +-<br>
  cpukit/posix/src/key.c                       |   59 ++++++++++++++++++++++-<br>
  cpukit/posix/src/keycreate.c                 |   52 +-------------------<br>
  cpukit/posix/src/keydelete.c                 |    3 +-<br>
  cpukit/posix/src/<u></u>keyfreememory.c             |   35 ++++++++++++-<br>
  cpukit/posix/src/<u></u>keygetspecific.c            |   20 +++++---<br>
  cpukit/posix/src/<u></u>keyrundestructors.c         |   67 +++++++++++++++----------<br>
  cpukit/posix/src/<u></u>keysetspecific.c            |   34 ++++++++++---<br>
  cpukit/posix/src/pthread.c                   |    3 +<br>
  cpukit/sapi/src/posixapi.c                   |    2 +-<br>
  12 files changed, 229 insertions(+), 112 deletions(-)<br>
<br>
diff --git a/cpukit/posix/include/rtems/<u></u>posix/key.h b/cpukit/posix/include/rtems/<u></u>posix/key.h<br>
index 0bb1dbe..f045dad 100644<br>
--- a/cpukit/posix/include/rtems/<u></u>posix/key.h<br>
+++ b/cpukit/posix/include/rtems/<u></u>posix/key.h<br>
@@ -8,6 +8,7 @@<br>
   */<br>
<br>
  /*<br>
+ *  Copyright (c) 2012 Zhongwei Yao.<br>
   *  COPYRIGHT (c) 1989-2011.<br>
   *  On-Line Applications Research Corporation (OAR).<br>
   *<br>
@@ -20,6 +21,8 @@<br>
  #define _RTEMS_POSIX_KEY_H<br>
<br>
  #include <rtems/score/object.h><br>
+#include <rtems/score/rbtree.h><br>
+#include <rtems/score/chain.h><br>
<br>
  /**<br>
   * @defgroup POSIX_KEY POSIX Key<br>
@@ -34,32 +37,57 @@ extern "C" {<br>
  #endif<br>
<br>
  /**<br>
- * This is the data Structure used to manage a POSIX key.<br>
- *<br>
- * NOTE: The Values is a table indexed by the index portion of the<br>
- *       ID of the currently executing thread.<br>
+ * @brief The rbtree node used to manage a POSIX key and value.<br>
+ */<br>
+typedef struct {<br>
+  /** This field is the chain node structure. */<br>
+  Chain_Node ch_node;<br>
+  /** This field is the rbtree node structure. */<br>
+  RBTree_Node rb_node;<br>
+  /** This field is the POSIX key used as an rbtree key */<br>
+  pthread_key_t key;<br>
+  /** This field is the Thread id also used as an rbtree key */<br>
+  Objects_Id thread_id;<br>
+  /** This field points to the POSIX key value of specific thread */<br>
+  void *value;<br>
+ }  POSIX_Keys_Rbtree_node;<br>
+<br>
+/**<br>
+ * @brief The data structure used to manage a POSIX key.<br>
   */<br>
  typedef struct {<br>
     /** This field is the Object control structure. */<br>
-   Objects_Control     Object;<br>
-   /** This field points to the optional destructor method. */<br>
-   void              (*destructor)( void * );<br>
-   /** This field points to the values per thread. */<br>
-   void              **Values[ OBJECTS_APIS_LAST + 1 ];<br>
-}  POSIX_Keys_Control;<br>
+   Objects_Control     object;<br>
+   /** This field is the data destructor. */<br>
+   void (*destructor) (void *);<br>
+ }  POSIX_Keys_Control;<br>
<br>
  /**<br>
- * The following defines the information control block used to manage<br>
- * this class of objects.<br>
+ * @brief The information control block used to manage this class of objects.<br>
   */<br>
  POSIX_EXTERN Objects_Information  _POSIX_Keys_Information;<br>
<br>
  /**<br>
+ * @brief The rbtree control block used to manage all key values<br>
+ */<br>
+POSIX_EXTERN RBTree_Control _POSIX_Keys_Rbtree;<br>
+<br>
+/**<br>
   * @brief POSIX keys manager initialization.<br>
   *<br>
   * This routine performs the initialization necessary for this manager.<br>
   */<br>
-void _POSIX_Key_Manager_<u></u>initialization(void);<br>
+void _POSIX_Keys_Manager_<u></u>initialization(void);<br>
+<br>
+/**<br>
+ * @brief POSIX keys Red-Black tree node comparison.<br>
+ *<br>
+ * This routine compares the rbtree node<br>
+ */<br>
+int _POSIX_Keys_Rbtree_compare_<u></u>function(<br>
+  const RBTree_Node *node1,<br>
+  const RBTree_Node *node2<br>
+);<br>
<br>
  /**<br>
   * @brief Create thread-specific data POSIX key.<br>
diff --git a/cpukit/posix/include/rtems/<u></u>posix/threadsup.h b/cpukit/posix/include/rtems/<u></u>posix/threadsup.h<br>
index 80f64dc..d746ea8 100644<br>
--- a/cpukit/posix/include/rtems/<u></u>posix/threadsup.h<br>
+++ b/cpukit/posix/include/rtems/<u></u>posix/threadsup.h<br>
@@ -21,6 +21,7 @@<br>
  #include <sys/signal.h><br>
  #include <rtems/score/coresem.h><br>
  #include <rtems/score/tqdata.h><br>
+#include <rtems/score/chain.h><br>
<br>
  /**<br>
   *  @defgroup POSIX_THREAD POSIX Thread API Extension<br>
@@ -79,6 +80,15 @@ typedef struct {<br>
    /** This is the set of cancelation handlers. */<br>
    Chain_Control           Cancellation_Handlers;<br>
<br>
+  /**<br>
+   * This is the thread key value chain's control, which is used<br>
+   * to track all key value for specific thread, and when thread<br>
+   * exits, we can remove all key value for specific thread by<br>
+   * iterating this chain, or we have to search a whole rbtree,<br>
+   * which is inefficient.<br>
+   */<br>
+  Chain_Control           Key_Chain;<br>
+<br>
  } POSIX_API_Control;<br>
<br>
  /**<br>
diff --git a/cpukit/posix/inline/rtems/<u></u>posix/key.inl b/cpukit/posix/inline/rtems/<u></u>posix/key.inl<br>
index ce5601b..9469580 100644<br>
--- a/cpukit/posix/inline/rtems/<u></u>posix/key.inl<br>
+++ b/cpukit/posix/inline/rtems/<u></u>posix/key.inl<br>
@@ -45,7 +45,7 @@ RTEMS_INLINE_ROUTINE void _POSIX_Keys_Free (<br>
    POSIX_Keys_Control *the_key<br>
  )<br>
  {<br>
-  _Objects_Free( &_POSIX_Keys_Information, &the_key->Object );<br>
+  _Objects_Free( &_POSIX_Keys_Information, &the_key->object );<br>
  }<br>
<br>
  /**<br>
diff --git a/cpukit/posix/src/key.c b/cpukit/posix/src/key.c<br>
index 6eace26..82c11af 100644<br>
--- a/cpukit/posix/src/key.c<br>
+++ b/cpukit/posix/src/key.c<br>
@@ -29,6 +29,57 @@<br>
  #include <rtems/score/thread.h><br>
  #include <rtems/score/wkspace.h><br>
  #include <rtems/posix/key.h><br>
+#include <rtems/score/rbtree.h><br>
+<br>
+/*<br>
+ * _POSIX_Keys_Rbtree_compare_<u></u>function<br>
+ *<br>
+ * DESCRIPTION:<br>
+ * This routine compares the rbtree node<br>
+ * by comparing POSIX key first and comparing thread id second.<br>
+ * And if either of the input nodes's thread_id member is 0, then<br>
+ * it will only compare the pthread_key_t member. That is when we<br>
+ * pass thread_id = 0 node as a search node, the search is done only<br>
+ * by pthread_key_t.<br>
+ *<br>
+ * Input parameters: two rbtree node<br>
+ *<br>
+ * Output parameters: return positive if first node<br>
+ * has higher key than second, negative if lower, 0 if equal,<br>
+ * and for all the thread id is unique, then return 0 is impossible<br>
+ */<br>
+<br>
+int _POSIX_Keys_Rbtree_compare_<u></u>function(<br>
+  const RBTree_Node *node1,<br>
+  const RBTree_Node *node2<br>
+)<br>
+{<br>
+  pthread_key_t key1 = _RBTree_Container_of(node1,<br>
+                                           POSIX_Keys_Rbtree_node,<br>
+                                           rb_node)->key;<br>
+  pthread_key_t key2 = _RBTree_Container_of(node2,<br>
+                                           POSIX_Keys_Rbtree_node,<br>
+                                           rb_node)->key;<br>
+<br>
+  Objects_Id thread_id1 = _RBTree_Container_of(node1,<br>
+                                              POSIX_Keys_Rbtree_node,<br>
+                                              rb_node)->thread_id;<br>
+  Objects_Id thread_id2 = _RBTree_Container_of(node2,<br>
+                                              POSIX_Keys_Rbtree_node,<br>
+                                              rb_node)->thread_id;<br>
+<br>
+  int diff = key1 - key2;<br>
+  if ( diff )<br>
+    return diff;<br>
+  /**<br>
+   * if thread_id1 or thread_id2 equals to 0, only key1 and key2 is valued.<br>
+   * it enables us search node only by pthread_key_t type key.<br>
+   */<br>
+  if ( thread_id1 && thread_id2 )<br>
+    return thread_id1 - thread_id2;<br>
+  return 0;<br>
+}<br>
+<br>
<br>
  /*<br>
   *  _POSIX_Key_Manager_<u></u>initialization<br>
@@ -42,7 +93,7 @@<br>
   *  Output parameters:  NONE<br>
   */<br>
<br>
-void _POSIX_Key_Manager_<u></u>initialization(void)<br>
+void _POSIX_Keys_Manager_<u></u>initialization(void)<br>
  {<br>
    _Objects_Initialize_<u></u>information(<br>
      &_POSIX_Keys_Information,   /* object information table */<br>
@@ -60,4 +111,10 @@ void _POSIX_Key_Manager_<u></u>initialization(void)<br>
      NULL                        /* Proxy extraction support callout */<br>
  #endif<br>
    );<br>
+<br>
+  _RBTree_Initialize_empty(<br>
+    &_POSIX_Keys_Rbtree,<br>
+    _POSIX_Keys_Rbtree_compare_<u></u>function,<br>
+    true<br>
+  );<br>
  }<br>
diff --git a/cpukit/posix/src/keycreate.c b/cpukit/posix/src/keycreate.c<br>
index b41b590..09778c3 100644<br>
--- a/cpukit/posix/src/keycreate.c<br>
+++ b/cpukit/posix/src/keycreate.c<br>
@@ -37,10 +37,6 @@ int pthread_key_create(<br>
  )<br>
  {<br>
    POSIX_Keys_Control  *the_key;<br>
-  void                *table;<br>
-  uint32_t             the_api;<br>
-  uint32_t             bytes_to_allocate;<br>
-<br>
<br>
    _Thread_Disable_dispatch();<br>
<br>
@@ -52,52 +48,8 @@ int pthread_key_create(<br>
    }<br>
<br>
    the_key->destructor = destructor;<br>
-<br>
-  /*<br>
-   *  This is a bit more complex than one might initially expect because<br>
-   *  APIs are optional.<br>
-   *<br>
-   *  NOTE: Currently RTEMS Classic API tasks are always enabled.<br>
-   */<br>
-  for ( the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++ ) {<br>
-    the_key->Values[ the_api ] = NULL;<br>
-<br>
-    #if defined(RTEMS_DEBUG)<br>
-      /*<br>
-       *  Since the removal of ITRON, this cannot occur.<br>
-       */<br>
-      if ( !_Objects_Information_table[ the_api ] )<br>
-       continue;<br>
-<br>
-      /*<br>
-       * Currently all managers are installed if the API is installed.<br>
-       * This would be a horrible implementation error.<br>
-       */<br>
-      if (_Objects_Information_table[ the_api ][ 1 ] == NULL )<br>
-       _Internal_error_Occurred(<br>
-         INTERNAL_ERROR_CORE,<br>
-         true,<br>
-         INTERNAL_ERROR_IMPLEMENTATION_<u></u>KEY_CREATE_INCONSISTENCY<br>
-       );<br>
-    #endif<br>
-<br>
-    bytes_to_allocate = sizeof( void * ) *<br>
-      (_Objects_Information_table[ the_api ][ 1 ]->maximum + 1);<br>
-    table = _Workspace_Allocate( bytes_to_allocate );<br>
-    if ( !table ) {<br>
-      _POSIX_Keys_Free_memory( the_key );<br>
-<br>
-      _POSIX_Keys_Free( the_key );<br>
-      _Thread_Enable_dispatch();<br>
-      return ENOMEM;<br>
-    }<br>
-<br>
-    the_key->Values[ the_api ] = table;<br>
-    memset( table, '\0', bytes_to_allocate );<br>
-  }<br>
-<br>
-  _Objects_Open_u32( &_POSIX_Keys_Information, &the_key->Object, 0 );<br>
-  *key = the_key->Object.id;<br>
+  _Objects_Open_u32( &_POSIX_Keys_Information, &the_key->object, 0 );<br>
+  *key = the_key-><a href="http://object.id" target="_blank">object.id</a>;<br>
    _Thread_Enable_dispatch();<br>
    return 0;<br>
  }<br>
diff --git a/cpukit/posix/src/keydelete.c b/cpukit/posix/src/keydelete.c<br>
index 5ef6261..3f594bd 100644<br>
--- a/cpukit/posix/src/keydelete.c<br>
+++ b/cpukit/posix/src/keydelete.c<br>
@@ -42,8 +42,6 @@ int pthread_key_delete(<br>
    switch ( location ) {<br>
<br>
      case OBJECTS_LOCAL:<br>
-      _Objects_Close( &_POSIX_Keys_Information, &the_key->Object );<br>
-<br>
        _POSIX_Keys_Free_memory( the_key );<br>
<br>
        /*<br>
@@ -51,6 +49,7 @@ int pthread_key_delete(<br>
         *         of the application to free the memory.<br>
         */<br>
        _POSIX_Keys_Free( the_key );<br>
+      _Objects_Close( &_POSIX_Keys_Information, &the_key->object );<br>
        _Thread_Enable_dispatch();<br>
        return 0;<br>
<br>
diff --git a/cpukit/posix/src/<u></u>keyfreememory.c b/cpukit/posix/src/<u></u>keyfreememory.c<br>
index f71af4f..e01e6e9 100644<br>
--- a/cpukit/posix/src/<u></u>keyfreememory.c<br>
+++ b/cpukit/posix/src/<u></u>keyfreememory.c<br>
@@ -21,14 +21,43 @@<br>
  #include <rtems/system.h><br>
  #include <rtems/score/thread.h><br>
  #include <rtems/score/wkspace.h><br>
+#include <rtems/score/rbtree.h><br>
  #include <rtems/posix/key.h><br>
<br>
  void _POSIX_Keys_Free_memory(<br>
    POSIX_Keys_Control *the_key<br>
  )<br>
  {<br>
-  uint32_t            the_api;<br>
+  POSIX_Keys_Rbtree_node search_node;<br>
+  POSIX_Keys_Rbtree_node *p;<br>
+  RBTree_Node *iter, *next;<br>
<br>
-  for ( the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++ )<br>
-    _Workspace_Free( the_key->Values[ the_api ] );<br>
+  search_node.key = the_key-><a href="http://object.id" target="_blank">object.id</a>;<br>
+  search_node.thread_id = 0;<br>
+  iter = _RBTree_Find_unprotected( &_POSIX_Keys_Rbtree, &search_node.rb_node);<br>
+  if ( !iter )<br>
+    return;<br>
+  /**<br>
+   * find the smallest thread_id node in the rbtree.<br>
+   */<br>
+  next = _RBTree_Next_unprotected( iter, RBT_LEFT );<br>
+  p = _RBTree_Container_of( next, POSIX_Keys_Rbtree_node, rb_node );<br>
+  while ( p->key == the_key-><a href="http://object.id" target="_blank">object.id</a>) {<br>
+    iter = next;<br>
+    next = _RBTree_Next_unprotected( iter, RBT_LEFT );<br>
+    p = _RBTree_Container_of( next, POSIX_Keys_Rbtree_node, rb_node );<br>
+  }<br>
+<br>
+  /**<br>
+   * delete all nodes belongs to the_key from the rbtree and chain.<br>
+   */<br>
+  p = _RBTree_Container_of( iter, POSIX_Keys_Rbtree_node, rb_node );<br>
+  while ( p->key == the_key-><a href="http://object.id" target="_blank">object.id</a> ) {<br>
+    next = _RBTree_Next_unprotected( iter, RBT_RIGHT );<br>
+    _RBTree_Extract_unprotected( &_POSIX_Keys_Rbtree, iter );<br>
+    _Chain_Extract_unprotected( &p->ch_node );<br>
+    _Workspace_Free( p );<br>
+    iter = next;<br>
+    p = _RBTree_Container_of( iter, POSIX_Keys_Rbtree_node, rb_node );<br>
+  }<br>
  }<br>
diff --git a/cpukit/posix/src/<u></u>keygetspecific.c b/cpukit/posix/src/<u></u>keygetspecific.c<br>
index debad83..39c0fcc 100644<br>
--- a/cpukit/posix/src/<u></u>keygetspecific.c<br>
+++ b/cpukit/posix/src/<u></u>keygetspecific.c<br>
@@ -26,6 +26,7 @@<br>
  #include <rtems/system.h><br>
  #include <rtems/score/thread.h><br>
  #include <rtems/score/wkspace.h><br>
+#include <rtems/score/rbtree.h><br>
  #include <rtems/posix/key.h><br>
<br>
  /*<br>
@@ -36,19 +37,24 @@ void *pthread_getspecific(<br>
    pthread_key_t  key<br>
  )<br>
  {<br>
-  register POSIX_Keys_Control *the_key;<br>
-  uint32_t                     api;<br>
-  uint32_t                     index;<br>
    Objects_Locations            location;<br>
+  POSIX_Keys_Rbtree_node       search_node;<br>
+  RBTree_Node                 *p;<br>
    void                        *key_data;<br>
<br>
-  the_key = _POSIX_Keys_Get( key, &location );<br>
+  _POSIX_Keys_Get( key, &location );<br>
    switch ( location ) {<br>
<br>
      case OBJECTS_LOCAL:<br>
-      api      = _Objects_Get_API( _Thread_Executing->Object.id );<br>
-      index    = _Objects_Get_index( _Thread_Executing->Object.id );<br>
-      key_data = (void *) the_key->Values[ api ][ index ];<br>
+      search_node.key = key;<br>
+      search_node.thread_id = _Thread_Executing->Object.id;<br>
+      p = _RBTree_Find_unprotected( &_POSIX_Keys_Rbtree, &search_node.rb_node);<br>
+      key_data = NULL;<br>
+      if ( p ) {<br>
+        key_data = _RBTree_Container_of( p,<br>
+                                        POSIX_Keys_Rbtree_node,<br>
+                                        rb_node )->value;<br>
+      }<br>
        _Thread_Enable_dispatch();<br>
        return key_data;<br>
<br>
diff --git a/cpukit/posix/src/<u></u>keyrundestructors.c b/cpukit/posix/src/<u></u>keyrundestructors.c<br>
index 9f48888..db31d2b 100644<br>
--- a/cpukit/posix/src/<u></u>keyrundestructors.c<br>
+++ b/cpukit/posix/src/<u></u>keyrundestructors.c<br>
@@ -23,7 +23,10 @@<br>
  #include <rtems/system.h><br>
  #include <rtems/score/object.h><br>
  #include <rtems/score/thread.h><br>
+#include <rtems/score/wkspace.h><br>
+#include <rtems/score/chain.h><br>
  #include <rtems/posix/key.h><br>
+#include <rtems/posix/threadsup.h><br>
<br>
  /*<br>
   *  _POSIX_Keys_Run_destructors<br>
@@ -38,36 +41,46 @@ void _POSIX_Keys_Run_destructors(<br>
    Thread_Control *thread<br>
  )<br>
  {<br>
-  Objects_Maximum thread_index = _Objects_Get_index( thread->Object.id );<br>
-  Objects_APIs thread_api = _Objects_Get_API( thread->Object.id );<br>
-  bool done = false;<br>
+  Chain_Control *chain;<br>
+  Chain_Node *iter, *next;<br>
+  void *value;<br>
+  void (*destructor) (void *);<br>
+  POSIX_Keys_Control *the_key;<br>
+  Objects_Locations location;<br>
<br>
-  /*<br>
-   *  The standard allows one to avoid a potential infinite loop and limit the<br>
-   *  number of iterations.  An infinite loop may happen if destructors set<br>
-   *  thread specific data.  This can be considered dubious.<br>
-   *<br>
-   *  Reference: 17.1.1.2 P1003.1c/Draft 10, p. 163, line 99.<br>
-   */<br>
-  while ( !done ) {<br>
-    Objects_Maximum index = 0;<br>
-    Objects_Maximum max = _POSIX_Keys_Information.<u></u>maximum;<br>
+  _Thread_Disable_dispatch();<br>
<br>
-    done = true;<br>
+  chain = &((POSIX_API_Control *)\<br>
+           thread->API_Extensions[ THREAD_API_POSIX ])->Key_Chain;<br>
+  iter = _Chain_First( chain );<br>
+  while ( !_Chain_Is_tail( chain, iter ) ) {<br>
+    next = _Chain_Next( iter );<br>
+    /**<br>
+     * remove key from rbtree and chain.<br>
+     * here Chain_Node *iter can be convert to POSIX_Keys_Rbtree_node *,<br>
+     * because Chain_Node is the first member of POSIX_Keys_Rbtree_node<br>
+     * structure.<br>
+     */<br>
+    _RBTree_Extract_unprotected( &_POSIX_Keys_Rbtree,<br>
+                                &((POSIX_Keys_Rbtree_node *)iter)->rb_node );<br>
+    _Chain_Extract_unprotected( iter );<br>
<br>
-    for ( index = 1 ; index <= max ; ++index ) {<br>
-      POSIX_Keys_Control *key = (POSIX_Keys_Control *)<br>
-        _POSIX_Keys_Information.local_<u></u>table [ index ];<br>
+    /**<br>
+     * run key value's destructor if destructor and value are both non-null.<br>
+     */<br>
+    the_key = _POSIX_Keys_Get( ((POSIX_Keys_Rbtree_node *)iter)->key,<br>
+                              &location);<br>
+    destructor = the_key->destructor;<br>
+    value = ((POSIX_Keys_Rbtree_node *)iter)->value;<br>
+    if ( destructor != NULL && value != NULL )<br>
+      (*destructor)( value );<br>
+    /**<br>
+     * disable dispatch is nested here<br>
+     */<br>
+    _Thread_Enable_dispatch();<br>
<br>
-      if ( key != NULL && key->destructor != NULL ) {<br>
-        void *value = key->Values [ thread_api ][ thread_index ];<br>
-<br>
-        if ( value != NULL ) {<br>
-          key->Values [ thread_api ][ thread_index ] = NULL;<br>
-          (*key->destructor)( value );<br>
-          done = false;<br>
-        }<br>
-      }<br>
-    }<br>
+    _Workspace_Free( (POSIX_Keys_Rbtree_node *)iter );<br>
+    iter = next;<br>
    }<br>
+  _Thread_Enable_dispatch();<br>
  }<br>
diff --git a/cpukit/posix/src/<u></u>keysetspecific.c b/cpukit/posix/src/<u></u>keysetspecific.c<br>
index b25e44c..132061a 100644<br>
--- a/cpukit/posix/src/<u></u>keysetspecific.c<br>
+++ b/cpukit/posix/src/<u></u>keysetspecific.c<br>
@@ -26,7 +26,9 @@<br>
  #include <rtems/system.h><br>
  #include <rtems/score/thread.h><br>
  #include <rtems/score/wkspace.h><br>
+#include <rtems/score/rbtree.h><br>
  #include <rtems/posix/key.h><br>
+#include <rtems/posix/threadsup.h><br>
<br>
  /*<br>
   *  17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165<br>
@@ -37,18 +39,36 @@ int pthread_setspecific(<br>
    const void    *value<br>
  )<br>
  {<br>
-  register POSIX_Keys_Control *the_key;<br>
-  uint32_t                     api;<br>
-  uint32_t                     index;<br>
    Objects_Locations            location;<br>
+  POSIX_Keys_Rbtree_node      *rb_node;<br>
+  POSIX_API_Control           *api;<br>
<br>
-  the_key = _POSIX_Keys_Get( key, &location );<br>
+  /** _POSIX_Keys_Get() would call _Thread_Disable_dispatch() implicitly*/<br>
+  _POSIX_Keys_Get( key, &location );<br>
    switch ( location ) {<br>
<br>
      case OBJECTS_LOCAL:<br>
-      api   = _Objects_Get_API( _Thread_Executing->Object.id );<br>
-      index = _Objects_Get_index( _Thread_Executing->Object.id );<br>
-      the_key->Values[ api ][ index ] = (void *) value;<br>
+      rb_node = _Workspace_Allocate( sizeof( POSIX_Keys_Rbtree_node ) );<br>
+      if ( !rb_node ) {<br>
+        _Thread_Enable_dispatch();<br>
+        return ENOMEM;<br>
+      }<br>
+<br>
+      rb_node->key = key;<br>
+      rb_node->thread_id = _Thread_Executing->Object.id;<br>
+      rb_node->value = value;<br>
+      if (_RBTree_Insert_unprotected( &_POSIX_Keys_Rbtree,<br>
+                                     &(rb_node->rb_node) ) ) {<br>
+          _Workspace_Free( rb_node );<br>
+          _Thread_Enable_dispatch();<br>
+          return EAGAIN;<br>
+        }<br>
+<br>
+      /** append rb_node to the thread API extension's chain */<br>
+      api = (POSIX_API_Control *)\<br>
+       (_Thread_Executing->API_<u></u>Extensions[THREAD_API_POSIX]);<br>
+      _Chain_Append_unprotected( &api->Key_Chain, &rb_node->ch_node );<br>
+<br>
        _Thread_Enable_dispatch();<br>
        return 0;<br>
<br>
diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c<br>
index 873449a..0ea44f1 100644<br>
--- a/cpukit/posix/src/pthread.c<br>
+++ b/cpukit/posix/src/pthread.c<br>
@@ -234,6 +234,9 @@ static bool _POSIX_Threads_Create_<u></u>extension(<br>
      created<br>
    );<br>
<br>
+  /** initialize thread's key vaule node chain */<br>
+  _Chain_Initialize_empty( &api->Key_Chain );<br>
+<br>
    return true;<br>
  }<br>
<br>
diff --git a/cpukit/sapi/src/posixapi.c b/cpukit/sapi/src/posixapi.c<br>
index 3f65442..b5e62c2 100644<br>
--- a/cpukit/sapi/src/posixapi.c<br>
+++ b/cpukit/sapi/src/posixapi.c<br>
@@ -64,7 +64,7 @@ void _POSIX_API_Initialize(void)<br>
    _POSIX_signals_Manager_<u></u>Initialization();<br>
    _POSIX_Threads_Manager_<u></u>initialization();<br>
    _POSIX_Condition_variables_<u></u>Manager_initialization();<br>
-  _POSIX_Key_Manager_<u></u>initialization();<br>
+  _POSIX_Keys_Manager_<u></u>initialization();<br>
    _POSIX_Mutex_Manager_<u></u>initialization();<br>
    _POSIX_Message_queue_Manager_<u></u>initialization();<br>
    _POSIX_Semaphore_Manager_<u></u>initialization();<br>
--<br>
1.7.1<br>
<br>
______________________________<u></u>_________________<br>
rtems-devel mailing list<br>
<a href="mailto:rtems-devel@rtems.org" target="_blank">rtems-devel@rtems.org</a><br>
<a href="http://www.rtems.org/mailman/listinfo/rtems-devel" target="_blank">http://www.rtems.org/mailman/<u></u>listinfo/rtems-devel</a><br>
<br>
______________________________<u></u>_________________<br>
rtems-devel mailing list<br>
<a href="mailto:rtems-devel@rtems.org" target="_blank">rtems-devel@rtems.org</a><br>
<a href="http://www.rtems.org/mailman/listinfo/rtems-devel" target="_blank">http://www.rtems.org/mailman/<u></u>listinfo/rtems-devel</a><br>
</blockquote>
<br>
<br></div></div><span class="HOEnZb"><font color="#888888">
-- <br>
Joel Sherrill, Ph.D.             Director of Research & Development<br>
joel.sherrill@OARcorp.com        On-Line Applications Research<br>
Ask me about RTEMS: a free RTOS  Huntsville AL 35805<br>
Support Available                <a href="tel:%28256%29%20722-9985" value="+12567229985" target="_blank">(256) 722-9985</a></font></span><div class="HOEnZb"><div class="h5"><br>
<br>
______________________________<u></u>_________________<br>
rtems-devel mailing list<br>
<a href="mailto:rtems-devel@rtems.org" target="_blank">rtems-devel@rtems.org</a><br>
<a href="http://www.rtems.org/mailman/listinfo/rtems-devel" target="_blank">http://www.rtems.org/mailman/<u></u>listinfo/rtems-devel</a><br>
</div></div></blockquote></div><br></div>