mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-02 17:28:30 +00:00
Make improvements
- Invent openatemp() API - Invent O_UNLINK open flag - Introduce getenv_secure() API - Remove `git pull` from cosmocc - Fix utimes() when path is NULL - Fix mktemp() to never return NULL - Fix utimensat() UTIME_OMIT on XNU - Improve utimensat() code for RHEL5 - Turn `argv[0]` C:/ to /C/ on Windows - Introduce tmpnam() and tmpnam_r() APIs - Fix more const issues with internal APIs - Permit utimes() on WIN32 in O_RDONLY mode - Fix fdopendir() to check fd is a directory - Fix recent crash regression in landlock make - Fix futimens(AT_FDCWD, NULL) to return EBADF - Use workaround so `make -j` doesn't fork bomb - Rename dontdiscard to __wur (just like glibc) - Fix st_size for WIN32 symlinks containing UTF-8 - Introduce stdio ext APIs needed by GNU coreutils - Fix lstat() on WIN32 for symlinks to directories - Move some constants from normalize.inc to limits.h - Fix segv with memchr() and memcmp() overlapping page - Implement POSIX fflush() behavior for reader streams - Implement AT_SYMLINK_NOFOLLOW for utimensat() on WIN32 - Don't change read-only status of existing files on WIN32 - Correctly handle `0x[^[:xdigit:]]` case in strtol() functions
This commit is contained in:
parent
8596e83cce
commit
f531acc8f9
297 changed files with 1920 additions and 1681 deletions
|
@ -347,7 +347,7 @@ static void __asan_exit(void) {
|
|||
_Exit(99);
|
||||
}
|
||||
|
||||
dontdiscard static __asan_die_f *__asan_die(void) {
|
||||
static __wur __asan_die_f *__asan_die(void) {
|
||||
if (_weaken(__die)) {
|
||||
return _weaken(__die);
|
||||
} else {
|
||||
|
@ -707,8 +707,7 @@ static const char *__asan_describe_access_poison(signed char kind) {
|
|||
}
|
||||
}
|
||||
|
||||
static dontdiscard __asan_die_f *__asan_report_invalid_pointer(
|
||||
const void *addr) {
|
||||
static __wur __asan_die_f *__asan_report_invalid_pointer(const void *addr) {
|
||||
kprintf("\n\e[J\e[1;31masan error\e[0m: this corruption at %p shadow %p\n",
|
||||
addr, SHADOW(addr));
|
||||
return __asan_die();
|
||||
|
@ -825,9 +824,9 @@ static void __asan_report_memory_origin(const unsigned char *addr, int size,
|
|||
}
|
||||
}
|
||||
|
||||
dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
||||
const char *message,
|
||||
signed char kind) {
|
||||
static __wur __asan_die_f *__asan_report(const void *addr, int size,
|
||||
const char *message,
|
||||
signed char kind) {
|
||||
int i;
|
||||
wint_t c;
|
||||
signed char t;
|
||||
|
@ -940,8 +939,8 @@ void __asan_verify_str(const char *p) {
|
|||
__asan_verify_failed(UNSHADOW(f.shadow), 8, f);
|
||||
}
|
||||
|
||||
static dontdiscard __asan_die_f *__asan_report_memory_fault(
|
||||
void *addr, int size, const char *message) {
|
||||
static __wur __asan_die_f *__asan_report_memory_fault(void *addr, int size,
|
||||
const char *message) {
|
||||
return __asan_report(addr, size, message,
|
||||
__asan_fault(SHADOW(addr), -128).kind);
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ int _bsrl(long) pureconst;
|
|||
int _bsrll(long long) pureconst;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define _bsr(x) (__builtin_clz(x) ^ (sizeof(int) * CHAR_BIT - 1))
|
||||
#define _bsrl(x) (__builtin_clzl(x) ^ (sizeof(long) * CHAR_BIT - 1))
|
||||
#define _bsrll(x) (__builtin_clzll(x) ^ (sizeof(long long) * CHAR_BIT - 1))
|
||||
#define _bsr(x) (__builtin_clz(x) ^ (sizeof(int) * 8 - 1))
|
||||
#define _bsrl(x) (__builtin_clzl(x) ^ (sizeof(long) * 8 - 1))
|
||||
#define _bsrll(x) (__builtin_clzll(x) ^ (sizeof(long long) * 8 - 1))
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -139,6 +139,10 @@ void bzero(void *p, size_t n) {
|
|||
#ifdef __x86_64__
|
||||
asm("xorl\t%k0,%k0" : "=r"(x));
|
||||
#else
|
||||
if (1) {
|
||||
memset(p, 0, n);
|
||||
return;
|
||||
}
|
||||
x = 0;
|
||||
#endif
|
||||
if (n <= 16) {
|
||||
|
|
|
@ -31,11 +31,11 @@ __msabi extern typeof(CreateDirectory) *const __imp_CreateDirectoryW;
|
|||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows bool32 CreateDirectory(const char16_t *lpPathName,
|
||||
struct NtSecurityAttributes *lpSecurity) {
|
||||
const struct NtSecurityAttributes *lpSec) {
|
||||
bool32 ok;
|
||||
ok = __imp_CreateDirectoryW(lpPathName, lpSecurity);
|
||||
ok = __imp_CreateDirectoryW(lpPathName, lpSec);
|
||||
if (!ok) __winerr();
|
||||
NTTRACE("CreateDirectory(%#hs, %s) → %hhhd% m", lpPathName,
|
||||
DescribeNtSecurityAttributes(lpSecurity), ok);
|
||||
DescribeNtSecurityAttributes(lpSec), ok);
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ __msabi extern typeof(CreateProcess) *const __imp_CreateProcessW;
|
|||
*/
|
||||
textwindows bool32
|
||||
CreateProcess(const char16_t *opt_lpApplicationName, char16_t *lpCommandLine,
|
||||
struct NtSecurityAttributes *opt_lpProcessAttributes,
|
||||
struct NtSecurityAttributes *opt_lpThreadAttributes,
|
||||
const struct NtSecurityAttributes *opt_lpProcessAttributes,
|
||||
const struct NtSecurityAttributes *opt_lpThreadAttributes,
|
||||
bool32 bInheritHandles, uint32_t dwCreationFlags,
|
||||
void *opt_lpEnvironment, const char16_t *opt_lpCurrentDirectory,
|
||||
const struct NtStartupInfo *lpStartupInfo,
|
||||
|
|
|
@ -32,7 +32,7 @@ __msabi extern typeof(CreateThread) *const __imp_CreateThread;
|
|||
* @note this wrapper takes care of ABI, STRACE()
|
||||
*/
|
||||
textwindows int64_t
|
||||
CreateThread(struct NtSecurityAttributes *lpThreadAttributes,
|
||||
CreateThread(const struct NtSecurityAttributes *lpThreadAttributes,
|
||||
size_t dwStackSize, void *lpStartAddress, void *lpParameter,
|
||||
uint32_t dwCreationFlags, uint32_t *opt_lpThreadId) {
|
||||
int64_t hHandle;
|
||||
|
|
|
@ -46,7 +46,6 @@ dontasan int __cxa_atexit(void *fp, void *arg, void *pred) {
|
|||
/* asan runtime depends on this function */
|
||||
unsigned i;
|
||||
struct CxaAtexitBlock *b, *b2;
|
||||
_Static_assert(ATEXIT_MAX == CHAR_BIT * sizeof(b->mask), "");
|
||||
__cxa_lock();
|
||||
b = __cxa_blocks.p;
|
||||
if (!b) b = __cxa_blocks.p = &__cxa_blocks.root;
|
||||
|
|
|
@ -14,7 +14,7 @@ struct CxaAtexitBlocks {
|
|||
void *fp;
|
||||
void *arg;
|
||||
void *pred;
|
||||
} p[ATEXIT_MAX];
|
||||
} p[32];
|
||||
} * p, root;
|
||||
};
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ const char *DescribeNtProcAccessFlags(char[256], uint32_t);
|
|||
const char *DescribeNtStartFlags(char[128], uint32_t);
|
||||
const char *DescribeNtSymlinkFlags(char[64], uint32_t);
|
||||
const char *DescribeOpenFlags(char[128], int);
|
||||
const char *DescribeOpenMode(char[15], int, int);
|
||||
const char *DescribePersonalityFlags(char[128], int);
|
||||
const char *DescribePollFlags(char[64], int);
|
||||
const char *DescribePrctlOperation(int);
|
||||
|
@ -97,6 +98,7 @@ const char *DescribeWhichPrio(char[12], int);
|
|||
#define DescribeNtStartFlags(x) DescribeNtStartFlags(alloca(128), x)
|
||||
#define DescribeNtSymlinkFlags(x) DescribeNtSymlinkFlags(alloca(64), x)
|
||||
#define DescribeOpenFlags(x) DescribeOpenFlags(alloca(128), x)
|
||||
#define DescribeOpenMode(x, y) DescribeOpenMode(alloca(15), x, y)
|
||||
#define DescribePersonalityFlags(p) DescribePersonalityFlags(alloca(128), p)
|
||||
#define DescribePollFlags(p) DescribePollFlags(alloca(64), p)
|
||||
#define DescribeProtFlags(x) DescribeProtFlags(alloca(48), x)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
const char *(DescribeNtOverlapped)(char b[128], struct NtOverlapped *o) {
|
||||
const char *(DescribeNtOverlapped)(char b[128], const struct NtOverlapped *o) {
|
||||
int i = 0, n = 128;
|
||||
bool gotsome = false;
|
||||
if (!o) return "NULL";
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
const char *DescribeNtOverlapped(char[128], struct NtOverlapped *);
|
||||
const char *DescribeNtOverlapped(char[128], const struct NtOverlapped *);
|
||||
#define DescribeNtOverlapped(x) DescribeNtOverlapped(alloca(128), x)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -21,8 +21,9 @@
|
|||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
|
||||
const char *(DescribeNtSecurityAttributes)(char buf[32],
|
||||
struct NtSecurityAttributes *p) {
|
||||
const char *(
|
||||
DescribeNtSecurityAttributes)(char buf[32],
|
||||
const struct NtSecurityAttributes *p) {
|
||||
if (p == &kNtIsInheritable) return "&kNtIsInheritable";
|
||||
FormatInt64(buf, (uintptr_t)p);
|
||||
return buf;
|
||||
|
|
40
libc/intrin/describeopenmode.c
Normal file
40
libc/intrin/describeopenmode.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
#define O_TMPFILE_LINUX 0x00410000
|
||||
|
||||
static bool IsCreatingFile(int flags) {
|
||||
return (flags & O_CREAT) ||
|
||||
(IsLinux() && (flags & O_TMPFILE_LINUX) == O_TMPFILE_LINUX);
|
||||
}
|
||||
|
||||
const char *(DescribeOpenMode)(char buf[15], int flags, int mode) {
|
||||
if (!IsCreatingFile(flags)) {
|
||||
return "";
|
||||
}
|
||||
char *p = buf;
|
||||
*p++ = ',';
|
||||
*p++ = ' ';
|
||||
FormatOctal32(p, mode, true);
|
||||
return buf;
|
||||
}
|
47
libc/intrin/formatoctal32.c
Normal file
47
libc/intrin/formatoctal32.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/itoa.h"
|
||||
|
||||
/**
|
||||
* Converts unsigned 32-bit integer to octal string.
|
||||
*
|
||||
* @param p needs at least 12 bytes
|
||||
* @param z ensures it starts with zero
|
||||
* @return pointer to nul byte
|
||||
*/
|
||||
char *FormatOctal32(char p[hasatleast 13], uint32_t x, bool z) {
|
||||
char t;
|
||||
size_t i, a, b;
|
||||
i = 0;
|
||||
z = x && z;
|
||||
do {
|
||||
p[i++] = x % 8 + '0';
|
||||
x = x / 8;
|
||||
} while (x > 0);
|
||||
if (z) p[i++] = '0';
|
||||
p[i] = '\0';
|
||||
if (i) {
|
||||
for (a = 0, b = i - 1; a < b; ++a, --b) {
|
||||
t = p[a];
|
||||
p[a] = p[b];
|
||||
p[b] = t;
|
||||
}
|
||||
}
|
||||
return p + i;
|
||||
}
|
|
@ -34,6 +34,8 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
#define OPEN_MAX 16
|
||||
|
||||
#ifdef __x86_64__
|
||||
__static_yoink("_init_g_fds");
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
char *getenv(const char *s) {
|
||||
char **p;
|
||||
struct Env e;
|
||||
if (!s) return 0;
|
||||
if (!(p = environ)) return 0;
|
||||
e = __getenv(p, s);
|
||||
#if SYSDEBUG
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/nt/struct/securityattributes.h"
|
||||
|
||||
const struct NtSecurityAttributes kNtIsInheritable = {
|
||||
sizeof(struct NtSecurityAttributes),
|
||||
NULL,
|
||||
true,
|
||||
.nLength = sizeof(struct NtSecurityAttributes),
|
||||
.lpSecurityDescriptor = NULL,
|
||||
.bInheritHandle = true,
|
||||
};
|
||||
|
|
|
@ -36,7 +36,8 @@ kOpenFlags:
|
|||
.e O_TRUNC,"TRUNC" //
|
||||
.e O_CLOEXEC,"CLOEXEC" //
|
||||
.e O_NONBLOCK,"NONBLOCK" //
|
||||
.e O_TMPFILE,"TMPFILE" // linux, windows
|
||||
.e O_TMPFILE,"TMPFILE" // linux
|
||||
.e O_UNLINK,"UNLINK" // windows+unix
|
||||
.e O_DIRECTORY,"DIRECTORY" // order matters
|
||||
.e O_DIRECT,"DIRECT" // no-op on xnu/openbsd
|
||||
.e O_APPEND,"APPEND" // weird on nt
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#ifndef __aarch64__
|
||||
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
||||
static inline const unsigned char *memchr_pure(const unsigned char *s,
|
||||
unsigned char c, size_t n) {
|
||||
|
@ -68,14 +68,22 @@ dontasan static inline const unsigned char *memchr_sse(const unsigned char *s,
|
|||
* @return is pointer to first instance of c or NULL if not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memchr(const void *s, int c, size_t n) {
|
||||
dontasan void *memchr(const void *s, int c, size_t n) {
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
const void *r;
|
||||
if (IsAsan()) __asan_verify(s, n);
|
||||
r = memchr_sse(s, c, n);
|
||||
const unsigned char *p = (const unsigned char *)s;
|
||||
while (n && ((intptr_t)p & 15)) {
|
||||
if (*p == (unsigned char)c) {
|
||||
return (void *)p;
|
||||
}
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
r = memchr_sse(p, c, n);
|
||||
return (void *)r;
|
||||
#else
|
||||
return memchr_pure(s, c, n);
|
||||
return (void *)memchr_pure(s, c, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -22,113 +22,34 @@
|
|||
#include "libc/str/str.h"
|
||||
#ifndef __aarch64__
|
||||
|
||||
#define PMOVMSKB(x) __builtin_ia32_pmovmskb128(x)
|
||||
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
|
||||
static dontinline antiquity int memcmp_sse(const unsigned char *p,
|
||||
const unsigned char *q, size_t n) {
|
||||
unsigned u;
|
||||
if (n > 32) {
|
||||
while (n > 16 + 16) {
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)p == *(xmm_t *)q) ^ 0xffff)) {
|
||||
n -= 16;
|
||||
p += 16;
|
||||
q += 16;
|
||||
} else {
|
||||
u = __builtin_ctzl(u);
|
||||
return p[u] - q[u];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)p == *(xmm_t *)q) ^ 0xffff)) {
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)(p + n - 16) == *(xmm_t *)(q + n - 16)) ^
|
||||
0xffff)) {
|
||||
return 0;
|
||||
} else {
|
||||
u = __builtin_ctzl(u);
|
||||
return p[n - 16 + u] - q[n - 16 + u];
|
||||
}
|
||||
} else {
|
||||
u = __builtin_ctzl(u);
|
||||
return p[u] - q[u];
|
||||
}
|
||||
}
|
||||
|
||||
_Microarchitecture("avx") static int memcmp_avx(const unsigned char *p,
|
||||
const unsigned char *q,
|
||||
size_t n) {
|
||||
uint64_t w;
|
||||
unsigned u;
|
||||
if (n > 32) {
|
||||
while (n >= 16 + 64) {
|
||||
w = (uint64_t)PMOVMSKB(((xmm_t *)p)[0] == ((xmm_t *)q)[0]) << 000 |
|
||||
(uint64_t)PMOVMSKB(((xmm_t *)p)[1] == ((xmm_t *)q)[1]) << 020 |
|
||||
(uint64_t)PMOVMSKB(((xmm_t *)p)[2] == ((xmm_t *)q)[2]) << 040 |
|
||||
(uint64_t)PMOVMSKB(((xmm_t *)p)[3] == ((xmm_t *)q)[3]) << 060;
|
||||
if (w == -1) {
|
||||
n -= 64;
|
||||
p += 64;
|
||||
q += 64;
|
||||
} else {
|
||||
w = __builtin_ctzll(w ^ -1);
|
||||
return p[w] - q[w];
|
||||
}
|
||||
}
|
||||
while (n > 16 + 16) {
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)p == *(xmm_t *)q) ^ 0xffff)) {
|
||||
n -= 16;
|
||||
p += 16;
|
||||
q += 16;
|
||||
} else {
|
||||
u = __builtin_ctzl(u);
|
||||
return p[u] - q[u];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)p == *(xmm_t *)q) ^ 0xffff)) {
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)(p + n - 16) == *(xmm_t *)(q + n - 16)) ^
|
||||
0xffff)) {
|
||||
return 0;
|
||||
} else {
|
||||
u = __builtin_ctzl(u);
|
||||
return p[n - 16 + u] - q[n - 16 + u];
|
||||
}
|
||||
} else {
|
||||
u = __builtin_ctzl(u);
|
||||
return p[u] - q[u];
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
/**
|
||||
* Compares memory byte by byte.
|
||||
*
|
||||
* memcmp n=0 992 picoseconds
|
||||
* memcmp n=1 1 ns/byte 738 mb/s
|
||||
* memcmp n=2 661 ps/byte 1,476 mb/s
|
||||
* memcmp n=3 551 ps/byte 1,771 mb/s
|
||||
* memcmp n=4 248 ps/byte 3,936 mb/s
|
||||
* memcmp n=5 198 ps/byte 4,920 mb/s
|
||||
* memcmp n=6 165 ps/byte 5,904 mb/s
|
||||
* memcmp n=7 141 ps/byte 6,889 mb/s
|
||||
* memcmp n=8 124 ps/byte 7,873 mb/s
|
||||
* memcmp n=9 110 ps/byte 8,857 mb/s
|
||||
* memcmp n=15 44 ps/byte 22,143 mb/s
|
||||
* memcmp n=16 41 ps/byte 23,619 mb/s
|
||||
* memcmp n=17 77 ps/byte 12,547 mb/s
|
||||
* memcmp n=31 42 ps/byte 22,881 mb/s
|
||||
* memcmp n=32 41 ps/byte 23,619 mb/s
|
||||
* memcmp n=33 60 ps/byte 16,238 mb/s
|
||||
* memcmp n=80 53 ps/byte 18,169 mb/s
|
||||
* memcmp n=128 38 ps/byte 25,194 mb/s
|
||||
* memcmp n=256 32 ps/byte 30,233 mb/s
|
||||
* memcmp n=16384 27 ps/byte 35,885 mb/s
|
||||
* memcmp n=32768 29 ps/byte 32,851 mb/s
|
||||
* memcmp n=131072 33 ps/byte 28,983 mb/s
|
||||
* memcmp n=0 2 nanoseconds
|
||||
* memcmp n=1 2 ns/byte 357 mb/s
|
||||
* memcmp n=2 1 ns/byte 530 mb/s
|
||||
* memcmp n=3 1 ns/byte 631 mb/s
|
||||
* 𝗺𝗲𝗺𝗰𝗺𝗽 n=4 1 ns/byte 849 mb/s
|
||||
* memcmp n=5 816 ps/byte 1,195 mb/s
|
||||
* memcmp n=6 888 ps/byte 1,098 mb/s
|
||||
* memcmp n=7 829 ps/byte 1,176 mb/s
|
||||
* 𝗺𝗲𝗺𝗰𝗺𝗽 n=8 773 ps/byte 1,261 mb/s
|
||||
* memcmp n=9 629 ps/byte 1,551 mb/s
|
||||
* memcmp n=15 540 ps/byte 1,805 mb/s
|
||||
* 𝗺𝗲𝗺𝗰𝗺𝗽 n=16 211 ps/byte 4,623 mb/s
|
||||
* memcmp n=17 268 ps/byte 3,633 mb/s
|
||||
* memcmp n=31 277 ps/byte 3,524 mb/s
|
||||
* memcmp n=32 153 ps/byte 6,351 mb/s
|
||||
* memcmp n=33 179 ps/byte 5,431 mb/s
|
||||
* memcmp n=79 148 ps/byte 6,576 mb/s
|
||||
* 𝗺𝗲𝗺𝗰𝗺𝗽 n=80 81 ps/byte 11 GB/s
|
||||
* memcmp n=128 76 ps/byte 12 GB/s
|
||||
* memcmp n=256 60 ps/byte 15 GB/s
|
||||
* memcmp n=16384 51 ps/byte 18 GB/s
|
||||
* memcmp n=32768 51 ps/byte 18 GB/s
|
||||
* memcmp n=131072 52 ps/byte 18 GB/s
|
||||
*
|
||||
* @return an integer that's (1) equal to zero if `a` is equal to `b`,
|
||||
* (2) less than zero if `a` is less than `b`, or (3) greater than
|
||||
|
@ -137,62 +58,21 @@ _Microarchitecture("avx") static int memcmp_avx(const unsigned char *p,
|
|||
*/
|
||||
int memcmp(const void *a, const void *b, size_t n) {
|
||||
int c;
|
||||
unsigned u;
|
||||
uint32_t k, i, j;
|
||||
uint64_t w, x, y;
|
||||
const unsigned char *p, *q;
|
||||
if ((p = a) == (q = b) || !n) return 0;
|
||||
if ((c = *p - *q)) return c;
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
if (!IsTiny()) {
|
||||
if (n <= 16) {
|
||||
if (n >= 8) {
|
||||
if (!(w = (x = ((uint64_t)p[0] << 000 | (uint64_t)p[1] << 010 |
|
||||
(uint64_t)p[2] << 020 | (uint64_t)p[3] << 030 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[6] << 060 | (uint64_t)p[7] << 070)) ^
|
||||
(y = ((uint64_t)q[0] << 000 | (uint64_t)q[1] << 010 |
|
||||
(uint64_t)q[2] << 020 | (uint64_t)q[3] << 030 |
|
||||
(uint64_t)q[4] << 040 | (uint64_t)q[5] << 050 |
|
||||
(uint64_t)q[6] << 060 | (uint64_t)q[7] << 070)))) {
|
||||
p += n - 8;
|
||||
q += n - 8;
|
||||
if (!(w = (x = ((uint64_t)p[0] << 000 | (uint64_t)p[1] << 010 |
|
||||
(uint64_t)p[2] << 020 | (uint64_t)p[3] << 030 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[6] << 060 | (uint64_t)p[7] << 070)) ^
|
||||
(y = ((uint64_t)q[0] << 000 | (uint64_t)q[1] << 010 |
|
||||
(uint64_t)q[2] << 020 | (uint64_t)q[3] << 030 |
|
||||
(uint64_t)q[4] << 040 | (uint64_t)q[5] << 050 |
|
||||
(uint64_t)q[6] << 060 | (uint64_t)q[7] << 070)))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
u = __builtin_ctzll(w);
|
||||
u = u & -8;
|
||||
return ((x >> u) & 255) - ((y >> u) & 255);
|
||||
} else if (n >= 4) {
|
||||
if (!(k = (i = ((uint32_t)p[0] << 000 | (uint32_t)p[1] << 010 |
|
||||
(uint32_t)p[2] << 020 | (uint32_t)p[3] << 030)) ^
|
||||
(j = ((uint32_t)q[0] << 000 | (uint32_t)q[1] << 010 |
|
||||
(uint32_t)q[2] << 020 | (uint32_t)q[3] << 030)))) {
|
||||
p += n - 4;
|
||||
q += n - 4;
|
||||
if (!(k = (i = ((uint32_t)p[0] << 000 | (uint32_t)p[1] << 010 |
|
||||
(uint32_t)p[2] << 020 | (uint32_t)p[3] << 030)) ^
|
||||
(j = ((uint32_t)q[0] << 000 | (uint32_t)q[1] << 010 |
|
||||
(uint32_t)q[2] << 020 | (uint32_t)q[3] << 030)))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
u = __builtin_ctzl(k);
|
||||
u = u & -8;
|
||||
return ((i >> u) & 255) - ((j >> u) & 255);
|
||||
}
|
||||
} else if (LIKELY(X86_HAVE(AVX))) {
|
||||
return memcmp_avx(p, q, n);
|
||||
unsigned u;
|
||||
while (n >= 16 && (((uintptr_t)p & 0xfff) <= 0x1000 - 16 &&
|
||||
((uintptr_t)q & 0xfff) <= 0x1000 - 16)) {
|
||||
if (!(u = __builtin_ia32_pmovmskb128(*(xmm_t *)p == *(xmm_t *)q) ^
|
||||
0xffff)) {
|
||||
n -= 16;
|
||||
p += 16;
|
||||
q += 16;
|
||||
} else {
|
||||
return memcmp_sse(p, q, n);
|
||||
u = __builtin_ctzl(u);
|
||||
return p[u] - q[u];
|
||||
}
|
||||
}
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/str/str.h"
|
||||
#ifndef __aarch64__
|
||||
|
@ -75,7 +76,7 @@ void *memrchr(const void *s, int c, size_t n) {
|
|||
r = memrchr_sse(s, c, n);
|
||||
return (void *)r;
|
||||
#else
|
||||
return memrchr_pure(s, c, n);
|
||||
return (void *)memrchr_pure(s, c, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
|
||||
.init.start 200,_init__mmi
|
||||
movb $OPEN_MAX,_mmi+8
|
||||
movb $16,_mmi+8
|
||||
movl $_mmi+24,_mmi+16
|
||||
movb $PTHREAD_MUTEX_RECURSIVE,__mmi_lock_obj+4(%rip)
|
||||
.init.end 200,_init__mmi
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/sysv/consts/limits.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/sysv/consts/limits.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
|
|
@ -107,14 +107,14 @@ dontasan char *strchr(const char *s, int c) {
|
|||
unassert(!r || *r || !(c & 255));
|
||||
return (char *)r;
|
||||
#else
|
||||
char *r;
|
||||
const char *r;
|
||||
for (c &= 255; (uintptr_t)s & 7; ++s) {
|
||||
if ((*s & 255) == c) return s;
|
||||
if ((*s & 255) == c) return (char *)s;
|
||||
if (!*s) return NULL;
|
||||
}
|
||||
r = strchr_x64(s, c);
|
||||
unassert(!r || *r || !c);
|
||||
return r;
|
||||
return (char *)r;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
*/
|
||||
privileged dontdiscard char *strsignal_r(int sig, char buf[21]) {
|
||||
privileged char *strsignal_r(int sig, char buf[21]) {
|
||||
const char *s;
|
||||
if (!sig) {
|
||||
return "0";
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/intrin/pushpop.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
|
@ -218,7 +219,7 @@ static char *__ubsan_stpcpy(char *d, const char *s) {
|
|||
}
|
||||
}
|
||||
|
||||
dontdiscard static __ubsan_die_f *__ubsan_die(void) {
|
||||
__wur static __ubsan_die_f *__ubsan_die(void) {
|
||||
if (_weaken(__die)) {
|
||||
return _weaken(__die);
|
||||
} else {
|
||||
|
@ -232,8 +233,8 @@ static void __ubsan_warning(const struct UbsanSourceLocation *loc,
|
|||
loc->line, SUBTLE, description, RESET);
|
||||
}
|
||||
|
||||
dontdiscard __ubsan_die_f *__ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
__wur __ubsan_die_f *__ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
kprintf("\n%s:%d: %subsan error%s: %s (tid %d)\n", loc->file, loc->line, RED2,
|
||||
RESET, description, gettid());
|
||||
return __ubsan_die();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue