/** * Destroy a slab. * * @param[in] handle Handle to the allocator being used. * @param[in] slab Slab to be destroyed. * * @return FI_SUCCESS On successful slab destruction. * * @return -FI_EINVAL On invalid handle or slab being given as parameters. */ static int __destroy_slab(struct gnix_mbox_alloc_handle *handle, struct gnix_slab *slab) { size_t total_size; GNIX_TRACE(FI_LOG_EP_CTRL, "\n"); if (!handle || !slab) { GNIX_WARN(FI_LOG_EP_CTRL, "Invalid argument handle or slab.\n"); return -FI_EINVAL; } total_size = handle->page_size * __page_count(handle); _gnix_free_bitmap(slab->used); free(slab->used); COND_ACQUIRE(handle->nic_handle->requires_lock, &handle->nic_handle->lock); GNI_MemDeregister(handle->nic_handle->gni_nic_hndl, &slab->memory_handle); COND_RELEASE(handle->nic_handle->requires_lock, &handle->nic_handle->lock); munmap(slab->base, total_size); free(slab); return FI_SUCCESS; }
int _gnix_buddy_allocator_destroy(gnix_buddy_alloc_handle_t *alloc_handle) { GNIX_TRACE(FI_LOG_EP_CTRL, "\n"); if (unlikely(!alloc_handle)) { GNIX_WARN(FI_LOG_EP_CTRL, "Invalid parameter to _gnix_buddy_allocator_destroy." "\n"); return -FI_EINVAL; } fastlock_acquire(&alloc_handle->lock); free(alloc_handle->lists); while (_gnix_free_bitmap(&alloc_handle->bitmap)) { GNIX_WARN(FI_LOG_EP_CTRL, "Trying to free buddy allocator handle bitmap.\n"); sleep(1); } fastlock_release(&alloc_handle->lock); fastlock_destroy(&alloc_handle->lock); free(alloc_handle); return FI_SUCCESS; }
Test(gnix_hashtable_advanced, insert_8K_lookup_128K_random) { int ret, i, index; gnix_test_element_t *test_elements; gnix_test_element_t *found = NULL, *to_find = NULL; gnix_test_element_t *item; gnix_bitmap_t allocated = {0}; int test_size = 8 * 1024; int bitmap_size = 64 * test_size; int lookups = 128 * 1024; test_elements = calloc(test_size, sizeof(gnix_test_element_t)); cr_assert(test_elements != NULL); ret = _gnix_alloc_bitmap(&allocated, bitmap_size); cr_assert(ret == 0); srand(time(NULL)); for (i = 0; i < test_size; ++i) { do { index = rand() % bitmap_size; } while (_gnix_test_and_set_bit(&allocated, index)); item = &test_elements[i]; item->key = index; item->val = rand() % lookups; item->magic = __GNIX_MAGIC_VALUE; } for (i = 0; i < test_size; ++i) { item = &test_elements[i]; ret = _gnix_ht_insert(test_ht, item->key, item); cr_assert(ret == 0); cr_assert(atomic_get(&test_ht->ht_elements) == (i + 1)); } cr_assert(atomic_get(&test_ht->ht_elements) == test_size); for (i = 0; i < lookups; ++i) { to_find = &test_elements[rand() % test_size]; found = _gnix_ht_lookup(test_ht, to_find->key); cr_assert(found != NULL); cr_assert(found == to_find); cr_assert(found->magic == __GNIX_MAGIC_VALUE); } ret = _gnix_free_bitmap(&allocated); cr_expect(ret == 0); free(test_elements); }
/** * Create a slab from a handle and append to the slab list. * * @param[in] handle Handle to the allocator being used. * * @return FI_SUCCESS On successful slab creation. * * @return -FI_ENOMEM if failure to allocate memory for slab or bitmap. * @return [Unspec] if failure in alloc_bitmap. Will return error code from * alloc_bitmap. * @return [Unspec] if failure in GNI_MemRegister. Converts gni_return_t * status code to FI_ERRNO value. */ static int __create_slab(struct gnix_mbox_alloc_handle *handle) { struct gnix_slab *slab; gni_return_t status; char error_buf[256]; char *error; size_t total_size; int ret; int vmdh_index = -1; int flags = GNI_MEM_READWRITE; struct gnix_auth_key *info; GNIX_TRACE(FI_LOG_EP_CTRL, "\n"); slab = calloc(1, sizeof(*slab)); if (!slab) { error = strerror_r(errno, error_buf, sizeof(error_buf)); GNIX_WARN(FI_LOG_EP_CTRL, "Error allocating slab: %s\n", error); ret = -FI_ENOMEM; goto err_slab_calloc; } total_size = handle->page_size * __page_count(handle); GNIX_DEBUG(FI_LOG_EP_CTRL, "total_size requested for mmap: %zu.\n", total_size); slab->used = calloc(1, sizeof(*(slab->used))); if (!slab->used) { error = strerror_r(errno, error_buf, sizeof(error_buf)); GNIX_WARN(FI_LOG_EP_CTRL, "Error allocating bitmap: %s\n", error); ret = -FI_ENOMEM; goto err_bitmap_calloc; } slab->base = mmap(0, total_size, (PROT_READ | PROT_WRITE), MAP_SHARED, handle->fd, handle->last_offset); if (slab->base == MAP_FAILED) { error = strerror_r(errno, error_buf, sizeof(error_buf)); GNIX_WARN(FI_LOG_EP_CTRL, "%s\n", error); ret = -FI_ENOMEM; goto err_mmap; } ret = _gnix_alloc_bitmap(slab->used, __mbox_count(handle), NULL); if (ret) { GNIX_WARN(FI_LOG_EP_CTRL, "Error allocating bitmap.\n"); goto err_alloc_bitmap; } COND_ACQUIRE(handle->nic_handle->requires_lock, &handle->nic_handle->lock); if (handle->nic_handle->using_vmdh) { info = _gnix_auth_key_lookup(GNIX_PROV_DEFAULT_AUTH_KEY, GNIX_PROV_DEFAULT_AUTH_KEYLEN); assert(info); if (!handle->nic_handle->mdd_resources_set) { /* check to see if the ptag registration limit was set * yet or not -- becomes read-only after success */ _gnix_auth_key_enable(info); status = GNI_SetMddResources( handle->nic_handle->gni_nic_hndl, (info->attr.prov_key_limit + info->attr.user_key_limit)); assert(status == GNI_RC_SUCCESS); handle->nic_handle->mdd_resources_set = 1; } vmdh_index = _gnix_get_next_reserved_key(info); if (vmdh_index <= 0) { GNIX_FATAL(FI_LOG_DOMAIN, "failed to get reserved key for mbox " "registration, rc=%d\n", vmdh_index); } flags |= GNI_MEM_USE_VMDH; } status = GNI_MemRegister(handle->nic_handle->gni_nic_hndl, (uint64_t) slab->base, total_size, handle->cq_handle, flags, vmdh_index, &slab->memory_handle); COND_RELEASE(handle->nic_handle->requires_lock, &handle->nic_handle->lock); if (status != GNI_RC_SUCCESS) { GNIX_WARN(FI_LOG_EP_CTRL, "GNI_MemRegister failed: %s\n", gni_err_str[status]); ret = gnixu_to_fi_errno(status); goto err_memregister; } slab->allocator = handle; gnix_slist_insert_tail(&slab->list_entry, &handle->slab_list); handle->last_offset += total_size; return ret; err_memregister: _gnix_free_bitmap(slab->used); err_alloc_bitmap: munmap(slab->base, total_size); err_mmap: free(slab->used); err_bitmap_calloc: free(slab); err_slab_calloc: return ret; }
/* Destroy an unconnected VC. More Support is needed to shutdown and destroy * an active VC. */ int _gnix_vc_destroy(struct gnix_vc *vc) { int ret = FI_SUCCESS; struct gnix_nic *nic = NULL; gni_return_t status; GNIX_TRACE(FI_LOG_EP_CTRL, "\n"); if (vc->ep == NULL) { GNIX_WARN(FI_LOG_EP_CTRL, "ep null\n"); return -FI_EINVAL; } nic = vc->ep->nic; if (nic == NULL) { GNIX_WARN(FI_LOG_EP_CTRL, "ep nic null for vc %p\n", vc); return -FI_EINVAL; } /* * move vc state to terminating */ vc->conn_state = GNIX_VC_CONN_TERMINATING; /* * try to unbind the gni_ep if non-NULL. * If there are SMSG or PostFMA/RDMA outstanding * wait here for them to complete */ if (vc->gni_ep != NULL) { while (status == GNI_RC_NOT_DONE) { fastlock_acquire(&nic->lock); status = GNI_EpUnbind(vc->gni_ep); fastlock_release(&nic->lock); if ((status != GNI_RC_NOT_DONE) && (status != GNI_RC_SUCCESS)) { GNIX_WARN(FI_LOG_EP_CTRL, "GNI_EpUnBind returned %s\n", gni_err_str[status]); break; } if (status == GNI_RC_NOT_DONE) _gnix_nic_progress(nic); } fastlock_acquire(&nic->lock); status = GNI_EpDestroy(vc->gni_ep); fastlock_release(&nic->lock); if (status != GNI_RC_SUCCESS) GNIX_WARN(FI_LOG_EP_CTRL, "GNI_EpDestroy returned %s\n", gni_err_str[status]); } /* * if the vc is in a nic's work queue, remove it */ __gnix_vc_cancel(vc); /* * We may eventually want to check the state of the VC, if we * implement true VC shutdown. if ((vc->conn_state != GNIX_VC_CONN_NONE) && (vc->conn_state != GNIX_VC_CONN_TERMINATED)) { GNIX_WARN(FI_LOG_EP_CTRL, "vc conn state %d\n", vc->conn_state); GNIX_WARN(FI_LOG_EP_CTRL, "vc conn state error\n"); return -FI_EBUSY; } */ /* * if send_q not empty, return -FI_EBUSY * Note for FI_EP_MSG type eps, this behavior * may not be correct for handling fi_shutdown. */ if (!slist_empty(&vc->tx_queue)) { GNIX_WARN(FI_LOG_EP_CTRL, "vc sendqueue not empty\n"); return -FI_EBUSY; } fastlock_destroy(&vc->tx_queue_lock); if (vc->smsg_mbox != NULL) { ret = _gnix_mbox_free(vc->smsg_mbox); if (ret != FI_SUCCESS) GNIX_WARN(FI_LOG_EP_CTRL, "_gnix_mbox_free returned %s\n", fi_strerror(-ret)); vc->smsg_mbox = NULL; } if (vc->dgram != NULL) { ret = _gnix_dgram_free(vc->dgram); if (ret != FI_SUCCESS) GNIX_WARN(FI_LOG_EP_CTRL, "_gnix_dgram_free returned %s\n", fi_strerror(-ret)); vc->dgram = NULL; } ret = _gnix_nic_free_rem_id(nic, vc->vc_id); if (ret != FI_SUCCESS) GNIX_WARN(FI_LOG_EP_CTRL, "__gnix_vc_free_id returned %s\n", fi_strerror(-ret)); _gnix_free_bitmap(&vc->flags); free(vc); return ret; }