summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src/keysetspecific.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-03-17 07:56:31 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-03-18 07:43:46 +0100
commit5eaf0e7458bac80ba669f03c4feaae5bad55c6c9 (patch)
treea6ed26d6617c2b1c2503df1607443e966d875897 /cpukit/posix/src/keysetspecific.c
parentscore: Destroy thread timer lock (diff)
downloadrtems-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.c164
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;
}