Changeset 5eaf0e7 in rtems


Ignore:
Timestamp:
Mar 17, 2016, 6:56:31 AM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
b545d97c
Parents:
90de3001
git-author:
Sebastian Huber <sebastian.huber@…> (03/17/16 06:56:31)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/18/16 06:43:46)
Message:

posix: Use per-thread lookup tree for POSIX Keys

Yields higher performance on SMP systems.

Close #2625.

Location:
cpukit
Files:
1 deleted
12 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libcsupport/src/resource_snapshot.c

    r90de3001 r5eaf0e7  
    106106}
    107107
    108 static bool count_posix_key_value_pairs(
    109   const RBTree_Node *node,
    110   void *visitor_arg
    111 )
     108static POSIX_Keys_Control *get_next_key(Objects_Id *id)
    112109{
    113   uint32_t *count = visitor_arg;
     110  Objects_Locations location;
    114111
    115   (void) node;
    116 
    117   ++(*count);
    118 
    119   return false;
     112  return (POSIX_Keys_Control *)
     113    _Objects_Get_next(&_POSIX_Keys_Information, *id, &location, id);
    120114}
    121115
     
    123117{
    124118  uint32_t count = 0;
     119  Objects_Id id = OBJECTS_ID_INITIAL_INDEX;
     120  POSIX_Keys_Control *the_key;
    125121
    126   _Thread_Disable_dispatch();
    127   _RBTree_Iterate(
    128     &_POSIX_Keys_Key_value_lookup_tree,
    129     count_posix_key_value_pairs,
    130     &count
    131   );
    132   _Thread_Enable_dispatch();
     122  while ((the_key = get_next_key(&id)) != NULL ) {
     123    count += _Chain_Node_count_unprotected(&the_key->Key_value_pairs);
     124    _Objects_Allocator_unlock();
     125  }
    133126
    134127  return count;
  • cpukit/posix/Makefile.am

    r90de3001 r5eaf0e7  
    155155## KEY_C_FILES
    156156libposix_a_SOURCES += src/key.c src/keycreate.c src/keydelete.c \
    157     src/keygetspecific.c src/keyfreememory.c \
     157    src/keygetspecific.c \
    158158    src/keysetspecific.c
    159159
  • cpukit/posix/include/rtems/posix/key.h

    r90de3001 r5eaf0e7  
    1212 * COPYRIGHT (c) 1989-2011.
    1313 * On-Line Applications Research Corporation (OAR).
     14 * Copyright (c) 2016 embedded brains GmbH.
    1415 *
    1516 * The license and distribution terms for this file may be
     
    4546typedef struct {
    4647  /**
    47    * @brief The chain node for the per-thread value chain.
     48   * @brief The chain node for the key value pairs chain in POSIX_Keys_Control.
    4849   */
    49   Chain_Node Key_values_per_thread_node;
     50  Chain_Node Key_node;
    5051
    5152  /**
    52    * @brief The tree node for the lookup tree.
     53   * @brief The tree node for the lookup tree in Thread_Keys_information.
    5354   */
    54   RBTree_Node Key_value_lookup_node;
     55  RBTree_Node Lookup_node;
    5556
    5657  /**
    57    * @brief The POSIX key identifier used in combination with the thread
    58    * pointer as the tree key.
     58   * @brief The POSIX key identifier used as the tree key.
    5959   */
    6060  pthread_key_t key;
    6161
    6262  /**
    63    * @brief The thread pointer used in combination with the POSIX key
    64    * identifier as the tree key.
     63   * @brief The corresponding thread.
    6564   */
    6665  Thread_Control *thread;
     
    8079   /** This field is the data destructor. */
    8180   void (*destructor) (void *);
     81
     82   /**
     83    * @brief Key value pairs of this key.
     84    */
     85   Chain_Control Key_value_pairs;
    8286 }  POSIX_Keys_Control;
    8387
  • cpukit/posix/include/rtems/posix/keyimpl.h

    r90de3001 r5eaf0e7  
    1111 *  COPYRIGHT (c) 1989-1999.
    1212 *  On-Line Applications Research Corporation (OAR).
     13 *  Copyright (c) 2016 embedded brains GmbH.
    1314 *
    1415 *  The license and distribution terms for this file may be
     
    4243
    4344/**
    44  * @brief The rbtree control block used to manage all key values
    45  */
    46 extern RBTree_Control _POSIX_Keys_Key_value_lookup_tree;
    47 
    48 /**
    4945 * @brief This freechain is used as a memory pool for POSIX_Keys_Key_value_pair.
    5046 */
     
    5248
    5349#define POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node ) \
    54   RTEMS_CONTAINER_OF( node, POSIX_Keys_Key_value_pair, Key_value_lookup_node )
    55 
    56 /**
    57  * @brief POSIX keys Red-Black tree node comparison.
    58  *
    59  * This routine compares the rbtree node
    60  */
    61 RBTree_Compare_result _POSIX_Keys_Key_value_compare(
    62   const RBTree_Node *node1,
    63   const RBTree_Node *node2
    64 );
    65 
    66 /**
    67  * @brief Free a POSIX key table memory.
    68  *
    69  * This memory frees the key table memory associated with @a the_key.
    70  *
    71  * @param[in] the_key is a pointer to the POSIX key to free
    72  * the table memory of.
    73  */
    74 void _POSIX_Keys_Free_memory(
    75   POSIX_Keys_Control *the_key
    76 );
    77 
    78 /**
    79  * @brief Free a POSIX keys control block.
    80  *
    81  * This routine frees a keys control block to the
    82  * inactive chain of free keys control blocks.
    83  *
    84  * @param[in] the_key is a pointer to the POSIX key to free.
    85  */
    86 RTEMS_INLINE_ROUTINE void _POSIX_Keys_Free (
    87   POSIX_Keys_Control *the_key
    88 );
     50  RTEMS_CONTAINER_OF( node, POSIX_Keys_Key_value_pair, Lookup_node )
    8951
    9052/**
     
    10668 * inactive chain of free keys control blocks.
    10769 */
    108 RTEMS_INLINE_ROUTINE void _POSIX_Keys_Free (
     70RTEMS_INLINE_ROUTINE void _POSIX_Keys_Free(
    10971  POSIX_Keys_Control *the_key
    11072)
     
    11375}
    11476
    115 /**
    116  * @brief Get a keys control block.
    117  *
    118  * This function maps key IDs to key control blocks.
    119  * If ID corresponds to a local keys, then it returns
    120  * the_key control pointer which maps to ID and location
    121  * is set to OBJECTS_LOCAL.  if the keys ID is global and
    122  * resides on a remote node, then location is set to OBJECTS_REMOTE,
    123  * and the_key is undefined.  Otherwise, location is set
    124  * to OBJECTS_ERROR and the_key is undefined.
    125  */
     77RTEMS_INLINE_ROUTINE POSIX_Keys_Control *_POSIX_Keys_Get( pthread_key_t key )
     78{
     79  Objects_Locations location;
    12680
    127 RTEMS_INLINE_ROUTINE POSIX_Keys_Control *_POSIX_Keys_Get (
    128   pthread_key_t      id,
    129   Objects_Locations *location
     81  return (POSIX_Keys_Control *) _Objects_Get_no_protection(
     82    &_POSIX_Keys_Information,
     83    (Objects_Id) key,
     84    &location
     85  );
     86}
     87
     88RTEMS_INLINE_ROUTINE void _POSIX_Keys_Key_value_acquire(
     89  Thread_Control   *the_thread,
     90  ISR_lock_Context *lock_context
    13091)
    13192{
    132   return (POSIX_Keys_Control *)
    133     _Objects_Get( &_POSIX_Keys_Information, (Objects_Id) id, location );
     93  _ISR_lock_ISR_disable_and_acquire( &the_thread->Keys.Lock, lock_context );
    13494}
    13595
    136 POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_pair_allocate( void );
     96RTEMS_INLINE_ROUTINE void _POSIX_Keys_Key_value_release(
     97  Thread_Control   *the_thread,
     98  ISR_lock_Context *lock_context
     99)
     100{
     101  _ISR_lock_Release_and_ISR_enable( &the_thread->Keys.Lock, lock_context );
     102}
    137103
    138 RTEMS_INLINE_ROUTINE void _POSIX_Keys_Key_value_pair_free(
     104POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_allocate( void );
     105
     106RTEMS_INLINE_ROUTINE void _POSIX_Keys_Key_value_free(
    139107  POSIX_Keys_Key_value_pair *key_value_pair
    140108)
    141109{
     110  _Chain_Extract_unprotected( &key_value_pair->Key_node );
    142111  _Freechain_Put( &_POSIX_Keys_Keypool, key_value_pair );
    143112}
    144113
    145 RTEMS_INLINE_ROUTINE RBTree_Node *_POSIX_Keys_Find(
    146   pthread_key_t   key,
    147   Thread_Control *thread
     114RTEMS_INLINE_ROUTINE RBTree_Node *_POSIX_Keys_Key_value_find(
     115  pthread_key_t     key,
     116  Thread_Control   *the_thread
    148117)
    149118{
    150   POSIX_Keys_Key_value_pair search_node;
     119  RBTree_Node **link;
     120  RBTree_Node  *parent;
    151121
    152   search_node.key = key;
    153   search_node.thread = thread;
     122  link = _RBTree_Root_reference( &the_thread->Keys.Key_value_pairs );
     123  parent = NULL;
    154124
    155   return _RBTree_Find(
    156     &_POSIX_Keys_Key_value_lookup_tree,
    157     &search_node.Key_value_lookup_node,
    158     _POSIX_Keys_Key_value_compare,
    159     true
    160   );
     125  while ( *link != NULL ) {
     126    POSIX_Keys_Key_value_pair *parent_key_value_pair;
     127    pthread_key_t              parent_key;
     128
     129    parent = *link;
     130    parent_key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( parent );
     131    parent_key = parent_key_value_pair->key;
     132
     133    if ( key == parent_key ) {
     134      return parent;
     135    } else if ( key < parent_key ) {
     136      link = _RBTree_Left_reference( parent );
     137    } else {
     138      link = _RBTree_Right_reference( parent );
     139    }
     140  }
     141
     142  return NULL;
    161143}
    162144
    163 RTEMS_INLINE_ROUTINE void _POSIX_Keys_Free_key_value_pair(
    164   POSIX_Keys_Key_value_pair *key_value_pair
     145RTEMS_INLINE_ROUTINE void _POSIX_Keys_Key_value_insert(
     146  pthread_key_t              key,
     147  POSIX_Keys_Key_value_pair *key_value_pair,
     148  Thread_Control            *the_thread
    165149)
    166150{
    167   _RBTree_Extract(
    168     &_POSIX_Keys_Key_value_lookup_tree,
    169     &key_value_pair->Key_value_lookup_node
     151  RBTree_Node **link;
     152  RBTree_Node  *parent;
     153
     154  link = _RBTree_Root_reference( &the_thread->Keys.Key_value_pairs );
     155  parent = NULL;
     156
     157  while ( *link != NULL ) {
     158    POSIX_Keys_Key_value_pair *parent_key_value_pair;
     159
     160    parent = *link;
     161    parent_key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( parent );
     162
     163    if ( key < parent_key_value_pair->key ) {
     164      link = _RBTree_Left_reference( parent );
     165    } else {
     166      link = _RBTree_Right_reference( parent );
     167    }
     168  }
     169
     170  _RBTree_Add_child( &key_value_pair->Lookup_node, parent, link );
     171  _RBTree_Insert_color(
     172    &the_thread->Keys.Key_value_pairs,
     173    &key_value_pair->Lookup_node
    170174  );
    171   _Chain_Extract_unprotected( &key_value_pair->Key_values_per_thread_node );
    172   _POSIX_Keys_Key_value_pair_free( key_value_pair );
    173175}
    174176
  • cpukit/posix/src/key.c

    r90de3001 r5eaf0e7  
    1010 * COPYRIGHT (c) 1989-2014.
    1111 * On-Line Applications Research Corporation (OAR).
     12 * Copyright (c) 2016 embedded brains GmbH.
    1213 *
    1314 * The license and distribution terms for this file may be
     
    2425
    2526#include <rtems/posix/keyimpl.h>
    26 #include <rtems/score/chainimpl.h>
    27 #include <rtems/score/objectimpl.h>
    2827#include <rtems/score/userextimpl.h>
    2928#include <rtems/score/wkspace.h>
     
    3130Objects_Information _POSIX_Keys_Information;
    3231
    33 RBTREE_DEFINE_EMPTY( _POSIX_Keys_Key_value_lookup_tree );
    34 
    3532Freechain_Control _POSIX_Keys_Keypool;
    36 
    37 /**
    38  * @brief This routine compares the rbtree node by comparing POSIX key first
    39  * and comparing thread id second.
    40  *
    41  * if either of the input nodes's thread_id member is 0, then it will only
    42  * compare the pthread_key_t member. That is when we pass thread_id = 0 node
    43  * as a search node, the search is done only by pthread_key_t.
    44  *
    45  * @param[in] node1 The node to be compared
    46  * @param[in] node2 The node to be compared
    47  * @retval positive if first node has higher key than second
    48  * @retval negative if lower
    49  * @retval 0 if equal,and for all the thread id is unique, then return 0 is
    50  * impossible
    51  */
    52 
    53 RBTree_Compare_result _POSIX_Keys_Key_value_compare(
    54   const RBTree_Node *node1,
    55   const RBTree_Node *node2
    56 )
    57 {
    58   POSIX_Keys_Key_value_pair *n1;
    59   POSIX_Keys_Key_value_pair *n2;
    60   Thread_Control *thread1;
    61   Thread_Control *thread2;
    62   RBTree_Compare_result diff;
    63 
    64   n1 = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node1 );
    65   n2 = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node2 );
    66 
    67   diff = n1->key - n2->key;
    68   if ( diff )
    69     return diff;
    70 
    71   thread1 = n1->thread;
    72   thread2 = n2->thread;
    73 
    74   /*
    75    * If thread1 or thread2 equals to NULL, only key1 and key2 is valued.  It
    76    * enables us search node only by pthread_key_t type key.  Exploit that the
    77    * thread control alignment is at least two to avoid integer overflows.
    78    */
    79   if ( thread1 != NULL && thread2 != NULL )
    80     return (RBTree_Compare_result) ( (uintptr_t) thread1 >> 1 )
    81       - (RBTree_Compare_result) ( (uintptr_t) thread2 >> 1 );
    82 
    83   return 0;
    84 }
    8533
    8634static uint32_t _POSIX_Keys_Get_keypool_bump_count( void )
     
    10957}
    11058
    111 POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_pair_allocate( void )
     59POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_allocate( void )
    11260{
    11361  return (POSIX_Keys_Key_value_pair *) _Freechain_Get(
     
    11967}
    12068
    121 static void _POSIX_Keys_Run_destructors( Thread_Control *thread )
     69static void _POSIX_Keys_Run_destructors( Thread_Control *the_thread )
    12270{
    123   Chain_Control *chain;
    124   POSIX_Keys_Key_value_pair *iter, *next;
    125   void *value;
    126   void (*destructor) (void *);
    127   POSIX_Keys_Control *the_key;
    128   Objects_Locations location;
     71  while ( true ) {
     72    ISR_lock_Context  lock_context;
     73    RBTree_Node      *node;
    12974
    130   chain = &thread->Key_Chain;
    131   iter = (POSIX_Keys_Key_value_pair *) _Chain_First( chain );
    132   while ( !_Chain_Is_tail( chain, &iter->Key_values_per_thread_node ) ) {
    133     next = (POSIX_Keys_Key_value_pair *)
    134       _Chain_Next( &iter->Key_values_per_thread_node );
     75    _Objects_Allocator_lock();
     76    _POSIX_Keys_Key_value_acquire( the_thread, &lock_context );
    13577
    136     the_key = _POSIX_Keys_Get( iter->key, &location );
    137     _Assert( location == OBJECTS_LOCAL );
     78    node = _RBTree_Root( &the_thread->Keys.Key_value_pairs );
     79    if ( node != NULL ) {
     80      POSIX_Keys_Key_value_pair *key_value_pair;
     81      pthread_key_t              key;
     82      void                      *value;
     83      POSIX_Keys_Control        *the_key;
     84      void                    ( *destructor )( void * );
    13885
    139     /**
    140      * remove key from rbtree and chain.
    141      * here Chain_Node *iter can be convert to POSIX_Keys_Key_value_pair *,
    142      * because Chain_Node is the first member of POSIX_Keys_Key_value_pair
    143      * structure.
    144      */
    145     _RBTree_Extract(
    146         &_POSIX_Keys_Key_value_lookup_tree,
    147         &iter->Key_value_lookup_node
    148     );
    149     _Chain_Extract_unprotected( &iter->Key_values_per_thread_node );
     86      key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node );
     87      key = key_value_pair->key;
     88      value = key_value_pair->value;
     89      _RBTree_Extract(
     90        &the_thread->Keys.Key_value_pairs,
     91        &key_value_pair->Lookup_node
     92      );
    15093
    151     destructor = the_key->destructor;
    152     value = iter->value;
     94      _POSIX_Keys_Key_value_release( the_thread, &lock_context );
     95      _POSIX_Keys_Key_value_free( key_value_pair );
    15396
    154     _POSIX_Keys_Key_value_pair_free( iter );
     97      the_key = _POSIX_Keys_Get( key );
     98      _Assert( the_key != NULL );
     99      destructor = the_key->destructor;
    155100
    156     _Objects_Put( &the_key->Object );
     101      _Objects_Allocator_unlock();
    157102
    158     /**
    159      * run key value's destructor if destructor and value are both non-null.
    160      */
    161     if ( destructor != NULL && value != NULL )
    162       (*destructor)( value );
    163 
    164     iter = next;
     103      if ( destructor != NULL && value != NULL ) {
     104        ( *destructor )( value );
     105      }
     106    } else {
     107      _POSIX_Keys_Key_value_release( the_thread, &lock_context );
     108      _Objects_Allocator_unlock();
     109      break;
     110    }
    165111  }
    166112}
  • cpukit/posix/src/keycreate.c

    r90de3001 r5eaf0e7  
    99 * COPYRIGHT (c) 1989-2010.
    1010 * On-Line Applications Research Corporation (OAR).
     11 * Copyright (c) 2016 embedded brains GmbH.
    1112 *
    1213 * The license and distribution terms for this file may be
     
    1920#endif
    2021
     22#include <rtems/posix/keyimpl.h>
     23
    2124#include <errno.h>
    22 #include <limits.h>
    23 #include <pthread.h>
    24 #include <string.h>
    25 
    26 #include <rtems/system.h>
    27 #include <rtems/score/thread.h>
    28 #include <rtems/score/wkspace.h>
    29 #include <rtems/posix/keyimpl.h>
    3025
    3126/**
     
    4742
    4843  the_key->destructor = destructor;
     44  _Chain_Initialize_empty( &the_key->Key_value_pairs );
    4945  _Objects_Open_u32( &_POSIX_Keys_Information, &the_key->Object, 0 );
    5046  *key = the_key->Object.id;
  • cpukit/posix/src/keydelete.c

    r90de3001 r5eaf0e7  
    99 * COPYRIGHT (c) 1989-2007.
    1010 * On-Line Applications Research Corporation (OAR).
     11 * Copyright (c) 2016 embedded brains GmbH.
    1112 *
    1213 * The license and distribution terms for this file may be
     
    1920#endif
    2021
     22#include <rtems/posix/keyimpl.h>
     23
    2124#include <errno.h>
    22 #include <limits.h>
    23 #include <pthread.h>
    24 #include <string.h>
    2525
    26 #include <rtems/system.h>
    27 #include <rtems/score/thread.h>
    28 #include <rtems/score/wkspace.h>
    29 #include <rtems/posix/keyimpl.h>
     26static void _POSIX_Keys_Destroy( POSIX_Keys_Control *the_key )
     27{
     28  _Objects_Close( &_POSIX_Keys_Information, &the_key->Object );
     29
     30  while ( true ) {
     31    POSIX_Keys_Key_value_pair *key_value_pair;
     32    ISR_lock_Context           lock_context;
     33    Thread_Control            *the_thread;
     34
     35    key_value_pair = (POSIX_Keys_Key_value_pair *)
     36      _Chain_Get_unprotected( &the_key->Key_value_pairs );
     37    if ( key_value_pair == NULL ) {
     38      break;
     39    }
     40
     41    the_thread = key_value_pair->thread;
     42    _POSIX_Keys_Key_value_acquire( the_thread, &lock_context );
     43    _RBTree_Extract(
     44      &the_thread->Keys.Key_value_pairs,
     45      &key_value_pair->Lookup_node
     46    );
     47    _POSIX_Keys_Key_value_release( the_thread, &lock_context );
     48
     49    _POSIX_Keys_Key_value_free( key_value_pair );
     50  }
     51
     52  _Objects_Free( &_POSIX_Keys_Information, &the_key->Object );
     53}
    3054
    3155/*
     
    3761{
    3862  POSIX_Keys_Control *the_key;
    39   Objects_Locations   location;
     63  int                 eno;
    4064
    4165  _Objects_Allocator_lock();
    42   the_key = _POSIX_Keys_Get( key, &location );
    43   switch ( location ) {
    4466
    45     case OBJECTS_LOCAL:
    46       _POSIX_Keys_Free_memory( the_key );
    47 
    48       /*
    49        *  NOTE:  The destructor is not called and it is the responsibility
    50        *         of the application to free the memory.
    51        */
    52       _POSIX_Keys_Free( the_key );
    53       _Objects_Put(&the_key->Object);
    54       _Objects_Allocator_unlock();
    55       return 0;
    56 
    57 #if defined(RTEMS_MULTIPROCESSING)
    58     case OBJECTS_REMOTE:   /* should never happen */
    59 #endif
    60     case OBJECTS_ERROR:
    61       break;
     67  the_key = _POSIX_Keys_Get( key );
     68  if ( the_key != NULL ) {
     69    _POSIX_Keys_Destroy( the_key );
     70    eno = 0;
     71  } else {
     72    eno = EINVAL;
    6273  }
    6374
    6475  _Objects_Allocator_unlock();
    6576
    66   return EINVAL;
     77  return eno;
    6778}
  • cpukit/posix/src/keygetspecific.c

    r90de3001 r5eaf0e7  
    1010 * COPYRIGHT (c) 1989-2007.
    1111 * On-Line Applications Research Corporation (OAR).
     12 * Copyright (c) 2016 embedded brains GmbH.
    1213 *
    1314 * The license and distribution terms for this file may be
     
    2021#endif
    2122
    22 #include <errno.h>
    23 #include <limits.h>
    24 #include <pthread.h>
    25 #include <string.h>
    26 
    27 #include <rtems/system.h>
    28 #include <rtems/score/thread.h>
    29 #include <rtems/score/wkspace.h>
    30 #include <rtems/score/rbtree.h>
    3123#include <rtems/posix/keyimpl.h>
    3224
     
    3931)
    4032{
    41   POSIX_Keys_Control          *the_key;
    42   Objects_Locations            location;
    43   RBTree_Node                 *p;
    44   void                        *key_data;
    45   POSIX_Keys_Key_value_pair   *value_pair_p;
     33  Thread_Control   *executing;
     34  ISR_lock_Context  lock_context;
     35  RBTree_Node      *node;
     36  void             *value;
    4637
    47   the_key = _POSIX_Keys_Get( key, &location );
    48   switch ( location ) {
     38  executing = _Thread_Get_executing();
     39  _POSIX_Keys_Key_value_acquire( executing, &lock_context );
    4940
    50     case OBJECTS_LOCAL:
    51       p = _POSIX_Keys_Find( key, _Thread_Executing );
    52       if ( p != NULL ) {
    53         value_pair_p = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( p );
    54         key_data = value_pair_p->value;
    55       } else {
    56         key_data = NULL;
    57       }
     41  node = _POSIX_Keys_Key_value_find( key, executing );
    5842
    59       _Objects_Put( &the_key->Object );
     43  if ( node != NULL ) {
     44    POSIX_Keys_Key_value_pair *key_value_pair;
    6045
    61       return key_data;
    62 
    63 #if defined(RTEMS_MULTIPROCESSING)
    64     case OBJECTS_REMOTE:   /* should never happen */
    65 #endif
    66     case OBJECTS_ERROR:
    67       break;
     46    key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node );
     47    value = key_value_pair->value;
     48  } else {
     49    value = NULL;
    6850  }
    6951
    70   return NULL;
     52  _POSIX_Keys_Key_value_release( executing, &lock_context );
     53
     54  return value;
    7155}
  • cpukit/posix/src/keysetspecific.c

    r90de3001 r5eaf0e7  
    1010 * COPYRIGHT (c) 1989-2014.
    1111 * On-Line Applications Research Corporation (OAR).
     12 * Copyright (c) 2016 embedded brains GmbH.
    1213 *
    1314 * The license and distribution terms for this file may be
     
    2122
    2223#include <rtems/posix/keyimpl.h>
    23 #include <rtems/score/thread.h>
    24 #include <rtems/score/chainimpl.h>
    2524
    2625#include <errno.h>
    2726
    28 static int _POSIX_Keys_Set_value(
    29   pthread_key_t       key,
    30   const void         *value,
    31   POSIX_Keys_Control *the_key,
    32   Thread_Control     *executing,
    33   RBTree_Node        *rb_node
    34 )
     27static int _POSIX_Keys_Set_value( RBTree_Node *node, const void *value )
    3528{
    3629  POSIX_Keys_Key_value_pair *key_value_pair;
    3730
    38   if ( rb_node != NULL ) {
    39     key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( rb_node );
    40     key_value_pair->value = RTEMS_DECONST( void *, value );
    41   } else {
    42     key_value_pair = _POSIX_Keys_Key_value_pair_allocate();
    43 
    44     if ( key_value_pair == NULL ) {
    45       return ENOMEM;
    46     }
    47 
    48     key_value_pair->key = key;
    49     key_value_pair->thread = executing;
    50     key_value_pair->value = RTEMS_DECONST( void *, value );
    51 
    52     /*
    53      * The insert can only go wrong if the same node is already in a unique
    54      * tree.  This has been already checked with the _RBTree_Find().
    55      */
    56     _RBTree_Insert(
    57       &_POSIX_Keys_Key_value_lookup_tree,
    58       &key_value_pair->Key_value_lookup_node,
    59       _POSIX_Keys_Key_value_compare,
    60       true
    61     );
    62 
    63     _Chain_Append_unprotected(
    64       &executing->Key_Chain,
    65       &key_value_pair->Key_values_per_thread_node
    66     );
    67   }
     31  key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node );
     32  key_value_pair->value = RTEMS_DECONST( void *, value );
    6833
    6934  return 0;
    7035}
    7136
    72 static int _POSIX_Keys_Delete_value(
     37static int _POSIX_Keys_Create_value(
    7338  pthread_key_t       key,
    74   POSIX_Keys_Control *the_key,
    75   RBTree_Node        *rb_node
     39  const void         *value,
     40  Thread_Control     *executing
    7641)
    7742{
     43  POSIX_Keys_Control *the_key;
     44  int                 eno;
    7845
    79   if ( rb_node != NULL ) {
    80     POSIX_Keys_Key_value_pair *key_value_pair =
    81       POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( rb_node );
     46  _Objects_Allocator_lock();
    8247
    83     _POSIX_Keys_Free_key_value_pair( key_value_pair );
     48  the_key = _POSIX_Keys_Get( key );
     49  if ( the_key != NULL ) {
     50    POSIX_Keys_Key_value_pair *key_value_pair;
     51
     52    key_value_pair = _POSIX_Keys_Key_value_allocate();
     53    if ( key_value_pair != NULL ) {
     54      ISR_lock_Context lock_context;
     55
     56      key_value_pair->key = key;
     57      key_value_pair->thread = executing;
     58      key_value_pair->value = RTEMS_DECONST( void *, value );
     59
     60      _Chain_Append_unprotected(
     61        &the_key->Key_value_pairs,
     62        &key_value_pair->Key_node
     63      );
     64
     65      _POSIX_Keys_Key_value_acquire( executing, &lock_context );
     66      _POSIX_Keys_Key_value_insert( key, key_value_pair, executing );
     67      _POSIX_Keys_Key_value_release( executing, &lock_context );
     68      eno = 0;
     69    } else {
     70      eno = ENOMEM;
     71    }
     72
     73  } else {
     74    eno = EINVAL;
    8475  }
    8576
    86   return 0;
     77  _Objects_Allocator_unlock();
     78
     79  return eno;
     80}
     81
     82static int _POSIX_Keys_Delete_value(
     83  pthread_key_t   key,
     84  Thread_Control *executing
     85)
     86{
     87  POSIX_Keys_Control *the_key;
     88  int                 eno;
     89
     90  _Objects_Allocator_lock();
     91
     92  the_key = _POSIX_Keys_Get( key );
     93  if ( the_key != NULL ) {
     94    ISR_lock_Context  lock_context;
     95    RBTree_Node      *node;
     96
     97    _POSIX_Keys_Key_value_acquire( executing, &lock_context );
     98
     99    node = _POSIX_Keys_Key_value_find( key, executing );
     100    if ( node != NULL ) {
     101      POSIX_Keys_Key_value_pair *key_value_pair;
     102
     103      key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node );
     104      _RBTree_Extract(
     105        &executing->Keys.Key_value_pairs,
     106        &key_value_pair->Lookup_node
     107      );
     108
     109      _POSIX_Keys_Key_value_release( executing, &lock_context );
     110
     111      _POSIX_Keys_Key_value_free( key_value_pair );
     112    } else {
     113      _POSIX_Keys_Key_value_release( executing, &lock_context );
     114    }
     115
     116    eno = 0;
     117  } else {
     118    eno = EINVAL;
     119  }
     120
     121  _Objects_Allocator_unlock();
     122
     123  return eno;
    87124}
    88125
     
    96133)
    97134{
    98   POSIX_Keys_Control *the_key;
    99   Objects_Locations   location;
    100   Thread_Control     *executing;
    101   RBTree_Node        *rb_node;
    102   int                 eno;
     135  Thread_Control   *executing;
     136  int               eno;
    103137
    104   the_key = _POSIX_Keys_Get( key, &location );
    105   switch ( location ) {
     138  executing = _Thread_Get_executing();
    106139
    107     case OBJECTS_LOCAL:
    108       executing = _Thread_Executing;
    109       rb_node = _POSIX_Keys_Find( key, executing );
     140  if ( value != NULL ) {
     141    ISR_lock_Context  lock_context;
     142    RBTree_Node      *node;
    110143
    111       if ( value != NULL ) {
    112         eno = _POSIX_Keys_Set_value( key, value, the_key, executing, rb_node );
    113       } else {
    114         eno = _POSIX_Keys_Delete_value( key, the_key, rb_node );
    115       }
     144    _POSIX_Keys_Key_value_acquire( executing, &lock_context );
    116145
    117       _Objects_Put( &the_key->Object );
    118 
    119       return eno;
    120 
    121 #if defined(RTEMS_MULTIPROCESSING)
    122     case OBJECTS_REMOTE:   /* should never happen */
    123 #endif
    124     case OBJECTS_ERROR:
    125       break;
     146    node = _POSIX_Keys_Key_value_find( key, executing );
     147    if ( node != NULL ) {
     148      eno = _POSIX_Keys_Set_value( node, value );
     149      _POSIX_Keys_Key_value_release( executing, &lock_context );
     150    } else {
     151      _POSIX_Keys_Key_value_release( executing, &lock_context );
     152      eno = _POSIX_Keys_Create_value( key, value, executing );
     153    }
     154  } else {
     155    eno = _POSIX_Keys_Delete_value( key, executing );
    126156  }
    127157
    128   return EINVAL;
     158  return eno;
    129159}
  • cpukit/score/include/rtems/score/thread.h

    r90de3001 r5eaf0e7  
    488488
    489489/**
     490 * @brief Per-thread information for POSIX Keys.
     491 */
     492typedef struct {
     493  /**
     494   * @brief Key value pairs registered for this thread.
     495   */
     496  RBTree_Control Key_value_pairs;
     497
     498  /**
     499   * @brief Lock to protect the tree operations.
     500   */
     501  ISR_LOCK_MEMBER( Lock )
     502} Thread_Keys_information;
     503
     504/**
    490505 * @brief Control block to manage thread actions.
    491506 *
     
    838853
    839854  /**
    840    * This is the thread key value chain's control, which is used
    841    * to track all key value for specific thread, and when thread
    842    * exits, we can remove all key value for specific thread by
    843    * iterating this chain, or we have to search a whole rbtree,
    844    * which is inefficient.
    845    */
    846   Chain_Control           Key_Chain;
     855   * @brief The POSIX Keys information.
     856   */
     857  Thread_Keys_information               Keys;
    847858
    848859  /**
  • cpukit/score/src/threadinitialize.c

    r90de3001 r5eaf0e7  
    211211  _Scheduler_Update_priority( the_thread, priority );
    212212
    213   /*
    214    * initialize thread's key vaule node chain
    215    */
    216   _Chain_Initialize_empty( &the_thread->Key_Chain );
     213  /* POSIX Keys */
     214  _RBTree_Initialize_empty( &the_thread->Keys.Key_value_pairs );
     215  _ISR_lock_Initialize( &the_thread->Keys.Lock, "POSIX Key Value Pairs" );
    217216
    218217  _Thread_Action_control_initialize( &the_thread->Post_switch_actions );
  • cpukit/score/src/threadrestart.c

    r90de3001 r5eaf0e7  
    9898
    9999  _User_extensions_Thread_delete( the_thread );
     100  _ISR_lock_Destroy( &the_thread->Keys.Lock );
    100101  _Scheduler_Node_destroy( _Scheduler_Get( the_thread ), the_thread );
    101102  _ISR_lock_Destroy( &the_thread->Timer.Lock );
Note: See TracChangeset for help on using the changeset viewer.