[rtems commit] Unlimited objects support for POSIX keys

Sebastian Huber sebh at rtems.org
Tue Aug 6 12:06:21 UTC 2013


Module:    rtems
Branch:    master
Commit:    b5c906429f6e67452eec1b0089ac7a204ff998ee
Changeset: http://git.rtems.org/rtems/commit/?id=b5c906429f6e67452eec1b0089ac7a204ff998ee

Author:    Zhongwei Yao <ashi08104 at gmail.com>
Date:      Mon Aug  5 09:20:45 2013 -0400

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.

---

 cpukit/posix/include/rtems/posix/config.h    |    1 +
 cpukit/posix/include/rtems/posix/key.h       |   90 +++++++++++---
 cpukit/posix/include/rtems/posix/threadsup.h |    9 ++
 cpukit/posix/src/key.c                       |  131 ++++++++++++++++++--
 cpukit/posix/src/keycreate.c                 |   64 ++--------
 cpukit/posix/src/keydelete.c                 |   14 +--
 cpukit/posix/src/keyfreememory.c             |   50 ++++++--
 cpukit/posix/src/keygetspecific.c            |   39 ++++--
 cpukit/posix/src/keyrundestructors.c         |   89 ++++++++-----
 cpukit/posix/src/keysetspecific.c            |   49 ++++++--
 cpukit/posix/src/pthread.c                   |    3 +
 cpukit/sapi/include/confdefs.h               |   34 +++++-
 testsuites/psxtests/Makefile.am              |    3 +-
 testsuites/psxtests/configure.ac             |    7 +
 testsuites/psxtests/psxkey01/init.c          |    4 +-
 testsuites/psxtests/psxkey01/psxkey01.scn    |    4 +-
 testsuites/psxtests/psxkey04/Makefile.am     |   23 ++++
 testsuites/psxtests/psxkey04/init.c          |  128 +++++++++++++++++++
 testsuites/psxtests/psxkey04/psxkey04.doc    |   22 ++++
 testsuites/psxtests/psxkey04/psxkey04.scn    |   11 ++
 testsuites/psxtests/psxkey05/Makefile.am     |   23 ++++
 testsuites/psxtests/psxkey05/init.c          |   82 ++++++++++++
 testsuites/psxtests/psxkey05/psxkey05.doc    |   22 ++++
 testsuites/psxtests/psxkey05/psxkey05.scn    |   10 ++
 testsuites/psxtests/psxkey06/Makefile.am     |   23 ++++
 testsuites/psxtests/psxkey06/init.c          |  153 +++++++++++++++++++++++
 testsuites/psxtests/psxkey06/psxkey06.doc    |   23 ++++
 testsuites/psxtests/psxkey06/psxkey06.scn    |   18 +++
 testsuites/psxtests/psxkey07/Makefile.am     |   23 ++++
 testsuites/psxtests/psxkey07/init.c          |  173 ++++++++++++++++++++++++++
 testsuites/psxtests/psxkey07/psxkey07.doc    |   26 ++++
 testsuites/psxtests/psxkey07/psxkey07.scn    |   18 +++
 testsuites/psxtests/psxkey08/Makefile.am     |   23 ++++
 testsuites/psxtests/psxkey08/init.c          |  165 ++++++++++++++++++++++++
 testsuites/psxtests/psxkey08/psxkey08.doc    |   25 ++++
 testsuites/psxtests/psxkey08/psxkey08.scn    |   15 +++
 testsuites/psxtests/psxkey09/Makefile.am     |   23 ++++
 testsuites/psxtests/psxkey09/init.c          |  103 +++++++++++++++
 testsuites/psxtests/psxkey09/psxkey09.doc    |   22 ++++
 testsuites/psxtests/psxkey09/psxkey09.scn    |    9 ++
 testsuites/psxtests/psxkey10/Makefile.am     |   23 ++++
 testsuites/psxtests/psxkey10/init.c          |  106 ++++++++++++++++
 testsuites/psxtests/psxkey10/psxkey10.doc    |   22 ++++
 testsuites/psxtests/psxkey10/psxkey10.scn    |   10 ++
 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 104bd84..a842f7a 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 6d2ebff..ee5b573 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 414b46f..7bd1f93 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 6eace26..2bb415c 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 b41b590..349e883 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 8f96ca3..c3d3da1 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 f71af4f..c42616d 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 0e8bbcd..88e084e 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 eb692e0..7e3c88f 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 22eb8eb..f527fe1 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 121b087..13f7525 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 ed1385a..50db877 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 0e8a3e8..423cf07 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 a04fc5e..8e0a238 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 3383c8d..e63407c 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 597b0f8..e1a747c 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 0000000..cd5f2bb
--- /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 at .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 0000000..76540dd
--- /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 0000000..6438d4e
--- /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 0000000..aa0500f
--- /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 0000000..c253900
--- /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 at .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 0000000..08d22b0
--- /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 0000000..f4359d6
--- /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 0000000..f352a36
--- /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 0000000..9815baf
--- /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 at .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 0000000..98b46a4
--- /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 0000000..6becdb9
--- /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 0000000..a105b6f
--- /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 0000000..a701f30
--- /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 at .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 0000000..e911dc7
--- /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 0000000..16d93de
--- /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 0000000..851876f
--- /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 0000000..e5bf787
--- /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 at .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 0000000..81f4378
--- /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 0000000..5d0b171
--- /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 0000000..a4f1be4
--- /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 0000000..ed3ee00
--- /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 at .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 0000000..a44f0e3
--- /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 0000000..ecb9b74
--- /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 0000000..707c7d6
--- /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 0000000..8e4f2f4
--- /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 at .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 0000000..eee0c18
--- /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 0000000..75c35c8
--- /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 0000000..98940e2
--- /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 ***




More information about the vc mailing list