1 /*
2 * Copyright (c) 2000-2005 by Hewlett-Packard Company. All rights reserved.
3 *
4 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
6 *
7 * Permission is hereby granted to use or copy this program
8 * for any purpose, provided the above notices are retained on all copies.
9 * Permission to modify the code and to distribute modified code is granted,
10 * provided the above notices are retained, and a notice that the code was
11 * modified is included with the above copyright notice.
12 */
13 14 /*
15 * Included indirectly from a thread-library-specific file.
16 * This is the interface for thread-local allocation, whose implementation
17 * is mostly thread-library-independent. Here we describe only the interface
18 * that needs to be known and invoked from the thread support layer;
19 * the actual implementation also exports `GC_malloc` and friends, which are
20 * declared in `gc.h` file.
21 */
22 23 #ifndef GC_THREAD_LOCAL_ALLOC_H
24 #define GC_THREAD_LOCAL_ALLOC_H
25 26 #include "gc_priv.h"
27 28 #ifdef THREAD_LOCAL_ALLOC
29 30 # if defined(USE_HPUX_TLS)
31 # error USE_HPUX_TLS macro was replaced by USE_COMPILER_TLS
32 # endif
33 34 # include <stdlib.h>
35 36 EXTERN_C_BEGIN
37 38 # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) \
39 && !defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) \
40 && !defined(USE_CUSTOM_SPECIFIC)
41 # if defined(GC_WIN32_THREADS)
42 # if defined(CYGWIN32) && GC_GNUC_PREREQ(4, 0)
43 # if defined(__clang__)
44 /* As of Cygwin clang-3.5.2, thread-local storage is unsupported. */
45 # define USE_PTHREAD_SPECIFIC
46 # else
47 # define USE_COMPILER_TLS
48 # endif
49 # elif defined(__GNUC__) || defined(MSWINCE)
50 # define USE_WIN32_SPECIFIC
51 # else
52 # define USE_WIN32_COMPILER_TLS
53 # endif /* !GNU */
54 55 # elif defined(HOST_ANDROID)
56 # if defined(ARM32) \
57 && (GC_GNUC_PREREQ(4, 6) || GC_CLANG_PREREQ_FULL(3, 8, 256229))
58 # define USE_COMPILER_TLS
59 # elif !defined(__clang__) && !defined(ARM32)
60 /* TODO: Support clang/arm64. */
61 # define USE_COMPILER_TLS
62 # else
63 # define USE_PTHREAD_SPECIFIC
64 # endif
65 66 # elif defined(LINUX) && GC_GNUC_PREREQ(3, 3) /* `&& !HOST_ANDROID` */
67 # if defined(ARM32) || defined(AVR32)
68 /* TODO: Change to USE_COMPILER_TLS on Linux/arm. */
69 # define USE_PTHREAD_SPECIFIC
70 # elif defined(AARCH64) && defined(__clang__) && !GC_CLANG_PREREQ(8, 0)
71 /* To avoid "R_AARCH64_ABS64 used with TLS symbol" linker warnings. */
72 # define USE_PTHREAD_SPECIFIC
73 # else
74 # define USE_COMPILER_TLS
75 # endif
76 77 # elif (defined(COSMO) || defined(FREEBSD) \
78 || (defined(NETBSD) && __NetBSD_Version__ >= 600000000 /* 6.0 */)) \
79 && (GC_GNUC_PREREQ(4, 4) || GC_CLANG_PREREQ(3, 9))
80 # define USE_COMPILER_TLS
81 82 # elif defined(HPUX)
83 # ifdef __GNUC__
84 /* Empirically, as of gcc-3.3, USE_COMPILER_TLS does not work. */
85 # define USE_PTHREAD_SPECIFIC
86 # else
87 # define USE_COMPILER_TLS
88 # endif
89 90 # elif defined(IRIX5) || defined(OPENBSD) || defined(SOLARIS) \
91 || defined(NINTENDO_SWITCH) || defined(NN_PLATFORM_CTR)
92 /* Use our own. */
93 # define USE_CUSTOM_SPECIFIC
94 95 # else
96 # define USE_PTHREAD_SPECIFIC
97 # endif
98 # endif /* !USE_x_SPECIFIC */
99 100 # ifndef THREAD_FREELISTS_KINDS
101 # ifdef ENABLE_DISCLAIM
102 # define THREAD_FREELISTS_KINDS (NORMAL + 2)
103 # else
104 # define THREAD_FREELISTS_KINDS (NORMAL + 1)
105 # endif
106 # endif /* !THREAD_FREELISTS_KINDS */
107 108 /*
109 * The first `GC_TINY_FREELISTS` free lists correspond to the first
110 * `GC_TINY_FREELISTS` multiples of `GC_GRANULE_BYTES`, i.e. we keep
111 * separate free lists for each multiple of `GC_GRANULE_BYTES` up to
112 * `(GC_TINY_FREELISTS-1) * GC_GRANULE_BYTES`. After that they may be
113 * spread out further.
114 */
115 116 /*
117 * This should be used for the `tlfs` field in the structure pointed to
118 * by a `GC_thread` entity. Free lists contain either a pointer or
119 * a small count reflecting the number of granules allocated at that size:
120 * - zero means thread-local allocation in use, free list is empty;
121 * - greater than zero but not greater than `DIRECT_GRANULES` means
122 * using global allocation, too few objects of this size have been
123 * allocated by this thread;
124 * - greater than `DIRECT_GRANULES` but less than `HBLKSIZE` means
125 * transition to local allocation, equivalent to zero;
126 * - not less than `HBLKSIZE` means pointer to nonempty free list.
127 */
128 129 struct thread_local_freelists {
130 /* Note: preserve `*_freelists` names for some clients. */
131 void *_freelists[THREAD_FREELISTS_KINDS][GC_TINY_FREELISTS];
132 # define ptrfree_freelists _freelists[PTRFREE]
133 # define normal_freelists _freelists[NORMAL]
134 # ifdef GC_GCJ_SUPPORT
135 void *gcj_freelists[GC_TINY_FREELISTS];
136 /* A value used for `gcj_freelists[-1]`; allocation is erroneous. */
137 # define ERROR_FL GC_WORD_MAX
138 # endif
139 140 /* Do not use local free lists for up to this much allocation. */
141 # define DIRECT_GRANULES (HBLKSIZE / GC_GRANULE_BYTES)
142 };
143 typedef struct thread_local_freelists *GC_tlfs;
144 145 # if defined(USE_PTHREAD_SPECIFIC)
146 # define GC_getspecific pthread_getspecific
147 # define GC_setspecific pthread_setspecific
148 # define GC_key_create pthread_key_create
149 /*
150 * Explicitly delete the value to stop the TLS (thread-local storage)
151 * destructor from being called repeatedly.
152 */
153 # define GC_remove_specific(key) (void)pthread_setspecific(key, NULL)
154 # define GC_remove_specific_after_fork(key, t) \
155 (void)0 /*< no action needed */
156 typedef pthread_key_t GC_key_t;
157 # elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS)
158 # define GC_getspecific(x) (x)
159 # define GC_setspecific(key, v) ((key) = (v), 0)
160 # define GC_key_create(key, d) 0
161 /* Just to clear the pointer to `tlfs`. */
162 # define GC_remove_specific(key) (void)GC_setspecific(key, NULL)
163 # define GC_remove_specific_after_fork(key, t) (void)0
164 typedef void *GC_key_t;
165 # elif defined(USE_WIN32_SPECIFIC)
166 # define GC_getspecific TlsGetValue
167 /* Note: we assume that zero means success, Win32 API does the opposite. */
168 # define GC_setspecific(key, v) !TlsSetValue(key, v)
169 # ifndef TLS_OUT_OF_INDEXES
170 /* This is currently missing in WinCE. */
171 # define TLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
172 # endif
173 # define GC_key_create(key, d) \
174 ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0)
175 /* TODO: Is `TlsFree` needed on process exit/detach? */
176 # define GC_remove_specific(key) (void)GC_setspecific(key, NULL)
177 # define GC_remove_specific_after_fork(key, t) (void)0
178 typedef DWORD GC_key_t;
179 # elif defined(USE_CUSTOM_SPECIFIC)
180 EXTERN_C_END
181 # include "specific.h"
182 EXTERN_C_BEGIN
183 # else
184 # error implement me
185 # endif
186 187 /*
188 * Each thread structure must be initialized. This call must be made from
189 * the new thread. Caller should hold the allocator lock.
190 */
191 GC_INNER void GC_init_thread_local(GC_tlfs p);
192 193 /*
194 * Called when a thread is unregistered, or exits. Caller should hold
195 * the allocator lock.
196 */
197 GC_INNER void GC_destroy_thread_local(GC_tlfs p);
198 199 /*
200 * The thread support layer must arrange to mark thread-local free lists
201 * explicitly, since the link field is often invisible to the marker.
202 * It knows how to find all threads; we take care of an individual thread
203 * free-list structure.
204 */
205 GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p);
206 207 # ifdef GC_ASSERTIONS
208 GC_bool GC_is_thread_tsd_valid(void *tsd);
209 void GC_check_tls_for(GC_tlfs p);
210 # if defined(USE_CUSTOM_SPECIFIC)
211 void GC_check_tsd_marks(tsd *key);
212 # endif
213 # endif /* GC_ASSERTIONS */
214 215 # ifndef GC_ATTR_TLS_FAST
216 # define GC_ATTR_TLS_FAST /*< empty */
217 # endif
218 219 /*
220 * This is set up by `GC_init_thread_local()`. No need for cleanup
221 * on thread exit. But the thread support layer makes sure that
222 * `GC_thread_key` is traced, if necessary.
223 */
224 extern
225 # if defined(USE_COMPILER_TLS)
226 __thread GC_ATTR_TLS_FAST
227 # elif defined(USE_WIN32_COMPILER_TLS)
228 __declspec(thread) GC_ATTR_TLS_FAST
229 # endif
230 GC_key_t GC_thread_key;
231 232 EXTERN_C_END
233 234 #endif /* THREAD_LOCAL_ALLOC */
235 236 #endif /* GC_THREAD_LOCAL_ALLOC_H */
237