Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:21

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup POSIXAPI
0007  *
0008  * @brief Thread-Specific Data Key Create
0009  */
0010 
0011 /*
0012  * COPYRIGHT (c) 1989-2010.
0013  * On-Line Applications Research Corporation (OAR).
0014  * Copyright (c) 2016 embedded brains GmbH & Co. KG
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041 
0042 #include <rtems/posix/keyimpl.h>
0043 #include <rtems/score/userextimpl.h>
0044 #include <rtems/score/wkspace.h>
0045 #include <rtems/sysinit.h>
0046 
0047 #include <errno.h>
0048 
0049 /**
0050  *  17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163
0051  */
0052 int pthread_key_create(
0053   pthread_key_t  *key,
0054   void          (*destructor)( void * )
0055 )
0056 {
0057   POSIX_Keys_Control  *the_key;
0058 
0059   the_key = _POSIX_Keys_Allocate();
0060 
0061   if ( !the_key ) {
0062     _Objects_Allocator_unlock();
0063     return EAGAIN;
0064   }
0065 
0066   the_key->destructor = destructor;
0067   _Chain_Initialize_empty( &the_key->Key_value_pairs );
0068   _Objects_Open_u32( &_POSIX_Keys_Information, &the_key->Object, 0 );
0069   *key = the_key->Object.id;
0070   _Objects_Allocator_unlock();
0071   return 0;
0072 }
0073 
0074 Freechain_Control _POSIX_Keys_Keypool;
0075 
0076 static uint32_t _POSIX_Keys_Get_keypool_bump_count( void )
0077 {
0078   uint32_t max;
0079 
0080   max = _POSIX_Keys_Key_value_pair_maximum;
0081   return _Objects_Is_unlimited( max ) ?
0082     _Objects_Maximum_per_allocation( max ) : 0;
0083 }
0084 
0085 static uint32_t _POSIX_Keys_Get_initial_keypool_size( void )
0086 {
0087   uint32_t max;
0088 
0089   max = _POSIX_Keys_Key_value_pair_maximum;
0090   return _Objects_Maximum_per_allocation( max );
0091 }
0092 
0093 static void _POSIX_Keys_Initialize_keypool( void )
0094 {
0095   _Freechain_Initialize(
0096     &_POSIX_Keys_Keypool,
0097     _POSIX_Keys_Key_value_pairs,
0098     _POSIX_Keys_Get_initial_keypool_size(),
0099     sizeof( _POSIX_Keys_Key_value_pairs[ 0 ] )
0100   );
0101 }
0102 
0103 POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_allocate( void )
0104 {
0105   return (POSIX_Keys_Key_value_pair *) _Freechain_Get(
0106     &_POSIX_Keys_Keypool,
0107     _Workspace_Allocate,
0108     _POSIX_Keys_Get_keypool_bump_count(),
0109     sizeof( POSIX_Keys_Key_value_pair )
0110   );
0111 }
0112 
0113 static void _POSIX_Keys_Run_destructors( Thread_Control *the_thread )
0114 {
0115   while ( true ) {
0116     ISR_lock_Context  lock_context;
0117     RBTree_Node      *node;
0118 
0119     _Objects_Allocator_lock();
0120     _POSIX_Keys_Key_value_acquire( the_thread, &lock_context );
0121 
0122     node = _RBTree_Root( &the_thread->Keys.Key_value_pairs );
0123     if ( node != NULL ) {
0124       POSIX_Keys_Key_value_pair *key_value_pair;
0125       pthread_key_t              key;
0126       void                      *value;
0127       POSIX_Keys_Control        *the_key;
0128       void                    ( *destructor )( void * );
0129 
0130       key_value_pair = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( node );
0131       key = key_value_pair->key;
0132       value = key_value_pair->value;
0133       _RBTree_Extract(
0134         &the_thread->Keys.Key_value_pairs,
0135         &key_value_pair->Lookup_node
0136       );
0137 
0138       _POSIX_Keys_Key_value_release( the_thread, &lock_context );
0139       _POSIX_Keys_Key_value_free( key_value_pair );
0140 
0141       the_key = _POSIX_Keys_Get( key );
0142       _Assert( the_key != NULL );
0143       destructor = the_key->destructor;
0144 
0145       _Objects_Allocator_unlock();
0146 
0147       if ( destructor != NULL && value != NULL ) {
0148         ( *destructor )( value );
0149       }
0150     } else {
0151       _POSIX_Keys_Key_value_release( the_thread, &lock_context );
0152       _Objects_Allocator_unlock();
0153       break;
0154     }
0155   }
0156 }
0157 
0158 static void _POSIX_Keys_Restart_run_destructors(
0159   Thread_Control *executing,
0160   Thread_Control *the_thread
0161 )
0162 {
0163   (void) executing;
0164   _POSIX_Keys_Run_destructors( the_thread );
0165 }
0166 
0167 static User_extensions_Control _POSIX_Keys_Extensions = {
0168   .Callouts = {
0169     .thread_restart = _POSIX_Keys_Restart_run_destructors,
0170     .thread_terminate = _POSIX_Keys_Run_destructors
0171   }
0172 };
0173 
0174 /**
0175  * @brief This routine performs the initialization necessary for this manager.
0176  */
0177 static void _POSIX_Keys_Manager_initialization(void)
0178 {
0179   _Objects_Initialize_information( &_POSIX_Keys_Information );
0180   _POSIX_Keys_Initialize_keypool();
0181   _User_extensions_Add_API_set( &_POSIX_Keys_Extensions );
0182 }
0183 
0184 RTEMS_SYSINIT_ITEM(
0185   _POSIX_Keys_Manager_initialization,
0186   RTEMS_SYSINIT_POSIX_KEYS,
0187   RTEMS_SYSINIT_ORDER_MIDDLE
0188 );