// SPDX-License-Identifier: GPL-2.0 or OpenIB.org BSD (MIT) See COPYING file // Authors: Cheng Xu // Copyright (c) 2020-2021, Alibaba Group. #include #include #include #include #include #include "erdma.h" #include "erdma_db.h" #define ERDMA_DBREC_SIZE 16 struct erdma_dbrecord_page { struct list_node list; void *page_buf; uint32_t cnt; uint32_t used; unsigned long *bitmap; }; uint64_t *erdma_alloc_dbrecords(struct erdma_context *ctx) { struct erdma_dbrecord_page *page = NULL; uint32_t free_idx, dbrecords_per_page; uint64_t *db_records = NULL; int rv; pthread_mutex_lock(&ctx->dbrecord_pages_mutex); list_for_each(&ctx->dbrecord_pages_list, page, list) if (page->used < page->cnt) goto found; dbrecords_per_page = ctx->page_size / ERDMA_DBREC_SIZE; page = calloc(1, sizeof(*page)); if (!page) goto err_out; page->bitmap = bitmap_alloc1(dbrecords_per_page); if (!page->bitmap) goto err_bitmap; rv = posix_memalign(&page->page_buf, ctx->page_size, ctx->page_size); if (rv) goto err_alloc; page->cnt = dbrecords_per_page; page->used = 0; list_node_init(&page->list); list_add_tail(&ctx->dbrecord_pages_list, &page->list); found: ++page->used; free_idx = bitmap_find_first_bit(page->bitmap, 0, page->cnt); bitmap_clear_bit(page->bitmap, free_idx); db_records = page->page_buf + free_idx * ERDMA_DBREC_SIZE; pthread_mutex_unlock(&ctx->dbrecord_pages_mutex); return db_records; err_alloc: free(page->bitmap); err_bitmap: free(page); err_out: pthread_mutex_unlock(&ctx->dbrecord_pages_mutex); return NULL; } void erdma_dealloc_dbrecords(struct erdma_context *ctx, uint64_t *dbrec) { uint32_t page_mask = ~(ctx->page_size - 1); struct erdma_dbrecord_page *page; uint32_t idx; pthread_mutex_lock(&ctx->dbrecord_pages_mutex); list_for_each(&ctx->dbrecord_pages_list, page, list) if (((uintptr_t)dbrec & page_mask) == (uintptr_t)page->page_buf) goto found; goto out; found: idx = ((uintptr_t)dbrec - (uintptr_t)page->page_buf) / ERDMA_DBREC_SIZE; bitmap_set_bit(page->bitmap, idx); page->used--; if (!page->used) { list_del(&page->list); free(page->bitmap); free(page); } out: pthread_mutex_unlock(&ctx->dbrecord_pages_mutex); }