static UCS_CLASS_INIT_FUNC(uct_tcp_ep_t, uct_tcp_iface_t *iface, int fd, const struct sockaddr_in *dest_addr) { ucs_status_t status; UCS_CLASS_CALL_SUPER_INIT(uct_base_ep_t, &iface->super) self->buf = ucs_malloc(iface->config.buf_size, "tcp_buf"); if (self->buf == NULL) { return UCS_ERR_NO_MEMORY; } self->events = 0; self->offset = 0; self->length = 0; ucs_queue_head_init(&self->pending_q); if (fd == -1) { status = ucs_tcpip_socket_create(&self->fd); if (status != UCS_OK) { goto err; } /* TODO use non-blocking connect */ status = uct_tcp_socket_connect(self->fd, dest_addr); if (status != UCS_OK) { goto err_close; } } else { self->fd = fd; } status = ucs_sys_fcntl_modfl(self->fd, O_NONBLOCK, 0); if (status != UCS_OK) { goto err_close; } status = uct_tcp_iface_set_sockopt(iface, self->fd); if (status != UCS_OK) { goto err_close; } uct_tcp_ep_epoll_ctl(self, EPOLL_CTL_ADD); UCS_ASYNC_BLOCK(iface->super.worker->async); ucs_list_add_tail(&iface->ep_list, &self->list); UCS_ASYNC_UNBLOCK(iface->super.worker->async); ucs_debug("tcp_ep %p: created on iface %p, fd %d", self, iface, self->fd); return UCS_OK; err_close: close(self->fd); err: return status; }
void uct_dc_ep_cleanup(uct_ep_h tl_ep, ucs_class_t *cls) { uct_dc_ep_t *ep = ucs_derived_of(tl_ep, uct_dc_ep_t); uct_dc_iface_t *iface = ucs_derived_of(ep->super.super.iface, uct_dc_iface_t); UCS_CLASS_CLEANUP_CALL(cls, ep); if (uct_dc_ep_fc_wait_for_grant(ep)) { ucs_trace("not releasing dc_ep %p - waiting for grant", ep); ep->state = UCT_DC_EP_INVALID; ucs_list_add_tail(&iface->tx.gc_list, &ep->list); } else { ucs_free(ep); } }
void __ucs_wtimer_add(ucs_twheel_t *t, ucs_wtimer_t *timer, ucs_time_t delta) { uint64_t slot; timer->is_active = 1; slot = delta>>t->res_order; if (ucs_unlikely(slot == 0)) { /* nothing really wrong with adding timer to the current slot. However * we want to guard against the case we spend to much time in hi res * timer processing */ ucs_fatal("Timer resolution is too low. Min resolution %lf usec, wanted %lf usec", ucs_time_to_usec(t->res), ucs_time_to_usec(delta)); } ucs_assert(slot > 0); if (ucs_unlikely(slot >= t->num_slots)) { slot = t->num_slots - 1; } slot = (t->current + slot) % t->num_slots; ucs_assert(slot != t->current); ucs_list_add_tail(&t->wheel[slot], &timer->list); }
static UCS_CLASS_INIT_FUNC(uct_rdmacm_ep_t, uct_iface_t *tl_iface, const ucs_sock_addr_t *sockaddr, const void *priv_data, size_t length) { uct_rdmacm_iface_t *iface = ucs_derived_of(tl_iface, uct_rdmacm_iface_t); char ip_port_str[UCS_SOCKADDR_STRING_LEN]; uct_rdmacm_priv_data_hdr_t hdr; ucs_status_t status; UCS_CLASS_CALL_SUPER_INIT(uct_base_ep_t, &iface->super); if (iface->is_server) { /* TODO allow an interface to be used both for server and client */ return UCS_ERR_UNSUPPORTED; } /* Initialize these fields before calling rdma_resolve_addr to avoid a race * where they are used before being initialized (from the async thread * - after an RDMA_CM_EVENT_ROUTE_RESOLVED event) */ hdr.length = length; self->priv_data = ucs_malloc(sizeof(hdr) + length, "client private data"); if (self->priv_data == NULL) { status = UCS_ERR_NO_MEMORY; goto err; } memcpy(self->priv_data, &hdr, sizeof(hdr)); memcpy(self->priv_data + sizeof(hdr), priv_data, length); /* Save the remote address */ if (sockaddr->addr->sa_family == AF_INET) { memcpy(&self->remote_addr, sockaddr->addr, sizeof(struct sockaddr_in)); } else if (sockaddr->addr->sa_family == AF_INET6) { memcpy(&self->remote_addr, sockaddr->addr, sizeof(struct sockaddr_in6)); } else { ucs_error("rdmacm ep: unknown remote sa_family=%d", sockaddr->addr->sa_family); status = UCS_ERR_IO_ERROR; goto err_free_mem; } self->slow_prog_id = UCS_CALLBACKQ_ID_NULL; /* The interface can point at one endpoint at a time and therefore, the * connection establishment cannot be done in parallel for several endpoints */ /* TODO support connection establishment on parallel endpoints on the same iface */ if (iface->ep == NULL) { iface->ep = self; self->is_on_pending = 0; /* After rdma_resolve_addr(), the client will wait for an * RDMA_CM_EVENT_ADDR_RESOLVED event on the event_channel * to proceed with the connection establishment. * This event will be retrieved from the event_channel by the async thread. * All endpoints share the interface's event_channel but can use it serially. */ status = uct_rdmacm_ep_resolve_addr(self); if (status != UCS_OK) { goto err_free_mem; } } else { /* Add the ep to the pending queue */ UCS_ASYNC_BLOCK(iface->super.worker->async); ucs_list_add_tail(&iface->pending_eps_list, &self->list_elem); self->is_on_pending = 1; UCS_ASYNC_UNBLOCK(iface->super.worker->async); } ucs_debug("created an RDMACM endpoint on iface %p. event_channel: %p, " "iface cm_id: %p remote addr: %s", iface, iface->event_ch, iface->cm_id, ucs_sockaddr_str((struct sockaddr *)sockaddr->addr, ip_port_str, UCS_SOCKADDR_STRING_LEN)); return UCS_OK; err_free_mem: ucs_free(self->priv_data); err: return status; }