static int psmx2_ep_close(fid_t fid) { struct psmx2_fid_ep *ep; struct slist_entry *entry; struct psmx2_context *item; ep = container_of(fid, struct psmx2_fid_ep, ep.fid); if (ep->base_ep) { atomic_dec(&ep->base_ep->ref); return 0; } if (atomic_get(&ep->ref)) return -FI_EBUSY; ep->domain->eps[ep->vlane] = NULL; psmx2_free_vlane(ep->domain, ep->vlane); psmx2_domain_release(ep->domain); while (!slist_empty(&ep->free_context_list)) { entry = slist_remove_head(&ep->free_context_list); item = container_of(entry, struct psmx2_context, list_entry); free(item); } fastlock_destroy(&ep->context_lock); free(ep); return 0; }
ssize_t ofi_eq_read(struct fid_eq *eq_fid, uint32_t *event, void *buf, size_t len, uint64_t flags) { struct util_eq *eq; struct util_event *entry; void *user_err_data = NULL; ssize_t ret; eq = container_of(eq_fid, struct util_eq, eq_fid); fastlock_acquire(&eq->lock); if (slist_empty(&eq->list)) { ret = -FI_EAGAIN; goto out; } entry = container_of(eq->list.head, struct util_event, entry); if (entry->err && !(flags & UTIL_FLAG_ERROR)) { ret = -FI_EAVAIL; goto out; } else if (!entry->err && (flags & UTIL_FLAG_ERROR)) { ret = -FI_EAGAIN; goto out; } if (event) *event = entry->event; if (buf) { if (flags & UTIL_FLAG_ERROR) { if (eq->saved_err_data) { free(eq->saved_err_data); eq->saved_err_data = NULL; } assert((size_t)entry->size == sizeof(struct fi_eq_err_entry)); user_err_data = ((struct fi_eq_err_entry *)buf)->err_data; ofi_eq_handle_err_entry(eq->fabric->fabric_fid.api_version, (struct fi_eq_err_entry *)entry->data, (struct fi_eq_err_entry *)buf); ret = (ssize_t)entry->size; } else { ret = MIN(len, (size_t)entry->size); memcpy(buf, entry->data, ret); } } else { ret = 0; } if (!(flags & FI_PEEK)) { if ((flags & UTIL_FLAG_ERROR) && !user_err_data && ((struct fi_eq_err_entry *)buf)->err_data) { eq->saved_err_data = ((struct fi_eq_err_entry *)buf)->err_data; } slist_remove_head(&eq->list); free(entry); } out: fastlock_release(&eq->lock); return ret; }
static struct psmx2_eq_event *psmx2_eq_peek_event(struct psmx2_fid_eq *eq) { if (slist_empty(&eq->event_queue)) return NULL; return container_of(eq->event_queue.head, struct psmx2_eq_event, list_entry); }
/* slist_reset -- retourne au début de la liste: positionne * le noeud courant sur le premier de la liste. * Si la liste est vide, ne fait rien. * Complexité: O(1) */ void slist_reset(SList *list) { assert(list != NULL); if (!slist_empty(list)) { list->current = list->first; list->index = 1; } }
/* slist_current -- renvoie un pointeur sur le contenu du noeud courant * ou bien NULL si la liste est vide. * Si on a dépassé la fin de la liste (avec slist_next), renvoie * aussi NULL. * Complexité: O(1) */ void *slist_current(SList *list) { assert(list != NULL); if (slist_empty(list) || (list->current == NULL)) return NULL; else return list->current->item; }
static void tcpx_ep_tx_rx_queues_release(struct tcpx_ep *ep) { struct slist_entry *entry; struct tcpx_xfer_entry *xfer_entry; struct tcpx_cq *tcpx_cq; fastlock_acquire(&ep->lock); while (!slist_empty(&ep->tx_queue)) { entry = ep->tx_queue.head; xfer_entry = container_of(entry, struct tcpx_xfer_entry, entry); slist_remove_head(&ep->tx_queue); tcpx_cq = container_of(xfer_entry->ep->util_ep.tx_cq, struct tcpx_cq, util_cq); tcpx_xfer_entry_release(tcpx_cq, xfer_entry); } while (!slist_empty(&ep->rx_queue)) { entry = ep->rx_queue.head; xfer_entry = container_of(entry, struct tcpx_xfer_entry, entry); slist_remove_head(&ep->rx_queue); tcpx_cq = container_of(xfer_entry->ep->util_ep.rx_cq, struct tcpx_cq, util_cq); tcpx_xfer_entry_release(tcpx_cq, xfer_entry); } while (!slist_empty(&ep->rma_read_queue)) { entry = ep->rma_read_queue.head; xfer_entry = container_of(entry, struct tcpx_xfer_entry, entry); slist_remove_head(&ep->rma_read_queue); tcpx_cq = container_of(xfer_entry->ep->util_ep.tx_cq, struct tcpx_cq, util_cq); tcpx_xfer_entry_release(tcpx_cq, xfer_entry); } while (!slist_empty(&ep->tx_rsp_pend_queue)) { entry = ep->tx_rsp_pend_queue.head; xfer_entry = container_of(entry, struct tcpx_xfer_entry, entry); slist_remove_head(&ep->tx_rsp_pend_queue); tcpx_cq = container_of(xfer_entry->ep->util_ep.tx_cq, struct tcpx_cq, util_cq); tcpx_xfer_entry_release(tcpx_cq, xfer_entry); } fastlock_release(&ep->lock); }
slist slist_intersec(slist l1, slist l2) { slist listaNueva = slist_create(); slist l2Aux = l2; for( ; l1 != slist_empty(); l1 = slist_next(l1)) { for( ; l2 != slist_empty(); l2 = slist_next(l2)) { if( slist_data(l1) == slist_data(l2)) { if(slist_contain(listaNueva, slist_data(l1)) == FALSE) listaNueva = slist_append(listaNueva, slist_data(l1)); } } l2 = l2Aux; } return listaNueva; }
bool slist_contain(slist lista, const int elem) { for( ; lista != slist_empty(); lista = slist_next(lista)) { if(elem == slist_data(lista)) return TRUE; } return FALSE; }
void slist_foreach(SList list, VisitorFunc func) { SList aux_list = list; while (aux_list != slist_empty()) { func(aux_list->data,NULL); aux_list = aux_list->next; } }
bool slist_has_next(SList list) { if(list == slist_empty()) return FALSE; if(slist_next(list) != NULL) return TRUE; return FALSE; }
static ssize_t fi_ibv_cq_read(struct fid_cq *cq_fid, void *buf, size_t count) { struct fi_ibv_cq *cq; struct fi_ibv_wce *wce; struct slist_entry *entry; struct ibv_wc wc; ssize_t ret = 0, i; cq = container_of(cq_fid, struct fi_ibv_cq, util_cq.cq_fid); cq->util_cq.cq_fastlock_acquire(&cq->util_cq.cq_lock); for (i = 0; i < count; i++) { if (!slist_empty(&cq->wcq)) { wce = container_of(cq->wcq.head, struct fi_ibv_wce, entry); if (wce->wc.status) { ret = -FI_EAVAIL; break; } entry = slist_remove_head(&cq->wcq); wce = container_of(entry, struct fi_ibv_wce, entry); cq->read_entry(&wce->wc, (char *)buf + i * cq->entry_size); util_buf_release(cq->wce_pool, wce); continue; } ret = fi_ibv_poll_cq(cq, &wc); if (ret <= 0) break; /* Insert error entry into wcq */ if (OFI_UNLIKELY(wc.status)) { if (wc.status == IBV_WC_WR_FLUSH_ERR) { /* Handle case when remote side destroys * the connection, but local side isn't aware * about that yet */ VERBS_DBG(FI_LOG_CQ, "Ignoring WC with status " "IBV_WC_WR_FLUSH_ERR(%d)\n", wc.status); i--; continue; } wce = util_buf_alloc(cq->wce_pool); if (!wce) { cq->util_cq.cq_fastlock_release(&cq->util_cq.cq_lock); return -FI_ENOMEM; } memset(wce, 0, sizeof(*wce)); memcpy(&wce->wc, &wc, sizeof wc); slist_insert_tail(&wce->entry, &cq->wcq); ret = -FI_EAVAIL; break; } cq->read_entry(&wc, (char *)buf + i * cq->entry_size); }
SList slist_interect_custom(SList list1, SList list2, CompareFunc func, size_t size) { SList aux_list1 = list1; SList aux_list2 = list2; SList new_list = slist_create(); while (aux_list1 != slist_empty()) { while(aux_list2 != slist_empty()) { if(func(slist_data(aux_list1), slist_data(aux_list2)) && !slist_contain(new_list, slist_data(aux_list1), func)) new_list = slist_append(new_list, slist_data(aux_list1), size); aux_list2 = slist_next(aux_list2); } aux_list2 = list2; aux_list1 = slist_next(aux_list1); } return new_list; }
int slist_index(slist lista, const int elem) { int index = 0; for( ; lista != slist_empty(); lista = slist_next(lista), index++) { if(slist_data(lista) == elem) return index; } return -1; }
void slist_destroy(slist lista) { slist nodoAux; for( ; lista != slist_empty(); ) { nodoAux = lista; lista = slist_next(lista); free(nodoAux); } }
slist slist_intersec_custom(slist l1, slist l2, bool (*f)(int, int)) { slist listaNueva = slist_empty(); slist l2Aux = l2; for( ; l1 != slist_empty(); l1 = slist_next(l1)) { for( ; l2 != slist_empty(); l2 = slist_next(l2)) { if ((slist_data(l1) == slist_data(l2)) && f(slist_data(l1), slist_data(l2))) { if(slist_contain(listaNueva, slist_data(l1)) == FALSE) listaNueva = slist_append(listaNueva, slist_data(l1)); } } l2 = l2Aux; } return listaNueva; }
static struct psmx_cq_event *psmx_cq_alloc_event(struct psmx_fid_cq *cq) { struct psmx_cq_event *event; fastlock_acquire(&cq->lock); if (!slist_empty(&cq->free_list)) { event = container_of(slist_remove_head(&cq->free_list), struct psmx_cq_event, list_entry); fastlock_release(&cq->lock); return event; }
static struct psmx2_cq_event *psmx2_cq_alloc_event(struct psmx2_fid_cq *cq) { struct psmx2_cq_event *event; psmx2_lock(&cq->lock, 2); if (!slist_empty(&cq->free_list)) { event = container_of(slist_remove_head(&cq->free_list), struct psmx2_cq_event, list_entry); psmx2_unlock(&cq->lock, 2); return event; }
SList slist_concat(SList list1, SList list2, size_t size) { SList new_list = slist_create(); SList aux_list1 = list1; SList aux_list2 = list2; while(aux_list1 != slist_empty()) { new_list = slist_append(new_list, slist_data(aux_list1), size); aux_list1 = slist_next(aux_list1); } while(aux_list2 != slist_empty()) { new_list = slist_append(new_list, slist_data(aux_list2), size); aux_list2 = slist_next(aux_list2); } return new_list; }
struct fi_context *psmx2_ep_get_op_context(struct psmx2_fid_ep *ep) { struct psmx2_context *context; fastlock_acquire(&ep->context_lock); if (!slist_empty(&ep->free_context_list)) { context = container_of(slist_remove_head(&ep->free_context_list), struct psmx2_context, list_entry); fastlock_release(&ep->context_lock); return &context->fi_context; }
int _gnix_mbox_allocator_destroy(struct gnix_mbox_alloc_handle *alloc_handle) { struct slist_entry *entry; struct gnix_slab *temp; char error_buf[256]; int position; char *error; int ret = FI_SUCCESS; GNIX_TRACE(FI_LOG_EP_CTRL, "\n"); if (!alloc_handle) { GNIX_WARN(FI_LOG_EP_CTRL, "Invalid alloc handle.\n"); return -FI_EINVAL; } position = __find_used(alloc_handle, &temp); if (position >= 0) { GNIX_WARN(FI_LOG_EP_CTRL, "Can't destroy, not all mailboxes have been returned (pos = %d).\n", position); return -FI_EBUSY; } while (!slist_empty(&alloc_handle->slab_list)) { entry = slist_remove_head(&alloc_handle->slab_list); temp = container_of(entry, struct gnix_slab, list_entry); ret = __destroy_slab(alloc_handle, temp); if (ret) GNIX_WARN(FI_LOG_EP_CTRL, "Error destroying slab.\n"); } if (alloc_handle->filename != NULL) free(alloc_handle->filename); if (alloc_handle->fd != -1) ret = close(alloc_handle->fd); if (ret) { error = strerror_r(errno, error_buf, sizeof(error_buf)); GNIX_WARN(FI_LOG_EP_CTRL, "Error closing map file: %s\n", error); } fastlock_destroy(&alloc_handle->lock); free(alloc_handle); return FI_SUCCESS; }
SList slist_append(SList list, void *data, size_t size) { SList new_node = malloc(sizeof(SList)); new_node->next = slist_empty(); SList aux = list; void *new_data = malloc(sizeof(size)); new_data = data; new_node->data = new_data; if(list == slist_empty()) { list = new_node; return list; } while(aux->next != slist_empty()) aux = aux->next; aux->next = new_node; return list; }
unsigned int slist_length(SList list) { SList aux_list = list; unsigned int length = 0; while (aux_list != slist_empty()) { ++length; aux_list = slist_next(aux_list); } return length; }
/* slist_find -- Trouve le premier élément de la liste égal à item * (d'après le prédicat pred) et positionne le pointeur de liste dessus. * Renvoie un pointeur sur son son contenu. * Si l'élément n'a pas pu ^etre trouvé, renvoie NULL. * Complexité: O(longueur(list)*C(pred)) */ void *slist_find(SList *list, void *item, int (*pred)(void *, void *)) { assert((list != NULL) && (pred != NULL)); if (slist_empty(list)) return NULL; for (slist_reset(list); list->current != NULL; slist_next(list)) if (pred(slist_current(list), item)) break; if (list->current != NULL) return list->current->item; /* Trouvé */ else return NULL; /* Pas trouvé */ }
slist slist_append(slist lista, int dato) { slist nodoNuevo = malloc(sizeof(slist)); slist aux = lista; slist_data(nodoNuevo) = dato; slist_next(nodoNuevo) = slist_empty(); if(lista == slist_empty()) { return nodoNuevo; } else { for( ; slist_next(lista) != slist_empty(); lista = slist_next(lista)) ; slist_next(lista) = nodoNuevo; } return aux; }
bool slist_contain(SList list, void *data, CompareFunc func) { SList aux_list = list; while(aux_list != slist_empty()) { if(func(slist_data(aux_list), data) == TRUE) return TRUE; aux_list = slist_next(aux_list); } return FALSE; }
struct psmx_cq_event *psmx_cq_create_event(struct psmx_fid_cq *cq, void *op_context, void *buf, uint64_t flags, size_t len, uint64_t data, uint64_t tag, size_t olen, int err) { struct psmx_cq_event *event; if (!slist_empty(&cq->free_list)) { event = container_of(slist_remove_head(&cq->free_list), struct psmx_cq_event, list_entry); }
static struct psmx_cq_event *psmx_cq_dequeue_event(struct psmx_fid_cq *cq) { struct slist_entry *entry; if (slist_empty(&cq->event_queue)) return NULL; entry = slist_remove_head(&cq->event_queue); cq->event_count--; return container_of(entry, struct psmx_cq_event, list_entry); }
static struct psmx2_eq_event *psmx2_eq_dequeue_error(struct psmx2_fid_eq *eq) { struct slist_entry *entry; if (slist_empty(&eq->error_queue)) return NULL; fastlock_acquire(&eq->lock); entry = slist_remove_head(&eq->error_queue); fastlock_release(&eq->lock); return container_of(entry, struct psmx2_eq_event, list_entry); }
/* slist_next -- avance d'un élément dans la liste et renvoie * un pointeur sur le contenu de l'élément d'arrivé. * Ne fait rien (et renvoie NULL) si la liste est vide où qu'on est * déjà en fin de liste. * Complextié: O(1) */ void *slist_next(SList *list) { assert(list != NULL); if (slist_empty(list) || (list->current == NULL)) return NULL; list->current = list->current->next; if (list->current == NULL) return NULL; else { list->index += 1; return list->current->item; } }
list *merge(list *first, list *second) { list *m; link *fl, *sl; if (slist_empty(first)) return second; if (slist_empty(second)) return first; m = slist_init(); fl = first->front; sl = second->front; while (fl && sl) { if (fl->value < sl->value) { slist_push_back(m, fl->value); fl = fl->next; } else if (fl->value == sl->value) { slist_push_back(m, fl->value); slist_push_back(m, sl->value); fl = fl->next; sl = sl->next; } else { slist_push_back(m, sl->value); sl = sl->next; } } if (fl) { while (fl) { slist_push_back(m, fl->value); fl = fl->next; } } else if (sl) { while (sl) { slist_push_back(m, sl->value); sl = sl->next; } } return m; }