[PATCH 1/2] posix: Reimplement POSIX Key manager to use a red-black tree.

Gedare Bloom gedare at rtems.org
Mon Feb 25 14:31:13 UTC 2013


On Sun, Feb 24, 2013 at 8:46 PM, Ashi <ashi08104 at gmail.com> wrote:
> Yeah, of course!
>
>
> On Feb 23, 2013, at 10:52 PM, Joel Sherrill <joel.sherrill at oarcorp.com>
> wrote:
>
>> Some quick comments. Reviewing on my Nexus 7 and I would love a client
>> that let's you respond inline.
>>
>> Object field in the data structure should be named with capitalisation.
>>
> OK
>
>> Look for "DESCRIPTION". convert this and similar blocks to Doxygen.
>>
> Sorry, I don't quite understand it, does it mean add a @brief … line above
> "DESCRIPTION"?

Convert the comments into doxygen comments. See
http://wiki.rtems.org/wiki/index.php/Doxygen_Recommendations

>> Why was the manager initialization method renamed keys manager
>> initialization? Others are singular.
>>
> I see, I'll change it back to singular.
>
>> New files should follow style with @file comment block.
>>
> Does this apply to file in test cases? I find other files under
> testsuites/psxtests/ has no such block.
>
I don't think so. Right now we don't use doxygen in the test cases.

>> No need for comment about disable dispatching above call to Get to convert
>> from Id to pointer.
>>
> OK

Please also be sure to use the updated patches I sent that include the
whitespace fixes. (No extra white space at the end of lines, no extra
blank lines at the end of files.)

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




More information about the devel mailing list