int NaClAppThreadAllocSegCtor(struct NaClAppThread *natp, struct NaClApp *nap, int is_privileged, uintptr_t usr_entry, uintptr_t usr_stack_ptr, uintptr_t sys_tdb_base, size_t tdb_size) { uint32_t tls_idx; uint32_t tdb_size32; if (tdb_size > UINT32_MAX) { NaClLog(LOG_ERROR, "Requested TDB size is too large"); return 0; } else { tdb_size32 = (uint32_t) tdb_size; } /* * Even though we don't know what segment base/range should gs/r9/nacl_tls_idx * select, we still need one, since it identifies the thread when we context * switch back. This use of a dummy tls is only needed for the main thread, * which is expected to invoke the tls_init syscall from its crt code (before * main or much of libc can run). Other threads are spawned with the tdb * address and size as a parameter. */ tls_idx = NaClTlsAllocate(natp, (void *) sys_tdb_base, tdb_size32); NaClLog(4, "NaClAppThreadAllocSegCtor: stack_ptr 0x%08"NACL_PRIxPTR", " "tls_idx 0x%02"NACL_PRIx32"\n", usr_stack_ptr, tls_idx); if (0 == tls_idx) { NaClLog(LOG_ERROR, "No tls for thread, num_thread %d\n", nap->num_threads); return 0; } return NaClAppThreadCtor(natp, nap, is_privileged, usr_entry, usr_stack_ptr, tls_idx, sys_tdb_base); }
struct NaClAppThread *NaClAppThreadMake(struct NaClApp *nap, uintptr_t usr_entry, uintptr_t usr_stack_ptr, uint32_t user_tls1, uint32_t user_tls2) { struct NaClAppThread *natp; uint32_t tls_idx; natp = NaClAlignedMalloc(sizeof *natp, __alignof(struct NaClAppThread)); if (natp == NULL) { return NULL; } NaClLog(4, " natp = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) natp); NaClLog(4, " nap = 0x%016"NACL_PRIxPTR"\n", (uintptr_t) nap); NaClLog(4, "usr_stack_ptr = 0x%016"NACL_PRIxPTR"\n", usr_stack_ptr); /* * Set these early, in case NaClTlsAllocate() wants to examine them. */ natp->nap = nap; natp->thread_num = -1; /* illegal index */ natp->host_thread_is_defined = 0; memset(&natp->host_thread, 0, sizeof(natp->host_thread)); /* * Even though we don't know what segment base/range should gs/r9/nacl_tls_idx * select, we still need one, since it identifies the thread when we context * switch back. This use of a dummy tls is only needed for the main thread, * which is expected to invoke the tls_init syscall from its crt code (before * main or much of libc can run). Other threads are spawned with the thread * pointer address as a parameter. */ tls_idx = NaClTlsAllocate(natp); if (NACL_TLS_INDEX_INVALID == tls_idx) { NaClLog(LOG_ERROR, "No tls for thread, num_thread %d\n", nap->num_threads); goto cleanup_free; } NaClThreadContextCtor(&natp->user, nap, usr_entry, usr_stack_ptr, tls_idx); NaClTlsSetTlsValue1(natp, user_tls1); NaClTlsSetTlsValue2(natp, user_tls2); natp->signal_stack = NULL; natp->exception_stack = 0; natp->exception_flag = 0; if (!NaClMutexCtor(&natp->mu)) { goto cleanup_free; } if (!NaClSignalStackAllocate(&natp->signal_stack)) { goto cleanup_mu; } if (!NaClMutexCtor(&natp->suspend_mu)) { goto cleanup_mu; } natp->suspend_state = NACL_APP_THREAD_TRUSTED; natp->suspended_registers = NULL; natp->fault_signal = 0; natp->dynamic_delete_generation = 0; return natp; cleanup_mu: NaClMutexDtor(&natp->mu); if (NULL != natp->signal_stack) { NaClSignalStackFree(&natp->signal_stack); natp->signal_stack = NULL; } cleanup_free: NaClAlignedFree(natp); return NULL; }