source: rtems/c/src/exec/posix/src/key.c @ 1ceface

4.104.114.84.95
Last change on this file since 1ceface was 5e9b32b, checked in by Joel Sherrill <joel.sherrill@…>, on 09/26/95 at 19:27:15

posix support initially added

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