mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 19:00:27 +00:00
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 commit3265324e00
. 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 commite9272f03fb
. 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 commit155b378a39
. 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 commitbae7367774
. commit cd184ff7fe4f8539a3928e8f2b8703e699c199e4 Author: Gavin Hayes <gavin@computoid.com> Date: Wed Sep 21 22:41:55 2022 -0400 Revert "Rewrite recursive mutex code" This reverts commitcfcf5918bc
. 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 commit333768440c
. 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 commitcdb2284f0d
. commit d10cd5c40f576a2dde8448338d2e9b3d88e160f8 Author: Gavin Hayes <gavin@computoid.com> Date: Wed Sep 21 22:41:50 2022 -0400 Revert "Import nsync" This reverts commit5dff63a31c
. commit 2a49d50c29f518367e0a51cb7a0a2b4b0a1679f0 Author: Gavin Hayes <gavin@computoid.com> Date: Wed Sep 21 22:41:49 2022 -0400 Revert "Fix the build" This reverts commit3de35e196c
. 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 commitb5cb71ab84
. commit 43bf84f09737bf87d79c7650dde52e030556056d Author: Gavin Hayes <gavin@computoid.com> Date: Wed Sep 21 22:41:48 2022 -0400 Revert "Add *NSYNC mu_test" This reverts commit9b89a7c51d
. 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 commit569c031934
. 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 commit55ddf73484
. 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 commit0305194d98
. 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 commitc03359c637
. 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 commit116bda997e
. 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 commitc4eb701d56
. commit 86f6a61d16e2c896939f536119ba328c7220f1eb Author: Gavin Hayes <gavin@computoid.com> Date: Wed Sep 21 22:41:38 2022 -0400 Revert "Fix the build" This reverts commit790c661317
. 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 commit827f25f054
. commit 3a5b536995cf8c48fffd371097aae9dfbeeebb44 Author: Gavin Hayes <gavin@computoid.com> Date: Wed Sep 21 22:41:36 2022 -0400 Revert "Fix preadv() and pwritev()" This reverts commit050062bcbb
. 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 commita5fa90a21f
. 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 commitc64e7eaf7c
. 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 commit30140812f0
.
This commit is contained in:
parent
30140812f0
commit
a80eea78fe
419 changed files with 2468 additions and 10224 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -4,12 +4,10 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "vista"
|
||||
- "flake"
|
||||
pull_request:
|
||||
branches:
|
||||
- "master"
|
||||
- "vista"
|
||||
|
||||
# run workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
|
4
Makefile
4
Makefile
|
@ -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 \
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||

|
||||
|
||||
[](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
|
||||
|
|
83
ape/ape.S
83
ape/ape.S
|
@ -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 # PDPT←PML4T (+)
|
||||
movl $0x7c000+PAGE_V+PAGE_RW,0x7e800-SEG # PDPT←PML4T (-)
|
||||
movl $0x7b000+PAGE_V+PAGE_RW,0x7d000-SEG # PDT←PDPT (+)
|
||||
|
@ -1410,14 +1392,13 @@ pinit: push %ds
|
|||
movl $0x79000+PAGE_V+PAGE_RW,0x7a000-SEG # PD←PDT (-)
|
||||
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 # PML4T←CR3
|
||||
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
|
||||
|
|
13
ape/ape.lds
13
ape/ape.lds
|
@ -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) */
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
30
ape/loader.c
30
ape/loader.c
|
@ -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) {
|
||||
|
|
|
@ -14,7 +14,7 @@ struct ApeLoader {
|
|||
int os;
|
||||
char *prog;
|
||||
char *page;
|
||||
void *systemcall;
|
||||
void *syscall;
|
||||
};
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_LOADER_H_ */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
20
examples/hello4.c
Normal 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;
|
||||
}
|
2054
examples/mu_test.c
2054
examples/mu_test.c
File diff suppressed because it is too large
Load diff
|
@ -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"
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
||||
/**
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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_
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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_ */
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
/**
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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_ */
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. │
|
||||
│ │
|
||||
|
|
|
@ -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_
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
16
libc/intrin/bigword.internal.h
Normal file
16
libc/intrin/bigword.internal.h
Normal 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_ */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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_
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_???";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
12
libc/intrin/futex.internal.h
Normal file
12
libc/intrin/futex.internal.h
Normal 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_ */
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 += \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
47
libc/intrin/lockcmpxchg.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/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;
|
||||
}
|
||||
}
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 :'(
|
||||
|
|
|
@ -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.
|
|
@ -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
205
libc/intrin/pthread.h
Normal 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_ */
|
|
@ -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_
|
||||
|
|
@ -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"
|
||||
|
||||
/**
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue