source: rtems/cpukit/posix/src/key.c @ 895efd9

4.104.114.84.95
Last change on this file since 895efd9 was 895efd9, checked in by Joel Sherrill <joel.sherrill@…>, on 06/07/96 at 13:54:23

key destructor is now run at correct point in pthread_exit() sequence and
should be correct for other apis as well.

missing page numbers added on some references.

initial attempt at sig_procmask() and pthread_sigmask().

  • Property mode set to 100644
File size: 6.0 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      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
209void _POSIX_Keys_Run_destructors(
210  Thread_Control *thread
211)
212{
213  unsigned32           index;
214  unsigned32           pthread_index;
215  unsigned32           pthread_class;
216  unsigned32           iterations;
217  boolean              are_all_null;
218  POSIX_Keys_Control  *the_key;
219  void                *value;
220
221  pthread_index = _Objects_Get_index( thread->Object.id );
222  pthread_class = _Objects_Get_class( thread->Object.id );
223
224  iterations = 0;
225
226  for ( ; ; ) {
227
228    are_all_null = TRUE;
229
230    for ( index=1 ; index <= _POSIX_Keys_Information.maximum ; index++ ) {
231
232      the_key = (POSIX_Keys_Control *)
233        _POSIX_Keys_Information.local_table[ index ];
234     
235      if ( the_key && the_key->is_active && the_key->destructor ) {
236        value = the_key->Values[ pthread_class ][ pthread_index ];
237        if ( value ) {
238          (*the_key->destructor)( value );
239          if ( the_key->Values[ pthread_class ][ pthread_index ] )
240            are_all_null = FALSE;
241        }
242      }
243    }
244
245    if ( are_all_null == TRUE )
246      return;
247
248    iterations++;
249
250    /*
251     *  The standard allows one to not do this and thus go into an infinite
252     *  loop.  It seems rude to unnecessarily lock up a system.
253     *
254     *  Reference: 17.1.1.2 P1003.1c/Draft 10, p. 163, line 99.
255     */
256
257    if ( iterations >= PTHREAD_DESTRUCTOR_ITERATIONS )
258      return;
259  }
260}
Note: See TracBrowser for help on using the repository browser.