diff options
author | Zhongwei Yao <ashi08104@gmail.com> | 2013-08-05 09:20:45 -0400 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-08-06 14:11:38 +0200 |
commit | b5c906429f6e67452eec1b0089ac7a204ff998ee (patch) | |
tree | 5e24aed5499922f6d3fa6e1559f5bc7e83fba4b2 | |
parent | bsp/realview-pbx-a9: Enable fast idle clock (diff) | |
download | rtems-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.
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 *** |