LCOV - code coverage report
Current view: top level - lib/ftl/utils - ftl_mempool.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 52 131 39.7 %
Date: 2024-12-03 11:27:30 Functions: 7 15 46.7 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2022 Intel Corporation.
       3             :  *   All rights reserved.
       4             :  */
       5             : 
       6             : #include "spdk/stdinc.h"
       7             : #include "spdk/queue.h"
       8             : #include "spdk/util.h"
       9             : #include "spdk/env.h"
      10             : #include "spdk/likely.h"
      11             : 
      12             : #include "ftl_mempool.h"
      13             : #include "ftl_bitmap.h"
      14             : 
      15             : struct ftl_mempool_element {
      16             :         SLIST_ENTRY(ftl_mempool_element) entry;
      17             : };
      18             : 
      19             : struct ftl_mempool {
      20             :         SLIST_HEAD(, ftl_mempool_element) list;
      21             :         size_t element_size;
      22             :         void *buffer;
      23             :         size_t buffer_size;
      24             :         size_t count;
      25             :         size_t alignment;
      26             :         int socket_id;
      27             :         struct ftl_bitmap *inuse_bmp;
      28             :         void *inuse_buf;
      29             : };
      30             : 
      31             : static inline bool is_element_valid(struct ftl_mempool *mpool,
      32             :                                     void *element)  __attribute__((unused));
      33             : 
      34             : static inline bool ftl_mempool_is_initialized(struct ftl_mempool *mpool) __attribute__((unused));
      35             : 
      36             : static size_t
      37           1 : element_size_aligned(size_t size, size_t alignment)
      38             : {
      39           1 :         if (!alignment) {
      40           0 :                 return size;
      41             :         }
      42             : 
      43           1 :         if (size % alignment) {
      44           0 :                 return (size / alignment + 1) * alignment;
      45             :         }
      46             : 
      47           1 :         return size;
      48             : }
      49             : 
      50             : static inline bool
      51          32 : is_element_valid(struct ftl_mempool *mpool, void *element)
      52             : {
      53          32 :         if (element < mpool->buffer) {
      54           0 :                 return false;
      55             :         }
      56             : 
      57          32 :         if (element + mpool->element_size > mpool->buffer + mpool->buffer_size) {
      58           0 :                 return false;
      59             :         }
      60             : 
      61          32 :         if (!mpool->alignment) {
      62           0 :                 return true;
      63             :         }
      64             : 
      65          32 :         if ((size_t)element % mpool->alignment) {
      66           0 :                 return false;
      67             :         }
      68             : 
      69          32 :         if ((element - mpool->buffer) % mpool->element_size != 0) {
      70           0 :                 return false;
      71             :         }
      72             : 
      73          32 :         return true;
      74             : }
      75             : 
      76           2 : struct ftl_mempool *ftl_mempool_create(size_t count, size_t size,
      77             :                                        size_t alignment, int socket_id)
      78             : {
      79             :         struct ftl_mempool *mp;
      80             :         void *buffer;
      81             :         size_t i;
      82             : 
      83           2 :         assert(count > 0);
      84           2 :         assert(size > 0);
      85             : 
      86           2 :         if (!spdk_u64_is_pow2(alignment)) {
      87           1 :                 return NULL;
      88             :         }
      89             : 
      90           1 :         mp = calloc(1, sizeof(*mp));
      91           1 :         if (!mp) {
      92           0 :                 return NULL;
      93             :         }
      94             : 
      95           1 :         size = spdk_max(size, sizeof(struct ftl_mempool_element));
      96             : 
      97           1 :         mp->count = count;
      98           1 :         mp->element_size = element_size_aligned(size, alignment);
      99           1 :         mp->alignment = alignment;
     100           1 :         mp->socket_id = socket_id;
     101           1 :         SLIST_INIT(&mp->list);
     102             : 
     103           1 :         mp->buffer_size = mp->element_size * mp->count;
     104           1 :         mp->buffer = spdk_dma_malloc_socket(mp->buffer_size, mp->alignment,
     105             :                                             NULL, socket_id);
     106           1 :         if (!mp->buffer) {
     107           0 :                 free(mp);
     108           0 :                 return NULL;
     109             :         }
     110             : 
     111           1 :         buffer = mp->buffer;
     112          17 :         for (i = 0; i < count; i++, buffer += mp->element_size) {
     113          16 :                 struct ftl_mempool_element *el = buffer;
     114          16 :                 assert(is_element_valid(mp, el));
     115          16 :                 SLIST_INSERT_HEAD(&mp->list, el, entry);
     116             :         }
     117             : 
     118           1 :         return mp;
     119             : }
     120             : 
     121             : void
     122           1 : ftl_mempool_destroy(struct ftl_mempool *mpool)
     123             : {
     124           1 :         if (!mpool) {
     125           0 :                 return;
     126             :         }
     127             : 
     128           1 :         spdk_dma_free(mpool->buffer);
     129           1 :         free(mpool);
     130             : }
     131             : 
     132             : static inline bool
     133          33 : ftl_mempool_is_initialized(struct ftl_mempool *mpool)
     134             : {
     135          33 :         return mpool->inuse_buf == NULL;
     136             : }
     137             : 
     138             : void *
     139          17 : ftl_mempool_get(struct ftl_mempool *mpool)
     140             : {
     141             :         struct ftl_mempool_element *el;
     142             : 
     143          17 :         assert(ftl_mempool_is_initialized(mpool));
     144          17 :         if (spdk_unlikely(SLIST_EMPTY(&mpool->list))) {
     145           1 :                 return NULL;
     146             :         }
     147             : 
     148          16 :         el = SLIST_FIRST(&mpool->list);
     149          16 :         SLIST_REMOVE_HEAD(&mpool->list, entry);
     150             : 
     151          16 :         return el;
     152             : }
     153             : 
     154             : void
     155          16 : ftl_mempool_put(struct ftl_mempool *mpool, void *element)
     156             : {
     157          16 :         struct ftl_mempool_element *el = element;
     158             : 
     159          16 :         assert(ftl_mempool_is_initialized(mpool));
     160          16 :         assert(is_element_valid(mpool, element));
     161          16 :         SLIST_INSERT_HEAD(&mpool->list, el, entry);
     162          16 : }
     163             : 
     164             : struct ftl_mempool *
     165           0 : ftl_mempool_create_ext(void *buffer, size_t count, size_t size, size_t alignment)
     166             : {
     167             :         struct ftl_mempool *mp;
     168             :         size_t inuse_buf_sz;
     169             : 
     170           0 :         assert(buffer);
     171           0 :         assert(count > 0);
     172           0 :         assert(size > 0);
     173             : 
     174           0 :         mp = calloc(1, sizeof(*mp));
     175           0 :         if (!mp) {
     176           0 :                 goto error;
     177             :         }
     178             : 
     179           0 :         size = spdk_max(size, sizeof(struct ftl_mempool_element));
     180             : 
     181           0 :         mp->count = count;
     182           0 :         mp->element_size = element_size_aligned(size, alignment);
     183           0 :         mp->alignment = alignment;
     184           0 :         SLIST_INIT(&mp->list);
     185             : 
     186             :         /* Calculate underlying inuse_bmp's buf size */
     187           0 :         inuse_buf_sz = spdk_divide_round_up(mp->count, 8);
     188             :         /* The bitmap size must be a multiple of word size (8b) - round up */
     189           0 :         if (inuse_buf_sz & 7UL) {
     190           0 :                 inuse_buf_sz &= ~7UL;
     191           0 :                 inuse_buf_sz += 8;
     192             :         }
     193             : 
     194           0 :         mp->inuse_buf = calloc(1, inuse_buf_sz);
     195           0 :         if (!mp->inuse_buf) {
     196           0 :                 goto error;
     197             :         }
     198             : 
     199           0 :         mp->inuse_bmp = ftl_bitmap_create(mp->inuse_buf, inuse_buf_sz);
     200           0 :         if (!mp->inuse_bmp) {
     201           0 :                 goto error;
     202             :         }
     203             : 
     204             :         /* Map the buffer */
     205           0 :         mp->buffer_size = mp->element_size * mp->count;
     206           0 :         mp->buffer = buffer;
     207             : 
     208           0 :         return mp;
     209             : 
     210           0 : error:
     211           0 :         ftl_mempool_destroy_ext(mp);
     212           0 :         return NULL;
     213             : }
     214             : 
     215             : void
     216           0 : ftl_mempool_destroy_ext(struct ftl_mempool *mpool)
     217             : {
     218           0 :         if (!mpool) {
     219           0 :                 return;
     220             :         }
     221             : 
     222           0 :         if (mpool->inuse_bmp) {
     223           0 :                 ftl_bitmap_destroy(mpool->inuse_bmp);
     224             :         }
     225           0 :         free(mpool->inuse_buf);
     226           0 :         free(mpool);
     227             : }
     228             : 
     229             : void
     230           0 : ftl_mempool_initialize_ext(struct ftl_mempool *mpool)
     231             : {
     232             :         struct ftl_mempool_element *el;
     233           0 :         void *buffer = mpool->buffer;
     234             :         size_t i;
     235             : 
     236           0 :         assert(!ftl_mempool_is_initialized(mpool));
     237             : 
     238           0 :         for (i = 0; i < mpool->count; i++, buffer += mpool->element_size) {
     239           0 :                 if (ftl_bitmap_get(mpool->inuse_bmp, i)) {
     240           0 :                         continue;
     241             :                 }
     242           0 :                 el = buffer;
     243           0 :                 assert(is_element_valid(mpool, el));
     244           0 :                 SLIST_INSERT_HEAD(&mpool->list, el, entry);
     245             :         }
     246             : 
     247           0 :         ftl_bitmap_destroy(mpool->inuse_bmp);
     248           0 :         mpool->inuse_bmp = NULL;
     249             : 
     250           0 :         free(mpool->inuse_buf);
     251           0 :         mpool->inuse_buf = NULL;
     252           0 : }
     253             : 
     254             : ftl_df_obj_id
     255           0 : ftl_mempool_get_df_obj_id(struct ftl_mempool *mpool, void *df_obj_ptr)
     256             : {
     257           0 :         return ftl_df_get_obj_id(mpool->buffer, df_obj_ptr);
     258             : }
     259             : 
     260             : size_t
     261           0 : ftl_mempool_get_df_obj_index(struct ftl_mempool *mpool, void *df_obj_ptr)
     262             : {
     263           0 :         return ftl_mempool_get_df_obj_id(mpool, df_obj_ptr) / mpool->element_size;
     264             : }
     265             : 
     266             : void *
     267           0 : ftl_mempool_get_df_ptr(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
     268             : {
     269           0 :         return ftl_df_get_obj_ptr(mpool->buffer, df_obj_id);
     270             : }
     271             : 
     272             : void *
     273           0 : ftl_mempool_claim_df(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
     274             : {
     275           0 :         struct ftl_mempool_element *el = ftl_df_get_obj_ptr(mpool->buffer, df_obj_id);
     276             : 
     277           0 :         assert(!ftl_mempool_is_initialized(mpool));
     278           0 :         assert(df_obj_id % mpool->element_size == 0);
     279           0 :         assert(df_obj_id / mpool->element_size < mpool->count);
     280             : 
     281           0 :         ftl_bitmap_set(mpool->inuse_bmp, df_obj_id / mpool->element_size);
     282           0 :         return el;
     283             : }
     284             : 
     285             : void
     286           0 : ftl_mempool_release_df(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
     287             : {
     288           0 :         assert(!ftl_mempool_is_initialized(mpool));
     289           0 :         assert(df_obj_id % mpool->element_size == 0);
     290           0 :         assert(df_obj_id / mpool->element_size < mpool->count);
     291             : 
     292           0 :         ftl_bitmap_clear(mpool->inuse_bmp, df_obj_id / mpool->element_size);
     293           0 : }

Generated by: LCOV version 1.15