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); }
/** * Fill all of the fields of an mbox to be returned to the requester. * * @param[in] handle Handle to the allocator being used. * @param[in] slab Slab which the mbox is allocated from. * @param[in] position Position of the mbox in the slab. * @param[out] ptr Contains the allocated mbox upon success. * * @return FI_SUCCESS Upon successfully filling an mbox with relevant data. * @return -FI_EINVAL Upon receiving invalid input, or finding the bitmap in * a corrupted state. * @return -FI_ENOMEM Upon failure to create the mbox structure using calloc. */ static int __fill_mbox(struct gnix_mbox_alloc_handle *handle, struct gnix_slab *slab, size_t position, struct gnix_mbox **ptr) { struct gnix_mbox *out; int ret = FI_SUCCESS; char error_buf[256]; size_t mapped_size; char *error; out = calloc(1, sizeof(*out)); if (!out) { error = strerror_r(errno, error_buf, sizeof(error_buf)); GNIX_WARN(FI_LOG_EP_CTRL, "Error allocating mbox: %s\n", error); ret = -FI_ENOMEM; goto err_mbox_calloc; } mapped_size = handle->page_size * __page_count(handle); out->slab = slab; out->base = slab->base; out->offset = (position * handle->mbox_size); out->memory_handle = &slab->memory_handle; if (out->offset > mapped_size) { GNIX_WARN(FI_LOG_EP_CTRL, "Mbox out of bounds.\n"); ret = -FI_EINVAL; goto err_invalid; } /* On some systems, the page may not be zero'd from first use. Memset it here */ memset((void *) ((uint64_t) out->base + out->offset), 0x0, handle->mbox_size); ret = _gnix_test_and_set_bit(slab->used, position); if (ret != 0) { GNIX_WARN(FI_LOG_EP_CTRL, "Bit already set when creating mbox.\n"); ret = -FI_EINVAL; goto err_invalid; } *ptr = out; return ret; err_invalid: free(out); err_mbox_calloc: return ret; }
/* Schedule the VC for RX progress. */ int _gnix_vc_rx_schedule(struct gnix_vc *vc) { struct gnix_nic *nic = vc->ep->nic; if (!_gnix_test_and_set_bit(&vc->flags, GNIX_VC_FLAG_RX_SCHEDULED)) { fastlock_acquire(&nic->rx_vc_lock); dlist_insert_tail(&vc->rx_list, &nic->rx_vcs); fastlock_release(&nic->rx_vc_lock); GNIX_INFO(FI_LOG_EP_CTRL, "Scheduled RX VC (%p)\n", vc); } return FI_SUCCESS; }
/* Schedule the VC for work progress. */ static int __gnix_vc_work_schedule(struct gnix_vc *vc) { struct gnix_nic *nic = vc->ep->nic; /* Don't bother scheduling if there's no work to do. */ if (slist_empty(&vc->work_queue)) return FI_SUCCESS; if (!_gnix_test_and_set_bit(&vc->flags, GNIX_VC_FLAG_WORK_SCHEDULED)) { fastlock_acquire(&nic->work_vc_lock); dlist_insert_tail(&vc->work_list, &nic->work_vcs); fastlock_release(&nic->work_vc_lock); GNIX_INFO(FI_LOG_EP_CTRL, "Scheduled work VC (%p)\n", vc); } return FI_SUCCESS; }