OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #if NACL_OSX | 7 #if NACL_OSX |
8 # include <pthread.h> | 8 # include <pthread.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 uint32_t NaClTlsGetTlsValue2(struct NaClAppThread *natp) { | 136 uint32_t NaClTlsGetTlsValue2(struct NaClAppThread *natp) { |
137 return natp->user.tls_value2; | 137 return natp->user.tls_value2; |
138 } | 138 } |
139 | 139 |
140 uint32_t NaClGetThreadIdx(struct NaClAppThread *natp) { | 140 uint32_t NaClGetThreadIdx(struct NaClAppThread *natp) { |
141 return natp->user.tls_idx; | 141 return natp->user.tls_idx; |
142 } | 142 } |
143 | 143 |
144 #if NACL_OSX | 144 #if NACL_OSX |
145 | 145 |
146 pthread_key_t nacl_thread_info_key; | 146 static pthread_key_t nacl_thread_info_key; |
147 uint32_t nacl_thread_index_tls_offset; | 147 uint32_t nacl_current_thread_tls_offset; |
148 | 148 |
149 int NaClTlsInit(void) { | 149 int NaClTlsInit(void) { |
150 int errnum; | 150 int errnum; |
151 | 151 |
152 /* | 152 /* |
153 * Unlike Linux and Windows, Mac OS X does not provide TLS variables | 153 * Unlike Linux and Windows, Mac OS X does not provide TLS variables |
154 * that can be accessed via a TLS register without a function call, | 154 * that can be accessed via a TLS register without a function call, |
155 * which we need in order to restore the thread's trusted stack in | 155 * which we need in order to restore the thread's trusted stack in |
156 * nacl_syscall_64.S. | 156 * nacl_syscall_64.S. |
157 * | 157 * |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 return 0; | 190 return 0; |
191 } | 191 } |
192 | 192 |
193 errnum = pthread_key_create(&nacl_thread_info_key, (void (*)(void *)) 0); | 193 errnum = pthread_key_create(&nacl_thread_info_key, (void (*)(void *)) 0); |
194 if (0 != errnum) { | 194 if (0 != errnum) { |
195 NaClLog(LOG_WARNING, | 195 NaClLog(LOG_WARNING, |
196 "NaClTlsInit: pthread_key_create failed for thread info key, %d\n", | 196 "NaClTlsInit: pthread_key_create failed for thread info key, %d\n", |
197 errnum); | 197 errnum); |
198 return 0; | 198 return 0; |
199 } | 199 } |
200 nacl_thread_index_tls_offset = pthread_tsd_offset + 8 * nacl_thread_info_key; | 200 nacl_current_thread_tls_offset = |
| 201 pthread_tsd_offset + 8 * nacl_thread_info_key; |
201 | 202 |
202 return 1; | 203 return 1; |
203 } | 204 } |
204 | 205 |
205 void NaClTlsFini(void) { | 206 void NaClTlsFini(void) { |
206 int errnum = pthread_key_delete(nacl_thread_info_key); | 207 int errnum = pthread_key_delete(nacl_thread_info_key); |
207 if (0 != errnum) { | 208 if (0 != errnum) { |
208 NaClLog(LOG_FATAL, | 209 NaClLog(LOG_FATAL, |
209 "NaClTlsInit: pthread_key_delete failed for thread info key, %d\n", | 210 "NaClTlsInit: pthread_key_delete failed for thread info key, %d\n", |
210 errnum); | 211 errnum); |
211 } | 212 } |
212 NaClThreadIdxFini(); | 213 NaClThreadIdxFini(); |
213 return; | 214 return; |
214 } | 215 } |
215 | 216 |
216 void NaClTlsSetIdx(uint32_t tls_idx) { | 217 void NaClTlsSetCurrentThread(struct NaClAppThread *natp) { |
217 uint32_t tls_idx_check; | 218 struct NaClThreadContext *ntcp_check; |
218 | 219 |
219 #if 1 /* PARANOIA */ | 220 #if 1 /* PARANOIA */ |
220 if (NULL != pthread_getspecific(nacl_thread_info_key)) { | 221 if (NULL != pthread_getspecific(nacl_thread_info_key)) { |
221 NaClLog(LOG_WARNING, | 222 NaClLog(LOG_WARNING, |
222 "NaClSetThreadInfo invoked twice for the same thread\n"); | 223 "NaClSetThreadInfo invoked twice for the same thread\n"); |
223 } | 224 } |
224 #endif | 225 #endif |
225 pthread_setspecific(nacl_thread_info_key, (void *) (uintptr_t) tls_idx); | 226 if (pthread_setspecific(nacl_thread_info_key, &natp->user) != 0) { |
| 227 NaClLog(LOG_FATAL, "NaClTlsSetCurrentThread: " |
| 228 "pthread_setspecific() failed\n"); |
| 229 } |
226 | 230 |
227 /* | 231 /* |
228 * Sanity check: Make sure that reading back the value using our | 232 * Sanity check: Make sure that reading back the value using our |
229 * knowledge of Mac OS X's TLS internals gives us the correct value. | 233 * knowledge of Mac OS X's TLS internals gives us the correct value. |
230 * This checks that we inferred _PTHREAD_TSD_OFFSET correctly earlier. | 234 * This checks that we inferred _PTHREAD_TSD_OFFSET correctly earlier. |
231 */ | 235 */ |
232 __asm__("movl %%gs:(%1), %0" | 236 __asm__("movq %%gs:(%1), %0" |
233 : "=r"(tls_idx_check) | 237 : "=r"(ntcp_check) |
234 : "r"(nacl_thread_index_tls_offset)); | 238 : "r"(nacl_current_thread_tls_offset)); |
235 if (tls_idx_check != tls_idx) { | 239 if (ntcp_check != &natp->user) { |
236 NaClLog(LOG_FATAL, "NaClTlsSetIdx: Sanity check failed: " | 240 NaClLog(LOG_FATAL, "NaClTlsSetCurrentThread: Sanity check failed: " |
237 "TLS offset must be wrong\n"); | 241 "TLS offset must be wrong\n"); |
238 } | 242 } |
239 } | 243 } |
240 | 244 |
241 /* | 245 /* |
242 * May be called from asm (or have compiler-generated code copied into | 246 * May be called from asm (or have compiler-generated code copied into |
243 * asm)! We assume that register state is amenable to the use of | 247 * asm)! We assume that register state is amenable to the use of |
244 * pthread_getspecific. For both x86-32 and x86-64 OSX, this compiles | 248 * pthread_getspecific. For both x86-32 and x86-64 OSX, this compiles |
245 * to just a memory load using the %gs or %fs segment prefixes, and | 249 * to just a memory load using the %gs or %fs segment prefixes, and |
246 * for x86-64 we do not change %fs. (However, we are unlikely to use | 250 * for x86-64 we do not change %fs. (However, we are unlikely to use |
247 * this for x86-32 on OSX, since that's handled by NaCl "Classic" | 251 * this for x86-32 on OSX, since that's handled by NaCl "Classic" |
248 * where %gs gets swapped, and we use %gs >> 3 in the asm code.) | 252 * where %gs gets swapped, and we use %gs >> 3 in the asm code.) |
249 */ | 253 */ |
250 uint32_t NaClTlsGetIdx(void) { | 254 struct NaClAppThread *NaClTlsGetCurrentThread(void) { |
251 return (intptr_t) pthread_getspecific(nacl_thread_info_key); | 255 struct NaClThreadContext *ntcp = pthread_getspecific(nacl_thread_info_key); |
| 256 return NaClAppThreadFromThreadContext(ntcp); |
252 } | 257 } |
253 | 258 |
254 #elif NACL_LINUX || NACL_WINDOWS | 259 #elif NACL_LINUX || NACL_WINDOWS |
255 | 260 |
256 THREAD uint32_t nacl_thread_index; | 261 /* May be NULL if the current thread does not host a NaClAppThread. */ |
257 /* encoded index; 0 is used to indicate error */ | 262 THREAD struct NaClThreadContext *nacl_current_thread; |
258 | 263 |
259 int NaClTlsInit(void) { | 264 int NaClTlsInit(void) { |
260 | |
261 NaClThreadStartupCheck(); | 265 NaClThreadStartupCheck(); |
262 | 266 |
263 if (!NaClThreadIdxInit()) { | 267 if (!NaClThreadIdxInit()) { |
264 return 0; | 268 return 0; |
265 } | 269 } |
266 return 1; | 270 return 1; |
267 } | 271 } |
268 | 272 |
269 void NaClTlsFini(void) { | 273 void NaClTlsFini(void) { |
270 NaClThreadIdxFini(); | 274 NaClThreadIdxFini(); |
271 } | 275 } |
272 | 276 |
273 /* | 277 /* |
274 * On x86-64, we must avoid using segment registers since Windows | 278 * On x86-64, we must avoid using segment registers since Windows |
275 * Vista 64, Windows 7 64, etc do not permit user code to create LDT | 279 * Vista 64, Windows 7 64, etc do not permit user code to create LDT |
276 * entries. The sandboxing scheme reserves %r15 for the base of the | 280 * entries. The sandboxing scheme reserves %r15 for the base of the |
277 * NaCl app's 4G address space, but does not reserve any additional | 281 * NaCl app's 4G address space, but does not reserve any additional |
278 * registers for thread identity. This reduces additional register | 282 * registers for thread identity. This reduces additional register |
279 * pressure, but implies that we have to figure out the thread | 283 * pressure, but implies that we have to figure out the thread |
280 * identity in some other way -- we use TLS (or TSD, see below) to do | 284 * identity in some other way -- we use TLS (or TSD, see below) to do |
281 * so, and on context switch we must access the TLS variable in order | 285 * so, and on context switch we must access the TLS variable in order |
282 * to determine where to save the user register context. | 286 * to determine where to save the user register context. |
283 */ | 287 */ |
284 void NaClTlsSetIdx(uint32_t tls_idx) { | 288 void NaClTlsSetCurrentThread(struct NaClAppThread *natp) { |
285 nacl_thread_index = tls_idx; | 289 nacl_current_thread = &natp->user; |
286 } | 290 } |
287 | 291 |
288 uint32_t NaClTlsGetIdx(void) { | 292 struct NaClAppThread *NaClTlsGetCurrentThread(void) { |
289 return nacl_thread_index; | 293 return NaClAppThreadFromThreadContext(nacl_current_thread); |
290 } | 294 } |
291 | 295 |
292 #else | 296 #else |
293 # error "Woe to the service runtime. What OS is it being compiled for?!?" | 297 # error "Woe to the service runtime. What OS is it being compiled for?!?" |
294 #endif | 298 #endif |
OLD | NEW |