From: Matthew Wilcox <mawil...@microsoft.com>

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 <mawil...@microsoft.com>
---
 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

Reply via email to