Squashed commit of the following:

commit d9e0429dec42bf786aa73a66c259c275be5a8de9
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:59 2022 -0400

    Revert "Don't relocate file descriptor memory"

    This reverts commit 3265324e00.

commit 22ce7f16eeb326408208fabee57eace63371352c
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:58 2022 -0400

    Revert "Make some minor touchups for nightlies"

    This reverts commit e9272f03fb.

commit 8ef0057111e955fa18f2cce77b36046fa96fdcd5
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:57 2022 -0400

    Revert "Tidy up the threading implementation"

    This reverts commit 155b378a39.

commit 7e99e6e08b14003df21d42bedf473219417d3610
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:56 2022 -0400

    Revert "Bare metal VGA: minor improvements (#608)"

    This reverts commit bae7367774.

commit cd184ff7fe4f8539a3928e8f2b8703e699c199e4
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:55 2022 -0400

    Revert "Rewrite recursive mutex code"

    This reverts commit cfcf5918bc.

commit 4aa26c44ee200ffbcb591b3145876095fa235bd3
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:54 2022 -0400

    Revert "Clean up the TLS code"

    This reverts commit 333768440c.

commit f8c989127c7b8821e2183858c321fcd54fc45ffe
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:52 2022 -0400

    Revert "Remove stdio lock macros from amalgamation"

    This reverts commit cdb2284f0d.

commit d10cd5c40f576a2dde8448338d2e9b3d88e160f8
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:50 2022 -0400

    Revert "Import nsync"

    This reverts commit 5dff63a31c.

commit 2a49d50c29f518367e0a51cb7a0a2b4b0a1679f0
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:49 2022 -0400

    Revert "Fix the build"

    This reverts commit 3de35e196c.

commit c258d09ee5a7f48cd3d0d71667aba6fa7ab0e9ee
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:49 2022 -0400

    Revert "Use *NSYNC for POSIX threads locking APIs"

    This reverts commit b5cb71ab84.

commit 43bf84f09737bf87d79c7650dde52e030556056d
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:48 2022 -0400

    Revert "Add *NSYNC mu_test"

    This reverts commit 9b89a7c51d.

commit 94a0e96d666f7cf2dd4af03b42516956908f4ad7
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:47 2022 -0400

    Revert "Don't pushpop in long mode without stack (#611)"

    This reverts commit 569c031934.

commit 55f9f15c8659f6956ac4c9e0334b7884f5ff1c01
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:46 2022 -0400

    Revert "Update redbean doc to correct return values (#610)"

    This reverts commit 55ddf73484.

commit 30865675f4c750d1fec64df9b7bf98e6132787a9
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:45 2022 -0400

    Revert "Left-align stub arguments to dd (fixes #374) (#598)"

    This reverts commit 0305194d98.

commit 01e8de146f8de3abb1fe8cf2c6e7054a68be411e
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:43 2022 -0400

    Revert "Add Vista branch to GitHub workflows"

    This reverts commit c03359c637.

commit 66966f8ae2d020e7c3e8f1ed20eddd9b155f9ac4
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:43 2022 -0400

    Revert "[WIP] Get bare metal working outside of an emulator (#609)"

    This reverts commit 116bda997e.

commit 9ab0952c35086ac6c3c1dc186ae9ff1f90d8d76c
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:41 2022 -0400

    Revert "Bare metal VGA: implement "status report" escape codes (#613)"

    This reverts commit c4eb701d56.

commit 86f6a61d16e2c896939f536119ba328c7220f1eb
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:38 2022 -0400

    Revert "Fix the build"

    This reverts commit 790c661317.

commit 92b09acf939fdd3c10a81d5dd212f76351f05451
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:37 2022 -0400

    Revert "Fix bug with sendfile() on XNU"

    This reverts commit 827f25f054.

commit 3a5b536995cf8c48fffd371097aae9dfbeeebb44
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:36 2022 -0400

    Revert "Fix preadv() and pwritev()"

    This reverts commit 050062bcbb.

commit 854ec3631f54d087797a67c8e86b7d2655bc1317
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:35 2022 -0400

    Revert "Fix POSIX advisory locks on Windows"

    This reverts commit a5fa90a21f.

commit 5cc1a788126b5b2b54656e0f4244a56596b59978
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:35 2022 -0400

    Revert "Fix F_DUPFD_CLOEXEC on some systems"

    This reverts commit c64e7eaf7c.

commit 0264d3b34dcf80b0d34d6f4ef100a0f8545047e0
Author: Gavin Hayes <gavin@computoid.com>
Date:   Wed Sep 21 22:41:33 2022 -0400

    Revert "Add README description for new vista branch"

    This reverts commit 30140812f0.
This commit is contained in:
Gavin Hayes 2022-09-21 22:43:07 -04:00
parent 30140812f0
commit a80eea78fe
419 changed files with 2468 additions and 10224 deletions

View file

@ -4,12 +4,10 @@ on:
push:
branches:
- "master"
- "vista"
- "flake"
pull_request:
branches:
- "master"
- "vista"
# run workflow manually from the Actions tab
workflow_dispatch:

View file

@ -122,7 +122,6 @@ include libc/vga/vga.mk #─┘
include libc/calls/calls.mk #─┐
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
include libc/crt/crt.mk # │ You can issue system calls
include third_party/nsync/nsync.mk # │
include third_party/dlmalloc/dlmalloc.mk #─┘
include libc/mem/mem.mk #─┐
include libc/zipos/zipos.mk # ├──DYNAMIC RUNTIME
@ -212,7 +211,6 @@ include test/libc/fmt/test.mk
include test/libc/dns/test.mk
include test/libc/time/test.mk
include test/libc/stdio/test.mk
include test/libc/zipos/test.mk
include test/libc/release/test.mk
include test/libc/test.mk
include test/net/http/test.mk
@ -300,7 +298,6 @@ COSMOPOLITAN_OBJECTS = \
LIBC_MEM \
THIRD_PARTY_DLMALLOC \
LIBC_RUNTIME \
THIRD_PARTY_NSYNC \
LIBC_ELF \
LIBC_CALLS \
LIBC_SYSV_CALLS \
@ -340,7 +337,6 @@ COSMOPOLITAN_HEADERS = \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
THIRD_PARTY_NSYNC \
THIRD_PARTY_XED \
LIBC_STR \
LIBC_SYSV \

View file

