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

4.104.114.84.95
Last change on this file since 05195890 was eb5a7e07, checked in by Joel Sherrill <joel.sherrill@…>, on 10/06/95 at 20:48:38

fixed missing CVS IDs

  • 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/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;
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 
145  the_key = _POSIX_Keys_Get( key, &location );
146  switch ( location ) {
147    case OBJECTS_ERROR:
148      return NULL;
149    case OBJECTS_REMOTE:
150      return 0;       /* should never happen */
151    case OBJECTS_LOCAL:
152      index = _Objects_Get_index( _Thread_Executing->Object.id );
153      class = _Objects_Get_class( _Thread_Executing->Object.id );
154      return (void *) the_key->Values[ class ][ index ];
155  }
156  return (void *) POSIX_BOTTOM_REACHED();
157}
158
159/*PAGE
160 *
161 *  17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167
162 */
163
164int pthread_key_delete(
165  pthread_key_t  key
166)
167{
168  register POSIX_Keys_Control *the_key;
169  Objects_Locations            location;
170  unsigned32                   the_class;
171 
172  the_key = _POSIX_Keys_Get( key, &location );
173  switch ( location ) {
174    case OBJECTS_ERROR:
175      return EINVAL;
176    case OBJECTS_REMOTE:
177      return 0;       /* should never happen */
178    case OBJECTS_LOCAL:
179      _Objects_Close( &_POSIX_Keys_Information, &the_key->Object );
180
181      the_key->is_active = FALSE;
182
183      for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
184            the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
185            the_class++ )
186        _Workspace_Free( the_key->Values[ the_class ] );
187
188      /*
189       *  NOTE:  The destructor is not called and it is the responsibility
190       *         of the application to free the memory.
191       */
192
193      _POSIX_Keys_Free( the_key );
194      return 0;
195  }
196  return POSIX_BOTTOM_REACHED();
197}
198
199/*PAGE
200 *
201 *  _POSIX_Keys_Run_destructors
202 *
203 *  17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163
204 *
205 *  NOTE:  This is the routine executed when a thread exits to
206 *         run through all the keys and do the destructor action.
207 *
208 *  XXX: This needs to be hooked to the thread exitting -- SOMEHOW.
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
257    if ( iterations >= PTHREAD_DESTRUCTOR_ITERATIONS )
258      return;
259  }
260}
Note: See TracBrowser for help on using the repository browser.