1 #include <minix/mthread.h>
6 static int keys_used
= 0;
12 void (*destr
)(void *);
13 } keys
[MTHREAD_KEYS_MAX
];
15 /*===========================================================================*
17 *===========================================================================*/
18 void mthread_init_keys(void)
20 /* Initialize the table of key entries.
24 for (k
= 0; k
< MTHREAD_KEYS_MAX
; k
++)
28 /*===========================================================================*
29 * mthread_key_create *
30 *===========================================================================*/
31 int mthread_key_create(mthread_key_t
*key
, void (*destructor
)(void *))
39 /* We do not yet allocate storage space for the values here, because we can
40 * not estimate how many threads will be created in the common case that the
41 * application creates keys before spawning threads.
43 for (k
= 0; k
< MTHREAD_KEYS_MAX
; k
++) {
47 keys
[k
].mvalue
= NULL
;
49 keys
[k
].destr
= destructor
;
59 /*===========================================================================*
60 * mthread_key_delete *
61 *===========================================================================*/
62 int mthread_key_delete(mthread_key_t key
)
64 /* Free up a key, as well as any associated storage space.
67 if (key
< 0 || key
>= MTHREAD_KEYS_MAX
|| !keys
[key
].used
)
70 free(keys
[key
].value
);
72 keys
[key
].used
= FALSE
;
77 /*===========================================================================*
78 * mthread_getspecific *
79 *===========================================================================*/
80 void *mthread_getspecific(mthread_key_t key
)
82 /* Get this thread's local value for the given key. The default is NULL.
85 if (key
< 0 || key
>= MTHREAD_KEYS_MAX
|| !keys
[key
].used
)
88 if (current_thread
== MAIN_THREAD
)
89 return keys
[key
].mvalue
;
91 if (current_thread
< keys
[key
].nvalues
)
92 return(keys
[key
].value
[current_thread
]);
97 /*===========================================================================*
98 * mthread_setspecific *
99 *===========================================================================*/
100 int mthread_setspecific(mthread_key_t key
, void *value
)
102 /* Set this thread's value for the given key. Allocate more resources as
107 if (key
< 0 || key
>= MTHREAD_KEYS_MAX
|| !keys
[key
].used
)
110 if (current_thread
== MAIN_THREAD
) {
111 keys
[key
].mvalue
= value
;
116 if (current_thread
>= keys
[key
].nvalues
) {
117 if (current_thread
>= no_threads
)
118 mthread_panic("Library state corrupt");
120 if ((p
= (void **) realloc(keys
[key
].value
,
121 sizeof(void*) * no_threads
)) == NULL
)
124 memset(&p
[keys
[key
].nvalues
], 0,
125 sizeof(void*) * (no_threads
- keys
[key
].nvalues
));
127 keys
[key
].nvalues
= no_threads
;
131 keys
[key
].value
[current_thread
] = value
;
136 /*===========================================================================*
137 * mthread_cleanup_values *
138 *===========================================================================*/
139 void mthread_cleanup_values(void)
141 /* Clean up all the values associated with an exiting thread, calling keys'
142 * destruction procedures as appropriate.
148 if (!keys_used
) return; /* Only clean up if we used any keys at all */
150 /* Any of the destructors may set a new value on any key, so we may have to
151 * loop over the table of keys multiple times. This implementation has no
152 * protection against infinite loops in this case.
157 for (k
= 0; k
< MTHREAD_KEYS_MAX
; k
++) {
158 if (!keys
[k
].used
) continue;
159 if (keys
[k
].destr
== NULL
) continue;
161 if (current_thread
== MAIN_THREAD
) {
162 value
= keys
[k
].mvalue
;
164 keys
[k
].mvalue
= NULL
;
166 if (current_thread
>= keys
[k
].nvalues
) continue;
168 value
= keys
[k
].value
[current_thread
];
170 keys
[k
].value
[current_thread
] = NULL
;
174 /* Note: calling mthread_exit() from a destructor
175 * causes undefined behavior.
177 keys
[k
].destr(value
);
185 /* pthread compatibility layer. */
186 __weak_alias(pthread_key_create
, mthread_key_create
)
187 __weak_alias(pthread_key_delete
, mthread_key_delete
)
188 __weak_alias(pthread_getspecific
, mthread_getspecific
)
189 __weak_alias(pthread_setspecific
, mthread_setspecific
)