Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2017 Intel Corporation. All rights reserved.
3 : * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
4 : */
5 :
6 : /** \file
7 : * General utility functions
8 : */
9 :
10 : #ifndef SPDK_UTIL_H
11 : #define SPDK_UTIL_H
12 :
13 : /* memset_s is only available if __STDC_WANT_LIB_EXT1__ is set to 1 before including \<string.h\> */
14 : #define __STDC_WANT_LIB_EXT1__ 1
15 :
16 : #include "spdk/stdinc.h"
17 :
18 : #ifdef __cplusplus
19 : extern "C" {
20 : #endif
21 :
22 : #define SPDK_CACHE_LINE_SIZE 64
23 :
24 : #define spdk_min(a,b) (((a)<(b))?(a):(b))
25 : #define spdk_max(a,b) (((a)>(b))?(a):(b))
26 :
27 : #define SPDK_COUNTOF(arr) (sizeof(arr) / sizeof((arr)[0]))
28 :
29 : #define SPDK_CONTAINEROF(ptr, type, member) ((type *)((uintptr_t)ptr - offsetof(type, member)))
30 :
31 : /** Returns size of an object pointer by ptr up to and including member */
32 : #define SPDK_SIZEOF(ptr, member) (offsetof(__typeof__(*(ptr)), member) + sizeof((ptr)->member))
33 :
34 : /**
35 : * Get the size of a member of a struct.
36 : */
37 : #define SPDK_SIZEOF_MEMBER(type, member) (sizeof(((type *)0)->member))
38 :
39 : #define SPDK_SEC_TO_USEC 1000000ULL
40 : #define SPDK_SEC_TO_NSEC 1000000000ULL
41 :
42 : /* Ceiling division of unsigned integers */
43 : #define SPDK_CEIL_DIV(x,y) (((x)+(y)-1)/(y))
44 :
45 : /**
46 : * Macro to align a value to a given power-of-two. The resultant value
47 : * will be of the same type as the first parameter, and will be no
48 : * bigger than the first parameter. Second parameter must be a
49 : * power-of-two value.
50 : */
51 : #define SPDK_ALIGN_FLOOR(val, align) \
52 : (__typeof__(val))((val) & (~((__typeof__(val))((align) - 1))))
53 : /**
54 : * Macro to align a value to a given power-of-two. The resultant value
55 : * will be of the same type as the first parameter, and will be no lower
56 : * than the first parameter. Second parameter must be a power-of-two
57 : * value.
58 : */
59 : #define SPDK_ALIGN_CEIL(val, align) \
60 : SPDK_ALIGN_FLOOR(((val) + ((__typeof__(val)) (align) - 1)), align)
61 :
62 : uint32_t spdk_u32log2(uint32_t x);
63 :
64 : static inline uint32_t
65 209702 : spdk_align32pow2(uint32_t x)
66 : {
67 209702 : return 1u << (1 + spdk_u32log2(x - 1));
68 : }
69 :
70 : uint64_t spdk_u64log2(uint64_t x);
71 :
72 : static inline uint64_t
73 34374 : spdk_align64pow2(uint64_t x)
74 : {
75 34374 : return 1ULL << (1 + spdk_u64log2(x - 1));
76 : }
77 :
78 : /**
79 : * Check if a uint32_t is a power of 2.
80 : */
81 : static inline bool
82 1274 : spdk_u32_is_pow2(uint32_t x)
83 : {
84 1274 : if (x == 0) {
85 0 : return false;
86 : }
87 :
88 1274 : return (x & (x - 1)) == 0;
89 : }
90 :
91 : /**
92 : * Check if a uint64_t is a power of 2.
93 : */
94 : static inline bool
95 3 : spdk_u64_is_pow2(uint64_t x)
96 : {
97 3 : if (x == 0) {
98 0 : return false;
99 : }
100 :
101 3 : return (x & (x - 1)) == 0;
102 : }
103 :
104 : static inline uint64_t
105 7669 : spdk_divide_round_up(uint64_t num, uint64_t divisor)
106 : {
107 7669 : return (num + divisor - 1) / divisor;
108 : }
109 :
110 : struct spdk_single_ioviter {
111 : struct iovec *iov;
112 : size_t iovcnt;
113 : size_t idx;
114 : size_t iov_len;
115 : uint8_t *iov_base;
116 : };
117 :
118 : /**
119 : * An N-way iovec iterator. Calculate the size, given N, using
120 : * SPDK_IOVITER_SIZE. For backward compatibility, the structure
121 : * has a default size of 2 iovecs.
122 : */
123 : struct spdk_ioviter {
124 : uint32_t count;
125 :
126 : union {
127 : struct spdk_single_ioviter iters_compat[2];
128 : struct spdk_single_ioviter iters[0];
129 : };
130 : };
131 :
132 : /* count must be greater than or equal to 2 */
133 : #define SPDK_IOVITER_SIZE(count) (sizeof(struct spdk_single_ioviter) * (count - 2) + sizeof(struct spdk_ioviter))
134 :
135 : /**
136 : * Initialize and move to the first common segment of the two given
137 : * iovecs. See spdk_ioviter_next().
138 : */
139 : size_t spdk_ioviter_first(struct spdk_ioviter *iter,
140 : struct iovec *siov, size_t siovcnt,
141 : struct iovec *diov, size_t diovcnt,
142 : void **src, void **dst);
143 :
144 : /**
145 : * Initialize and move to the first common segment of the N given
146 : * iovecs. See spdk_ioviter_nextv().
147 : */
148 : size_t spdk_ioviter_firstv(struct spdk_ioviter *iter,
149 : uint32_t count,
150 : struct iovec **iov,
151 : size_t *iovcnt,
152 : void **out);
153 :
154 : /**
155 : * Move to the next segment in the iterator.
156 : *
157 : * This will iterate through the segments of the source and destination
158 : * and return the individual segments, one by one. For example, if the
159 : * source consists of one element of length 4k and the destination
160 : * consists of 4 elements each of length 1k, this function will return
161 : * 4 1k src+dst pairs of buffers, and then return 0 bytes to indicate
162 : * the iteration is complete on the fifth call.
163 : */
164 : size_t spdk_ioviter_next(struct spdk_ioviter *iter, void **src, void **dst);
165 :
166 : /**
167 : * Move to the next segment in the iterator.
168 : *
169 : * This will iterate through the segments of the iovecs in the iterator
170 : * and return the individual segments, one by one. For example, if the
171 : * set consists one iovec of one element of length 4k and another iovec
172 : * of 4 elements each of length 1k, this function will return
173 : * 4 1k pairs of buffers, and then return 0 bytes to indicate
174 : * the iteration is complete on the fifth call.
175 : */
176 : size_t spdk_ioviter_nextv(struct spdk_ioviter *iter, void **out);
177 :
178 : /**
179 : * Operate like memset across an iovec.
180 : */
181 : void
182 : spdk_iov_memset(struct iovec *iovs, int iovcnt, int c);
183 :
184 : /**
185 : * Initialize an iovec with just the single given buffer.
186 : */
187 : void
188 : spdk_iov_one(struct iovec *iov, int *iovcnt, void *buf, size_t buflen);
189 :
190 : #define SPDK_IOV_ONE(piov, piovcnt, buf, buflen) do { \
191 : (piov)->iov_base = (buf); \
192 : (piov)->iov_len = (buflen); \
193 : *(piovcnt) = 1; \
194 : } while (0)
195 :
196 : /**
197 : * Copy the data described by the source iovec to the destination iovec.
198 : *
199 : * \return The number of bytes copied.
200 : */
201 : size_t spdk_iovcpy(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt);
202 :
203 : /**
204 : * Same as spdk_iovcpy(), but the src/dst buffers might overlap.
205 : *
206 : * \return The number of bytes copied.
207 : */
208 : size_t spdk_iovmove(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt);
209 :
210 : /**
211 : * Transfer state for iterative copying in or out of an iovec.
212 : */
213 : struct spdk_iov_xfer {
214 : struct iovec *iovs;
215 : int iovcnt;
216 : int cur_iov_idx;
217 : size_t cur_iov_offset;
218 : };
219 :
220 : /**
221 : * Initialize a transfer context to point to the given iovec.
222 : */
223 : void
224 : spdk_iov_xfer_init(struct spdk_iov_xfer *ix, struct iovec *iovs, int iovcnt);
225 :
226 : /**
227 : * Copy from the given buf up to buf_len bytes, into the given ix iovec
228 : * iterator, advancing the iterator as needed.. Returns the number of bytes
229 : * copied.
230 : */
231 : size_t
232 : spdk_iov_xfer_from_buf(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len);
233 :
234 : /**
235 : * Copy from the given ix iovec iterator into the given buf up to buf_len
236 : * bytes, advancing the iterator as needed. Returns the number of bytes copied.
237 : */
238 : size_t
239 : spdk_iov_xfer_to_buf(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len);
240 :
241 : /**
242 : * Copy iovs contents to buf through memcpy.
243 : */
244 : void spdk_copy_iovs_to_buf(void *buf, size_t buf_len, struct iovec *iovs,
245 : int iovcnt);
246 :
247 : /**
248 : * Copy buf contents to iovs through memcpy.
249 : */
250 : void spdk_copy_buf_to_iovs(struct iovec *iovs, int iovcnt, void *buf,
251 : size_t buf_len);
252 :
253 : /**
254 : * Scan build is really pessimistic and assumes that mempool functions can
255 : * dequeue NULL buffers even if they return success. This is obviously a false
256 : * positive, but the mempool dequeue can be done in a DPDK inline function that
257 : * we can't decorate with usual assert(buf != NULL). Instead, we'll
258 : * preinitialize the dequeued buffer array with some dummy objects.
259 : */
260 : #define SPDK_CLANG_ANALYZER_PREINIT_PTR_ARRAY(arr, arr_size, buf_size) \
261 : do { \
262 : static char dummy_buf[buf_size]; \
263 : int i; \
264 : for (i = 0; i < arr_size; i++) { \
265 : arr[i] = (void *)dummy_buf; \
266 : } \
267 : } while (0)
268 :
269 : /**
270 : * Add two sequence numbers s1 and s2
271 : *
272 : * \param s1 First sequence number
273 : * \param s2 Second sequence number
274 : *
275 : * \return Sum of s1 and s2 based on serial number arithmetic.
276 : */
277 : static inline uint32_t
278 5 : spdk_sn32_add(uint32_t s1, uint32_t s2)
279 : {
280 5 : return (uint32_t)(s1 + s2);
281 : }
282 :
283 : #define SPDK_SN32_CMPMAX (1U << (32 - 1))
284 :
285 : /**
286 : * Compare if sequence number s1 is less than s2.
287 : *
288 : * \param s1 First sequence number
289 : * \param s2 Second sequence number
290 : *
291 : * \return true if s1 is less than s2, or false otherwise.
292 : */
293 : static inline bool
294 31 : spdk_sn32_lt(uint32_t s1, uint32_t s2)
295 : {
296 55 : return (s1 != s2) &&
297 24 : ((s1 < s2 && s2 - s1 < SPDK_SN32_CMPMAX) ||
298 9 : (s1 > s2 && s1 - s2 > SPDK_SN32_CMPMAX));
299 : }
300 :
301 : /**
302 : * Compare if sequence number s1 is greater than s2.
303 : *
304 : * \param s1 First sequence number
305 : * \param s2 Second sequence number
306 : *
307 : * \return true if s1 is greater than s2, or false otherwise.
308 : */
309 : static inline bool
310 26 : spdk_sn32_gt(uint32_t s1, uint32_t s2)
311 : {
312 33 : return (s1 != s2) &&
313 7 : ((s1 < s2 && s2 - s1 > SPDK_SN32_CMPMAX) ||
314 3 : (s1 > s2 && s1 - s2 < SPDK_SN32_CMPMAX));
315 : }
316 :
317 : /**
318 : * Copies the value (unsigned char)ch into each of the first \b count characters of the object pointed to by \b data
319 : * \b data_size is used to check that filling \b count bytes won't lead to buffer overflow
320 : *
321 : * \param data Buffer to fill
322 : * \param data_size Size of the buffer
323 : * \param ch Fill byte
324 : * \param count Number of bytes to fill
325 : */
326 : static inline void
327 6 : spdk_memset_s(void *data, size_t data_size, int ch, size_t count)
328 : {
329 : #ifdef __STDC_LIB_EXT1__
330 : /* memset_s was introduced as an optional feature in C11 */
331 : memset_s(data, data_size, ch, count);
332 : #else
333 : size_t i;
334 6 : volatile unsigned char *buf = (volatile unsigned char *)data;
335 :
336 6 : if (!buf) {
337 0 : return;
338 : }
339 6 : if (count > data_size) {
340 0 : count = data_size;
341 : }
342 :
343 632 : for (i = 0; i < count; i++) {
344 626 : buf[i] = (unsigned char)ch;
345 : }
346 : #endif
347 : }
348 :
349 : #ifdef __cplusplus
350 : }
351 : #endif
352 :
353 : #endif
|