int NaClAppThreadSpawn(struct NaClApp *nap, uintptr_t usr_entry, uintptr_t usr_stack_ptr, uint32_t user_tls1, uint32_t user_tls2) { struct NaClAppThread *natp = NaClAppThreadMake(nap, usr_entry, usr_stack_ptr, user_tls1, user_tls2); if (natp == NULL) { return 0; } /* * We set host_thread_is_defined assuming, for now, that * NaClThreadCtor() will succeed. */ natp->host_thread_is_defined = 1; if (!NaClThreadCtor(&natp->host_thread, NaClAppThreadLauncher, (void *) natp, NACL_KERN_STACK_SIZE)) { /* * No other thread saw the NaClAppThread, so it is OK that * host_thread was not initialized despite host_thread_is_defined * being set. */ natp->host_thread_is_defined = 0; NaClAppThreadDelete(natp); return 0; } return 1; }
struct AlarmerState *SpawnAlarmer(uint64_t timeout_usec, uint64_t cond_timeout_usec) { struct AlarmerState *sp = (struct AlarmerState *) malloc(sizeof *sp); if (NULL == sp) return sp; AlarmerStateCtor(sp, timeout_usec, cond_timeout_usec); if (!NaClThreadCtor(&sp->thr, Alarmer, (void *) sp, 4096)) { AlarmerStateDtor(sp); free(sp); return 0; } return sp; }
int main(int ac, char **av) { int exit_status = -1; int opt; size_t num_threads = 16; size_t n; struct NaClThread thr; while (EOF != (opt = getopt(ac, av, "n:s:t:"))) { switch (opt) { case 'n': num_threads = strtoul(optarg, (char **) NULL, 0); break; case 't': gNumTriesSufficient = strtoul(optarg, (char **) NULL, 0); break; default: fprintf(stderr, "Usage: nacl_semaphore_test [args]\n" " -n n number of threads used to test semaphore\n" " -t n number of TryWait operations before blocking Try\n"); goto cleanup0; } } NaClPlatformInit(); if (!NaClSemCtor(&gSem, 0)) { fprintf(stderr, "nacl_semaphore_test: NaClSemCtor failed!\n"); goto cleanup1; } if (!NaClMutexCtor(&gMu)) { fprintf(stderr, "nacl_semaphore_test: NaClMutexCtor failed!\n"); goto cleanup2; } if (!NaClCondVarCtor(&gCv)) { fprintf(stderr, "nacl_semaphore_test: NaClCondVarCtor failed!\n"); goto cleanup3; } for (n = 0; n < num_threads; ++n) { if (!NaClThreadCtor(&thr, ThreadMain, (void *) (uintptr_t) n, STACK_SIZE_BYTES)) { fprintf(stderr, "nacl_semaphore_test: could not create thread %"NACL_PRIdS"\n", n); goto cleanup4; /* osx leak semaphore otherwise */ } } NaClMutexLock(&gMu); while (gNumThreadsTried != num_threads) { NaClCondVarWait(&gCv, &gMu); } NaClMutexUnlock(&gMu); for (n = 0; n < num_threads; ++n) { NaClSemPost(&gSem); /* let a thread go */ } NaClMutexLock(&gMu); while (gNumThreadsDone != num_threads) { NaClCondVarWait(&gCv, &gMu); } exit_status = gFailure; NaClMutexUnlock(&gMu); if (0 == exit_status) { printf("SUCCESS\n"); } cleanup4: /* single exit with (ah hem) simulation of RAII via cleanup sled */ NaClCondVarDtor(&gCv); cleanup3: NaClMutexDtor(&gMu); cleanup2: NaClSemDtor(&gSem); cleanup1: NaClPlatformFini(); cleanup0: return exit_status; }
int NaClThreadCreateJoinable(struct NaClThread *ntp, void (WINAPI *start_fn)(void *), void *state, size_t stack_size) { return NaClThreadCtor(ntp, start_fn, state, stack_size); }
int NaClAppThreadCtor(struct NaClAppThread *natp, struct NaClApp *nap, int is_privileged, uintptr_t usr_entry, uintptr_t usr_stack_ptr, uint32_t tls_idx, uintptr_t sys_tdb) { int rv; uint64_t thread_idx; struct NaClDescEffectorLdr *effp; 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); NaClThreadContextCtor(&natp->user, nap, usr_entry, usr_stack_ptr, tls_idx); effp = NULL; natp->signal_stack = NULL; if (!NaClMutexCtor(&natp->mu)) { return 0; } if (!NaClCondVarCtor(&natp->cv)) { goto cleanup_mutex; } natp->is_privileged = is_privileged; if (!NaClClosureResultCtor(&natp->result)) { goto cleanup_cv; } natp->sysret = 0; natp->nap = nap; effp = (struct NaClDescEffectorLdr *) malloc(sizeof *effp); if (NULL == effp) { goto cleanup_cv; } if (!NaClDescEffectorLdrCtor(effp, natp)) { goto cleanup_cv; } natp->effp = (struct NaClDescEffector *) effp; effp = NULL; if (!NaClSignalStackAllocate(&natp->signal_stack)) { goto cleanup_cv; } natp->holding_sr_locks = 0; natp->state = NACL_APP_THREAD_ALIVE; natp->thread_num = -1; /* illegal index */ natp->sys_tdb = sys_tdb; natp->dynamic_delete_generation = 0; thread_idx = NaClGetThreadIdx(natp); nacl_thread[thread_idx] = natp; nacl_user[thread_idx] = &natp->user; nacl_sys[thread_idx] = &natp->sys; rv = NaClThreadCtor(&natp->thread, NaClThreadLauncher, (void *) natp, NACL_KERN_STACK_SIZE); if (rv != 0) { return rv; /* Success */ } NaClClosureResultDtor(&natp->result); cleanup_cv: NaClCondVarDtor(&natp->cv); cleanup_mutex: NaClMutexDtor(&natp->mu); free(effp); natp->effp = NULL; if (NULL != natp->signal_stack) { NaClSignalStackFree(&natp->signal_stack); natp->signal_stack = NULL; } return 0; }