source: rtems/c/src/exec/posix/src/key.c @ b521ae2

4.104.114.84.95
Last change on this file since b521ae2 was b521ae2, checked in by Joel Sherrill <joel.sherrill@…>, on 08/06/96 at 16:23:09

pthread_getspecific: use local variable so references to tcb are completed
before enabling dispatching

  • Property mode set to 100644
File size: 6.2 KB
RevLine 
[7f72217e]1/*
[eb5a7e07]2 *  $Id$
[5e9b32b]3 */
4
5#include <errno.h>
6#include <limits.h>
7#include <pthread.h>
8#include <string.h>
9
[f4719d5a]10#include <rtems/system.h>
[5e9b32b]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      return EINVAL;
120    case OBJECTS_REMOTE:
121      return EINVAL;       /* should never happen */
122    case OBJECTS_LOCAL:
123      index = _Objects_Get_index( _Thread_Executing->Object.id );
124      class = _Objects_Get_class( _Thread_Executing->Object.id );
125      the_key->Values[ class ][ index ] = (void *) value;
[b521ae2]126      _Thread_Enable_dispatch();
[5e9b32b]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;
[b521ae2]145  void                        *key_data;
[5e9b32b]146 
147  the_key = _POSIX_Keys_Get( key, &location );
148  switch ( location ) {
149    case OBJECTS_ERROR:
150      return NULL;
151    case OBJECTS_REMOTE:
152      return 0;       /* should never happen */
153    case OBJECTS_LOCAL:
154      index = _Objects_Get_index( _Thread_Executing->Object.id );
155      class = _Objects_Get_class( _Thread_Executing->Object.id );
[b521ae2]156      key_data = (void *) the_key->Values[ class ][ index ];
157      _Thread_Enable_dispatch();
158      return key_data;
[5e9b32b]159  }
160  return (void *) POSIX_BOTTOM_REACHED();
161}
162
163/*PAGE
164 *
165 *  17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167
166 */
167
168int pthread_key_delete(
169  pthread_key_t  key
170)
171{
172  register POSIX_Keys_Control *the_key;
173  Objects_Locations            location;
174  unsigned32                   the_class;
175 
176  the_key = _POSIX_Keys_Get( key, &location );
177  switch ( location ) {
178    case OBJECTS_ERROR:
179      return EINVAL;
180    case OBJECTS_REMOTE:
181      return 0;       /* should never happen */
182    case OBJECTS_LOCAL:
183      _Objects_Close( &_POSIX_Keys_Information, &the_key->Object );
184
185      the_key->is_active = FALSE;
186
187      for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
188            the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
189            the_class++ )
190        _Workspace_Free( the_key->Values[ the_class ] );
191
192      /*
193       *  NOTE:  The destructor is not called and it is the responsibility
194       *         of the application to free the memory.
195       */
196
197      _POSIX_Keys_Free( the_key );
[b521ae2]198      _Thread_Enable_dispatch();
[5e9b32b]199      return 0;
200  }
201  return POSIX_BOTTOM_REACHED();
202}
203
204/*PAGE
205 *
206 *  _POSIX_Keys_Run_destructors
207 *
208 *  17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163
209 *
210 *  NOTE:  This is the routine executed when a thread exits to
211 *         run through all the keys and do the destructor action.
212 */
213
214void _POSIX_Keys_Run_destructors(
215  Thread_Control *thread
216)
217{
218  unsigned32           index;
219  unsigned32           pthread_index;
220  unsigned32           pthread_class;
221  unsigned32           iterations;
222  boolean              are_all_null;
223  POSIX_Keys_Control  *the_key;
224  void                *value;
225
226  pthread_index = _Objects_Get_index( thread->Object.id );
227  pthread_class = _Objects_Get_class( thread->Object.id );
228
229  iterations = 0;
230
231  for ( ; ; ) {
232
233    are_all_null = TRUE;
234
235    for ( index=1 ; index <= _POSIX_Keys_Information.maximum ; index++ ) {
236
237      the_key = (POSIX_Keys_Control *)
238        _POSIX_Keys_Information.local_table[ index ];
239     
240      if ( the_key && the_key->is_active && the_key->destructor ) {
241        value = the_key->Values[ pthread_class ][ pthread_index ];
242        if ( value ) {
243          (*the_key->destructor)( value );
244          if ( the_key->Values[ pthread_class ][ pthread_index ] )
245            are_all_null = FALSE;
246        }
247      }
248    }
249
250    if ( are_all_null == TRUE )
251      return;
252
253    iterations++;
254
255    /*
256     *  The standard allows one to not do this and thus go into an infinite
257     *  loop.  It seems rude to unnecessarily lock up a system.
[895efd9]258     *
259     *  Reference: 17.1.1.2 P1003.1c/Draft 10, p. 163, line 99.
[5e9b32b]260     */
261
262    if ( iterations >= PTHREAD_DESTRUCTOR_ITERATIONS )
263      return;
264  }
265}
Note: See TracBrowser for help on using the repository browser.