static int luv_thread_equal(lua_State* L) { luv_thread_t* t1 = luv_check_thread(L, 1); luv_thread_t* t2 = luv_check_thread(L, 2); int ret = uv_thread_equal(&t1->handle, &t2->handle); lua_pushboolean(L, ret); return 1; }
void eventpool_init(enum eventpool_threads_t t) { /* * Make sure we execute in the main thread */ const uv_thread_t pth_cur_id = uv_thread_self(); assert(uv_thread_equal(&pth_main_id, &pth_cur_id)); if(eventpoolinit == 1) { return; } eventpoolinit = 1; threads = t; if((async_req = MALLOC(sizeof(uv_async_t))) == NULL) { OUT_OF_MEMORY /*LCOV_EXCL_LINE*/ } uv_async_init(uv_default_loop(), async_req, eventpool_execute); if(lockinit == 0) { lockinit = 1; // pthread_mutexattr_init(&listeners_attr); // pthread_mutexattr_settype(&listeners_attr, PTHREAD_MUTEX_RECURSIVE); // pthread_mutex_init(&listeners_lock, &listeners_attr); uv_mutex_init(&listeners_lock); } }
static mrb_value mrb_uv_thread_eq(mrb_state *mrb, mrb_value self) { mrb_uv_thread *self_ctx = NULL, *other_ctx = NULL; mrb_value other; mrb_get_args(mrb, "o", &other); Data_Get_Struct(mrb, self, &mrb_uv_thread_type, self_ctx); Data_Get_Struct(mrb, other, &mrb_uv_thread_type, other_ctx); return mrb_bool_value(uv_thread_equal(&self_ctx->thread, &other_ctx->thread)); }
void uv_custom_poll_cb(uv_poll_t *req, int status, int events) { /* * Make sure we execute in the main thread */ const uv_thread_t pth_cur_id = uv_thread_self(); assert(uv_thread_equal(&pth_main_id, &pth_cur_id)); struct uv_custom_poll_t *custom_poll_data = NULL; struct iobuf_t *send_io = NULL; char buffer[BUFFER_SIZE]; uv_os_fd_t fd = 0; long int fromlen = 0; int r = 0, n = 0; custom_poll_data = req->data; if(custom_poll_data == NULL) { uv_poll_stop(req); return; } /* * Status == -9: Socket is unreachable * Events == 0: Client-end got disconnected */ r = uv_fileno((uv_handle_t *)req, &fd); if(status < 0 || events == 0) { if(status == -9) { logprintf(LOG_ERR, "uv_custom_poll_cb: socket not responding"); } else { logprintf(LOG_ERR, "uv_custom_poll_cb: %s", uv_strerror(status)); } if(custom_poll_data->close_cb != NULL) { custom_poll_data->close_cb(req); } if(!uv_is_closing((uv_handle_t *)req)) { uv_poll_stop(req); } if(fd > 0) { close(fd); } return; } custom_poll_data->started = 1; send_io = &custom_poll_data->send_iobuf; memset(&buffer, 0, BUFFER_SIZE); if(uv_is_closing((uv_handle_t *)req)) { return; } r = uv_fileno((uv_handle_t *)req, &fd); if(r != 0) { logprintf(LOG_ERR, "uv_fileno: %s", uv_strerror(r)); return; } if(custom_poll_data->is_ssl == 1 && custom_poll_data->ssl.init == 0) { custom_poll_data->ssl.init = 1; struct mbedtls_ssl_config *ssl_conf = &ssl_client_conf; if(custom_poll_data->is_server == 1) { custom_poll_data->ssl.handshake = 1; ssl_conf = &ssl_server_conf; } if((r = mbedtls_ssl_setup(&custom_poll_data->ssl.ctx, ssl_conf)) < 0) { mbedtls_strerror(r, (char *)&buffer, BUFFER_SIZE); logprintf(LOG_ERR, "mbedtls_ssl_setup: %s", buffer); FREE(req); return; } if((r = mbedtls_ssl_session_reset(&custom_poll_data->ssl.ctx)) < 0) { mbedtls_strerror(r, (char *)&buffer, BUFFER_SIZE); logprintf(LOG_ERR, "mbedtls_ssl_session_reset: %s", buffer); FREE(req); return; } // mbedtls_debug_set_threshold(2); mbedtls_ssl_set_bio(&custom_poll_data->ssl.ctx, &fd, mbedtls_net_send, mbedtls_net_recv, NULL); mbedtls_ssl_conf_dbg(ssl_conf, my_debug, stdout); if(custom_poll_data->host != NULL) { mbedtls_ssl_set_hostname(&custom_poll_data->ssl.ctx, custom_poll_data->host); } } if(custom_poll_data->is_ssl == 1 && custom_poll_data->ssl.handshake == 0) { n = mbedtls_ssl_handshake(&custom_poll_data->ssl.ctx); if(n == MBEDTLS_ERR_SSL_WANT_READ) { custom_poll_data->doread = 1; custom_poll_data->dowrite = 0; goto end; } else if(n == MBEDTLS_ERR_SSL_WANT_WRITE) { /*LCOV_EXCL_START*/ custom_poll_data->dowrite = 1; custom_poll_data->doread = 0; goto end; /*LCOV_EXCL_STOP*/ } if(n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE) { } else if(n < 0) { /*LCOV_EXCL_START*/ mbedtls_strerror(n, (char *)&buffer, BUFFER_SIZE); logprintf(LOG_NOTICE, "mbedtls_ssl_handshake: %s", buffer); uv_poll_stop(req); return; /*LCOV_EXCL_STOP*/ } else { custom_poll_data->ssl.handshake = 1; } custom_poll_data->dowrite = 1; goto end; } if(events & UV_WRITABLE) { if(send_io->len > 0) { if(custom_poll_data->is_ssl == 1) { n = mbedtls_ssl_write(&custom_poll_data->ssl.ctx, (unsigned char *)send_io->buf, send_io->len); if(n == MBEDTLS_ERR_SSL_WANT_READ) { /*LCOV_EXCL_START*/ custom_poll_data->doread = 1; custom_poll_data->dowrite = 0; goto end; /*LCOV_EXCL_STOP*/ } else if(n == MBEDTLS_ERR_SSL_WANT_WRITE) { /*LCOV_EXCL_START*/ custom_poll_data->dowrite = 1; custom_poll_data->doread = 0; goto end; /*LCOV_EXCL_STOP*/ } if(n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE) { } else if(n < 0) { /*LCOV_EXCL_START*/ mbedtls_strerror(n, (char *)&buffer, BUFFER_SIZE); logprintf(LOG_NOTICE, "mbedtls_ssl_handshake: %s", buffer); uv_poll_stop(req); return; /*LCOV_EXCL_STOP*/ } } else { n = (int)send((unsigned int)fd, send_io->buf, send_io->len, 0); } if(n > 0) { iobuf_remove(send_io, n); if(send_io->len > 0) { custom_poll_data->dowrite = 1; } else { custom_poll_data->dowrite = 0; if(custom_poll_data->doclose == 1 && send_io->len == 0) { custom_poll_data->doread = 0; goto end; } else { custom_poll_data->dowrite = 0; if(custom_poll_data->write_cb != NULL) { custom_poll_data->write_cb(req); } } } } else if(n == 0) { } else if(custom_poll_data->is_ssl == 0 && n < 0 && errno != EAGAIN && errno != EINTR) { if(errno == ECONNRESET) { uv_poll_stop(req); return; } else { uv_poll_stop(req); return; } } } else { custom_poll_data->dowrite = 0; if(custom_poll_data->doclose == 1 && send_io->len == 0) { custom_poll_data->doread = 0; goto end; } else { custom_poll_data->dowrite = 0; if(custom_poll_data->write_cb != NULL) { custom_poll_data->write_cb(req); } } } } if(send_io->len > 0) { custom_poll_data->dowrite = 1; } if(events & UV_READABLE) { if(custom_poll_data->is_ssl == 1) { n = mbedtls_ssl_read(&custom_poll_data->ssl.ctx, (unsigned char *)buffer, BUFFER_SIZE); if(n == MBEDTLS_ERR_SSL_WANT_READ) { custom_poll_data->doread = 1; custom_poll_data->dowrite = 0; goto end; } else if(n == MBEDTLS_ERR_SSL_WANT_WRITE) { /*LCOV_EXCL_START*/ custom_poll_data->dowrite = 1; custom_poll_data->doread = 0; goto end; /*LCOV_EXCL_STOP*/ } else if(n == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { custom_poll_data->doread = 0; if(custom_poll_data->read_cb != NULL) { custom_poll_data->read_cb(req, &custom_poll_data->recv_iobuf.len, custom_poll_data->recv_iobuf.buf); } } if(n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE) { } else if(n < 0) { if(n == MBEDTLS_ERR_NET_RECV_FAILED) { /* * FIXME: New client not yet accepted */ if(custom_poll_data->read_cb != NULL) { one = 1; custom_poll_data->read_cb(req, &one, NULL); } } else if(n != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { mbedtls_strerror(n, (char *)&buffer, BUFFER_SIZE); logprintf(LOG_NOTICE, "mbedtls_ssl_handshake: %s", buffer); uv_poll_stop(req); } return; } } else { if(custom_poll_data->custom_recv == 0) { if(custom_poll_data->is_udp == 1) { n = (int)recv((unsigned int)fd, buffer, BUFFER_SIZE, 0); } else { #ifdef _WIN32 n = recvfrom((SOCKET)fd, buffer, BUFFER_SIZE, 0, NULL, (socklen_t *)&fromlen); #else n = recvfrom(fd, buffer, BUFFER_SIZE, 0, NULL, (socklen_t *)&fromlen); #endif } } } if(custom_poll_data->custom_recv == 0) { if(n > 0) { iobuf_append(&custom_poll_data->recv_iobuf, buffer, n); custom_poll_data->doread = 0; if(custom_poll_data->read_cb != NULL) { custom_poll_data->read_cb(req, &custom_poll_data->recv_iobuf.len, custom_poll_data->recv_iobuf.buf); } } else if(n < 0 && errno != EINTR) { #ifdef _WIN32 switch(WSAGetLastError()) { case WSAENOTCONN: if(custom_poll_data->read_cb != NULL) { one = 1; custom_poll_data->read_cb(req, &one, NULL); } break; case WSAEWOULDBLOCK: #else switch(errno) { case ENOTCONN: if(custom_poll_data->read_cb != NULL) { one = 1; custom_poll_data->read_cb(req, &one, NULL); } break; #if defined EAGAIN case EAGAIN: #endif #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif #endif custom_poll_data->doread = 1; break; default: break; } /* * Client was disconnected */ } else if(n == 0) { custom_poll_data->doclose = 1; custom_poll_data->doread = 0; goto end; } } else { custom_poll_data->doread = 0; if(custom_poll_data->read_cb != NULL) { zero = 0; custom_poll_data->read_cb(req, &zero, NULL); } } }
static void eventpool_execute(uv_async_t *handle) { /* * Make sure we execute in the main thread */ const uv_thread_t pth_cur_id = uv_thread_self(); assert(uv_thread_equal(&pth_main_id, &pth_cur_id)); struct threadpool_tasks_t **node = NULL; int nrlisteners1[REASON_END] = {0}; int nr1 = 0, nrnodes = 16, nrnodes1 = 0, i = 0; if((node = MALLOC(sizeof(struct threadpool_tasks_t *)*nrnodes)) == NULL) { OUT_OF_MEMORY /*LCOV_EXCL_LINE*/ } uv_mutex_lock(&listeners_lock); struct eventqueue_t *queue = NULL; while(eventqueue) { queue = eventqueue; uv_sem_t *ref = NULL; #ifdef _WIN32 if((nr1 = InterlockedExchangeAdd(&nrlisteners[queue->reason], 0)) == 0) { #else if((nr1 = __sync_add_and_fetch(&nrlisteners[queue->reason], 0)) == 0) { #endif if(queue->done != NULL) { queue->done((void *)queue->data); } } else { if(threads == EVENTPOOL_THREADED) { if((ref = MALLOC(sizeof(uv_sem_t))) == NULL) { OUT_OF_MEMORY /*LCOV_EXCL_LINE*/ } uv_sem_init(ref, nr1-1); } struct eventpool_listener_t *listeners = eventpool_listeners; if(listeners == NULL) { if(queue->done != NULL) { queue->done((void *)queue->data); } } while(listeners) { if(listeners->reason == queue->reason) { if(nrnodes1 == nrnodes) { nrnodes *= 2; /*LCOV_EXCL_START*/ if((node = REALLOC(node, sizeof(struct threadpool_tasks_t *)*nrnodes)) == NULL) { OUT_OF_MEMORY } /*LCOV_EXCL_STOP*/ } if((node[nrnodes1] = MALLOC(sizeof(struct threadpool_tasks_t))) == NULL) { OUT_OF_MEMORY /*LCOV_EXCL_LINE*/ } node[nrnodes1]->func = listeners->func; node[nrnodes1]->userdata = queue->data; node[nrnodes1]->done = queue->done; node[nrnodes1]->ref = ref; node[nrnodes1]->reason = listeners->reason; nrnodes1++; if(threads == EVENTPOOL_THREADED) { nrlisteners1[queue->reason]++; } } listeners = listeners->next; } } eventqueue = eventqueue->next; FREE(queue); } uv_mutex_unlock(&listeners_lock); if(nrnodes1 > 0) { for(i=0;i<nrnodes1;i++) { if(threads == EVENTPOOL_NO_THREADS) { nrlisteners1[node[i]->reason]++; node[i]->func(node[i]->reason, node[i]->userdata); #ifdef _WIN32 if(nrlisteners1[node[i]->reason] == InterlockedExchangeAdd(&nrlisteners[node[i]->reason], 0)) { #else if(nrlisteners1[node[i]->reason] == __sync_add_and_fetch(&nrlisteners[node[i]->reason], 0)) { #endif if(node[i]->done != NULL) { node[i]->done((void *)node[i]->userdata); } nrlisteners1[node[i]->reason] = 0; } } else { struct threadpool_data_t *tpdata = NULL; tpdata = MALLOC(sizeof(struct threadpool_data_t)); if(tpdata == NULL) { OUT_OF_MEMORY /*LCOV_EXCL_LINE*/ } tpdata->userdata = node[i]->userdata; tpdata->func = node[i]->func; tpdata->done = node[i]->done; tpdata->ref = node[i]->ref; tpdata->reason = node[i]->reason; tpdata->priority = reasons[node[i]->reason].priority; uv_work_t *tp_work_req = MALLOC(sizeof(uv_work_t)); if(tp_work_req == NULL) { OUT_OF_MEMORY /*LCOV_EXCL_LINE*/ } tp_work_req->data = tpdata; if(uv_queue_work(uv_default_loop(), tp_work_req, reasons[node[i]->reason].reason, fib, fib_free) < 0) { if(node[i]->done != NULL) { node[i]->done((void *)node[i]->userdata); } FREE(tpdata); FREE(node[i]->ref); } } FREE(node[i]); } } for(i=0;i<REASON_END;i++) { nrlisteners1[i] = 0; } FREE(node); uv_mutex_lock(&listeners_lock); if(eventqueue != NULL) { uv_async_send(async_req); } uv_mutex_unlock(&listeners_lock); }