int work_collect_wait(work_collect *c) { int rv = 0; cb_mutex_enter(&c->collect_lock); while (c->count != 0 && rv == 0) { /* Can't test for > 0, due to -1 on init race. */ cb_cond_wait(&c->collect_cond, &c->collect_lock); } cb_mutex_exit(&c->collect_lock); return rv; }
/* * Initializes the thread subsystem, creating various worker threads. * * nthreads Number of worker event handler threads to spawn * main_base Event base for main thread */ void thread_init(int nthr, struct event_base *main_base, void (*dispatcher_callback)(evutil_socket_t, short, void *)) { int i; nthreads = nthr + 1; cqi_freelist = NULL; cb_mutex_initialize(&conn_lock); cb_mutex_initialize(&cqi_freelist_lock); cb_mutex_initialize(&init_lock); cb_cond_initialize(&init_cond); threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (! threads) { settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL, "Can't allocate thread descriptors: %s", strerror(errno)); exit(1); } thread_ids = calloc(nthreads, sizeof(cb_thread_t)); if (! thread_ids) { settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL, "Can't allocate thread descriptors: %s", strerror(errno)); exit(1); } setup_dispatcher(main_base, dispatcher_callback); for (i = 0; i < nthreads; i++) { if (!create_notification_pipe(&threads[i])) { exit(1); } threads[i].index = i; setup_thread(&threads[i]); } /* Create threads after we've done all the libevent setup. */ for (i = 0; i < nthreads; i++) { create_worker(worker_libevent, &threads[i], &thread_ids[i]); threads[i].thread_id = thread_ids[i]; } /* Wait for all the threads to set themselves up before returning. */ cb_mutex_enter(&init_lock); while (init_count < nthreads) { cb_cond_wait(&init_cond, &init_lock); } cb_mutex_exit(&init_lock); }
static void assoc_maintenance_thread(void *arg) { (void)arg; while (do_run_maintenance_thread) { int ii = 0; /* Lock the cache, and bulk move multiple buckets to the new * hash table. */ cb_mutex_enter(&cache_lock); for (ii = 0; ii < hash_bulk_move && expanding; ++ii) { item *it, *next; int bucket; for (it = old_hashtable[expand_bucket]; NULL != it; it = next) { next = it->h_next; bucket = hash(ITEM_key(it), it->nkey, 0) & hashmask(hashpower); it->h_next = primary_hashtable[bucket]; primary_hashtable[bucket] = it; } old_hashtable[expand_bucket] = NULL; expand_bucket++; if (expand_bucket == hashsize(hashpower - 1)) { expanding = false; free(old_hashtable); if (settings.verbose > 1) moxi_log_write("Hash table expansion done\n"); } } if (!expanding) { /* We are done expanding.. just wait for next invocation */ cb_cond_wait(&maintenance_cond, &cache_lock); } cb_mutex_exit(&cache_lock); } }