-
Notifications
You must be signed in to change notification settings - Fork 139
/
Copy pathomrthreadtls.c
206 lines (176 loc) · 5.52 KB
/
omrthreadtls.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*******************************************************************************
* Copyright IBM Corp. and others 1991
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
/**
* @file
* @ingroup Thread
* @brief Thread local storage
*/
#include "omrcfg.h"
#include "omrcomp.h"
#include "omrthread.h"
#include "threaddef.h"
#include "thread_internal.h"
static void J9THREAD_PROC tls_null_finalizer(void *entry);
/**
* Allocate a thread local storage (TLS) key.
*
* Create and return a new, unique key for thread local storage.
*
* @note The handle returned will be > 0, so it is safe to test the handle against 0 to see if it's been
* allocated yet.
*
* @param[out] handle pointer to a key to be initialized with a key value
* @return 0 on success or negative value if a key could not be allocated (i.e. all TLS has been allocated)
*
* @see omrthread_tls_free, omrthread_tls_set
*/
intptr_t
omrthread_tls_alloc(omrthread_tls_key_t *handle)
{
return omrthread_tls_alloc_with_finalizer(handle, tls_null_finalizer);
}
/**
* Allocate a thread local storage (TLS) key.
*
* Create and return a new, unique key for thread local storage.
*
* @note The handle returned will be > 0, so it is safe to test the handle against 0 to see if it's been
* allocated yet.
*
* @param[out] handle pointer to a key to be initialized with a key value
* @param[in] finalizer a finalizer function which will be invoked when a thread is detached or terminates if the thread's TLS entry for this key is non-NULL
* @return 0 on success or negative value if a key could not be allocated (i.e. all TLS has been allocated)
*
* @see omrthread_tls_free, omrthread_tls_set
*/
intptr_t
omrthread_tls_alloc_with_finalizer(omrthread_tls_key_t *handle, omrthread_tls_finalizer_t finalizer)
{
intptr_t index;
omrthread_library_t lib = GLOBAL_DATA(default_library);
ASSERT(lib);
*handle = 0;
OMROSMUTEX_ENTER(lib->tls_mutex);
for (index = 0; index < J9THREAD_MAX_TLS_KEYS; index++) {
if (lib->tls_finalizers[index] == NULL) {
*handle = index + 1;
lib->tls_finalizers[index] = finalizer;
break;
}
}
OMROSMUTEX_EXIT(lib->tls_mutex);
return index < J9THREAD_MAX_TLS_KEYS ? 0 : -1;
}
/**
* Release a TLS key.
*
* Release a TLS key previously allocated by omrthread_tls_alloc.
*
* @param[in] key TLS key to be freed
* @return 0 on success or negative value on failure
*
* @see omrthread_tls_alloc, omrthread_tls_set
*
*/
intptr_t
omrthread_tls_free(omrthread_tls_key_t key)
{
J9PoolState state;
omrthread_t each;
omrthread_library_t lib = GLOBAL_DATA(default_library);
ASSERT(lib);
/* clear the TLS in every existing thread */
GLOBAL_LOCK_SIMPLE(lib);
each = pool_startDo(lib->thread_pool, &state);
while (each) {
each->tls[key - 1] = NULL;
each = pool_nextDo(&state);
}
GLOBAL_UNLOCK_SIMPLE(lib);
/* now return the key to the free set */
OMROSMUTEX_ENTER(lib->tls_mutex);
lib->tls_finalizers[key - 1] = NULL;
OMROSMUTEX_EXIT(lib->tls_mutex);
return 0;
}
/**
* Set a thread's TLS value.
*
* @param[in] thread a thread
* @param[in] key key to have TLS value set (any value returned by omrthread_alloc)
* @param[in] value value to be stored in TLS
* @return 0 on success or negative value on failure
*
* @see omrthread_tls_alloc, omrthread_tls_free, omrthread_tls_get
*/
intptr_t
omrthread_tls_set(omrthread_t thread, omrthread_tls_key_t key, void *value)
{
thread->tls[key - 1] = value;
return 0;
}
/**
* Run finalizers on any non-NULL TLS values for the current thread
*
* @param[in] thread current thread
* @return none
*/
void
omrthread_tls_finalize(omrthread_t thread)
{
intptr_t index;
omrthread_library_t lib = thread->library;
for (index = 0; index < J9THREAD_MAX_TLS_KEYS; index++) {
if (thread->tls[index] != NULL) {
void *value;
omrthread_tls_finalizer_t finalizer;
/* read the value and finalizer together under mutex to be sure that they belong together */
OMROSMUTEX_ENTER(lib->tls_mutex);
value = thread->tls[index];
finalizer = lib->tls_finalizers[index];
OMROSMUTEX_EXIT(lib->tls_mutex);
if (value) {
finalizer(value);
}
}
}
}
void
omrthread_tls_finalizeNoLock(omrthread_t thread)
{
intptr_t index = 0;
omrthread_library_t lib = thread->library;
for (index = 0; index < J9THREAD_MAX_TLS_KEYS; index++) {
if (NULL != thread->tls[index]) {
void *value = thread->tls[index];
omrthread_tls_finalizer_t finalizer = lib->tls_finalizers[index];
if (NULL != value) {
finalizer(value);
}
}
}
}
static void J9THREAD_PROC
tls_null_finalizer(void *entry)
{
/* do nothing */
}