diff options
author | Matthew Wilcox <mawilcox@microsoft.com> | 2017-09-08 19:13:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-08 21:26:48 -0400 |
commit | 3b3c4babd898715926d24ae10aa64778ace33aae (patch) | |
tree | dde0523225ee26548a2b59c337930088ed7033c7 /lib/string.c | |
parent | 604df322363e5770735df85368f83cac4a955a24 (diff) |
lib/string.c: add multibyte memset functions
Patch series "Multibyte memset variations", v4.
A relatively common idiom we're missing is a function to fill an area of
memory with a pattern which is larger than a single byte. I first
noticed this with a zram patch which wanted to fill a page with an
'unsigned long' value. There turn out to be quite a few places in the
kernel which can benefit from using an optimised function rather than a
loop; sometimes text size, sometimes speed, and sometimes both. The
optimised PowerPC version (not included here) improves performance by
about 30% on POWER8 on just the raw memset_l().
Most of the extra lines of code come from the three testcases I added.
This patch (of 8):
memset16(), memset32() and memset64() are like memset(), but allow the
caller to fill the destination with a value larger than a single byte.
memset_l() and memset_p() allow the caller to use unsigned long and
pointer values respectively.
Link: http://lkml.kernel.org/r/20170720184539.31609-2-willy@infradead.org
Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "James E.J. Bottomley" <jejb@linux.vnet.ibm.com>
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Cc: David Miller <davem@davemloft.net>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/string.c')
-rw-r--r-- | lib/string.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/lib/string.c b/lib/string.c index ebbb99c775bd..198148bb61fd 100644 --- a/lib/string.c +++ b/lib/string.c | |||
@@ -723,6 +723,72 @@ void memzero_explicit(void *s, size_t count) | |||
723 | } | 723 | } |
724 | EXPORT_SYMBOL(memzero_explicit); | 724 | EXPORT_SYMBOL(memzero_explicit); |
725 | 725 | ||
726 | #ifndef __HAVE_ARCH_MEMSET16 | ||
727 | /** | ||
728 | * memset16() - Fill a memory area with a uint16_t | ||
729 | * @s: Pointer to the start of the area. | ||
730 | * @v: The value to fill the area with | ||
731 | * @count: The number of values to store | ||
732 | * | ||
733 | * Differs from memset() in that it fills with a uint16_t instead | ||
734 | * of a byte. Remember that @count is the number of uint16_ts to | ||
735 | * store, not the number of bytes. | ||
736 | */ | ||
737 | void *memset16(uint16_t *s, uint16_t v, size_t count) | ||
738 | { | ||
739 | uint16_t *xs = s; | ||
740 | |||
741 | while (count--) | ||
742 | *xs++ = v; | ||
743 | return s; | ||
744 | } | ||
745 | EXPORT_SYMBOL(memset16); | ||
746 | #endif | ||
747 | |||
748 | #ifndef __HAVE_ARCH_MEMSET32 | ||
749 | /** | ||
750 | * memset32() - Fill a memory area with a uint32_t | ||
751 | * @s: Pointer to the start of the area. | ||
752 | * @v: The value to fill the area with | ||
753 | * @count: The number of values to store | ||
754 | * | ||
755 | * Differs from memset() in that it fills with a uint32_t instead | ||
756 | * of a byte. Remember that @count is the number of uint32_ts to | ||
757 | * store, not the number of bytes. | ||
758 | */ | ||
759 | void *memset32(uint32_t *s, uint32_t v, size_t count) | ||
760 | { | ||
761 | uint32_t *xs = s; | ||
762 | |||
763 | while (count--) | ||
764 | *xs++ = v; | ||
765 | return s; | ||
766 | } | ||
767 | EXPORT_SYMBOL(memset32); | ||
768 | #endif | ||
769 | |||
770 | #ifndef __HAVE_ARCH_MEMSET64 | ||
771 | /** | ||
772 | * memset64() - Fill a memory area with a uint64_t | ||
773 | * @s: Pointer to the start of the area. | ||
774 | * @v: The value to fill the area with | ||
775 | * @count: The number of values to store | ||
776 | * | ||
777 | * Differs from memset() in that it fills with a uint64_t instead | ||
778 | * of a byte. Remember that @count is the number of uint64_ts to | ||
779 | * store, not the number of bytes. | ||
780 | */ | ||
781 | void *memset64(uint64_t *s, uint64_t v, size_t count) | ||
782 | { | ||
783 | uint64_t *xs = s; | ||
784 | |||
785 | while (count--) | ||
786 | *xs++ = v; | ||
787 | return s; | ||
788 | } | ||
789 | EXPORT_SYMBOL(memset64); | ||
790 | #endif | ||
791 | |||
726 | #ifndef __HAVE_ARCH_MEMCPY | 792 | #ifndef __HAVE_ARCH_MEMCPY |
727 | /** | 793 | /** |
728 | * memcpy - Copy one area of memory to another | 794 | * memcpy - Copy one area of memory to another |