LCOV - code coverage report
Current view: top level - include/spdk - util.h (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 28 32 87.5 %
Date: 2024-12-04 15:03:17 Functions: 9 9 100.0 %

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

Generated by: LCOV version 1.15