/* * Initializes the thread subsystem, creating various worker threads. * * nthreads Number of event handler threads to spawn * main_base Event base for main thread */ void thread_init(int nthreads, struct event_base *main_base) { int i; #ifdef WIN32 struct sockaddr_in serv_addr; int sockfd; if ((sockfd = createLocalListSock(&serv_addr)) < 0) exit(1); #endif pthread_mutex_init(&cache_lock, NULL); pthread_mutex_init(&stats_lock, NULL); pthread_mutex_init(&init_lock, NULL); pthread_cond_init(&init_cond, NULL); pthread_mutex_init(&cqi_freelist_lock, NULL); cqi_freelist = NULL; threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (! threads) { perror("Can't allocate thread descriptors"); exit(1); } threads[0].base = main_base; threads[0].thread_id = pthread_self(); for (i = 0; i < nthreads; i++) { int fds[2]; #ifdef WIN32 if (createLocalSocketPair(sockfd,fds,&serv_addr) == -1) { fprintf(stderr, "Can't create notify pipe: %s", strerror(errno)); exit(1); } #else if (pipe(fds)) { perror("Can't create notify pipe"); exit(1); } #endif threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; setup_thread(&threads[i]); #ifdef WIN32 if (i == (nthreads - 1)) { shutdown(sockfd, 2); } #endif } /* Create threads after we've done all the libevent setup. */ for (i = 1; i < nthreads; i++) { create_worker(worker_libevent, &threads[i]); } /* Wait for all the threads to set themselves up before returning. */ pthread_mutex_lock(&init_lock); init_count++; /* main thread */ while (init_count < nthreads) { pthread_cond_wait(&init_cond, &init_lock); } pthread_mutex_unlock(&init_lock); }
/** A work queue is a mechanism to allow thread-to-thread * communication in a libevent-based, multithreaded system. * * One thread can send work to another thread. The receiving thread * should be libevent-based, with a processing loop handled by * libevent. * * Use work_queue_init() to initialize a work_queue structure, * where the work_queue structure memory is owned by the caller. * * Returns true on success. */ bool work_queue_init(work_queue *m, struct event_base *event_base) { assert(m != NULL); memset(m, 0, sizeof(work_queue)); pthread_mutex_init(&m->work_lock, NULL); m->work_head = NULL; m->work_tail = NULL; m->num_items = 0; m->tot_sends = 0; m->tot_recvs = 0; m->event_base = event_base; assert(m->event_base != NULL); int fds[2] = {0}; #ifdef WIN32 struct sockaddr_in serv_addr; int sockfd; if ((sockfd = createLocalListSock(&serv_addr)) < 0 || createLocalSocketPair(sockfd,fds,&serv_addr) == -1) { fprintf(stderr, "Can't create notify pipe: %s", strerror(errno)); return false; } #else if (pipe(fds)) { perror("Can't create notify pipe"); return false; } #endif m->recv_fd = fds[0]; m->send_fd = fds[1]; event_set(&m->event, m->recv_fd, EV_READ | EV_PERSIST, work_recv, m); event_base_set(m->event_base, &m->event); if (event_add(&m->event, 0) == 0) { #ifdef WORK_DEBUG moxi_log_write("work_queue_init %x %x %x %d %d %u %llu\n", (int) pthread_self(), (int) m, (int) m->event_base, m->send_fd, m->recv_fd, m->work_head != NULL, m->tot_sends); #endif return true; } #ifdef WORK_DEBUG moxi_log_write("work_queue_init error\n"); #endif return false; }
/* * 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) { int i; nthreads = nthr; #ifdef __WIN32__ struct sockaddr_in serv_addr; int sockfd; if ((sockfd = createLocalListSock(&serv_addr)) < 0) exit(1); #endif pthread_mutex_init(&stats_lock, NULL); pthread_mutex_init(&setting_lock, NULL); pthread_mutex_init(&init_lock, NULL); pthread_cond_init(&init_cond, NULL); pthread_mutex_init(&cqi_freelist_lock, NULL); cqi_freelist = NULL; threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (! threads) { mc_logger->log(EXTENSION_LOG_WARNING, NULL, "Can't allocate thread descriptors: %s", strerror(errno)); exit(1); } thread_ids = calloc(nthreads, sizeof(pthread_t)); if (! thread_ids) { perror("Can't allocate thread descriptors"); exit(1); } dispatcher_thread.base = main_base; dispatcher_thread.thread_id = pthread_self(); int fds[2]; for (i = 0; i < nthreads; i++) { #ifdef __WIN32__ if (createLocalSocketPair(sockfd,fds,&serv_addr) == -1) { mc_logger->log(EXTENSION_LOG_WARNING, NULL, "Can't create notify pipe: %s", strerror(errno)); exit(1); } #else if (pipe(fds)) { mc_logger->log(EXTENSION_LOG_WARNING, NULL, "Can't create notify pipe: %s", strerror(errno)); exit(1); } #endif threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; threads[i].index = i; setup_thread(&threads[i]); #ifdef __WIN32__ if (i == (nthreads - 1)) { shutdown(sockfd, 2); } #endif } /* 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. */ pthread_mutex_lock(&init_lock); while (init_count < nthreads) { pthread_cond_wait(&init_cond, &init_lock); } pthread_mutex_unlock(&init_lock); }