rstatus_t thread_init(struct event_base *main_base) { rstatus_t status; err_t err; int nworkers = settings.num_workers; struct thread_worker *dispatcher; int i; init_count = 0; pthread_mutex_init(&init_lock, NULL); pthread_cond_init(&init_cond, NULL); last_thread = -1; /* dispatcher takes the extra (last) slice of thread descriptor */ threads = mc_zalloc(sizeof(*threads) * (1 + nworkers)); if (threads == NULL) { return MC_ENOMEM; } /* keep data of dispatcher close to worker threads for easy aggregation */ dispatcher = &threads[nworkers]; /* create keys for common members of thread_worker. */ err = pthread_key_create(&keys.stats_mutex, NULL); if (err != 0) { log_error("pthread key create failed: %s", strerror(err)); return MC_ERROR; } err = pthread_key_create(&keys.stats_thread, NULL); if (err != 0) { log_error("pthread key create failed: %s", strerror(err)); return MC_ERROR; } err = pthread_key_create(&keys.stats_slabs, NULL); if (err != 0) { log_error("pthread key create failed: %s", strerror(err)); return MC_ERROR; } err = pthread_key_create(&keys.kbuf, NULL); if (err != 0) { log_error("pthread key create failed: %s", strerror(err)); return MC_ERROR; } dispatcher->base = main_base; dispatcher->tid = pthread_self(); status = thread_setup_stats(dispatcher); if (status != MC_OK) { return status; } status = thread_setkeys(dispatcher); if (status != MC_OK) { return status; } for (i = 0; i < nworkers; i++) { int fds[2]; status = pipe(fds); if (status < 0) { log_error("pipe failed: %s", strerror(errno)); return status; } threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; status = thread_setup(&threads[i]); if (status != MC_OK) { return status; } } /* create worker threads after we've done all the libevent setup */ for (i = 0; i < nworkers; i++) { status = thread_create(thread_worker_main, &threads[i]); if (status != MC_OK) { return status; } } /* wait for all the workers to set themselves up */ pthread_mutex_lock(&init_lock); while (init_count < nworkers) { pthread_cond_wait(&init_cond, &init_lock); } pthread_mutex_unlock(&init_lock); /* for stats module */ /* setup thread data structures */ status = thread_setup_aggregator(); if (status != MC_OK) { return status; } /* create thread */ status = thread_create(thread_aggregator_main, NULL); if (status != MC_OK) { return status; } /* for klogger */ /* Setup thread data structure */ status = thread_setup_klogger(); if (status != MC_OK) { return status; } /* create thread */ status = thread_create(thread_klogger_main, NULL); if (status != MC_OK) { return status; } /* wait for all the workers and dispatcher to set themselves up */ pthread_mutex_lock(&init_lock); while (init_count < nworkers + 2) { /* +2: aggregator & klogger */ pthread_cond_wait(&init_cond, &init_lock); } pthread_mutex_unlock(&init_lock); return MC_OK; }
struct conn * conn_get(int sd, conn_state_t state, int ev_flags, int rsize, int udp) { struct conn *c; ASSERT(state >= CONN_LISTEN && state < CONN_SENTINEL); ASSERT(rsize > 0); c = _conn_get(); if (c == NULL) { c = mc_zalloc(sizeof(*c)); if (c == NULL) { return NULL; } c->rsize = rsize; c->rbuf = mc_alloc(c->rsize); c->wsize = TCP_BUFFER_SIZE; c->wbuf = mc_alloc(c->wsize); c->isize = ILIST_SIZE; c->ilist = mc_alloc(sizeof(*c->ilist) * c->isize); c->ssize = SLIST_SIZE; c->slist = mc_alloc(sizeof(*c->slist) * c->ssize); c->iov_size = IOV_SIZE; c->iov = mc_alloc(sizeof(*c->iov) * c->iov_size); c->msg_size = MSG_SIZE; c->msg = mc_alloc(sizeof(*c->msg) * c->msg_size); if (c->rbuf == NULL || c->wbuf == NULL || c->ilist == NULL || c->iov == NULL || c->msg == NULL || c->slist == NULL) { conn_free(c); return NULL; } stats_thread_incr(conn_struct); } STAILQ_NEXT(c, c_tqe) = NULL; c->thread = NULL; c->sd = sd; c->state = state; /* c->event is initialized later */ c->ev_flags = ev_flags; c->which = 0; ASSERT(c->rbuf != NULL && c->rsize > 0); c->rcurr = c->rbuf; c->rbytes = 0; ASSERT(c->wbuf != NULL && c->wsize > 0); c->wcurr = c->wbuf; c->wbytes = 0; c->write_and_go = state; c->write_and_free = NULL; c->ritem = NULL; c->rlbytes = 0; c->item = NULL; c->sbytes = 0; ASSERT(c->iov != NULL && c->iov_size > 0); c->iov_used = 0; ASSERT(c->msg != NULL && c->msg_size > 0); c->msg_used = 0; c->msg_curr = 0; c->msg_bytes = 0; ASSERT(c->ilist != NULL && c->isize > 0); c->icurr = c->ilist; c->ileft = 0; ASSERT(c->slist != NULL && c->ssize > 0); c->scurr = c->slist; c->sleft = 0; c->stats.buffer = NULL; c->stats.size = 0; c->stats.offset = 0; c->req_type = REQ_UNKNOWN; c->req = NULL; c->req_len = 0; c->udp = udp; c->udp_rid = 0; c->udp_hbuf = NULL; c->udp_hsize = 0; c->noreply = 0; stats_thread_incr(conn_total); stats_thread_incr(conn_curr); log_debug(LOG_VVERB, "get conn %p c %d", c, c->sd); return c; }