LCOV - code coverage report
Current view: top level - lib/util - xor.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 64 67 95.5 %
Date: 2024-11-19 04:11:26 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2022 Intel Corporation.
       3             :  *   All rights reserved.
       4             :  */
       5             : 
       6             : #include "spdk/xor.h"
       7             : #include "spdk/config.h"
       8             : #include "spdk/assert.h"
       9             : #include "spdk/util.h"
      10             : 
      11             : /* maximum number of source buffers */
      12             : #define SPDK_XOR_MAX_SRC        256
      13             : 
      14             : static inline bool
      15      125012 : is_aligned(void *ptr, size_t alignment)
      16             : {
      17      125012 :         uintptr_t p = (uintptr_t)ptr;
      18             : 
      19      250024 :         return p == SPDK_ALIGN_FLOOR(p, alignment);
      20      125012 : }
      21             : 
      22             : static bool
      23       76659 : buffers_aligned(void *dest, void **sources, uint32_t n, size_t alignment)
      24             : {
      25       76659 :         uint32_t i;
      26             : 
      27      125012 :         for (i = 0; i < n; i++) {
      28      110835 :                 if (!is_aligned(sources[i], alignment)) {
      29       62482 :                         return false;
      30             :                 }
      31       48353 :         }
      32             : 
      33       14177 :         return is_aligned(dest, alignment);
      34       76659 : }
      35             : 
      36             : static void
      37       31737 : xor_gen_unaligned(void *dest, void **sources, uint32_t n, uint32_t len)
      38             : {
      39       31737 :         uint32_t i, j;
      40             : 
      41   216604784 :         for (i = 0; i < len; i++) {
      42   216573047 :                 uint8_t b = 0;
      43             : 
      44   918776256 :                 for (j = 0; j < n; j++) {
      45   702203209 :                         b ^= ((uint8_t *)sources[j])[i];
      46   702203209 :                 }
      47   216573047 :                 ((uint8_t *)dest)[i] = b;
      48   216573047 :         }
      49       31737 : }
      50             : 
      51             : static void
      52       34069 : xor_gen_basic(void *dest, void **sources, uint32_t n, uint32_t len)
      53             : {
      54       34069 :         uint32_t shift;
      55       34069 :         uint32_t len_div, len_rem;
      56       34069 :         uint32_t i, j;
      57             : 
      58       34069 :         if (!buffers_aligned(dest, sources, n, sizeof(uint64_t))) {
      59       28413 :                 xor_gen_unaligned(dest, sources, n, len);
      60       28413 :                 return;
      61             :         }
      62             : 
      63        5656 :         shift = spdk_u32log2(sizeof(uint64_t));
      64        5656 :         len_div = len >> shift;
      65        5656 :         len_rem = len_div << shift;
      66             : 
      67     3156572 :         for (i = 0; i < len_div; i++) {
      68     3150916 :                 uint64_t w = 0;
      69             : 
      70    15152472 :                 for (j = 0; j < n; j++) {
      71    12001556 :                         w ^= ((uint64_t *)sources[j])[i];
      72    12001556 :                 }
      73     3150916 :                 ((uint64_t *)dest)[i] = w;
      74     3150916 :         }
      75             : 
      76        5656 :         if (len_rem < len) {
      77        3324 :                 void *sources2[SPDK_XOR_MAX_SRC];
      78             : 
      79       14612 :                 for (j = 0; j < n; j++) {
      80       11288 :                         sources2[j] = (uint8_t *)sources[j] + len_rem;
      81       11288 :                 }
      82             : 
      83        3324 :                 xor_gen_unaligned((uint8_t *)dest + len_rem, sources2, n, len - len_rem);
      84        3324 :         }
      85       34069 : }
      86             : 
      87             : #ifdef SPDK_CONFIG_ISAL
      88             : #include "isa-l/include/raid.h"
      89             : 
      90             : #define SPDK_XOR_BUF_ALIGN 32
      91             : 
      92             : static int
      93       42590 : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
      94             : {
      95       42590 :         if (buffers_aligned(dest, sources, n, SPDK_XOR_BUF_ALIGN)) {
      96        8521 :                 void *buffers[SPDK_XOR_MAX_SRC + 1];
      97             : 
      98        8521 :                 if (n >= INT_MAX) {
      99           0 :                         return -EINVAL;
     100             :                 }
     101             : 
     102        8521 :                 memcpy(buffers, sources, n * sizeof(buffers[0]));
     103        8521 :                 buffers[n] = dest;
     104             : 
     105        8521 :                 if (xor_gen(n + 1, len, buffers)) {
     106           0 :                         return -EINVAL;
     107             :                 }
     108        8521 :         } else {
     109       34069 :                 xor_gen_basic(dest, sources, n, len);
     110             :         }
     111             : 
     112       42590 :         return 0;
     113       42590 : }
     114             : 
     115             : #else
     116             : 
     117             : #define SPDK_XOR_BUF_ALIGN sizeof(uint64_t)
     118             : 
     119             : static inline int
     120             : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
     121             : {
     122             :         xor_gen_basic(dest, sources, n, len);
     123             :         return 0;
     124             : }
     125             : 
     126             : #endif
     127             : 
     128             : int
     129       42590 : spdk_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
     130             : {
     131       42590 :         if (n < 2 || n > SPDK_XOR_MAX_SRC) {
     132           0 :                 return -EINVAL;
     133             :         }
     134             : 
     135       42590 :         return do_xor_gen(dest, sources, n, len);
     136       42590 : }
     137             : 
     138             : size_t
     139           8 : spdk_xor_get_optimal_alignment(void)
     140             : {
     141           8 :         return SPDK_XOR_BUF_ALIGN;
     142             : }
     143             : 
     144             : SPDK_STATIC_ASSERT(SPDK_XOR_BUF_ALIGN > 0 && !(SPDK_XOR_BUF_ALIGN & (SPDK_XOR_BUF_ALIGN - 1)),
     145             :                    "Must be power of 2");

Generated by: LCOV version 1.15