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 *))
37 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
40 /* We do not yet allocate storage space for the values here, because we can
41 * not estimate how many threads will be created in the common case that the
42 * application creates keys before spawning threads.
44 for (k
= 0; k
< MTHREAD_KEYS_MAX
; k
++) {
48 keys
[k
].mvalue
= NULL
;
50 keys
[k
].destr
= destructor
;
60 /*===========================================================================*
61 * mthread_key_delete *
62 *===========================================================================*/
63 int mthread_key_delete(mthread_key_t key
)
65 /* Free up a key, as well as any associated storage space.
68 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
70 if (key
< 0 || key
>= MTHREAD_KEYS_MAX
|| !keys
[key
].used
)
73 free(keys
[key
].value
);
75 keys
[key
].used
= FALSE
;
80 /*===========================================================================*
81 * mthread_getspecific *
82 *===========================================================================*/
83 void *mthread_getspecific(mthread_key_t key
)
85 /* Get this thread's local value for the given key. The default is NULL.
88 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
90 if (key
< 0 || key
>= MTHREAD_KEYS_MAX
|| !keys
[key
].used
)
93 if (current_thread
== MAIN_THREAD
)
94 return keys
[key
].mvalue
;
96 if (current_thread
< keys
[key
].nvalues
)
97 return(keys
[key
].value
[current_thread
]);
102 /*===========================================================================*
103 * mthread_setspecific *
104 *===========================================================================*/
105 int mthread_setspecific(mthread_key_t key
, void *value
)
107 /* Set this thread's value for the given key. Allocate more resources as
112 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
114 if (key
< 0 || key
>= MTHREAD_KEYS_MAX
|| !keys
[key
].used
)
117 if (current_thread
== MAIN_THREAD
) {
118 keys
[key
].mvalue
= value
;
123 if (current_thread
>= keys
[key
].nvalues
) {
124 if (current_thread
>= no_threads
)
125 mthread_panic("Library state corrupt");
127 if ((p
= (void **) realloc(keys
[key
].value
,
128 sizeof(void*) * no_threads
)) == NULL
)
131 memset(&p
[keys
[key
].nvalues
], 0,
132 sizeof(void*) * (no_threads
- keys
[key
].nvalues
));
134 keys
[key
].nvalues
= no_threads
;
138 keys
[key
].value
[current_thread
] = value
;
143 /*===========================================================================*
144 * mthread_cleanup_values *
145 *===========================================================================*/
146 void mthread_cleanup_values(void)
148 /* Clean up all the values associated with an exiting thread, calling keys'
149 * destruction procedures as appropriate.
155 if (!keys_used
) return; /* Only clean up if we used any keys at all */
157 /* Any of the destructors may set a new value on any key, so we may have to
158 * loop over the table of keys multiple times. This implementation has no
159 * protection against infinite loops in this case.
164 for (k
= 0; k
< MTHREAD_KEYS_MAX
; k
++) {
165 if (!keys
[k
].used
) continue;
166 if (keys
[k
].destr
== NULL
) continue;
168 if (current_thread
== MAIN_THREAD
) {
169 value
= keys
[k
].mvalue
;
171 keys
[k
].mvalue
= NULL
;
173 if (current_thread
>= keys
[k
].nvalues
) continue;
175 value
= keys
[k
].value
[current_thread
];
177 keys
[k
].value
[current_thread
] = NULL
;
181 /* Note: calling mthread_exit() from a destructor
182 * causes undefined behavior.
184 keys
[k
].destr(value
);