@ -1,10 +1,7 @@
![Cosmopolitan Honeybadger](usr/share/img/honeybadger.png)
[![build](https://github.com/jart/cosmopolitan/actions/workflows/build.yml/badge.svg)](https://github.com/jart/cosmopolitan/actions/workflows/build.yml)
# Cosmopolitan (Vista Edition)
**This is a community supported legacy branch of Cosmopolitan 2.0 that's
intended to preserve compatibility with Windows Vista and Windows 7.**
# Cosmopolitan
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C
a build-once run-anywhere language, like Java, except it doesn't need an

View file

@ -329,7 +329,7 @@ dsknfo: push %bx
movpp %es,%ds
xor %si,%si
mov %si,%es
mov $0x1d10,%si # mman::pc_drive_base_table
mov $0x1510,%si # mman::pc_drive_base_table
xchg %si,%di
movsw # headunloadtime, headloadtime
movsw # shutofftime, bytespersector
@ -382,11 +382,11 @@ pcread: push %ax
add $512>>4,%si
mov %si,%es
inc %al # ++sector
cmp 0x1d1c,%al # mman::pc_drive_last_sector
cmp 0x151c,%al # mman::pc_drive_last_sector
jbe 2f
mov $1,%al
inc %dh # ++head
cmp 0x1d20,%dh # mman::pc_drive_last_head
cmp 0x1520,%dh # mman::pc_drive_last_head
jbe 2f
xor %dh,%dh
inc %cx # ++cylinder
@ -485,19 +485,19 @@ ape.mbrpad:
ape_disk:
.stub ape.diskid,quad
.org 0x1be,0x00
.macro .partn x:req sta h0 s0 c0 fs h9 s9 c9 lba0 nsec
.stub ape.part\x\().status,byte,\sta # 0=non-boot / 0x80=active
.stub ape.part\x\().first.head,byte,\h0
.stub ape.part\x\().first.sector,byte,\s0 # in low 6 bits
.stub ape.part\x\().first.cylinder,byte,\c0
.stub ape.part\x\().filesystem,byte,\fs
.stub ape.part\x\().last.head,byte,\h9
.stub ape.part\x\().last.sector,byte,\s9
.stub ape.part\x\().last.cylinder,byte,\c9
.stub ape.part\x\().lba,long,\lba0 # c*C + h*H + s*S
.stub ape.part\x\().sector.count,long,\nsec # sectors are 512 bytes
.macro .partn x
.stub ape.part\x\().status,byte # 0=absent / 0x80=present
.stub ape.part\x\().first.head,byte # in low 6 bits
.stub ape.part\x\().first.cylinder,byte
.stub ape.part\x\().first.sector,byte
.stub ape.part\x\().filesystem,byte
.stub ape.part\x\().last.head,byte
.stub ape.part\x\().last.cylinder,byte
.stub ape.part\x\().last.sector,byte
.stub ape.part\x\().lba,long # c*C + h*H + s*S
.stub ape.part\x\().sector.count,long # sectors are 512 bytes
.endm
.partn 1,0x80,0,1,0,0x7f,0xff,0xff,0xff,0,0xffffffff
.partn 1
.partn 2
.partn 3
.partn 4
@ -569,11 +569,11 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape\"\n"
.ascii "[ -x \"$t\" ] || {\n"
.ascii "mkdir -p \"${t%/*}\" &&\n"
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
.ascii "dd if=\"$o\" of=\"$t.$$\" skip=\""
.shstub ape_loader_dd_skip,2
.ascii " count="
.ascii "\" count=\""
.shstub ape_loader_dd_count,2
.ascii " bs=64 2>/dev/null\n"
.ascii "\" bs=64 2>/dev/null\n"
#if SupportsXnu()
.ascii "[ -d /Applications ] && "
.ascii "dd if=\"$t.$$\""
@ -637,11 +637,11 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "dd if=\"$o\""
.ascii " of=\"$o\""
.ascii " bs=8"
.ascii " skip="
.ascii " skip=\""
.shstub ape_macho_dd_skip,2
.ascii " count="
.ascii "\" count=\""
.shstub ape_macho_dd_count,2
.ascii " conv=notrunc 2>/dev/null\n"
.ascii "\" conv=notrunc 2>/dev/null\n"
#endif /* XNU */
.ascii "[ x\"$1\" = x--assimilate ] && exit 0\n"
#ifndef APE_NO_MODIFY_SELF
@ -1291,38 +1291,27 @@ lcheck: pushf # check for i8086 / i8088 / i80186
// Gets memory map from BIOS.
e820: mov $0x0510>>4,%di # mman::e820
mov %di,%es
xor %di,%di # es:di is destination buffer
xor %edi,%edi # es:di is destination buffer
xor %ebx,%ebx # ebx is an api state tracker
1: mov $0xE820,%eax # magic
mov $8+8+4+4,%ecx # sizeof(struct SmapEntry)
mov $0x534d4150,%edx # magic number
movl $1,8+8+4/*SmapEntry::acpi3*/(%di) # prefill ACPI attributes;
# apparently some buggy BIOSes say
# that they return this field, yet
# do not fill it correctly
int $0x15 # ax,bx,cx,dx,di ax,bx,cx
jc 9f # cf = unsupported or abuse
cmp %edx,%eax # more magic means success
jne 9f
test %cx,%cx # discard empty results
jz 5f
mov 8/*LODWORD(SmapEntry::size)*/(%di),%eax
or 8+4/*HIDWORD(SmapEntry::size)*/(%di),%eax
jz 5f
cmp $8+8+4+1,%cx # discard if ignore flag
jb 4f
testb $1/*don't ignore*/,8+8+4/*SmapEntry::acpi3*/(%di)
jz 5f
testb $1/*ignore*/,8+8+4/*SmapEntry::__acpi3*/(%di)
jnz 5f
4: add $8+8+4+4,%di # keep entry
5: test %ebx,%ebx # last entry?
jz 8f
cmp $(256-1)*(8+8+4+4),%di
cmp $0x1000,%di
jb 1b
8: xor %ax,%ax # add a blank sentinel entry
mov $(8+8)/2,%cx
cld
rep stosw
ret
8: ret
9: mov $REAL(str.e820),%di
call rldie
.endfn e820
@ -1392,16 +1381,9 @@ a20: cli
// Initializes long mode paging.
pinit: push %ds
push %es
#define SEG 0x79000
mov $SEG>>4,%ax
mov %ax,%ds
mov %ax,%es
xor %di,%di
xor %ax,%ax
mov $(0x7f000-SEG)/2,%cx
cld
rep stosw
movl $0x7d000+PAGE_V+PAGE_RW,0x7e000-SEG # PDPTPML4T (+)
movl $0x7c000+PAGE_V+PAGE_RW,0x7e800-SEG # PDPTPML4T (-)
movl $0x7b000+PAGE_V+PAGE_RW,0x7d000-SEG # PDTPDPT (+)
@ -1410,14 +1392,13 @@ pinit: push %ds
movl $0x79000+PAGE_V+PAGE_RW,0x7a000-SEG # PDPDT (-)
mov $512,%cx # PD±2MB
mov $PAGE_V+PAGE_RW,%eax
xor %di,%di
0: stosl
xor %si,%si
0: mov %eax,(%si)
add $0x1000,%eax
scasl # di += 4
add $8,%si
loop 0b
mov $0x7e000,%eax # PML4TCR3
mov %eax,%cr3
pop %es
pop %ds
ret
.endfn pinit
@ -1426,7 +1407,7 @@ pinit: push %ds
//
// @see Intel Manual V3A §4.1.2
golong: cli
lidt 0x1d22 # mman::bad_idt
lidt 0x1522 # mman::bad_idt
mov %cr4,%eax
or $CR4_PAE|CR4_PGE|CR4_OSFXSR,%eax
mov %eax,%cr4
@ -1444,8 +1425,8 @@ golong: cli
// Long mode is long.
.code64
long: xor %eax,%eax
mov $GDT_LONG_DATA,%al
long: push $GDT_LONG_DATA
pop %rax
mov %eax,%ds
mov %eax,%ss
mov %eax,%es

View file

@ -180,7 +180,6 @@
#include "libc/elf/def.h"
#include "libc/elf/pf2prot.internal.h"
#include "libc/nt/pedef.internal.h"
#include "libc/thread/tls.h"
#include "libc/zip.h"
ENTRY(_start)
@ -384,14 +383,17 @@ SECTIONS {
HIDDEN(_ezip = .);
. = ALIGN(PAGESIZE);
} :Ram
. = ALIGN(PAGESIZE);
.tdata . : {
_tdata_start = .;
*(SORT_BY_ALIGNMENT(.tdata))
*(SORT_BY_ALIGNMENT(.tdata.*))
. = ALIGN(16);
_tdata_end = .;
. = ALIGN(PAGESIZE);
} :Tls :Ram
. = ALIGN(PAGESIZE);
/*END: file content that's loaded by o/s */
/*BEGIN: bss memory void */
@ -400,7 +402,7 @@ SECTIONS {
_tbss_start = .;
*(SORT_BY_ALIGNMENT(.tbss))
*(SORT_BY_ALIGNMENT(.tbss.*))
. = ALIGN(TLS_ALIGNMENT);
. = ALIGN(16);
/* the %fs register is based on this location */
_tbss_end = .;
} :Tls
@ -486,10 +488,8 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
PFSTUB4(ape_elf_shnum, 0);
PFSTUB4(ape_elf_shstrndx, 0);
HIDDEN(_tls_size = _tbss_end - _tdata_start);
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
HIDDEN(_tbss_size = _tbss_end - _tbss_start);
HIDDEN(_tbss_offset = _tbss_start - _tdata_start);
HIDDEN(_tls_size = _tbss_end - _tdata_start);
HIDDEN(_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start));
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
@ -717,9 +717,6 @@ ASSERT(IS2POW(ape_stack_memsz),
ASSERT(!(ape_stack_vaddr & (ape_stack_memsz - 1)),
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000000000 - ape_stack_memsz);");
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
/* Let's not be like Knight Capital. */
/* NOCROSSREFS_TO(.test .text) */

View file

@ -63,7 +63,6 @@ o/$(MODE)/ape/ape.lds: \
ape/macros.internal.h \
ape/relocations.h \
libc/intrin/bits.h \
libc/thread/tls.h \
libc/calls/struct/timespec.h \
libc/dce.h \
libc/elf/def.h \
@ -80,7 +79,6 @@ o/$(MODE)/ape/public/ape.lds: \
ape/macros.internal.h \
ape/relocations.h \
libc/intrin/bits.h \
libc/thread/tls.h \
libc/calls/struct/timespec.h \
libc/dce.h \
libc/elf/def.h \

View file

@ -179,7 +179,7 @@ struct ElfPhdr {
extern char ehdr[];
extern char _end[];
static void *syscall_;
static void *syscall;
static char relocated;
static struct PathSearcher ps;
extern char __syscall_loader[];
@ -275,7 +275,7 @@ __attribute__((__noreturn__)) static void Exit(int rc, int os) {
asm volatile("call\t*%2"
: /* no outputs */
: "a"((IsLinux() ? 60 : 1) | (IsXnu() ? 0x2000000 : 0)), "D"(rc),
"rm"(syscall_)
"rm"(syscall)
: "memory");
__builtin_unreachable();
}
@ -285,7 +285,7 @@ static void Close(int fd, int os) {
asm volatile("call\t*%4"
: "=a"(ax), "=D"(di)
: "0"((IsLinux() ? 3 : 6) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
"rm"(syscall_)
"rm"(syscall)
: "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "memory", "cc");
}
@ -295,7 +295,7 @@ static int Read(int fd, void *data, int size, int os) {
asm volatile("call\t*%8"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"((IsLinux() ? 0 : 3) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
"2"(data), "3"(size), "rm"(syscall_)
"2"(data), "3"(size), "rm"(syscall)
: "rcx", "r8", "r9", "r10", "r11", "memory");
return ax;
}
@ -306,7 +306,7 @@ static void Write(int fd, const void *data, int size, int os) {
asm volatile("call\t*%8"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"((IsLinux() ? 1 : 4) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
"2"(data), "3"(size), "rm"(syscall_)
"2"(data), "3"(size), "rm"(syscall)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
}
@ -315,7 +315,7 @@ static void Execve(const char *prog, char **argv, char **envp, int os) {
asm volatile("call\t*%8"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"(59 | (IsXnu() ? 0x2000000 : 0)), "1"(prog), "2"(argv),
"3"(envp), "rm"(syscall_)
"3"(envp), "rm"(syscall)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
}
@ -325,7 +325,7 @@ static int Access(const char *path, int mode, int os) {
asm volatile("call\t*%7"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"((IsLinux() ? 21 : 33) | (IsXnu() ? 0x2000000 : 0)),
"1"(path), "2"(mode), "rm"(syscall_)
"1"(path), "2"(mode), "rm"(syscall)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}
@ -338,7 +338,7 @@ static int Msyscall(long p, long n, int os) {
} else {
asm volatile("call\t*%6"
: "=a"(ax), "=D"(di), "=S"(si)
: "0"(37), "1"(p), "2"(n), "rm"(syscall_)
: "0"(37), "1"(p), "2"(n), "rm"(syscall)
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}
@ -350,7 +350,7 @@ static int Open(const char *path, int flags, int mode, int os) {
asm volatile("call\t*%8"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"((IsLinux() ? 2 : 5) | (IsXnu() ? 0x2000000 : 0)),
"1"(path), "2"(flags), "3"(mode), "rm"(syscall_)
"1"(path), "2"(flags), "3"(mode), "rm"(syscall)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}
@ -369,7 +369,7 @@ __attribute__((__noinline__)) static long Mmap(long addr, long size, int prot,
"pop\t%%r9"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx), "+r"(flags_),
"+r"(fd_), "+r"(off_)
: "rm"(syscall_),
: "rm"(syscall),
"0"((IsLinux() ? 9
: IsFreebsd() ? 477
: 197) |
@ -589,7 +589,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
// since it probably means a userspace program executed this loader
// and passed us a custom syscall function earlier.
if (Msyscall(code, codesize, os) != -1) {
syscall_ = 0;
syscall = 0;
}
#if TROUBLESHOOT
@ -600,7 +600,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
// to extend the behavior of this loader in the future. we don't need
// to clear the xmm registers since the ape loader should be compiled
// with the -mgeneral-regs-only flag.
register void *r8 asm("r8") = syscall_;
register void *r8 asm("r8") = syscall;
asm volatile("xor\t%%eax,%%eax\n\t"
"xor\t%%r9d,%%r9d\n\t"
"xor\t%%r10d,%%r10d\n\t"
@ -659,10 +659,10 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl,
}
// get syscall function pointer
if (handoff && handoff->systemcall) {
syscall_ = handoff->systemcall;
if (handoff && handoff->syscall) {
syscall = handoff->syscall;
} else {
syscall_ = __syscall_loader;
syscall = __syscall_loader;
}
if (handoff) {

View file

@ -14,7 +14,7 @@ struct ApeLoader {
int os;
char *prog;
char *page;
void *systemcall;
void *syscall;
};
#endif /* COSMOPOLITAN_APE_LOADER_H_ */

View file

@ -221,41 +221,44 @@
/**
* Binary coded decimal support.
*
* <p>This allows linker scripts to generate dd commands, e.g. ape.lds.
* There are a few ways to pad each number to the necessary 8 bytes.
* Spaces cannot be prepended because busybox refuses to parse them.
* Zeros cannot be prepended because Mac will take numbers as octal.
* That leaves appending spaces. The user's shell ought to treat any
* unquoted run of spaces as if there was only one, so this is safe.
* <p>This allows linker scripts to generate dd commands. Leading spaces
* need to be inserted so Mac doesn't consider them octal; therefore,
* parameters must be quoted; and eight digits should be good enough.
*/
#define SHSTUB2(SYM, X) \
HIDDEN(SYM##_bcs0 = BCD_LEFT(X)); \
HIDDEN(SYM##_bcs1 = BCD_RIGHT(X))
#define BCD_SMEAR(X) ((X) + (X) * 10000)
#define BCD_LEFT(X) \
(((X)) < 10000 ? BCD_RIGHT(BCD_SMEAR(X)) | 0x10 \
: (X) < 100000 ? BCD_RIGHT(BCD_SMEAR((X) / 10)) \
: (X) < 1000000 ? BCD_RIGHT(BCD_SMEAR((X) / 100)) \
: (X) < 10000000 ? BCD_RIGHT(BCD_SMEAR((X) / 1000)) \
: (X) < 100000000 ? BCD_RIGHT(BCD_SMEAR((X) / 10000)) \
: 0xffffffffffffffff)
#define BCD_RIGHT(X) \
(((X)) < 10000 ? 0x20202020 \
: (X) < 100000 ? 0x20202030 + \
(X) % 10 \
: (X) < 1000000 ? 0x20203030 + \
((X) / 10) % 10 + \
(X) % 10 * 0x100 \
: (X) < 10000000 ? 0x20303030 + \
((X) / 100) % 10 + \
((X) / 10) % 10 * 0x100 + \
(X) % 10 * 0x10000 \
: (X) < 100000000 ? 0x30303030 + \
((X) / 1000) % 10 + \
((X) / 100) % 10 * 0x100 + \
((X) / 10) % 10 * 0x10000 + \
(X) % 10 * 0x1000000 \
: 0xffffffffffffffff)
#define SHSTUB2(SYM, X) \
HIDDEN(SYM##_bcs0 = BCD10K(X)); \
HIDDEN(SYM##_bcs1 = BCD(X))
#define BCD(X) \
((X) == 0 \
? 0x20202030 \
: (X) < 10 ? 0x30202020 + (((X) % 10) << 24) \
: (X) < 100 ? 0x30302020 + (((X) % 10) << 24) + \
(((X) / 10 % 10) << 16) \
: (X) < 1000 ? 0x30303020 + (((X) % 10) << 24) + \
(((X) / 10 % 10) << 16) + \
(((X) / 100 % 10) << 8) \
: 0x30303030 + (((X) % 10) << 24) + \
(((X) / 10 % 10) << 16) + \
(((X) / 100 % 10) << 8) + \
(((X) / 1000 % 10) << 0))
#define BCD10K(X) \
((X) < 10000 \
? 0x20202020 \
: (X) < 100000 \
? 0x30202020 + (((X) / 10000 % 10) << 24) \
: (X) < 1000000 \
? 0x30302020 + (((X) / 10000 % 10) << 24) + \
(((X) / 100000 % 10) << 16) \
: (X) < 10000000 \
? 0x30303020 + (((X) / 10000 % 10) << 24) + \
(((X) / 100000 % 10) << 16) + \
(((X) / 1000000 % 10) << 8) \
: (X) < 100000000 \
? 0x30303030 + (((X) / 10000 % 10) << 24) + \
(((X) / 100000 % 10) << 16) + \
(((X) / 1000000 % 10) << 8) + \
(((X) / 10000000 % 10) << 0) \
: 0xffffffffffffffff)
#endif /* __ASSEMBLER__ */
#endif /* APE_MACROS_H_ */

View file

@ -80,7 +80,6 @@ EXAMPLES_DIRECTDEPS = \
THIRD_PARTY_LUA \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_MUSL \
THIRD_PARTY_NSYNC \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_STB \
THIRD_PARTY_XED \

View file

@ -8,7 +8,6 @@
*/
#endif
#include "libc/assert.h"
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
@ -19,11 +18,14 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/wait0.internal.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
@ -46,9 +48,6 @@
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/consts/tcp.h"
#include "libc/thread/spawn.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/thread/wait0.internal.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
#include "net/http/http.h"
@ -105,11 +104,11 @@
"Cache-Control: private; max-age=0\r\n"
int threads;
atomic_int workers;
atomic_int messages;
atomic_int listening;
atomic_int connections;
atomic_int closingtime;
_Atomic(int) workers;
_Atomic(int) messages;
_Atomic(int) listening;
_Atomic(int) connections;
_Atomic(int) closingtime;
const char *volatile status;
void *Worker(void *id) {

20
examples/hello4.c Normal file
View file

@ -0,0 +1,20 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/math.h"
#include "libc/stdio/stdio.h"
STATIC_YOINK("vga_console");
int main(int argc, char *argv[]) {
volatile long double x = -.5;
volatile long double y = 1.5;
printf("Hello World! %.19Lg\n", atan2l(x, y));
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
#include "libc/stdio/stdio.h"
/**

View file

@ -1,60 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/termios.h"
#include "libc/isystem/unistd.h"
#include "libc/math.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/termios.h"
/**
* @fileoverview Bare Metal VGA TTY demo.
*
* This program can boot as an operating system. Try it out:
*
* make -j8 o//examples/vga.com
* qemu-system-x86_64 -hda o//examples/vga.com -serial stdio
*
* Please note that, by default, APE binaries only use the serial port
* for stdio. To get the VGA console as an added bonus:
*
* STATIC_YOINK("vga_console");
*
* Should be added to the top of your main() program source file.
*/
STATIC_YOINK("vga_console");
int main(int argc, char *argv[]) {
volatile long double x = -.5;
volatile long double y = 1.5;
struct termios tio;
char buf[16];
ssize_t res;
if (tcgetattr(0, &tio) != -1) {
tio.c_lflag &= ~(ECHO | ICANON);
tcsetattr(0, TCSANOW, &tio);
}
write(1, "\e[5n", 4);
res = read(0, buf, 4);
if (res != 4 || memcmp(buf, "\e[0n", 4) != 0) {
printf("res = %d?\n", res);
return -1;
}
printf("Hello World! %.19Lg\n", atan2l(x, y));
// read/print loop so machine doesn't reset on metal
for (;;) {
if ((res = readansi(0, buf, 16)) > 0) {
printf("got %`'.*s\r\n", res, buf);
}
}
}

View file

@ -7,12 +7,16 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/s.h"
#include "libc/x/x.h"
#include "third_party/musl/ftw.h"
/**

View file

@ -17,20 +17,6 @@ void __assert_fail(const char *, const char *, int) hidden relegated;
#define static_assert _Static_assert
#endif
#define _unassert(x) \
do { \
if (__builtin_expect(!(x), 0)) { \
unreachable; \
} \
} while (0)
#define _npassert(x) \
do { \
if (__builtin_expect(!(x), 0)) { \
notpossible; \
} \
} while (0)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_ASSERT_H_ */

View file

@ -1,6 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_ATOMIC_H_
#define COSMOPOLITAN_LIBC_ATOMIC_H_
#include "libc/inttypes.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/struct/timespec.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/nr.h"
@ -25,6 +26,6 @@ struct timespec _timespec_real(void) {
int ax, dx;
struct timespec ts;
ax = clock_gettime(CLOCK_REALTIME_FAST, &ts);
if (ax) notpossible;
assert(!ax);
return ts;
}

View file

@ -21,12 +21,12 @@
/**
* Subtracts two nanosecond timestamps.
*/
struct timespec _timespec_sub(struct timespec a, struct timespec b) {
a.tv_sec -= b.tv_sec;
if (a.tv_nsec < b.tv_nsec) {
a.tv_nsec += 1000000000;
a.tv_sec--;
struct timespec _timespec_sub(struct timespec x, struct timespec y) {
x.tv_sec -= y.tv_sec;
x.tv_nsec -= y.tv_nsec;
if (x.tv_nsec < 0) {
x.tv_nsec += 1000000000;
x.tv_sec -= 1;
}
a.tv_nsec -= b.tv_nsec;
return a;
return x;
}

View file

@ -79,6 +79,14 @@ o/$(MODE)/libc/calls/vdsofunc.greg.o: private \
-ffreestanding \
-fno-sanitize=address
# we can't use asan because:
# asan guard pages haven't been allocated yet
o/$(MODE)/libc/calls/directmap.o \
o/$(MODE)/libc/calls/directmap-nt.o: private \
OVERRIDE_COPTS += \
-ffreestanding \
-fno-sanitize=address
# we can't use asan because:
# ntspawn allocates 128kb of heap memory via win32
o/$(MODE)/libc/calls/ntspawn.o \
@ -136,6 +144,12 @@ o/$(MODE)/libc/calls/ioctl-siocgifconf-nt.o: private \
-ffunction-sections \
-fdata-sections
# we want small code size because:
# to keep .text.head under 4096 bytes
o/$(MODE)/libc/calls/mman.greg.o: private \
OVERRIDE_COPTS += \
-Os
# we always want -Os because:
# va_arg codegen is very bloated in default mode
o//libc/calls/open.o \

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/timespec.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/sysv/consts/clock.h"

View file

@ -1,10 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_EXTEND_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_EXTEND_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void *_extend(void *, size_t, void *, intptr_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_EXTEND_INTERNAL_H_ */

View file

@ -44,34 +44,22 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
bool __force_sqlite_to_work_until_we_can_fix_it;
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
if (start < 0) return einval();
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
}
static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
int e;
struct flock *l;
uint32_t flags, err;
struct NtOverlapped ov;
int64_t pos, off, len, size;
struct NtByHandleFileInformation info;
if (!GetFileInformationByHandle(f->handle, &info)) {
return __winerr();
}
pos = 0;
if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) {
return __winerr();
}
if (!GetFileInformationByHandle(f->handle, &info)) return __winerr();
if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) return __winerr();
l = (struct flock *)arg;
len = l->l_len;
off = l->l_start;
size = (uint64_t)info.nFileSizeHigh << 32 | info.nFileSizeLow;
switch (l->l_whence) {
case SEEK_SET:
break;
@ -84,64 +72,37 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
default:
return einval();
}
if (!len) {
len = size - off;
}
if (off < 0 || len < 0) {
return einval();
}
bool32 ok;
struct NtOverlapped ov = {.hEvent = f->handle,
.Pointer = (void *)(uintptr_t)off};
if (!len) len = size - off;
if (off < 0 || len < 0) return einval();
_offset2overlap(f->handle, off, &ov);
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
flags = 0;
if (cmd != F_SETLKW) {
flags |= kNtLockfileFailImmediately;
}
if (l->l_type == F_WRLCK) {
flags |= kNtLockfileExclusiveLock;
}
e = errno;
ok = LockFileEx(f->handle, flags, 0, len, len >> 32, &ov);
if (cmd == F_GETLK) {
if (ok) {
l->l_type = F_UNLCK;
if (!UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
notpossible;
}
} else {
l->l_pid = -1;
ok = true;
}
}
if (ok) {
return 0;
} else if (__force_sqlite_to_work_until_we_can_fix_it) {
errno = e;
if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately;
/* TODO: How can we make SQLite locks on Windows to work? */
/* if (l->l_type == F_WRLCK) flags |= kNtLockfileExclusiveLock; */
if (LockFileEx(f->handle, flags, 0, len, len >> 32, &ov)) {
return 0;
} else {
err = GetLastError();
if (err == kNtErrorLockViolation) err = EAGAIN;
errno = err;
return -1;
}
}
if (l->l_type == F_UNLCK) {
if (cmd == F_GETLK) return einval();
e = errno;
} else if (l->l_type == F_UNLCK) {
if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
return 0;
} else if (errno == ENOLCK) {
errno = e;
return 0;
} else {
return 0;
err = GetLastError();
if (err == kNtErrorNotLocked) {
return 0;
} else {
errno = err;
return -1;
}
}
} else {
return einval();
}
return einval();
}
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {

View file

@ -20,14 +20,12 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
int sys_fcntl(int fd, int cmd, uintptr_t arg) {
int e, rc;
int rc;
bool islock;
if ((islock = cmd == F_GETLK || //
cmd == F_SETLK || //
@ -39,13 +37,9 @@ int sys_fcntl(int fd, int cmd, uintptr_t arg) {
}
cosmo2flock(arg);
}
e = errno;
rc = __sys_fcntl(fd, cmd, arg);
if (islock) {
flock2cosmo(arg);
} else if (rc == -1 && cmd == F_DUPFD_CLOEXEC && errno == EINVAL) {
errno = e;
rc = __fixupnewfd(__sys_fcntl(fd, F_DUPFD, arg), O_CLOEXEC);
}
return rc;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- 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
This is free and unencumbered software released into the public domain.
@ -26,6 +26,5 @@
*/
#include "libc/macros.internal.h"
fstatat64:
jmp fstatat
fstatat64: jmp fstatat
.endfn fstatat64,globl

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- 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
This is free and unencumbered software released into the public domain.
@ -26,6 +26,5 @@
*/
#include "libc/macros.internal.h"
ftruncate64:
jmp ftruncate
ftruncate64: jmp ftruncate
.endfn ftruncate64,globl

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/state.internal.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
// TODO(jart): These should be _Thread_local but doing that currently
// causes a regression with runitd.com on Windows.

View file

@ -20,7 +20,7 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
#include "libc/macros.internal.h"
#include "libc/nt/accounting.h"
#include "libc/runtime/sysconf.h"

View file

@ -27,7 +27,7 @@
#include "libc/dce.h"
#include "libc/intrin/lockcmpxchgp.h"
#include "libc/intrin/weaken.h"
#include "libc/thread/tls.h"
#include "libc/nexgen32e/threaded.h"
textwindows bool _check_interrupts(bool restartable, struct Fd *fd) {
bool res;

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- 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
This is free and unencumbered software released into the public domain.
@ -26,6 +26,5 @@
*/
#include "libc/macros.internal.h"
lstat64:
jmp lstat
lstat64: jmp lstat
.endfn lstat64,globl

View file

@ -17,14 +17,14 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/weaken.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
@ -201,9 +201,6 @@ int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
unsigned i;
#if IsModeDbg()
assert(y >= x);
if (!AreMemoryIntervalsOk(mm)) {
PrintMemoryIntervals(2, mm);
}
assert(AreMemoryIntervalsOk(mm));
#endif

View file

@ -74,7 +74,6 @@ noasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
if (!(*e & PAGE_V)) {
if (!maketables) return NULL;
if (!(p = __new_page(mm))) return NULL;
__clear_page(BANE + p);
*e = p | PAGE_V | PAGE_RW;
}
t = (uint64_t *)(BANE + (*e & PAGE_TA));
@ -118,7 +117,7 @@ static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
uint64_t i, j, *m, p, pe;
for (i = 0; i < mm->e820n; ++i) {
for (p = mm->e820[i].addr, pe = mm->e820[i].addr + mm->e820[i].size;
p != pe + 0x200000; p += 4096) {
p + 0x200000 < pe; p += 4096) {
m = __get_virtual(mm, pml4t, BANE + p, true);
if (m && !(*m & PAGE_V)) {
*m = p | PAGE_V | PAGE_RW;
@ -151,7 +150,7 @@ noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b) {
v = b + p->p_offset + i;
m = MAX(m, v);
} else {
v = __clear_page(BANE + __new_page(mm));
v = __clear_page(__new_page(mm));
}
*__get_virtual(mm, pml4t, p->p_vaddr + i, true) = (v & PAGE_TA) | f;
}

View file

@ -16,15 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/iovec.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
@ -36,89 +33,74 @@
#include "libc/intrin/weaken.h"
#include "libc/macros.internal.h"
#include "libc/sysv/consts/iov.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
int e, i;
size_t got;
bool masked;
ssize_t rc, toto;
sigset_t mask, oldmask;
if (fd < 0) {
return ebadf();
}
if (iovlen < 0) {
return einval();
}
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
return efault();
}
static bool once, demodernize;
int i, err;
ssize_t rc;
size_t got, toto;
if (fd < 0) return einval();
if (iovlen < 0) return einval();
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
}
if (IsMetal()) {
return espipe(); // must be serial or console if not zipos
}
if (IsWindows()) {
} else if (IsWindows()) {
if (fd < g_fds.n) {
return sys_read_nt(g_fds.p + fd, iov, iovlen, off);
} else {
return ebadf();
}
}
while (iovlen && !iov->iov_len) {
--iovlen;
++iov;
}
if (!iovlen) {
return sys_pread(fd, 0, 0, off, off);
} else if (IsMetal()) {
return enosys();
}
if (iovlen == 1) {
return sys_pread(fd, iov->iov_base, iov->iov_len, off, off);
return sys_pread(fd, iov[0].iov_base, iov[0].iov_len, off, off);
}
e = errno;
rc = sys_preadv(fd, iov, iovlen, off, off);
if (rc != -1 || errno != ENOSYS) return rc;
errno = e;
/*
* NT, 2018-era XNU, and 2007-era Linux don't support this system call
*/
if (!__vforked && !once) {
err = errno;
rc = sys_preadv(fd, iov, iovlen, off, off);
if (rc == -1 && errno == ENOSYS) {
errno = err;
once = true;
demodernize = true;
STRACE("demodernizing %s() due to %s", "preadv", "ENOSYS");
} else {
once = true;
return rc;
}
}
if (!demodernize) {
return sys_preadv(fd, iov, iovlen, off, off);
}
if (!iovlen) {
return sys_pread(fd, NULL, 0, off, off);
}
for (toto = i = 0; i < iovlen; ++i) {
rc = sys_pread(fd, iov[i].iov_base, iov[i].iov_len, off, off);
if (rc == -1) {
if (!toto) {
toto = -1;
if (toto && (errno == EINTR || errno == EAGAIN)) {
return toto;
} else {
return -1;
}
break;
}
got = rc;
toto += got;
off += got;
if (got != iov[i].iov_len) {
break;
}
if (!masked) {
sigfillset(&mask);
_npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask));
masked = true;
}
}
if (masked) {
_npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0));
}
return toto;

View file

@ -16,13 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/iovec.internal.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
@ -33,90 +31,75 @@
#include "libc/intrin/weaken.h"
#include "libc/macros.internal.h"
#include "libc/sysv/consts/iov.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
int64_t off) {
int i, e;
bool masked;
size_t sent;
ssize_t rc, toto;
sigset_t mask, oldmask;
if (fd < 0) {
return ebadf();
}
if (iovlen < 0) {
return einval();
}
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
return efault();
}
static bool once, demodernize;
int i, err;
ssize_t rc;
size_t sent, toto;
if (fd < 0) return einval();
if (iovlen < 0) return einval();
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_write)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
}
if (IsWindows()) {
} else if (IsWindows()) {
if (fd < g_fds.n) {
return sys_write_nt(fd, iov, iovlen, off);
} else {
return ebadf();
}
}
if (IsMetal()) {
return espipe(); // must be serial or console if not zipos
}
while (iovlen && !iov->iov_len) {
--iovlen;
++iov;
}
if (!iovlen) {
return sys_pwrite(fd, 0, 0, off, off);
} else if (IsMetal()) {
return enosys();
}
if (iovlen == 1) {
return sys_pwrite(fd, iov->iov_base, iov->iov_len, off, off);
return sys_pwrite(fd, iov[0].iov_base, iov[0].iov_len, off, off);
}
e = errno;
rc = sys_pwritev(fd, iov, iovlen, off, off);
if (rc != -1 || errno != ENOSYS) return rc;
errno = e;
/*
* NT, 2018-era XNU, and 2007-era Linux don't support this system call
*/
if (!once) {
err = errno;
rc = sys_pwritev(fd, iov, iovlen, off, off);
if (rc == -1 && errno == ENOSYS) {
errno = err;
once = true;
demodernize = true;
STRACE("demodernizing %s() due to %s", "pwritev", "ENOSYS");
} else {
once = true;
return rc;
}
}
if (!demodernize) {
return sys_pwritev(fd, iov, iovlen, off, off);
}
if (!iovlen) {
return sys_pwrite(fd, NULL, 0, off, off);
}
for (toto = i = 0; i < iovlen; ++i) {
rc = sys_pwrite(fd, iov[i].iov_base, iov[i].iov_len, off, off);
if (rc == -1) {
if (!toto) {
toto = -1;
if (toto && (errno == EINTR || errno == EAGAIN)) {
return toto;
} else {
return -1;
}
break;
}
sent = rc;
toto += sent;
off += sent;
if (sent != iov[i].iov_len) {
break;
}
if (!masked) {
sigfillset(&mask);
_npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask));
masked = true;
}
}
if (masked) {
_npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0));
}
return toto;

View file

@ -21,7 +21,7 @@
#include "libc/calls/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/thread/tls.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/internal.h"
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h"

View file

@ -20,28 +20,15 @@
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/iovec.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
#include "libc/vga/vga.internal.h"
ssize_t sys_readv_metal(struct Fd *fd, const struct iovec *iov, int iovlen) {
int i;
size_t got, toto;
struct MetalFile *file;
switch (fd->kind) {
case kFdConsole:
/*
* The VGA teletypewriter code may wish to send out "status report"
* escape sequences, in response to requests sent to it via write().
* Read & return these if they are available.
*/
if (weaken(sys_readv_vga)) {
ssize_t res = weaken(sys_readv_vga)(fd, iov, iovlen);
if (res > 0) return res;
}
/* fall through */
case kFdSerial:
return sys_readv_serial(fd, iov, iovlen);
case kFdFile:

View file

@ -18,7 +18,6 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/extend.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/strace.internal.h"
@ -47,11 +46,33 @@ static volatile size_t mapsize;
* @asyncsignalsafe
*/
int __ensurefds_unlocked(int fd) {
bool relocate;
uint64_t addr;
int prot, flags;
size_t size, chunk;
struct DirectMap dm;
if (fd < g_fds.n) return fd;
g_fds.n = fd + 1;
g_fds.e =
_extend(g_fds.p, g_fds.n * sizeof(*g_fds.p), g_fds.e, 0x6ff000000000);
STRACE("__ensurefds(%d) extending", fd);
size = mapsize;
chunk = FRAMESIZE;
if (IsAsan()) chunk *= 8;
addr = kMemtrackFdsStart + size;
prot = PROT_READ | PROT_WRITE;
flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
dm = sys_mmap((char *)addr, chunk, prot, flags, -1, 0);
TrackMemoryInterval(&_mmi, addr >> 16, (addr + chunk - 1) >> 16, dm.maphandle,
prot, flags, false, false, 0, chunk);
if (IsAsan()) {
addr = (addr >> 3) + 0x7fff8000;
dm = sys_mmap((char *)addr, FRAMESIZE, prot, flags, -1, 0);
TrackMemoryInterval(&_mmi, addr >> 16, addr >> 16, dm.maphandle, prot,
flags, false, false, 0, FRAMESIZE);
}
if (!size) {
g_fds.p = memcpy((char *)kMemtrackFdsStart, g_fds.__init_p,
sizeof(g_fds.__init_p));
}
g_fds.n = (size + chunk) / sizeof(*g_fds.p);
mapsize = size + chunk;
return fd;
}

View file

@ -19,8 +19,8 @@
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/intrin/pthread.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/stdio/lcg.internal.h"
/**

View file

@ -22,7 +22,7 @@
#include "libc/calls/struct/sched_param.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/thread/tls.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"

View file

@ -1,26 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SEMAPHORE_H_
#define COSMOPOLITAN_LIBC_CALLS_SEMAPHORE_H_
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define SEM_FAILED ((sem_t *)0)
typedef struct {
volatile int __val[4 * sizeof(long) / sizeof(int)];
} sem_t;
int sem_close(sem_t *);
int sem_destroy(sem_t *);
int sem_getvalue(sem_t *, int *);
int sem_init(sem_t *, int, unsigned);
sem_t *sem_open(const char *, int, ...);
int sem_post(sem_t *);
int sem_timedwait(sem_t *, const struct timespec *);
int sem_trywait(sem_t *);
int sem_unlink(const char *);
int sem_wait(sem_t *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_SEMAPHORE_H_ */

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/strace.internal.h"

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/state.internal.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
static pthread_mutex_t __sig_lock_obj;
@ -30,5 +30,5 @@ void(__sig_unlock)(void) {
}
__attribute__((__constructor__)) static void init(void) {
__sig_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
__sig_lock_obj.type = PTHREAD_MUTEX_RECURSIVE;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- 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
This is free and unencumbered software released into the public domain.

View file

@ -1,8 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_
#include "libc/intrin/nopl.internal.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/intrin/nopl.h"
#include "libc/intrin/pthread.h"
#include "libc/nexgen32e/threaded.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

View file

@ -25,9 +25,10 @@ struct Fd {
};
struct Fds {
int f; /* lowest free slot */
size_t n;
struct Fd *p, *e;
int f; /* lowest free slot */
size_t n; /* monotonic capacity */
struct Fd *p;
struct Fd __init_p[OPEN_MAX];
};
COSMOPOLITAN_C_END_

View file

@ -17,7 +17,6 @@ int utimensat(int, const char *, const struct timespec[2], int);
int timespec_get(struct timespec *, int);
int timespec_getres(struct timespec *, int);
int _timespec_cmp(struct timespec, struct timespec) pureconst;
bool _timespec_eq(struct timespec, struct timespec) pureconst;
bool _timespec_gte(struct timespec, struct timespec) pureconst;
int64_t _timespec_tomicros(struct timespec) pureconst;

View file

@ -19,7 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/errno.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/symboliclink.h"

View file

@ -30,7 +30,7 @@
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/macros.internal.h"
#include "libc/thread/tls.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"

View file

@ -23,7 +23,7 @@
#include "libc/dce.h"
#include "libc/dns/hoststxt.h"
#include "libc/fmt/fmt.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
#include "libc/macros.internal.h"
#include "libc/nt/systeminfo.h"
#include "libc/runtime/runtime.h"

View file

@ -20,7 +20,7 @@
#include "libc/dce.h"
#include "libc/dns/resolvconf.h"
#include "libc/fmt/fmt.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"

View file

@ -118,8 +118,7 @@ imaxdiv_t imaxdiv(intmax_t, intmax_t) pureconst;
#define lldiv(num, den) ((lldiv_t){(num) / (den), (num) % (den)})
#endif
#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 406 || defined(__llvm__)) && \
!defined(__STRICT_ANSI__)
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 406 || defined(__llvm__)
int128_t i128abs(int128_t) libcesque pureconst;
int128_t strtoi128(const char *, char **, int) paramsnonnull((1));
uint128_t strtou128(const char *, char **, int) paramsnonnull((1));

View file

@ -123,9 +123,7 @@ typedef __UINT64_TYPE__ uint64_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406 || \
defined(__llvm__)) && \
!defined(__STRICT_ANSI__)
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406 || defined(__llvm__)
typedef signed __int128 int128_t;
typedef unsigned __int128 uint128_t;
#endif

View file

@ -67,8 +67,8 @@
#endif
/* TODO(jart): Remove this in favor of GetStackSize() */
#if defined(COSMO) && (defined(MODE_DBG) || defined(__SANITIZE_ADDRESS__))
#define STACKSIZE 262144 /* 256kb stack */
#if defined(COSMO) && defined(MODE_DBG)
#define STACKSIZE 131072 /* 128kb stack */
#elif defined(COSMO)
#define STACKSIZE 65536 /* 64kb stack */
#else

View file

@ -25,10 +25,10 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/asancodes.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/leaky.internal.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/weaken.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/internal.h"
@ -39,7 +39,9 @@
#include "libc/mem/mem.h"
#include "libc/mem/reverse.internal.h"
#include "libc/nexgen32e/gc.internal.h"
#include "libc/nexgen32e/gettls.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nt/enum/version.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.internal.h"
@ -56,7 +58,6 @@
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "third_party/dlmalloc/dlmalloc.h"
STATIC_YOINK("_init_asan");
@ -171,7 +172,7 @@ struct ReportOriginHeap {
};
static int __asan_noreentry;
static pthread_spinlock_t __asan_lock;
static pthread_mutex_t __asan_lock;
static struct AsanMorgue __asan_morgue;
#define __asan_unreachable() \
@ -868,25 +869,25 @@ dontdiscard __asan_die_f *__asan_report_memory_fault(void *addr, int size,
void *__asan_morgue_add(void *p) {
int i;
void *r;
if (__threaded) pthread_spin_lock(&__asan_lock);
if (__threaded) pthread_mutex_lock(&__asan_lock);
i = __asan_morgue.i++ & (ARRAYLEN(__asan_morgue.p) - 1);
r = __asan_morgue.p[i];
__asan_morgue.p[i] = p;
if (__threaded) pthread_spin_unlock(&__asan_lock);
if (__threaded) pthread_mutex_unlock(&__asan_lock);
return r;
}
static void __asan_morgue_flush(void) {
int i;
void *p;
if (__threaded) pthread_spin_lock(&__asan_lock);
if (__threaded) pthread_mutex_lock(&__asan_lock);
for (i = 0; i < ARRAYLEN(__asan_morgue.p); ++i) {
if (__asan_morgue.p[i] && weaken(dlfree)) {
weaken(dlfree)(__asan_morgue.p[i]);
}
__asan_morgue.p[i] = 0;
}
if (__threaded) pthread_spin_unlock(&__asan_lock);
if (__threaded) pthread_mutex_unlock(&__asan_lock);
}
static size_t __asan_user_size(size_t n) {
@ -937,7 +938,7 @@ static void __asan_trace(struct AsanTrace *bt, const struct StackFrame *bp) {
size_t i, gi;
intptr_t addr;
struct Garbages *garbage;
garbage = __tls_enabled ? __get_tls()->tib_garbages : 0;
garbage = __tls_enabled ? ((cthread_t)__get_tls())->garbages : 0;
gi = garbage ? garbage->i : 0;
for (f1 = -1, i = 0; bp && i < ARRAYLEN(bt->p); ++i, bp = bp->next) {
if (f1 != (f2 = ((intptr_t)bp >> 16))) {
@ -1053,30 +1054,6 @@ int __asan_print_trace(void *p) {
return 0;
}
// Returns true if `p` was allocated by an IGNORE_LEAKS(function).
int __asan_is_leaky(void *p) {
int sym;
size_t c, i, n;
intptr_t f, *l;
struct AsanExtra *e;
struct SymbolTable *st;
if (!weaken(GetSymbolTable)) notpossible;
if (!(e = __asan_get_extra(p, &c))) return 0;
if (!__asan_read48(e->size, &n)) return 0;
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16)) return 0;
if (!(st = GetSymbolTable())) return 0;
for (i = 0; i < ARRAYLEN(e->bt.p) && e->bt.p[i]; ++i) {
if ((sym = weaken(__get_symbol)(st, e->bt.p[i])) == -1) continue;
f = st->addr_base + st->symbols[sym].x;
for (l = _leaky_start; l < _leaky_end; ++l) {
if (f == *l) {
return 1;
}
}
}
return 0;
}
static void __asan_deallocate(char *p, long kind) {
size_t c, n;
struct AsanExtra *e;

View file

@ -3,7 +3,6 @@
#include "libc/calls/struct/iovec.h"
#include "libc/intrin/asancodes.h"
#include "libc/macros.internal.h"
#include "libc/thread/thread.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -30,7 +29,6 @@ struct AsanFault __asan_check(const void *, long) nosideeffect;
void __asan_free(void *);
void *__asan_malloc(size_t);
int __asan_is_leaky(void *);
int __asan_malloc_trim(size_t);
int __asan_print_trace(void *);
void *__asan_calloc(size_t, size_t);

View file

@ -0,0 +1,16 @@
#ifndef COSMOPOLITAN_LIBC_BITS_BIGWORD_H_
#define COSMOPOLITAN_LIBC_BITS_BIGWORD_H_
#ifndef BIGWORD
#if __AVX512F__ + 0
#define BIGWORD 64
#elif __AVX2__ + 0
#define BIGWORD 32
#elif __SSE2__ + 0
#define BIGWORD 16
#else
#define BIGWORD __BIGGEST_ALIGNMENT__
#endif
#endif /*BIGWORD*/
#endif /* COSMOPOLITAN_LIBC_BITS_BIGWORD_H_ */

View file

@ -1,7 +1,7 @@
/*-*- 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
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,27 +16,32 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "third_party/nsync/cv.h"
#include "libc/intrin/cmpxchg.h"
/**
* Wakes at least one thread waiting on condition, e.g.
* Compares and exchanges.
*
* pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
* pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
* // ...
* pthread_mutex_lock(&lock);
* pthread_cond_signal(&cond, &lock);
* pthread_mutex_unlock(&lock);
*
* This function has no effect if there aren't any threads currently
* waiting on the condition.
*
* @return 0 on success, or errno on error
* @see pthread_cond_broadcast
* @see pthread_cond_wait
* @param ifthing is uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @param size is automatically supplied by macro wrapper
* @return true if value was exchanged, otherwise false
* @see _lockcmpxchg()
*/
int pthread_cond_signal(pthread_cond_t *cond) {
nsync_cv_signal((nsync_cv *)cond);
return 0;
bool(_cmpxchg)(void *ifthing, intptr_t isequaltome, intptr_t replaceitwithme,
size_t size) {
switch (size) {
case 1:
return _cmpxchg((int8_t *)ifthing, (int8_t)isequaltome,
(int8_t)replaceitwithme);
case 2:
return _cmpxchg((int16_t *)ifthing, (int16_t)isequaltome,
(int16_t)replaceitwithme);
case 4:
return _cmpxchg((int32_t *)ifthing, (int32_t)isequaltome,
(int32_t)replaceitwithme);
case 8:
return _cmpxchg((int64_t *)ifthing, (int64_t)isequaltome,
(int64_t)replaceitwithme);
default:
return false;
}
}

View file

@ -4,6 +4,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
bool _cmpxchg(void *, intptr_t, intptr_t, size_t);
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86__)
#define _cmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
@ -17,6 +19,9 @@ COSMOPOLITAN_C_START_
: "cc"); \
DidIt; \
})
#else
#define _cmpxchg(MEM, CMP, VAL) \
_cmpxchg(MEM, (intptr_t)(CMP), (intptr_t)(VAL), sizeof(*(MEM)))
#endif /* GNUC && !ANSI && x86 */
COSMOPOLITAN_C_END_

View file

@ -1,7 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_
#define COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_
#include "libc/intrin/nopl.internal.h"
#include "libc/thread/tls.h"
#include "libc/intrin/nopl.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/stdio/stdio.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/cxaatexit.internal.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
static pthread_mutex_t __cxa_lock_obj;

View file

@ -17,7 +17,7 @@ const char *DescribeCapability(char[20], int);
const char *DescribeClockName(char[32], int);
const char *DescribeDirfd(char[12], int);
const char *DescribeFrame(char[32], int);
const char *DescribeFutexOp(char[64], int);
const char *DescribeFutexOp(int);
const char *DescribeFutexResult(char[12], int);
const char *DescribeHow(char[12], int);
const char *DescribeMapFlags(char[64], int);
@ -30,7 +30,6 @@ const char *DescribeNtFileFlagAttr(char[256], uint32_t);
const char *DescribeNtFileMapFlags(char[64], uint32_t);
const char *DescribeNtFileShareFlags(char[64], uint32_t);
const char *DescribeNtFiletypeFlags(char[64], uint32_t);
const char *DescribeNtLockFileFlags(char[64], uint32_t);
const char *DescribeNtMovFileInpFlags(char[256], uint32_t);
const char *DescribeNtPageFlags(char[64], uint32_t);
const char *DescribeNtPipeModeFlags(char[64], uint32_t);
@ -61,7 +60,6 @@ const char *DescribeWhence(char[12], int);
#define DescribeClockName(x) DescribeClockName(alloca(32), x)
#define DescribeDirfd(x) DescribeDirfd(alloca(12), x)
#define DescribeFrame(x) DescribeFrame(alloca(32), x)
#define DescribeFutexOp(x) DescribeFutexOp(alloca(64), x)
#define DescribeFutexResult(x) DescribeFutexResult(alloca(12), x)
#define DescribeHow(x) DescribeHow(alloca(12), x)
#define DescribeMapFlags(x) DescribeMapFlags(alloca(64), x)
@ -73,7 +71,6 @@ const char *DescribeWhence(char[12], int);
#define DescribeNtFileMapFlags(x) DescribeNtFileMapFlags(alloca(64), x)
#define DescribeNtFileShareFlags(x) DescribeNtFileShareFlags(alloca(64), x)
#define DescribeNtFiletypeFlags(x) DescribeNtFiletypeFlags(alloca(64), x)
#define DescribeNtLockFileFlags(x) DescribeNtLockFileFlags(alloca(64), x)
#define DescribeNtMovFileInpFlags(x) DescribeNtMovFileInpFlags(alloca(256), x)
#define DescribeNtPageFlags(x) DescribeNtPageFlags(alloca(64), x)
#define DescribeNtPipeModeFlags(x) DescribeNtPipeModeFlags(alloca(64), x)

View file

@ -16,47 +16,16 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/futex.h"
const char *(DescribeFutexOp)(char buf[64], int x) {
bool priv = false;
if (x & FUTEX_PRIVATE_FLAG) {
priv = true;
x &= ~FUTEX_PRIVATE_FLAG;
}
bool real = false;
if (x & FUTEX_CLOCK_REALTIME) {
real = true;
x &= ~FUTEX_CLOCK_REALTIME;
}
char *p = buf;
if (x == FUTEX_WAIT) {
p = stpcpy(p, "FUTEX_WAIT");
} else if (x == FUTEX_WAKE) {
p = stpcpy(p, "FUTEX_WAKE");
} else if (x == FUTEX_REQUEUE) {
p = stpcpy(p, "FUTEX_REQUEUE");
} else if (x == FUTEX_WAIT_BITSET) {
p = stpcpy(p, "FUTEX_WAIT_BITSET");
} else {
p = stpcpy(p, "FUTEX_");
p = FormatUint32(p, x);
}
if (priv) {
p = stpcpy(p, "_PRIVATE");
}
if (real) {
p = stpcpy(p, "|FUTEX_CLOCK_REALTIME");
}
return buf;
const char *DescribeFutexOp(int x) {
if (x == FUTEX_WAIT) return "FUTEX_WAIT";
if (x == FUTEX_WAKE) return "FUTEX_WAKE";
if (x == FUTEX_REQUEUE) return "FUTEX_REQUEUE";
// order matters (the private bit might be zero)
if (x == FUTEX_WAIT_PRIVATE) return "FUTEX_WAIT_PRIVATE";
if (x == FUTEX_WAKE_PRIVATE) return "FUTEX_WAKE_PRIVATE";
if (x == FUTEX_REQUEUE_PRIVATE) return "FUTEX_REQUEUE_PRIVATE";
return "FUTEX_???";
}

View file

@ -1,50 +0,0 @@
/*-*- 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/intrin/describentoverlapped.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/nt/struct/overlapped.h"
const char *(DescribeNtOverlapped)(char b[128], struct NtOverlapped *o) {
int i = 0, n = 128;
bool gotsome = false;
if (!o) return "NULL";
i += ksnprintf(b + i, MAX(0, n - i), "{");
if (o->hEvent) {
if (gotsome) {
i += ksnprintf(b + i, MAX(0, n - i), ", ");
} else {
gotsome = true;
}
i += ksnprintf(b + i, MAX(0, n - i), ".hEvent = %ld", o->hEvent);
}
if (o->Pointer) {
if (gotsome) {
i += ksnprintf(b + i, MAX(0, n - i), ", ");
} else {
gotsome = true;
}
i += ksnprintf(b + i, MAX(0, n - i), ".Pointer = (void *)%p", o->Pointer);
}
i += ksnprintf(b + i, MAX(0, n - i), "}");
return b;
}

View file

@ -1,13 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_
#define COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_
#include "libc/mem/alloca.h"
#include "libc/nt/struct/overlapped.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
const char *DescribeNtOverlapped(char[128], struct NtOverlapped *);
#define DescribeNtOverlapped(x) DescribeNtOverlapped(alloca(128), x)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_DESCRIBENTOVERLAPPED_INTERNAL_H_ */

View file

@ -1,86 +0,0 @@
/*-*- 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/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/asancodes.h"
#include "libc/macros.internal.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#define G FRAMESIZE
static void _mapframe(void *p) {
int prot, flags;
struct DirectMap dm;
prot = PROT_READ | PROT_WRITE;
flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
if ((dm = sys_mmap(p, G, prot, flags, -1, 0)).addr != p) {
notpossible;
}
__mmi_lock();
if (TrackMemoryInterval(&_mmi, (uintptr_t)p >> 16, (uintptr_t)p >> 16,
dm.maphandle, prot, flags, false, false, 0, G)) {
notpossible;
}
__mmi_unlock();
}
/**
* Extends static allocation.
*
* This simple fixed allocator has unusual invariants
*
* !(p & 0xffff) && !(((p >> 3) + 0x7fff8000) & 0xffff)
*
* which must be the case when selecting a starting address.
*
* @param p points to start of memory region
* @param n specifies how many bytes are needed
* @param e points to end of memory that's allocated
* @param h is highest address to which `e` may grow
* @return new value for `e`
*/
noasan void *_extend(void *p, size_t n, void *e, intptr_t h) {
char *q;
#ifndef NDEBUG
if ((uintptr_t)SHADOW(p) & (G - 1)) notpossible;
if ((uintptr_t)p + (G << kAsanScale) > h) notpossible;
#endif
for (q = e; q < ((char *)p + n); q += 8) {
if (!((uintptr_t)q & (G - 1))) {
if (q + G > (char *)h) notpossible;
_mapframe(q);
if (IsAsan()) {
if (!((uintptr_t)SHADOW(q) & (G - 1))) {
_mapframe(SHADOW(q));
__asan_poison(q, G << kAsanScale, kAsanProtected);
}
}
}
if (IsAsan()) {
*SHADOW(q) = 0;
}
}
asm("mfence");
return q;
}

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/state.internal.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
void(__fds_lock)(void) {
pthread_mutex_lock(&__fds_lock_obj);

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/atomic.h"
#include "libc/runtime/runtime.h"
/**
@ -40,4 +39,4 @@
* though under normal circumstances, `__ftrace` should only be either
* zero or one.
*/
atomic_int __ftrace;
_Atomic(int) __ftrace;

View file

@ -20,14 +20,11 @@
#include "libc/macros.internal.h"
.privileged
_futex: push %rbp
mov %rsp,%rbp
mov %rcx,%r10
_futex: mov %rcx,%r10
mov __NR_futex,%eax
clc
syscall
jnc 1f
neg %eax
1: pop %rbp
ret
1: ret
.endfn _futex,globl,hidden

View file

@ -0,0 +1,12 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_FUTEX_INTERNAL_H_
#define COSMOPOLITAN_LIBC_INTRIN_FUTEX_INTERNAL_H_
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int _futex_wait(void *, int, char, struct timespec *) hidden;
int _futex_wake(void *, int, char) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_FUTEX_INTERNAL_H_ */

View file

@ -17,29 +17,34 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/strace.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describentoverlapped.internal.h"
#include "libc/nt/files.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/futex.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/sysv/consts/futex.h"
__msabi extern typeof(UnlockFileEx) *const __imp_UnlockFileEx;
int _futex(void *, int, int, struct timespec *) hidden;
/**
* Unlocks file on the New Technology.
*
* @return handle, or -1 on failure
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
*/
bool32 UnlockFileEx(int64_t hFile, uint32_t dwReserved,
uint32_t nNumberOfBytesToUnlockLow,
uint32_t nNumberOfBytesToUnlockHigh,
struct NtOverlapped *lpOverlapped) {
bool32 ok;
ok = __imp_UnlockFileEx(hFile, dwReserved, nNumberOfBytesToUnlockLow,
nNumberOfBytesToUnlockHigh, lpOverlapped);
if (!ok) __winerr();
STRACE("UnlockFileEx(%ld, %#x, %'zu, %s) → %hhhd% m", hFile, dwReserved,
(uint64_t)nNumberOfBytesToUnlockHigh << 32 | nNumberOfBytesToUnlockLow,
DescribeNtOverlapped(lpOverlapped), ok);
return ok;
int _futex_wait(void *addr, int expect, char pshared,
struct timespec *timeout) {
int op, ax, pf;
if (IsLinux() || IsOpenbsd()) {
pf = pshared == PTHREAD_PROCESS_PRIVATE ? FUTEX_PRIVATE_FLAG : 0;
op = FUTEX_WAIT | pf;
ax = _futex(addr, op, expect, timeout);
if (SupportsLinux() && pf && ax == -ENOSYS) {
// RHEL5 doesn't support FUTEX_PRIVATE_FLAG
op = FUTEX_WAIT;
ax = _futex(addr, op, expect, timeout);
}
if (IsOpenbsd() && ax > 0) ax = -ax; // yes openbsd does this w/o cf
STRACE("futex(%t, %s, %d, %s) → %s", addr, DescribeFutexOp(op), expect,
DescribeTimespec(0, timeout), DescribeFutexResult(ax));
return ax;
} else {
return pthread_yield();
}
}

View file

@ -16,16 +16,31 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/filelockflags.h"
#include "libc/intrin/futex.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/sysv/consts/futex.h"
static const struct DescribeFlags kNtLockFileFlags[] = {
{kNtLockfileFailImmediately, "FailImmediately"}, //
{kNtLockfileExclusiveLock, "ExclusiveLock"}, //
};
int _futex(void *, int, int) hidden;
const char *(DescribeNtLockFileFlags)(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kNtLockFileFlags, ARRAYLEN(kNtLockFileFlags),
"kNtLockfile", x);
int _futex_wake(void *addr, int count, char pshared) {
int op, ax, pf;
if (IsLinux() || IsOpenbsd()) {
pf = pshared == PTHREAD_PROCESS_PRIVATE ? FUTEX_PRIVATE_FLAG : 0;
op = FUTEX_WAKE | pf;
ax = _futex(addr, op, count);
if (SupportsLinux() && pf && ax == -ENOSYS) {
// RHEL5 doesn't support FUTEX_PRIVATE_FLAG
op = FUTEX_WAKE;
ax = _futex(addr, op, count);
}
STRACE("futex(%t, %s, %d) → %s", addr, DescribeFutexOp(op), count,
DescribeFutexResult(ax));
return ax;
} else {
return 0;
}
}

View file

@ -16,14 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/extend.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/weaken.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/o.h"
#include "libc/thread/thread.h"
STATIC_YOINK("_init_g_fds");
@ -34,39 +33,38 @@ static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x) {
int64_t h;
h = GetStdHandle(x);
if (!h || h == -1) return;
fds->p[i].kind = pushpop(kFdFile);
fds->p[i].handle = h;
fds->__init_p[i].kind = pushpop(kFdFile);
fds->__init_p[i].handle = h;
fds->f = i + 1;
}
textstartup void InitializeFileDescriptors(void) {
struct Fds *fds;
__fds_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
__fds_lock_obj.type = PTHREAD_MUTEX_RECURSIVE;
fds = VEIL("r", &g_fds);
fds->p = fds->e = (void *)0x6fe000040000;
fds->n = 4;
pushmov(&fds->n, ARRAYLEN(fds->__init_p));
fds->f = 3;
fds->e = _extend(fds->p, fds->n * sizeof(*fds->p), fds->e, 0x6ff000000000);
fds->p = fds->__init_p;
if (IsMetal()) {
extern const char vga_console[];
pushmov(&fds->f, 3ull);
if (weaken(vga_console)) {
fds->p[0].kind = pushpop(kFdConsole);
fds->p[1].kind = pushpop(kFdConsole);
fds->p[2].kind = pushpop(kFdConsole);
fds->__init_p[0].kind = pushpop(kFdConsole);
fds->__init_p[1].kind = pushpop(kFdConsole);
fds->__init_p[2].kind = pushpop(kFdConsole);
} else {
fds->p[0].kind = pushpop(kFdSerial);
fds->p[1].kind = pushpop(kFdSerial);
fds->p[2].kind = pushpop(kFdSerial);
fds->__init_p[0].kind = pushpop(kFdSerial);
fds->__init_p[1].kind = pushpop(kFdSerial);
fds->__init_p[2].kind = pushpop(kFdSerial);
}
fds->p[0].handle = VEIL("r", 0x3F8ull);
fds->p[1].handle = VEIL("r", 0x3F8ull);
fds->p[2].handle = VEIL("r", 0x3F8ull);
fds->__init_p[0].handle = VEIL("r", 0x3F8ull);
fds->__init_p[1].handle = VEIL("r", 0x3F8ull);
fds->__init_p[2].handle = VEIL("r", 0x3F8ull);
} else if (IsWindows()) {
SetupWinStd(fds, 0, kNtStdInputHandle);
SetupWinStd(fds, 1, kNtStdOutputHandle);
SetupWinStd(fds, 2, kNtStdErrorHandle);
}
fds->p[1].flags = O_WRONLY | O_APPEND;
fds->p[2].flags = O_WRONLY | O_APPEND;
fds->__init_p[1].flags = O_WRONLY | O_APPEND;
fds->__init_p[2].flags = O_WRONLY | O_APPEND;
}

View file

@ -16,10 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/thread/tls.h"
#include "libc/dce.h"
#include "libc/nexgen32e/gettls.h"
#include "libc/nexgen32e/threaded.h"
/**
* Returns current thread id.
@ -28,6 +31,22 @@
* if this is the main thread. On NetBSD, gettid() for the main thread
* is always 1.
*
* This function issues a system call. That stops being the case as soon
* as __install_tls() is called. That'll happen automatically, when you
* call clone() and provide the TLS parameter. We assume that when a TLS
* block exists, then
*
* *(int *)(__get_tls() + 0x38)
*
* will contain the thread id. Therefore when issuing clone() calls, the
* `CLONE_CHILD_SETTID` and `CLONE_CHILD_CLEARTID` flags should use that
* index as its `ctid` memory.
*
* gettid (single threaded) l: 126𝑐 41𝑛𝑠
* gettid (tls enabled) l: 2𝑐 1𝑛𝑠
*
* The TLS convention is important for reentrant lock performance.
*
* @return thread id greater than zero or -1 w/ errno
* @asyncsignalsafe
* @threadsafe
@ -36,7 +55,7 @@
int gettid(void) {
int tid;
if (__tls_enabled && !__vforked) {
tid = __get_tls()->tib_tid;
tid = *(int *)(__get_tls() + 0x38);
if (tid > 0) {
return tid;
}

View file

@ -43,20 +43,6 @@ $(LIBC_INTRIN_A).pkg: \
$(LIBC_INTRIN_A_OBJS) \
$(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x)_A).pkg)
# we can't use asan because:
# asan guard pages haven't been allocated yet
o/$(MODE)/libc/intrin/directmap.o \
o/$(MODE)/libc/intrin/directmap-nt.o: private \
OVERRIDE_COPTS += \
-ffreestanding \
-fno-sanitize=address
# we want small code size because:
# to keep .text.head under 4096 bytes
o/$(MODE)/libc/intrin/mman.greg.o: private \
OVERRIDE_COPTS += \
-Os
# we can't use asan and ubsan because:
# this is asan and ubsan
o/$(MODE)/libc/intrin/asan.o \
@ -93,6 +79,11 @@ o/$(MODE)/libc/intrin/futex_wait.o \
o/$(MODE)/libc/intrin/futex_wake.o \
o/$(MODE)/libc/intrin/gettid.greg.o \
o/$(MODE)/libc/intrin/sys_gettid.greg.o \
o/$(MODE)/libc/intrin/pthread_mutex_lock.o \
o/$(MODE)/libc/intrin/pthread_mutex_wait.o \
o/$(MODE)/libc/intrin/pthread_mutex_wake.o \
o/$(MODE)/libc/intrin/pthread_mutex_unlock.o \
o/$(MODE)/libc/intrin/pthread_mutex_trylock.o \
o/$(MODE)/libc/intrin/_trylock_debug_4.o \
o/$(MODE)/libc/intrin/_spinlock_debug_4.o: private \
OVERRIDE_CFLAGS += \

View file

@ -24,8 +24,6 @@
#include "libc/errno.h"
#include "libc/fmt/divmod10.internal.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/asancodes.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/kprintf.h"
@ -37,7 +35,9 @@
#include "libc/limits.h"
#include "libc/log/internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/gettls.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/threaded.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
@ -52,8 +52,6 @@
#include "libc/str/utf16.h"
#include "libc/sysv/consts/nr.h"
#include "libc/sysv/consts/prot.h"
#include "libc/thread/tls.h"
#include "libc/thread/tls2.h"
extern hidden struct SymbolTable *__symtab;
@ -183,22 +181,19 @@ privileged static void klog(const char *b, size_t n) {
: "=a"(rax), "=D"(rdi), "=S"(rsi), "=d"(rdx)
: "0"(__NR_write), "1"(2), "2"(b), "3"(n)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
if (rax < 0) {
notpossible;
}
}
}
privileged static size_t kformat(char *b, size_t n, const char *fmt,
va_list va) {
int si, y;
int si;
wint_t t, u;
const char *abet;
signed char type;
const char *s, *f;
unsigned long long x;
unsigned i, j, m, rem, sign, hash, cols, prec;
char c, *p, *e, pdot, zero, flip, dang, base, quot, uppr, ansi, z[128];
char c, *p, *e, pdot, zero, flip, dang, base, quot, uppr, z[128];
if (kistextpointer(b) || kisdangerous(b)) n = 0;
if (!kistextpointer(fmt)) fmt = "!!WONTFMT";
p = b;
@ -317,17 +312,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
if (!__tls_enabled) {
x = __pid;
} else {
x = __get_tls_privileged()->tib_tid;
}
if (!__nocolor && p + 7 <= e) {
*p++ = '\e';
*p++ = '[';
*p++ = '1';
*p++ = ';';
*p++ = '3';
*p++ = '0' + x % 8;
*p++ = 'm';
ansi = true;
x = *(int *)(__get_tls_privileged() + 0x38);
}
} else {
x = 666;
@ -705,15 +690,6 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
}
break;
}
if (ansi) {
if (p + 4 <= e) {
*p++ = '\e';
*p++ = '[';
*p++ = '0';
*p++ = 'm';
}
ansi = false;
}
break;
}
}

View file

@ -1,16 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_LEAKY_INTERNAL_H_
#define COSMOPOLITAN_LIBC_INTRIN_LEAKY_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define IGNORE_LEAKS(FUNC) \
STATIC_YOINK("_leaky_start"); \
void *_leaky_##FUNC[] _Section(".piro.relo.sort.leaky.2." #FUNC \
",\"aw\",@init_array #") = {FUNC}
extern intptr_t _leaky_end[] __attribute__((__weak__));
extern intptr_t _leaky_start[] __attribute__((__weak__));
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_LEAKY_INTERNAL_H_ */

47
libc/intrin/lockcmpxchg.c Normal file
View file

@ -0,0 +1,47 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/lockcmpxchg.h"
/**
* Compares and exchanges w/ lock prefix.
*
* @param ifthing is uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @param size is automatically supplied by macro wrapper
* @return true if value was exchanged, otherwise false
* @see cmpxchg() if only written by one thread
*/
bool(_lockcmpxchg)(void *ifthing, intptr_t isequaltome,
intptr_t replaceitwithme, size_t size) {
switch (size) {
case 1:
return _lockcmpxchg((int8_t *)ifthing, (int8_t)isequaltome,
(int8_t)replaceitwithme);
case 2:
return _lockcmpxchg((int16_t *)ifthing, (int16_t)isequaltome,
(int16_t)replaceitwithme);
case 4:
return _lockcmpxchg((int32_t *)ifthing, (int32_t)isequaltome,
(int32_t)replaceitwithme);
case 8:
return _lockcmpxchg((int64_t *)ifthing, (int64_t)isequaltome,
(int64_t)replaceitwithme);
default:
return false;
}
}

View file

@ -4,6 +4,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
bool _lockcmpxchg(void *, intptr_t, intptr_t, size_t);
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86__)
#define _lockcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
@ -17,6 +19,9 @@ COSMOPOLITAN_C_START_
: "cc"); \
DidIt; \
})
#else
#define _lockcmpxchg(MEM, CMP, VAL) \
_lockcmpxchg(MEM, (intptr_t)(CMP), (intptr_t)(VAL), sizeof(*(MEM)))
#endif /* GNUC && !ANSI && x86 */
COSMOPOLITAN_C_END_

View file

@ -1,50 +0,0 @@
/*-*- 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/strace.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/describentoverlapped.internal.h"
#include "libc/nt/files.h"
__msabi extern typeof(LockFileEx) *const __imp_LockFileEx;
/**
* Locks file on the New Technology.
*
* @return handle, or -1 on failure
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
*/
bool32 LockFileEx(int64_t hFile, uint32_t dwFlags, uint32_t dwReserved,
uint32_t nNumberOfBytesToLockLow,
uint32_t nNumberOfBytesToLockHigh,
struct NtOverlapped *lpOverlapped) {
bool32 ok;
STRACE("LockFileEx(%ld, %s, %#x, %'zu, %s) → ...", hFile,
DescribeNtLockFileFlags(dwFlags), dwReserved,
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
DescribeNtOverlapped(lpOverlapped));
ok = __imp_LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow,
nNumberOfBytesToLockHigh, lpOverlapped);
if (!ok) __winerr();
STRACE("LockFileEx(%ld, %s, %#x, %'zu, [%s]) → %hhhd% m", hFile,
DescribeNtLockFileFlags(dwFlags), dwReserved,
(uint64_t)nNumberOfBytesToLockHigh << 32 | nNumberOfBytesToLockLow,
DescribeNtOverlapped(lpOverlapped), ok);
return ok;
}

View file

@ -1,7 +1,7 @@
/*-*- 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
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,15 +16,29 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/timespec.h"
#include "libc/intrin/lockxadd.h"
#include "libc/runtime/runtime.h"
/**
* Compares two nanosecond timestamps.
* Compares and exchanges w/ lock prefix.
*
* @param ifthing is uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @param size is automatically supplied by macro wrapper
* @return value at location `*ifthing` *before* addition
* @see InterlockedAdd() for a very similar API
* @see xadd() if only written by one thread
*/
int _timespec_cmp(struct timespec a, struct timespec b) {
int cmp;
if (!(cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec))) {
cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
intptr_t(_lockxadd)(void *ifthing, intptr_t replaceitwithme, size_t size) {
switch (size) {
case 1:
return _lockxadd((int8_t *)ifthing, (int8_t)replaceitwithme);
case 2:
return _lockxadd((int16_t *)ifthing, (int16_t)replaceitwithme);
case 4:
return _lockxadd((int32_t *)ifthing, (int32_t)replaceitwithme);
case 8:
return _lockxadd((int64_t *)ifthing, (int64_t)replaceitwithme);
default:
abort();
}
return cmp;
}

View file

@ -1,7 +1,7 @@
/*-*- 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
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,21 +16,27 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "third_party/nsync/mu.h"
#include "libc/intrin/lockxchg.h"
/**
* Unlocks read-write lock.
* Compares and exchanges w/ lock prefix.
*
* @return 0 on success, or errno on error
* @raise EINVAL if lock is in a bad state
* @param memory is uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @param size is automatically supplied by macro wrapper
* @return true if value was exchanged, otherwise false
* @see xchg()
*/
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) {
if (rwlock->_iswrite) {
rwlock->_iswrite = 0;
nsync_mu_unlock((nsync_mu *)rwlock);
} else {
nsync_mu_runlock((nsync_mu *)rwlock);
intptr_t(lockxchg)(void *memory, void *localvar, size_t size) {
switch (size) {
case 1:
return lockxchg((int8_t *)memory, (int8_t *)localvar);
case 2:
return lockxchg((int16_t *)memory, (int16_t *)localvar);
case 4:
return lockxchg((int32_t *)memory, (int32_t *)localvar);
case 8:
return lockxchg((int64_t *)memory, (int64_t *)localvar);
default:
return false;
}
return 0;
}

View file

@ -16,11 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
#include "libc/macros.internal.h"
.init.start 200,_init__mmi
movb $OPEN_MAX,_mmi+8
movl $_mmi+24,_mmi+16
movb $PTHREAD_MUTEX_RECURSIVE,__mmi_lock_obj+16(%rip)
movb $PTHREAD_MUTEX_RECURSIVE,__mmi_lock_obj(%rip)
.init.end 200,_init__mmi

View file

@ -16,10 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/pthread.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/thread/thread.h"
// this lock currently needs to be (1) recursive and (2) not nsync
extern pthread_mutex_t __mmi_lock_obj;

View file

@ -16,6 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
pthread_mutex_t __mmi_lock_obj; // recursive :'(

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
/**
* Sets thread scheduler policy attribute, e.g.

View file

@ -1,7 +1,7 @@
/*-*- 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
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -17,8 +17,12 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
int pthread_cancel(pthread_t thread) {
return ESRCH;
}
void *__tls_get_addr(size_t v[2]) {
return NULL;
}

205
libc/intrin/pthread.h Normal file
View file

@ -0,0 +1,205 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_
#define COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_
#define PTHREAD_KEYS_MAX 64
#define PTHREAD_STACK_MIN FRAMESIZE
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
#define PTHREAD_BARRIER_SERIAL_THREAD 31337
#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
#define PTHREAD_MUTEX_NORMAL 0
#define PTHREAD_MUTEX_RECURSIVE 1
#define PTHREAD_MUTEX_ERRORCHECK 2
#define PTHREAD_MUTEX_STALLED 0
#define PTHREAD_MUTEX_ROBUST 1
#define PTHREAD_PROCESS_DEFAULT PTHREAD_PROCESS_PRIVATE
#define PTHREAD_PROCESS_PRIVATE 0
#define PTHREAD_PROCESS_SHARED 1
#define PTHREAD_CREATE_JOINABLE 0
#define PTHREAD_CREATE_DETACHED 1
#define PTHREAD_INHERIT_SCHED 0
#define PTHREAD_EXPLICIT_SCHED 1
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */
#define PTHREAD_ONCE_INIT {0}
#define PTHREAD_COND_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
#define PTHREAD_BARRIER_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
#define PTHREAD_RWLOCK_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
#define PTHREAD_MUTEX_INITIALIZER {PTHREAD_MUTEX_DEFAULT, \
PTHREAD_PROCESS_DEFAULT}
/* clang-format on */
typedef uintptr_t pthread_t;
typedef int pthread_id_np_t;
typedef char pthread_condattr_t;
typedef char pthread_rwlockattr_t;
typedef char pthread_barrierattr_t;
typedef unsigned pthread_key_t;
typedef void (*pthread_key_dtor)(void *);
typedef struct pthread_once_s {
_Atomic(char) lock;
} pthread_once_t;
typedef struct pthread_spinlock_s {
_Atomic(char) lock;
} pthread_spinlock_t;
typedef struct pthread_mutex_s {
char type;
char pshared;
int reent;
_Atomic(int) lock;
_Atomic(int) waits;
} pthread_mutex_t;
typedef struct pthread_mutexattr_s {
char type;
char pshared;
} pthread_mutexattr_t;
typedef struct pthread_cond_s {
char pshared;
_Atomic(int) waits;
_Atomic(unsigned) seq;
} pthread_cond_t;
typedef struct pthread_barrier_s {
char pshared;
int count;
_Atomic(int) waits;
_Atomic(int) popped;
} pthread_barrier_t;
typedef struct pthread_rwlock_s {
char pshared;
_Atomic(int) lock;
_Atomic(int) waits;
} pthread_rwlock_t;
typedef struct pthread_attr_s {
char detachstate;
char inheritsched;
int schedparam;
int schedpolicy;
int scope;
unsigned guardsize;
unsigned stacksize;
char *stackaddr;
} pthread_attr_t;
int pthread_yield(void);
void pthread_exit(void *) wontreturn;
pthread_t pthread_self(void) pureconst;
pthread_id_np_t pthread_getthreadid_np(void);
int64_t pthread_getunique_np(pthread_t);
int pthread_setname_np(pthread_t, const char *);
int pthread_getname_np(pthread_t, char *, size_t);
int pthread_getattr_np(pthread_t, pthread_attr_t *);
int pthread_attr_init(pthread_attr_t *);
int pthread_attr_destroy(pthread_attr_t *);
int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
int pthread_attr_setdetachstate(pthread_attr_t *, int);
int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
int pthread_attr_setguardsize(pthread_attr_t *, size_t);
int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
int pthread_attr_setinheritsched(pthread_attr_t *, int);
int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
int pthread_attr_getscope(const pthread_attr_t *, int *);
int pthread_attr_setscope(pthread_attr_t *, int);
int pthread_attr_getstack(const pthread_attr_t *, void **, size_t *);
int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
int pthread_attr_setstacksize(pthread_attr_t *, size_t);
int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *),
void *);
int pthread_detach(pthread_t);
int pthread_cancel(pthread_t);
int pthread_join(pthread_t, void **);
int pthread_equal(pthread_t, pthread_t);
int pthread_once(pthread_once_t *, void (*)(void));
int pthread_spin_init(pthread_spinlock_t *, int);
int pthread_spin_destroy(pthread_spinlock_t *);
int pthread_spin_lock(pthread_spinlock_t *);
int pthread_spin_unlock(pthread_spinlock_t *);
int pthread_spin_trylock(pthread_spinlock_t *);
int pthread_mutexattr_init(pthread_mutexattr_t *);
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_lock(pthread_mutex_t *);
int pthread_mutex_unlock(pthread_mutex_t *);
int pthread_mutex_trylock(pthread_mutex_t *);
int pthread_mutex_destroy(pthread_mutex_t *);
int pthread_mutex_consistent(pthread_mutex_t *);
int pthread_condattr_init(pthread_condattr_t *);
int pthread_condattr_destroy(pthread_condattr_t *);
int pthread_condattr_setpshared(pthread_condattr_t *, int);
int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
int pthread_cond_destroy(pthread_cond_t *);
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int pthread_cond_broadcast(pthread_cond_t *);
int pthread_cond_signal(pthread_cond_t *);
int pthread_rwlockattr_init(pthread_rwlockattr_t *);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *);
int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
int pthread_rwlock_destroy(pthread_rwlock_t *);
int pthread_rwlock_rdlock(pthread_rwlock_t *);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
int pthread_rwlock_wrlock(pthread_rwlock_t *);
int pthread_rwlock_trywrlock(pthread_rwlock_t *);
int pthread_rwlock_unlock(pthread_rwlock_t *);
int pthread_key_create(pthread_key_t *, pthread_key_dtor);
int pthread_key_delete(pthread_key_t);
int pthread_setspecific(pthread_key_t, void *);
void *pthread_getspecific(pthread_key_t);
int pthread_barrierattr_init(pthread_barrierattr_t *);
int pthread_barrierattr_destroy(pthread_barrierattr_t *);
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *);
int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
int pthread_barrier_wait(pthread_barrier_t *);
int pthread_barrier_destroy(pthread_barrier_t *);
int pthread_barrier_init(pthread_barrier_t *, const pthread_barrierattr_t *,
unsigned);
#define pthread_spin_init(pSpin, multiprocess) ((pSpin)->lock = 0, 0)
#define pthread_spin_destroy(pSpin) ((pSpin)->lock = -1, 0)
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 && \
!defined(__STRICT_ANSI__)
extern const errno_t EBUSY;
#define pthread_spin_lock(pSpin) \
({ \
pthread_spinlock_t *_s = pSpin; \
while (__atomic_test_and_set(&_s->lock, __ATOMIC_SEQ_CST)) donothing; \
0; \
})
#define pthread_spin_unlock(pSpin) \
({ \
pthread_spinlock_t *_s = pSpin; \
__atomic_store_n(&_s->lock, 0, __ATOMIC_RELAXED); \
0; \
})
#define pthread_spin_trylock(pSpin) \
({ \
pthread_spinlock_t *_s = pSpin; \
__atomic_test_and_set(&_s->lock, __ATOMIC_SEQ_CST) ? EBUSY : 0; \
})
#endif /* GCC 4.7+ */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_ */

View file

@ -3,8 +3,8 @@
#include "libc/calls/struct/cpuset.h"
#include "libc/calls/struct/sched_param.h"
#include "libc/calls/struct/timespec.h"
#include "libc/intrin/pthread.h"
#include "libc/runtime/stack.h"
#include "libc/thread/thread.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
#include "libc/str/str.h"
/**

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
/**
* Gets thread detachable attribute.

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
/**
* Returns size of unmapped pages at bottom of stack.

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "libc/intrin/pthread.h"
/**
* Returns thread inherit schedule attribute.

Some files were not shown because too many files have changed in this diff Show more