source: rtems/cpukit/posix/src/key.c @ 0553a3a

4.104.114.84.95
Last change on this file since 0553a3a was f4719d5a, checked in by Joel Sherrill <joel.sherrill@…>, on 05/22/96 at 22:32:39

These files have been modified in the initial pass at getting the portion
of the POSIX API necessary to support the GNAT runtime to initially compile.
We now have verified that the specifications for the necessary routines
are correct per the POSIX standards we have.

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*  key.c
2 *
3 *  $Id$
4 */
5
6#include <errno.h>
7#include <limits.h>
8#include <pthread.h>
9#include <string.h>
10
11#include <rtems/system.h>
12#include <rtems/score/thread.h>
13#include <rtems/score/wkspace.h>
14#include <rtems/posix/key.h>
15
16/*
17 *  _POSIX_Key_Manager_initialization
18 *
19 *  DESCRIPTION:
20 *
21 *  This routine performs the initialization necessary for this manager.
22 */
23 
24void _POSIX_Key_Manager_initialization(
25  unsigned32 maximum_keys
26)
27{
28  _Objects_Initialize_information(
29    &_POSIX_Keys_Information,
30    OBJECTS_POSIX_KEYS,
31    FALSE,
32    maximum_keys,
33    sizeof( POSIX_Keys_Control ),
34    FALSE,
35    0,
36    FALSE
37  );
38}
39 
40/*PAGE
41 *
42 *  17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163
43 */
44
45int pthread_key_create(
46  pthread_key_t  *key,
47  void          (*destructor)( void * )
48)
49{
50  POSIX_Keys_Control  *the_key;
51  void                *table;
52  unsigned32           the_class;
53  unsigned32           bytes_to_allocate;
54
55
56  _Thread_Disable_dispatch();
57 
58  the_key = _POSIX_Keys_Allocate();
59 
60  if ( !the_key ) {
61    _Thread_Enable_dispatch();
62    return EAGAIN;
63  }
64
65  the_key->destructor = destructor;
66
67  for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
68        the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
69        the_class++ ) {
70
71    bytes_to_allocate =
72      (_Objects_Information_table[ the_class ]->maximum + 1) * sizeof( void * );
73
74    table = _Workspace_Allocate( bytes_to_allocate );
75
76    if ( !table ) {
77      for ( --the_class;
78            the_class >= OBJECTS_CLASSES_FIRST_THREAD_CLASS;
79            the_class-- )
80        _Workspace_Free( the_key->Values[ the_class ] );
81
82      _POSIX_Keys_Free( the_key );
83      _Thread_Enable_dispatch();
84      return ENOMEM;
85    }
86
87    the_key->Values[ the_class ] = table;
88    memset( table, '\0', bytes_to_allocate );
89  }
90
91  the_key->is_active = TRUE;
92
93  _Objects_Open( &_POSIX_Keys_Information, &the_key->Object, 0 );
94 
95  *key = the_key->Object.id;
96
97  _Thread_Enable_dispatch();
98
99  return 0;
100}
101
102/*PAGE
103 *
104 *  17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165
105 */
106
107int pthread_setspecific(
108  pthread_key_t  key,
109  const void    *value
110)
111{
112  register POSIX_Keys_Control *the_key;
113  unsigned32                   index;
114  unsigned32                   class;
115  Objects_Locations            location;
116 
117  the_key = _POSIX_Keys_Get( key, &location );
118  switch ( location ) {
119    case OBJECTS_ERROR:
120      return EINVAL;
121    case OBJECTS_REMOTE:
122      return EINVAL;       /* should never happen */
123    case OBJECTS_LOCAL:
124      index = _Objects_Get_index( _Thread_Executing->Object.id );
125      class = _Objects_Get_class( _Thread_Executing->Object.id );
126      the_key->Values[ class ][ index ] = (void *) value;
127      return 0;
128  }
129  return POSIX_BOTTOM_REACHED();
130}
131
132/*PAGE
133 *
134 *  17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165
135 */
136
137void *pthread_getspecific(
138  pthread_key_t  key
139)
140{
141  register POSIX_Keys_Control *the_key;
142  unsigned32                   index;
143  unsigned32                   class;
144  Objects_Locations            location;
145 
146  the_key = _POSIX_Keys_Get( key, &location );
147  switch ( location ) {
148    case OBJECTS_ERROR:
149      return NULL;
150    case OBJECTS_REMOTE:
151      return 0;       /* should never happen */
152    case OBJECTS_LOCAL:
153      index = _Objects_Get_index( _Thread_Executing->Object.id );
154      class = _Objects_Get_class( _Thread_Executing->Object.id );
155      return (void *) the_key->Values[ class ][ index ];
156  }
157  return (void *) POSIX_BOTTOM_REACHED();
158}
159
160/*PAGE
161 *
162 *  17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167
163 */
164
165int pthread_key_delete(
166  pthread_key_t  key
167)
168{
169  register POSIX_Keys_Control *the_key;
170  Objects_Locations            location;
171  unsigned32                   the_class;
172 
173  the_key = _POSIX_Keys_Get( key, &location );
174  switch ( location ) {
175    case OBJECTS_ERROR:
176      return EINVAL;
177    case OBJECTS_REMOTE:
178      return 0;       /* should never happen */
179    case OBJECTS_LOCAL:
180      _Objects_Close( &_POSIX_Keys_Information, &the_key->Object );
181
182      the_key->is_active = FALSE;
183
184      for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
185            the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
186            the_class++ )
187        _Workspace_Free( the_key->Values[ the_class ] );
188
189      /*
190       *  NOTE:  The destructor is not called and it is the responsibility
191       *         of the application to free the memory.
192       */
193
194      _POSIX_Keys_Free( the_key );
195      return 0;
196  }
197  return POSIX_BOTTOM_REACHED();
198}
199
200/*PAGE
201 *
202 *  _POSIX_Keys_Run_destructors
203 *
204 *  17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163
205 *
206 *  NOTE:  This is the routine executed when a thread exits to
207 *         run through all the keys and do the destructor action.
208 *
209 *  XXX: This needs to be hooked to the thread exitting -- SOMEHOW.
210 */
211
212void _POSIX_Keys_Run_destructors(
213  Thread_Control *thread
214)
215{
216  unsigned32           index;
217  unsigned32           pthread_index;
218  unsigned32           pthread_class;
219  unsigned32           iterations;
220  boolean              are_all_null;
221  POSIX_Keys_Control  *the_key;
222  void                *value;
223
224  pthread_index = _Objects_Get_index( thread->Object.id );
225  pthread_class = _Objects_Get_class( thread->Object.id );
226
227  iterations = 0;
228
229  for ( ; ; ) {
230
231    are_all_null = TRUE;
232
233    for ( index=1 ; index <= _POSIX_Keys_Information.maximum ; index++ ) {
234
235      the_key = (POSIX_Keys_Control *)
236        _POSIX_Keys_Information.local_table[ index ];
237     
238      if ( the_key && the_key->is_active && the_key->destructor ) {
239        value = the_key->Values[ pthread_class ][ pthread_index ];
240        if ( value ) {
241          (*the_key->destructor)( value );
242          if ( the_key->Values[ pthread_class ][ pthread_index ] )
243            are_all_null = FALSE;
244        }
245      }
246    }
247
248    if ( are_all_null == TRUE )
249      return;
250
251    iterations++;
252
253    /*
254     *  The standard allows one to not do this and thus go into an infinite
255     *  loop.  It seems rude to unnecessarily lock up a system.
256     */
257
258    if ( iterations >= PTHREAD_DESTRUCTOR_ITERATIONS )
259      return;
260  }
261}
Note: See TracBrowser for help on using the repository browser.