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; |
| 205 return natp; |
201 | 206 |
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 | |
210 NaClMutexDtor(&natp->suspend_mu); | |
211 cleanup_mu: | 207 cleanup_mu: |
212 NaClMutexDtor(&natp->mu); | 208 NaClMutexDtor(&natp->mu); |
213 if (NULL != natp->signal_stack) { | 209 if (NULL != natp->signal_stack) { |
214 NaClSignalStackFree(&natp->signal_stack); | 210 NaClSignalStackFree(&natp->signal_stack); |
215 natp->signal_stack = NULL; | 211 natp->signal_stack = NULL; |
216 } | 212 } |
217 cleanup_free: | 213 cleanup_free: |
218 NaClAlignedFree(natp); | 214 NaClAlignedFree(natp); |
219 return NULL; | 215 return NULL; |
220 } | 216 } |
221 | 217 |
222 | 218 |
| 219 int NaClAppThreadSpawn(struct NaClApp *nap, |
| 220 uintptr_t usr_entry, |
| 221 uintptr_t usr_stack_ptr, |
| 222 uint32_t user_tls1, |
| 223 uint32_t user_tls2) { |
| 224 struct NaClAppThread *natp = NaClAppThreadMake(nap, usr_entry, usr_stack_ptr, |
| 225 user_tls1, user_tls2); |
| 226 if (natp == NULL) { |
| 227 return 0; |
| 228 } |
| 229 /* |
| 230 * We set host_thread_is_defined assuming, for now, that |
| 231 * NaClThreadCtor() will succeed. |
| 232 */ |
| 233 natp->host_thread_is_defined = 1; |
| 234 if (!NaClThreadCtor(&natp->host_thread, NaClAppThreadLauncher, (void *) natp, |
| 235 NACL_KERN_STACK_SIZE)) { |
| 236 /* |
| 237 * No other thread saw the NaClAppThread, so it is OK that |
| 238 * host_thread was not initialized despite host_thread_is_defined |
| 239 * being set. |
| 240 */ |
| 241 natp->host_thread_is_defined = 0; |
| 242 NaClAppThreadDelete(natp); |
| 243 return 0; |
| 244 } |
| 245 return 1; |
| 246 } |
| 247 |
| 248 |
223 void NaClAppThreadDelete(struct NaClAppThread *natp) { | 249 void NaClAppThreadDelete(struct NaClAppThread *natp) { |
224 /* | 250 /* |
225 * the thread must not be still running, else this crashes the system | 251 * the thread must not be still running, else this crashes the system |
226 */ | 252 */ |
227 | 253 |
| 254 if (natp->host_thread_is_defined) { |
| 255 NaClThreadDtor(&natp->host_thread); |
| 256 } |
228 free(natp->suspended_registers); | 257 free(natp->suspended_registers); |
229 NaClMutexDtor(&natp->suspend_mu); | 258 NaClMutexDtor(&natp->suspend_mu); |
230 NaClThreadDtor(&natp->thread); | |
231 NaClSignalStackFree(natp->signal_stack); | 259 NaClSignalStackFree(natp->signal_stack); |
232 natp->signal_stack = NULL; | 260 natp->signal_stack = NULL; |
233 NaClTlsFree(natp); | 261 NaClTlsFree(natp); |
234 NaClMutexDtor(&natp->mu); | 262 NaClMutexDtor(&natp->mu); |
235 NaClAlignedFree(natp); | 263 NaClAlignedFree(natp); |
236 } | 264 } |
OLD | NEW |