annotate libphobos/libdruntime/gcc/emutls.d @ 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 // GNU D Compiler emulated TLS routines.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 // Copyright (C) 2019-2020 Free Software Foundation, Inc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4 // GCC is free software; you can redistribute it and/or modify it under
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 // the terms of the GNU General Public License as published by the Free
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6 // Software Foundation; either version 3, or (at your option) any later
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 // version.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 // for more details.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 // Under Section 7 of GPL version 3, you are granted additional
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 // permissions described in the GCC Runtime Library Exception, version
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16 // 3.1, as published by the Free Software Foundation.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 // You should have received a copy of the GNU General Public License and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19 // a copy of the GCC Runtime Library Exception along with this program;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 // <http://www.gnu.org/licenses/>.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 // This code is based on the libgcc emutls.c emulated TLS support.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 module gcc.emutls;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 import core.atomic, core.stdc.stdlib, core.stdc.string, core.sync.mutex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 import rt.util.container.array, rt.util.container.hashtab;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 import core.internal.traits : classInstanceAlignment;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 import gcc.builtins, gcc.gthread;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 version (GNU_EMUTLS): private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 alias word = __builtin_machine_uint;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 alias pointer = __builtin_pointer_uint;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 alias TlsArray = Array!(void**);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 /*
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 * TLS control data emitted by GCC for every TLS variable.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 struct __emutls_object
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 word size;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 word align_;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 union
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 pointer offset;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 void* ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 ubyte* templ;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 // Per-thread key to obtain the per-thread TLS variable array
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 __gshared __gthread_key_t emutlsKey;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 // Largest, currently assigned TLS variable offset
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 __gshared pointer emutlsMaxOffset = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 // Contains the size of the TLS variables (for GC)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 __gshared Array!word emutlsSizes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 // Contains the TLS variable array for single-threaded apps
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 __gshared TlsArray singleArray;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 // List of all currently alive TlsArrays (for GC)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 __gshared HashTab!(TlsArray*, TlsArray*) emutlsArrays;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 // emutlsMutex Mutex + @nogc handling
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 enum mutexAlign = classInstanceAlignment!Mutex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 enum mutexClassInstanceSize = __traits(classInstanceSize, Mutex);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 __gshared align(mutexAlign) void[mutexClassInstanceSize] _emutlsMutex;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 @property Mutex emutlsMutex() nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 return cast(Mutex) _emutlsMutex.ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 /*
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 * Global (de)initialization functions
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 extern (C) void _d_emutls_init() nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 memcpy(_emutlsMutex.ptr, typeid(Mutex).initializer.ptr, _emutlsMutex.length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 (cast(Mutex) _emutlsMutex.ptr).__ctor();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 if (__gthread_key_create(&emutlsKey, &emutlsDestroyThread) != 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 abort();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 __gshared __gthread_once_t initOnce = GTHREAD_ONCE_INIT;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 /*
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 * emutls main entrypoint, called by GCC for each TLS variable access.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 extern (C) void* __emutls_get_address(shared __emutls_object* obj) nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 pointer offset;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 if (__gthread_active_p())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 // Obtain the offset index into the TLS array (same for all-threads)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 // for requested var. If it is unset, obtain a new offset index.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 offset = atomicLoad!(MemoryOrder.acq, pointer)(obj.offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 if (__builtin_expect(offset == 0, 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 __gthread_once(&initOnce, &_d_emutls_init);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 emutlsMutex.lock_nothrow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 offset = obj.offset;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 if (offset == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 offset = ++emutlsMaxOffset;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 emutlsSizes.ensureLength(offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 // Note: it's important that we copy any data from obj and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 // do not keep an reference to obj itself: If a library is
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113 // unloaded, its tls variables are not removed from the arrays
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 // and the GC will still scan these. If we then try to reference
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 // a pointer to the data segment of an unloaded library, this
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 // will crash.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 emutlsSizes[offset - 1] = obj.size;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 atomicStore!(MemoryOrder.rel, pointer)(obj.offset, offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 emutlsMutex.unlock_nothrow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 // For single-threaded systems, don't synchronize
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 if (__builtin_expect(obj.offset == 0, 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 offset = ++emutlsMaxOffset;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 emutlsSizes.ensureLength(offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 emutlsSizes[offset - 1] = obj.size;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 obj.offset = offset;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 TlsArray* arr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 if (__gthread_active_p())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 arr = cast(TlsArray*) __gthread_getspecific(emutlsKey);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 arr = &singleArray;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 // This will always be false for singleArray
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 if (__builtin_expect(arr == null, 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 arr = mallocTlsArray(offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 __gthread_setspecific(emutlsKey, arr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 emutlsMutex.lock_nothrow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 emutlsArrays[arr] = arr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 emutlsMutex.unlock_nothrow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 // Check if we have to grow the per-thread array
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 else if (__builtin_expect(offset > arr.length, 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 (*arr).ensureLength(offset);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 // Offset 0 is used as a not-initialized marker above. In the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 // TLS array, we start at 0.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 auto index = offset - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 // Get the per-thread pointer from the TLS array
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 void** ret = (*arr)[index];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 if (__builtin_expect(ret == null, 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 // Initial access, have to allocate the storage
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 ret = emutlsAlloc(obj);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 (*arr)[index] = ret;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 return ret;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 // 1:1 copy from libgcc emutls.c
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 extern (C) void __emutls_register_common(__emutls_object* obj, word size, word align_, ubyte* templ) nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 if (obj.size < size)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 obj.size = size;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 obj.templ = null;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 if (obj.align_ < align_)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 obj.align_ = align_;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 if (templ && size == obj.size)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 obj.templ = templ;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 // 1:1 copy from libgcc emutls.c
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 void** emutlsAlloc(shared __emutls_object* obj) nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 void* ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 void* ret;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 enum pointerSize = (void*).sizeof;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 /* We could use here posix_memalign if available and adjust
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 emutls_destroy accordingly. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198 if ((cast() obj).align_ <= pointerSize)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 ptr = malloc((cast() obj).size + pointerSize);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 if (ptr == null)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 abort();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 (cast(void**) ptr)[0] = ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 ret = ptr + pointerSize;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 ptr = malloc(obj.size + pointerSize + obj.align_ - 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 if (ptr == null)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 abort();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 ret = cast(void*)((cast(pointer)(ptr + pointerSize + obj.align_ - 1)) & ~cast(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212 pointer)(obj.align_ - 1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 (cast(void**) ret)[-1] = ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 if (obj.templ)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 memcpy(ret, cast(ubyte*) obj.templ, cast() obj.size);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 memset(ret, 0, cast() obj.size);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 return cast(void**) ret;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 /*
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225 * When a thread has finished, remove the TLS array from the GC
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 * scan list emutlsArrays, free all allocated TLS variables and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 * finally free the array.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229 extern (C) void emutlsDestroyThread(void* ptr) nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 auto arr = cast(TlsArray*) ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 emutlsMutex.lock_nothrow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 emutlsArrays.remove(arr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 emutlsMutex.unlock_nothrow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 foreach (entry; *arr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 if (entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239 free(entry[-1]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 free(arr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 /*
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 * Allocate a new TLS array, set length according to offset.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 TlsArray* mallocTlsArray(pointer offset = 0) nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 static assert(TlsArray.alignof == (void*).alignof);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 void[] data = malloc(TlsArray.sizeof)[0 .. TlsArray.sizeof];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 if (data.ptr == null)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 abort();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 static immutable TlsArray init = TlsArray.init;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 memcpy(data.ptr, &init, data.length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 (cast(TlsArray*) data).length = 32;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 return cast(TlsArray*) data.ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 /*
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 * Make sure array is large enough to hold an entry for offset.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 * Note: the array index will be offset - 1!
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 void ensureLength(Value)(ref Array!(Value) arr, size_t offset) nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 // index is offset-1
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 if (offset > arr.length)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 auto newSize = arr.length * 2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 if (offset > newSize)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 newSize = offset + 32;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 arr.length = newSize;
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
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 // Public interface
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 void _d_emutls_scan(scope void delegate(void* pbeg, void* pend) nothrow cb) nothrow
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 void scanArray(scope TlsArray* arr) nothrow
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 foreach (index, entry; *arr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 auto ptr = cast(void*) entry;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286 if (ptr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 cb(ptr, ptr + emutlsSizes[index]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 __gthread_once(&initOnce, &_d_emutls_init);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 emutlsMutex.lock_nothrow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 // this code is effectively nothrow
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 try
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 foreach (arr, value; emutlsArrays)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 scanArray(arr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 catch (Exception)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 emutlsMutex.unlock_nothrow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 scanArray(&singleArray);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308 // Call this after druntime has been unloaded
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 void _d_emutls_destroy() nothrow @nogc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 if (__gthread_key_delete(emutlsKey) != 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 abort();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 (cast(Mutex) _emutlsMutex.ptr).__dtor();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 destroy(emutlsArrays);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316 }