static ssize_t sock_eq_sread(struct fid_eq *eq, uint32_t *event, void *buf, size_t len, int timeout, uint64_t flags) { int ret; struct sock_eq *sock_eq; struct dlist_entry *list; struct sock_eq_entry *entry; sock_eq = container_of(eq, struct sock_eq, eq); sock_eq_clean_err_data_list(sock_eq, 0); if (!dlistfd_empty(&sock_eq->err_list)) { return -FI_EAVAIL; } if (dlistfd_empty(&sock_eq->list)) { if(!timeout) { SOCK_LOG_DBG("Nothing to read from eq!\n"); return -FI_EAGAIN; } ret = dlistfd_wait_avail(&sock_eq->list, timeout); if (!dlistfd_empty(&sock_eq->err_list)) { return -FI_EAVAIL; } if (ret <= 0) return (ret == 0 || ret == -FI_ETIMEDOUT) ? -FI_EAGAIN : ret; } fastlock_acquire(&sock_eq->lock); list = sock_eq->list.list.next; entry = container_of(list, struct sock_eq_entry, entry); if (entry->len > len) { ret = -FI_ETOOSMALL; goto out; } ret = entry->len; *event = entry->type; memcpy(buf, entry->event, entry->len); if (!(flags & FI_PEEK)) { dlistfd_remove(list, &sock_eq->list); free(entry); } out: fastlock_release(&sock_eq->lock); return (ret == 0 || ret == -FI_ETIMEDOUT) ? -FI_EAGAIN : ret; }
static ssize_t sock_eq_readerr(struct fid_eq *eq, struct fi_eq_err_entry *buf, uint64_t flags) { int ret; struct sock_eq *sock_eq; struct dlist_entry *list; struct sock_eq_entry *entry; struct fi_eq_err_entry *err_entry; struct sock_eq_err_data_entry *err_data_entry; sock_eq = container_of(eq, struct sock_eq, eq); fastlock_acquire(&sock_eq->lock); if (dlistfd_empty(&sock_eq->err_list)) { ret = -FI_EAGAIN; goto out; } list = sock_eq->err_list.list.next; entry = container_of(list, struct sock_eq_entry, entry); ret = entry->len; memcpy(buf, entry->event, entry->len); if (!(flags & FI_PEEK)) { err_entry = (struct fi_eq_err_entry *) entry->event; if (err_entry->err_data) { err_data_entry = container_of( err_entry->err_data, struct sock_eq_err_data_entry, err_data); err_data_entry->do_free = 1; }
static int fi_ibv_eq_close(fid_t fid) { struct fi_ibv_eq *eq; struct fi_ibv_eq_entry *entry; eq = container_of(fid, struct fi_ibv_eq, eq_fid.fid); if (eq->channel) rdma_destroy_event_channel(eq->channel); close(eq->epfd); fastlock_acquire(&eq->lock); while(!dlistfd_empty(&eq->list_head)) { entry = container_of(eq->list_head.list.next, struct fi_ibv_eq_entry, item); dlistfd_remove(eq->list_head.list.next, &eq->list_head); free(entry); } dlistfd_head_free(&eq->list_head); fastlock_destroy(&eq->lock); free(eq); return 0; }
static size_t fi_ibv_eq_read_event(struct fi_ibv_eq *eq, uint32_t *event, void *buf, size_t len, uint64_t flags) { struct fi_ibv_eq_entry *entry; ssize_t ret = 0; fastlock_acquire(&eq->lock); if (dlistfd_empty(&eq->list_head)) goto out; entry = container_of(eq->list_head.list.next, struct fi_ibv_eq_entry, item); if (entry->len > len) { ret = -FI_ETOOSMALL; goto out; } ret = entry->len; *event = entry->event; memcpy(buf, entry->eq_entry, entry->len); if (!(flags & FI_PEEK)) { dlistfd_remove(eq->list_head.list.next, &eq->list_head); free(entry); } out: fastlock_release(&eq->lock); return ret; }
static int fi_ibv_eq_close(fid_t fid) { struct fi_ibv_eq *eq; struct fi_ibv_eq_entry *entry; eq = container_of(fid, struct fi_ibv_eq, eq_fid.fid); /* TODO: use util code, if possible, and add ref counting */ if (eq->channel) rdma_destroy_event_channel(eq->channel); close(eq->epfd); while (!dlistfd_empty(&eq->list_head)) { entry = container_of(eq->list_head.list.next, struct fi_ibv_eq_entry, item); dlistfd_remove(eq->list_head.list.next, &eq->list_head); free(entry); } dlistfd_head_free(&eq->list_head); fastlock_destroy(&eq->lock); free(eq); return 0; }
static int sock_poll_poll(struct fid_poll *pollset, void **context, int count) { struct sock_poll *poll; struct sock_cq *cq; struct sock_eq *eq; struct sock_cntr *cntr; struct sock_fid_list *list_item; struct dlist_entry *p, *head; int ret_count = 0; poll = container_of(pollset, struct sock_poll, poll_fid.fid); head = &poll->fid_list; for (p = head->next; p != head && ret_count < count; p = p->next) { list_item = container_of(p, struct sock_fid_list, entry); switch (list_item->fid->fclass) { case FI_CLASS_CQ: cq = container_of(list_item->fid, struct sock_cq, cq_fid); sock_cq_progress(cq); fastlock_acquire(&cq->lock); if (rbfdused(&cq->cq_rbfd)) { *context++ = cq->cq_fid.fid.context; ret_count++; } fastlock_release(&cq->lock); break; case FI_CLASS_CNTR: cntr = container_of(list_item->fid, struct sock_cntr, cntr_fid); sock_cntr_progress(cntr); fastlock_acquire(&cntr->mut); if (atomic_get(&cntr->value) >= atomic_get(&cntr->threshold)) { *context++ = cntr->cntr_fid.fid.context; ret_count++; } fastlock_release(&cntr->mut); break; case FI_CLASS_EQ: eq = container_of(list_item->fid, struct sock_eq, eq); fastlock_acquire(&eq->lock); if (!dlistfd_empty(&eq->list)) { *context++ = eq->eq.fid.context; ret_count++; } fastlock_release(&eq->lock); break; default: break; } } return ret_count; }
static void sock_ep_clear_eq_list(struct dlistfd_head *list, struct fid_ep *ep_fid) { struct dlist_entry *entry; while (!dlistfd_empty(list)) { entry = dlist_remove_first_match(&list->list, sock_eq_fid_match, ep_fid); if (!entry) break; dlistfd_reset(list); free(container_of(entry, struct sock_eq_entry, entry)); } }