[PATCH 4/5] Add memfill()
From: Matthew Wilcox
Date: Wed Mar 08 2017 - 16:01:58 EST
From: Matthew Wilcox <mawilcox@xxxxxxxxxxxxx>
Similar to Lars Wirzenius' memfill(), this version has optimisations for
source sizes of 1, 2, 4 (and 8 on 64 bit architectures).
Signed-off-by: Matthew Wilcox <mawilcox@xxxxxxxxxxxxx>
---
include/linux/string.h | 3 +++
lib/string.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/include/linux/string.h b/include/linux/string.h
index 642a82290a25..f340e6fb309f 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -112,6 +112,9 @@ static inline void *memset_l(unsigned long *p, unsigned long v,
#endif
}
#endif
+#ifndef __HAVE_ARCH_MEMFILL
+extern void memfill(void *, __kernel_size_t, void *, __kernel_size_t);
+#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 85628c8d3abd..d22711e6490a 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -741,6 +741,47 @@ EXPORT_SYMBOL(memset64);
#endif
#endif
+#ifndef __HAVE_ARCH_MEMFILL
+/**
+ * memfill() - Fill a region of memory with copies of another region
+ * @dst: Destination address
+ * @dsz: Size of destination area
+ * @src: Source address
+ * @ssz: Size of source area
+ */
+void memfill(void *dst, size_t dsz, void *src, size_t ssz)
+{
+ if (ssz == 1) {
+ memset(dst, *(unsigned char *)src, dsz);
+ return;
+ } else if (ssz == sizeof(short)) {
+ uint32_t v = *(unsigned short *)src;
+ v |= (v << 16);
+
+ memset32(dst, v, dsz / sizeof(uint32_t));
+ dst = (uint32_t *)dst + dsz / sizeof(uint32_t);
+ dsz %= sizeof(uint32_t);
+ } else if (ssz == sizeof(int)) {
+ memset32(dst, *(uint32_t *)src, dsz / sizeof(uint32_t));
+ dst = (uint32_t *)dst + dsz / sizeof(uint32_t);
+ dsz %= sizeof(int);
+ } else if (ssz == sizeof(long)) {
+ memset_l(dst, *(long *)src, dsz / sizeof(long));
+ dst = (long *)dst + dsz / sizeof(long);
+ dsz %= sizeof(long);
+ } else {
+ while (dsz >= ssz) {
+ memcpy(dst, src, ssz);
+ dsz -= ssz;
+ dst += ssz;
+ }
+ }
+ if (dsz)
+ memcpy(dst, src, dsz);
+}
+EXPORT_SYMBOL(memfill);
+#endif
+
#ifndef __HAVE_ARCH_MEMCPY
/**
* memcpy - Copy one area of memory to another
--
2.11.0