| 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 |