diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-03-17 07:56:31 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-03-18 07:43:46 +0100 |
commit | 5eaf0e7458bac80ba669f03c4feaae5bad55c6c9 (patch) | |
tree | a6ed26d6617c2b1c2503df1607443e966d875897 /cpukit/posix/src/keysetspecific.c | |
parent | score: Destroy thread timer lock (diff) | |
download | rtems-5eaf0e7458bac80ba669f03c4feaae5bad55c6c9.tar.bz2 |
posix: Use per-thread lookup tree for POSIX Keys
Yields higher performance on SMP systems.
Close #2625.
Diffstat (limited to 'cpukit/posix/src/keysetspecific.c')
-rw-r--r-- | cpukit/posix/src/keysetspecific.c | 164 |
1 files changed, 97 insertions, 67 deletions
diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c index 20e3042b4d..8b0f517eaf 100644 --- a/cpukit/posix/src/keysetspecific.c +++ b/cpukit/posix/src/keysetspecific.c @@ -9,6 +9,7 @@ * Copyright (c) 2012 Zhongwei Yao. * COPYRIGHT (c) 1989-2014. * On-Line Applications Research Corporation (OAR). + * Copyright (c) 2016 embedded brains GmbH. * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -20,70 +21,106 @@ #endif #include <rtems/posix/keyimpl.h> -#include <rtems/score/thread.h> -#include <rtems/score/chainimpl.h> #include <errno.h> -static int _POSIX_Keys_Set_value( +static int _POSIX_Keys_Set_value( RBTree_Node *node, const void *value ) +{ + POSIX_Keys_Key_value_pair *key_value_pair; + + key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node ); + key_value_pair->value = RTEMS_DECONST( void *, value ); + + return 0; +} + +static int _POSIX_Keys_Create_value( pthread_key_t key, const void *value, - POSIX_Keys_Control *the_key, - Thread_Control *executing, - RBTree_Node *rb_node + Thread_Control *executing ) { - POSIX_Keys_Key_value_pair *key_value_pair; + POSIX_Keys_Control *the_key; + int eno; - if ( rb_node != NULL ) { - key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( rb_node ); - key_value_pair->value = RTEMS_DECONST( void *, value ); - } else { - key_value_pair = _POSIX_Keys_Key_value_pair_allocate(); + _Objects_Allocator_lock(); + + the_key = _POSIX_Keys_Get( key ); + if ( the_key != NULL ) { + POSIX_Keys_Key_value_pair *key_value_pair; + + key_value_pair = _POSIX_Keys_Key_value_allocate(); + if ( key_value_pair != NULL ) { + ISR_lock_Context lock_context; + + key_value_pair->key = key; + key_value_pair->thread = executing; + key_value_pair->value = RTEMS_DECONST( void *, value ); + + _Chain_Append_unprotected( + &the_key->Key_value_pairs, + &key_value_pair->Key_node + ); - if ( key_value_pair == NULL ) { - return ENOMEM; + _POSIX_Keys_Key_value_acquire( executing, &lock_context ); + _POSIX_Keys_Key_value_insert( key, key_value_pair, executing ); + _POSIX_Keys_Key_value_release( executing, &lock_context ); + eno = 0; + } else { + eno = ENOMEM; } - key_value_pair->key = key; - key_value_pair->thread = executing; - key_value_pair->value = RTEMS_DECONST( void *, value ); - - /* - * The insert can only go wrong if the same node is already in a unique - * tree. This has been already checked with the _RBTree_Find(). - */ - _RBTree_Insert( - &_POSIX_Keys_Key_value_lookup_tree, - &key_value_pair->Key_value_lookup_node, - _POSIX_Keys_Key_value_compare, - true - ); - - _Chain_Append_unprotected( - &executing->Key_Chain, - &key_value_pair->Key_values_per_thread_node - ); + } else { + eno = EINVAL; } - return 0; + _Objects_Allocator_unlock(); + + return eno; } static int _POSIX_Keys_Delete_value( - pthread_key_t key, - POSIX_Keys_Control *the_key, - RBTree_Node *rb_node + pthread_key_t key, + Thread_Control *executing ) { + POSIX_Keys_Control *the_key; + int eno; + + _Objects_Allocator_lock(); + + the_key = _POSIX_Keys_Get( key ); + if ( the_key != NULL ) { + ISR_lock_Context lock_context; + RBTree_Node *node; + + _POSIX_Keys_Key_value_acquire( executing, &lock_context ); - if ( rb_node != NULL ) { - POSIX_Keys_Key_value_pair *key_value_pair = - POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( rb_node ); + node = _POSIX_Keys_Key_value_find( key, executing ); + if ( node != NULL ) { + POSIX_Keys_Key_value_pair *key_value_pair; - _POSIX_Keys_Free_key_value_pair( key_value_pair ); + key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node ); + _RBTree_Extract( + &executing->Keys.Key_value_pairs, + &key_value_pair->Lookup_node + ); + + _POSIX_Keys_Key_value_release( executing, &lock_context ); + + _POSIX_Keys_Key_value_free( key_value_pair ); + } else { + _POSIX_Keys_Key_value_release( executing, &lock_context ); + } + + eno = 0; + } else { + eno = EINVAL; } - return 0; + _Objects_Allocator_unlock(); + + return eno; } /* @@ -95,35 +132,28 @@ int pthread_setspecific( const void *value ) { - POSIX_Keys_Control *the_key; - Objects_Locations location; - Thread_Control *executing; - RBTree_Node *rb_node; - int eno; - - the_key = _POSIX_Keys_Get( key, &location ); - switch ( location ) { + Thread_Control *executing; + int eno; - case OBJECTS_LOCAL: - executing = _Thread_Executing; - rb_node = _POSIX_Keys_Find( key, executing ); + executing = _Thread_Get_executing(); - if ( value != NULL ) { - eno = _POSIX_Keys_Set_value( key, value, the_key, executing, rb_node ); - } else { - eno = _POSIX_Keys_Delete_value( key, the_key, rb_node ); - } + if ( value != NULL ) { + ISR_lock_Context lock_context; + RBTree_Node *node; - _Objects_Put( &the_key->Object ); + _POSIX_Keys_Key_value_acquire( executing, &lock_context ); - return eno; - -#if defined(RTEMS_MULTIPROCESSING) - case OBJECTS_REMOTE: /* should never happen */ -#endif - case OBJECTS_ERROR: - break; + node = _POSIX_Keys_Key_value_find( key, executing ); + if ( node != NULL ) { + eno = _POSIX_Keys_Set_value( node, value ); + _POSIX_Keys_Key_value_release( executing, &lock_context ); + } else { + _POSIX_Keys_Key_value_release( executing, &lock_context ); + eno = _POSIX_Keys_Create_value( key, value, executing ); + } + } else { + eno = _POSIX_Keys_Delete_value( key, executing ); } - return EINVAL; + return eno; } |