summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhongwei Yao <ashi08104@gmail.com>2013-08-05 09:20:45 -0400
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-08-06 14:11:38 +0200
commitb5c906429f6e67452eec1b0089ac7a204ff998ee (patch)
tree5e24aed5499922f6d3fa6e1559f5bc7e83fba4b2
parentbsp/realview-pbx-a9: Enable fast idle clock (diff)
downloadrtems-b5c906429f6e67452eec1b0089ac7a204ff998ee.tar.bz2
Unlimited objects support for POSIX keys
This patch enables unlimited model in POSIX key manger and have a decent runtime on POSIX key searching, adding and deleting operations. Memory overhead is lower than current implementation when the size of key and key value becomes big.
-rw-r--r--cpukit/posix/include/rtems/posix/config.h1
-rw-r--r--cpukit/posix/include/rtems/posix/key.h90
-rw-r--r--cpukit/posix/include/rtems/posix/threadsup.h9
-rw-r--r--cpukit/posix/src/key.c131
-rw-r--r--cpukit/posix/src/keycreate.c64
-rw-r--r--cpukit/posix/src/keydelete.c14
-rw-r--r--cpukit/posix/src/keyfreememory.c50
-rw-r--r--cpukit/posix/src/keygetspecific.c39
-rw-r--r--cpukit/posix/src/keyrundestructors.c89
-rw-r--r--cpukit/posix/src/keysetspecific.c49
-rw-r--r--cpukit/posix/src/pthread.c3
-rw-r--r--cpukit/sapi/include/confdefs.h34
-rw-r--r--testsuites/psxtests/Makefile.am3
-rw-r--r--testsuites/psxtests/configure.ac7
-rw-r--r--testsuites/psxtests/psxkey01/init.c4
-rw-r--r--testsuites/psxtests/psxkey01/psxkey01.scn4
-rw-r--r--testsuites/psxtests/psxkey04/Makefile.am23
-rw-r--r--testsuites/psxtests/psxkey04/init.c128
-rw-r--r--testsuites/psxtests/psxkey04/psxkey04.doc22
-rw-r--r--testsuites/psxtests/psxkey04/psxkey04.scn11
-rw-r--r--testsuites/psxtests/psxkey05/Makefile.am23
-rw-r--r--testsuites/psxtests/psxkey05/init.c82
-rw-r--r--testsuites/psxtests/psxkey05/psxkey05.doc22
-rw-r--r--testsuites/psxtests/psxkey05/psxkey05.scn10
-rw-r--r--testsuites/psxtests/psxkey06/Makefile.am23
-rw-r--r--testsuites/psxtests/psxkey06/init.c153
-rw-r--r--testsuites/psxtests/psxkey06/psxkey06.doc23
-rw-r--r--testsuites/psxtests/psxkey06/psxkey06.scn18
-rw-r--r--testsuites/psxtests/psxkey07/Makefile.am23
-rw-r--r--testsuites/psxtests/psxkey07/init.c173
-rw-r--r--testsuites/psxtests/psxkey07/psxkey07.doc26
-rw-r--r--testsuites/psxtests/psxkey07/psxkey07.scn18
-rw-r--r--testsuites/psxtests/psxkey08/Makefile.am23
-rw-r--r--testsuites/psxtests/psxkey08/init.c165
-rw-r--r--testsuites/psxtests/psxkey08/psxkey08.doc25
-rw-r--r--testsuites/psxtests/psxkey08/psxkey08.scn15
-rw-r--r--testsuites/psxtests/psxkey09/Makefile.am23
-rw-r--r--testsuites/psxtests/psxkey09/init.c103
-rw-r--r--testsuites/psxtests/psxkey09/psxkey09.doc22
-rw-r--r--testsuites/psxtests/psxkey09/psxkey09.scn9
-rw-r--r--testsuites/psxtests/psxkey10/Makefile.am23
-rw-r--r--testsuites/psxtests/psxkey10/init.c106
-rw-r--r--testsuites/psxtests/psxkey10/psxkey10.doc22
-rw-r--r--testsuites/psxtests/psxkey10/psxkey10.scn10
44 files changed, 1740 insertions, 175 deletions
diff --git a/cpukit/posix/include/rtems/posix/config.h b/cpukit/posix/include/rtems/posix/config.h
index 104bd84046..a842f7a453 100644
--- a/cpukit/posix/include/rtems/posix/config.h
+++ b/cpukit/posix/include/rtems/posix/config.h
@@ -51,6 +51,7 @@ typedef struct {
uint32_t maximum_mutexes;
uint32_t maximum_condition_variables;
uint32_t maximum_keys;
+ uint32_t maximum_key_value_pairs;
uint32_t maximum_timers;
uint32_t maximum_queued_signals;
uint32_t maximum_message_queues;
diff --git a/cpukit/posix/include/rtems/posix/key.h b/cpukit/posix/include/rtems/posix/key.h
index 6d2ebff6fd..ee5b573c9b 100644
--- a/cpukit/posix/include/rtems/posix/key.h
+++ b/cpukit/posix/include/rtems/posix/key.h
@@ -1,6 +1,6 @@
/**
* @file
- *
+ *
* @brief POSIX Key Private Support
*
* This include file contains all the private support information for
@@ -8,24 +8,28 @@
*/
/*
- * COPYRIGHT (c) 1989-2011.
- * On-Line Applications Research Corporation (OAR).
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
*/
#ifndef _RTEMS_POSIX_KEY_H
#define _RTEMS_POSIX_KEY_H
+#include <rtems/score/rbtree.h>
+#include <rtems/score/chainimpl.h>
+#include <rtems/score/freechain.h>
#include <rtems/score/objectimpl.h>
/**
* @defgroup POSIX_KEY POSIX Key
*
* @ingroup POSIXAPI
- *
+ *
*/
/**@{**/
@@ -34,40 +38,86 @@ 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 Key_values_per_thread_node;
+ /** This field is the rbtree node structure. */
+ RBTree_Node Key_value_lookup_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_Key_value_pair;
+
+/**
+ * @brief POSIX_Keys_Freechain is used in Freechain structure
+ */
+typedef struct {
+ Freechain_Control super_fc;
+ size_t bump_count;
+} POSIX_Keys_Freechain;
+
+/**
+ * @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;
+ /** 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 POSIX keys manager initialization.
+ * @brief The rbtree control block used to manage all key values
+ */
+POSIX_EXTERN RBTree_Control _POSIX_Keys_Key_value_lookup_tree;
+
+/**
+ * @brief This freechain is used as a memory pool for POSIX_Keys_Key_value_pair.
+ */
+POSIX_EXTERN POSIX_Keys_Freechain _POSIX_Keys_Keypool;
+
+/**
+ * @brief POSIX key manager initialization.
*
* This routine performs the initialization necessary for this manager.
*/
void _POSIX_Key_Manager_initialization(void);
/**
+ * @brief POSIX key Freechain extend handle
+ *
+ * This routine extend freechain node, which is called in freechain_get
+ * automatically.
+ */
+bool _POSIX_Keys_Freechain_extend(Freechain_Control *freechain);
+
+/**
+ * @brief POSIX keys Red-Black tree node comparison.
+ *
+ * This routine compares the rbtree node
+ */
+int _POSIX_Keys_Key_value_lookup_tree_compare_function(
+ const RBTree_Node *node1,
+ const RBTree_Node *node2
+);
+
+/**
* @brief Create thread-specific data POSIX key.
*
* This function executes all the destructors associated with the thread's
* keys. This function will execute until all values have been set to NULL.
*
- * @param[in] thread is a pointer to the thread whose keys should have
+ * @param[in] thread is a pointer to the thread whose keys should have
* all their destructors run.
*
* NOTE: This is the routine executed when a thread exits to
diff --git a/cpukit/posix/include/rtems/posix/threadsup.h b/cpukit/posix/include/rtems/posix/threadsup.h
index 414b46fd83..7bd1f934ad 100644
--- a/cpukit/posix/include/rtems/posix/threadsup.h
+++ b/cpukit/posix/include/rtems/posix/threadsup.h
@@ -83,6 +83,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/src/key.c b/cpukit/posix/src/key.c
index 6eace26eed..2bb415c4d5 100644
--- a/cpukit/posix/src/key.c
+++ b/cpukit/posix/src/key.c
@@ -6,12 +6,13 @@
*/
/*
- * COPYRIGHT (c) 1989-2008.
- * On-Line Applications Research Corporation (OAR).
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -29,19 +30,115 @@
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#include <rtems/posix/key.h>
+#include <rtems/score/rbtree.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/freechain.h>
-/*
- * _POSIX_Key_Manager_initialization
- *
- * DESCRIPTION:
- *
- * This routine performs the initialization necessary for this manager.
+/* forward declarations to avoid warnings */
+void _POSIX_Keys_Keypool_init(void);
+void _POSIX_Keys_Freechain_init(Freechain_Control *freechain);
+
+/**
+ * @brief This routine compares the rbtree node by comparing POSIX key first
+ * and comparing thread id second.
*
- * Input parameters: NONE
+ * 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.
*
- * Output parameters: NONE
+ * @param[in] node1 The node to be compared
+ * @param[in] node2 The node to be compared
+ * @retval positive if first node has higher key than second
+ * @retval negative if lower
+ * @retval 0 if equal,and for all the thread id is unique, then return 0 is
+ * impossible
*/
+int _POSIX_Keys_Key_value_lookup_tree_compare_function(
+ const RBTree_Node *node1,
+ const RBTree_Node *node2
+)
+{
+ POSIX_Keys_Key_value_pair *n1;
+ POSIX_Keys_Key_value_pair *n2;
+ Objects_Id thread_id1, thread_id2;
+ int diff;
+
+ n1 = _RBTree_Container_of( node1, POSIX_Keys_Key_value_pair, Key_value_lookup_node );
+ n2 = _RBTree_Container_of( node2, POSIX_Keys_Key_value_pair, Key_value_lookup_node );
+
+ diff = n1->key - n2->key;
+ if ( diff )
+ return diff;
+
+ thread_id1 = n1->thread_id;
+ thread_id2 = n2->thread_id;
+
+ /**
+ * 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;
+}
+
+/**
+ * @brief This routine does keypool initialize, keypool contains all
+ * POSIX_Keys_Key_value_pair
+ */
+
+void _POSIX_Keys_Keypool_init(void)
+{
+ _Freechain_Initialize((Freechain_Control *)&_POSIX_Keys_Keypool,
+ &_POSIX_Keys_Freechain_extend);
+
+ _POSIX_Keys_Freechain_init((Freechain_Control *)&_POSIX_Keys_Keypool);
+}
+
+/**
+ * @brief This routine does user side freechain initialization
+ */
+void _POSIX_Keys_Freechain_init(Freechain_Control *freechain)
+{
+ POSIX_Keys_Freechain *psx_freechain_p = (POSIX_Keys_Freechain *)freechain;
+ psx_freechain_p->bump_count =
+ Configuration_POSIX_API.maximum_key_value_pairs & 0x7FFFFFFF;
+ size_t size = psx_freechain_p->bump_count * sizeof(POSIX_Keys_Key_value_pair);
+ POSIX_Keys_Key_value_pair *nodes = _Workspace_Allocate(size);
+
+ _Chain_Initialize(
+ &freechain->Freechain,
+ nodes,
+ psx_freechain_p->bump_count,
+ sizeof(POSIX_Keys_Key_value_pair)
+ );
+}
+
+/**
+ * @brief This routine is user defined freechain extension handle
+ */
+bool _POSIX_Keys_Freechain_extend(Freechain_Control *freechain)
+{
+ POSIX_Keys_Freechain *psx_freechain_p = (POSIX_Keys_Freechain *)freechain;
+ size_t node_size = sizeof(POSIX_Keys_Key_value_pair);
+ size_t size = psx_freechain_p->bump_count * node_size;
+ int i;
+ POSIX_Keys_Key_value_pair *nodes = _Workspace_Allocate(size);
+
+ if (!nodes)
+ return false;
+
+ for ( i = 0; i < psx_freechain_p->bump_count; i++ ) {
+ _Freechain_Put(freechain,
+ nodes + i);
+ }
+ return true;
+}
+
+/**
+ * @brief This routine performs the initialization necessary for this manager.
+ */
void _POSIX_Key_Manager_initialization(void)
{
_Objects_Initialize_information(
@@ -60,4 +157,12 @@ void _POSIX_Key_Manager_initialization(void)
NULL /* Proxy extraction support callout */
#endif
);
+
+ _RBTree_Initialize_empty(
+ &_POSIX_Keys_Key_value_lookup_tree,
+ _POSIX_Keys_Key_value_lookup_tree_compare_function,
+ true
+ );
+
+ _POSIX_Keys_Keypool_init();
}
diff --git a/cpukit/posix/src/keycreate.c b/cpukit/posix/src/keycreate.c
index b41b59017e..349e88378a 100644
--- a/cpukit/posix/src/keycreate.c
+++ b/cpukit/posix/src/keycreate.c
@@ -1,17 +1,17 @@
/**
- * @file
+ * @file
*
- * @brief Thread-Specific Data Key Create
- * @ingroup POSIXAPI
+ * @brief Thread-Specific Data Key Create
+ * @ingroup POSIXAPI
*/
/*
- * COPYRIGHT (c) 1989-2010.
- * On-Line Applications Research Corporation (OAR).
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -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,50 +48,6 @@ 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;
_Thread_Enable_dispatch();
diff --git a/cpukit/posix/src/keydelete.c b/cpukit/posix/src/keydelete.c
index 8f96ca36fe..c3d3da1a3b 100644
--- a/cpukit/posix/src/keydelete.c
+++ b/cpukit/posix/src/keydelete.c
@@ -6,12 +6,12 @@
*/
/*
- * COPYRIGHT (c) 1989-2007.
- * On-Line Applications Research Corporation (OAR).
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -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,7 +49,7 @@ int pthread_key_delete(
* of the application to free the memory.
*/
_POSIX_Keys_Free( the_key );
- _Objects_Put( &the_key->Object );
+ _Objects_Put(&the_key->Object);
return 0;
#if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/posix/src/keyfreememory.c b/cpukit/posix/src/keyfreememory.c
index f71af4f327..c42616dcb0 100644
--- a/cpukit/posix/src/keyfreememory.c
+++ b/cpukit/posix/src/keyfreememory.c
@@ -1,17 +1,18 @@
/**
* @file
*
- * @brief POSIX Function Keys Free Memory
+ * @brief POSIX Function Keys Free Memory
* @ingroup POSIXAPI
*/
/*
- * COPYRIGHT (c) 1989-2010.
- * On-Line Applications Research Corporation (OAR).
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -21,14 +22,45 @@
#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_Key_value_pair search_node;
+ POSIX_Keys_Key_value_pair *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_Key_value_lookup_tree, &search_node.Key_value_lookup_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_Key_value_pair, Key_value_lookup_node );
+ while ( p->key == the_key->Object.id) {
+ iter = next;
+ next = _RBTree_Next_unprotected( iter, RBT_LEFT );
+ p = _RBTree_Container_of( next, POSIX_Keys_Key_value_pair, Key_value_lookup_node );
+ }
+
+ /**
+ * delete all nodes belongs to the_key from the rbtree and chain.
+ */
+ p = _RBTree_Container_of( iter, POSIX_Keys_Key_value_pair, Key_value_lookup_node );
+ while ( p->key == the_key->Object.id ) {
+ next = _RBTree_Next_unprotected( iter, RBT_RIGHT );
+ _RBTree_Extract_unprotected( &_POSIX_Keys_Key_value_lookup_tree, iter );
+ _Chain_Extract_unprotected( &p->Key_values_per_thread_node );
+ /* append the node to _POSIX_Keys_Keypool */
+ _Freechain_Put( &_POSIX_Keys_Keypool.super_fc,
+ ( void * )p);
+ iter = next;
+ p = _RBTree_Container_of( iter, POSIX_Keys_Key_value_pair, Key_value_lookup_node );
+ }
}
diff --git a/cpukit/posix/src/keygetspecific.c b/cpukit/posix/src/keygetspecific.c
index 0e8bbcdec8..88e084ee96 100644
--- a/cpukit/posix/src/keygetspecific.c
+++ b/cpukit/posix/src/keygetspecific.c
@@ -6,12 +6,13 @@
*/
/*
- * COPYRIGHT (c) 1989-2007.
- * On-Line Applications Research Corporation (OAR).
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -26,6 +27,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,20 +38,31 @@ void *pthread_getspecific(
pthread_key_t key
)
{
- register POSIX_Keys_Control *the_key;
- uint32_t api;
- uint32_t index;
Objects_Locations location;
+ POSIX_Keys_Key_value_pair search_node;
+ RBTree_Node *p;
void *key_data;
+ POSIX_Keys_Key_value_pair *value_pair_p;
- 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 ];
- _Objects_Put( &the_key->Object );
+ search_node.key = key;
+ search_node.thread_id = _Thread_Executing->Object.id;
+ p = _RBTree_Find_unprotected( &_POSIX_Keys_Key_value_lookup_tree,
+ &search_node.Key_value_lookup_node );
+ key_data = NULL;
+ if ( p ) {
+ value_pair_p = _RBTree_Container_of( p,
+ POSIX_Keys_Key_value_pair,
+ Key_value_lookup_node );
+ /* key_data = _RBTree_Container_of( p, */
+ /* POSIX_Keys_Key_value_pair, */
+ /* Key_value_lookup_node )->value; */
+ key_data = value_pair_p->value;
+ }
+ _Thread_Enable_dispatch();
return key_data;
#if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/posix/src/keyrundestructors.c b/cpukit/posix/src/keyrundestructors.c
index eb692e0dc9..7e3c88fdb6 100644
--- a/cpukit/posix/src/keyrundestructors.c
+++ b/cpukit/posix/src/keyrundestructors.c
@@ -6,14 +6,15 @@
*/
/*
- * Copyright (c) 2010 embedded brains GmbH.
+ * Copyright (c) 2012 Zhongwei Yao.
+ * Copyright (c) 2010 embedded brains GmbH.
*
- * COPYRIGHT (c) 1989-2007.
- * On-Line Applications Research Corporation (OAR).
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -22,7 +23,10 @@
#include <rtems/system.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
@@ -32,41 +36,60 @@
* NOTE: This is the routine executed when a thread exits to
* run through all the keys and do the destructor action.
*/
-
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_Key_value_pair *,
+ * because Chain_Node is the first member of POSIX_Keys_Key_value_pair
+ * structure.
+ */
+ _RBTree_Extract_unprotected(
+ &_POSIX_Keys_Key_value_lookup_tree,
+ &((POSIX_Keys_Key_value_pair *)iter)->Key_value_lookup_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_Key_value_pair *)iter)->key,
+ &location
+ );
+ destructor = the_key->destructor;
+ value = ((POSIX_Keys_Key_value_pair *)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 ];
+ /**
+ * put back this node to keypool
+ */
+ _Freechain_Put( &_POSIX_Keys_Keypool.super_fc,
+ (void *)iter );
- if ( value != NULL ) {
- key->Values [ thread_api ][ thread_index ] = NULL;
- (*key->destructor)( value );
- done = false;
- }
- }
- }
+ iter = next;
}
+ _Thread_Enable_dispatch();
}
diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c
index 22eb8eb643..f527fe1ee4 100644
--- a/cpukit/posix/src/keysetspecific.c
+++ b/cpukit/posix/src/keysetspecific.c
@@ -6,12 +6,13 @@
*/
/*
- * COPYRIGHT (c) 1989-2007.
- * On-Line Applications Research Corporation (OAR).
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -22,11 +23,14 @@
#include <limits.h>
#include <pthread.h>
#include <string.h>
+#include <stddef.h>
#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,19 +41,38 @@ int pthread_setspecific(
const void *value
)
{
- register POSIX_Keys_Control *the_key;
- uint32_t api;
- uint32_t index;
Objects_Locations location;
+ POSIX_Keys_Key_value_pair *value_pair_ptr;
+ POSIX_API_Control *api;
- 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 );
- the_key->Values[ api ][ index ] = (void *) value;
- _Objects_Put( &the_key->Object );
+ value_pair_ptr = ( POSIX_Keys_Key_value_pair * )
+ _Freechain_Get( &_POSIX_Keys_Keypool.super_fc );
+ if ( !value_pair_ptr ) {
+ _Thread_Enable_dispatch();
+ return ENOMEM;
+ }
+
+ value_pair_ptr->key = key;
+ value_pair_ptr->thread_id = _Thread_Executing->Object.id;
+ value_pair_ptr->value = value;
+ if ( _RBTree_Insert_unprotected( &_POSIX_Keys_Key_value_lookup_tree,
+ &(value_pair_ptr->Key_value_lookup_node) ) ) {
+ _Freechain_Put( (Freechain_Control *)&_POSIX_Keys_Keypool,
+ (void *) value_pair_ptr );
+ _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, &value_pair_ptr->Key_values_per_thread_node );
+
+ _Thread_Enable_dispatch();
return 0;
#if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c
index 121b0874e7..13f7525c75 100644
--- a/cpukit/posix/src/pthread.c
+++ b/cpukit/posix/src/pthread.c
@@ -236,6 +236,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/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index ed1385a3c9..50db8779af 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -1728,11 +1728,17 @@ const rtems_libio_helper rtems_fs_init_helper =
#ifndef CONFIGURE_MAXIMUM_POSIX_KEYS
#define CONFIGURE_MAXIMUM_POSIX_KEYS 0
- #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys) 0
+ #define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 0
+ #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys, _key_value_pairs) 0
#else
- #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys) \
+ #ifndef CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS
+ #define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS \
+ CONFIGURE_MAXIMUM_POSIX_KEYS \
+ * (CONFIGURE_MAXIMUM_POSIX_THREADS + CONFIGURE_MAXIMUM_TASKS)
+ #endif
+ #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys, _key_value_pairs) \
(_Configure_Object_RAM(_keys, sizeof(POSIX_Keys_Control) ) \
- + (_keys) * 3 * _Configure_From_workspace(sizeof(void *) * 2))
+ + _Configure_From_workspace(_key_value_pairs * sizeof(POSIX_Keys_Key_value_pair)))
#endif
#ifndef CONFIGURE_MAXIMUM_POSIX_TIMERS
@@ -1854,7 +1860,8 @@ const rtems_libio_helper rtems_fs_init_helper =
CONFIGURE_MEMORY_FOR_POSIX_CONDITION_VARIABLES( \
CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES + \
CONFIGURE_MAXIMUM_GO_CHANNELS + CONFIGURE_GO_INIT_CONDITION_VARIABLES) + \
- CONFIGURE_MEMORY_FOR_POSIX_KEYS( CONFIGURE_MAXIMUM_POSIX_KEYS ) + \
+ CONFIGURE_MEMORY_FOR_POSIX_KEYS( CONFIGURE_MAXIMUM_POSIX_KEYS, \
+ CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS ) + \
CONFIGURE_MEMORY_FOR_POSIX_QUEUED_SIGNALS( \
CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS ) + \
CONFIGURE_MEMORY_FOR_POSIX_MESSAGE_QUEUES( \
@@ -2303,6 +2310,7 @@ const rtems_libio_helper rtems_fs_init_helper =
CONFIGURE_MAXIMUM_ADA_TASKS + CONFIGURE_MAXIMUM_FAKE_ADA_TASKS +
CONFIGURE_GO_INIT_CONDITION_VARIABLES + CONFIGURE_MAXIMUM_GO_CHANNELS,
CONFIGURE_MAXIMUM_POSIX_KEYS,
+ CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS,
CONFIGURE_MAXIMUM_POSIX_TIMERS,
CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS,
CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES,
@@ -2545,7 +2553,8 @@ const rtems_libio_helper rtems_fs_init_helper =
CONFIGURE_MEMORY_FOR_POSIX_CONDITION_VARIABLES(
CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES +
CONFIGURE_MAXIMUM_GO_CHANNELS + CONFIGURE_GO_INIT_CONDITION_VARIABLES),
- CONFIGURE_MEMORY_FOR_POSIX_KEYS( CONFIGURE_MAXIMUM_POSIX_KEYS ),
+ CONFIGURE_MEMORY_FOR_POSIX_KEYS( CONFIGURE_MAXIMUM_POSIX_KEYS, \
+ CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS ),
CONFIGURE_MEMORY_FOR_POSIX_QUEUED_SIGNALS(
CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS ),
CONFIGURE_MEMORY_FOR_POSIX_MESSAGE_QUEUES(
@@ -2616,6 +2625,7 @@ const rtems_libio_helper rtems_fs_init_helper =
(CONFIGURE_MAXIMUM_POSIX_MUTEXES != 0) || \
(CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES != 0) || \
(CONFIGURE_MAXIMUM_POSIX_KEYS != 0) || \
+ (CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS != 0) || \
(CONFIGURE_MAXIMUM_POSIX_TIMERS != 0) || \
(CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS != 0) || \
(CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES != 0) || \
@@ -2697,5 +2707,19 @@ const rtems_libio_helper rtems_fs_init_helper =
#error "Fewer POSIX Message Queue descriptors than Queues!"
#endif
+/*
+ * POSIX Key pair shouldn't be less than POSIX Key, which is highly
+ * likely to be error.
+ */
+#if defined(RTEMS_POSIX_API)
+ #if (CONFIGURE_MAXIMUM_POSIX_KEYS != 0) && \
+ (CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS != 0)
+ #if (CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS < \
+ CONFIGURE_MAXIMUM_POSIX_KEYS)
+ #error "Fewer POSIX Key pairs than POSIX Key!"
+ #endif
+ #endif
+#endif
+
#endif
/* end of include file */
diff --git a/testsuites/psxtests/Makefile.am b/testsuites/psxtests/Makefile.am
index 0e8a3e805b..423cf07043 100644
--- a/testsuites/psxtests/Makefile.am
+++ b/testsuites/psxtests/Makefile.am
@@ -7,7 +7,8 @@ SUBDIRS += psxhdrs psx01 psx02 psx03 psx04 psx05 psx06 psx07 psx08 psx09 \
psxaio01 psxaio02 psxaio03 \
psxalarm01 psxautoinit01 psxautoinit02 psxbarrier01 \
psxcancel psxcancel01 psxclassic01 psxcleanup psxcleanup01 \
- psxcond01 psxconfig01 psxenosys psxkey01 psxkey02 psxkey03 \
+ psxcond01 psxconfig01 psxenosys psxkey01 psxkey02 psxkey03 psxkey04 \
+ psxkey05 psxkey06 psxkey07 psxkey08 psxkey09 psxkey10 \
psxitimer psxmsgq01 psxmsgq02 psxmsgq03 psxmsgq04 \
psxmutexattr01 psxobj01 psxrwlock01 psxsem01 psxsignal01 psxsignal02 \
psxsignal03 psxsignal04 psxsignal05 psxsignal06 \
diff --git a/testsuites/psxtests/configure.ac b/testsuites/psxtests/configure.ac
index a04fc5ec65..8e0a2384cd 100644
--- a/testsuites/psxtests/configure.ac
+++ b/testsuites/psxtests/configure.ac
@@ -122,6 +122,13 @@ psxitimer/Makefile
psxkey01/Makefile
psxkey02/Makefile
psxkey03/Makefile
+psxkey04/Makefile
+psxkey05/Makefile
+psxkey06/Makefile
+psxkey07/Makefile
+psxkey08/Makefile
+psxkey09/Makefile
+psxkey10/Makefile
psxmount/Makefile
psxmsgq01/Makefile
psxmsgq02/Makefile
diff --git a/testsuites/psxtests/psxkey01/init.c b/testsuites/psxtests/psxkey01/init.c
index 3383c8da3c..e63407cda8 100644
--- a/testsuites/psxtests/psxkey01/init.c
+++ b/testsuites/psxtests/psxkey01/init.c
@@ -43,10 +43,10 @@ void *POSIX_Init(
rtems_workspace_greedy_allocate( NULL, 0 );
- puts("Init: pthread_key_create - ENOMEM (Workspace not available)");
+ puts("Init: pthread_key_create - OK");
empty_line();
status = pthread_key_create( &Key_id[0], Key_destructor );
- fatal_directive_check_status_only( status, ENOMEM, "no workspace available" );
+ fatal_directive_check_status_only( status, 0, "OK" );
puts( "*** END OF POSIX KEY 01 TEST ***" );
rtems_test_exit( 0 );
diff --git a/testsuites/psxtests/psxkey01/psxkey01.scn b/testsuites/psxtests/psxkey01/psxkey01.scn
index 597b0f8e23..e1a747c8ab 100644
--- a/testsuites/psxtests/psxkey01/psxkey01.scn
+++ b/testsuites/psxtests/psxkey01/psxkey01.scn
@@ -1,5 +1,5 @@
*** POSIX KEY 01 TEST ***
Init's ID is 0x0b010001
-Allocate_majority_of_workspace:
-Init: pthread_key_create - ENOMEM (Workspace not available)
+Init: pthread_key_create - OK
+
*** END OF POSIX KEY 01 TEST ***
diff --git a/testsuites/psxtests/psxkey04/Makefile.am b/testsuites/psxtests/psxkey04/Makefile.am
new file mode 100644
index 0000000000..cd5f2bb8c1
--- /dev/null
+++ b/testsuites/psxtests/psxkey04/Makefile.am
@@ -0,0 +1,23 @@
+
+rtems_tests_PROGRAMS = psxkey04
+psxkey04_SOURCES = init.c
+
+dist_rtems_tests_DATA = psxkey04.scn
+dist_rtems_tests_DATA += psxkey04.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxkey04_OBJECTS)
+LINK_LIBS = $(psxkey04_LDLIBS)
+
+psxkey04$(EXEEXT): $(psxkey04_OBJECTS) $(psxkey04_DEPENDENCIES)
+ @rm -f psxkey04$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxkey04/init.c b/testsuites/psxtests/psxkey04/init.c
new file mode 100644
index 0000000000..76540dd76f
--- /dev/null
+++ b/testsuites/psxtests/psxkey04/init.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+#include "tmacros.h"
+#include "pmacros.h"
+
+/* forward declarations to avoid warnings */
+void *POSIX_Init(void *argument);
+void *Test_Thread1(void *argument);
+void *Test_Thread2(void *argument);
+
+int Data_array[2] = {1, 2};
+pthread_t thread1, thread2;
+
+pthread_key_t Key;
+
+void *Test_Thread1(
+ void *argument
+)
+{
+ int sc;
+ int *value;
+ struct timespec delay_request;
+ /*
+ * Detach ourselves so we don't wait for a join that won't happen.
+ */
+ pthread_detach( pthread_self() );
+
+ puts( "Test_Thread 1 - pthread_setspecific - OK" );
+ sc = pthread_setspecific( Key, &Data_array[0] );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread 1 - sleep - let thread 2 run - OK" );
+ delay_request.tv_sec = 0;
+ delay_request.tv_nsec = 4 * 100000000;
+ sc = nanosleep( &delay_request, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread 1 - pthread_getspecific - OK" );
+ value = pthread_getspecific( Key );
+ rtems_test_assert( *value == Data_array[0] );
+
+ return NULL;
+}
+
+void *Test_Thread2(
+ void *argument
+)
+{
+ int sc;
+ int *value;
+ /*
+ * Detach ourselves so we don't wait for a join that won't happen.
+ */
+ pthread_detach( pthread_self() );
+
+ puts( "Test_Thread 2 - pthread_setspecific - OK" );
+ sc = pthread_setspecific( Key, &Data_array[1] );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread 2 - pthread_getspecific - OK" );
+ value = pthread_getspecific( Key );
+ rtems_test_assert( *value == Data_array[1] );
+
+ return NULL;
+}
+
+void *POSIX_Init(
+ void *ignored
+)
+{
+ int sc;
+ struct timespec delay_request;
+
+ puts( "\n\n*** TEST KEY 04 ***" );
+
+ puts( "Init - pthread_key_create - OK" );
+ sc = pthread_key_create( &Key, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread_create - OK" );
+ sc = pthread_create( &thread1, NULL, Test_Thread1, NULL );
+ rtems_test_assert( !sc );
+
+ sc = pthread_create( &thread2, NULL, Test_Thread2, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - sleep - let thread run - OK" );
+ delay_request.tv_sec = 0;
+ delay_request.tv_nsec = 8 * 100000000;
+ sc = nanosleep( &delay_request, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread_key_delete - OK" );
+ sc = pthread_key_delete( Key );
+ rtems_test_assert( sc == 0 );
+
+ puts( "*** END OF TEST KEY 04 ***" );
+ rtems_test_exit(0);
+}
+
+/* configuration information */
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 3
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
+/* global variables */
diff --git a/testsuites/psxtests/psxkey04/psxkey04.doc b/testsuites/psxtests/psxkey04/psxkey04.doc
new file mode 100644
index 0000000000..6438d4e501
--- /dev/null
+++ b/testsuites/psxtests/psxkey04/psxkey04.doc
@@ -0,0 +1,22 @@
+# COPYRIGHT (c) 1989-2009.
+# On-Line Applications Research Corporation (OAR).
+#
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.com/license/LICENSE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxkey04
+
+directives:
+
+ pthread_key_create
+ pthread_setspecific
+ pthread_getspecific
+ pthread_key_delete
+
+concepts:
+
++ Ensure that key data's operation(set and get) under multithreads work.
diff --git a/testsuites/psxtests/psxkey04/psxkey04.scn b/testsuites/psxtests/psxkey04/psxkey04.scn
new file mode 100644
index 0000000000..aa0500fcba
--- /dev/null
+++ b/testsuites/psxtests/psxkey04/psxkey04.scn
@@ -0,0 +1,11 @@
+*** TEST KEY 04 ***
+Init - pthread_key_create - OK
+Init - pthread_create - OK
+Init - sleep - let thread run - OK
+Test_Thread 1 - pthread_setspecific - OK
+Test_Thread 1 - sleep - let thread 2 run - OK
+Test_Thread 2 - pthread_setspecific - OK
+Test_Thread 2 - pthread_getspecific - OK
+Test_Thread 1 - pthread_getspecific - OK
+Init - pthread_key_delete - OK
+*** END OF TEST KEY 04 ***
diff --git a/testsuites/psxtests/psxkey05/Makefile.am b/testsuites/psxtests/psxkey05/Makefile.am
new file mode 100644
index 0000000000..c253900c06
--- /dev/null
+++ b/testsuites/psxtests/psxkey05/Makefile.am
@@ -0,0 +1,23 @@
+
+rtems_tests_PROGRAMS = psxkey05
+psxkey05_SOURCES = init.c
+
+dist_rtems_tests_DATA = psxkey05.scn
+dist_rtems_tests_DATA += psxkey05.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxkey05_OBJECTS)
+LINK_LIBS = $(psxkey05_LDLIBS)
+
+psxkey05$(EXEEXT): $(psxkey05_OBJECTS) $(psxkey05_DEPENDENCIES)
+ @rm -f psxkey05$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxkey05/init.c b/testsuites/psxtests/psxkey05/init.c
new file mode 100644
index 0000000000..08d22b0cbd
--- /dev/null
+++ b/testsuites/psxtests/psxkey05/init.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+#include "tmacros.h"
+#include "pmacros.h"
+
+/* forward declarations to avoid warnings */
+void *POSIX_Init(void *argument);
+
+void *POSIX_Init(
+ void *ignored
+)
+{
+ pthread_key_t key1, key2;
+ int sc, *value;
+ int Data_array[2] = {1, 2};
+
+ puts( "\n\n*** TEST KEY 05 ***" );
+
+ puts( "Init - pthread key1 create - OK" );
+ sc = pthread_key_create( &key1, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread key2 create - OK" );
+ sc = pthread_key_create( &key2, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - key1 pthread_setspecific - OK" );
+ sc = pthread_setspecific( key1, &Data_array[0] );
+ rtems_test_assert( !sc );
+
+ puts( "Init - key2 pthread_setspecific - OK" );
+ sc = pthread_setspecific( key2, &Data_array[1] );
+ rtems_test_assert( !sc );
+
+ puts( "Init - key1 pthread_getspecific - OK" );
+ value = pthread_getspecific( key1 );
+ rtems_test_assert( *value == Data_array[0] );
+
+ puts( "Init - key2 pthread_getspecific - OK" );
+ value = pthread_getspecific( key2 );
+ rtems_test_assert( *value == Data_array[1] );
+
+ puts( "Init - pthread key1 delete - OK" );
+ sc = pthread_key_delete( key1 );
+ rtems_test_assert( sc == 0 );
+
+ puts( "Init - pthread key2 delete - OK" );
+ sc = pthread_key_delete( key2 );
+ rtems_test_assert( sc == 0 );
+
+ puts( "*** END OF TEST KEY 05 ***" );
+ rtems_test_exit(0);
+}
+
+/* configuration information */
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 1
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 2
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
+/* global variables */
diff --git a/testsuites/psxtests/psxkey05/psxkey05.doc b/testsuites/psxtests/psxkey05/psxkey05.doc
new file mode 100644
index 0000000000..f4359d64c7
--- /dev/null
+++ b/testsuites/psxtests/psxkey05/psxkey05.doc
@@ -0,0 +1,22 @@
+# COPYRIGHT (c) 1989-2009.
+# On-Line Applications Research Corporation (OAR).
+#
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.com/license/LICENSE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxkey05
+
+directives:
+
+ pthread_key_create
+ pthread_setspecific
+ pthread_getspecific
+ pthread_key_delete
+
+concepts:
+
++ Ensure that key data's operation(create, set, get and delete) under multikeys work.
diff --git a/testsuites/psxtests/psxkey05/psxkey05.scn b/testsuites/psxtests/psxkey05/psxkey05.scn
new file mode 100644
index 0000000000..f352a36785
--- /dev/null
+++ b/testsuites/psxtests/psxkey05/psxkey05.scn
@@ -0,0 +1,10 @@
+*** TEST KEY 05 ***
+Init - pthread key1 create - OK
+Init - pthread key2 create - OK
+Init - key1 pthread_setspecific - OK
+Init - key1 pthread_getspecific - OK
+Init - key2 pthread_setspecific - OK
+Init - key2 pthread_getspecific - OK
+Init - pthread key1 delete - OK
+Init - pthread key2 delete - OK
+*** END OF TEST KEY 05 *** \ No newline at end of file
diff --git a/testsuites/psxtests/psxkey06/Makefile.am b/testsuites/psxtests/psxkey06/Makefile.am
new file mode 100644
index 0000000000..9815baf4eb
--- /dev/null
+++ b/testsuites/psxtests/psxkey06/Makefile.am
@@ -0,0 +1,23 @@
+
+rtems_tests_PROGRAMS = psxkey06
+psxkey06_SOURCES = init.c
+
+dist_rtems_tests_DATA = psxkey06.scn
+dist_rtems_tests_DATA += psxkey06.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxkey06_OBJECTS)
+LINK_LIBS = $(psxkey06_LDLIBS)
+
+psxkey06$(EXEEXT): $(psxkey06_OBJECTS) $(psxkey06_DEPENDENCIES)
+ @rm -f psxkey06$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxkey06/init.c b/testsuites/psxtests/psxkey06/init.c
new file mode 100644
index 0000000000..98b46a42be
--- /dev/null
+++ b/testsuites/psxtests/psxkey06/init.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+#include "tmacros.h"
+#include "pmacros.h"
+
+/* forward declarations to avoid warnings */
+void *POSIX_Init(void *argument);
+void *Test_Thread1(void *argument);
+void *Test_Thread2(void *argument);
+
+int Data_array[4] = {1, 2, 3, 4};
+
+pthread_key_t key1, key2;
+
+void *Test_Thread1(
+ void *argument
+)
+{
+ int sc;
+ int *value;
+ struct timespec delay_request;
+ /*
+ * Detach ourselves so we don't wait for a join that won't happen.
+ */
+ pthread_detach( pthread_self() );
+
+ puts( "Test_Thread 1 - key1 pthread_setspecific - OK" );
+ sc = pthread_setspecific( key1, &Data_array[0] );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread 1 - key2 pthread_setspecific - OK" );
+ sc = pthread_setspecific( key2, &Data_array[1] );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread 1 - sleep - let thread2 run - OK" );
+ delay_request.tv_sec = 0;
+ delay_request.tv_nsec = 4 * 100000000;
+ sc = nanosleep( &delay_request, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread 1 - key1 pthread_getspecific - OK" );
+ value = pthread_getspecific( key1 );
+ rtems_test_assert( *value == Data_array[0] );
+
+ puts( "Test_Thread 1 - key2 pthread_getspecific - OK" );
+ value = pthread_getspecific( key2 );
+ rtems_test_assert( *value == Data_array[1] );
+
+ return NULL;
+}
+
+void *Test_Thread2(
+ void *argument
+)
+{
+ int sc;
+ int *value;
+ /*
+ * Detach ourselves so we don't wait for a join that won't happen.
+ */
+ pthread_detach( pthread_self() );
+
+ puts( "Test_Thread 2 - key1 pthread_setspecific - OK" );
+ sc = pthread_setspecific( key1, &Data_array[2] );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread 2 - key2 pthread_setspecific - OK" );
+ sc = pthread_setspecific( key2, &Data_array[3] );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread 2 - key1 pthread_getspecific - OK" );
+ value = pthread_getspecific( key1 );
+ rtems_test_assert( *value == Data_array[2] );
+
+ puts( "Test_Thread 2 - key2 pthread_getspecific - OK" );
+ value = pthread_getspecific( key2 );
+ rtems_test_assert( *value == Data_array[3] );
+
+ return NULL;
+}
+
+void *POSIX_Init(
+ void *ignored
+)
+{
+ pthread_t thread1, thread2;
+ int sc;
+ struct timespec delay_request;
+
+ puts( "\n\n*** TEST KEY 06 ***" );
+
+ puts( "Init - pthread key1 create - OK" );
+ sc = pthread_key_create( &key1, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread key2 create - OK" );
+ sc = pthread_key_create( &key2, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread1 create - OK" );
+ sc = pthread_create( &thread1, NULL, Test_Thread1, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread2 create - OK" );
+ sc = pthread_create( &thread2, NULL, Test_Thread2, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - sleep - let thread run - OK" );
+ delay_request.tv_sec = 0;
+ delay_request.tv_nsec = 8 * 100000000;
+ sc = nanosleep( &delay_request, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread key1 delete - OK" );
+ sc = pthread_key_delete( key1 );
+ rtems_test_assert( sc == 0 );
+
+ puts( "Init - pthread key2 delete - OK" );
+ sc = pthread_key_delete( key2 );
+ rtems_test_assert( sc == 0 );
+
+ puts( "*** END OF TEST KEY 06 ***" );
+ rtems_test_exit(0);
+}
+
+/* configuration information */
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 3
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 2
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
+/* global variables */
diff --git a/testsuites/psxtests/psxkey06/psxkey06.doc b/testsuites/psxtests/psxkey06/psxkey06.doc
new file mode 100644
index 0000000000..6becdb9e66
--- /dev/null
+++ b/testsuites/psxtests/psxkey06/psxkey06.doc
@@ -0,0 +1,23 @@
+# COPYRIGHT (c) 1989-2009.
+# On-Line Applications Research Corporation (OAR).
+#
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.com/license/LICENSE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxkey06
+
+directives:
+
+ pthread_key_create
+ pthread_setspecific
+ pthread_getspecific
+ pthread_key_delete
+
+concepts:
+
++ Ensure that key data's operation(create, set, get and delete) under
+ multikeys and multi threads work.
diff --git a/testsuites/psxtests/psxkey06/psxkey06.scn b/testsuites/psxtests/psxkey06/psxkey06.scn
new file mode 100644
index 0000000000..a105b6fd8f
--- /dev/null
+++ b/testsuites/psxtests/psxkey06/psxkey06.scn
@@ -0,0 +1,18 @@
+*** TEST KEY 06 ***
+Init - pthread key1 create - OK
+Init - pthread key2 create - OK
+Init - pthread1 create - OK
+Init - pthread2 create - OK
+Init - sleep - let thread run - OK
+Test_Thread 1 - key1 pthread_setspecific - OK
+Test_Thread 1 - key2 pthread_setspecific - OK
+Test_Thread 1 - sleep - let thread2 run - OK
+Test_Thread 2 - key1 pthread_setspecific - OK
+Test_Thread 2 - key2 pthread_setspecific - OK
+Test_Thread 2 - key1 pthread_getspecific - OK
+Test_Thread 2 - key2 pthread_getspecific - OK
+Test_Thread 1 - key1 pthread_getspecific - OK
+Test_Thread 1 - key2 pthread_getspecific - OK
+Init - pthread key1 delete - OK
+Init - pthread key2 delete - OK
+*** END OF TEST KEY 06 ***
diff --git a/testsuites/psxtests/psxkey07/Makefile.am b/testsuites/psxtests/psxkey07/Makefile.am
new file mode 100644
index 0000000000..a701f309b2
--- /dev/null
+++ b/testsuites/psxtests/psxkey07/Makefile.am
@@ -0,0 +1,23 @@
+
+rtems_tests_PROGRAMS = psxkey07
+psxkey07_SOURCES = init.c
+
+dist_rtems_tests_DATA = psxkey07.scn
+dist_rtems_tests_DATA += psxkey07.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxkey07_OBJECTS)
+LINK_LIBS = $(psxkey07_LDLIBS)
+
+psxkey07$(EXEEXT): $(psxkey07_OBJECTS) $(psxkey07_DEPENDENCIES)
+ @rm -f psxkey07$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxkey07/init.c b/testsuites/psxtests/psxkey07/init.c
new file mode 100644
index 0000000000..e911dc77d9
--- /dev/null
+++ b/testsuites/psxtests/psxkey07/init.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <sched.h>
+#include <errno.h>
+#include "tmacros.h"
+#include "pmacros.h"
+
+/* forward declarations to avoid warnings */
+void *POSIX_Init(void *argument);
+void *Test_Thread(void *argument);
+
+pthread_key_t Key;
+int created_thread_count, setted_thread_count, got_thread_count;
+int all_thread_created;
+pthread_mutex_t mutex1, mutex2;
+pthread_cond_t create_condition_var, set_condition_var;
+
+void *Test_Thread(
+ void *argument
+)
+{
+ int sc;
+ int *value_p, *value_p2;
+
+ value_p = malloc( sizeof( int ) );
+ //printf( "Test_Thread%d - Key pthread_setspecific - OK\n", (int)pthread_self() );
+ sc = pthread_setspecific( Key, value_p );
+ rtems_test_assert( !sc );
+ pthread_mutex_lock( &mutex1 );
+ ++setted_thread_count;
+ pthread_cond_signal( &set_condition_var );
+ pthread_mutex_unlock( &mutex1 );
+
+ /**
+ * blocked untill all threads have been created.
+ */
+ pthread_mutex_lock( &mutex2 );
+ while( !all_thread_created )
+ pthread_cond_wait( &create_condition_var, &mutex2 );
+ pthread_mutex_unlock( &mutex2 );
+
+ //printf( "Test_Thread%d - Key pthread_getspecific - OK\n", (int)pthread_self() );
+ value_p2 = pthread_getspecific( Key );
+ rtems_test_assert( value_p == value_p2 );
+ ++got_thread_count;
+
+ return NULL;
+}
+
+void *POSIX_Init(
+ void *ignored
+)
+{
+ pthread_t *thread_p;
+ int sc;
+ struct timespec delay_request;
+ all_thread_created = 0;
+
+ puts( "\n\n*** TEST KEY 07 ***" );
+
+ puts( "Init - Mutex 1 create - OK" );
+ sc = pthread_mutex_init( &mutex1, NULL );
+ rtems_test_assert( !sc );
+ puts( "Init - Mutex 2 create - OK" );
+ sc = pthread_mutex_init( &mutex2, NULL );
+ rtems_test_assert( !sc );
+ puts( "Init - Condition variable 1 create - OK" );
+ sc = pthread_cond_init( &create_condition_var, NULL );
+ rtems_test_assert( !sc );
+ puts( "Init - Condition variable 2 create - OK" );
+ sc = pthread_cond_init( &set_condition_var, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread Key create - OK" );
+ sc = pthread_key_create( &Key, NULL );
+ rtems_test_assert( !sc );
+
+ for( ; ; )
+ {
+ thread_p = malloc( sizeof( pthread_t ) );
+ rtems_test_assert( thread_p );
+ pthread_mutex_lock( &mutex1 );
+ sc = pthread_create( thread_p, NULL, Test_Thread, NULL );
+ rtems_test_assert( ( sc == 0 ) || ( sc == EAGAIN ) );
+ /**
+ * check if return is EAGAIN, it means RTEMS Workspace RAM
+ * have been exhausted.
+ */
+ if ( sc == EAGAIN )
+ {
+ pthread_mutex_unlock( &mutex1 );
+ break;
+ }
+ ++created_thread_count;
+ /**
+ * wait for test thread set key, the while loop here is used to
+ * avoid suprious wakeup.
+ */
+ while( created_thread_count > setted_thread_count )
+ pthread_cond_wait( &set_condition_var, &mutex1 );
+ pthread_mutex_unlock( &mutex1 );
+ }
+ printf( "Init - %d pthreads have been created - OK\n", created_thread_count );
+ printf( "Init - %d pthreads have been setted key data - OK\n", setted_thread_count );
+ rtems_test_assert( created_thread_count == setted_thread_count );
+ /* unblock all created pthread to let them set key data.*/
+ pthread_mutex_lock( &mutex2 );
+ all_thread_created = 1;
+ pthread_cond_broadcast( &create_condition_var );
+ pthread_mutex_unlock( &mutex2 );
+
+ puts( "Init - sleep - let threads run - OK" );
+ delay_request.tv_sec = 0;
+ delay_request.tv_nsec = 8 * 100000000;
+ sc = nanosleep( &delay_request, NULL );
+ rtems_test_assert( !sc );
+
+ printf( "Init - %d pthreads have been got key data - OK\n", got_thread_count );
+ rtems_test_assert( created_thread_count == got_thread_count );
+ puts( "Init - pthread Key delete - OK" );
+ sc = pthread_key_delete( Key );
+ rtems_test_assert( sc == 0 );
+
+ puts( "Init - Mutex1 delete - OK" );
+ sc = pthread_mutex_destroy( &mutex1 );
+ rtems_test_assert( !sc );
+ puts( "Init - Mutex2 delete - OK" );
+ sc = pthread_mutex_destroy( &mutex2 );
+ rtems_test_assert( !sc );
+ puts( "Init - Condition variable 1 delete - OK" );
+ sc = pthread_cond_destroy( &create_condition_var );
+ rtems_test_assert( !sc );
+ puts( "Init - Condition variable 2 delete - OK" );
+ sc = pthread_cond_destroy( &set_condition_var );
+ rtems_test_assert( !sc );
+
+ puts( "*** END OF TEST KEY 07 ***" );
+ rtems_test_exit(0);
+}
+
+/* configuration information */
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS rtems_resource_unlimited(10)
+#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 2
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
+#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 2
+#define CONFIGURE_UNIFIED_WORK_AREAS
+
+
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
+/* global variables */
diff --git a/testsuites/psxtests/psxkey07/psxkey07.doc b/testsuites/psxtests/psxkey07/psxkey07.doc
new file mode 100644
index 0000000000..16d93de78c
--- /dev/null
+++ b/testsuites/psxtests/psxkey07/psxkey07.doc
@@ -0,0 +1,26 @@
+# COPYRIGHT (c) 1989-2009.
+# On-Line Applications Research Corporation (OAR).
+#
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.com/license/LICENSE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxkey07
+
+directives:
+
+ pthread_key_create
+ pthread_setspecific
+ pthread_getspecific
+ pthread_key_delete
+
+concepts:
+
++ Ensure that key data's operation(create, set, get and delete) under unlimited configuration in POSIX API.
++ this test workflow is:
+ 1. create thread and set thread's key data one by one until exhausting workspace RAM
+ 2. when step 1 finished, let all thread created thread run the getspecific function to
+test if key set and get works correctly.
diff --git a/testsuites/psxtests/psxkey07/psxkey07.scn b/testsuites/psxtests/psxkey07/psxkey07.scn
new file mode 100644
index 0000000000..851876fce1
--- /dev/null
+++ b/testsuites/psxtests/psxkey07/psxkey07.scn
@@ -0,0 +1,18 @@
+
+
+*** TEST KEY 07 ***
+Init - Mutex 1 create - OK
+Init - Mutex 2 create - OK
+Init - Condition variable 1 create - OK
+Init - Condition variable 2 create - OK
+Init - pthread Key create - OK
+Init - 380 pthreads have been created - OK
+Init - 380 pthreads have been setted key data - OK
+Init - sleep - let threads run - OK
+Init - 380 pthreads have been got key data - OK
+Init - pthread Key delete - OK
+Init - Mutex1 delete - OK
+Init - Mutex2 delete - OK
+Init - Condition variable 1 delete - OK
+Init - Condition variable 2 delete - OK
+*** END OF TEST KEY 07 ***
diff --git a/testsuites/psxtests/psxkey08/Makefile.am b/testsuites/psxtests/psxkey08/Makefile.am
new file mode 100644
index 0000000000..e5bf7873ee
--- /dev/null
+++ b/testsuites/psxtests/psxkey08/Makefile.am
@@ -0,0 +1,23 @@
+
+rtems_tests_PROGRAMS = psxkey08
+psxkey08_SOURCES = init.c
+
+dist_rtems_tests_DATA = psxkey08.scn
+dist_rtems_tests_DATA += psxkey08.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxkey08_OBJECTS)
+LINK_LIBS = $(psxkey08_LDLIBS)
+
+psxkey08$(EXEEXT): $(psxkey08_OBJECTS) $(psxkey08_DEPENDENCIES)
+ @rm -f psxkey08$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxkey08/init.c b/testsuites/psxtests/psxkey08/init.c
new file mode 100644
index 0000000000..81f4378828
--- /dev/null
+++ b/testsuites/psxtests/psxkey08/init.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tmacros.h"
+
+#include <stdio.h>
+#include <rtems.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <errno.h>
+
+pthread_key_t Key;
+int created_task_count, setted_task_count, got_task_count;
+int all_thread_created;
+rtems_id sema1, sema2;
+rtems_name name1, name2;
+
+/* forward declarations to avoid warnings */
+rtems_task Init(rtems_task_argument arg);
+rtems_task test_task(rtems_task_argument arg);
+
+rtems_task test_task(rtems_task_argument arg)
+{
+ int sc;
+ int *value_p, *value_p2;
+
+ value_p = malloc( sizeof( int ) );
+ //printf( "Test_Task%d - Key pthread_setspecific - OK\n", (int)rtems_task_self() );
+ sc = pthread_setspecific( Key, value_p );
+ rtems_test_assert( !sc );
+ ++setted_task_count;
+ sc = rtems_semaphore_release( sema1 );
+
+ /**
+ * blocked untill all tasks have been created.
+ */
+ rtems_semaphore_obtain( sema2 , RTEMS_WAIT, 0 );
+
+ //printf( "Test_Task%d - Key pthread_getspecific - OK\n", (int)rtems_task_self() );
+ value_p2 = pthread_getspecific( Key );
+ rtems_test_assert( value_p == value_p2 );
+ ++got_task_count;
+
+ pthread_exit( 0 );
+}
+
+rtems_task Init(rtems_task_argument arg)
+{
+ rtems_status_code status;
+ int sc;
+ rtems_id *task_id_p;
+
+ all_thread_created = 0;
+
+ puts( "\n\n*** TEST KEY 08 ***" );
+
+ puts( "Init - Semaphore 1 create - OK" );
+ name1 = rtems_build_name('S', 'E', 'M', '1');
+ sc = rtems_semaphore_create( name1, 0,
+ RTEMS_SIMPLE_BINARY_SEMAPHORE |
+ RTEMS_FIFO,
+ 0, &sema1 );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+ puts( "Init - Semaphore 2 create - OK" );
+ name2 = rtems_build_name('S', 'E', 'M', '2');
+ sc = rtems_semaphore_create( name2, 0,
+ RTEMS_SIMPLE_BINARY_SEMAPHORE |
+ RTEMS_FIFO,
+ 0, &sema2 );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+ puts( "Init - pthread Key create - OK" );
+ sc = pthread_key_create( &Key, NULL );
+ rtems_test_assert( !sc );
+
+ for( ; ; )
+ {
+ task_id_p = malloc( sizeof( rtems_id ) );
+ rtems_test_assert( task_id_p );
+ sc = rtems_task_create(
+ rtems_build_name('T','A',created_task_count, ' '),
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ task_id_p
+ );
+ rtems_test_assert( (sc == RTEMS_UNSATISFIED) || (sc == RTEMS_TOO_MANY) || (sc == RTEMS_SUCCESSFUL) );
+ /**
+ * when return is RTEMS_TOO_MANY or RTEMS_UNSATISFIED, there is not
+ * enough source to create task.
+ */
+ if ( (sc == RTEMS_TOO_MANY) || (sc == RTEMS_UNSATISFIED) )
+ {
+ break;
+ }
+ ++created_task_count;
+ sc = rtems_task_start( *task_id_p, test_task, 0 );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+ sc = rtems_semaphore_obtain( sema1, RTEMS_WAIT, 0 );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+ }
+
+ printf( "Init - %d tasks have been created - OK\n", created_task_count );
+ printf( "Init - %d tasks have been setted key data - OK\n", setted_task_count );
+ rtems_test_assert( created_task_count == setted_task_count );
+
+ /* unblock all created tasks to let them set key data.*/
+ puts( "Init - flush semaphore 2 - OK" );
+ sc = rtems_semaphore_flush( sema2 );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+ puts( "Init - sleep to yield processor - OK" );
+ status = rtems_task_wake_after( RTEMS_YIELD_PROCESSOR );
+ directive_failed( status, "rtems_task_wake_after" );
+
+ printf( "Init - %d Tasks have been got key data - OK\n", got_task_count );
+ rtems_test_assert( created_task_count == got_task_count );
+ puts( "Init - pthread Key delete - OK" );
+ sc = pthread_key_delete( Key );
+ rtems_test_assert( sc == 0 );
+
+ puts( "Init - semaphore 1 delete - OK" );
+ sc = rtems_semaphore_delete( sema1 );
+ rtems_test_assert( !sc );
+
+ puts( "Init - semaphore 2 delete - OK" );
+ sc = rtems_semaphore_delete( sema2 );
+ rtems_test_assert( !sc );
+
+ puts( "*** END OF TEST KEY 08***" );
+ exit(0);
+}
+
+/* configuration information */
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(5)
+#define CONFIGURE_MAXIMUM_SEMAPHORES 2
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
+
+#define CONFIGURE_INIT_TASK_INITIAL_MODES \
+ (RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_ASR | RTEMS_INTERRUPT_LEVEL(0))
+
+#define CONFIGURE_INIT_TASK_PRIORITY 4
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_UNIFIED_WORK_AREAS
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+/* end of file */
diff --git a/testsuites/psxtests/psxkey08/psxkey08.doc b/testsuites/psxtests/psxkey08/psxkey08.doc
new file mode 100644
index 0000000000..5d0b1711c4
--- /dev/null
+++ b/testsuites/psxtests/psxkey08/psxkey08.doc
@@ -0,0 +1,25 @@
+# COPYRIGHT (c) 1989-2009.
+# On-Line Applications Research Corporation (OAR).
+#
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.com/license/LICENSE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxkey08
+
+directives:
+
+ pthread_key_create
+ pthread_setspecific
+ pthread_getspecific
+ pthread_key_delete
+
+concepts:
+
++ Ensure that key data's operation(create, set, get and delete) under unlimited configuration in RTEMS classic API. Note: posix key is allowed to be called by RTEMS classic API.
++ this test workflow is:
+ 1. create thread and set thread's key data one by one until exhausting workspace RAM
+ 2. when step 1 finished, let all thread created thread run the getspecific function to test if key set and get works correctly.
diff --git a/testsuites/psxtests/psxkey08/psxkey08.scn b/testsuites/psxtests/psxkey08/psxkey08.scn
new file mode 100644
index 0000000000..a4f1be4959
--- /dev/null
+++ b/testsuites/psxtests/psxkey08/psxkey08.scn
@@ -0,0 +1,15 @@
+
+
+*** TEST KEY 08 ***
+Init - Semaphore 1 create - OK
+Init - Semaphore 2 create - OK
+Init - pthread Key create - OK
+Init - 651 tasks have been created - OK
+Init - 651 tasks have been setted key data - OK
+Init - flush semaphore 2 - OK
+Init - sleep to yield processor - OK
+Init - 651 Tasks have been got key data - OK
+Init - pthread Key delete - OK
+Init - semaphore 1 delete - OK
+Init - semaphore 2 delete - OK
+*** END OF TEST KEY 08***
diff --git a/testsuites/psxtests/psxkey09/Makefile.am b/testsuites/psxtests/psxkey09/Makefile.am
new file mode 100644
index 0000000000..ed3ee0045d
--- /dev/null
+++ b/testsuites/psxtests/psxkey09/Makefile.am
@@ -0,0 +1,23 @@
+
+rtems_tests_PROGRAMS = psxkey09
+psxkey09_SOURCES = init.c
+
+dist_rtems_tests_DATA = psxkey09.scn
+dist_rtems_tests_DATA += psxkey09.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxkey09_OBJECTS)
+LINK_LIBS = $(psxkey09_LDLIBS)
+
+psxkey09$(EXEEXT): $(psxkey09_OBJECTS) $(psxkey09_DEPENDENCIES)
+ @rm -f psxkey09$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxkey09/init.c b/testsuites/psxtests/psxkey09/init.c
new file mode 100644
index 0000000000..a44f0e36ca
--- /dev/null
+++ b/testsuites/psxtests/psxkey09/init.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+#include "tmacros.h"
+#include "pmacros.h"
+
+
+/* forward declarations to avoid warnings */
+void *POSIX_Init(void *argument);
+void destructor(void *value);
+void *Test_Thread(void *argument);
+
+int Data_array[1] = {1};
+
+pthread_key_t key;
+volatile bool destructor_ran;
+
+void destructor(void *value)
+{
+ destructor_ran = true;
+}
+
+void *Test_Thread(
+ void *argument
+)
+{
+ int sc;
+
+ /**
+ * Detach ourselves to release test thread's resource after thread exit.
+ */
+ pthread_detach( pthread_self() );
+
+ puts( "Test_Thread - key pthread_setspecific - OK" );
+ sc = pthread_setspecific( key, argument );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread - pthread_exit to run key destructors - OK" );
+ return NULL;
+}
+
+void *POSIX_Init(
+ void *ignored
+)
+{
+ pthread_t thread;
+ int sc;
+ struct timespec delay_request;
+
+ puts( "\n\n*** TEST KEY 09 ***" );
+
+ puts( "Init - pthread key create with destructor - OK" );
+ sc = pthread_key_create( &key, destructor );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread create - OK" );
+ sc = pthread_create( &thread, NULL, Test_Thread, &sc );
+ rtems_test_assert( !sc );
+
+ puts( "Init - sleep - let thread run - OK" );
+ delay_request.tv_sec = 0;
+ delay_request.tv_nsec = 8 * 100000000;
+ sc = nanosleep( &delay_request, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - verify destructor run - OK" );
+ rtems_test_assert( destructor_ran == true );
+
+ puts( "Init - pthread key delete - OK" );
+ sc = pthread_key_delete( key );
+ rtems_test_assert( sc == 0 );
+
+ puts( "*** END OF TEST KEY 09 ***" );
+ rtems_test_exit(0);
+}
+
+/* configuration information */
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
+/* global variables */
diff --git a/testsuites/psxtests/psxkey09/psxkey09.doc b/testsuites/psxtests/psxkey09/psxkey09.doc
new file mode 100644
index 0000000000..ecb9b742be
--- /dev/null
+++ b/testsuites/psxtests/psxkey09/psxkey09.doc
@@ -0,0 +1,22 @@
+# COPYRIGHT (c) 1989-2009.
+# On-Line Applications Research Corporation (OAR).
+#
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.com/license/LICENSE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxkey09
+
+directives:
+
+ pthread_key_create
+ pthread_setspecific
+ pthread_key_delete
+ _POSIX_Keys_Run_destructors
+
+concepts:
+
++ Ensure that POSIX Key works when thread deleted first and then deleted key self.
diff --git a/testsuites/psxtests/psxkey09/psxkey09.scn b/testsuites/psxtests/psxkey09/psxkey09.scn
new file mode 100644
index 0000000000..707c7d63b1
--- /dev/null
+++ b/testsuites/psxtests/psxkey09/psxkey09.scn
@@ -0,0 +1,9 @@
+*** TEST KEY 09 ***
+Init - pthread key create with destructor - OK
+Init - pthread create - OK
+Init - sleep - let thread run - OK
+Test_Thread - key pthread_setspecific - OK
+Test_Thread - pthread_exit to run key destructors - OK
+Init - verify destructor run - OK
+Init - pthread key delete - OK
+*** END OF TEST KEY 09 ***
diff --git a/testsuites/psxtests/psxkey10/Makefile.am b/testsuites/psxtests/psxkey10/Makefile.am
new file mode 100644
index 0000000000..8e4f2f409b
--- /dev/null
+++ b/testsuites/psxtests/psxkey10/Makefile.am
@@ -0,0 +1,23 @@
+
+rtems_tests_PROGRAMS = psxkey10
+psxkey10_SOURCES = init.c
+
+dist_rtems_tests_DATA = psxkey10.scn
+dist_rtems_tests_DATA += psxkey10.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxkey10_OBJECTS)
+LINK_LIBS = $(psxkey10_LDLIBS)
+
+psxkey10$(EXEEXT): $(psxkey10_OBJECTS) $(psxkey10_DEPENDENCIES)
+ @rm -f psxkey10$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxkey10/init.c b/testsuites/psxtests/psxkey10/init.c
new file mode 100644
index 0000000000..eee0c18d8d
--- /dev/null
+++ b/testsuites/psxtests/psxkey10/init.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012 Zhongwei Yao.
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+#include "tmacros.h"
+#include "pmacros.h"
+
+/* forward declarations to avoid warnings */
+void *POSIX_Init(void *argument);
+void destructor(void *value);
+void *Test_Thread(void *argument);
+
+int Data_array[1] = {1};
+
+pthread_key_t key;
+volatile bool destructor_ran;
+
+void destructor(void *value)
+{
+ destructor_ran = true;
+}
+
+void *Test_Thread(
+ void *argument
+)
+{
+ int sc;
+
+ /**
+ * Detach ourselves to release test thread's resource after thread exit.
+ */
+ pthread_detach( pthread_self() );
+
+ puts( "Test_Thread - key pthread_setspecific - OK" );
+ sc = pthread_setspecific( key, argument );
+ rtems_test_assert( !sc );
+
+ puts( "Test_Thread - pthread key delete - OK" );
+ sc = pthread_key_delete( key );
+ rtems_test_assert( sc == 0 );
+
+ puts( "Test_Thread - pthread exit, but don't run key destructors - OK" );
+ return NULL;
+}
+
+void *POSIX_Init(
+ void *ignored
+)
+{
+ pthread_t thread;
+ int sc;
+ struct timespec delay_request;
+
+ puts( "\n\n*** TEST KEY 10 ***" );
+
+ puts( "Init - pthread key create with destructor - OK" );
+ sc = pthread_key_create( &key, destructor );
+ rtems_test_assert( !sc );
+
+ puts( "Init - pthread create - OK" );
+ sc = pthread_create( &thread, NULL, Test_Thread, &sc );
+ rtems_test_assert( !sc );
+
+ puts( "Init - sleep - let thread run - OK" );
+ delay_request.tv_sec = 0;
+ delay_request.tv_nsec = 8 * 100000000;
+ sc = nanosleep( &delay_request, NULL );
+ rtems_test_assert( !sc );
+
+ puts( "Init - verify destructor did NOT run - OK" );
+ rtems_test_assert( destructor_ran == false );
+
+ /* puts( "Init - pthread key delete - OK" ); */
+ /* sc = pthread_key_delete( key ); */
+ /* rtems_test_assert( sc == 0 ); */
+
+ puts( "*** END OF TEST KEY 10 ***" );
+ rtems_test_exit(0);
+}
+
+/* configuration information */
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
+/* global variables */
diff --git a/testsuites/psxtests/psxkey10/psxkey10.doc b/testsuites/psxtests/psxkey10/psxkey10.doc
new file mode 100644
index 0000000000..75c35c85c2
--- /dev/null
+++ b/testsuites/psxtests/psxkey10/psxkey10.doc
@@ -0,0 +1,22 @@
+# COPYRIGHT (c) 1989-2009.
+# On-Line Applications Research Corporation (OAR).
+#
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.com/license/LICENSE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxkey10
+
+directives:
+
+ pthread_key_create
+ pthread_setspecific
+ pthread_key_delete
+ _POSIX_Keys_Run_destructors
+
+concepts:
+
++ Ensure that POSIX Key works when key first and then deleted thread self.
diff --git a/testsuites/psxtests/psxkey10/psxkey10.scn b/testsuites/psxtests/psxkey10/psxkey10.scn
new file mode 100644
index 0000000000..98940e24ad
--- /dev/null
+++ b/testsuites/psxtests/psxkey10/psxkey10.scn
@@ -0,0 +1,10 @@
+
+*** TEST KEY 10 ***
+Init - pthread key create with destructor - OK
+Init - pthread create - OK
+Init - sleep - let thread run - OK
+Test_Thread - key pthread_setspecific - OK
+Test_Thread - pthread key delete - OK
+Test_Thread - pthread exit, but don't run key destructors - OK
+Init - verify destructor did NOT run - OK
+*** END OF TEST KEY 10 ***