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 /* | 7 /* |
8 * NaCl Server Runtime user thread state. | 8 * NaCl Server Runtime user thread state. |
9 */ | 9 */ |
10 | |
11 #include <string.h> | |
12 | |
10 #include "native_client/src/shared/platform/aligned_malloc.h" | 13 #include "native_client/src/shared/platform/aligned_malloc.h" |
11 #include "native_client/src/shared/platform/nacl_check.h" | 14 #include "native_client/src/shared/platform/nacl_check.h" |
12 #include "native_client/src/shared/platform/nacl_exit.h" | 15 #include "native_client/src/shared/platform/nacl_exit.h" |
13 #include "native_client/src/shared/platform/nacl_sync_checked.h" | 16 #include "native_client/src/shared/platform/nacl_sync_checked.h" |
14 | 17 |
15 #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h" | 18 #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h" |
16 #include "native_client/src/trusted/service_runtime/nacl_desc_effector_ldr.h" | 19 #include "native_client/src/trusted/service_runtime/nacl_desc_effector_ldr.h" |
17 #include "native_client/src/trusted/service_runtime/nacl_globals.h" | 20 #include "native_client/src/trusted/service_runtime/nacl_globals.h" |
18 #include "native_client/src/trusted/service_runtime/nacl_tls.h" | 21 #include "native_client/src/trusted/service_runtime/nacl_tls.h" |
19 #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h" | 22 #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h" |
20 #include "native_client/src/trusted/service_runtime/nacl_stack_safety.h" | 23 #include "native_client/src/trusted/service_runtime/nacl_stack_safety.h" |
21 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h" | 24 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h" |
22 | 25 |
23 | 26 |
24 void WINAPI NaClThreadLauncher(void *state) { | 27 void WINAPI NaClAppThreadLauncher(void *state) { |
25 struct NaClAppThread *natp = (struct NaClAppThread *) state; | 28 struct NaClAppThread *natp = (struct NaClAppThread *) state; |
26 uint32_t thread_idx; | 29 uint32_t thread_idx; |
27 NaClLog(4, "NaClThreadLauncher: entered\n"); | 30 NaClLog(4, "NaClAppThreadLauncher: entered\n"); |
28 | 31 |
29 NaClSignalStackRegister(natp->signal_stack); | 32 NaClSignalStackRegister(natp->signal_stack); |
30 | 33 |
31 NaClLog(4, " natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp); | 34 NaClLog(4, " natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp); |
32 NaClLog(4, " prog_ctr = 0x%016"NACL_PRIxNACL_REG"\n", natp->user.prog_ctr); | 35 NaClLog(4, " prog_ctr = 0x%016"NACL_PRIxNACL_REG"\n", natp->user.prog_ctr); |
33 NaClLog(4, "stack_ptr = 0x%016"NACL_PRIxPTR"\n", | 36 NaClLog(4, "stack_ptr = 0x%016"NACL_PRIxPTR"\n", |
34 NaClGetThreadCtxSp(&natp->user)); | 37 NaClGetThreadCtxSp(&natp->user)); |
35 | 38 |
36 thread_idx = NaClGetThreadIdx(natp); | 39 thread_idx = NaClGetThreadIdx(natp); |
37 CHECK(0 < thread_idx); | 40 CHECK(0 < thread_idx); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 /* NOTREACHED */ | 137 /* NOTREACHED */ |
135 } | 138 } |
136 | 139 |
137 | 140 |
138 struct NaClAppThread *NaClAppThreadMake(struct NaClApp *nap, | 141 struct NaClAppThread *NaClAppThreadMake(struct NaClApp *nap, |
139 uintptr_t usr_entry, | 142 uintptr_t usr_entry, |
140 uintptr_t usr_stack_ptr, | 143 uintptr_t usr_stack_ptr, |
141 uint32_t user_tls1, | 144 uint32_t user_tls1, |
142 uint32_t user_tls2) { | 145 uint32_t user_tls2) { |
143 struct NaClAppThread *natp; | 146 struct NaClAppThread *natp; |
144 int rv; | |
145 uint32_t tls_idx; | 147 uint32_t tls_idx; |
146 | 148 |
147 natp = NaClAlignedMalloc(sizeof *natp, __alignof(struct NaClAppThread)); | 149 natp = NaClAlignedMalloc(sizeof *natp, __alignof(struct NaClAppThread)); |
148 if (natp == NULL) { | 150 if (natp == NULL) { |
149 return NULL; | 151 return NULL; |
150 } | 152 } |
151 | 153 |
152 NaClLog(4, " natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp); | 154 NaClLog(4, " natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp); |
153 NaClLog(4, " nap = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) nap); | 155 NaClLog(4, " nap = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) nap); |
154 NaClLog(4, "usr_stack_ptr = 0x%016"NACL_PRIxPTR"\n", usr_stack_ptr); | 156 NaClLog(4, "usr_stack_ptr = 0x%016"NACL_PRIxPTR"\n", usr_stack_ptr); |
155 | 157 |
156 /* | 158 /* |
157 * Set these early, in case NaClTlsAllocate() wants to examine them. | 159 * Set these early, in case NaClTlsAllocate() wants to examine them. |
158 */ | 160 */ |
159 natp->nap = nap; | 161 natp->nap = nap; |
160 natp->thread_num = -1; /* illegal index */ | 162 natp->thread_num = -1; /* illegal index */ |
163 natp->host_thread_is_defined = 0; | |
164 memset(&natp->host_thread, 0, sizeof(natp->host_thread)); | |
161 | 165 |
162 /* | 166 /* |
163 * Even though we don't know what segment base/range should gs/r9/nacl_tls_idx | 167 * Even though we don't know what segment base/range should gs/r9/nacl_tls_idx |
164 * select, we still need one, since it identifies the thread when we context | 168 * select, we still need one, since it identifies the thread when we context |
165 * switch back. This use of a dummy tls is only needed for the main thread, | 169 * switch back. This use of a dummy tls is only needed for the main thread, |
166 * which is expected to invoke the tls_init syscall from its crt code (before | 170 * which is expected to invoke the tls_init syscall from its crt code (before |
167 * main or much of libc can run). Other threads are spawned with the thread | 171 * main or much of libc can run). Other threads are spawned with the thread |
168 * pointer address as a parameter. | 172 * pointer address as a parameter. |
169 */ | 173 */ |
170 tls_idx = NaClTlsAllocate(natp); | 174 tls_idx = NaClTlsAllocate(natp); |
(...skipping 20 matching lines...) Expand all Loading... | |
191 } | 195 } |
192 | 196 |
193 if (!NaClMutexCtor(&natp->suspend_mu)) { | 197 if (!NaClMutexCtor(&natp->suspend_mu)) { |
194 goto cleanup_mu; | 198 goto cleanup_mu; |
195 } | 199 } |
196 natp->suspend_state = NACL_APP_THREAD_TRUSTED; | 200 natp->suspend_state = NACL_APP_THREAD_TRUSTED; |
197 natp->suspended_registers = NULL; | 201 natp->suspended_registers = NULL; |
198 natp->fault_signal = 0; | 202 natp->fault_signal = 0; |
199 | 203 |
200 natp->dynamic_delete_generation = 0; | 204 natp->dynamic_delete_generation = 0; |
201 | 205 return natp; |
202 rv = NaClThreadCtor(&natp->thread, | |
203 NaClThreadLauncher, | |
204 (void *) natp, | |
205 NACL_KERN_STACK_SIZE); | |
206 if (rv != 0) { | |
207 return natp; /* Success */ | |
208 } | |
209 | 206 |
210 NaClMutexDtor(&natp->suspend_mu); | 207 NaClMutexDtor(&natp->suspend_mu); |
bsy
2012/12/17 21:02:05
this is dead?
Mark Seaborn
2012/12/17 22:30:14
Good point. Removed.
| |
211 cleanup_mu: | 208 cleanup_mu: |
212 NaClMutexDtor(&natp->mu); | 209 NaClMutexDtor(&natp->mu); |
213 if (NULL != natp->signal_stack) { | 210 if (NULL != natp->signal_stack) { |
214 NaClSignalStackFree(&natp->signal_stack); | 211 NaClSignalStackFree(&natp->signal_stack); |
215 natp->signal_stack = NULL; | 212 natp->signal_stack = NULL; |
216 } | 213 } |
217 cleanup_free: | 214 cleanup_free: |
218 NaClAlignedFree(natp); | 215 NaClAlignedFree(natp); |
219 return NULL; | 216 return NULL; |
220 } | 217 } |
221 | 218 |
222 | 219 |
220 int NaClAppThreadSpawn(struct NaClApp *nap, | |
221 uintptr_t usr_entry, | |
222 uintptr_t usr_stack_ptr, | |
223 uint32_t user_tls1, | |
224 uint32_t user_tls2) { | |
225 struct NaClAppThread *natp = NaClAppThreadMake(nap, usr_entry, usr_stack_ptr, | |
226 user_tls1, user_tls2); | |
227 if (natp == NULL) { | |
228 return 0; | |
229 } | |
230 /* | |
231 * We set host_thread_is_defined assuming, for now, that | |
232 * NaClThreadCtor() will succeed. | |
233 */ | |
234 natp->host_thread_is_defined = 1; | |
235 if (!NaClThreadCtor(&natp->host_thread, NaClAppThreadLauncher, (void *) natp, | |
236 NACL_KERN_STACK_SIZE)) { | |
237 /* | |
238 * No other thread saw the NaClAppThread, so it is OK that | |
239 * host_thread was not initialized despite host_thread_is_defined | |
240 * being set. | |
241 */ | |
242 natp->host_thread_is_defined = 0; | |
243 NaClAppThreadDelete(natp); | |
244 return 0; | |
245 } | |
246 return 1; | |
247 } | |
248 | |
249 | |
223 void NaClAppThreadDelete(struct NaClAppThread *natp) { | 250 void NaClAppThreadDelete(struct NaClAppThread *natp) { |
224 /* | 251 /* |
225 * the thread must not be still running, else this crashes the system | 252 * the thread must not be still running, else this crashes the system |
226 */ | 253 */ |
227 | 254 |
255 if (natp->host_thread_is_defined) { | |
256 NaClThreadDtor(&natp->host_thread); | |
bsy
2012/12/17 21:02:05
if an embedding-supplied thread, there should prob
Mark Seaborn
2012/12/17 22:30:14
Not necessarily. If the embedder implements its o
| |
257 } | |
228 free(natp->suspended_registers); | 258 free(natp->suspended_registers); |
229 NaClMutexDtor(&natp->suspend_mu); | 259 NaClMutexDtor(&natp->suspend_mu); |
230 NaClThreadDtor(&natp->thread); | |
231 NaClSignalStackFree(natp->signal_stack); | 260 NaClSignalStackFree(natp->signal_stack); |
232 natp->signal_stack = NULL; | 261 natp->signal_stack = NULL; |
233 NaClTlsFree(natp); | 262 NaClTlsFree(natp); |
234 NaClMutexDtor(&natp->mu); | 263 NaClMutexDtor(&natp->mu); |
235 NaClAlignedFree(natp); | 264 NaClAlignedFree(natp); |
236 } | 265 } |
OLD | NEW |