<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Feb 22, 2013 at 10:38 PM, Gedare Bloom <span dir="ltr"><<a href="mailto:gedare@rtems.org" target="_blank">gedare@rtems.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I pulled this from github using the latest pull request you sent.<br>
Maybe you posted an updated patch somewhere? Check to make sure there<br>
are no other major issues to deal with and let me know if there are<br>
any updates for me to pull. I will be looking to commit this work<br>
soon. I will figure out the confdefs.h issue myself.<br></blockquote><div>I've checked there no other major issues to deal with. And the updated patches(without fixing confdefs.h issue) are attached.<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="HOEnZb"><div class="h5"><br>
On Thu, Feb 21, 2013 at 10:19 PM, Ashi <<a href="mailto:ashi08104@gmail.com">ashi08104@gmail.com</a>> wrote:<br>
> Gedare, I feel this patch is a little old than my actually work, because<br>
> some line I have removed before(like the "TODO" line), I haven't figured out<br>
> which commit this patch is based.<br>
> Anyway, I've updated according your comments.<br>
><br>
><br>
> On Sat, Feb 9, 2013 at 9:15 PM, Gedare Bloom <<a href="mailto:gedare@rtems.org">gedare@rtems.org</a>> wrote:<br>
>><br>
>> On Thu, Feb 7, 2013 at 9:20 PM, Gedare Bloom <<a href="mailto:gedare@rtems.org">gedare@rtems.org</a>> wrote:<br>
>> > From: Zhongwei Yao <<a href="mailto:ashi08104@gmail.com">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/posix/key.h       |   56<br>
>> > ++++++++++++++++-----<br>
>> >  cpukit/posix/include/rtems/posix/threadsup.h |    4 ++<br>
>> >  cpukit/posix/inline/rtems/posix/key.inl      |    2 +-<br>
>> >  cpukit/posix/src/key.c                       |   52<br>
>> > +++++++++++++++++++-<br>
>> >  cpukit/posix/src/keycreate.c                 |   53<br>
>> > +-------------------<br>
>> >  cpukit/posix/src/keydelete.c                 |    4 +-<br>
>> >  cpukit/posix/src/keyfreememory.c             |   35 ++++++++++++-<br>
>> >  cpukit/posix/src/keygetspecific.c            |   21 +++++---<br>
>> >  cpukit/posix/src/keyrundestructors.c         |   68<br>
>> > +++++++++++++++-----------<br>
>> >  cpukit/posix/src/keysetspecific.c            |   32 +++++++++---<br>
>> >  cpukit/posix/src/pthread.c                   |    3 +<br>
>> >  cpukit/sapi/src/posixapi.c                   |    2 +-<br>
>> >  12 files changed, 216 insertions(+), 116 deletions(-)<br>
>> ><br>
>> > diff --git a/cpukit/posix/include/rtems/posix/key.h<br>
>> > b/cpukit/posix/include/rtems/posix/key.h<br>
>> > index 0bb1dbe..80e534b 100644<br>
>> > --- a/cpukit/posix/include/rtems/posix/key.h<br>
>> > +++ b/cpukit/posix/include/rtems/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 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>
>> > +  /** 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>
>> > - * The following defines the information control block used to manage<br>
>> > - * this class of objects.<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 is the data destructor. */<br>
>> > +   void (*destructor) (void *);<br>
>> > + }  POSIX_Keys_Control;<br>
>> > +<br>
>> > +/**<br>
>> > + * @brief The information control block used to manage this class of<br>
>> > 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_initialization(void);<br>
>> > +void _POSIX_Keys_Manager_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_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/posix/threadsup.h<br>
>> > b/cpukit/posix/include/rtems/posix/threadsup.h<br>
>> > index 80f64dc..f47a7d4 100644<br>
>> > --- a/cpukit/posix/include/rtems/posix/threadsup.h<br>
>> > +++ b/cpukit/posix/include/rtems/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>
>> > @@ -78,6 +79,9 @@ typedef struct {<br>
>> >    int                     cancelation_requested;<br>
>> >    /** This is the set of cancelation handlers. */<br>
>> >    Chain_Control           Cancellation_Handlers;<br>
>> > +<br>
>> > +  /** This is the thread key value chain's control */<br>
>> > +  Chain_Control          the_chain;<br>
>> ><br>
>> Perhaps a more descriptive variable name? Also the name the_chain<br>
>> should be in initial capitals because it is an aggregate structure.<br>
>> Finally, we should make a note of why this chain exists.  it is<br>
>><br>
>> needed to iterate through the keys of a given thread when destroying<br>
>> the thread.<br>
>><br>
> Yeah, that's the point. I've add a little more detail in comment.<br>
>><br>
>> >  } POSIX_API_Control;<br>
>> ><br>
>> > diff --git a/cpukit/posix/inline/rtems/posix/key.inl<br>
>> > b/cpukit/posix/inline/rtems/posix/key.inl<br>
>> > index ce5601b..9469580 100644<br>
>> > --- a/cpukit/posix/inline/rtems/posix/key.inl<br>
>> > +++ b/cpukit/posix/inline/rtems/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..b0a1f86 100644<br>
>> > --- a/cpukit/posix/src/key.c<br>
>> > +++ b/cpukit/posix/src/key.c<br>
>> > @@ -29,6 +29,49 @@<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_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_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, rb_node)->key;<br>
>> > +  pthread_key_t key2 = _RBTree_Container_of(node2,<br>
>> > POSIX_Keys_Rbtree_node, rb_node)->key;<br>
>> > +<br>
>> > +  Objects_Id thread_id1 = _RBTree_Container_of(node1,<br>
>> > POSIX_Keys_Rbtree_node, rb_node)->thread_id;<br>
>> > +  Objects_Id thread_id2 = _RBTree_Container_of(node2,<br>
>> > POSIX_Keys_Rbtree_node, rb_node)->thread_id;<br>
>> > +<br>
>> These lines are too long (>80 char) and need to be broken. I think<br>
>> there are a few others in this patch too.<br>
><br>
> I remember there is a  format check script, which I also have run it my<br>
> code...<br>
>><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<br>
>> > 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_initialization<br>
>> > @@ -42,7 +85,7 @@<br>
>> >   *  Output parameters:  NONE<br>
>> >   */<br>
>> ><br>
>> > -void _POSIX_Key_Manager_initialization(void)<br>
>> > +void _POSIX_Keys_Manager_initialization(void)<br>
>> >  {<br>
>> >    _Objects_Initialize_information(<br>
>> >      &_POSIX_Keys_Information,   /* object information table */<br>
>> > @@ -60,4 +103,11 @@ void _POSIX_Key_Manager_initialization(void)<br>
>> >      NULL                        /* Proxy extraction support callout */<br>
>> >  #endif<br>
>> >    );<br>
>> > +<br>
>> > +  _RBTree_Initialize_empty(<br>
>> > +    &_POSIX_Keys_Rbtree,     /* the rbtree control block */<br>
>> > +    _POSIX_Keys_Rbtree_compare_function,<br>
>> > +                            /* the rbtree compare function */<br>
>> > +    true                    /* true if each rbtree node is unique */<br>
>> > +  );<br>
>> I don't think the parameter comments here are necessary.<br>
>><br>
>> >  }<br>
>> > diff --git a/cpukit/posix/src/keycreate.c b/cpukit/posix/src/keycreate.c<br>
>> > index b41b590..84a4d9c 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,9 @@ 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<br>
>> > 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_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>
>> > +  /*problem: not clear about _Objects_Open_u32() */<br>
>> > +  _Objects_Open_u32( &_POSIX_Keys_Information, &the_key->object, 0 );<br>
>> I believe you need to "open" the object for RTEMS object<br>
>> tracking..like reference counting. Not sure though.<br>
><br>
> OK.<br>
>><br>
>><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..f45e264 100644<br>
>> > --- a/cpukit/posix/src/keydelete.c<br>
>> > +++ b/cpukit/posix/src/keydelete.c<br>
>> > @@ -42,9 +42,9 @@ 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>
>> > +      /* problem: should it done before _POSIX_Keys_Free_memory? */<br>
>> > +      _Objects_Close( &_POSIX_Keys_Information, &the_key->object );<br>
>> I think you need to be finished with the_key before closing it.<br>
>><br>
> I see.<br>
>><br>
>> ><br>
>> >        /*<br>
>> >         *  NOTE:  The destructor is not called and it is the<br>
>> > responsibility<br>
>> > diff --git a/cpukit/posix/src/keyfreememory.c<br>
>> > b/cpukit/posix/src/keyfreememory.c<br>
>> > index f71af4f..50f560e 100644<br>
>> > --- a/cpukit/posix/src/keyfreememory.c<br>
>> > +++ b/cpukit/posix/src/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,<br>
>> > &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/keygetspecific.c<br>
>> > b/cpukit/posix/src/keygetspecific.c<br>
>> > index debad83..61adea6 100644<br>
>> > --- a/cpukit/posix/src/keygetspecific.c<br>
>> > +++ b/cpukit/posix/src/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,23 @@ 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>
>> > +<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>
>> > +      /** TODO: search the node in TCB's chain(maybe the rbtree) to<br>
>> > speed up the search */<br>
>> Is this TODO still relevant? I don't quite understand it.<br>
>><br>
> I thought search a node in chain's runtime is O(n1) and in rbtree is<br>
> O(log(n2), where n2 is bigger than n1,<br>
> so I think there is no big difference between these two and this TODO can be<br>
> removed.<br>
>><br>
>> > +      search_node.key = key;<br>
>> > +      search_node.thread_id = _Thread_Executing->Object.id;<br>
>> > +      p = _RBTree_Find_unprotected( &_POSIX_Keys_Rbtree,<br>
>> > &search_node.rb_node);<br>
>> > +      key_data = NULL;<br>
>> > +      if ( p ) {<br>
>> > +        key_data = _RBTree_Container_of( p, 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/keyrundestructors.c<br>
>> > b/cpukit/posix/src/keyrundestructors.c<br>
>> > index 9f48888..687217c 100644<br>
>> > --- a/cpukit/posix/src/keyrundestructors.c<br>
>> > +++ b/cpukit/posix/src/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,43 @@ void _POSIX_Keys_Run_destructors(<br>
>> >    Thread_Control *thread<br>
>> >  )<br>
>> >  {<br>
>> > -  Objects_Maximum thread_index = _Objects_Get_index( thread->Object.id<br>
>> > );<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<br>
>> > limit the<br>
>> > -   *  number of iterations.  An infinite loop may happen if destructors<br>
>> > 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.maximum;<br>
>> > +  _Thread_Disable_dispatch();<br>
>> > +<br>
>> > +  chain = &((POSIX_API_Control *)thread->API_Extensions[<br>
>> > THREAD_API_POSIX ])->the_chain;<br>
>> > +  iter = _Chain_First( chain );<br>
>> > +  while ( !_Chain_Is_tail( chain, iter ) ) {<br>
>> > +    next = _Chain_Next( iter );<br>
>> > +<br>
>> > +    /**<br>
>> > +     * remove key from rbtree and chain.<br>
>> > +     * here Chain_Node *iter can be convert to POSIX_Keys_Rbtree_node<br>
>> > *,<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>
>> > -    done = true;<br>
>> > -<br>
>> > -    for ( index = 1 ; index <= max ; ++index ) {<br>
>> > -      POSIX_Keys_Control *key = (POSIX_Keys_Control *)<br>
>> > -        _POSIX_Keys_Information.local_table [ index ];<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>
>> > +    /**<br>
>> > +     * run key value's destructor if destructor and value are both<br>
>> > 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>
>> > +    _Workspace_Free( (POSIX_Keys_Rbtree_node *)iter );<br>
>> > +    iter = next;<br>
>> >    }<br>
>> > +  _Thread_Enable_dispatch();<br>
>> >  }<br>
>> > diff --git a/cpukit/posix/src/keysetspecific.c<br>
>> > b/cpukit/posix/src/keysetspecific.c<br>
>> > index b25e44c..eeb4d84 100644<br>
>> > --- a/cpukit/posix/src/keysetspecific.c<br>
>> > +++ b/cpukit/posix/src/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,34 @@ 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()<br>
>> > 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>
>> > );<br>
>> This allocation needs to be accounted for in confdefs.h<br>
>><br>
> I remember we have discussed this before, the exactly post<br>
> is:<a href="http://www.rtems.org/pipermail/rtems-devel/2012-August/001712.html" target="_blank">http://www.rtems.org/pipermail/rtems-devel/2012-August/001712.html</a>,<br>
> but seem there is no conclusion yet.<br>
>><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_Extensions[THREAD_API_POSIX]);<br>
>> > +      _Chain_Append_unprotected( &api->the_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..22c835f 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_extension(<br>
>> >      created<br>
>> >    );<br>
>> ><br>
>> > +  /** initialize thread's key vaule node chain */<br>
>> > +  _Chain_Initialize_empty( &api->the_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_Initialization();<br>
>> >    _POSIX_Threads_Manager_initialization();<br>
>> >    _POSIX_Condition_variables_Manager_initialization();<br>
>> > -  _POSIX_Key_Manager_initialization();<br>
>> > +  _POSIX_Keys_Manager_initialization();<br>
>> >    _POSIX_Mutex_Manager_initialization();<br>
>> >    _POSIX_Message_queue_Manager_initialization();<br>
>> >    _POSIX_Semaphore_Manager_initialization();<br>
>> > --<br>
>> > 1.7.1<br>
>> ><br>
><br>
><br>
</div></div></blockquote></div>Thanks,<br>Zhongwei Yao<br></div></div>