Add malloc logging tool

STATIC_YOINK("enable_memory_log");
This commit is contained in:
Justine Tunney 2022-05-26 23:17:19 -07:00
parent 7e9fb0a9f1
commit cb67223051
25 changed files with 502 additions and 78 deletions

View file

@ -13,12 +13,37 @@
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "third_party/getopt/getopt.h"
#include "third_party/zlib/zlib.h"
#define CHUNK 32768
#define USAGE \
" <STDIN >STDOUT\n\
\n\
SYNOPSIS\n\
\n\
Zlib Compressor\n\
\n\
FLAGS\n\
\n\
-?\n\
-h help\n\
-0 disable compression\n\
-1 fastest compression\n\
-4 coolest compression\n\
-9 maximum compression\n\
-F fixed strategy (advanced)\n\
-L filtered strategy (advanced)\n\
-R run length strategy (advanced)\n\
-H huffman only strategy (advanced)\n\
\n"
// clang-format off
// make -j8 o//examples && dd if=/dev/urandom count=100 | tee a | o//examples/compress.com | o//examples/decompress.com >b && sha1sum a b
/*
@ -35,18 +60,67 @@
# level 9 75016 compress 5.4 MB/s decompress 344 MB/s
m=
make -j8 MODE=$m o/$m/examples || exit
for level in $(seq 0 9); do
o/$m/examples/compress.com $level <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
for level in $(seq 1 9); do
for strategy in F L R H; do
o/$m/examples/compress.com -$strategy$level <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
compspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
o/$m/examples/decompress.com $level </tmp/comp | dd count=10000 2>/tmp/info >/dev/null
o/$m/examples/decompress.com </tmp/comp | dd count=10000 2>/tmp/info >/dev/null
decompspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
size=$(o/$m/examples/compress.com $level <o/$m/examples/compress.com | wc -c)
echo "level $level $size compress $compspeed decompress $decompspeed"
size=$(o/$m/examples/compress.com -$strategy$level <o/$m/examples/compress.com | wc -c)
echo "level $strategy $level $size compress $compspeed decompress $decompspeed"
done
done
*/
// clang-format on
int compressor(int infd, int outfd, int level) {
int level;
int strategy;
wontreturn void PrintUsage(int rc, FILE *f) {
fputs("usage: ", f);
fputs(program_invocation_name, f);
fputs(USAGE, f);
exit(rc);
}
void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "?hFLRH0123456789")) != -1) {
switch (opt) {
case 'F':
strategy = Z_FIXED;
break;
case 'L':
strategy = Z_FILTERED;
break;
case 'R':
strategy = Z_RLE;
break;
case 'H':
strategy = Z_HUFFMAN_ONLY;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
level = opt - '0';
break;
case 'h':
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
}
int compressor(int infd, int outfd) {
z_stream zs;
int rc, flush;
unsigned have;
@ -57,8 +131,7 @@ int compressor(int infd, int outfd, int level) {
zs.zalloc = 0;
zs.zfree = 0;
zs.opaque = 0;
rc = deflateInit2(&zs, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
Z_DEFAULT_STRATEGY);
rc = deflateInit2(&zs, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, strategy);
if (rc != Z_OK) return rc;
do {
rc = read(infd, inbuf, CHUNK);
@ -105,13 +178,11 @@ const char *zerr(int rc) {
}
int main(int argc, char *argv[]) {
int rc, level;
if (argc > 1) {
level = atoi(argv[1]);
} else {
level = Z_DEFAULT_COMPRESSION;
}
rc = compressor(0, 1, level);
int rc;
level = Z_DEFAULT_COMPRESSION;
strategy = Z_DEFAULT_STRATEGY;
GetOpts(argc, argv);
rc = compressor(0, 1);
if (rc == Z_OK) {
return 0;
} else {

View file

@ -33,12 +33,14 @@
m=
make -j8 MODE=$m o/$m/examples || exit
for level in $(seq 0 9); do
o/$m/examples/compress.com $level <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
for strategy in F L R H; do
o/$m/examples/compress.com -$strategy$level <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
compspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
o/$m/examples/decompress.com $level </tmp/comp | dd count=10000 2>/tmp/info >/dev/null
o/$m/examples/decompress.com </tmp/comp | dd count=10000 2>/tmp/info >/dev/null
decompspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
size=$(o/$m/examples/compress.com $level <o/$m/examples/compress.com | wc -c)
echo "level $level $size compress $compspeed decompress $decompspeed"
size=$(o/$m/examples/compress.com -$strategy$level <o/$m/examples/compress.com | wc -c)
echo "level $strategy $level $size compress $compspeed decompress $decompspeed"
done
done
*/
// clang-format on

View file

@ -20,6 +20,7 @@ i32 __sys_execve(const char *, char *const[], char *const[]) hidden;
i32 __sys_fcntl(i32, i32, ...) hidden;
i32 __sys_fstat(i32, void *) hidden;
i32 __sys_fstatat(i32, const char *, void *, i32) hidden;
i32 __sys_gettid(i64 *) hidden;
i32 __sys_munmap(void *, u64) hidden;
i32 __sys_openat(i32, const char *, i32, u32) hidden;
i32 __sys_pipe2(i32[hasatleast 2], u32) hidden;
@ -51,6 +52,7 @@ i32 sys_getpriority(i32, u32) hidden;
i32 sys_getresgid(u32 *, u32 *, u32 *);
i32 sys_getresuid(u32 *, u32 *, u32 *);
i32 sys_getsid(int) hidden;
i32 sys_gettid(void) hidden;
i32 sys_ioctl(i32, u64, ...) hidden;
i32 sys_kill(i32, i32, i32) hidden;
i32 sys_linkat(i32, const char *, i32, const char *, i32) hidden;
@ -108,7 +110,6 @@ i64 sys_write(i32, const void *, u64) hidden;
u32 sys_getegid(void) hidden;
u32 sys_geteuid(void) hidden;
u32 sys_getgid(void) hidden;
u32 sys_gettid(void) hidden;
u32 sys_getuid(void) hidden;
u32 sys_umask(u32) hidden;
void *__sys_mmap(void *, u64, u32, u32, i64, i64, i64) hidden;

View file

@ -19,6 +19,7 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/setjmp.internal.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nt/thread.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/nr.h"
@ -32,8 +33,13 @@
* @noreturn
*/
privileged wontreturn void _Exit1(int rc) {
jmp_buf *jb;
struct WinThread *wt;
STRACE("_Exit1(%d)", rc);
if (__tls_enabled) {
jb = (jmp_buf *)(__get_tls() + 0x08);
longjmp(*jb, rc);
}
if (!IsWindows() && !IsMetal()) {
asm volatile("xor\t%%r10d,%%r10d\n\t"
"syscall"

View file

@ -32,7 +32,6 @@
#include "libc/intrin/kprintf.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/color.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"
#include "libc/nexgen32e/gc.internal.h"
#include "libc/runtime/gc.internal.h"
@ -150,11 +149,11 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
strlen(" (discriminator ") - 1)) &&
(p3 = memchr(p2, '\n', got - (p2 - p1)))) {
if (p3 > p2 && p3[-1] == '\r') --p3;
__write(p1, p2 - p1);
write(2, p1, p2 - p1);
got -= p3 - p1;
p1 += p3 - p1;
} else {
__write(p1, got);
write(2, p1, got);
break;
}
}

297
libc/log/memlog.c Normal file
View file

@ -0,0 +1,297 @@
/*-*- 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/assert.h"
#include "libc/bits/atomic.h"
#include "libc/bits/weaken.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/hook/hook.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/sysv/consts/o.h"
#include "third_party/dlmalloc/dlmalloc.h"
/**
* @fileoverview Malloc Logging
*
* If you put the following in your main file:
*
* STATIC_YOINK("enable_memory_log");
*
* Then memory allocations with constant backtraces will be logged to
* standard error. The columns printed are
*
* MEM TID OP USAGE PTR OLD SIZE CALLER1 CALLER2 CALLER3 CALLER4
*
* delimited by spaces. For example, to see peak malloc usage:
*
* ./myprog.com 2>log
* grep ^MEM log | sort -nk4 | tail -n10
*
* To see the largest allocations:
*
* ./myprog.com 2>log
* grep ^MEM log | grep -v free | sort -nk7 | tail -n10
*/
static struct Memlog {
void (*free)(void *);
void *(*malloc)(size_t);
void *(*calloc)(size_t, size_t);
void *(*memalign)(size_t, size_t);
void *(*realloc)(void *, size_t);
void *(*realloc_in_place)(void *, size_t);
size_t (*bulk_free)(void *[], size_t);
struct Allocs {
long i, n, f;
struct Alloc {
void *addr;
long size;
} * p;
} allocs;
long usage;
} __memlog;
_Alignas(64) static int __memlog_lock_obj;
static void __memlog_lock(void) {
_spinlock(&__memlog_lock_obj);
}
static void __memlog_unlock(void) {
_spunlock(&__memlog_lock_obj);
}
static long __memlog_size(void *p) {
return malloc_usable_size(p) + 16;
}
static void __memlog_backtrace(struct StackFrame *frame, intptr_t *a,
intptr_t *b, intptr_t *c, intptr_t *d) {
*a = *b = *c = *d = 0;
if (!frame) return;
*a = frame->addr;
if (!(frame = frame->next)) return;
*b = frame->addr;
if (!(frame = frame->next)) return;
*c = frame->addr;
if (!(frame = frame->next)) return;
*d = frame->addr;
}
static long __memlog_find(void *p) {
long i;
for (i = 0; i < __memlog.allocs.i; ++i) {
if (__memlog.allocs.p[i].addr == p) {
return i;
}
}
return -1;
}
static void __memlog_insert(void *p) {
long i, n, n2;
struct Alloc *p2;
n = __memlog_size(p);
for (i = __memlog.allocs.f; i < __memlog.allocs.i; ++i) {
if (!__memlog.allocs.p[i].addr) {
__memlog.allocs.p[i].addr = p;
__memlog.allocs.p[i].size = n;
__memlog.usage += n;
return;
}
}
if (i == __memlog.allocs.n) {
p2 = __memlog.allocs.p;
n2 = __memlog.allocs.n;
n2 += 1;
n2 += n2 >> 1;
if ((p2 = dlrealloc(p2, n2 * sizeof(*p2)))) {
__memlog.allocs.p = p2;
__memlog.allocs.n = n2;
} else {
return;
}
}
__memlog.allocs.p[i].addr = p;
__memlog.allocs.p[i].size = n;
__memlog.allocs.i++;
__memlog.usage += n;
}
static void __memlog_update(void *p2, void *p) {
long i, n;
n = __memlog_size(p2);
for (i = 0; i < __memlog.allocs.i; ++i) {
if (__memlog.allocs.p[i].addr == p) {
__memlog.usage += n - __memlog.allocs.p[i].size;
__memlog.allocs.p[i].addr = p2;
__memlog.allocs.p[i].size = n;
assert(__memlog.usage >= 0);
return;
}
}
assert(!"this corruption");
}
static void __memlog_log(struct StackFrame *frame, const char *op, void *res,
void *old, size_t n) {
intptr_t a, b, c, d;
__memlog_backtrace(frame, &a, &b, &c, &d);
kprintf("MEM %6P %7s %12ld %14p %14p %8zu %t %t %t %t\n", op,
atomic_load(&__memlog.usage), res, old, n, a, b, c, d);
}
static void __memlog_free(void *p) {
long i, n;
if (!p) return;
__memlog_lock();
if ((i = __memlog_find(p)) != -1) {
n = __memlog.allocs.p[i].size;
__memlog.allocs.p[i].addr = 0;
__memlog.usage -= __memlog.allocs.p[i].size;
__memlog.allocs.f = MIN(__memlog.allocs.f, i);
assert(__memlog.usage >= 0);
} else {
kprintf("memlog could not find %p\n", p);
assert(!"this corruption");
n = -1;
}
__memlog_unlock();
assert(__memlog.free);
__memlog.free(p);
__memlog_log(__builtin_frame_address(0), "free", 0, p, n);
}
static void *__memlog_malloc(size_t n) {
void *res;
assert(__memlog.malloc);
if ((res = __memlog.malloc(n))) {
__memlog_lock();
__memlog_insert(res);
__memlog_unlock();
__memlog_log(__builtin_frame_address(0), "malloc", res, 0, n);
}
return res;
}
static void *__memlog_calloc(size_t n, size_t z) {
void *res;
assert(__memlog.calloc);
if ((res = __memlog.calloc(n, z))) {
__memlog_lock();
__memlog_insert(res);
__memlog_unlock();
__memlog_log(__builtin_frame_address(0), "malloc", res, 0, n * z);
}
return res;
}
static void *__memlog_memalign(size_t l, size_t n) {
void *res;
assert(__memlog.memalign);
if ((res = __memlog.memalign(l, n))) {
__memlog_lock();
__memlog_insert(res);
__memlog_unlock();
__memlog_log(__builtin_frame_address(0), "malloc", res, 0, n);
}
return res;
}
static void *__memlog_realloc_impl(void *p, size_t n,
void *(*f)(void *, size_t),
struct StackFrame *frame) {
void *res;
assert(f);
if ((res = f(p, n))) {
__memlog_lock();
if (p) {
__memlog_update(res, p);
} else {
__memlog_insert(res);
}
__memlog_unlock();
__memlog_log(frame, "realloc", res, p, n);
}
return res;
}
static void *__memlog_realloc(void *p, size_t n) {
return __memlog_realloc_impl(p, n, __memlog.realloc,
__builtin_frame_address(0));
}
static void *__memlog_realloc_in_place(void *p, size_t n) {
return __memlog_realloc_impl(p, n, __memlog.realloc_in_place,
__builtin_frame_address(0));
}
static size_t __memlog_bulk_free(void *p[], size_t n) {
size_t i;
for (i = 0; i < n; ++i) {
__memlog_free(p[i]);
p[i] = 0;
}
return 0;
}
static textexit void __memlog_destroy(void) {
__memlog_lock();
hook_free = __memlog.free;
hook_malloc = __memlog.malloc;
hook_calloc = __memlog.calloc;
hook_realloc = __memlog.realloc;
hook_memalign = __memlog.memalign;
hook_bulk_free = __memlog.bulk_free;
hook_realloc_in_place = __memlog.realloc_in_place;
dlfree(__memlog.allocs.p);
__memlog.allocs.p = 0;
__memlog.allocs.i = 0;
__memlog.allocs.n = 0;
__memlog_unlock();
}
static textstartup void __memlog_init(void) {
GetSymbolTable();
__memlog_lock();
__memlog.free = hook_free;
hook_free = __memlog_free;
__memlog.malloc = hook_malloc;
hook_malloc = __memlog_malloc;
__memlog.calloc = hook_calloc;
hook_calloc = __memlog_calloc;
__memlog.realloc = hook_realloc;
hook_realloc = __memlog_realloc;
__memlog.memalign = hook_memalign;
hook_memalign = __memlog_memalign;
__memlog.bulk_free = hook_bulk_free;
hook_bulk_free = __memlog_bulk_free;
__memlog.realloc_in_place = hook_realloc_in_place;
hook_realloc_in_place = __memlog_realloc_in_place;
atexit(__memlog_destroy);
__memlog_unlock();
}
const void *const enable_memory_log[] initarray = {
__memlog_init,
};

View file

@ -25,11 +25,11 @@ CheckStackIsAligned:
push %rbp
mov %rsp,%rbp
/ allocate sixteen bytes
// allocate sixteen bytes
push %rax
push %rax
/ put a value in it
// put a value in it
xorps %xmm0,%xmm0
movaps %xmm0,-16(%rbp)

View file

@ -199,10 +199,11 @@ static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
wt->tls = flags & CLONE_SETTLS ? tls : 0;
_seizelock(&wt->lock); // TODO: How can we get the tid without locking?
wt->lock = 1;
if ((rc = bsdthread_create(fn, arg, wt, 0, PTHREAD_START_CUSTOM_XNU)) != -1) {
_spinlock(&wt->lock);
rc = wt->tid;
_spunlock(&wt->lock);
}
return rc;
}
@ -263,9 +264,7 @@ static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
// OPEN BESIYATA DISHMAYA
int __tfork(struct __tfork *params, size_t psize, struct CloneArgs *wt);
asm(".section\t.privileged,\"ax\",@progbits\n\t"
".local\t__tfork\n"
"__tfork:\n\t"
asm("__tfork:\n\t"
"push\t$8\n\t"
"pop\t%rax\n\t"
"mov\t%rdx,%r8\n\t"
@ -282,11 +281,10 @@ asm(".section\t.privileged,\"ax\",@progbits\n\t"
"and\t$-16,%rsp\n\t"
"push\t%rax\n\t"
"jmp\tOpenbsdThreadMain\n\t"
".size\t__tfork,.-__tfork\n\t"
".previous");
".size\t__tfork,.-__tfork\n\t");
__attribute__((__used__, __no_reorder__))
static privileged wontreturn void
static wontreturn void
OpenbsdThreadMain(struct CloneArgs *wt) {
wt->func(wt->arg);
// we no longer use the stack after this point. however openbsd

View file

@ -0,0 +1,27 @@
/*-*- 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/runtime/memtrack.internal.h"
noasan size_t GetMemtrackSize(struct MemoryIntervals *mm) {
size_t i, n;
for (n = i = 0; i < mm->i; ++i) {
n += ((size_t)(mm->p[i].y - mm->p[i].x) + 1) << 16;
}
return n;
}

View file

@ -63,6 +63,7 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
void (*)(struct MemoryIntervals *, int, int)) hidden;
void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden;
int UntrackMemoryIntervals(void *, size_t) hidden;
size_t GetMemtrackSize(struct MemoryIntervals *);
#define IsLegalPointer(p) \
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)

View file

@ -148,14 +148,6 @@ noasan static bool Automap(int count, int align, int *res) {
*res + count <= FRAME(kAutomapStart + (kAutomapSize - 1));
}
noasan static size_t GetMemtrackSize(struct MemoryIntervals *mm) {
size_t i, n;
for (n = i = 0; i < mm->i; ++i) {
n += ((size_t)(mm->p[i].y - mm->p[i].x) + 1) << 16;
}
return n;
}
static noasan void *FinishMemory(void *addr, size_t size, int prot, int flags,
int fd, int64_t off, int f, int x, int n,
struct DirectMap dm) {
@ -491,10 +483,15 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
int64_t off) {
void *res;
size_t toto;
_spinlock(&_mmi.lock);
res = Mmap(addr, size, prot, flags, fd, off);
#if SYSDEBUG
toto = __strace > 0 ? GetMemtrackSize(&_mmi) : 0;
#endif
_spunlock(&_mmi.lock);
STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → %p% m", addr, size,
DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off, res);
STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → %p% m (%'zu bytes total)", addr,
size, DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off, res,
toto);
return res;
}

View file

@ -163,9 +163,13 @@ static noasan int Munmap(char *p, size_t n) {
*/
noasan int munmap(void *p, size_t n) {
int rc;
size_t toto;
_spinlock(&_mmi.lock);
rc = Munmap(p, n);
#if SYSDEBUG
toto = __strace > 0 ? GetMemtrackSize(&_mmi) : 0;
#endif
_spunlock(&_mmi.lock);
STRACE("munmap(%.12p, %'zu) → %d% m", p, n, rc);
STRACE("munmap(%.12p, %'zu) → %d% m (%'zu bytes total)", p, n, rc, toto);
return rc;
}

View file

@ -0,0 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall __sys_gettid,0x13712b1b0101b0ba,globl,hidden

View file

@ -1,2 +0,0 @@
.include "o/libc/sysv/macros.internal.inc"
.scall break,0xffffff011fffffff,globl

View file

@ -1,2 +0,0 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_gettid,0xfffffffff211e0ba,globl,hidden

View file

@ -2054,7 +2054,7 @@ syscon nr __NR_modify_ldt 0x009a 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_pivot_root 0x009b 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR__sysctl 0x009c 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_prctl 0x009d 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_arch_prctl 0x009e 0xfff 0x00a5 0x00a5 0xfff 0xfff
syscon nr __NR_arch_prctl 0x009e 0x3000003 0x00a5 0x149 0x13d 0xfff # sysarch on freebsd, _lwp_setprivate on netbsd, __set_tcb on openbsd, thread_fast_set_cthread_self on xnu
syscon nr __NR_adjtimex 0x009f 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_umount2 0x00a6 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_swapon 0x00a7 0x2000055 0x0055 0xfff 0xfff 0xfff
@ -2065,7 +2065,7 @@ syscon nr __NR_iopl 0x00ac 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_ioperm 0x00ad 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_init_module 0x00af 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_delete_module 0x00b0 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_gettid 0x00ba 0x200011e 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_gettid 0x00ba 0x0100001b 432 299 311 0xfff # TODO(jart): thread_self_trap vs. gettid?
syscon nr __NR_readahead 0x00bb 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_setxattr 0x00bc 0x20000ec 0xfff 0xfff 0x177 0xfff
syscon nr __NR_fsetxattr 0x00be 0x20000ed 0xfff 0xfff 0x179 0xfff

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,TIOCGPTN,0x80045430,0,0x4004740f,0,0,0
.syscon pty,TIOCGPTN,0x80045430,0,0x4004740f,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon pty,TIOCSPTLCK,0x40045431,0,0,0,0,-1
.syscon pty,TIOCSPTLCK,0x40045431,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon nr,__NR_arch_prctl,0x009e,0xfff,0x00a5,0x00a5,0xfff,0xfff
.syscon nr,__NR_arch_prctl,0x009e,0x3000003,0x00a5,0x149,0x13d,0xfff

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon nr,__NR_gettid,0x00ba,0x200011e,0xfff,0xfff,0xfff,0xfff
.syscon nr,__NR_gettid,0x00ba,0x0100001b,432,299,311,0xfff

View file

@ -219,7 +219,7 @@ scall iopl 0xfffffffffffff0ac globl
scall ioperm 0xfffffffffffff0ad globl
scall init_module 0xfffffffffffff0af globl
scall delete_module 0xfffffffffffff0b0 globl
scall sys_gettid 0xfffffffff211e0ba globl hidden
scall __sys_gettid 0x13712b1b0101b0ba globl hidden # thread_self_trap (or gettid? on xnu), _lwp_self on netbsd, thr_self on freebsd, getthrid on openbsd
scall readahead 0xfffffffffffff0bb globl # consider fadvise() / madvise()
scall setxattr 0x177ffffff20ec0bc globl
scall fsetxattr 0x179ffffff20ed0be globl
@ -618,10 +618,10 @@ scall workq_open 0xfffffffff216ffff globl
scall write_nocancel 0xfffffffff218dfff globl
scall writev_nocancel 0xfffffffff219cfff globl
#──────────────────────────FREEBSD───────────────────────────
scall _umtx_op 0xffffff1c6fffffff globl
scall abort2 0xffffff1cffffffff globl
scall afs3_syscall 0xffffff179fffffff globl
scall bindat 0xffffff21afffffff globl
scall break 0xffffff011fffffff globl
scall cap_enter 0xffffff204fffffff globl
scall cap_fcntls_get 0xffffff219fffffff globl
scall cap_fcntls_limit 0xffffff218fffffff globl
@ -816,7 +816,6 @@ scall __acl_aclcheck_link 0xffffff1acfffffff globl
scall __mac_syscall 0xfffffffff217dfff globl
scall __acl_set_file 0xffffff15cfffffff globl
scall __acl_delete_file 0xffffff15ffffffff globl
scall _umtx_op 0xffffff1c6fffffff globl
scall __semwait_signal_nocancel 0xfffffffff21a7fff globl
scall __old_semwait_signal_nocancel 0xfffffffff2173fff globl
scall sctp_peeloff 0xffffff1d7fffffff globl

View file

@ -0,0 +1,27 @@
/*-*- 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/nexgen32e/nexgen32e.h"
#include "libc/testlib/testlib.h"
// pcmpestrm
/* TEST(pcmpstr, test) { */
/* EXPECT_EQ(0, pcmpstr()); */
/* EXPECT_STREQ("", pcmpstr()); */
/* } */

View file

@ -357,12 +357,7 @@ int count;
void *ptrs[N];
void BenchUnmap(void) {
int i;
for (i = 0; i < count; ++i) {
if (ptrs[i]) {
ASSERT_EQ(0, munmap(ptrs[i], FRAMESIZE));
}
}
ASSERT_EQ(0, munmap(ptrs[count++], FRAMESIZE));
}
void BenchMmapPrivate(void) {
@ -375,16 +370,11 @@ void BenchMmapPrivate(void) {
BENCH(mmap, bench) {
EZBENCH2("mmap", donothing, BenchMmapPrivate());
BenchUnmap();
EZBENCH2("munmap", donothing, BenchUnmap());
}
void BenchUnmapLinux(void) {
int i;
for (i = 0; i < count; ++i) {
if (ptrs[i]) {
ASSERT_EQ(0, LinuxMunmap(ptrs[i], FRAMESIZE));
}
}
ASSERT_EQ(0, LinuxMunmap(ptrs[count++], FRAMESIZE));
}
void BenchMmapPrivateLinux(void) {
@ -399,5 +389,5 @@ BENCH(mmap, benchLinux) {
void *p;
if (!IsLinux()) return;
EZBENCH2("mmap (linux)", donothing, BenchMmapPrivateLinux());
BenchUnmapLinux();
EZBENCH2("munmap (linux)", donothing, BenchUnmapLinux());
}

View file

@ -53,8 +53,8 @@ noasan bool MemoryExists(char *p) {
sigaction(SIGSEGV, &sa, old + 0);
sigaction(SIGBUS, &sa, old + 1);
c = atomic_load(p);
sigaction(SIGSEGV, old + 0, 0);
sigaction(SIGBUS, old + 1, 0);
sigaction(SIGSEGV, old + 0, 0);
return !gotsignal;
}

View file

@ -236,12 +236,6 @@ USAGE
$ file redbean.com
redbean.com: ELF 64-bit LSB executable
redbean contains software licensed ISC, MIT, BSD-2, BSD-3, zlib
which makes it a permissively licensed gift to anyone who might
find it useful. The transitive closure of legalese can be found
inside the binary. redbean also respects your privacy and won't
phone home because your computer is its home.
────────────────────────────────────────────────────────────────────────────────
SECURITY
@ -1088,7 +1082,7 @@ FUNCTIONS
ProgramPrivateKey(pem:str)
Same as the -K flag if called from .init.lua, e.g.
ProgramPrivateKey(LoadAsset("/.sign.key")) for zip loading or
ProgramPrivateKey(Slurp("/etc/letsencrypt/fullchain.pem")) for
ProgramPrivateKey(Slurp("/etc/letsencrypt/privkey.pem")) for
local file system only.
ProgramRedirect(code:int,src:str,location:str)
@ -4148,6 +4142,19 @@ UNIX MODULE
reflects the value chosen by the underlying operating system.
────────────────────────────────────────────────────────────────────────────────
LEGAL
redbean contains software licensed ISC, MIT, BSD-2, BSD-3, zlib
which makes it a permissively licensed gift to anyone who might
find it useful. The transitive closure of legalese can be found
inside the binary structure, because notice licenses require we
distribute the license along with any software that uses it. By
putting them in the binary, compliance in automated and no need
for further action on the part of the user who is distributing.
────────────────────────────────────────────────────────────────────────────────
SEE ALSO