diff options
author | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-06-01 14:34:47 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-06-01 17:10:10 +1000 |
commit | f232117367198c330ddf64a4c61bda0110ae9cec (patch) | |
tree | 098556ac2e6b4488e7bfb0012d769be1f68d292b | |
parent | 3bd6f3ba4a2070ab42647a0d07770e9828765031 (diff) | |
download | skiboot-f232117367198c330ddf64a4c61bda0110ae9cec.zip skiboot-f232117367198c330ddf64a4c61bda0110ae9cec.tar.gz skiboot-f232117367198c330ddf64a4c61bda0110ae9cec.tar.bz2 |
Optimized memset() implementation for POWER
This uses the dcbz instruction to clear cacheline at a time rather than
byte at a time. This means that even without high levels of optimization,
we *dramatically* improve boot performance with SKIBOOT_GCOV=1 and probably
ever so slightly speed things up for normal builds.
We currently just hard-code 128 as cacheline size as all CPUs that skiboot
currently boots on have 128 byte cachelines.
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | libc/string/memset.c | 22 | ||||
-rw-r--r-- | libc/test/run-memops-test.c | 16 | ||||
-rw-r--r-- | libc/test/run-memops.c | 17 |
3 files changed, 55 insertions, 0 deletions
diff --git a/libc/string/memset.c b/libc/string/memset.c index f8dfbf5..18b7619 100644 --- a/libc/string/memset.c +++ b/libc/string/memset.c @@ -12,11 +12,33 @@ #include "string.h" +#define CACHE_LINE_SIZE 128 + void * memset(void *dest, int c, size_t size) { unsigned char *d = (unsigned char *)dest; +#if defined(__powerpc__) || defined(__powerpc64__) + if (size > CACHE_LINE_SIZE && c==0) { + while ((unsigned long long)d % CACHE_LINE_SIZE) { + *d++ = (unsigned char)c; + size--; + } + while (size >= CACHE_LINE_SIZE) { + asm volatile ("dcbz 0,%0\n" : : "r"(d) : "memory"); + d+= CACHE_LINE_SIZE; + size-= CACHE_LINE_SIZE; + } + } +#endif + + while (size >= 8 && c == 0) { + *((unsigned long long*)d) = 0ULL; + d+=8; + size-=8; + } + while (size-- > 0) { *d++ = (unsigned char)c; } diff --git a/libc/test/run-memops-test.c b/libc/test/run-memops-test.c index 0979994..429cfdc 100644 --- a/libc/test/run-memops-test.c +++ b/libc/test/run-memops-test.c @@ -41,3 +41,19 @@ #include "../string/strncpy.c" #include "../string/strstr.c" #include "../string/strtok.c" +#include <stdlib.h> + +int test_memset(char* buf, int c, size_t s); + +int test_memset(char* buf, int c, size_t s) +{ + int i; + int r= 0; + + memset(buf, c, s); + for(i=0; i<s; i++) + if (buf[i] != c) + r = -1; + + return r; +} diff --git a/libc/test/run-memops.c b/libc/test/run-memops.c index 15ec9bd..80822df 100644 --- a/libc/test/run-memops.c +++ b/libc/test/run-memops.c @@ -21,7 +21,24 @@ #include <string.h> #include <stdio.h> +int test_memset(char* buf, int c, size_t s); + int main(void) { + char* buf; + + buf = malloc(100); + assert(test_memset(buf, 0x42, 100) == 0); + free(buf); + + buf = malloc(128); + assert(test_memset(buf, 0, 128) == 0); + assert(test_memset(buf+1, 0, 127) == 0); + free(buf); + + buf = malloc(1024); + assert(test_memset(buf, 0, 1024) == 0); + free(buf); + return 0; } |