int NaClIntrMutexCtor(struct NaClIntrMutex *mp) { if (!NaClMutexCtor(&mp->mu)) { return 0; } if (!NaClCondVarCtor(&mp->cv)) { NaClMutexDtor(&mp->mu); return 0; } mp->lock_state = NACL_INTR_LOCK_FREE; return 1; }
int NaClReverseServiceCtor(struct NaClReverseService *self, struct NaClReverseInterface *iface, struct NaClDesc *conn_cap) { int retval = 0; /* fail */ CHECK(iface != NULL); NaClLog(4, "Entered NaClReverseServiceCtor\n"); if (!NaClSimpleRevServiceCtor(&self->base, conn_cap, kNaClReverseServiceHandlers, NaClReverseThreadIfFactoryFn, (void *) self)) { NaClLog(4, "NaClReverseServiceCtor: NaClSimpleRevServiceCtor failed\n"); goto done; } NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl *) &kNaClReverseServiceVtbl; if (!NaClMutexCtor(&self->mu)) { NaClLog(4, "NaClMutexCtor failed\n"); goto mutex_ctor_fail; } if (!NaClCondVarCtor(&self->cv)) { NaClLog(4, "NaClCondVar failed\n"); goto condvar_ctor_fail; } /* success return path */ self->iface = (struct NaClReverseInterface *) NaClRefCountRef( (struct NaClRefCount *) iface); self->thread_count = 0; retval = 1; goto done; /* cleanup unwind */ condvar_ctor_fail: NaClMutexDtor(&self->mu); mutex_ctor_fail: (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self); done: return retval; }
int NaClSimpleLtdServiceCtor( struct NaClSimpleLtdService *self, struct NaClSrpcHandlerDesc const *srpc_handlers, int max_cli, NaClThreadIfFactoryFunction thread_factory_fn, void *thread_factory_data) { NaClLog(4, "Entered NaClSimpleLtdServiceCtor\n"); if (!NaClSimpleServiceCtor((struct NaClSimpleService *) self, srpc_handlers, thread_factory_fn, thread_factory_data)) { NaClLog(4, "NaClSimpleServiceCtor failed\n"); goto base_ctor_fail; } if (!NaClMutexCtor(&self->mu)) { NaClLog(4, "NaClSimpleLtdServiceCtor: NaClMutexCtor failed\n"); goto mutex_ctor_fail; } if (!NaClCondVarCtor(&self->cv)) { NaClLog(4, "NaClSimpleLtdServiceCtor: NaClCondVarCtor failed\n"); goto condvar_ctor_fail; } self->max_clients = max_cli; self->num_clients = 0; NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl *) &kNaClSimpleLtdServiceVtbl; NaClLog(4, "NaClSimpleLtdServiceCtor: success\n"); return 1; /* failure cascade, in reverse construction order */ condvar_ctor_fail: NaClMutexDtor(&self->mu); mutex_ctor_fail: (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self); base_ctor_fail: return 0; }
/* Based on NaClAppThreadCtor() */ static void InitThread(struct NaClApp *nap, struct NaClAppThread *natp) { struct NaClDescEffectorLdr *effp; memset(natp, 0xff, sizeof(*natp)); natp->nap = nap; if (!NaClMutexCtor(&natp->mu)) { ASSERT(0); } if (!NaClCondVarCtor(&natp->cv)) { ASSERT(0); } natp->is_privileged = 0; effp = (struct NaClDescEffectorLdr *) malloc(sizeof *effp); ASSERT_NE(effp, NULL); if (!NaClDescEffectorLdrCtor(effp, natp)) { ASSERT(0); } natp->effp = (struct NaClDescEffector *) effp; }
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; }
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; 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)); if (!NaClAppThreadInitArchSpecific(natp, usr_entry, usr_stack_ptr)) { goto cleanup_free; } 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; if (!NaClCondVarCtor(&natp->futex_condvar)) { goto cleanup_suspend_mu; } return natp; cleanup_suspend_mu: NaClMutexDtor(&natp->suspend_mu); cleanup_mu: NaClMutexDtor(&natp->mu); if (NULL != natp->signal_stack) { NaClSignalStackFree(&natp->signal_stack); natp->signal_stack = NULL; } cleanup_free: NaClAlignedFree(natp); return NULL; }
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; }