LCOV - code coverage report
Current view: top level - lib/util - xor.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 26 49 53.1 %
Date: 2024-12-14 14:11:45 Functions: 5 7 71.4 %

          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           4 : is_aligned(void *ptr, size_t alignment)
      16             : {
      17           4 :         uintptr_t p = (uintptr_t)ptr;
      18             : 
      19           4 :         return p == SPDK_ALIGN_FLOOR(p, alignment);
      20             : }
      21             : 
      22             : static bool
      23           2 : buffers_aligned(void *dest, void **sources, uint32_t n, size_t alignment)
      24             : {
      25             :         uint32_t i;
      26             : 
      27           4 :         for (i = 0; i < n; i++) {
      28           3 :                 if (!is_aligned(sources[i], alignment)) {
      29           1 :                         return false;
      30             :                 }
      31             :         }
      32             : 
      33           1 :         return is_aligned(dest, alignment);
      34             : }
      35             : 
      36             : static void
      37           0 : xor_gen_unaligned(void *dest, void **sources, uint32_t n, uint32_t len)
      38             : {
      39             :         uint32_t i, j;
      40             : 
      41           0 :         for (i = 0; i < len; i++) {
      42           0 :                 uint8_t b = 0;
      43             : 
      44           0 :                 for (j = 0; j < n; j++) {
      45           0 :                         b ^= ((uint8_t *)sources[j])[i];
      46             :                 }
      47           0 :                 ((uint8_t *)dest)[i] = b;
      48             :         }
      49           0 : }
      50             : 
      51             : static void
      52           1 : xor_gen_basic(void *dest, void **sources, uint32_t n, uint32_t len)
      53             : {
      54             :         uint32_t shift;
      55             :         uint32_t len_div, len_rem;
      56             :         uint32_t i, j;
      57             : 
      58           1 :         if (!buffers_aligned(dest, sources, n, sizeof(uint64_t))) {
      59           0 :                 xor_gen_unaligned(dest, sources, n, len);
      60           0 :                 return;
      61             :         }
      62             : 
      63           1 :         shift = spdk_u32log2(sizeof(uint64_t));
      64           1 :         len_div = len >> shift;
      65           1 :         len_rem = len_div << shift;
      66             : 
      67           9 :         for (i = 0; i < len_div; i++) {
      68           8 :                 uint64_t w = 0;
      69             : 
      70          24 :                 for (j = 0; j < n; j++) {
      71          16 :                         w ^= ((uint64_t *)sources[j])[i];
      72             :                 }
      73           8 :                 ((uint64_t *)dest)[i] = w;
      74             :         }
      75             : 
      76           1 :         if (len_rem < len) {
      77           0 :                 void *sources2[SPDK_XOR_MAX_SRC];
      78             : 
      79           0 :                 for (j = 0; j < n; j++) {
      80           0 :                         sources2[j] = (uint8_t *)sources[j] + len_rem;
      81             :                 }
      82             : 
      83           0 :                 xor_gen_unaligned((uint8_t *)dest + len_rem, sources2, n, len - len_rem);
      84             :         }
      85             : }
      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           1 : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
      94             : {
      95           1 :         if (buffers_aligned(dest, sources, n, SPDK_XOR_BUF_ALIGN)) {
      96           0 :                 void *buffers[SPDK_XOR_MAX_SRC + 1];
      97             : 
      98           0 :                 if (n >= INT_MAX) {
      99           0 :                         return -EINVAL;
     100             :                 }
     101             : 
     102           0 :                 memcpy(buffers, sources, n * sizeof(buffers[0]));
     103           0 :                 buffers[n] = dest;
     104             : 
     105           0 :                 if (xor_gen(n + 1, len, buffers)) {
     106           0 :                         return -EINVAL;
     107             :                 }
     108             :         } else {
     109           1 :                 xor_gen_basic(dest, sources, n, len);
     110             :         }
     111             : 
     112           1 :         return 0;
     113             : }
     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           1 : spdk_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
     130             : {
     131           1 :         if (n < 2 || n > SPDK_XOR_MAX_SRC) {
     132           0 :                 return -EINVAL;
     133             :         }
     134             : 
     135           1 :         return do_xor_gen(dest, sources, n, len);
     136             : }
     137             : 
     138             : size_t
     139           0 : spdk_xor_get_optimal_alignment(void)
     140             : {
     141           0 :         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