[PATCH 1/5] Add memset_l(), memset32() and memset64()

From: Matthew Wilcox
Date: Wed Mar 08 2017 - 17:08:22 EST


From: Matthew Wilcox <mawilcox@xxxxxxxxxxxxx>

memset_l() is like memset() but allows the user to fill the destination
with a pattern which fits in an unsigned long. memset32() and memset64()
are 32-bit and 64-bit variants of this; memset_l() will call the
appropriate one. memset32() is also useful by itself, while I am not
currently aware of any user who would benefit from memset64() on 32-bit.

Architecture maintainers should be able to write optimised versions of
these quite easily as it would share a lot with the core of an optimised
memset().

Signed-off-by: Matthew Wilcox <mawilcox@xxxxxxxxxxxxx>
---
include/linux/string.h | 13 +++++++++++++
lib/string.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index 26b6f6a66f83..642a82290a25 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -99,6 +99,19 @@ extern __kernel_size_t strcspn(const char *,const char *);
#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,__kernel_size_t);
#endif
+#ifndef __HAVE_ARCH_MEMSET_PLUS
+extern void *memset32(uint32_t *, uint32_t, __kernel_size_t);
+extern void *memset64(uint64_t *, uint64_t, __kernel_size_t);
+static inline void *memset_l(unsigned long *p, unsigned long v,
+ __kernel_size_t n)
+{
+#if BITS_PER_LONG == 32
+ return memset32((uint32_t *)p, v, n);
+#else
+ return memset64((uint64_t *)p, v, n);
+#endif
+}
+#endif
#ifndef __HAVE_ARCH_MEMCPY
extern void * memcpy(void *,const void *,__kernel_size_t);
#endif
diff --git a/lib/string.c b/lib/string.c
index ed83562a53ae..85628c8d3abd 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -697,6 +697,50 @@ void memzero_explicit(void *s, size_t count)
}
EXPORT_SYMBOL(memzero_explicit);

+#ifndef __HAVE_ARCH_MEMSET_PLUS
+/**
+ * memset32() - Fill a memory area with a uint32_t
+ * @s: Pointer to the start of the area.
+ * @v: The value to fill the area with
+ * @count: The number of values to store
+ *
+ * Differs from memset() in that it fills with a uint32_t instead
+ * of a byte. Remember that @count is the number of uint32_ts to
+ * store, not the number of bytes.
+ */
+void *memset32(uint32_t *s, uint32_t v, size_t count)
+{
+ uint32_t *xs = s;
+
+ while (count--)
+ *xs++ = v;
+ return s;
+}
+EXPORT_SYMBOL(memset32);
+
+#if BITS_PER_LONG > 32
+/**
+ * memset64() - Fill a memory area with a uint64_t
+ * @s: Pointer to the start of the area.
+ * @v: The value to fill the area with
+ * @count: The number of values to store
+ *
+ * Differs from memset() in that it fills with a uint64_t instead
+ * of a byte. Remember that @count is the number of uint64_ts to
+ * store, not the number of bytes.
+ */
+void *memset64(uint64_t *s, uint64_t v, size_t count)
+{
+ uint64_t *xs = s;
+
+ while (count--)
+ *xs++ = v;
+ return s;
+}
+EXPORT_SYMBOL(memset64);
+#endif
+#endif
+
#ifndef __HAVE_ARCH_MEMCPY
/**
* memcpy - Copy one area of memory to another
--
2.11.0