void initialize_event_loop(bool is_main_thread, global_data_t *global_data, h2o_multithread_receiver_t *h2o_receiver, event_loop_t *loop) { h2o_socket_cb accept_cb = accept_connection; const config_t * const config = global_data->global_thread_data->config; memset(loop, 0, sizeof(*loop)); h2o_context_init(&loop->h2o_ctx, h2o_evloop_create(), &global_data->h2o_config); loop->h2o_accept_ctx.ctx = &loop->h2o_ctx; loop->h2o_accept_ctx.hosts = global_data->h2o_config.hosts; if (global_data->ssl_ctx) { loop->h2o_accept_ctx.ssl_ctx = global_data->ssl_ctx; start_accept_polling(config, accept_connection, true, loop); // Assume that the majority of the connections use HTTPS, // so HTTP can take a few extra operations. accept_cb = accept_http_connection; } start_accept_polling(config, accept_cb, false, loop); h2o_multithread_register_receiver(loop->h2o_ctx.queue, h2o_receiver, process_messages); if (is_main_thread) { global_data->signals = h2o_evloop_socket_create(loop->h2o_ctx.loop, global_data->signal_fd, H2O_SOCKET_FLAG_DONT_READ); global_data->signals->data = loop; h2o_socket_read_start(global_data->signals, shutdown_server); } }
void initialize_event_loop(bool is_main_thread, global_data_t *global_data, event_loop_t *loop) { memset(loop, 0, sizeof(*loop)); h2o_context_init(&loop->h2o_ctx, h2o_evloop_create(), &global_data->h2o_config); loop->h2o_accept_ctx.ctx = &loop->h2o_ctx; loop->h2o_accept_ctx.hosts = global_data->h2o_config.hosts; loop->h2o_accept_ctx.ssl_ctx = global_data->ssl_ctx; int listener_sd; if (is_main_thread) listener_sd = global_data->listener_sd; else { int flags; CHECK_ERRNO_RETURN(listener_sd, dup, global_data->listener_sd); CHECK_ERRNO_RETURN(flags, fcntl, listener_sd, F_GETFD); CHECK_ERRNO(fcntl, listener_sd, F_SETFD, flags | FD_CLOEXEC); } // Let all the threads race to call accept() on the socket; since the latter is // non-blocking, that will effectively act as load balancing. loop->h2o_socket = h2o_evloop_socket_create(loop->h2o_ctx.loop, listener_sd, H2O_SOCKET_FLAG_DONT_READ); loop->h2o_socket->data = loop; h2o_socket_read_start(loop->h2o_socket, accept_connection); h2o_multithread_register_receiver(loop->h2o_ctx.queue, &loop->h2o_receiver, process_messages); // libh2o's event loop does not support write polling unless it // controls sending the data as well, so do read polling on the // epoll file descriptor as a work-around. CHECK_ERRNO_RETURN(loop->epoll_fd, epoll_create1, EPOLL_CLOEXEC); loop->epoll_socket = h2o_evloop_socket_create(loop->h2o_ctx.loop, loop->epoll_fd, H2O_SOCKET_FLAG_DONT_READ); loop->epoll_socket->data = loop; h2o_socket_read_start(loop->epoll_socket, do_epoll_wait); if (is_main_thread) { global_data->signals = h2o_evloop_socket_create(loop->h2o_ctx.loop, global_data->signal_fd, H2O_SOCKET_FLAG_DONT_READ); global_data->signals->data = loop; h2o_socket_read_start(global_data->signals, shutdown_server); } }
void test_lib__common__multithread_c(void) { pthread_t tid; main_thread.loop = create_loop(); main_thread.queue = h2o_multithread_create_queue(main_thread.loop); h2o_multithread_register_receiver(main_thread.queue, &main_thread.pong_receiver, on_pong); h2o_multithread_register_receiver(main_thread.queue, &main_thread.shutdown_receiver, on_shutdown); worker_thread.loop = create_loop(); worker_thread.queue = h2o_multithread_create_queue(worker_thread.loop); h2o_multithread_register_receiver(worker_thread.queue, &worker_thread.ping_receiver, on_ping); pthread_create(&tid, NULL, worker_main, NULL); /* send first message */ send_empty_message(&worker_thread.ping_receiver); while (!main_thread.received_shutdown) { #if H2O_USE_LIBUV uv_run(main_thread.loop, UV_RUN_ONCE); #else h2o_evloop_run(main_thread.loop, INT32_MAX); #endif } pthread_join(tid, NULL); h2o_multithread_unregister_receiver(worker_thread.queue, &worker_thread.ping_receiver); h2o_multithread_destroy_queue(worker_thread.queue); destroy_loop(worker_thread.loop); h2o_multithread_unregister_receiver(main_thread.queue, &main_thread.pong_receiver); h2o_multithread_unregister_receiver(main_thread.queue, &main_thread.shutdown_receiver); h2o_multithread_destroy_queue(main_thread.queue); destroy_loop(main_thread.loop); ok(1); }
void h2o_context_init(h2o_context_t *ctx, h2o_loop_t *loop, h2o_globalconf_t *config) { size_t i, j; assert(config->hosts[0] != NULL); memset(ctx, 0, sizeof(*ctx)); ctx->loop = loop; ctx->globalconf = config; h2o_timeout_init(ctx->loop, &ctx->zero_timeout, 0); h2o_timeout_init(ctx->loop, &ctx->one_sec_timeout, 1000); h2o_timeout_init(ctx->loop, &ctx->hundred_ms_timeout, 100); ctx->queue = h2o_multithread_create_queue(loop); h2o_multithread_register_receiver(ctx->queue, &ctx->receivers.hostinfo_getaddr, h2o_hostinfo_getaddr_receiver); ctx->filecache = h2o_filecache_create(config->filecache.capacity); h2o_timeout_init(ctx->loop, &ctx->handshake_timeout, config->handshake_timeout); h2o_timeout_init(ctx->loop, &ctx->http1.req_timeout, config->http1.req_timeout); h2o_linklist_init_anchor(&ctx->http1._conns); h2o_timeout_init(ctx->loop, &ctx->http2.idle_timeout, config->http2.idle_timeout); h2o_linklist_init_anchor(&ctx->http2._conns); ctx->proxy.client_ctx.loop = loop; h2o_timeout_init(ctx->loop, &ctx->proxy.io_timeout, config->proxy.io_timeout); ctx->proxy.client_ctx.getaddr_receiver = &ctx->receivers.hostinfo_getaddr; ctx->proxy.client_ctx.io_timeout = &ctx->proxy.io_timeout; ctx->proxy.client_ctx.ssl_ctx = config->proxy.ssl_ctx; ctx->_module_configs = h2o_mem_alloc(sizeof(*ctx->_module_configs) * config->_num_config_slots); memset(ctx->_module_configs, 0, sizeof(*ctx->_module_configs) * config->_num_config_slots); static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); for (i = 0; config->hosts[i] != NULL; ++i) { h2o_hostconf_t *hostconf = config->hosts[i]; for (j = 0; j != hostconf->paths.size; ++j) { h2o_pathconf_t *pathconf = hostconf->paths.entries + j; h2o_context_init_pathconf_context(ctx, pathconf); } h2o_context_init_pathconf_context(ctx, &hostconf->fallback_path); } pthread_mutex_unlock(&mutex); }