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

Generated by: LCOV version 1.15