Branch data 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 : 269 : element_size_aligned(size_t size, size_t alignment)
38 : : {
39 [ - + ]: 269 : if (!alignment) {
40 : 0 : return size;
41 : : }
42 : :
43 [ - + + + ]: 269 : if (size % alignment) {
44 [ - + ]: 27 : return (size / alignment + 1) * alignment;
45 : : }
46 : :
47 : 242 : return size;
48 : : }
49 : :
50 : : static inline bool
51 : 12089553 : is_element_valid(struct ftl_mempool *mpool, void *element)
52 : : {
53 [ - + ]: 12089553 : if (element < mpool->buffer) {
54 : 0 : return false;
55 : : }
56 : :
57 [ - + ]: 12089553 : if (element + mpool->element_size > mpool->buffer + mpool->buffer_size) {
58 : 0 : return false;
59 : : }
60 : :
61 [ - + ]: 12089553 : if (!mpool->alignment) {
62 : 0 : return true;
63 : : }
64 : :
65 [ - + - + ]: 12089553 : if ((size_t)element % mpool->alignment) {
66 : 0 : return false;
67 : : }
68 : :
69 [ - + - + ]: 12089553 : if ((element - mpool->buffer) % mpool->element_size != 0) {
70 : 0 : return false;
71 : : }
72 : :
73 : 12089553 : return true;
74 : : }
75 : :
76 : 221 : 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 [ - + ]: 221 : assert(count > 0);
84 [ - + ]: 221 : assert(size > 0);
85 : :
86 [ + + ]: 221 : if (!spdk_u64_is_pow2(alignment)) {
87 : 6 : return NULL;
88 : : }
89 : :
90 : 215 : mp = calloc(1, sizeof(*mp));
91 [ - + ]: 215 : if (!mp) {
92 : 0 : return NULL;
93 : : }
94 : :
95 : 215 : size = spdk_max(size, sizeof(struct ftl_mempool_element));
96 : :
97 : 215 : mp->count = count;
98 : 215 : mp->element_size = element_size_aligned(size, alignment);
99 : 215 : mp->alignment = alignment;
100 : 215 : mp->socket_id = socket_id;
101 : 215 : SLIST_INIT(&mp->list);
102 : :
103 : 215 : mp->buffer_size = mp->element_size * mp->count;
104 : 215 : mp->buffer = spdk_dma_malloc_socket(mp->buffer_size, mp->alignment,
105 : : NULL, socket_id);
106 [ - + ]: 215 : if (!mp->buffer) {
107 : 0 : free(mp);
108 : 0 : return NULL;
109 : : }
110 : :
111 : 215 : buffer = mp->buffer;
112 [ + + ]: 1037409 : for (i = 0; i < count; i++, buffer += mp->element_size) {
113 : 1037194 : struct ftl_mempool_element *el = buffer;
114 [ - + ]: 1037194 : assert(is_element_valid(mp, el));
115 : 1037194 : SLIST_INSERT_HEAD(&mp->list, el, entry);
116 : : }
117 : :
118 : 215 : return mp;
119 : : }
120 : :
121 : : void
122 : 215 : ftl_mempool_destroy(struct ftl_mempool *mpool)
123 : : {
124 [ - + ]: 215 : if (!mpool) {
125 : 0 : return;
126 : : }
127 : :
128 : 215 : spdk_dma_free(mpool->buffer);
129 : 215 : free(mpool);
130 : : }
131 : :
132 : : static inline bool
133 : 21706876 : ftl_mempool_is_initialized(struct ftl_mempool *mpool)
134 : : {
135 : 21706876 : return mpool->inuse_buf == NULL;
136 : : }
137 : :
138 : : void *
139 : 10852857 : ftl_mempool_get(struct ftl_mempool *mpool)
140 : : {
141 : : struct ftl_mempool_element *el;
142 : :
143 [ - + ]: 10852857 : assert(ftl_mempool_is_initialized(mpool));
144 [ + + ]: 10852857 : if (spdk_unlikely(SLIST_EMPTY(&mpool->list))) {
145 : 6 : return NULL;
146 : : }
147 : :
148 : 10852851 : el = SLIST_FIRST(&mpool->list);
149 : 10852851 : SLIST_REMOVE_HEAD(&mpool->list, entry);
150 : :
151 : 10852851 : return el;
152 : : }
153 : :
154 : : void
155 : 10852761 : ftl_mempool_put(struct ftl_mempool *mpool, void *element)
156 : : {
157 : 10852761 : struct ftl_mempool_element *el = element;
158 : :
159 [ - + ]: 10852761 : assert(ftl_mempool_is_initialized(mpool));
160 [ - + ]: 10852761 : assert(is_element_valid(mpool, element));
161 : 10852761 : SLIST_INSERT_HEAD(&mpool->list, el, entry);
162 : 10852761 : }
163 : :
164 : : struct ftl_mempool *
165 : 54 : 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 [ - + ]: 54 : assert(buffer);
171 [ - + ]: 54 : assert(count > 0);
172 [ - + ]: 54 : assert(size > 0);
173 : :
174 : 54 : mp = calloc(1, sizeof(*mp));
175 [ - + ]: 54 : if (!mp) {
176 : 0 : goto error;
177 : : }
178 : :
179 : 54 : size = spdk_max(size, sizeof(struct ftl_mempool_element));
180 : :
181 : 54 : mp->count = count;
182 : 54 : mp->element_size = element_size_aligned(size, alignment);
183 : 54 : mp->alignment = alignment;
184 : 54 : SLIST_INIT(&mp->list);
185 : :
186 : : /* Calculate underlying inuse_bmp's buf size */
187 : 54 : 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 [ + + ]: 54 : if (inuse_buf_sz & 7UL) {
190 : 42 : inuse_buf_sz &= ~7UL;
191 : 42 : inuse_buf_sz += 8;
192 : : }
193 : :
194 : 54 : mp->inuse_buf = calloc(1, inuse_buf_sz);
195 [ - + ]: 54 : if (!mp->inuse_buf) {
196 : 0 : goto error;
197 : : }
198 : :
199 : 54 : mp->inuse_bmp = ftl_bitmap_create(mp->inuse_buf, inuse_buf_sz);
200 [ - + ]: 54 : if (!mp->inuse_bmp) {
201 : 0 : goto error;
202 : : }
203 : :
204 : : /* Map the buffer */
205 : 54 : mp->buffer_size = mp->element_size * mp->count;
206 : 54 : mp->buffer = buffer;
207 : :
208 : 54 : return mp;
209 : :
210 : 0 : error:
211 : 0 : ftl_mempool_destroy_ext(mp);
212 : 0 : return NULL;
213 : : }
214 : :
215 : : void
216 : 54 : ftl_mempool_destroy_ext(struct ftl_mempool *mpool)
217 : : {
218 [ - + ]: 54 : if (!mpool) {
219 : 0 : return;
220 : : }
221 : :
222 [ - + ]: 54 : if (mpool->inuse_bmp) {
223 : 0 : ftl_bitmap_destroy(mpool->inuse_bmp);
224 : : }
225 : 54 : free(mpool->inuse_buf);
226 : 54 : free(mpool);
227 : : }
228 : :
229 : : void
230 : 54 : ftl_mempool_initialize_ext(struct ftl_mempool *mpool)
231 : : {
232 : : struct ftl_mempool_element *el;
233 : 54 : void *buffer = mpool->buffer;
234 : : size_t i;
235 : :
236 [ - + ]: 54 : assert(!ftl_mempool_is_initialized(mpool));
237 : :
238 [ + + ]: 200856 : for (i = 0; i < mpool->count; i++, buffer += mpool->element_size) {
239 [ + + ]: 200802 : if (ftl_bitmap_get(mpool->inuse_bmp, i)) {
240 : 1204 : continue;
241 : : }
242 : 199598 : el = buffer;
243 [ - + ]: 199598 : assert(is_element_valid(mpool, el));
244 : 199598 : SLIST_INSERT_HEAD(&mpool->list, el, entry);
245 : : }
246 : :
247 : 54 : ftl_bitmap_destroy(mpool->inuse_bmp);
248 : 54 : mpool->inuse_bmp = NULL;
249 : :
250 : 54 : free(mpool->inuse_buf);
251 : 54 : mpool->inuse_buf = NULL;
252 : 54 : }
253 : :
254 : : ftl_df_obj_id
255 : 248896 : ftl_mempool_get_df_obj_id(struct ftl_mempool *mpool, void *df_obj_ptr)
256 : : {
257 : 248896 : return ftl_df_get_obj_id(mpool->buffer, df_obj_ptr);
258 : : }
259 : :
260 : : size_t
261 : 124443 : ftl_mempool_get_df_obj_index(struct ftl_mempool *mpool, void *df_obj_ptr)
262 : : {
263 [ - + ]: 124443 : return ftl_mempool_get_df_obj_id(mpool, df_obj_ptr) / mpool->element_size;
264 : : }
265 : :
266 : : void *
267 : 27863097 : ftl_mempool_get_df_ptr(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
268 : : {
269 : 27863097 : return ftl_df_get_obj_ptr(mpool->buffer, df_obj_id);
270 : : }
271 : :
272 : : void *
273 : 1204 : ftl_mempool_claim_df(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
274 : : {
275 : 1204 : struct ftl_mempool_element *el = ftl_df_get_obj_ptr(mpool->buffer, df_obj_id);
276 : :
277 [ - + ]: 1204 : assert(!ftl_mempool_is_initialized(mpool));
278 [ - + - + ]: 1204 : assert(df_obj_id % mpool->element_size == 0);
279 [ - + - + ]: 1204 : assert(df_obj_id / mpool->element_size < mpool->count);
280 : :
281 [ - + ]: 1204 : ftl_bitmap_set(mpool->inuse_bmp, df_obj_id / mpool->element_size);
282 : 1204 : 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 : }
|