aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.vnet.ibm.com>2015-06-01 14:34:47 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-06-01 17:10:10 +1000
commitf232117367198c330ddf64a4c61bda0110ae9cec (patch)
tree098556ac2e6b4488e7bfb0012d769be1f68d292b
parent3bd6f3ba4a2070ab42647a0d07770e9828765031 (diff)
downloadskiboot-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.c22
-rw-r--r--libc/test/run-memops-test.c16
-rw-r--r--libc/test/run-memops.c17
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;
}