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

Generated by: LCOV version 1.15