annotate libgcc/config/gthr-vxworks-tls.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1 /* Copyright (C) 2002-2020 Free Software Foundation, Inc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 Contributed by Zack Weinberg <zack@codesourcery.com>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4 This file is part of GCC.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 version.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 for more details.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16 Under Section 7 of GPL version 3, you are granted additional
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17 permissions described in the GCC Runtime Library Exception, version
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 3.1, as published by the Free Software Foundation.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20 You should have received a copy of the GNU General Public License and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 a copy of the GCC Runtime Library Exception along with this program;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 <http://www.gnu.org/licenses/>. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 /* Threads compatibility routines for libgcc2 for VxWorks.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 These are out-of-line routines called from gthr-vxworks.h.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 This file provides the TLS related support routines, calling specific
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 VxWorks kernel entry points for this purpose. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 #include "tconfig.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 #include "tsystem.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 #include "gthr.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 #if defined(__GTHREADS)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 #include <vxWorks.h>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 #ifndef __RTP__
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 #include <vxLib.h>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 #include <taskLib.h>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 #ifndef __RTP__
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 #include <taskHookLib.h>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 #include <errno.h>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 #include <_vxworks-versions.h>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 /* Thread-local storage.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 A gthread TLS key is simply an offset in an array, the address of which
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 we store in a single pointer field associated with the current task.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 On VxWorks 7, we have direct support for __thread variables and use
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 such a variable as the pointer "field". On other versions, we resort
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 to __gthread_get_tls_data and __gthread_set_tls_data functions provided
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 by the kernel.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 There is also a global array which records which keys are valid and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 which have destructors.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 A task delete hook is installed to execute key destructors. The routines
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 __gthread_enter_tls_dtor_context and __gthread_leave_tls_dtor_context,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 which are also provided by the kernel, ensure that it is safe to call
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 free() on memory allocated by the task being deleted. This is a no-op on
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 VxWorks 5, but a major undertaking on AE.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 The task delete hook is only installed when at least one thread
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 has TLS data. This is a necessary precaution, to allow this module
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 to be unloaded - a module with a hook can not be removed.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 Since this interface is used to allocate only a small number of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 keys, the table size is small and static, which simplifies the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 code quite a bit. Revisit this if and when it becomes necessary. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 #define MAX_KEYS 4
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 /* This is the structure pointed to by the pointer returned
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 by __gthread_get_tls_data. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 struct tls_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 int *owner;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 void *values[MAX_KEYS];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 unsigned int generation[MAX_KEYS];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 /* To make sure we only delete TLS data associated with this object,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 include a pointer to a local variable in the TLS data object. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 static int self_owner;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 /* Flag to check whether the delete hook is installed. Once installed
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 it is only removed when unloading this module. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 static volatile int delete_hook_installed;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 /* TLS data access internal API. A straight __thread variable starting with
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 VxWorks 7, a pointer returned by kernel provided routines otherwise. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 #if _VXWORKS_MAJOR_GE(7)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 static __thread struct tls_data *__gthread_tls_data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 #define VX_GET_TLS_DATA() __gthread_tls_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 #define VX_SET_TLS_DATA(x) __gthread_tls_data = (x)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 #define VX_ENTER_TLS_DTOR()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 #define VX_LEAVE_TLS_DTOR()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 extern void *__gthread_get_tls_data (void);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 extern void __gthread_set_tls_data (void *data);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 extern void __gthread_enter_tls_dtor_context (void);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 extern void __gthread_leave_tls_dtor_context (void);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 #define VX_GET_TLS_DATA() __gthread_get_tls_data()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 #define VX_SET_TLS_DATA(x) __gthread_set_tls_data(x)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 #define VX_ENTER_TLS_DTOR() __gthread_enter_tls_dtor_context ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 #define VX_LEAVE_TLS_DTOR() __gthread_leave_tls_dtor_context ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 /* This is a global structure which records all of the active keys.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 A key is potentially valid (i.e. has been handed out by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 __gthread_key_create) iff its generation count in this structure is
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 even. In that case, the matching entry in the dtors array is a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 routine to be called when a thread terminates with a valid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 non-NULL specific value for that key.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 A key is actually valid in a thread T iff the generation count
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 stored in this structure is equal to the generation count stored in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 T's specific-value structure. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 typedef void (*tls_dtor) (void *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 struct tls_keys
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 tls_dtor dtor[MAX_KEYS];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 unsigned int generation[MAX_KEYS];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 #define KEY_VALID_P(key) !(tls_keys.generation[key] & 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 /* Note: if MAX_KEYS is increased, this initializer must be updated
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 to match. All the generation counts begin at 1, which means no
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 key is valid. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 static struct tls_keys tls_keys =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 { NULL, NULL, NULL, NULL },
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 { 1, 1, 1, 1 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 /* This lock protects the tls_keys structure. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 static __gthread_mutex_t tls_lock;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 static __gthread_once_t tls_init_guard = __GTHREAD_ONCE_INIT;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 /* Internal routines. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 /* The task TCB has just been deleted. Call the destructor
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 function for each TLS key that has both a destructor and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 a non-NULL specific value in this thread.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 This routine does not need to take tls_lock; the generation
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 count protects us from calling a stale destructor. It does
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 need to read tls_keys.dtor[key] atomically. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 tls_delete_hook (void *tcb ATTRIBUTE_UNUSED)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 struct tls_data *data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 __gthread_key_t key;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177 data = VX_GET_TLS_DATA();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 if (data && data->owner == &self_owner)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 VX_ENTER_TLS_DTOR();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 for (key = 0; key < MAX_KEYS; key++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 if (data->generation[key] == tls_keys.generation[key])
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 tls_dtor dtor = tls_keys.dtor[key];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 if (dtor)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 dtor (data->values[key]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 free (data);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 VX_LEAVE_TLS_DTOR();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195 VX_SET_TLS_DATA(NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 /* Initialize global data used by the TLS system. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 tls_init (void)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 __GTHREAD_MUTEX_INIT_FUNCTION (&tls_lock);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 static void tls_destructor (void) __attribute__ ((destructor));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 tls_destructor (void)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 #ifdef __RTP__
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 /* All threads but this one should have exited by now. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212 tls_delete_hook (NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214 /* Unregister the hook. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 if (delete_hook_installed)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 taskDeleteHookDelete ((FUNCPTR)tls_delete_hook);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218 if (tls_init_guard.done && __gthread_mutex_lock (&tls_lock) != ERROR)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 semDelete (tls_lock);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 /* External interface */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 /* Store in KEYP a value which can be passed to __gthread_setspecific/
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225 __gthread_getspecific to store and retrieve a value which is
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 specific to each calling thread. If DTOR is not NULL, it will be
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 called when a thread terminates with a non-NULL specific value for
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 this key, with the value as its sole argument. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 __gthread_key_create (__gthread_key_t *keyp, tls_dtor dtor)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 __gthread_key_t key;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235 __gthread_once (&tls_init_guard, tls_init);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237 if (__gthread_mutex_lock (&tls_lock) == ERROR)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 return errno;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 for (key = 0; key < MAX_KEYS; key++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241 if (!KEY_VALID_P (key))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 goto found_slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 /* no room */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 __gthread_mutex_unlock (&tls_lock);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 return EAGAIN;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 found_slot:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 tls_keys.generation[key]++; /* making it even */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 tls_keys.dtor[key] = dtor;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 *keyp = key;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 __gthread_mutex_unlock (&tls_lock);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 /* Invalidate KEY; it can no longer be used as an argument to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 setspecific/getspecific. Note that this does NOT call destructor
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 functions for any live values for this key. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 __gthread_key_delete (__gthread_key_t key)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 if (key >= MAX_KEYS)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 return EINVAL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 __gthread_once (&tls_init_guard, tls_init);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 if (__gthread_mutex_lock (&tls_lock) == ERROR)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 return errno;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 if (!KEY_VALID_P (key))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 __gthread_mutex_unlock (&tls_lock);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 return EINVAL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 tls_keys.generation[key]++; /* making it odd */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 tls_keys.dtor[key] = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 __gthread_mutex_unlock (&tls_lock);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 /* Retrieve the thread-specific value for KEY. If it has never been
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 set in this thread, or KEY is invalid, returns NULL.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286 It does not matter if this function races with key_create or
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 key_delete; the worst that can happen is you get a value other than
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 the one that a serialized implementation would have provided. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 void *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 __gthread_getspecific (__gthread_key_t key)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 struct tls_data *data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 if (key >= MAX_KEYS)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 data = VX_GET_TLS_DATA();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 if (!data)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 if (data->generation[key] != tls_keys.generation[key])
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 return data->values[key];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 /* Set the thread-specific value for KEY. If KEY is invalid, or
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310 memory allocation fails, returns -1, otherwise 0.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 The generation count protects this function against races with
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 key_create/key_delete; the worst thing that can happen is that a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 value is successfully stored into a dead generation (and then
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 immediately becomes invalid). However, we do have to make sure
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316 to read tls_keys.generation[key] atomically. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319 __gthread_setspecific (__gthread_key_t key, void *value)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321 struct tls_data *data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 unsigned int generation;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 if (key >= MAX_KEYS)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 return EINVAL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 data = VX_GET_TLS_DATA();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329 if (!data)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 if (!delete_hook_installed)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 /* Install the delete hook. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 if (__gthread_mutex_lock (&tls_lock) == ERROR)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 return ENOMEM;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336 if (!delete_hook_installed)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 taskDeleteHookAdd ((FUNCPTR)tls_delete_hook);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 delete_hook_installed = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 __gthread_mutex_unlock (&tls_lock);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344 data = malloc (sizeof (struct tls_data));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 if (!data)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 return ENOMEM;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348 memset (data, 0, sizeof (struct tls_data));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 data->owner = &self_owner;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 VX_SET_TLS_DATA(data);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 generation = tls_keys.generation[key];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 if (generation & 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 return EINVAL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 data->generation[key] = generation;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 data->values[key] = value;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 #endif /* __GTHREADS */