Spdk/lib/util/xor.c

146 lines
2.7 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2022 Intel Corporation.
* All rights reserved.
*/
#include "spdk/xor.h"
#include "spdk/config.h"
#include "spdk/assert.h"
#include "spdk/util.h"
/* maximum number of source buffers */
#define SPDK_XOR_MAX_SRC 256
static inline bool
is_aligned(void *ptr, size_t alignment)
{
uintptr_t p = (uintptr_t)ptr;
return p == SPDK_ALIGN_FLOOR(p, alignment);
}
static bool
buffers_aligned(void *dest, void **sources, uint32_t n, size_t alignment)
{
uint32_t i;
for (i = 0; i < n; i++) {
if (!is_aligned(sources[i], alignment)) {
return false;
}
}
return is_aligned(dest, alignment);
}
static void
xor_gen_unaligned(void *dest, void **sources, uint32_t n, uint32_t len)
{
uint32_t i, j;
for (i = 0; i < len; i++) {
uint8_t b = 0;
for (j = 0; j < n; j++) {
b ^= ((uint8_t *)sources[j])[i];
}
((uint8_t *)dest)[i] = b;
}
}
static void
xor_gen_basic(void *dest, void **sources, uint32_t n, uint32_t len)
{
uint32_t shift;
uint32_t len_div, len_rem;
uint32_t i, j;
if (!buffers_aligned(dest, sources, n, sizeof(uint64_t))) {
xor_gen_unaligned(dest, sources, n, len);
return;
}
shift = spdk_u32log2(sizeof(uint64_t));
len_div = len >> shift;
len_rem = len_div << shift;
for (i = 0; i < len_div; i++) {
uint64_t w = 0;
for (j = 0; j < n; j++) {
w ^= ((uint64_t *)sources[j])[i];
}
((uint64_t *)dest)[i] = w;
}
if (len_rem < len) {
void *sources2[SPDK_XOR_MAX_SRC];
for (j = 0; j < n; j++) {
sources2[j] = sources[j] + len_rem;
}
xor_gen_unaligned(dest + len_rem, sources2, n, len - len_rem);
}
}
#ifdef SPDK_CONFIG_ISAL
#include "isa-l/include/raid.h"
#define SPDK_XOR_BUF_ALIGN 32
static int
do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
{
if (buffers_aligned(dest, sources, n, SPDK_XOR_BUF_ALIGN)) {
void *buffers[SPDK_XOR_MAX_SRC + 1];
if (n >= INT_MAX) {
return -EINVAL;
}
memcpy(buffers, sources, n * sizeof(buffers[0]));
buffers[n] = dest;
if (xor_gen(n + 1, len, buffers)) {
return -EINVAL;
}
} else {
xor_gen_basic(dest, sources, n, len);
}
return 0;
}
#else
#define SPDK_XOR_BUF_ALIGN sizeof(uint64_t)
static inline int
do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
{
xor_gen_basic(dest, sources, n, len);
return 0;
}
#endif
int
spdk_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
{
if (n < 2 || n > SPDK_XOR_MAX_SRC) {
return -EINVAL;
}
return do_xor_gen(dest, sources, n, len);
}
size_t
spdk_xor_get_optimal_alignment(void)
{
return SPDK_XOR_BUF_ALIGN;
}
SPDK_STATIC_ASSERT(SPDK_XOR_BUF_ALIGN > 0 && !(SPDK_XOR_BUF_ALIGN & (SPDK_XOR_BUF_ALIGN - 1)),
"Must be power of 2");