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

Generated by: LCOV version 1.15