From bdcf29ba337f4e68e674a5ef04cc5a48d50b18cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kowalczyk?= Date: Thu, 23 Jul 2020 03:33:43 +0200 Subject: [PATCH] [Pal] Simplify memset and clean up other string ops --- LICENSE.addendum.txt | 5 --- Pal/include/lib/api.h | 24 +++++----- Pal/lib/string/memcmp.c | 34 ++++++-------- Pal/lib/string/memcpy.c | 47 +++++++------------ Pal/lib/string/memset.c | 99 ++++++++--------------------------------- Pal/lib/string/strcmp.c | 27 ++++------- 6 files changed, 69 insertions(+), 167 deletions(-) diff --git a/LICENSE.addendum.txt b/LICENSE.addendum.txt index 29cc5811..f3241eae 100644 --- a/LICENSE.addendum.txt +++ b/LICENSE.addendum.txt @@ -19,10 +19,6 @@ cJSON - MIT uthash - BSD revised A number of files taken from other C libraries: -* musl - MIT - ** Pal/lib/string/memcmp.c - ** Pal/lib/string/memcpy.c - ** Pal/lib/string/strcmp.c * glibc - LGPL ** clone, sysdeps.h (and variants) used in code ** Pal/src/host/Linux/clone-x86_64.S @@ -33,7 +29,6 @@ A number of files taken from other C libraries: ** Pal/include/sysdeps/generic/sysdep.h ** Pal/lib/network/hton.c ** Pal/lib/string/atoi.c - ** Pal/lib/string/memset.c ** Pal/lib/string/strchr.c ** Pal/lib/string/strlen.c ** Pal/src/dynamic_link.h, do-rel.h , dl-machine-x86_64.h diff --git a/Pal/include/lib/api.h b/Pal/include/lib/api.h index a5bb8a20..9d343e45 100644 --- a/Pal/include/lib/api.h +++ b/Pal/include/lib/api.h @@ -103,28 +103,28 @@ typedef ptrdiff_t ssize_t; #define __UNUSED(x) do { (void)(x); } while (0) #define static_strlen(str) (ARRAY_SIZE(FORCE_LITERAL_CSTR(str)) - 1) -/* Libc functions */ +/* LibC functions */ -/* Libc String functions string.h/stdlib.h */ -size_t strnlen (const char *str, size_t maxlen); -size_t strlen (const char *str); +/* LibC string functions */ +size_t strnlen(const char* str, size_t maxlen); +size_t strlen(const char* str); int strcmp(const char* a, const char* b); -long strtol (const char *s, char **endptr, int base); -int atoi (const char *nptr); -long int atol (const char *nptr); +long strtol(const char* s, char** endptr, int base); +int atoi(const char* nptr); +long int atol(const char* nptr); char* strchr(const char* s, int c_in); char* strstr(const char* haystack, const char* needle); -void * memcpy (void *dstpp, const void *srcpp, size_t len); -void * memmove (void *dstpp, const void *srcpp, size_t len); -void * memset (void *dstpp, int c, size_t len); -int memcmp (const void *s1, const void *s2, size_t len); +void* memcpy(void* restrict dest, const void* restrict src, size_t count); +void* memmove(void* dest, const void* src, size_t count); +void* memset(void* dest, int ch, size_t count); +int memcmp(const void* lhs, const void* rhs, size_t count); bool strendswith(const char* haystack, const char* needle); -/* Libc memory allocation functions. stdlib.h. */ +/* Libc memory allocation functions */ void *malloc(size_t size); void free(void *ptr); void *calloc(size_t nmemb, size_t size); diff --git a/Pal/lib/string/memcmp.c b/Pal/lib/string/memcmp.c index 62c2b816..23dcfa78 100644 --- a/Pal/lib/string/memcmp.c +++ b/Pal/lib/string/memcmp.c @@ -1,24 +1,16 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ + +#include + #include "api.h" -/* Copyright © 2005-2014 Rich Felker, et al. */ - -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ - -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ - -/* musl 1.1.24 */ - -int memcmp(const void* vl, const void* vr, size_t n) { - const unsigned char* l=vl; - const unsigned char* r=vr; - for (; n && *l == *r; n--, l++, r++) - /*nop*/; - return n ? *l - *r : 0; +int memcmp(const void* lhs, const void* rhs, size_t count) { + const unsigned char* l = lhs; + const unsigned char* r = rhs; + while (count && *l == *r) { + count--; + l++; + r++; + } + return count ? *l - *r : 0; } diff --git a/Pal/lib/string/memcpy.c b/Pal/lib/string/memcpy.c index 2d3672a7..52e77e24 100644 --- a/Pal/lib/string/memcpy.c +++ b/Pal/lib/string/memcpy.c @@ -1,22 +1,11 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ + +#include + #include "api.h" -/* Copyright © 2005-2014 Rich Felker, et al. */ - -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ - -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ - -/* heavily based on musl 1.1.15/1.1.24 */ - -void* memcpy(void* restrict dst, const void* restrict src, size_t n) { - char* d = dst; +void* memcpy(void* restrict dest, const void* restrict src, size_t count) { + char* d = dest; #if defined(__x86_64__) /* "Beginning with processors based on Intel microarchitecture code name Ivy Bridge, REP string * operation using MOVSB and STOSB can provide both flexible and high-performance REP string @@ -26,33 +15,31 @@ void* memcpy(void* restrict dst, const void* restrict src, size_t n) { * memcpy() is heavily used in Linux-SGX PAL to copy data in/out of SGX enclave. Experiments * with Redis 5.0 show perf improvement of using "rep movsb" at 3-5% for 4KB payloads over * previous implementation taken from Glibc 2.23. */ - __asm__ volatile("rep movsb" : "+D" (d) : "c"(n), "S"(src) : "cc", "memory"); + __asm__ volatile("rep movsb" : "+&D"(d), "+&c"(count) : "S"(src) : "cc", "memory"); #else const char* s = src; - for (; n; n--) + while (count--) *d++ = *s++; #endif - return dst; + return dest; } -void* memmove(void* dst, const void* src, size_t n) { - char* d = dst; +void* memmove(void* dest, const void* src, size_t count) { + char* d = dest; const char* s = src; if (d == s) return d; - if (s + n <= d || d + n <= s) - return memcpy(d, s, n); + if (s + count <= d || d + count <= s) + return memcpy(d, s, count); if (d < s) { - for (; n; n--) + while (count--) *d++ = *s++; } else { - while (n) { - n--; - d[n] = s[n]; - } + while (count--) + d[count] = s[count]; } - return dst; + return dest; } diff --git a/Pal/lib/string/memset.c b/Pal/lib/string/memset.c index 9bc45c53..36ea00f1 100644 --- a/Pal/lib/string/memset.c +++ b/Pal/lib/string/memset.c @@ -1,85 +1,24 @@ -/* Copyright (C) 1991,1993,1995,1997,1998,2003,2004 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Torbjorn Granlund (tege@sics.se). +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* Copyright (C) 2020 Invisible Things Lab + * Michał Kowalczyk + */ - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ +#include #include "api.h" -#define op_t unsigned long int -#define OPSIZ (sizeof(op_t)) - -typedef unsigned char byte; - -void* memset(void* dstpp, int c, size_t len) { - long int dstp = (long int)dstpp; - - if (len >= 8) { - int xlen; - op_t cccc; - - cccc = (unsigned char)c; - cccc |= cccc << 8; - cccc |= cccc << 16; - if (OPSIZ > 4) { - /* Do the shift in two steps to avoid warning if long has 32 bits. */ - cccc |= (cccc << 16) << 16; - } - - /* There are at least some bytes to set. - No need to test for LEN == 0 in this alignment loop. */ - while (dstp % OPSIZ != 0) { - ((byte*)dstp)[0] = c; - dstp += 1; - len -= 1; - } - - /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */ - xlen = len / (OPSIZ * 8); - while (xlen > 0) { - ((op_t*)dstp)[0] = cccc; - ((op_t*)dstp)[1] = cccc; - ((op_t*)dstp)[2] = cccc; - ((op_t*)dstp)[3] = cccc; - ((op_t*)dstp)[4] = cccc; - ((op_t*)dstp)[5] = cccc; - ((op_t*)dstp)[6] = cccc; - ((op_t*)dstp)[7] = cccc; - dstp += 8 * OPSIZ; - xlen -= 1; - } - len %= OPSIZ * 8; - - /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */ - xlen = len / OPSIZ; - while (xlen > 0) { - ((op_t*)dstp)[0] = cccc; - dstp += OPSIZ; - xlen -= 1; - } - len %= OPSIZ; - } - - /* Write the last few bytes. */ - while (len > 0) { - ((byte*)dstp)[0] = c; - dstp += 1; - len -= 1; - } - - return dstpp; +void* memset(void* dest, int ch, size_t count) { + char* d = dest; +#if defined(__x86_64__) + /* "Beginning with processors based on Intel microarchitecture code name Ivy Bridge, REP string + * operation using MOVSB and STOSB can provide both flexible and high-performance REP string + * operations for software in common situations like memory copy and set operations" + * Intel 64 and IA-32 Architectures Optimization Reference Manual + */ + __asm__ volatile("rep stosb" : "+&D"(d), "+&c"(count) : "a"((uint8_t)ch) : "cc", "memory"); +#else + while (count--) + *d++ = ch; +#endif + return dest; } diff --git a/Pal/lib/string/strcmp.c b/Pal/lib/string/strcmp.c index 71bb2251..723d403a 100644 --- a/Pal/lib/string/strcmp.c +++ b/Pal/lib/string/strcmp.c @@ -1,22 +1,11 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ + #include "api.h" -/* Copyright © 2005-2014 Rich Felker, et al. */ - -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ - -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ - -/* musl 1.1.24 */ - -int strcmp(const char* l, const char* r) { - for (; *l == *r && *l; l++, r++) - ; - return *(unsigned char*)l - *(unsigned char*)r; +int strcmp(const char* lhs, const char* rhs) { + while (*lhs == *rhs && *lhs) { + lhs++; + rhs++; + } + return *(unsigned char*)lhs - *(unsigned char*)rhs; }