mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Make improvements
- Make rand64() thread safe - Introduce lemur64 lcg prng - Improve strace on New Technology - Improve msync() on New Technology
This commit is contained in:
parent
43ba3009b2
commit
29bf8b1a30
73 changed files with 888 additions and 269 deletions
|
@ -209,6 +209,7 @@ const struct Function {
|
|||
{"getrandom", GetRandom}, //
|
||||
{"inc", inc}, //
|
||||
{"knuth", knuth}, //
|
||||
{"lemur64", lemur64}, //
|
||||
{"libc", libc}, //
|
||||
{"moby", moby}, //
|
||||
{"mt19937", _mt19937}, //
|
||||
|
|
46
libc/bits/cmpxchg16b.internal.h
Normal file
46
libc/bits/cmpxchg16b.internal.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_BITS_CMPXCHG16B_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_BITS_CMPXCHG16B_INTERNAL_H_
|
||||
#include "libc/bits/bits.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* Compares and exchanges 128-bit value, i.e.
|
||||
*
|
||||
* if (*IfThing == *IsEqualToMe) {
|
||||
* *IfThing = ReplaceItWithMe;
|
||||
* return true;
|
||||
* } else {
|
||||
* *IsEqualToMe = *IfThing;
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* Please note that Intel Architecture doesn't guarantee 16-byte memory
|
||||
* accesses to be atomic on their own. Therefore _lockcmpxchg16b should
|
||||
* be considered instead for both thread and asynchronous signal safety
|
||||
*
|
||||
* @param IfThing should point to aligned memory
|
||||
* @param IsEqualToMe should point to in/out local variable
|
||||
* @param ReplaceItWithMe might become the new memory value
|
||||
* @return true if *IfThing was changed
|
||||
*/
|
||||
static inline bool _cmpxchg16b(uint128_t *IfThing, uint128_t *IsEqualToMe,
|
||||
uint128_t ReplaceItWithMe) {
|
||||
bool DidIt;
|
||||
uint64_t ax, bx, cx, dx;
|
||||
ax = *IsEqualToMe;
|
||||
dx = *IsEqualToMe >> 64;
|
||||
bx = ReplaceItWithMe;
|
||||
cx = ReplaceItWithMe >> 64;
|
||||
asm volatile(ZFLAG_ASM("cmpxchg16b\t%1")
|
||||
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(ax), "+d"(dx)
|
||||
: "b"(bx), "c"(cx));
|
||||
if (!DidIt) {
|
||||
*IsEqualToMe = ax | (uint128_t)dx << 64;
|
||||
}
|
||||
return DidIt;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_BITS_CMPXCHG16B_INTERNAL_H_ */
|
44
libc/bits/lockcmpxchg16b.internal.h
Normal file
44
libc/bits/lockcmpxchg16b.internal.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_BITS_LOCKCMPXCHG16B_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_BITS_LOCKCMPXCHG16B_INTERNAL_H_
|
||||
#include "libc/bits/bits.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* Compares and exchanges 128-bit value, i.e.
|
||||
*
|
||||
* if (*IfThing == *IsEqualToMe) {
|
||||
* *IfThing = ReplaceItWithMe;
|
||||
* return true;
|
||||
* } else {
|
||||
* *IsEqualToMe = *IfThing;
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* @param IfThing should point to aligned memory
|
||||
* @param IsEqualToMe should point to in/out local variable
|
||||
* @param ReplaceItWithMe might become the new memory value
|
||||
* @return true if *IfThing was changed
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
*/
|
||||
static inline bool _lockcmpxchg16b(uint128_t *IfThing, uint128_t *IsEqualToMe,
|
||||
uint128_t ReplaceItWithMe) {
|
||||
bool DidIt;
|
||||
uint64_t ax, bx, cx, dx;
|
||||
ax = *IsEqualToMe;
|
||||
dx = *IsEqualToMe >> 64;
|
||||
bx = ReplaceItWithMe;
|
||||
cx = ReplaceItWithMe >> 64;
|
||||
asm volatile(ZFLAG_ASM("lock cmpxchg16b\t%1")
|
||||
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(ax), "+d"(dx)
|
||||
: "b"(bx), "c"(cx));
|
||||
if (!DidIt) {
|
||||
*IsEqualToMe = ax | (uint128_t)dx << 64;
|
||||
}
|
||||
return DidIt;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_BITS_LOCKCMPXCHG16B_INTERNAL_H_ */
|
16
libc/bits/lockxadd.internal.h
Normal file
16
libc/bits/lockxadd.internal.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_BITS_LOCKXADD_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_BITS_LOCKXADD_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define _lockxadd(PTR, VAL) \
|
||||
({ \
|
||||
typeof(*(PTR)) Res; \
|
||||
typeof(Res) Val = (VAL); \
|
||||
asm volatile("lock xadd\t%0,%1" : "=r"(Res), "+m"(*(PTR)) : "0"(Val)); \
|
||||
Res; /* contains *PTR before addition cf. InterlockedAdd() */ \
|
||||
})
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_BITS_LOCKXADD_INTERNAL_H_ */
|
|
@ -36,5 +36,5 @@ textwindows int sys_close_nt(struct Fd *fd) {
|
|||
if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
|
||||
ok &= CloseHandle(fd->extra);
|
||||
}
|
||||
return ok ? 0 : __winerr();
|
||||
return ok ? 0 : -1;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
|
|||
int64_t handle, int64_t off) {
|
||||
size_t i;
|
||||
struct DirectMap dm;
|
||||
uint32_t flags1, flags2;
|
||||
struct ProtectNt fl;
|
||||
const struct NtSecurityAttributes *sec;
|
||||
|
||||
if (flags & MAP_PRIVATE) {
|
||||
|
@ -42,37 +42,19 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
|
|||
if ((prot & PROT_WRITE) && (flags & MAP_PRIVATE) && handle != -1) {
|
||||
// windows has cow pages but they can't propagate across fork()
|
||||
if (prot & PROT_EXEC) {
|
||||
flags1 = kNtPageExecuteWritecopy;
|
||||
flags2 = kNtFileMapCopy | kNtFileMapExecute;
|
||||
fl = (struct ProtectNt){kNtPageExecuteWritecopy,
|
||||
kNtFileMapCopy | kNtFileMapExecute};
|
||||
} else {
|
||||
flags1 = kNtPageWritecopy;
|
||||
flags2 = kNtFileMapCopy;
|
||||
}
|
||||
} else if (prot & PROT_WRITE) {
|
||||
if (prot & PROT_EXEC) {
|
||||
flags1 = kNtPageExecuteReadwrite;
|
||||
flags2 = kNtFileMapWrite | kNtFileMapExecute;
|
||||
} else {
|
||||
flags1 = kNtPageReadwrite;
|
||||
flags2 = kNtFileMapWrite;
|
||||
}
|
||||
} else if (prot & PROT_READ) {
|
||||
if (prot & PROT_EXEC) {
|
||||
flags1 = kNtPageExecuteRead;
|
||||
flags2 = kNtFileMapRead | kNtFileMapExecute;
|
||||
} else {
|
||||
flags1 = kNtPageReadonly;
|
||||
flags2 = kNtFileMapRead;
|
||||
fl = (struct ProtectNt){kNtPageWritecopy, kNtFileMapCopy};
|
||||
}
|
||||
} else {
|
||||
flags1 = kNtPageNoaccess;
|
||||
flags2 = 0;
|
||||
fl = __nt2prot(prot);
|
||||
}
|
||||
|
||||
if ((dm.maphandle = CreateFileMapping(handle, sec, flags1, (size + off) >> 32,
|
||||
(size + off), 0))) {
|
||||
if ((dm.addr = MapViewOfFileEx(dm.maphandle, flags2, off >> 32, off, size,
|
||||
addr))) {
|
||||
if ((dm.maphandle = CreateFileMapping(handle, sec, fl.flags1,
|
||||
(size + off) >> 32, (size + off), 0))) {
|
||||
if ((dm.addr = MapViewOfFileEx(dm.maphandle, fl.flags2, off >> 32, off,
|
||||
size, addr))) {
|
||||
return dm;
|
||||
}
|
||||
CloseHandle(dm.maphandle);
|
||||
|
|
|
@ -22,10 +22,5 @@
|
|||
|
||||
textwindows int sys_fdatasync_nt(int fd) {
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
/*
|
||||
* XXX: On Windows NT this might be more analagous to fflush() and
|
||||
* Microsoft docs say to do manual block i/o for database-ish
|
||||
* guarantees on disk persistence. Consider: Really good UPS.
|
||||
*/
|
||||
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : __winerr();
|
||||
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : -1;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
* This function is typically regarded as a libc implementation detail;
|
||||
* thus, the source code is the documentation.
|
||||
*
|
||||
* @return aux val or 0 if not available
|
||||
* @see libc/sysv/consts.sh
|
||||
* @see System Five Application Binary Interface § 3.4.3
|
||||
* @asyncsignalsafe
|
||||
|
|
|
@ -226,7 +226,6 @@ void sys_exit(int) hidden;
|
|||
|
||||
void __onfork(void) hidden;
|
||||
i32 __fixupnewfd(i32, i32) hidden;
|
||||
u32 __prot2nt(i32, i32) privileged;
|
||||
void __restore_rt() hidden;
|
||||
int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden;
|
||||
int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden;
|
||||
|
@ -284,7 +283,7 @@ int sys_linkat_nt(int, const char *, int, const char *) hidden;
|
|||
int sys_lstat_nt(const char *, struct stat *) hidden;
|
||||
int sys_madvise_nt(void *, size_t, int) hidden;
|
||||
int sys_mkdirat_nt(int, const char *, uint32_t) hidden;
|
||||
int sys_msync_nt(void *, size_t, int) hidden;
|
||||
int sys_msync_nt(char *, size_t, int) hidden;
|
||||
int sys_nanosleep_nt(const struct timespec *, struct timespec *) hidden;
|
||||
int sys_pipe_nt(int[hasatleast 2], unsigned) hidden;
|
||||
int sys_renameat_nt(int, const char *, int, const char *) hidden;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
||||
|
|
|
@ -50,11 +50,8 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
|
|||
pipefd[1] = writer;
|
||||
return 0;
|
||||
} else {
|
||||
__winerr();
|
||||
CloseHandle(hin);
|
||||
}
|
||||
} else {
|
||||
__winerr();
|
||||
}
|
||||
__releasefd(writer);
|
||||
__releasefd(reader);
|
||||
|
|
|
@ -63,7 +63,7 @@ struct Signals {
|
|||
struct Signal mem[__SIG_QUEUE_LENGTH];
|
||||
};
|
||||
|
||||
struct Signals __sig;
|
||||
struct Signals __sig; // TODO(jart): Need TLS
|
||||
|
||||
/**
|
||||
* Allocates piece of memory for storing pending signal.
|
||||
|
|
|
@ -51,7 +51,7 @@ static textwindows int SyncDirectory(int df, char16_t path[PATH_MAX], int n) {
|
|||
if (FlushFileBuffers(df)) {
|
||||
return 0;
|
||||
} else {
|
||||
return __winerr();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
path[0] = '.';
|
||||
|
@ -65,11 +65,11 @@ static textwindows int SyncDirectory(int df, char16_t path[PATH_MAX], int n) {
|
|||
if (FlushFileBuffers(fh)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = __winerr();
|
||||
rc = -1;
|
||||
}
|
||||
CloseHandle(fh);
|
||||
} else {
|
||||
rc = __winerr();
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
|
|
36
libc/intrin/closehandle.greg.c
Normal file
36
libc/intrin/closehandle.greg.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 2022 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/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CloseHandle) *const __imp_CloseHandle __msabi;
|
||||
|
||||
/**
|
||||
* Closes an open object handle.
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows bool32 CloseHandle(int64_t hObject) {
|
||||
bool32 ok;
|
||||
ok = __imp_CloseHandle(hObject);
|
||||
if (!ok) __winerr();
|
||||
STRACE("CloseHandle(%ld) → %hhhd% m", hObject, ok);
|
||||
return ok;
|
||||
}
|
55
libc/intrin/createnamedpipe.greg.c
Normal file
55
libc/intrin/createnamedpipe.greg.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*-*- 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 2022 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/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CreateNamedPipe) *const __imp_CreateNamedPipeW __msabi;
|
||||
|
||||
/**
|
||||
* Creates pipe.
|
||||
*
|
||||
* @return handle to server end
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows int64_t CreateNamedPipe(
|
||||
const char16_t *lpName, uint32_t dwOpenMode, uint32_t dwPipeMode,
|
||||
uint32_t nMaxInstances, uint32_t nOutBufferSize, uint32_t nInBufferSize,
|
||||
uint32_t nDefaultTimeOutMs,
|
||||
const struct NtSecurityAttributes *opt_lpSecurityAttributes) {
|
||||
int64_t hServer;
|
||||
hServer = __imp_CreateNamedPipeW(lpName, dwOpenMode, dwPipeMode,
|
||||
nMaxInstances, nOutBufferSize, nInBufferSize,
|
||||
nDefaultTimeOutMs, opt_lpSecurityAttributes);
|
||||
if (hServer == -1) __winerr();
|
||||
STRACE("CreateNamedPipe(%#hs,"
|
||||
" dwOpenMode=%u,"
|
||||
" dwPipeMode=%u,"
|
||||
" nMaxInstances=%u,"
|
||||
" nOutBufferSize=%'u,"
|
||||
" nInBufferSize=%'u,"
|
||||
" nDefaultTimeOutMs=%'u,"
|
||||
" lpSecurity=%p) → "
|
||||
"%ld% m",
|
||||
lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize,
|
||||
nInBufferSize, nDefaultTimeOutMs, opt_lpSecurityAttributes, hServer);
|
||||
return hServer;
|
||||
}
|
41
libc/intrin/createpipe.greg.c
Normal file
41
libc/intrin/createpipe.greg.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- 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 2022 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/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(CreatePipe) *const __imp_CreatePipe __msabi;
|
||||
|
||||
/**
|
||||
* Creates anonymous pipe.
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows bool32 CreatePipe(
|
||||
int64_t *out_hReadPipe, int64_t *out_hWritePipe,
|
||||
const struct NtSecurityAttributes *opt_lpPipeAttributes, uint32_t nSize) {
|
||||
bool32 ok;
|
||||
ok = __imp_CreatePipe(out_hReadPipe, out_hWritePipe, opt_lpPipeAttributes,
|
||||
nSize);
|
||||
if (!ok) __winerr();
|
||||
STRACE("CreatePipe([%ld], [%ld], %p, %'zu) → %hhhd% m", *out_hReadPipe,
|
||||
*out_hWritePipe, opt_lpPipeAttributes, nSize, ok);
|
||||
return ok;
|
||||
}
|
|
@ -26,6 +26,7 @@ extern typeof(CreateThread) *const __imp_CreateThread __msabi;
|
|||
/**
|
||||
* Opens file on the New Technology.
|
||||
*
|
||||
* @param dwStackSize may be 0 for default per executable
|
||||
* @return thread handle, or 0 on failure
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
|
|
43
libc/intrin/flushfilebuffers.greg.c
Normal file
43
libc/intrin/flushfilebuffers.greg.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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 2022 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/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers __msabi;
|
||||
|
||||
/**
|
||||
* Flushes buffers of specified file to disk.
|
||||
*
|
||||
* This provides a stronger degree of assurance and blocking for things
|
||||
* to be sent to a physical medium, but it's not guaranteed unless your
|
||||
* file is opened in a direct non-caching mode. One main advantage here
|
||||
* seems to be coherency.
|
||||
*
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
* @note consider buying a ups
|
||||
* @see FlushViewOfFile()
|
||||
*/
|
||||
textwindows bool32 FlushFileBuffers(int64_t hFile) {
|
||||
bool32 ok;
|
||||
ok = __imp_FlushFileBuffers(hFile);
|
||||
if (!ok) __winerr();
|
||||
STRACE("FlushFileBuffers(%ld) → %hhhd% m", hFile, ok);
|
||||
return ok;
|
||||
}
|
43
libc/intrin/flushviewoffile.greg.c
Normal file
43
libc/intrin/flushviewoffile.greg.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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 2022 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/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/memory.h"
|
||||
|
||||
extern typeof(FlushViewOfFile) *const __imp_FlushViewOfFile __msabi;
|
||||
|
||||
/**
|
||||
* Syncs memory created by MapViewOfFileEx().
|
||||
*
|
||||
* This doesn't wait until the pages are written out to the physical
|
||||
* medium. This doesn't update timestamps or file/dir metadata.
|
||||
*
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
* @note consider buying a ups
|
||||
* @see FlushFileBuffers()
|
||||
*/
|
||||
textwindows bool32 FlushViewOfFile(const void *lpBaseAddress,
|
||||
size_t dwNumberOfBytesToFlush) {
|
||||
bool32 ok;
|
||||
ok = __imp_FlushViewOfFile(lpBaseAddress, dwNumberOfBytesToFlush);
|
||||
if (!ok) __winerr();
|
||||
STRACE("FlushViewOfFile(%p, %'zu) → %hhhd% m", lpBaseAddress,
|
||||
dwNumberOfBytesToFlush, ok);
|
||||
return ok;
|
||||
}
|
|
@ -64,7 +64,14 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: \
|
|||
$(NO_MAGIC)
|
||||
|
||||
o/$(MODE)/libc/intrin/createfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/createpipe.greg.o \
|
||||
o/$(MODE)/libc/intrin/closehandle.greg.o \
|
||||
o/$(MODE)/libc/intrin/createthread.greg.o \
|
||||
o/$(MODE)/libc/intrin/describeflags.greg.o \
|
||||
o/$(MODE)/libc/intrin/createnamedpipe.greg.o \
|
||||
o/$(MODE)/libc/intrin/unmapviewoffile.greg.o \
|
||||
o/$(MODE)/libc/intrin/flushviewoffile.greg.o \
|
||||
o/$(MODE)/libc/intrin/flushfilebuffers.greg.o \
|
||||
o/$(MODE)/libc/intrin/mapviewoffileexnuma.greg.o \
|
||||
o/$(MODE)/libc/intrin/createfilemappingnuma.greg.o \
|
||||
o/$(MODE)/libc/intrin/kstarttsc.o \
|
||||
|
|
42
libc/intrin/nt2prot.greg.c
Normal file
42
libc/intrin/nt2prot.greg.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 2020 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/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
privileged struct ProtectNt __nt2prot(int prot) {
|
||||
if (prot & PROT_WRITE) {
|
||||
if (prot & PROT_EXEC) {
|
||||
return (struct ProtectNt){kNtPageExecuteReadwrite,
|
||||
kNtFileMapWrite | kNtFileMapExecute};
|
||||
} else {
|
||||
return (struct ProtectNt){kNtPageReadwrite, kNtFileMapWrite};
|
||||
}
|
||||
} else if (prot & PROT_READ) {
|
||||
if (prot & PROT_EXEC) {
|
||||
return (struct ProtectNt){kNtPageExecuteRead,
|
||||
kNtFileMapRead | kNtFileMapExecute};
|
||||
} else {
|
||||
return (struct ProtectNt){kNtPageReadonly, kNtFileMapRead};
|
||||
}
|
||||
} else {
|
||||
return (struct ProtectNt){kNtPageNoaccess};
|
||||
}
|
||||
}
|
35
libc/intrin/unmapviewoffile.greg.c
Normal file
35
libc/intrin/unmapviewoffile.greg.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 2022 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/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/nt/memory.h"
|
||||
|
||||
extern typeof(UnmapViewOfFile) *const __imp_UnmapViewOfFile __msabi;
|
||||
|
||||
/**
|
||||
* Unmaps memory created by MapViewOfFileEx().
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows bool32 UnmapViewOfFile(const void *lpBaseAddress) {
|
||||
bool32 ok;
|
||||
ok = __imp_UnmapViewOfFile(lpBaseAddress);
|
||||
if (!ok) __winerr();
|
||||
STRACE("UnmapViewOfFile(%p) → %hhhd% m", lpBaseAddress, ok);
|
||||
return ok;
|
||||
}
|
|
@ -171,27 +171,14 @@ void ShowBacktrace(int fd, const struct StackFrame *bp) {
|
|||
#ifdef __FNO_OMIT_FRAME_POINTER__
|
||||
/* asan runtime depends on this function */
|
||||
int st, ft;
|
||||
static bool noreentry;
|
||||
if (!noreentry) {
|
||||
noreentry = true;
|
||||
st = __strace, __strace = 0;
|
||||
ft = g_ftrace, g_ftrace = 0;
|
||||
if (!bp) bp = __builtin_frame_address(0);
|
||||
|
||||
st = __strace;
|
||||
__strace = 0;
|
||||
PrintBacktrace(fd, bp);
|
||||
|
||||
ft = g_ftrace;
|
||||
g_ftrace = 0;
|
||||
|
||||
if (!bp) {
|
||||
bp = __builtin_frame_address(0);
|
||||
}
|
||||
|
||||
PrintBacktrace(fd, bp);
|
||||
|
||||
__strace = st;
|
||||
g_ftrace = ft;
|
||||
|
||||
noreentry = false;
|
||||
}
|
||||
__strace = st;
|
||||
g_ftrace = ft;
|
||||
#else
|
||||
kprintf("ShowBacktrace() needs these flags to show C backtrace:%n"
|
||||
"\t-D__FNO_OMIT_FRAME_POINTER__%n"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
|
@ -296,10 +297,11 @@ static wontreturn relegated noinstrument void __minicrash(int sig,
|
|||
relegated noinstrument void __oncrash(int sig, struct siginfo *si,
|
||||
ucontext_t *ctx) {
|
||||
intptr_t rip;
|
||||
int gdbpid, err;
|
||||
int gdbpid, err, st, ft;
|
||||
static bool noreentry, notpossible;
|
||||
--g_ftrace;
|
||||
if (cmpxchg(&noreentry, false, true)) {
|
||||
st = __strace, __strace = 0;
|
||||
ft = g_ftrace, g_ftrace = 0;
|
||||
if (lockcmpxchg(&noreentry, false, true)) {
|
||||
if (!__vforked) {
|
||||
rip = ctx ? ctx->uc_mcontext.rip : 0;
|
||||
err = errno;
|
||||
|
@ -326,9 +328,10 @@ relegated noinstrument void __oncrash(int sig, struct siginfo *si,
|
|||
}
|
||||
} else if (sig == SIGTRAP) {
|
||||
/* chances are IsDebuggerPresent() confused strace w/ gdb */
|
||||
++g_ftrace;
|
||||
g_ftrace = ft;
|
||||
__strace = st;
|
||||
return;
|
||||
} else if (cmpxchg(¬possible, false, true)) {
|
||||
} else if (lockcmpxchg(¬possible, false, true)) {
|
||||
__minicrash(sig, si, ctx, "WHILE CRASHING");
|
||||
} else {
|
||||
for (;;) {
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp KernelBase,__imp_UnmapViewOfFile2,UnmapViewOfFile2,1696
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp KernelBase,__imp_UnmapViewOfFileEx,UnmapViewOfFileEx,1697
|
|
@ -2,7 +2,7 @@
|
|||
.imp kernel32,__imp_CloseHandle,CloseHandle,0
|
||||
|
||||
.text.windows
|
||||
CloseHandle:
|
||||
__CloseHandle:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
|
@ -11,5 +11,5 @@ CloseHandle:
|
|||
call *__imp_CloseHandle(%rip)
|
||||
leave
|
||||
ret
|
||||
.endfn CloseHandle,globl
|
||||
.endfn __CloseHandle,globl
|
||||
.previous
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
.imp kernel32,__imp_CreateNamedPipeW,CreateNamedPipeW,0
|
||||
|
||||
.text.windows
|
||||
CreateNamedPipe:
|
||||
__CreateNamedPipe:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_CreateNamedPipeW(%rip),%rax
|
||||
jmp __sysv2nt8
|
||||
.endfn CreateNamedPipe,globl
|
||||
.endfn __CreateNamedPipe,globl
|
||||
.previous
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
.imp kernel32,__imp_CreatePipe,CreatePipe,0
|
||||
|
||||
.text.windows
|
||||
CreatePipe:
|
||||
__CreatePipe:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_CreatePipe(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn CreatePipe,globl
|
||||
.endfn __CreatePipe,globl
|
||||
.previous
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
.imp kernel32,__imp_FlushFileBuffers,FlushFileBuffers,0
|
||||
|
||||
.text.windows
|
||||
FlushFileBuffers:
|
||||
__FlushFileBuffers:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
|
@ -11,5 +11,5 @@ FlushFileBuffers:
|
|||
call *__imp_FlushFileBuffers(%rip)
|
||||
leave
|
||||
ret
|
||||
.endfn FlushFileBuffers,globl
|
||||
.endfn __FlushFileBuffers,globl
|
||||
.previous
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
.imp kernel32,__imp_FlushViewOfFile,FlushViewOfFile,0
|
||||
|
||||
.text.windows
|
||||
FlushViewOfFile:
|
||||
__FlushViewOfFile:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_FlushViewOfFile(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn FlushViewOfFile,globl
|
||||
.endfn __FlushViewOfFile,globl
|
||||
.previous
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
.imp kernel32,__imp_UnmapViewOfFile,UnmapViewOfFile,0
|
||||
|
||||
.text.windows
|
||||
UnmapViewOfFile:
|
||||
__UnmapViewOfFile:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
|
@ -11,5 +11,5 @@ UnmapViewOfFile:
|
|||
call *__imp_UnmapViewOfFile(%rip)
|
||||
leave
|
||||
ret
|
||||
.endfn UnmapViewOfFile,globl
|
||||
.endfn __UnmapViewOfFile,globl
|
||||
.previous
|
||||
|
|
12
libc/nt/kernel32/UnmapViewOfFile2.s
Normal file
12
libc/nt/kernel32/UnmapViewOfFile2.s
Normal file
|
@ -0,0 +1,12 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp kernel32,__imp_UnmapViewOfFile2,UnmapViewOfFile2,0
|
||||
|
||||
.text.windows
|
||||
UnmapViewOfFile2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_UnmapViewOfFile2(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn UnmapViewOfFile2,globl
|
||||
.previous
|
12
libc/nt/kernel32/UnmapViewOfFileEx.s
Normal file
12
libc/nt/kernel32/UnmapViewOfFileEx.s
Normal file
|
@ -0,0 +1,12 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp kernel32,__imp_UnmapViewOfFileEx,UnmapViewOfFileEx,0
|
||||
|
||||
.text.windows
|
||||
UnmapViewOfFileEx:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_UnmapViewOfFileEx(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn UnmapViewOfFileEx,globl
|
||||
.previous
|
|
@ -418,7 +418,7 @@ imp 'CloseEventLog' CloseEventLog advapi32 1102
|
|||
imp 'CloseFigure' CloseFigure gdi32 1045
|
||||
imp 'CloseGestureInfoHandle' CloseGestureInfoHandle user32 1589
|
||||
imp 'CloseGlobalizationUserSettingsKey' CloseGlobalizationUserSettingsKey KernelBase 133
|
||||
imp 'CloseHandle' CloseHandle kernel32 0 1 # KernelBase
|
||||
imp '__CloseHandle' CloseHandle kernel32 0 1 # KernelBase
|
||||
imp 'CloseMetaFile' CloseMetaFile gdi32 1046
|
||||
imp 'ClosePackageInfo' ClosePackageInfo kernel32 0 # KernelBase
|
||||
imp 'ClosePrivateNamespace' ClosePrivateNamespace kernel32 0 # KernelBase
|
||||
|
@ -624,7 +624,7 @@ imp 'CreateMutex' CreateMutexW kernel32 0 # KernelBase
|
|||
imp 'CreateMutexA' CreateMutexA kernel32 0 # KernelBase
|
||||
imp 'CreateMutexEx' CreateMutexExW kernel32 0 # KernelBase
|
||||
imp 'CreateMutexExA' CreateMutexExA kernel32 0 # KernelBase
|
||||
imp 'CreateNamedPipe' CreateNamedPipeW kernel32 0 8 # KernelBase
|
||||
imp '__CreateNamedPipe' CreateNamedPipeW kernel32 0 8 # KernelBase
|
||||
imp 'CreateNamedPipeA' CreateNamedPipeA kernel32 219 8
|
||||
imp 'CreateOPMProtectedOutput' CreateOPMProtectedOutput gdi32 1089
|
||||
imp 'CreateOPMProtectedOutputs' CreateOPMProtectedOutputs gdi32 1090
|
||||
|
@ -633,7 +633,7 @@ imp 'CreatePalmRejectionDelayZone' CreatePalmRejectionDelayZone user32 15
|
|||
imp 'CreatePatternBrush' CreatePatternBrush gdi32 1092
|
||||
imp 'CreatePen' CreatePen gdi32 1093
|
||||
imp 'CreatePenIndirect' CreatePenIndirect gdi32 1094
|
||||
imp 'CreatePipe' CreatePipe kernel32 0 4 # KernelBase
|
||||
imp '__CreatePipe' CreatePipe kernel32 0 4 # KernelBase
|
||||
imp 'CreatePolyPolygonRgn' CreatePolyPolygonRgn gdi32 1095
|
||||
imp 'CreatePolygonRgn' CreatePolygonRgn gdi32 1096
|
||||
imp 'CreatePopupMenu' CreatePopupMenu user32 1622 0
|
||||
|
@ -1677,11 +1677,11 @@ imp 'FlsGetValue' FlsGetValue kernel32 0 # KernelBase
|
|||
imp 'FlsSetValue' FlsSetValue kernel32 0 # KernelBase
|
||||
imp 'FlushConsoleInputBuffer' FlushConsoleInputBuffer kernel32 0 1 # KernelBase
|
||||
imp 'FlushEfsCache' FlushEfsCache advapi32 1303
|
||||
imp 'FlushFileBuffers' FlushFileBuffers kernel32 0 1 # KernelBase
|
||||
imp '__FlushFileBuffers' FlushFileBuffers kernel32 0 1 # KernelBase
|
||||
imp 'FlushInstructionCache' FlushInstructionCache kernel32 0 # KernelBase
|
||||
imp 'FlushTraceA' FlushTraceA advapi32 1304
|
||||
imp 'FlushTrace' FlushTraceW advapi32 1305
|
||||
imp 'FlushViewOfFile' FlushViewOfFile kernel32 0 2 # KernelBase
|
||||
imp '__FlushViewOfFile' FlushViewOfFile kernel32 0 2 # KernelBase
|
||||
imp 'FoldStringA' FoldStringA kernel32 424
|
||||
imp 'FoldString' FoldStringW kernel32 0 # KernelBase
|
||||
imp 'FontIsLinked' FontIsLinked gdi32 1484
|
||||
|
@ -6714,9 +6714,9 @@ imp 'UnlockFile' UnlockFile kernel32 0 5 # KernelBase
|
|||
imp 'UnlockFileEx' UnlockFileEx kernel32 0 5 # KernelBase
|
||||
imp 'UnlockServiceDatabase' UnlockServiceDatabase advapi32 1820
|
||||
imp 'UnlockWindowStation' UnlockWindowStation user32 2456
|
||||
imp 'UnmapViewOfFile' UnmapViewOfFile kernel32 0 1 # KernelBase
|
||||
imp 'UnmapViewOfFile2' UnmapViewOfFile2 KernelBase 1696
|
||||
imp 'UnmapViewOfFileEx' UnmapViewOfFileEx KernelBase 1697
|
||||
imp '__UnmapViewOfFile' UnmapViewOfFile kernel32 0 1 # KernelBase
|
||||
imp 'UnmapViewOfFile2' UnmapViewOfFile2 kernel32 0 2 # KernelBase
|
||||
imp 'UnmapViewOfFileEx' UnmapViewOfFileEx kernel32 0 3 # KernelBase
|
||||
imp 'UnpackDDElParam' UnpackDDElParam user32 2457
|
||||
imp 'UnrealizeObject' UnrealizeObject gdi32 1934
|
||||
imp 'UnregisterApplicationRecoveryCallback' UnregisterApplicationRecoveryCallback kernel32 1466
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#define CopyFile(...) __imp_CopyFileW(__VA_ARGS__)
|
||||
extern typeof(CopyFile) *const __imp_CopyFileW __msabi;
|
||||
|
||||
#define FlushFileBuffers(...) __imp_FlushFileBuffers(__VA_ARGS__)
|
||||
extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers __msabi;
|
||||
|
||||
#define GetFileType(...) __imp_GetFileType(__VA_ARGS__)
|
||||
extern typeof(GetFileType) *const __imp_GetFileType __msabi;
|
||||
|
|
|
@ -1,6 +1 @@
|
|||
#define FlushViewOfFile(...) __imp_FlushViewOfFile(__VA_ARGS__)
|
||||
#define UnmapViewOfFile(...) __imp_UnmapViewOfFile(__VA_ARGS__)
|
||||
|
||||
extern typeof(LocalFree) *const __imp_LocalFree __msabi;
|
||||
extern typeof(UnmapViewOfFile) *const __imp_UnmapViewOfFile __msabi;
|
||||
extern typeof(FlushViewOfFile) *const __imp_FlushViewOfFile __msabi;
|
||||
|
|
|
@ -43,7 +43,7 @@ static bool have_getrandom;
|
|||
/**
|
||||
* Returns cryptographic random data.
|
||||
*
|
||||
* This random number seed generator blends information from:
|
||||
* This random number seed generator obtains information from:
|
||||
*
|
||||
* - getrandom() on Linux
|
||||
* - RtlGenRandom() on Windows
|
||||
|
@ -61,6 +61,9 @@ static bool have_getrandom;
|
|||
* This function is safe to use with fork() and vfork(). It will also
|
||||
* close any file descriptor it ends up needing before it returns.
|
||||
*
|
||||
* @note this function could block a nontrivial time on old computers
|
||||
* @note this function is indeed intended for cryptography
|
||||
* @note this function takes around 900 cycles
|
||||
* @asyncsignalsafe
|
||||
* @restartable
|
||||
* @vforksafe
|
||||
|
|
|
@ -7,7 +7,7 @@ forceinline uint64_t KnuthLinearCongruentialGenerator(uint64_t prev[1]) {
|
|||
Seminumerical Algorithms, Third Edition, Addison-Wesley, 1998,
|
||||
p. 106 (line 26) & p. 108 */
|
||||
prev[0] = prev[0] * 6364136223846793005 + 1442695040888963407;
|
||||
return prev[0];
|
||||
return prev[0]; /* be sure to shift! */
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
45
libc/rand/lemur64.c
Normal file
45
libc/rand/lemur64.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- 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 2022 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/rand/rand.h"
|
||||
|
||||
/**
|
||||
* Returns linear congruential deterministic pseudorandom data, e.g.
|
||||
*
|
||||
* uint64_t x = lemur64();
|
||||
*
|
||||
* You can generate different types of numbers as follows:
|
||||
*
|
||||
* int64_t x = lemur64() >> 1; // make positive signed integer
|
||||
* double x = _real1(lemur64()); // make float on [0,1]-interval
|
||||
*
|
||||
* If you want a fast pseudorandom number generator that seeds itself
|
||||
* automatically on startup and fork() then consider rand64(). If you
|
||||
* want true random data then consider rdseed, rdrand, and getrandom.
|
||||
*
|
||||
* @return 64 bits of pseudorandom data
|
||||
* @note this is Lemire's Lehmer generator
|
||||
* @note this function takes at minimum 1 cycle
|
||||
* @note this function passes bigcrush and practrand
|
||||
* @note this function is not intended for cryptography
|
||||
* @see rand64(), rngset(), _real1(), _real2(), _real3()
|
||||
*/
|
||||
uint64_t lemur64(void) {
|
||||
static uint128_t s = 2131259787901769494;
|
||||
return (s *= 15750249268501108917ull) >> 64;
|
||||
}
|
|
@ -21,11 +21,18 @@
|
|||
#include "libc/rand/rand.h"
|
||||
|
||||
/**
|
||||
* Returns 31-bit random number using a linear congruential generator.
|
||||
* Returns 31-bit linear congruential pseudorandom number, e.g.
|
||||
*
|
||||
* Please note that, unlike rand32(), the rand() function uses the same
|
||||
* seed at startup by default, unless srand() is called. This makes it
|
||||
* useful in cases where deterministic behavior is needed.
|
||||
* int x = rand();
|
||||
* assert(x >= 0);
|
||||
*
|
||||
* This function always returns a positive number. If srand() isn't
|
||||
* called, then it'll return the same sequence each time your program
|
||||
* runs. Faster and more modern alternatives exist to this function.
|
||||
*
|
||||
* @note this function does well on bigcrush and practrand
|
||||
* @note this function is not intended for cryptography
|
||||
* @see lemur64(), rand64(), rdrand()
|
||||
*/
|
||||
int rand(void) {
|
||||
return KnuthLinearCongruentialGenerator(&g_rando) >> 33;
|
||||
|
|
|
@ -23,12 +23,13 @@ char *setstate(char *);
|
|||
long random(void);
|
||||
void srandom(unsigned);
|
||||
|
||||
uint64_t lemur64(void);
|
||||
uint64_t rand64(void);
|
||||
uint64_t vigna(void);
|
||||
uint64_t vigna_r(uint64_t[hasatleast 1]);
|
||||
void svigna(uint64_t);
|
||||
uint64_t rdrand(void);
|
||||
uint64_t rdseed(void);
|
||||
uint64_t rand64(void);
|
||||
void _smt19937(uint64_t);
|
||||
void _Smt19937(uint64_t[], size_t);
|
||||
uint64_t _mt19937(void);
|
||||
|
|
|
@ -16,59 +16,80 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/xadd.h"
|
||||
#include "libc/bits/lockcmpxchg16b.internal.h"
|
||||
#include "libc/bits/lockxadd.internal.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/thread/create.h"
|
||||
|
||||
static uint64_t thepool;
|
||||
extern int __pid;
|
||||
static int thepid;
|
||||
static int thecount;
|
||||
static uint128_t thepool;
|
||||
|
||||
/**
|
||||
* Returns nondeterministic random data.
|
||||
*
|
||||
* This function automatically seeds itself on startup and reseeds
|
||||
* itself after fork() and vfork(). It takes about nanosecond to run.
|
||||
* That makes it much slower than vigna() and rand() but much faster
|
||||
* than rdrand() and rdseed().
|
||||
* This function is similar to lemur64() except it'thepool intended to
|
||||
* be unpredictable. This PRNG automatically seeds itself on startup
|
||||
* using a much stronger and faster random source than `srand(time(0))`.
|
||||
* This function will automatically reseed itself when new processes and
|
||||
* threads are spawned. This function is thread safe in the sense that a
|
||||
* race condition can't happen where two threads return the same result.
|
||||
*
|
||||
* @see rdseed(), rdrand(), rand(), random(), rngset()
|
||||
* @note based on vigna's algorithm
|
||||
* @note this function is not intended for cryptography
|
||||
* @note this function passes bigcrush and practrand
|
||||
* @note this function takes at minimum 30 cycles
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
uint64_t rand64(void) {
|
||||
bool cf;
|
||||
register uint64_t t;
|
||||
if (X86_HAVE(RDSEED)) {
|
||||
asm volatile(CFLAG_ASM("rdseed\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(t)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) {
|
||||
thepool ^= t;
|
||||
return t;
|
||||
void *d;
|
||||
int c1, p1, p2;
|
||||
uint128_t s1, s2;
|
||||
do {
|
||||
p1 = __pid;
|
||||
p2 = thepid;
|
||||
c1 = thecount;
|
||||
asm volatile("" ::: "memory");
|
||||
s1 = thepool;
|
||||
if (p1 == p2) {
|
||||
// fast path
|
||||
s2 = s1;
|
||||
} else {
|
||||
// slow path
|
||||
if (!p2) {
|
||||
// first call so get some cheap entropy
|
||||
if ((d = (void *)getauxval(AT_RANDOM))) {
|
||||
memcpy(&s2, d, 16); // kernel entropy
|
||||
} else {
|
||||
s2 = kStartTsc; // rdtsc() @ _start()
|
||||
}
|
||||
} else {
|
||||
// process contention so blend a timestamp
|
||||
s2 = s1 ^ rdtsc();
|
||||
}
|
||||
// toss the new pid in there
|
||||
s2 ^= p1;
|
||||
// ordering for thepid probably doesn't matter
|
||||
thepid = p1;
|
||||
}
|
||||
}
|
||||
t = _xadd(&thepool, 0x9e3779b97f4a7c15);
|
||||
t ^= (getpid() * 0x1001111111110001ull + 0xdeaadead) >> 31;
|
||||
t = (t ^ (t >> 30)) * 0xbf58476d1ce4e5b9;
|
||||
t = (t ^ (t >> 27)) * 0x94d049bb133111eb;
|
||||
return t ^ (t >> 31);
|
||||
// lemur64 pseudorandom number generator
|
||||
s2 *= 15750249268501108917ull;
|
||||
// sadly 128-bit values aren't atomic on x86
|
||||
_lockcmpxchg16b(&thepool, &s1, s2);
|
||||
// do it again if there's thread contention
|
||||
} while (_lockxadd(&thecount, 1) != c1);
|
||||
// the most important step in the prng
|
||||
return s2 >> 64;
|
||||
}
|
||||
|
||||
static textstartup void rand64_init(int argc, char **argv, char **envp,
|
||||
intptr_t *auxv) {
|
||||
for (; auxv[0]; auxv += 2) {
|
||||
if (auxv[0] == AT_RANDOM) {
|
||||
thepool = READ64LE((const char *)auxv[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
thepool = kStartTsc;
|
||||
}
|
||||
|
||||
const void *const g_rand64_init[] initarray = {rand64_init};
|
||||
|
|
|
@ -55,9 +55,12 @@ static dontinline uint64_t rdrand_failover(void) {
|
|||
* aren't available then we try /dev/urandom and if that fails, we try
|
||||
* getauxval(AT_RANDOM), and if not we finally use RDTSC and getpid().
|
||||
*
|
||||
* This function takes between 10 nanoseconds to several microseconds.
|
||||
*
|
||||
* @note this function could block a nontrivial time on old computers
|
||||
* @note this function is indeed intended for cryptography
|
||||
* @note this function takes around 300 cycles
|
||||
* @see rngset(), rdseed(), rand64()
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
uint64_t rdrand(void) {
|
||||
int i;
|
||||
|
|
|
@ -31,9 +31,12 @@
|
|||
* sysctl(KERN_ARND). If those aren't available then we try /dev/urandom
|
||||
* and if that fails, we use RDTSC and getpid().
|
||||
*
|
||||
* This function takes about 32 nanoseconds.
|
||||
*
|
||||
* @note this function could block a nontrivial time on old computers
|
||||
* @note this function is indeed intended for cryptography
|
||||
* @note this function takes around 800 cycles
|
||||
* @see rngset(), rdrand(), rand64()
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
uint64_t rdseed(void) {
|
||||
int i;
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
/**
|
||||
* Generates number on [0,1]-real-interval, e.g.
|
||||
*
|
||||
* double x = _real1(vigna())
|
||||
* double x = _real1(lemur64())
|
||||
*
|
||||
* @see vigna(), mt19937()
|
||||
* @see lemur64(), mt19937()
|
||||
*/
|
||||
double _real1(uint64_t x) {
|
||||
return 1. / 9007199254740991. * (x >> 11);
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
/**
|
||||
* Generates number on [0,1)-real-interval, e.g.
|
||||
*
|
||||
* double x = _real2(vigna())
|
||||
* double x = _real2(lemur64())
|
||||
*
|
||||
* @see vigna(), mt19937()
|
||||
* @see lemur64(), mt19937()
|
||||
*/
|
||||
double _real2(uint64_t x) {
|
||||
return 1. / 9007199254740992. * (x >> 11);
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
/**
|
||||
* Generates number on (0,1)-real-interval, e.g.
|
||||
*
|
||||
* double x = _real3(vigna())
|
||||
* double x = _real3(lemur64())
|
||||
*
|
||||
* @see vigna(), mt19937()
|
||||
* @see lemur64(), mt19937()
|
||||
*/
|
||||
double _real3(uint64_t x) {
|
||||
return 1. / 4503599627370496. * ((x >> 12) + .5);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/xadd.h"
|
||||
#include "libc/rand/rand.h"
|
||||
|
||||
static uint64_t g_vigna;
|
||||
|
@ -40,9 +39,8 @@ static uint64_t g_vigna;
|
|||
* static uint64_t s = 0;
|
||||
* uint64_t x = svigna_r(&s);
|
||||
*
|
||||
* This function is the fastest way to generate good scalar pseudorandom
|
||||
* numbers that aren't truncated. If you want to fill a buffer with data
|
||||
* then rngset() implements vigna's algorithm to do that extremely well:
|
||||
* If you want to fill a buffer with data then rngset() implements
|
||||
* vigna's algorithm to do that extremely well:
|
||||
*
|
||||
* char buf[4096];
|
||||
* rngset(buf, sizeof(buf), vigna, 0);
|
||||
|
@ -52,6 +50,9 @@ static uint64_t g_vigna;
|
|||
* want true random data then consider rdseed, rdrand, and getrandom.
|
||||
*
|
||||
* @return 64 bits of pseudorandom data
|
||||
* @note this function is not intended for cryptography
|
||||
* @note this function passes bigcrush and practrand
|
||||
* @note this function takes at minimum 4 cycles
|
||||
*/
|
||||
uint64_t vigna(void) {
|
||||
return vigna_r(&g_vigna);
|
||||
|
|
|
@ -29,7 +29,9 @@ textwindows wontreturn void sys_abort_nt(void) {
|
|||
info.si_signo = SIGABRT;
|
||||
rva = __sighandrvas[SIGABRT];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
((sigaction_f)(_base + rva))(SIGABRT, &info, NULL);
|
||||
if (((sigaction_f)(_base + rva))) {
|
||||
((sigaction_f)(_base + rva))(SIGABRT, &info, NULL);
|
||||
}
|
||||
}
|
||||
_Exit(128 + SIGABRT);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/nt2sysv.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
|
@ -24,6 +25,8 @@
|
|||
#include "libc/nt/thread.h"
|
||||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
struct WinThread {
|
||||
|
@ -32,7 +35,7 @@ struct WinThread {
|
|||
void *stack;
|
||||
};
|
||||
|
||||
static noasan textwindows uint32_t winthread(void *param) {
|
||||
static noasan textwindows uint32_t WinThreadMain(void *param) {
|
||||
struct WinThread *wt = param;
|
||||
asm volatile("mov\t%%rbp,%%r14\n\t"
|
||||
"mov\t%%rsp,%%r15\n\t"
|
||||
|
@ -50,15 +53,19 @@ static noasan textwindows uint32_t winthread(void *param) {
|
|||
/**
|
||||
* Creates thread.
|
||||
*
|
||||
* @note CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND creates thread
|
||||
* @note CLONE_VFORK|CLONE_VM|SIGCHLD does vfork()
|
||||
* @note SIGCHLD does fork()
|
||||
* @param flags usually has one of
|
||||
* - `CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND` for threads
|
||||
* - `CLONE_VFORK|CLONE_VM|SIGCHLD` for vfork()
|
||||
* - `SIGCHLD` for fork()
|
||||
* as part high bytes, and the low order byte may optionally contain
|
||||
* a signal e.g. SIGCHLD, to enable parent notification on terminate
|
||||
*/
|
||||
privileged int clone(int (*f)(void *), void *stack, int flags, void *arg, ...) {
|
||||
int64_t h;
|
||||
int tidfd;
|
||||
va_list va;
|
||||
intptr_t ax;
|
||||
uint32_t tid;
|
||||
int64_t hand;
|
||||
int32_t *ptid;
|
||||
register void *tls asm("r8");
|
||||
register int32_t *ctid asm("r10");
|
||||
|
@ -90,11 +97,16 @@ privileged int clone(int (*f)(void *), void *stack, int flags, void *arg, ...) {
|
|||
: "memory");
|
||||
unreachable;
|
||||
} else if (IsWindows()) {
|
||||
if (flags == (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)) {
|
||||
if ((h = CreateThread(0, PAGESIZE, NT2SYSV(winthread),
|
||||
&(struct WinThread){f, arg, stack}, 0, &tid))) {
|
||||
CloseHandle(h);
|
||||
return tid;
|
||||
if ((tidfd = __reservefd()) == -1) return -1;
|
||||
if (flags == CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND) {
|
||||
if ((hand = CreateThread(&kNtIsInheritable, 0, NT2SYSV(WinThreadMain),
|
||||
&(struct WinThread){f, arg, stack}, 0, &tid))) {
|
||||
// XXX: this should be tracked in a separate data structure
|
||||
g_fds.p[tidfd].kind = kFdProcess;
|
||||
g_fds.p[tidfd].handle = hand;
|
||||
g_fds.p[tidfd].flags = O_CLOEXEC;
|
||||
g_fds.p[tidfd].zombie = false;
|
||||
return tidfd;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct ProtectNt {
|
||||
uint32_t flags1;
|
||||
uint32_t flags2;
|
||||
};
|
||||
|
||||
struct DirectMap {
|
||||
void *addr;
|
||||
int64_t maphandle;
|
||||
|
@ -12,6 +17,8 @@ struct DirectMap sys_mmap(void *, size_t, int, int, int, int64_t);
|
|||
struct DirectMap sys_mmap_nt(void *, size_t, int, int, int64_t, int64_t);
|
||||
struct DirectMap sys_mmap_metal(void *, size_t, int, int, int, int64_t);
|
||||
int sys_munmap_metal(void *, size_t);
|
||||
uint32_t __prot2nt(int, int);
|
||||
struct ProtectNt __nt2prot(int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -177,23 +177,8 @@ textwindows void WinMainForked(void) {
|
|||
}
|
||||
} else {
|
||||
// we can however safely inherit MAP_SHARED with zero copy
|
||||
if (maps[i].prot & PROT_WRITE) {
|
||||
if (maps[i].prot & PROT_EXEC) {
|
||||
flags2 = kNtFileMapWrite | kNtFileMapExecute;
|
||||
} else {
|
||||
flags2 = kNtFileMapWrite;
|
||||
}
|
||||
} else if (maps[i].prot & PROT_READ) {
|
||||
if (maps[i].prot & PROT_EXEC) {
|
||||
flags2 = kNtFileMapRead | kNtFileMapExecute;
|
||||
} else {
|
||||
flags2 = kNtFileMapRead;
|
||||
}
|
||||
} else {
|
||||
flags2 = 0;
|
||||
}
|
||||
if (!MapViewOfFileEx(maps[i].h, flags2, maps[i].offset >> 32,
|
||||
maps[i].offset, size, addr)) {
|
||||
if (!MapViewOfFileEx(maps[i].h, __nt2prot(maps[i].prot).flags2,
|
||||
maps[i].offset >> 32, maps[i].offset, size, addr)) {
|
||||
ExitProcess(45);
|
||||
}
|
||||
}
|
||||
|
@ -216,29 +201,14 @@ textwindows void WinMainForked(void) {
|
|||
_mmi.n = specialz / sizeof(_mmi.p[0]);
|
||||
for (i = 0; i < mapcount; ++i) {
|
||||
if ((maps[i].flags & MAP_PRIVATE) && (~maps[i].prot & PROT_WRITE)) {
|
||||
if (maps[i].prot & PROT_WRITE) {
|
||||
if (maps[i].prot & PROT_EXEC) {
|
||||
flags1 = kNtPageExecuteReadwrite;
|
||||
} else {
|
||||
flags1 = kNtPageReadwrite;
|
||||
}
|
||||
} else if (maps[i].prot & PROT_READ) {
|
||||
if (maps[i].prot & PROT_EXEC) {
|
||||
flags1 = kNtPageExecuteRead;
|
||||
} else {
|
||||
flags1 = kNtPageReadonly;
|
||||
}
|
||||
} else {
|
||||
flags1 = kNtPageNoaccess;
|
||||
}
|
||||
VirtualProtect((void *)((uint64_t)maps[i].x << 16),
|
||||
ROUNDUP(maps[i].size, FRAMESIZE), flags1, &oldprot);
|
||||
ROUNDUP(maps[i].size, FRAMESIZE),
|
||||
__nt2prot(maps[i].prot).flags1, &oldprot);
|
||||
}
|
||||
}
|
||||
|
||||
// we're all done reading!
|
||||
if (!CloseHandle(reader)) {
|
||||
STRACE("CloseHandle(reader) failed %m");
|
||||
ExitProcess(47);
|
||||
}
|
||||
|
||||
|
@ -309,7 +279,6 @@ textwindows int sys_fork_nt(void) {
|
|||
if (ok) ok = WriteAll(writer, __bss_start, __bss_end - __bss_start);
|
||||
if (ok) {
|
||||
if (!CloseHandle(writer)) {
|
||||
STRACE("CloseHandle(writer) failed %m");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +301,7 @@ textwindows int sys_fork_nt(void) {
|
|||
}
|
||||
} else {
|
||||
STRACE("CreatePipe() failed %m");
|
||||
rc = __winerr();
|
||||
rc = -1;
|
||||
CloseHandle(writer);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -37,11 +37,7 @@ noasan void ReleaseMemoryNt(struct MemoryIntervals *mm, int l, int r) {
|
|||
for (i = l; i <= r; ++i) {
|
||||
addr = GetFrameAddr(mm->p[i].x);
|
||||
last = GetFrameAddr(mm->p[i].y);
|
||||
STRACE("UnmapViewOfFile(%p, size:%'zu, hand:%ld)", addr,
|
||||
last - addr + FRAMESIZE, mm->p[i].h);
|
||||
ok = UnmapViewOfFile(addr);
|
||||
assert(ok);
|
||||
ok = CloseHandle(mm->p[i].h);
|
||||
assert(ok);
|
||||
UnmapViewOfFile(addr);
|
||||
CloseHandle(mm->p[i].h);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,22 +17,40 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/sysv/consts/msync.h"
|
||||
|
||||
noasan textwindows int sys_msync_nt(void *addr, size_t size, int flags) {
|
||||
int x, y, l, r, i;
|
||||
x = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
|
||||
y = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
|
||||
for (i = FindMemoryInterval(&_mmi, x); i < _mmi.i; ++i) {
|
||||
if ((x >= _mmi.p[i].x && x <= _mmi.p[i].y) ||
|
||||
(y >= _mmi.p[i].x && y <= _mmi.p[i].y)) {
|
||||
FlushFileBuffers(_mmi.p[i].h);
|
||||
#define ADDR(x) ((char *)((int64_t)((uint64_t)(x) << 32) >> 16))
|
||||
|
||||
noasan textwindows int sys_msync_nt(char *addr, size_t size, int flags) {
|
||||
char *a, *b;
|
||||
int rc, x, y, l, r, i;
|
||||
rc = 0;
|
||||
for (i = FindMemoryInterval(&_mmi, (intptr_t)addr >> 16); i < _mmi.i; ++i) {
|
||||
if ((ADDR(_mmi.p[i].x) <= addr && addr < ADDR(_mmi.p[i].y + 1)) ||
|
||||
(ADDR(_mmi.p[i].x) < addr + size &&
|
||||
addr + size <= ADDR(_mmi.p[i].y + 1)) ||
|
||||
(addr < ADDR(_mmi.p[i].x) && ADDR(_mmi.p[i].y + 1) < addr + size)) {
|
||||
a = MIN(MAX(addr, ADDR(_mmi.p[i].x)), ADDR(_mmi.p[i].y + 1));
|
||||
b = MAX(MIN(addr + size, ADDR(_mmi.p[i].y + 1)), ADDR(_mmi.p[i].x));
|
||||
if (!FlushViewOfFile(a, b - a)) {
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
if (flags & MS_SYNC) {
|
||||
if (!FlushFileBuffers(_mmi.p[i].h)) {
|
||||
// TODO(jart): what's up with this?
|
||||
// rc = -1;
|
||||
// break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ textwindows int sys_socketpair_nt(int family, int type, int proto, int sv[2]) {
|
|||
}
|
||||
if ((hpipe = CreateNamedPipe(pipename, kNtPipeAccessDuplex, mode, 1, 65536,
|
||||
65536, 0, &kNtIsInheritable)) == -1) {
|
||||
__winerr();
|
||||
__releasefd(writer);
|
||||
__releasefd(reader);
|
||||
return -1;
|
||||
|
|
|
@ -909,6 +909,14 @@ syscon ptrace PTRACE_EVENT_EXEC 4 -1 -1 -1 -1 -1
|
|||
syscon ptrace PTRACE_EVENT_VFORK_DONE 5 -1 -1 -1 -1 -1
|
||||
syscon ptrace PTRACE_EVENT_EXIT 6 -1 -1 -1 -1 -1
|
||||
|
||||
# clone() codes
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon clone CLONE_VM 0x00000100 0x00000100 0x00000100 0x00000100 0x00000100 0x00000100 # intentionally symbolic so we can tell if clone() is being used to create threads
|
||||
|
||||
# IPPROTO_*
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon iproto IPPROTO_IP 0 0 0 0 0 0 # consensus
|
||||
syscon iproto IPPROTO_ICMP 1 1 1 1 1 1 # consensus
|
||||
syscon iproto IPPROTO_TCP 6 6 6 6 6 6 # consensus
|
||||
|
|
2
libc/sysv/consts/CLONE_VM.S
Normal file
2
libc/sysv/consts/CLONE_VM.S
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon clone,CLONE_VM,0x00000100,0x00000100,0x00000100,0x00000100,0x00000100,0x00000100
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon nr,__NR_sigprocmask,0x000e,0x2000030,0x0154,0x0030,0x125,0xfff
|
||||
.syscon nr,__NR_sigprocmask,0x000e,0x2000149,0x0154,0x0030,0x125,0xfff
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_
|
||||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_
|
||||
#include "libc/runtime/symbolic.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define CLONE_VM 0x00000100
|
||||
extern const long CLONE_VM;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
||||
#define CLONE_VM SYMBOLIC(CLONE_VM)
|
||||
#define CLONE_FS 0x00000200
|
||||
#define CLONE_FILES 0x00000400
|
||||
#define CLONE_SIGHAND 0x00000800
|
||||
|
@ -21,6 +27,4 @@ COSMOPOLITAN_C_START_
|
|||
#define CLONE_CHILD_SETTID 0x01000000
|
||||
#define CLONE_STOPPED 0x02000000
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_ */
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
static uint64_t Rando(void) {
|
||||
uint64_t x;
|
||||
do x = vigna();
|
||||
do x = lemur64();
|
||||
while (((x ^ READ64LE("!!!!!!!!")) - 0x0101010101010101) &
|
||||
~(x ^ READ64LE("!!!!!!!!")) & 0x8080808080808080);
|
||||
return x;
|
||||
|
@ -225,7 +225,7 @@ TEST(ksnprintf, fuzzTheUnbreakable) {
|
|||
x = Rando();
|
||||
memcpy(f + 8, &x, sizeof(x));
|
||||
f[Rando() & 15] = '%';
|
||||
ksnprintf(b, sizeof(b), f, vigna(), vigna(), vigna());
|
||||
ksnprintf(b, sizeof(b), f, lemur64(), lemur64(), lemur64());
|
||||
}
|
||||
EXPECT_SYS(0, 0, mprotect(f, PAGESIZE, PROT_READ));
|
||||
}
|
||||
|
|
|
@ -121,17 +121,17 @@ BENCH(bcmp, bench) {
|
|||
EZBENCH_N("bcmp", 256, v = buncmp(a, b, 256));
|
||||
a = gc(malloc(16 * 1024));
|
||||
b = gc(malloc(16 * 1024));
|
||||
rngset(a, 16 * 1024, vigna, -1);
|
||||
rngset(a, 16 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 16 * 1024);
|
||||
EZBENCH_N("bcmp", 16384, v = buncmp(a, b, 16384));
|
||||
a = gc(malloc(32 * 1024));
|
||||
b = gc(malloc(32 * 1024));
|
||||
rngset(a, 32 * 1024, vigna, -1);
|
||||
rngset(a, 32 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 32 * 1024);
|
||||
EZBENCH_N("bcmp", 32768, v = buncmp(a, b, 32768));
|
||||
a = gc(malloc(128 * 1024));
|
||||
b = gc(malloc(128 * 1024));
|
||||
rngset(a, 128 * 1024, vigna, -1);
|
||||
rngset(a, 128 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 128 * 1024);
|
||||
EZBENCH_N("bcmp", 131072, v = buncmp(a, b, 131072));
|
||||
}
|
||||
|
@ -166,17 +166,17 @@ BENCH(memcmp, bench) {
|
|||
EZBENCH_N("memcmp", 256, v = funcmp(a, b, 256));
|
||||
a = gc(malloc(16 * 1024));
|
||||
b = gc(malloc(16 * 1024));
|
||||
rngset(a, 16 * 1024, vigna, -1);
|
||||
rngset(a, 16 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 16 * 1024);
|
||||
EZBENCH_N("memcmp", 16384, v = funcmp(a, b, 16384));
|
||||
a = gc(malloc(32 * 1024));
|
||||
b = gc(malloc(32 * 1024));
|
||||
rngset(a, 32 * 1024, vigna, -1);
|
||||
rngset(a, 32 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 32 * 1024);
|
||||
EZBENCH_N("memcmp", 32768, v = funcmp(a, b, 32768));
|
||||
a = gc(malloc(128 * 1024));
|
||||
b = gc(malloc(128 * 1024));
|
||||
rngset(a, 128 * 1024, vigna, -1);
|
||||
rngset(a, 128 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 128 * 1024);
|
||||
EZBENCH_N("memcmp", 131072, v = funcmp(a, b, 131072));
|
||||
}
|
||||
|
@ -211,17 +211,17 @@ BENCH(timingsafe_memcmp, bench) {
|
|||
EZBENCH_N("timingsafe_memcmp", 256, v = timingsafe_memcmp(a, b, 256));
|
||||
a = gc(malloc(16 * 1024));
|
||||
b = gc(malloc(16 * 1024));
|
||||
rngset(a, 16 * 1024, vigna, -1);
|
||||
rngset(a, 16 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 16 * 1024);
|
||||
EZBENCH_N("timingsafe_memcmp", 16384, v = timingsafe_memcmp(a, b, 16384));
|
||||
a = gc(malloc(32 * 1024));
|
||||
b = gc(malloc(32 * 1024));
|
||||
rngset(a, 32 * 1024, vigna, -1);
|
||||
rngset(a, 32 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 32 * 1024);
|
||||
EZBENCH_N("timingsafe_memcmp", 32768, v = timingsafe_memcmp(a, b, 32768));
|
||||
a = gc(malloc(128 * 1024));
|
||||
b = gc(malloc(128 * 1024));
|
||||
rngset(a, 128 * 1024, vigna, -1);
|
||||
rngset(a, 128 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 128 * 1024);
|
||||
EZBENCH_N("timingsafe_memcmp", 131072, v = timingsafe_memcmp(a, b, 131072));
|
||||
}
|
||||
|
@ -256,17 +256,17 @@ BENCH(timingsafe_bcmp, bench) {
|
|||
EZBENCH_N("timingsafe_bcmp", 256, v = timingsafe_bcmp(a, b, 256));
|
||||
a = gc(malloc(16 * 1024));
|
||||
b = gc(malloc(16 * 1024));
|
||||
rngset(a, 16 * 1024, vigna, -1);
|
||||
rngset(a, 16 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 16 * 1024);
|
||||
EZBENCH_N("timingsafe_bcmp", 16384, v = timingsafe_bcmp(a, b, 16384));
|
||||
a = gc(malloc(32 * 1024));
|
||||
b = gc(malloc(32 * 1024));
|
||||
rngset(a, 32 * 1024, vigna, -1);
|
||||
rngset(a, 32 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 32 * 1024);
|
||||
EZBENCH_N("timingsafe_bcmp", 32768, v = timingsafe_bcmp(a, b, 32768));
|
||||
a = gc(malloc(128 * 1024));
|
||||
b = gc(malloc(128 * 1024));
|
||||
rngset(a, 128 * 1024, vigna, -1);
|
||||
rngset(a, 128 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 128 * 1024);
|
||||
EZBENCH_N("timingsafe_bcmp", 131072, v = timingsafe_bcmp(a, b, 131072));
|
||||
}
|
||||
|
@ -301,17 +301,17 @@ BENCH(memcasecmp, bench) {
|
|||
EZBENCH_N("memcasecmp", 256, v = memcasecmp(a, b, 256));
|
||||
a = gc(malloc(16 * 1024));
|
||||
b = gc(malloc(16 * 1024));
|
||||
rngset(a, 16 * 1024, vigna, -1);
|
||||
rngset(a, 16 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 16 * 1024);
|
||||
EZBENCH_N("memcasecmp", 16384, v = memcasecmp(a, b, 16384));
|
||||
a = gc(malloc(32 * 1024));
|
||||
b = gc(malloc(32 * 1024));
|
||||
rngset(a, 32 * 1024, vigna, -1);
|
||||
rngset(a, 32 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 32 * 1024);
|
||||
EZBENCH_N("memcasecmp", 32768, v = memcasecmp(a, b, 32768));
|
||||
a = gc(malloc(128 * 1024));
|
||||
b = gc(malloc(128 * 1024));
|
||||
rngset(a, 128 * 1024, vigna, -1);
|
||||
rngset(a, 128 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 128 * 1024);
|
||||
EZBENCH_N("memcasecmp", 131072, v = memcasecmp(a, b, 131072));
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ BENCH(timingsafe_memcmp, demonstration) {
|
|||
int bcmp_(const void *, const void *, size_t) asm("bcmp");
|
||||
int memcmp_(const void *, const void *, size_t) asm("memcmp");
|
||||
char a[256], b[256];
|
||||
rngset(a, 256, vigna, -1);
|
||||
rngset(a, 256, lemur64, -1);
|
||||
memcpy(b, a, 256);
|
||||
++a[0];
|
||||
EZBENCH_N("bcmp ne", 256, bcmp_(a, b, 256));
|
||||
|
|
|
@ -39,7 +39,7 @@ TEST(memset, hug) {
|
|||
b = gc(malloc(1025 * 2));
|
||||
for (i = 0; i < 1025; ++i) {
|
||||
for (j = 0; j < 1025 - i; ++j) {
|
||||
c = vigna();
|
||||
c = lemur64();
|
||||
rngset(a, i + j, 0, 0);
|
||||
memcpy(b, a, i + j);
|
||||
ASSERT_EQ(a + i, golden(a + i, c, j));
|
||||
|
|
|
@ -155,6 +155,8 @@ TEST(mt19937, test) {
|
|||
|
||||
BENCH(mt19937, bench8) {
|
||||
volatile uint64_t x;
|
||||
EZBENCH2("lemur64", donothing, x = lemur64());
|
||||
EZBENCH2("rand64", donothing, x = rand64());
|
||||
EZBENCH2("vigna", donothing, x = vigna());
|
||||
EZBENCH2("vigna_r", donothing, vigna_r(&x));
|
||||
EZBENCH2("xorshift", donothing, x = xorshift());
|
||||
|
|
103
test/libc/rand/rand64_test.c
Normal file
103
test/libc/rand/rand64_test.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*-*- 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 2022 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/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
#define THREADS 1
|
||||
#define ENTRIES 10
|
||||
|
||||
volatile bool ready;
|
||||
volatile uint64_t A[THREADS * ENTRIES];
|
||||
|
||||
void OnChld(int sig) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
int Thrasher(void *arg) {
|
||||
int i, id = (intptr_t)arg;
|
||||
while (!ready) asm("pause");
|
||||
for (i = 0; i < ENTRIES; ++i) {
|
||||
A[id * ENTRIES + i] = rand64();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(rand64, testLcg_doesntProduceIdenticalValues) {
|
||||
int i, j;
|
||||
bzero(A, sizeof(A));
|
||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||
A[i] = rand64();
|
||||
}
|
||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||
EXPECT_NE(0, A[i], "i=%d", i);
|
||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||
if (i == j) continue;
|
||||
EXPECT_NE(A[i], A[j], "i=%d j=%d", i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(rand64, testThreadSafety_doesntProduceIdenticalValues) {
|
||||
char *stack;
|
||||
sigset_t ss, oldss;
|
||||
int i, j, rc, ws, tid[THREADS], ptid[THREADS], ctid[THREADS], tls[THREADS];
|
||||
if (!IsLinux() && !IsNetbsd()) return;
|
||||
struct sigaction oldsa;
|
||||
struct sigaction sa = {.sa_handler = OnChld, .sa_flags = SA_RESTART};
|
||||
EXPECT_NE(-1, sigaction(SIGCHLD, &sa, &oldsa));
|
||||
bzero(A, sizeof(A));
|
||||
rand64(); // for effect
|
||||
sigemptyset(&ss);
|
||||
sigaddset(&ss, SIGCHLD);
|
||||
EXPECT_EQ(0, sigprocmask(SIG_BLOCK, &ss, &oldss));
|
||||
ready = false;
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
stack = gc(malloc(FRAMESIZE));
|
||||
tid[i] = clone(Thrasher, stack + FRAMESIZE,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD,
|
||||
(void *)(intptr_t)i, ptid + i, tls + i, ctid + i);
|
||||
EXPECT_NE(-1, tid[i]);
|
||||
}
|
||||
ready = true;
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
EXPECT_NE(-1, (rc = waitpid(0, &ws, 0)));
|
||||
EXPECT_TRUE(WIFEXITED(ws));
|
||||
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
EXPECT_EQ(0, sigaction(SIGCHLD, &oldsa, 0));
|
||||
EXPECT_EQ(0, sigprocmask(SIG_BLOCK, &oldss, 0));
|
||||
for (i = 0; i < ARRAYLEN(A); ++i) {
|
||||
EXPECT_NE(0, A[i], "i=%d", i);
|
||||
for (j = 0; j < ARRAYLEN(A); ++j) {
|
||||
if (i == j) continue;
|
||||
EXPECT_NE(A[i], A[j], "i=%d j=%d", i, j);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ TEST(clone, test) {
|
|||
if (!IsLinux() && !IsNetbsd() && !IsWindows()) return;
|
||||
char *stack;
|
||||
long double t;
|
||||
int tid, ptid, ctid, tls, ws;
|
||||
int tid, ptid, ctid, tls;
|
||||
t = nowl();
|
||||
stack = gc(malloc(FRAMESIZE));
|
||||
EXPECT_NE(-1, (tid = clone(thread, stack + FRAMESIZE,
|
||||
|
|
|
@ -42,7 +42,7 @@ TEST(mmap, testMapFile) {
|
|||
int fd;
|
||||
char *p;
|
||||
char path[PATH_MAX];
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, vigna());
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, lemur64());
|
||||
ASSERT_NE(-1, (fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644)));
|
||||
EXPECT_EQ(5, write(fd, "hello", 5));
|
||||
EXPECT_NE(-1, fdatasync(fd));
|
||||
|
@ -56,7 +56,7 @@ TEST(mmap, testMapFile) {
|
|||
TEST(mmap, testMapFile_fdGetsClosed_makesNoDifference) {
|
||||
int fd;
|
||||
char *p, buf[16], path[PATH_MAX];
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, vigna());
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, lemur64());
|
||||
ASSERT_NE(-1, (fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644)));
|
||||
EXPECT_EQ(5, write(fd, "hello", 5));
|
||||
EXPECT_NE(-1, fdatasync(fd));
|
||||
|
@ -163,7 +163,7 @@ TEST(mmap, cow) {
|
|||
int fd;
|
||||
char *p;
|
||||
char path[PATH_MAX];
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, vigna());
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, lemur64());
|
||||
ASSERT_NE(-1, (fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644)));
|
||||
EXPECT_EQ(5, write(fd, "hello", 5));
|
||||
EXPECT_NE(-1, fdatasync(fd));
|
||||
|
@ -182,7 +182,7 @@ TEST(mmap, cowFileMapReadonlyFork) {
|
|||
char *p;
|
||||
int fd, pid, ws;
|
||||
char path[PATH_MAX], lol[6];
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, vigna());
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, lemur64());
|
||||
ASSERT_NE(-1, (fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644)));
|
||||
EXPECT_EQ(6, write(fd, "hello", 6));
|
||||
EXPECT_NE(-1, close(fd));
|
||||
|
@ -206,7 +206,7 @@ TEST(mmap, cowFileMapFork) {
|
|||
char *p;
|
||||
int fd, pid, ws;
|
||||
char path[PATH_MAX], lol[6];
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, vigna());
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, lemur64());
|
||||
ASSERT_NE(-1, (fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644)));
|
||||
EXPECT_EQ(6, write(fd, "parnt", 6));
|
||||
EXPECT_NE(-1, fdatasync(fd));
|
||||
|
@ -256,7 +256,7 @@ TEST(mmap, sharedFileMapFork) {
|
|||
char *p;
|
||||
int fd, pid, ws;
|
||||
char path[PATH_MAX], lol[6];
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, vigna());
|
||||
sprintf(path, "%s%s.%ld", kTmpPath, program_invocation_short_name, lemur64());
|
||||
ASSERT_NE(-1, (fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644)));
|
||||
EXPECT_EQ(6, write(fd, "parnt", 6));
|
||||
EXPECT_NE(-1, fdatasync(fd));
|
||||
|
|
|
@ -49,5 +49,5 @@ BENCH(asin, bench) {
|
|||
EZBENCH2("asin(-0)", donothing, asin(-0.));
|
||||
EZBENCH2("asin(NAN)", donothing, asin(NAN));
|
||||
EZBENCH2("asin(INFINITY)", donothing, asin(INFINITY));
|
||||
EZBENCH_C("asin", _real1(vigna()), asin(_real1(vigna())));
|
||||
EZBENCH_C("asin", _real1(lemur64()), asin(_real1(lemur64())));
|
||||
}
|
||||
|
|
6
third_party/mbedtls/bignum.c
vendored
6
third_party/mbedtls/bignum.c
vendored
|
@ -1128,7 +1128,7 @@ static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
|
|||
* the two input MPIs is not the same.
|
||||
*/
|
||||
int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
|
||||
unsigned *ret )
|
||||
unsigned *ret )
|
||||
{
|
||||
size_t i;
|
||||
/* The value of any of these variables is either 0 or 1 at all times. */
|
||||
|
@ -1949,8 +1949,8 @@ static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
|
|||
* Note that unlike the usual convention in the library
|
||||
* for `const mbedtls_mpi*`, the content of T can change.
|
||||
*/
|
||||
static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
|
||||
const mbedtls_mpi *T )
|
||||
static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N,
|
||||
mbedtls_mpi_uint mm, const mbedtls_mpi *T )
|
||||
{
|
||||
size_t i, n, m;
|
||||
mbedtls_mpi_uint u0, u1, *d, *Ap, *Bp, *Np;
|
||||
|
|
26
third_party/mbedtls/ccm.c
vendored
26
third_party/mbedtls/ccm.c
vendored
|
@ -381,10 +381,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
|
|||
* \return A CCM or cipher-specific error code on failure.
|
||||
*/
|
||||
int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
unsigned char *tag, size_t tag_len )
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
CCM_VALIDATE_RET( ctx );
|
||||
CCM_VALIDATE_RET( iv );
|
||||
|
@ -433,10 +433,10 @@ int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
|||
* \return A CCM or cipher-specific error code on failure.
|
||||
*/
|
||||
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
unsigned char *tag, size_t tag_len )
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
CCM_VALIDATE_RET( ctx );
|
||||
CCM_VALIDATE_RET( iv );
|
||||
|
@ -448,7 +448,7 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
|||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
|
||||
add_len, input, output, tag, tag_len ) );
|
||||
add_len, input, output, tag, tag_len ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -491,10 +491,10 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
|||
* \return A cipher-specific error code on calculation failure.
|
||||
*/
|
||||
int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
const unsigned char *tag, size_t tag_len )
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
const unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_THIS_CORRUPTION;
|
||||
unsigned char check_tag[16];
|
||||
|
|
|
@ -456,7 +456,7 @@ static void OpCmpxchg16b(struct Machine *m, uint32_t rde) {
|
|||
}
|
||||
|
||||
static void OpRdrand(struct Machine *m, uint32_t rde) {
|
||||
WriteRegister(rde, RegRexbRm(m, rde), rand64());
|
||||
WriteRegister(rde, RegRexbRm(m, rde), rdrand());
|
||||
m->flags = SetFlag(m->flags, FLAGS_CF, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -204,6 +204,15 @@
|
|||
"scp $f $f.dbg win7:"
|
||||
"ssh win7 ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((eq kind 'run-win10)
|
||||
(format
|
||||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j8 -O $f MODE=$m")
|
||||
"scp $f $f.dbg win10:"
|
||||
"ssh win10 ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((and (equal suffix "")
|
||||
(cosmo-contains "_test." (buffer-file-name)))
|
||||
(format "m=%s; make -j8 -O MODE=$m %s"
|
||||
|
@ -643,6 +652,22 @@
|
|||
('t
|
||||
(error "cosmo-run: unknown major mode")))))))
|
||||
|
||||
(defun cosmo-run-win10 (arg)
|
||||
(interactive "P")
|
||||
(let* ((this (or (buffer-file-name) dired-directory))
|
||||
(proj (locate-dominating-file this "Makefile"))
|
||||
(root (or proj default-directory))
|
||||
(file (file-relative-name this root)))
|
||||
(when root
|
||||
(let ((default-directory root))
|
||||
(save-buffer)
|
||||
(cond ((memq major-mode '(c-mode c++-mode asm-mode fortran-mode))
|
||||
(let* ((mode (cosmo--make-mode arg ""))
|
||||
(compile-command (cosmo--compile-command this root 'run-win10 mode "" "" "")))
|
||||
(compile compile-command)))
|
||||
('t
|
||||
(error "cosmo-run: unknown major mode")))))))
|
||||
|
||||
(progn
|
||||
(define-key asm-mode-map (kbd "C-c C-r") 'cosmo-run)
|
||||
(define-key c-mode-base-map (kbd "C-c C-r") 'cosmo-run)
|
||||
|
@ -650,7 +675,7 @@
|
|||
(define-key sh-mode-map (kbd "C-c C-r") 'cosmo-run)
|
||||
(define-key python-mode-map (kbd "C-c C-r") 'cosmo-run)
|
||||
(define-key c-mode-map (kbd "C-c C-s") 'cosmo-run-test)
|
||||
(define-key c-mode-map (kbd "C-c C-_") 'cosmo-run-win7))
|
||||
(define-key c-mode-map (kbd "C-c C-_") 'cosmo-run-win10))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
Loading…
Reference in a new issue