void NaClUntrustedThreadsResumeAll(struct NaClApp *nap) { size_t index; for (index = 0; index < nap->threads.num_entries; index++) { struct NaClAppThread *natp = NaClGetThreadMu(nap, (int) index); if (natp != NULL) { NaClUntrustedThreadResume(natp); } } NaClXMutexUnlock(&nap->threads_mu); }
/* This must be called with the mutex nap->threads_mu held. */ struct NaClAppThread *GetOnlyThread(struct NaClApp *nap) { struct NaClAppThread *found_thread = NULL; size_t index; for (index = 0; index < nap->threads.num_entries; index++) { struct NaClAppThread *natp = NaClGetThreadMu(nap, (int) index); if (natp != NULL) { CHECK(found_thread == NULL); found_thread = natp; } } CHECK(found_thread != NULL); return found_thread; }
int NaClMinimumThreadGeneration(struct NaClApp *nap) { size_t index; int rv = INT_MAX; NaClXMutexLock(&nap->threads_mu); for (index = 0; index < nap->threads.num_entries; ++index) { struct NaClAppThread *thread = NaClGetThreadMu(nap, (int) index); if (thread != NULL) { NaClXMutexLock(&thread->mu); if (rv > thread->dynamic_delete_generation) { rv = thread->dynamic_delete_generation; } NaClXMutexUnlock(&thread->mu); } } NaClXMutexUnlock(&nap->threads_mu); return rv; }
void NaClUntrustedThreadsSuspendAll(struct NaClApp *nap, int save_registers) { size_t index; NaClXMutexLock(&nap->threads_mu); /* * TODO(mseaborn): A possible refinement here would be to use separate loops * for initiating and waiting for the suspension of the threads. This might * be faster, since we would not be waiting for each thread to suspend one by * one. It would take advantage of the asynchronous nature of thread * suspension. */ for (index = 0; index < nap->threads.num_entries; index++) { struct NaClAppThread *natp = NaClGetThreadMu(nap, (int) index); if (natp != NULL) { NaClUntrustedThreadSuspend(natp, save_registers); } } }