void func () { int a; a = _Cilk_spawn _Cilk_spawn spawn_func (4); a = _Cilk_spawn _Cilk_spawn _Cilk_spawn spawn_func (4); a = _Cilk_spawn _Cilk_spawn _Cilk_spawn _Cilk_spawn spawn_func (4); return; }
static void test_threads_conditionvar(void *arg) { cv_testinfo_t *ti=NULL; const struct timeval msec100 = { 0, 100*1000 }; const int timeout = !strcmp(arg, "tv"); ti = cv_testinfo_new(); if (timeout) { ti->tv = &msec100; } spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); tor_mutex_acquire(ti->mutex); ti->addend = 7; ti->shutdown = 1; tor_cond_signal_one(ti->cond); tor_mutex_release(ti->mutex); #define SPIN() \ while (1) { \ tor_mutex_acquire(ti->mutex); \ if (ti->addend == 0) { \ break; \ } \ tor_mutex_release(ti->mutex); \ } SPIN(); ti->addend = 30; ti->shutdown = 1; tor_cond_signal_all(ti->cond); tor_mutex_release(ti->mutex); SPIN(); ti->addend = 1000; if (! timeout) ti->shutdown = 1; tor_cond_signal_one(ti->cond); tor_mutex_release(ti->mutex); SPIN(); ti->addend = 300; if (! timeout) ti->shutdown = 1; tor_cond_signal_all(ti->cond); tor_mutex_release(ti->mutex); SPIN(); tor_mutex_release(ti->mutex); tt_int_op(ti->value, ==, 1337); if (!timeout) { tt_int_op(ti->n_shutdown, ==, 4); } else {
/** Launch a new cpuworker. Return 0 if we're happy, -1 if we failed. */ static int spawn_cpuworker(void) { tor_socket_t *fdarray; tor_socket_t fd; connection_t *conn; int err; fdarray = tor_malloc(sizeof(tor_socket_t)*2); if ((err = tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fdarray)) < 0) { log_warn(LD_NET, "Couldn't construct socketpair for cpuworker: %s", tor_socket_strerror(-err)); tor_free(fdarray); return -1; } tor_assert(SOCKET_OK(fdarray[0])); tor_assert(SOCKET_OK(fdarray[1])); fd = fdarray[0]; if (spawn_func(cpuworker_main, (void*)fdarray) < 0) { tor_close_socket(fdarray[0]); tor_close_socket(fdarray[1]); tor_free(fdarray); return -1; } log_debug(LD_OR,"just spawned a cpu worker."); #ifndef TOR_IS_MULTITHREADED tor_close_socket(fdarray[1]); /* don't need the worker's side of the pipe */ tor_free(fdarray); #endif conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX); /* set up conn so it's got all the data we need to remember */ conn->s = fd; conn->address = tor_strdup("localhost"); tor_addr_make_unspec(&conn->addr); if (set_socket_nonblocking(fd) == -1) { connection_free(conn); /* this closes fd */ return -1; } if (connection_add(conn) < 0) { /* no space, forget it */ log_warn(LD_NET,"connection_add for cpuworker failed. Giving up."); connection_free(conn); /* this closes fd */ return -1; } conn->state = CPUWORKER_STATE_IDLE; connection_start_reading(conn); return 0; /* success */ }
/** Allocate and start a new worker thread to use state object <b>state</b>, * and send responses to <b>replyqueue</b>. */ static workerthread_t * workerthread_new(void *state, threadpool_t *pool, replyqueue_t *replyqueue) { workerthread_t *thr = tor_malloc_zero(sizeof(workerthread_t)); thr->state = state; thr->reply_queue = replyqueue; thr->in_pool = pool; if (spawn_func(worker_thread_main, thr) < 0) { log_err(LD_GENERAL, "Can't launch worker thread."); return NULL; } return thr; }
/** Allocate and start a new worker thread to use state object <b>state</b>, * and send responses to <b>replyqueue</b>. */ static workerthread_t * workerthread_new(void *state, threadpool_t *pool, replyqueue_t *replyqueue) { workerthread_t *thr = tor_malloc_zero(sizeof(workerthread_t)); thr->state = state; thr->reply_queue = replyqueue; thr->in_pool = pool; if (spawn_func(worker_thread_main, thr) < 0) { //LCOV_EXCL_START tor_assert_nonfatal_unreached(); log_err(LD_GENERAL, "Can't launch worker thread."); tor_free(thr); return NULL; //LCOV_EXCL_STOP } return thr; }
/** Run unit tests for threading logic. */ static void test_threads_basic(void *arg) { char *s1 = NULL, *s2 = NULL; int done = 0, timedout = 0; time_t started; #ifndef _WIN32 struct timeval tv; tv.tv_sec=0; tv.tv_usec=100*1000; #endif (void) arg; set_main_thread(); thread_test_mutex_ = tor_mutex_new(); thread_test_start1_ = tor_mutex_new(); thread_test_start2_ = tor_mutex_new(); thread_test_strmap_ = strmap_new(); s1 = tor_strdup("thread 1"); s2 = tor_strdup("thread 2"); tor_mutex_acquire(thread_test_start1_); tor_mutex_acquire(thread_test_start2_); spawn_func(thread_test_func_, s1); spawn_func(thread_test_func_, s2); tor_mutex_release(thread_test_start2_); tor_mutex_release(thread_test_start1_); started = time(NULL); while (!done) { tor_mutex_acquire(thread_test_mutex_); strmap_assert_ok(thread_test_strmap_); if (strmap_get(thread_test_strmap_, "thread 1") && strmap_get(thread_test_strmap_, "thread 2")) { done = 1; } else if (time(NULL) > started + 150) { timedout = done = 1; } tor_mutex_release(thread_test_mutex_); #ifndef _WIN32 /* Prevent the main thread from starving the worker threads. */ select(0, NULL, NULL, NULL, &tv); #endif } tor_mutex_acquire(thread_test_start1_); tor_mutex_release(thread_test_start1_); tor_mutex_acquire(thread_test_start2_); tor_mutex_release(thread_test_start2_); tor_mutex_free(thread_test_mutex_); if (timedout) { printf("\nTimed out: %d %d", t1_count, t2_count); tt_assert(strmap_get(thread_test_strmap_, "thread 1")); tt_assert(strmap_get(thread_test_strmap_, "thread 2")); tt_assert(!timedout); } /* different thread IDs. */ tt_assert(strcmp(strmap_get(thread_test_strmap_, "thread 1"), strmap_get(thread_test_strmap_, "thread 2"))); tt_assert(!strcmp(strmap_get(thread_test_strmap_, "thread 1"), strmap_get(thread_test_strmap_, "last to run")) || !strcmp(strmap_get(thread_test_strmap_, "thread 2"), strmap_get(thread_test_strmap_, "last to run"))); tt_int_op(thread_fns_failed, ==, 0); tt_int_op(thread_fn_tid1, !=, thread_fn_tid2); done: tor_free(s1); tor_free(s2); tor_free(thread1_name_); tor_free(thread2_name_); if (thread_test_strmap_) strmap_free(thread_test_strmap_, NULL); if (thread_test_start1_) tor_mutex_free(thread_test_start1_); if (thread_test_start2_) tor_mutex_free(thread_test_start2_); }