From: Emil Tsalapatis <emil@etsalapatis.com>
To: bpf@vger.kernel.org
Cc: ast@kernel.org, andrii@kernel.org, memxor@gmail.com,
daniel@iogearbox.net, eddyz87@gmail.com,
Emil Tsalapatis <emil@etsalapatis.com>
Subject: [PATCH 6/6] selftests/bpf: libarena: Optimize and make public arena_memset
Date: Mon, 17 Aug 2026 15:16:16 -0400 [thread overview]
Message-ID: <20260817191616.11071-7-emil@etsalapatis.com> (raw)
In-Reply-To: <20260817191616.11071-1-emil@etsalapatis.com>
Clang currently provides no __builtin_{memset, memcpy, memcmp}
for its BPF backend. This is especially an issue for arena code
that is more likely to do these operations on buffers with user-provided
bounds. One example is the arena ASAN implementation that uses
memset to update the shadow bitmap. Arena ASAN actually already
has a naive implementation of this operation. Another user would
be a calloc() call that has to zero the memory it returns.
Introduce a more optimized version of the memset() operation for
arena memory and make it public to all libarena users. The operation
uses word-sized assignments to speed up the function for larger sizes.
We expose the function through common.h to allow for inlining from
the callers.
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
---
tools/testing/selftests/bpf/libarena/Makefile | 1 +
.../bpf/libarena/include/libarena/common.h | 57 ++++++++++++++++++-
2 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/libarena/Makefile b/tools/testing/selftests/bpf/libarena/Makefile
index 6d62eda34920..91164d43bd61 100644
--- a/tools/testing/selftests/bpf/libarena/Makefile
+++ b/tools/testing/selftests/bpf/libarena/Makefile
@@ -60,6 +60,7 @@ override BPF_CFLAGS += -O2 -g
override BPF_CFLAGS += -Wno-incompatible-pointer-types-discards-qualifiers
# Required for suppressing harmless vmlinux.h-related warnings.
override BPF_CFLAGS += -Wno-missing-declarations
+override BPF_CFLAGS += -fno-strict-aliasing
override BPF_CFLAGS += $(INCLUDES)
CFLAGS = -O2 -no-pie
diff --git a/tools/testing/selftests/bpf/libarena/include/libarena/common.h b/tools/testing/selftests/bpf/libarena/include/libarena/common.h
index d32a51ff5e7f..a6220355a697 100644
--- a/tools/testing/selftests/bpf/libarena/include/libarena/common.h
+++ b/tools/testing/selftests/bpf/libarena/include/libarena/common.h
@@ -71,10 +71,63 @@ void arena_free(void __arena *ptr);
*/
static inline int arena_memset(s8 __arena *dst, s8 val, size_t size)
{
+ size_t headalign;
+ size_t tailalign;
+ u8 uval = (u8)val;
+ size_t val64;
size_t i;
- for (i = zero; i < size && can_loop; i++)
- dst[i] = val;
+ /*
+ * Calculate how many bytes to the next word-aligned one.
+ * We get this by truncating the 2s complement of the
+ * pointer to the last 3 bits. Intuitively, since
+ *
+ * The N LSBs of dst and -dst add to 1 << N, which
+ * is why dst + (-dst) = 0x0ULL through overflow. So the
+ * last N = 3 bits of the negative are the number of
+ * bytes to align dst on the last 3 bits.
+ *
+ */
+ headalign = -(u64)dst & (sizeof(u64) - 1);
+ if (!headalign || size < headalign)
+ goto ptraligned;
+
+ for (i = zero; i < headalign && can_loop; i++)
+ dst[i] = uval;
+
+ dst += headalign;
+ size -= headalign;
+
+ptraligned:
+
+ /*
+ * Make a word with all bytes equal to the byte we are setting.
+ * Since 1 byte -> 2 hex digits.
+ *
+ * Shifting the value by a 0 bytes is equal to multiplication by 0x01
+ * Shifting by 1 bytes is equal to multiplication by 0x01 << 8,
+ * ...
+ * Shifting by 7 bytes is equal to multiplication by 0x01 << 56.
+ *
+ * End operation to replicate the byte into all the bytes of a word
+ * is (since a | b = a + b when a & b == 0):
+ *
+ * val + val * (1UL << 8) + val * (1UL << 16) + .. + val * (1UL << 56)
+ * = val * (1UL << 56 + 1UL << 48 + ... + 1UL << 0)
+ * = val * (0x01UL << 56 | 0x01UL << 48 + ... + 1UL << 0)
+ * = val * 0x0101 0101 0101 0101
+ */
+ val64 = (u8)val * 0x0101010101010101ULL;
+
+ /* Pointer is now aligned, use word-aligned assignments. */
+ for (i = zero; i < size / sizeof(u64) && can_loop; i++)
+ ((u64 __arena *)dst)[i] = val64;
+
+ /* Go back to byte-aligned for the tail. */
+ tailalign = size % sizeof(u64);
+ dst += size - tailalign;
+ for (i = zero; i < tailalign && can_loop; i++)
+ dst[i] = uval;
return 0;
}
--
2.54.0
next prev parent reply other threads:[~2026-08-17 19:16 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-17 19:16 [PATCH 0/6] selftests/bpf: Fixes and improvements for libarena Emil Tsalapatis
2026-08-17 19:16 ` [PATCH 1/6] selftests/bpf: libarena: Normalize SPDX headers across files Emil Tsalapatis
2026-08-17 19:21 ` sashiko-bot
2026-08-17 19:16 ` [PATCH 2/6] selftests/bpf: libarena: Inline nonatomic bitmap operations Emil Tsalapatis
2026-08-17 19:26 ` sashiko-bot
2026-08-17 20:25 ` bot+bpf-ci
2026-08-17 19:16 ` [PATCH 3/6] selftests/bpf: libarena: Disable IRQs during allocation Emil Tsalapatis
2026-08-17 19:28 ` sashiko-bot
2026-08-17 20:38 ` bot+bpf-ci
2026-08-17 19:16 ` [PATCH 4/6] selftests/bpf: libarena: Add calloc() call Emil Tsalapatis
2026-08-17 19:23 ` sashiko-bot
2026-08-17 20:25 ` bot+bpf-ci
2026-08-17 19:16 ` [PATCH 5/6] selftests/bpf: libarena: Add a benchmark for malloc()/calloc() Emil Tsalapatis
2026-08-17 19:31 ` sashiko-bot
2026-08-17 20:25 ` bot+bpf-ci
2026-08-17 19:16 ` Emil Tsalapatis [this message]
2026-08-17 20:25 ` [PATCH 6/6] selftests/bpf: libarena: Optimize and make public arena_memset bot+bpf-ci
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260817191616.11071-7-emil@etsalapatis.com \
--to=emil@etsalapatis.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=memxor@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox