blob: 503b6ccf4876dffb57f6826a983df7e7c5c65c0c [file]
// SPDX-License-Identifier: GPL-2.0 or OpenIB.org BSD (MIT) See COPYING file
// Authors: Cheng Xu <chengyou@linux.alibaba.com>
// Copyright (c) 2020-2021, Alibaba Group.
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <util/bitmap.h>
#include <util/util.h>
#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);
}