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 : 266 : element_size_aligned(size_t size, size_t alignment)
38 : : {
39 [ - + ]: 266 : if (!alignment) {
40 : 0 : return size;
41 : : }
42 : :
43 [ - + + + ]: 266 : if (size % alignment) {
44 [ - + ]: 27 : return (size / alignment + 1) * alignment;
45 : : }
46 : :
47 : 239 : return size;
48 : 0 : }
49 : :
50 : : static inline bool
51 : 12192031 : is_element_valid(struct ftl_mempool *mpool, void *element)
52 : : {
53 [ - + # # : 12192031 : if (element < mpool->buffer) {
# # ]
54 : 0 : return false;
55 : : }
56 : :
57 [ - + # # : 12192031 : if (element + mpool->element_size > mpool->buffer + mpool->buffer_size) {
# # # # #
# # # #
# ]
58 : 0 : return false;
59 : : }
60 : :
61 [ - + # # : 12192031 : if (!mpool->alignment) {
# # ]
62 : 0 : return true;
63 : : }
64 : :
65 [ - + - + : 12192031 : if ((size_t)element % mpool->alignment) {
# # # # ]
66 : 0 : return false;
67 : : }
68 : :
69 [ - + - + : 12192031 : if ((element - mpool->buffer) % mpool->element_size != 0) {
# # # # #
# # # ]
70 : 0 : return false;
71 : : }
72 : :
73 : 12192031 : return true;
74 : 0 : }
75 : :
76 : 215 : 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 [ - + # # ]: 215 : assert(count > 0);
84 [ - + # # ]: 215 : assert(size > 0);
85 : :
86 [ + + ]: 215 : if (!spdk_u64_is_pow2(alignment)) {
87 : 3 : return NULL;
88 : : }
89 : :
90 : 212 : mp = calloc(1, sizeof(*mp));
91 [ - + ]: 212 : if (!mp) {
92 : 0 : return NULL;
93 : : }
94 : :
95 [ # # ]: 212 : size = spdk_max(size, sizeof(struct ftl_mempool_element));
96 : :
97 [ # # # # ]: 212 : mp->count = count;
98 [ # # # # ]: 212 : mp->element_size = element_size_aligned(size, alignment);
99 [ # # # # ]: 212 : mp->alignment = alignment;
100 [ # # # # ]: 212 : mp->socket_id = socket_id;
101 [ # # # # : 212 : SLIST_INIT(&mp->list);
# # ]
102 : :
103 [ # # # # : 212 : mp->buffer_size = mp->element_size * mp->count;
# # # # #
# # # ]
104 [ # # # # : 212 : mp->buffer = spdk_dma_malloc_socket(mp->buffer_size, mp->alignment,
# # # # #
# # # #
# ]
105 : 0 : NULL, socket_id);
106 [ - + # # : 212 : if (!mp->buffer) {
# # ]
107 : 0 : free(mp);
108 : 0 : return NULL;
109 : : }
110 : :
111 [ # # # # ]: 212 : buffer = mp->buffer;
112 [ + + # # : 1037466 : for (i = 0; i < count; i++, buffer += mp->element_size) {
# # ]
113 : 1037254 : struct ftl_mempool_element *el = buffer;
114 [ - + # # ]: 1037254 : assert(is_element_valid(mp, el));
115 [ # # # # : 1037254 : SLIST_INSERT_HEAD(&mp->list, el, entry);
# # # # #
# # # # #
# # # # ]
116 : 0 : }
117 : :
118 : 212 : return mp;
119 : 0 : }
120 : :
121 : : void
122 : 212 : ftl_mempool_destroy(struct ftl_mempool *mpool)
123 : : {
124 [ - + ]: 212 : if (!mpool) {
125 : 0 : return;
126 : : }
127 : :
128 [ # # # # ]: 212 : spdk_dma_free(mpool->buffer);
129 : 212 : free(mpool);
130 : 0 : }
131 : :
132 : : static inline bool
133 : 21911733 : ftl_mempool_is_initialized(struct ftl_mempool *mpool)
134 : : {
135 [ # # # # ]: 21911733 : return mpool->inuse_buf == NULL;
136 : : }
137 : :
138 : : void *
139 : 10955296 : ftl_mempool_get(struct ftl_mempool *mpool)
140 : : {
141 : : struct ftl_mempool_element *el;
142 : :
143 [ - + # # ]: 10955296 : assert(ftl_mempool_is_initialized(mpool));
144 [ + + # # : 10955296 : if (spdk_unlikely(SLIST_EMPTY(&mpool->list))) {
# # # # ]
145 : 3 : return NULL;
146 : : }
147 : :
148 [ # # # # : 10955293 : el = SLIST_FIRST(&mpool->list);
# # ]
149 [ # # # # : 10955293 : SLIST_REMOVE_HEAD(&mpool->list, entry);
# # # # #
# # # # #
# # # # ]
150 : :
151 : 10955293 : return el;
152 : 0 : }
153 : :
154 : : void
155 : 10955179 : ftl_mempool_put(struct ftl_mempool *mpool, void *element)
156 : : {
157 : 10955179 : struct ftl_mempool_element *el = element;
158 : :
159 [ - + # # ]: 10955179 : assert(ftl_mempool_is_initialized(mpool));
160 [ - + # # ]: 10955179 : assert(is_element_valid(mpool, element));
161 [ # # # # : 10955179 : SLIST_INSERT_HEAD(&mpool->list, el, entry);
# # # # #
# # # # #
# # # # ]
162 : 10955179 : }
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 : 0 : }
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 : 0 : }
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 : 0 : }
225 [ # # # # ]: 54 : free(mpool->inuse_buf);
226 : 54 : free(mpool);
227 : 0 : }
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 : 0 : }
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 : 272546 : ftl_mempool_get_df_obj_id(struct ftl_mempool *mpool, void *df_obj_ptr)
256 : : {
257 [ # # # # ]: 272546 : return ftl_df_get_obj_id(mpool->buffer, df_obj_ptr);
258 : : }
259 : :
260 : : size_t
261 : 136268 : ftl_mempool_get_df_obj_index(struct ftl_mempool *mpool, void *df_obj_ptr)
262 : : {
263 [ - + # # : 136268 : return ftl_mempool_get_df_obj_id(mpool, df_obj_ptr) / mpool->element_size;
# # ]
264 : : }
265 : :
266 : : void *
267 : 28237398 : ftl_mempool_get_df_ptr(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
268 : : {
269 [ # # # # ]: 28237398 : 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 : }
|