/* * 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 nthreads, struct event_base *main_base) { int i; 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); } dispatcher_thread.base = main_base; dispatcher_thread.thread_id = pthread_self(); for (i = 0; i < nthreads; i++) { int fds[2]; if (pipe(fds)) { perror("Can't create notify pipe"); exit(1); } threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; 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]); } /* 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); }
/* * 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)(int, short, void *)) { int i; nthreads = nthr + 1; cqi_freelist = NULL; 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(pthread_t)); if (! thread_ids) { perror("Can't allocate thread descriptors"); 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. */ pthread_mutex_lock(&init_lock); while (init_count < nthreads) { pthread_cond_wait(&init_cond, &init_lock); } pthread_mutex_unlock(&init_lock); }
void thread_init(struct event_base *main_base, int nthreads, pthread_t *th) { int i; pthread_mutex_init(&init_lock, NULL); pthread_cond_init(&init_cond, NULL); pthread_mutex_init(&cqi_freelist_lock, NULL); cqi_freelist = NULL; dispatcher_thread.base = main_base; dispatcher_thread.thread_id = pthread_self(); threads = (LIBEVENT_THREAD *)calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (NULL == threads) { mfatal("allocate threads failed!"); exit(1); } for (i = 0; i < nthreads; i++) { int fds[2]; if (pipe(fds)) { mfatal("can't create notify pipe!"); exit(1); } threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; setup_thread(&threads[i]); } for (i = 0; i < nthreads; i++) { create_worker(worker_libevent, &threads[i], th + i); } pthread_mutex_lock(&init_lock); wait_for_thread_registration(nthreads); pthread_mutex_unlock(&init_lock); num_threads = nthreads; }
int thread_init(int num_of_threads){ int i; pthread_mutex_init(&init_lock, NULL); pthread_cond_init(&init_cond, NULL); pthread_mutex_init(&cqi_freelist_lock, NULL); cqi_freelist = NULL; thread_cgs = calloc(num_of_threads, sizeof(thread_cg)); if(!thread_cgs){ perror("can't alloc thread_cg"); exit(1); } dispatcher_thread.base = main_base; dispatcher_thread.thread_id = pthread_self(); for(i = 0; i < num_of_threads; i++){ int fds[2]; if(pipe(fds)){ perror("can't create notify pipe"); exit(1); } thread_cgs[i].read_fd = fds[0]; thread_cgs[i].write_fd = fds[1]; setup_thread(&thread_cgs[i]); } //未完成,需要等待现成完成setup,然后才退出函数 for(i = 0; i < num_of_threads; i++){ start_worker(worker_libevent, &thread_cgs[i]); } pthread_mutex_lock(&init_lock); while (init_count < NUM_OF_THREADS) { pthread_cond_wait(&init_cond, &init_lock); } pthread_mutex_unlock(&init_lock); }
void work_thread_init(int nthreads){ int i; work_threads = (LIBEVENT_WORK_THREAD *)calloc(nthreads, sizeof(LIBEVENT_WORK_THREAD)); if(!work_threads){ DEBUG("work_threads create error"); exit(1); } wtq_queue_tail = wtq_queue_head = NULL; pthread_mutex_init(&init_work_lock, NULL); pthread_cond_init(&init_work_cond, NULL); for(i=0; i< nthreads; i++){ int fds[2]; if(pipe(fds)){ } work_threads[i].notify_read_fd = fds[0]; work_threads[i].notify_write_fd = fds[1]; work_threads[i].no = i; work_threads[i].tdbp = initdbp(); setup_thread(&work_threads[i]); } for(i=0; i<nthreads; i++){ create_worker(worker_libevent, &work_threads[i]); } pthread_mutex_lock(&init_work_lock); while (init_count < nthreads) { pthread_cond_wait(&init_work_cond, &init_work_lock); } wtq_queue_head->next = wtq_queue_tail; pthread_mutex_unlock(&init_work_lock); }
void thread_init() { int nthreads = 4; pthread_mutex_init(&init_lock, NULL); pthread_cond_init(&init_cond, NULL); work_threads = calloc(nthreads, sizeof(WORK_THREAD)); if (! work_threads) { perror("Can't allocate thread descriptors\n"); exit(1); } //dispatcher_thread.loop = EV_DEFAULT_UC; //dispatcher_thread.thread_id = pthread_self(); dispatcher_thread.loop = ev_default_loop(0); dispatcher_thread.thread_id = pthread_self(); int i = 0; for (i = 0; i < nthreads; i++) { setup_thread(&work_threads[i]); } /* Create threads after we've done all the libevent setup. */ for (i = 0; i < nthreads; i++) { create_worker(worker_libev, &work_threads[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); }
/* * 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 nthreads, struct event_base *main_base) { int i; int power; 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; /* Want a wide lock table, but don't waste memory */ if (nthreads < 3) { power = 10; } else if (nthreads < 4) { power = 11; } else if (nthreads < 5) { power = 12; } else { /* 8192 buckets, and central locks don't scale much past 5 threads */ power = 13; } item_lock_count = ((unsigned long int)1 << (power)); item_lock_mask = item_lock_count - 1; item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t)); if (! item_locks) { perror("Can't allocate item locks"); exit(1); } for (i = 0; i < item_lock_count; i++) { pthread_mutex_init(&item_locks[i], NULL); } // added by Bin since libevent is not used for cache bench if (main_base == NULL) { //printf("as you know we are not using libevent\n"); return; } threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (! threads) { perror("Can't allocate thread descriptors"); exit(1); } dispatcher_thread.base = main_base; dispatcher_thread.thread_id = pthread_self(); for (i = 0; i < nthreads; i++) { int fds[2]; if (pipe(fds)) { perror("Can't create notify pipe"); exit(1); } threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; setup_thread(&threads[i]); /* Reserve three fds for the libevent base, and two for the pipe */ stats.reserved_fds += 5; } /* Create threads after we've done all the libevent setup. */ for (i = 0; i < nthreads; i++) { create_worker(worker_libevent, &threads[i], 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); }
/* * Initializes the thread subsystem, creating various worker threads. * * nthreads Number of worker event handler threads to spawn */ void memcached_thread_init(int nthreads, void *arg) { int i; int power; for (i = 0; i < POWER_LARGEST; i++) { pthread_mutex_init(&lru_locks[i], NULL); } pthread_mutex_init(&worker_hang_lock, NULL); pthread_mutex_init(&init_lock, NULL); pthread_cond_init(&init_cond, NULL); pthread_mutex_init(&cqi_freelist_lock, NULL); cqi_freelist = NULL; /* Want a wide lock table, but don't waste memory */ if (nthreads < 3) { power = 10; } else if (nthreads < 4) { power = 11; } else if (nthreads < 5) { power = 12; } else if (nthreads <= 10) { power = 13; } else if (nthreads <= 20) { power = 14; } else { /* 32k buckets. just under the hashpower default. */ power = 15; } if (power >= hashpower) { fprintf(stderr, "Hash table power size (%d) cannot be equal to or less than item lock table (%d)\n", hashpower, power); fprintf(stderr, "Item lock table grows with `-t N` (worker threadcount)\n"); fprintf(stderr, "Hash table grows with `-o hashpower=N` \n"); exit(1); } item_lock_count = hashsize(power); item_lock_hashpower = power; item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t)); if (! item_locks) { perror("Can't allocate item locks"); exit(1); } for (i = 0; i < item_lock_count; i++) { pthread_mutex_init(&item_locks[i], NULL); } threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (! threads) { perror("Can't allocate thread descriptors"); exit(1); } for (i = 0; i < nthreads; i++) { int fds[2]; if (pipe(fds)) { perror("Can't create notify pipe"); exit(1); } threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; setup_thread(&threads[i]); /* Reserve three fds for the libevent base, and two for the pipe */ stats_state.reserved_fds += 5; } /* Create threads after we've done all the libevent setup. */ for (i = 0; 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); wait_for_thread_registration(nthreads); pthread_mutex_unlock(&init_lock); }
//参数nthread是woker线程的数量。main_base则是主线程的event_base //主线程在main函数调用本函数,创建nthreads个worker线程 void thread_init(int nthreads, struct event_base *main_base) { int i; int power; //申请一个CQ_ITEM时需要加锁 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; /* Want a wide lock table, but don't waste memory */ if (nthreads < 3) { power = 10; } else if (nthreads < 4) { power = 11; } else if (nthreads < 5) { power = 12; } else { /* 8192 buckets, and central locks don't scale much past 5 threads */ power = 13; } item_lock_count = hashsize(power); item_lock_hashpower = power; //哈希表中段级别的锁。并不是一个桶就对应有一个锁。而是多个桶共用一个锁 item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t)); if (! item_locks) { perror("Can't allocate item locks"); exit(1); } for (i = 0; i < item_lock_count; i++) { pthread_mutex_init(&item_locks[i], NULL); } pthread_key_create(&item_lock_type_key, NULL); pthread_mutex_init(&item_global_lock, NULL); //申请具有nthreads个元素的LIBEVENT_THREAD数据 threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (! threads) { perror("Can't allocate thread descriptors"); exit(1); } //主线程对应的 dispatcher_thread.base = main_base; dispatcher_thread.thread_id = pthread_self(); //子线程的 for (i = 0; i < nthreads; i++) { int fds[2]; //为每个worker线程分配一个管道,用于通知worker线程 if (pipe(fds)) { perror("Can't create notify pipe"); exit(1); } threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; //每一个线程配一个event_base,并设置event监听notify_receive_fd的读事件 //同时还为这个线程分配一个conn_queue队列 setup_thread(&threads[i]); /* Reserve three fds for the libevent base, and two for the pipe */ stats.reserved_fds += 5; } /* Create threads after we've done all the libevent setup. */ for (i = 0; i < nthreads; i++) { //创建线程,线程函数为worker_libevent,线程参数为&thread[i] create_worker(worker_libevent, &threads[i]); } /* Wait for all the threads to set themselves up before returning. */ pthread_mutex_lock(&init_lock); wait_for_thread_registration(nthreads); //主线程阻塞等待事件到来 pthread_mutex_unlock(&init_lock); }
/* * 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 nthreads, struct event_base *main_base) { int i; int power; 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; /* Want a wide lock table, but don't waste memory */ if (nthreads < 3) { power = 10; } else if (nthreads < 4) { power = 11; } else if (nthreads < 5) { power = 12; } else { /* 8192 buckets, and central locks don't scale much past 5 threads */ power = 13; } item_lock_count = hashsize(power); item_lock_hashpower = power; item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t)); if (! item_locks) { perror("Can't allocate item locks"); exit(1); } for (i = 0; i < item_lock_count; i++) { pthread_mutex_init(&item_locks[i], NULL); } pthread_key_create(&item_lock_type_key, NULL); pthread_mutex_init(&item_global_lock, NULL); threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (! threads) { perror("Can't allocate thread descriptors"); exit(1); } dispatcher_thread.base = main_base; dispatcher_thread.thread_id = pthread_self(); for (i = 0; i < nthreads; i++) { int fds[2]; if (pipe(fds)) { perror("Can't create notify pipe"); exit(1); } threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; setup_thread(&threads[i]); /* Reserve three fds for the libevent base, and two for the pipe */ stats.reserved_fds += 5; } /* Create threads after we've done all the libevent setup. */ for (i = 0; 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); wait_for_thread_registration(nthreads); pthread_mutex_unlock(&init_lock); }
/* * 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); }
/* + ========================== + | 线程初始化 | 主线程Accept | 4个worker线程 read | 1个线程监控消息 | 4个worker线程 write + ========================== + */ void thread_init(void) { /*{{{*/ int i; threads = calloc(THREAD_NUM,sizeof(THREAD)); write_threads = calloc(W_THREAD_NUM,sizeof(THREAD)); //msg_thread = (THREAD*)malloc(sizeof(THREAD)); char* name[] = {"r_a","r_b","r_c","r_d","r_e"}; char* w_name[] = {"w_a","w_b","w_c","w_d","w_e"}; for(i = 0; i < THREAD_NUM; ++i) { int fds[2]; //create pipe if(pipe(fds)) { printf("pipe create error!\n"); exit(1); } threads[i].id = i + 1; threads[i].name = name[i]; threads[i].type = T_R; threads[i].notify_recv = fds[0]; threads[i].notify_send = fds[1]; threads[i].conn_queue = NULL; setup_thread(&threads[i]); } /* for(i = 0;i < W_THREAD_NUM;++i){ int fds[2]; //create pipe if(pipe(fds)){ printf("pipe create error!\n"); exit(1); } write_threads[i].id = i + 1; write_threads[i].name = w_name[i]; write_threads[i].type = T_W; write_threads[i].notify_recv = fds[0]; write_threads[i].notify_send = fds[1]; write_threads[i].conn_queue = NULL; setup_thread(&write_threads[i]); } */ //setup_msg_thread(msg_thread); //create thread for(i = 0; i < THREAD_NUM; ++i) { create_worker(worker_libevent,&threads[i]); } /* for(i = 0;i < W_THREAD_NUM;++i){ create_worker(worker_libevent,&write_threads[i]); } */ //create_worker(worker_msg_dispatcher,msg_thread); }/*}}}*/
void *reader_thread(void *_arg) { orc_t *orc = (orc_t*) _arg; setup_thread(); orc->fd = -1; int reconnectcount = 0; reconnect: // reconnect, if necessary. while (orc->fd < 0) { LOG_INFO("Trying to connect to orcboard...(%i)", reconnectcount++); orc->fd = orc->impl->connect(orc->impl); if (orc->fd < 0) sleep(1); } // read for a while while (1) { // read a packet uint8_t buf[3]; int res = read_fully(orc->fd, buf, 1); if (res <= 0) goto disconnected; if (buf[0] != 0xED) { LOG_DEBUG("Recovering sync [%02X]", buf[0]); continue; } res = read_fully(orc->fd, &buf[1], 2); if (res <= 0) goto disconnected; int id = buf[1]; int datalen = buf[2]; transaction_t *t = &orc->transactions[id]; memcpy(t->response, buf, 3); res = read_fully(orc->fd, &t->response[PACKET_DATA], datalen + 1); if (res <= 0) goto disconnected; if (!packet_test_checksum(t->response)) { LOG_WARN("Bad checksum received from Orc"); continue; } if (t->response == garbage && t->response[1]>=orc->idLow && t->response[1]<=orc->idHigh) LOG_VERBOSE("Unsolicited ack, id = %02X", t->response[1]); // is this a message from orcd, assigning us a client id? if (t->response[1] == 0xf7) { orc->idLow = t->response[4]; orc->idHigh = t->response[5]; orc->idLast = orc->idLow; LOG_INFO("Got client transaction range: %02x-%02x", orc->idLow, orc->idHigh); } if (t->response[1] == 0xfe) handle_pad_packet(orc, t->response); if (t->response[1] == PACKET_ID_ORCBOARD_BROADCAST && packet_16u(t->response, 1) == MSG_ASYNC_HEARTBEAT) handle_heartbeat_packet(orc, t->response); pthread_mutex_lock(&t->mutex); pthread_cond_signal(&t->cond); pthread_mutex_unlock(&t->mutex); } disconnected: orc->impl->disconnect(orc->impl, orc->fd); orc->fd = -1; goto reconnect; // silence compiler return NULL; }
//初始化主线程 void thread_init(int nthreads, struct event_base *main_base) { int i; int power; 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; /* Want a wide lock table, but don't waste memory */ //初始化item lock //根据线程数目调配锁的数目(加锁是由于线程之间的并发导致的,所以item锁的数量也要根据线程的个数来进行调配) if (nthreads < 3) { power = 10; } else if (nthreads < 4) { power = 11; } else if (nthreads < 5) { power = 12; } else { /* 8192 buckets, and central locks don't scale much past 5 threads */ power = 13; } item_lock_count = hashsize(power); item_lock_hashpower = power; item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t)); if (! item_locks) { perror("Can't allocate item locks"); exit(1); } for (i = 0; i < item_lock_count; i++) { pthread_mutex_init(&item_locks[i], NULL); } pthread_key_create(&item_lock_type_key, NULL); pthread_mutex_init(&item_global_lock, NULL); //创建nthreads个worker线程对象 threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); if (! threads) { perror("Can't allocate thread descriptors"); exit(1); } //设置主线程对象的event_base dispatcher_thread.base = main_base; //设置主线程对象的pid dispatcher_thread.thread_id = pthread_self(); //为每个work线程创建与主线程通信的管道 for (i = 0; i < nthreads; i++) { int fds[2]; //建立管道 if (pipe(fds)) { perror("Can't create notify pipe"); exit(1); } threads[i].notify_receive_fd = fds[0]; //worker线程管道接收fd threads[i].notify_send_fd = fds[1]; //worker线程管道发送fd //初始化worker线程的libevent配置 setup_thread(&threads[i]); /* Reserve three fds for the libevent base, and two for the pipe */ stats.reserved_fds += 5; } /* Create threads after we've done all the libevent setup. */ for (i = 0; i < nthreads; i++) { //创建worker线程,配置worker线程运行的函数:worker_libevent create_worker(worker_libevent, &threads[i]); } /* Wait for all the threads to set themselves up before returning. */ pthread_mutex_lock(&init_lock); //等待所有worker线程启动完毕 wait_for_thread_registration(nthreads); pthread_mutex_unlock(&init_lock); }
/* * 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); }
/* * 初始化线程子系统, 创建工作线程 * 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 nthreads, struct event_base *main_base) { int i; int power; // 互斥量初始化 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; /* Want a wide lock table, but don't waste memory */ // 锁表? if (nthreads < 3) { power = 10; } else if (nthreads < 4) { power = 11; } else if (nthreads < 5) { power = 12; } else { // 2^13 /* 8192 buckets, and central locks don't scale much past 5 threads */ power = 13; } // 预申请那么多的锁, 拿来做什么 // hashsize = 2^n item_lock_count = hashsize(power); item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t)); if (! item_locks) { perror("Can't allocate item locks"); exit(1); } // 初始化 for (i = 0; i < item_lock_count; i++) { pthread_mutex_init(&item_locks[i], NULL); } pthread_key_create(&item_lock_type_key, NULL); pthread_mutex_init(&item_global_lock, NULL); // LIBEVENT_THREAD 是结合 libevent 使用的结构体, event_base, 读写管道 threads = calloc(nthreads, sizeof(LIBEVENT_THREAD)); // 生成 nthreads 数量的线程 if (! threads) { perror("Can't allocate thread descriptors"); exit(1); } // main_base 应该是分发任务的线程, 即主线程 dispatcher_thread.base = main_base; dispatcher_thread.thread_id = pthread_self(); // 管道, libevent 通知用的 for (i = 0; i < nthreads; i++) { int fds[2]; if (pipe(fds)) { perror("Can't create notify pipe"); exit(1); } // 读管道 threads[i].notify_receive_fd = fds[0]; // 写管道 threads[i].notify_send_fd = fds[1]; // 初始化线程信息数据结构, 其中就将 event 结构体的回调函数设置为 thread_libevent_process() setup_thread(&threads[i]); /* Reserve three fds for the libevent base, and two for the pipe */ stats.reserved_fds += 5; } /* Create threads after we've done all the libevent setup. */ // 创建并初始化线程, 线程的代码都是 work_libevent() for (i = 0; i < nthreads; i++) { // 调用 pthread_attr_init() 和 pthread_create() create_worker(worker_libevent, &threads[i]); } /* Wait for all the threads to set themselves up before returning. */ pthread_mutex_lock(&init_lock); // wait_for_thread_registration() 是 pthread_cond_wait 的调用 wait_for_thread_registration(nthreads); pthread_mutex_unlock(&init_lock); }