void *pthread_getspecific( pthread_key_t key ) { register POSIX_Keys_Control *the_key; uint32_t api; uint32_t index; Objects_Locations location; void *key_data; the_key = _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 ]; _Thread_Enable_dispatch(); return key_data; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never happen */ #endif case OBJECTS_ERROR: break; } return NULL; }
/* * 17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167 */ int pthread_key_delete( pthread_key_t key ) { POSIX_Keys_Control *the_key; Objects_Locations location; _Objects_Allocator_lock(); the_key = _POSIX_Keys_Get( key, &location ); switch ( location ) { case OBJECTS_LOCAL: _POSIX_Keys_Free_memory( the_key ); /* * NOTE: The destructor is not called and it is the responsibility * of the application to free the memory. */ _POSIX_Keys_Free( the_key ); _Objects_Put(&the_key->Object); _Objects_Allocator_unlock(); return 0; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never happen */ #endif case OBJECTS_ERROR: break; } _Objects_Allocator_unlock(); return EINVAL; }
/* * _POSIX_Keys_Run_destructors * * 17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163 * * 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 ) { Chain_Control *chain; POSIX_Keys_Key_value_pair *iter, *next; void *value; void (*destructor) (void *); POSIX_Keys_Control *the_key; Objects_Locations location; _Thread_Disable_dispatch(); chain = &( (POSIX_API_Control *)thread->API_Extensions[ THREAD_API_POSIX ] )->Key_Chain; iter = (POSIX_Keys_Key_value_pair *) _Chain_First( chain ); while ( !_Chain_Is_tail( chain, &iter->Key_values_per_thread_node ) ) { next = (POSIX_Keys_Key_value_pair *) _Chain_Next( &iter->Key_values_per_thread_node ); /** * 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( &_POSIX_Keys_Key_value_lookup_tree, &iter->Key_value_lookup_node ); _Chain_Extract_unprotected( &iter->Key_values_per_thread_node ); /** * run key value's destructor if destructor and value are both non-null. */ the_key = _POSIX_Keys_Get( iter->key, &location ); destructor = the_key->destructor; value = iter->value; if ( destructor != NULL && value != NULL ) (*destructor)( value ); _Objects_Put( &the_key->Object ); _POSIX_Keys_Key_value_pair_free( iter ); iter = next; } _Thread_Enable_dispatch(); }
int pthread_setspecific( pthread_key_t key, const void *value ) { POSIX_Keys_Control *the_key; Objects_Locations location; POSIX_Keys_Key_value_pair *value_pair_ptr; RBTree_Node *p; POSIX_Keys_Key_value_pair search_node; Thread_Control *executing; the_key = _POSIX_Keys_Get( key, &location ); switch ( location ) { case OBJECTS_LOCAL: executing = _Thread_Executing; p = _POSIX_Keys_Find( key, executing, &search_node ); if ( p != NULL ) { value_pair_ptr = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( p ); value_pair_ptr->value = RTEMS_DECONST( void *, value ); } else {
void *pthread_getspecific( pthread_key_t key ) { POSIX_Keys_Control *the_key; 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 ); switch ( location ) { case OBJECTS_LOCAL: p = _POSIX_Keys_Find( key, _Thread_Executing, &search_node ); if ( p != NULL ) { value_pair_p = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( p ); key_data = value_pair_p->value; } else { key_data = NULL; } _Objects_Put( &the_key->Object ); return key_data; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never happen */ #endif case OBJECTS_ERROR: break; } return NULL; }
int pthread_key_delete( pthread_key_t key ) { register POSIX_Keys_Control *the_key; Objects_Locations location; uint32_t the_api; the_key = _POSIX_Keys_Get( key, &location ); switch ( location ) { case OBJECTS_LOCAL: _Objects_Close( &_POSIX_Keys_Information, &the_key->Object ); for ( the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++ ) if ( the_key->Values[ the_api ] ) _Workspace_Free( the_key->Values[ the_api ] ); /* * NOTE: The destructor is not called and it is the responsibility * of the application to free the memory. */ _POSIX_Keys_Free( the_key ); _Thread_Enable_dispatch(); return 0; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never happen */ #endif case OBJECTS_ERROR: break; } return EINVAL; }
int pthread_setspecific( pthread_key_t key, const void *value ) { POSIX_Keys_Control *the_key; Objects_Locations location; POSIX_Keys_Key_value_pair *value_pair_ptr; RBTree_Node *p; POSIX_Keys_Key_value_pair search_node; Thread_Control *executing; the_key = _POSIX_Keys_Get( key, &location ); switch ( location ) { case OBJECTS_LOCAL: executing = _Thread_Executing; p = _POSIX_Keys_Find( key, executing, &search_node ); if ( p != NULL ) { value_pair_ptr = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( p ); value_pair_ptr->value = value; } else { value_pair_ptr = _POSIX_Keys_Key_value_pair_allocate(); if ( !value_pair_ptr ) { _Objects_Put( &the_key->Object ); return ENOMEM; } value_pair_ptr->key = key; value_pair_ptr->thread = executing; value_pair_ptr->value = value; /* The insert can only go wrong if the same node is already in a unique * tree. This has been already checked with the _RBTree_Find() */ _RBTree_Insert( &_POSIX_Keys_Key_value_lookup_tree, &value_pair_ptr->Key_value_lookup_node, _POSIX_Keys_Key_value_compare, true ); /** append rb_node to the thread API extension's chain */ _Chain_Append_unprotected( &_Thread_Executing->Key_Chain, &value_pair_ptr->Key_values_per_thread_node ); } _Objects_Put( &the_key->Object ); return 0; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never happen */ #endif case OBJECTS_ERROR: break; } return EINVAL; }