source: rtems/cpukit/posix/src/key.c @ d858fdb

4.104.114.84.9
Last change on this file since d858fdb was d858fdb, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 9, 1996 at 5:30:13 PM

merged remote object id and invalid id error cases.

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