Make improvements

- More timspec_*() and timeval_*() APIs have been introduced.
- The copyfd() function is now simplified thanks to POSIX rules.
- More Cosmo-specific APIs have been moved behind the COSMO define.
- The setitimer() polyfill for Windows NT is now much higher quality.
- Fixed build error for MODE=aarch64 due to -mstringop-strategy=loop.
- This change introduces `make MODE=nox87 toolchain` which makes it
  possible to build programs using your cosmocc toolchain that don't
  have legacy fpu instructions. This is useful, for example, if you
  want to have a ~22kb tinier blink virtual machine.
This commit is contained in:
Justine Tunney 2023-06-15 13:50:42 -07:00
parent 8dc11afcf6
commit c3440d040c
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
132 changed files with 539 additions and 587 deletions

View file

@ -364,6 +364,28 @@ TARGET_ARCH ?= \
-msse3 -msse3
endif endif
# no x87 instructions mode
#
# export MODE=nox87
# make -j8 toolchain
# cosmocc -o /tmp/hello.com hello.c
#
# lets you shave ~23kb off blink
#
# git clone https://github.com/jart/blink
# cd blink
# ./configure --disable-x87
# make -j8
# o//blink/blink /tmp/hello.com
#
ifeq ($(MODE), nox87)
ENABLE_FTRACE = 1
CONFIG_COPTS += -mlong-double-64
CONFIG_CCFLAGS += $(BACKTRACES) -O2
CONFIG_CPPFLAGS += -DSYSDEBUG -DNOX87
TARGET_ARCH ?= -msse3
endif
# LLVM Mode # LLVM Mode
ifeq ($(MODE), llvm) ifeq ($(MODE), llvm)
TARGET_ARCH ?= -msse3 TARGET_ARCH ?= -msse3

View file

@ -33,7 +33,6 @@
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
#ifdef __x86_64__ #ifdef __x86_64__
/** /**

View file

@ -42,14 +42,6 @@
#define MAP_FAILED ((void *)-1) #define MAP_FAILED ((void *)-1)
#define ARCH_SET_GS 0x1001
#define ARCH_SET_FS 0x1002
#define ARCH_GET_FS 0x1003
#define ARCH_GET_GS 0x1004
#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT)
#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
#define WCOREDUMP(s) (128 & (s)) #define WCOREDUMP(s) (128 & (s))
#define WEXITSTATUS(s) ((0xff00 & (s)) >> 8) #define WEXITSTATUS(s) ((0xff00 & (s)) >> 8)
#define WIFCONTINUED(s) ((s) == 0xffff) #define WIFCONTINUED(s) ((s) == 0xffff)
@ -69,11 +61,9 @@ COSMOPOLITAN_C_START_
typedef int sig_atomic_t; typedef int sig_atomic_t;
bool32 isatty(int) nosideeffect; bool32 isatty(int) nosideeffect;
char *commandv(const char *, char *, size_t);
char *get_current_dir_name(void) dontdiscard; char *get_current_dir_name(void) dontdiscard;
char *getcwd(char *, size_t); char *getcwd(char *, size_t);
char *realpath(const char *, char *); char *realpath(const char *, char *);
char *replaceuser(const char *) dontdiscard;
char *ttyname(int); char *ttyname(int);
int access(const char *, int) dontthrow; int access(const char *, int) dontthrow;
int chdir(const char *); int chdir(const char *);
@ -122,7 +112,6 @@ int getpriority(int, unsigned);
int getresgid(unsigned *, unsigned *, unsigned *); int getresgid(unsigned *, unsigned *, unsigned *);
int getresuid(unsigned *, unsigned *, unsigned *); int getresuid(unsigned *, unsigned *, unsigned *);
int getsid(int) nosideeffect libcesque; int getsid(int) nosideeffect libcesque;
int gettid(void) libcesque;
int ioprio_get(int, int); int ioprio_get(int, int);
int ioprio_set(int, int, int); int ioprio_set(int, int, int);
int issetugid(void); int issetugid(void);
@ -133,8 +122,6 @@ int lchown(const char *, unsigned, unsigned);
int link(const char *, const char *) dontthrow; int link(const char *, const char *) dontthrow;
int linkat(int, const char *, int, const char *, int); int linkat(int, const char *, int, const char *, int);
int madvise(void *, uint64_t, int); int madvise(void *, uint64_t, int);
int makedirs(const char *, unsigned);
int memfd_create(const char *, unsigned int);
int mincore(void *, size_t, unsigned char *); int mincore(void *, size_t, unsigned char *);
int mkdir(const char *, unsigned); int mkdir(const char *, unsigned);
int mkdirat(int, const char *, unsigned); int mkdirat(int, const char *, unsigned);
@ -146,14 +133,10 @@ int nice(int);
int open(const char *, int, ...); int open(const char *, int, ...);
int openat(int, const char *, int, ...); int openat(int, const char *, int, ...);
int pause(void); int pause(void);
int personality(uint64_t);
int pipe(int[hasatleast 2]); int pipe(int[hasatleast 2]);
int pipe2(int[hasatleast 2], int); int pipe2(int[hasatleast 2], int);
int pivot_root(const char *, const char *);
int pledge(const char *, const char *);
int posix_fadvise(int, int64_t, int64_t, int); int posix_fadvise(int, int64_t, int64_t, int);
int posix_madvise(void *, uint64_t, int); int posix_madvise(void *, uint64_t, int);
int prctl(int, ...);
int raise(int); int raise(int);
int reboot(int); int reboot(int);
int remove(const char *); int remove(const char *);
@ -161,7 +144,6 @@ int rename(const char *, const char *);
int renameat(int, const char *, int, const char *); int renameat(int, const char *, int, const char *);
int rmdir(const char *); int rmdir(const char *);
int sched_yield(void); int sched_yield(void);
int seccomp(unsigned, unsigned, void *);
int setegid(unsigned); int setegid(unsigned);
int seteuid(unsigned); int seteuid(unsigned);
int setfsgid(unsigned); int setfsgid(unsigned);
@ -182,37 +164,21 @@ int siginterrupt(int, int);
int symlink(const char *, const char *); int symlink(const char *, const char *);
int symlinkat(const char *, int, const char *); int symlinkat(const char *, int, const char *);
int sync_file_range(int, int64_t, int64_t, unsigned); int sync_file_range(int, int64_t, int64_t, unsigned);
int sys_iopl(int);
int sys_mlock(const void *, size_t);
int sys_mlock2(const void *, size_t, int);
int sys_mlockall(int);
int sys_munlock(const void *, size_t);
int sys_munlockall(void);
int sys_ptrace(int, ...);
int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
int tcgetpgrp(int); int tcgetpgrp(int);
int tcsetpgrp(int, int); int tcsetpgrp(int, int);
int tgkill(int, int, int);
int tkill(int, int);
int tmpfd(void);
int touch(const char *, unsigned);
int truncate(const char *, int64_t); int truncate(const char *, int64_t);
int ttyname_r(int, char *, size_t); int ttyname_r(int, char *, size_t);
int unlink(const char *); int unlink(const char *);
int unlink_s(const char **);
int unlinkat(int, const char *, int); int unlinkat(int, const char *, int);
int unveil(const char *, const char *);
int usleep(unsigned); int usleep(unsigned);
int vfork(void) returnstwice; int vfork(void) returnstwice;
int wait(int *); int wait(int *);
int waitpid(int, int *, int); int waitpid(int, int *, int);
long ptrace(int, ...);
ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned); ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned);
ssize_t lseek(int, int64_t, int); ssize_t lseek(int, int64_t, int);
ssize_t pread(int, void *, size_t, int64_t); ssize_t pread(int, void *, size_t, int64_t);
ssize_t pwrite(int, const void *, size_t, int64_t); ssize_t pwrite(int, const void *, size_t, int64_t);
ssize_t read(int, void *, size_t); ssize_t read(int, void *, size_t);
ssize_t readansi(int, char *, size_t);
ssize_t readlink(const char *, char *, size_t); ssize_t readlink(const char *, char *, size_t);
ssize_t readlinkat(int, const char *, char *, size_t); ssize_t readlinkat(int, const char *, char *, size_t);
ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned); ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned);
@ -225,20 +191,38 @@ unsigned umask(unsigned);
void sync(void); void sync(void);
#ifdef COSMO #ifdef COSMO
#define fileexists __fileexists
#define isdirectory __isdirectory
#define isexecutable __isexecutable
#define isregularfile __isregularfile
#define issymlink __issymlink
#define ischardev __ischardev
#define copyfd __copyfd
bool fileexists(const char *); bool fileexists(const char *);
bool isdirectory(const char *); bool isdirectory(const char *);
bool isexecutable(const char *); bool isexecutable(const char *);
bool isregularfile(const char *); bool isregularfile(const char *);
bool issymlink(const char *); bool issymlink(const char *);
bool32 ischardev(int) nosideeffect; bool32 ischardev(int);
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, unsigned); char *commandv(const char *, char *, size_t);
char *replaceuser(const char *) dontdiscard;
int gettid(void) libcesque;
int makedirs(const char *, unsigned);
int memfd_create(const char *, unsigned int);
int personality(uint64_t);
int pivot_root(const char *, const char *);
int pledge(const char *, const char *);
int prctl(int, ...);
int seccomp(unsigned, unsigned, void *);
int sys_iopl(int);
int sys_mlock(const void *, size_t);
int sys_mlock2(const void *, size_t, int);
int sys_mlockall(int);
int sys_munlock(const void *, size_t);
int sys_munlockall(void);
int sys_ptrace(int, ...);
int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
int tgkill(int, int, int);
int tkill(int, int);
int tmpfd(void);
int touch(const char *, unsigned);
int unveil(const char *, const char *);
long ptrace(int, ...);
ssize_t copyfd(int, int, size_t);
ssize_t readansi(int, char *, size_t);
#endif #endif
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_

View file

@ -103,6 +103,7 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: private \
COPTS += \ COPTS += \
-fno-sanitize=all -fno-sanitize=all
ifneq ($(ARCH), aarch64)
# we always want -O3 because: # we always want -O3 because:
# it makes the code size smaller too # it makes the code size smaller too
# we need -mstringop-strategy=loop because: # we need -mstringop-strategy=loop because:
@ -116,6 +117,7 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: private \
COPTS += \ COPTS += \
-O3 \ -O3 \
-mstringop-strategy=loop -mstringop-strategy=loop
endif
# we must disable static stack safety because: # we must disable static stack safety because:
# these functions use alloca(n) # these functions use alloca(n)

View file

@ -42,7 +42,6 @@
* time. Among the more popular is CLOCK_MONOTONIC. This function has a * time. Among the more popular is CLOCK_MONOTONIC. This function has a
* zero syscall implementation of that on modern x86. * zero syscall implementation of that on modern x86.
* *
* nowl l: 45𝑐 15𝑛𝑠
* rdtsc l: 13𝑐 4𝑛𝑠 * rdtsc l: 13𝑐 4𝑛𝑠
* gettimeofday l: 44𝑐 14𝑛𝑠 * gettimeofday l: 44𝑐 14𝑛𝑠
* clock_gettime l: 40𝑐 13𝑛𝑠 * clock_gettime l: 40𝑐 13𝑛𝑠

View file

@ -17,59 +17,34 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/errno.h" #include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#define CHUNK 32768
/** /**
* Copies data between fds the old fashioned way. * Copies data between file descriptors the old fashioned way.
* *
* @return bytes successfully exchanged * This function is intended for simple programs without signals. If
* signals are in play, then `SA_RESTART` needs to be used.
*
* @param in is input file descriptor
* @param out is input file descriptor
* @param n is number of bytes to exchange, or -1 for until eof
* @return bytes successfully exchanged, or -1 w/ errno
*/ */
ssize_t _copyfd(int infd, int outfd, size_t n) { ssize_t copyfd(int in, int out, size_t n) {
int e; size_t i;
char *buf; char buf[512];
ssize_t rc; ssize_t dr, dw;
size_t i, j, got, sent; for (i = 0; i < n; i += dr) {
rc = 0; dr = read(in, buf, MIN(n - i, sizeof(buf)));
if (n) { if (dr == -1) return -1;
if ((buf = malloc(CHUNK))) { if (!dr) break;
for (e = errno, i = 0; i < n; i += j) { dw = write(out, buf, dr);
rc = read(infd, buf, CHUNK); if (dw == -1) return -1;
if (rc == -1) { if (dw != dr) {
// eintr may interrupt the read operation // POSIX requires atomic IO up to PIPE_BUF
if (i && errno == EINTR) { // The minimum permissible PIPE_BUF is 512
// suppress error if partially completed __builtin_trap();
errno = e;
rc = i;
}
break;
}
got = rc;
if (!got) {
rc = i;
break;
}
// write operation must complete
for (j = 0; j < got; j += sent) {
rc = write(outfd, buf + j, got - j);
if (rc != -1) {
sent = rc;
} else if (errno == EINTR) {
// write operation must be uninterruptible
errno = e;
sent = 0;
} else {
break;
}
}
if (rc == -1) break;
}
free(buf);
} else {
rc = -1;
} }
} }
return rc; return i;
} }

View file

@ -17,10 +17,10 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/asan.internal.h" #include "libc/calls/asan.internal.h"
#include "libc/calls/struct/itimerval.internal.h"
#include "libc/calls/struct/timespec.h" #include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h" #include "libc/calls/struct/timespec.internal.h"
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/timeval.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"

View file

@ -21,6 +21,7 @@
#include "libc/calls/struct/itimerval.internal.h" #include "libc/calls/struct/itimerval.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -41,12 +42,7 @@ int getitimer(int which, struct itimerval *curvalue) {
} else { } else {
rc = sys_setitimer_nt(which, 0, curvalue); rc = sys_setitimer_nt(which, 0, curvalue);
} }
if (curvalue) { STRACE("getitimer(%s, [%s]) → %d% m", DescribeItimer(which),
STRACE("getitimer(%d, [{{%'ld, %'ld}, {%'ld, %'ld}}]) → %d% m", which, DescribeItimerval(rc, curvalue), rc);
curvalue->it_interval.tv_sec, curvalue->it_interval.tv_usec,
curvalue->it_value.tv_sec, curvalue->it_value.tv_usec, rc);
} else {
STRACE("getitimer(%d, 0) → %d% m", which, rc);
}
return rc; return rc;
} }

View file

@ -38,13 +38,13 @@ static gettimeofday_f *__gettimeofday = __gettimeofday_init;
* Returns system wall time in microseconds, e.g. * Returns system wall time in microseconds, e.g.
* *
* int64_t t; * int64_t t;
* char p[30]; * char p[20];
* struct tm tm; * struct tm tm;
* struct timeval tv; * struct timeval tv;
* gettimeofday(&tv, 0); * gettimeofday(&tv, 0);
* t = tv.tv_sec; * t = tv.tv_sec;
* gmtime_r(&t, &tm); * gmtime_r(&t, &tm);
* FormatHttpDateTime(p, &tm); * iso8601(p, &tm);
* printf("%s\n", p); * printf("%s\n", p);
* *
* @param tv points to timeval that receives result if non-NULL * @param tv points to timeval that receives result if non-NULL

View file

@ -16,120 +16,49 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/sig.internal.h" #include "libc/calls/sig.internal.h"
#include "libc/calls/struct/itimerval.h" #include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/siginfo.h" #include "libc/calls/struct/timeval.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/strace.internal.h"
#include "libc/log/check.h"
#include "libc/math.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/nexgen32e/nt2sysv.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thread.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/itimer.h" #include "libc/sysv/consts/itimer.h"
#include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
#ifdef __x86_64__ #ifdef __x86_64__
/** static struct itimerval g_setitimer;
* @fileoverview Heartbreaking polyfill for SIGALRM on NT.
*
* Threads are used to trigger the SIGALRM handler, which should
* hopefully be an unfancy function like this:
*
* void OnAlarm(int sig, struct siginfo *si, struct ucontext *uc) {
* g_alarmed = true;
* }
*
* This is needed because WIN32 provides no obvious solutions for
* interrupting i/o operations on the standard input handle.
*/
static bool __hastimer;
static bool __singleshot;
static long double __lastalrm;
static long double __interval;
textwindows void _check_sigalrm(void) { textwindows void _check_sigalrm(void) {
// TODO(jart): use a different timing source struct timeval now;
// TODO(jart): synchronize across intervals? if (timeval_iszero(g_setitimer.it_value)) return;
long double now, elapsed; now = timeval_real();
if (!__hastimer) return; if (timeval_cmp(now, g_setitimer.it_value) < 0) return;
now = nowl(); if (timeval_iszero(g_setitimer.it_interval)) {
elapsed = now - __lastalrm; g_setitimer.it_value = timeval_zero;
if (elapsed > __interval) { } else {
__sig_add(0, SIGALRM, SI_TIMER); do {
if (__singleshot) { g_setitimer.it_value =
__hastimer = false; timeval_add(g_setitimer.it_value, g_setitimer.it_interval);
} else { } while (timeval_cmp(now, g_setitimer.it_value) > 0);
__lastalrm = now;
}
} }
__sig_add(0, SIGALRM, SI_TIMER);
} }
textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue, textwindows int sys_setitimer_nt(int which, const struct itimerval *neu,
struct itimerval *out_opt_oldvalue) { struct itimerval *old) {
long double elapsed, untilnext; if (which != ITIMER_REAL || (neu && (!timeval_isvalid(neu->it_value) ||
!timeval_isvalid(neu->it_interval)))) {
if (which != ITIMER_REAL ||
(newvalue && (!(0 <= newvalue->it_value.tv_usec &&
newvalue->it_value.tv_usec < 1000000) ||
!(0 <= newvalue->it_interval.tv_usec &&
newvalue->it_interval.tv_usec < 1000000)))) {
return einval(); return einval();
} }
if (old) {
if (out_opt_oldvalue) { old->it_interval = g_setitimer.it_interval;
if (__hastimer) { old->it_value = timeval_subz(g_setitimer.it_value, timeval_real());
elapsed = nowl() - __lastalrm;
if (elapsed > __interval) {
untilnext = 0;
} else {
untilnext = __interval - elapsed;
}
out_opt_oldvalue->it_interval.tv_sec = __interval;
out_opt_oldvalue->it_interval.tv_usec = 1 / 1e6 * fmodl(__interval, 1);
out_opt_oldvalue->it_value.tv_sec = untilnext;
out_opt_oldvalue->it_value.tv_usec = 1 / 1e6 * fmodl(untilnext, 1);
} else {
out_opt_oldvalue->it_interval.tv_sec = 0;
out_opt_oldvalue->it_interval.tv_usec = 0;
out_opt_oldvalue->it_value.tv_sec = 0;
out_opt_oldvalue->it_value.tv_usec = 0;
}
} }
if (neu) {
if (newvalue) { g_setitimer.it_interval = neu->it_interval;
if (newvalue->it_interval.tv_sec || newvalue->it_interval.tv_usec || g_setitimer.it_value = timeval_iszero(neu->it_value)
newvalue->it_value.tv_sec || newvalue->it_value.tv_usec) { ? timeval_zero
__hastimer = true; : timeval_add(timeval_real(), neu->it_value);
if (newvalue->it_interval.tv_sec || newvalue->it_interval.tv_usec) {
__singleshot = false;
__interval = newvalue->it_interval.tv_sec +
1 / 1e6 * newvalue->it_interval.tv_usec;
} else {
__singleshot = true;
__interval =
newvalue->it_value.tv_sec + 1 / 1e6 * newvalue->it_value.tv_usec;
}
__lastalrm = nowl();
} else {
__hastimer = false;
}
} }
return 0; return 0;
} }

View file

@ -20,6 +20,7 @@
#include "libc/calls/struct/itimerval.internal.h" #include "libc/calls/struct/itimerval.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/time/time.h" #include "libc/time/time.h"
@ -66,7 +67,6 @@
int setitimer(int which, const struct itimerval *newvalue, int setitimer(int which, const struct itimerval *newvalue,
struct itimerval *oldvalue) { struct itimerval *oldvalue) {
int rc; int rc;
if (IsAsan() && if (IsAsan() &&
((newvalue && !__asan_is_valid(newvalue, sizeof(*newvalue))) || ((newvalue && !__asan_is_valid(newvalue, sizeof(*newvalue))) ||
(oldvalue && !__asan_is_valid(oldvalue, sizeof(*oldvalue))))) { (oldvalue && !__asan_is_valid(oldvalue, sizeof(*oldvalue))))) {
@ -80,28 +80,7 @@ int setitimer(int which, const struct itimerval *newvalue,
} else { } else {
rc = sys_setitimer_nt(which, newvalue, oldvalue); rc = sys_setitimer_nt(which, newvalue, oldvalue);
} }
STRACE("setitimer(%s, %s, [%s]) → %d% m", DescribeItimer(which),
#ifdef SYSDEBUG DescribeItimerval(0, newvalue), DescribeItimerval(rc, oldvalue), rc);
if (newvalue && oldvalue) {
STRACE("setitimer(%d, "
"{{%'ld, %'ld}, {%'ld, %'ld}}, "
"[{{%'ld, %'ld}, {%'ld, %'ld}}]) → %d% m",
which, newvalue->it_interval.tv_sec, newvalue->it_interval.tv_usec,
newvalue->it_value.tv_sec, newvalue->it_value.tv_usec,
oldvalue->it_interval.tv_sec, oldvalue->it_interval.tv_usec,
oldvalue->it_value.tv_sec, oldvalue->it_value.tv_usec, rc);
} else if (newvalue) {
STRACE("setitimer(%d, {{%'ld, %'ld}, {%'ld, %'ld}}, NULL) → %d% m", which,
newvalue->it_interval.tv_sec, newvalue->it_interval.tv_usec,
newvalue->it_value.tv_sec, newvalue->it_value.tv_usec, rc);
} else if (oldvalue) {
STRACE("setitimer(%d, NULL, [{{%'ld, %'ld}, {%'ld, %'ld}}]) → %d% m", which,
oldvalue->it_interval.tv_sec, oldvalue->it_interval.tv_usec,
oldvalue->it_value.tv_sec, oldvalue->it_value.tv_usec, rc);
} else {
STRACE("setitimer(%d, NULL, NULL) → %d% m", which, rc);
}
#endif
return rc; return rc;
} }

View file

@ -9,8 +9,8 @@ int sys_getitimer(int, struct itimerval *) _Hide;
int sys_setitimer(int, const struct itimerval *, struct itimerval *) _Hide; int sys_setitimer(int, const struct itimerval *, struct itimerval *) _Hide;
int sys_setitimer_nt(int, const struct itimerval *, struct itimerval *) _Hide; int sys_setitimer_nt(int, const struct itimerval *, struct itimerval *) _Hide;
const char *DescribeTimeval(char[45], int, const struct timeval *); const char *DescribeItimerval(char[90], int, const struct itimerval *);
#define DescribeTimeval(rc, ts) DescribeTimeval(alloca(45), rc, ts) #define DescribeItimerval(rc, ts) DescribeItimerval(alloca(90), rc, ts)
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -14,14 +14,14 @@ int clock_nanosleep(int, int, const struct timespec *, struct timespec *);
int futimens(int, const struct timespec[2]); int futimens(int, const struct timespec[2]);
int nanosleep(const struct timespec *, struct timespec *); int nanosleep(const struct timespec *, struct timespec *);
int utimensat(int, const char *, const struct timespec[2], int); int utimensat(int, const char *, const struct timespec[2], int);
int timespec_getres(struct timespec *, int);
int timespec_get(struct timespec *, int);
#ifdef COSMO #ifdef COSMO
/* cosmopolitan libc's non-posix timespec library /* cosmopolitan libc's non-posix timespec library
removed by default due to emacs codebase clash */ removed by default due to emacs codebase clash */
#define timespec_zero ((struct timespec){0}) #define timespec_zero ((struct timespec){0})
#define timespec_max ((struct timespec){0x7fffffffffffffff, 999999999}) #define timespec_max ((struct timespec){0x7fffffffffffffff, 999999999})
int timespec_get(struct timespec *, int);
int timespec_getres(struct timespec *, int);
int timespec_cmp(struct timespec, struct timespec) pureconst; int timespec_cmp(struct timespec, struct timespec) pureconst;
int64_t timespec_tomicros(struct timespec) pureconst; int64_t timespec_tomicros(struct timespec) pureconst;
int64_t timespec_tomillis(struct timespec) pureconst; int64_t timespec_tomillis(struct timespec) pureconst;
@ -35,7 +35,14 @@ struct timespec timespec_mono(void);
struct timespec timespec_sleep(struct timespec); struct timespec timespec_sleep(struct timespec);
int timespec_sleep_until(struct timespec); int timespec_sleep_until(struct timespec);
struct timespec timespec_sub(struct timespec, struct timespec) pureconst; struct timespec timespec_sub(struct timespec, struct timespec) pureconst;
struct timespec timespec_subz(struct timespec, struct timespec) pureconst;
int sys_futex(int *, int, int, const struct timespec *, int *); int sys_futex(int *, int, int, const struct timespec *, int *);
static inline bool timespec_iszero(struct timespec __ts) {
return !(__ts.tv_sec | __ts.tv_nsec);
}
static inline bool timespec_isvalid(struct timespec __ts) {
return __ts.tv_sec >= 0 && __ts.tv_nsec < 1000000000ull;
}
#endif /* COSMO */ #endif /* COSMO */
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_

View file

@ -19,13 +19,23 @@ int utimes(const char *, const struct timeval[2]);
#ifdef COSMO #ifdef COSMO
/* cosmopolitan libc's non-posix timevals library /* cosmopolitan libc's non-posix timevals library
removed by default due to emacs codebase clash */ removed by default due to emacs codebase clash */
#define timeval_zero ((struct timeval){0})
#define timeval_max ((struct timeval){0x7fffffffffffffff, 999999})
int timeval_cmp(struct timeval, struct timeval) pureconst; int timeval_cmp(struct timeval, struct timeval) pureconst;
struct timeval timeval_real(void);
struct timeval timeval_frommicros(int64_t) pureconst; struct timeval timeval_frommicros(int64_t) pureconst;
struct timeval timeval_frommillis(int64_t) pureconst; struct timeval timeval_frommillis(int64_t) pureconst;
struct timeval timeval_add(struct timeval, struct timeval) pureconst; struct timeval timeval_add(struct timeval, struct timeval) pureconst;
struct timeval timeval_sub(struct timeval, struct timeval) pureconst; struct timeval timeval_sub(struct timeval, struct timeval) pureconst;
struct timeval timeval_subz(struct timeval, struct timeval) pureconst;
struct timeval timespec_totimeval(struct timespec) pureconst; struct timeval timespec_totimeval(struct timespec) pureconst;
struct timespec timeval_totimespec(struct timeval) pureconst; struct timespec timeval_totimespec(struct timeval) pureconst;
static inline bool timeval_iszero(struct timeval __tv) {
return !(__tv.tv_sec | __tv.tv_usec);
}
static inline bool timeval_isvalid(struct timeval __tv) {
return __tv.tv_sec >= 0 && __tv.tv_usec < 1000000ull;
}
#endif /* COSMO */ #endif /* COSMO */
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_

View file

@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_ #ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_ #define COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#include "libc/mem/alloca.h"
#include "libc/time/struct/timezone.h" #include "libc/time/struct/timezone.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
@ -15,6 +16,9 @@ axdx_t sys_gettimeofday_nt(struct timeval *, struct timezone *, void *) _Hide;
int sys_utimes_nt(const char *, const struct timeval[2]) _Hide; int sys_utimes_nt(const char *, const struct timeval[2]) _Hide;
axdx_t sys_gettimeofday_metal(struct timeval *, struct timezone *, void *); axdx_t sys_gettimeofday_metal(struct timeval *, struct timezone *, void *);
const char *DescribeTimeval(char[45], int, const struct timeval *);
#define DescribeTimeval(rc, ts) DescribeTimeval(alloca(45), rc, ts)
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_ */ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_ */

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,30 +16,17 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/runtime/pc.internal.h" #include "libc/calls/struct/timespec.h"
#include "libc/macros.internal.h"
// fmod [sic] does (𝑥 rem 𝑦) w/ round()-style rounding. /**
// * Subtracts two nanosecond timestamps.
// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes *
// @param 𝑦 is the power, also pushed on stack, in reverse order * Unlike `timespec_sub()` this function will return zero if `x < y`.
// @return remainder ∈ (-|𝑦|,|𝑦|) in %st */
// @define 𝑥-truncl(𝑥/𝑦)*𝑦 struct timespec timespec_subz(struct timespec x, struct timespec y) {
// @see emod() if (timespec_cmp(x, y) > 0) {
.ftrace1 return timespec_sub(x, y);
fmodl: .ftrace2 } else {
push %rbp return timespec_zero;
mov %rsp,%rbp }
fldt 32(%rbp) }
fldt 16(%rbp)
1: fprem
fnstsw
test $FPU_C2>>8,%ah
jnz 1b
fstp %st(1)
pop %rbp
ret
1: int3
pop %rbp
ret
.endfn fmodl,globl

31
libc/calls/timeval_real.c Normal file
View file

@ -0,0 +1,31 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/struct/timeval.h"
/**
* Returns current time w/ microsecond precision.
*
* @see timespec_real()
*/
struct timeval timeval_real(void) {
struct timeval tv;
_npassert(!gettimeofday(&tv, 0));
return tv;
}

30
libc/calls/timeval_subz.c Normal file
View file

@ -0,0 +1,30 @@
/*-*- 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/struct/timeval.h"
/**
* Subtracts two nanosecond timestamps.
*/
struct timeval timeval_subz(struct timeval x, struct timeval y) {
if (timeval_cmp(x, y) > 0) {
return timeval_sub(x, y);
} else {
return timeval_zero;
}
}

View file

@ -16,10 +16,10 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/struct/itimerval.internal.h"
#include "libc/calls/struct/timespec.h" #include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h" #include "libc/calls/struct/timespec.internal.h"
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/timeval.internal.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"

View file

@ -21,6 +21,7 @@
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/intrin/atomic.h" #include "libc/intrin/atomic.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/cmpxchg.h" #include "libc/intrin/cmpxchg.h"
#include "libc/intrin/directmap.internal.h" #include "libc/intrin/directmap.internal.h"
#include "libc/intrin/kmalloc.h" #include "libc/intrin/kmalloc.h"
@ -437,10 +438,7 @@ static struct AsanFault __asan_checka(const signed char *s, long ndiv8) {
if (UNLIKELY(!((intptr_t)s & (FRAMESIZE - 1))) && kisdangerous(s)) { if (UNLIKELY(!((intptr_t)s & (FRAMESIZE - 1))) && kisdangerous(s)) {
return (struct AsanFault){kAsanUnmapped, s}; return (struct AsanFault){kAsanUnmapped, s};
} }
if ((w = ((uint64_t)(255 & s[0]) << 000 | (uint64_t)(255 & s[1]) << 010 | if ((w = READ64LE(s))) {
(uint64_t)(255 & s[2]) << 020 | (uint64_t)(255 & s[3]) << 030 |
(uint64_t)(255 & s[4]) << 040 | (uint64_t)(255 & s[5]) << 050 |
(uint64_t)(255 & s[6]) << 060 | (uint64_t)(255 & s[7]) << 070))) {
s += __asan_bsf(w) >> 3; s += __asan_bsf(w) >> 3;
return __asan_fault(s, kAsanHeapOverrun); return __asan_fault(s, kAsanHeapOverrun);
} }

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/arch.h"
const char *(DescribeArchPrctlCode)(char buf[12], int x) { const char *(DescribeArchPrctlCode)(char buf[12], int x) {
if (x == ARCH_SET_FS) return "ARCH_SET_FS"; if (x == ARCH_SET_FS) return "ARCH_SET_FS";

View file

@ -24,6 +24,7 @@ const char *DescribeFrame(char[32], int);
const char *DescribeFutexOp(char[64], int); const char *DescribeFutexOp(char[64], int);
const char *DescribeHow(char[12], int); const char *DescribeHow(char[12], int);
const char *DescribeInOutInt64(char[23], ssize_t, int64_t *); const char *DescribeInOutInt64(char[23], ssize_t, int64_t *);
const char *DescribeItimer(char[12], int);
const char *DescribeMapFlags(char[64], int); const char *DescribeMapFlags(char[64], int);
const char *DescribeMapping(char[8], int, int); const char *DescribeMapping(char[8], int, int);
const char *DescribeNtConsoleInFlags(char[256], uint32_t); const char *DescribeNtConsoleInFlags(char[256], uint32_t);
@ -77,6 +78,7 @@ const char *DescribeWhichPrio(char[12], int);
#define DescribeFutexOp(x) DescribeFutexOp(alloca(64), x) #define DescribeFutexOp(x) DescribeFutexOp(alloca(64), x)
#define DescribeHow(x) DescribeHow(alloca(12), x) #define DescribeHow(x) DescribeHow(alloca(12), x)
#define DescribeInOutInt64(rc, x) DescribeInOutInt64(alloca(23), rc, x) #define DescribeInOutInt64(rc, x) DescribeInOutInt64(alloca(23), rc, x)
#define DescribeItimer(x) DescribeItimer(alloca(12), x)
#define DescribeMapFlags(x) DescribeMapFlags(alloca(64), x) #define DescribeMapFlags(x) DescribeMapFlags(alloca(64), x)
#define DescribeMapping(x, y) DescribeMapping(alloca(8), x, y) #define DescribeMapping(x, y) DescribeMapping(alloca(8), x, y)
#define DescribeNtConsoleInFlags(x) DescribeNtConsoleInFlags(alloca(256), x) #define DescribeNtConsoleInFlags(x) DescribeNtConsoleInFlags(alloca(256), x)

View file

@ -0,0 +1,29 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/itimer.h"
const char *(DescribeItimer)(char buf[12], int which) {
if (which == ITIMER_REAL) return "ITIMER_REAL";
if (which == ITIMER_VIRTUAL) return "ITIMER_VIRTUAL";
if (which == ITIMER_PROF) return "ITIMER_PROF";
FormatInt32(buf, which);
return buf;
}

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ /*-*- 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 vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,67 +16,26 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/fmt/conv.h" #include "libc/calls/struct/itimerval.internal.h"
#include "libc/limits.h" #include "libc/calls/struct/timeval.h"
#include "libc/macros.internal.h" #include "libc/calls/struct/timeval.internal.h"
#include "libc/mem/gc.h" #include "libc/dce.h"
#include "libc/stdio/stdio.h" #include "libc/intrin/asan.internal.h"
#include "libc/str/str.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/x/x.h" #include "libc/intrin/kprintf.h"
#include "libc/x/xasprintf.h"
float b32; #define N 90
double b64;
long double b80;
uint32_t u32;
uint64_t u64;
int128_t x;
void int2float(const char *s) { const char *(DescribeItimerval)(char buf[N], int rc,
x = strtoi128(s, NULL, 0); const struct itimerval *it) {
if ((0 <= x && x <= UINT32_MAX) && !_startswith(s, "-") && if (!it) return "NULL";
(!_endswith(s, "l") && !_endswith(s, "L"))) { if (rc == -1) return "n/a";
u32 = x; if ((!IsAsan() && kisdangerous(it)) ||
memcpy(&b32, &u32, 4); (IsAsan() && !__asan_is_valid(it, sizeof(*it)))) {
s = _gc(xdtoa(b32)); ksnprintf(buf, N, "%p", it);
if (!strchr(s, '.')) s = _gc(xasprintf("%s.", s));
s = _gc(xasprintf("%sf", s));
puts(s);
} else if ((0 <= x && x <= UINT64_MAX) && !_startswith(s, "-")) {
u64 = x;
memcpy(&b64, &u64, 8);
s = _gc(xdtoa(b64));
if (!strchr(s, '.')) s = _gc(xasprintf("%s.", s));
puts(s);
} else if ((INT32_MIN <= x && x <= 0) &&
(!_endswith(s, "l") && !_endswith(s, "L"))) {
u32 = ABS(x);
memcpy(&b32, &u32, 4);
b32 = -b32;
s = _gc(xdtoa(b32));
if (!strchr(s, '.')) s = _gc(xasprintf("%s.", s));
s = _gc(xasprintf("%sf", s));
puts(s);
} else if (INT64_MIN <= x && x <= 0) {
u64 = ABS(x);
memcpy(&b64, &u64, 8);
b64 = -b64;
s = _gc(xdtoa(b64));
if (!strchr(s, '.')) s = _gc(xasprintf("%s.", s));
puts(s);
} else { } else {
memcpy(&b80, &x, 16); ksnprintf(buf, N, "{%s, %s}", DescribeTimeval(0, &it->it_interval),
s = _gc(xdtoa(b80)); DescribeTimeval(0, &it->it_value));
if (!strchr(s, '.')) s = _gc(xasprintf("%s.", s));
s = _gc(xasprintf("%sL", s));
puts(s);
} }
} return buf;
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; ++i) {
int2float(argv[i]);
}
return 0;
} }

View file

@ -31,7 +31,6 @@ const char *(DescribeMapFlags)(char buf[64], int x) {
{MAP_FIXED, "FIXED"}, // {MAP_FIXED, "FIXED"}, //
{MAP_FIXED_NOREPLACE, "FIXED_NOREPLACE"}, // {MAP_FIXED_NOREPLACE, "FIXED_NOREPLACE"}, //
{MAP_CONCEAL, "CONCEAL"}, // {MAP_CONCEAL, "CONCEAL"}, //
{MAP_HUGETLB, "HUGETLB"}, //
{MAP_LOCKED, "LOCKED"}, // {MAP_LOCKED, "LOCKED"}, //
{MAP_NORESERVE, "NORESERVE"}, // {MAP_NORESERVE, "NORESERVE"}, //
{MAP_NONBLOCK, "NONBLOCK"}, // {MAP_NONBLOCK, "NONBLOCK"}, //

View file

@ -21,6 +21,8 @@
#include "libc/fmt/magnumstrs.internal.h" #include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sol.h" #include "libc/sysv/consts/sol.h"
#define N (PAGESIZE / 2 / sizeof(struct DescribeFlags)) #define N (PAGESIZE / 2 / sizeof(struct DescribeFlags))
@ -29,17 +31,42 @@
* Describes clock_gettime() clock argument. * Describes clock_gettime() clock argument.
*/ */
const char *(DescribeOpenFlags)(char buf[128], int x) { const char *(DescribeOpenFlags)(char buf[128], int x) {
char *s; char *p;
int i, n; int i, n;
const char *pipe;
struct DescribeFlags d[N]; struct DescribeFlags d[N];
if (x == -1) return "-1"; if (x == -1) return "-1";
// TODO(jart): unify DescribeFlags and MagnumStr data structures p = buf;
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR; ++n) { switch (x & O_ACCMODE) {
if (n == N) notpossible; case O_RDONLY:
p = stpcpy(p, "O_RDONLY");
x &= ~O_ACCMODE;
pipe = "|";
break;
case O_WRONLY:
p = stpcpy(p, "O_WRONLY");
x &= ~O_ACCMODE;
pipe = "|";
break;
case O_RDWR:
p = stpcpy(p, "O_RDWR");
x &= ~O_ACCMODE;
pipe = "|";
break;
default:
pipe = "";
break;
} }
for (i = 0; i < n; ++i) { if (x) {
d[i].flag = MAGNUM_NUMBER(kOpenFlags, i); p = stpcpy(p, pipe);
d[i].name = MAGNUM_STRING(kOpenFlags, i); for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR; ++n) {
if (n == N) notpossible;
}
for (i = 0; i < n; ++i) {
d[i].flag = MAGNUM_NUMBER(kOpenFlags, i);
d[i].name = MAGNUM_STRING(kOpenFlags, i);
}
DescribeFlags(p, 128 - (p - buf), d, n, "O_", x);
} }
return DescribeFlags(buf, 128, d, n, "O_", x); return buf;
} }

View file

@ -23,8 +23,8 @@
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
const char *(DescribeTimeval)(char buf[45], int rc, const struct timeval *tv) { const char *(DescribeTimeval)(char buf[45], int rc, const struct timeval *tv) {
if (rc == -1) return "n/a";
if (!tv) return "NULL"; if (!tv) return "NULL";
if (rc == -1) return "n/a";
if ((!IsAsan() && kisdangerous(tv)) || if ((!IsAsan() && kisdangerous(tv)) ||
(IsAsan() && !__asan_is_valid(tv, sizeof(*tv)))) { (IsAsan() && !__asan_is_valid(tv, sizeof(*tv)))) {
ksnprintf(buf, 45, "%p", tv); ksnprintf(buf, 45, "%p", tv);

View file

@ -46,11 +46,14 @@ feclearexcept:
// maintain exceptions in the sse mxcsr, clear x87 exceptions // maintain exceptions in the sse mxcsr, clear x87 exceptions
mov %edi,%ecx mov %edi,%ecx
and $0x3f,%ecx and $0x3f,%ecx
#ifndef NOX87
fnstsw %ax fnstsw %ax
test %eax,%ecx test %eax,%ecx
jz 1f jz 1f
fnclex fnclex
1: stmxcsr -8(%rsp) 1:
#endif
stmxcsr -8(%rsp)
and $0x3f,%eax and $0x3f,%eax
or %eax,-8(%rsp) or %eax,-8(%rsp)
test %ecx,-8(%rsp) test %ecx,-8(%rsp)
@ -96,12 +99,16 @@ fetestexcept:
.ftrace2 .ftrace2
#ifdef __x86_64__ #ifdef __x86_64__
and $0x3f,%edi and $0x3f,%edi
push %rax push $0
stmxcsr (%rsp) stmxcsr (%rsp)
#ifdef NOX87
pop %rax
#else
pop %rsi pop %rsi
fnstsw %ax fnstsw %ax
or %esi,%eax or %esi,%eax
and %edi,%eax and %edi,%eax
#endif
ret ret
#elif defined(__aarch64__) #elif defined(__aarch64__)
and w0,w0,#0x1f and w0,w0,#0x1f
@ -138,10 +145,12 @@ __fesetround:
push %rax push %rax
xor %eax,%eax xor %eax,%eax
mov %edi,%ecx mov %edi,%ecx
#ifndef NOX87
fnstcw (%rsp) fnstcw (%rsp)
andb $0xf3,1(%rsp) andb $0xf3,1(%rsp)
or %ch,1(%rsp) or %ch,1(%rsp)
fldcw (%rsp) fldcw (%rsp)
#endif
stmxcsr (%rsp) stmxcsr (%rsp)
shl $3,%ch shl $3,%ch
andb $0x9f,1(%rsp) andb $0x9f,1(%rsp)
@ -181,7 +190,9 @@ fegetenv:
.ftrace2 .ftrace2
#ifdef __x86_64__ #ifdef __x86_64__
xor %eax,%eax xor %eax,%eax
#ifndef NOX87
fnstenv (%rdi) fnstenv (%rdi)
#endif
stmxcsr 28(%rdi) stmxcsr 28(%rdi)
ret ret
#elif defined(__aarch64__) #elif defined(__aarch64__)
@ -200,14 +211,18 @@ fesetenv:
xor %eax,%eax xor %eax,%eax
inc %rdi inc %rdi
jz 1f jz 1f
#ifndef NOX87
fldenv -1(%rdi) fldenv -1(%rdi)
#endif
ldmxcsr 27(%rdi) ldmxcsr 27(%rdi)
ret ret
1: push %rax 1: push %rax
push %rax push %rax
pushq $0xffff pushq $0xffff
pushq $0x37f pushq $0x37f
#ifndef NOX87
fldenv (%rsp) fldenv (%rsp)
#endif
pushq $0x1f80 pushq $0x1f80
ldmxcsr (%rsp) ldmxcsr (%rsp)
add $40,%rsp add $40,%rsp

View file

@ -35,5 +35,5 @@ double fmax(double x, double y) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(fmax, fmaxl); __weak_reference(fmax, fmaxl);
#endif #endif

View file

@ -69,6 +69,6 @@ double scalbn(double x, int n)
__strong_reference(scalbn, ldexp); __strong_reference(scalbn, ldexp);
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(scalbn, ldexpl); __weak_reference(scalbn, ldexpl);
__strong_reference(scalbn, scalbnl); __weak_reference(scalbn, scalbnl);
#endif #endif

View file

@ -1,10 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_MEM_IO_H_
#define COSMOPOLITAN_LIBC_MEM_IO_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
ssize_t _copyfd(int, int, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_MEM_IO_H_ */

View file

@ -45,6 +45,7 @@ cosmo: push %rbp
mov %eax,%r12d mov %eax,%r12d
#endif /* SYSDEBUG */ #endif /* SYSDEBUG */
#ifndef NOX87
// Windows always initializes FPU to douuble precision. // Windows always initializes FPU to douuble precision.
// WSL breaks Linux ABI by initializing FPU to double precision. // WSL breaks Linux ABI by initializing FPU to double precision.
// This code makes long double long again. // This code makes long double long again.
@ -70,6 +71,7 @@ cosmo: push %rbp
// drr // drr
1: .short 0b00000000000000000001101111111 1: .short 0b00000000000000000001101111111
.previous .previous
#endif
#ifdef __FAST_MATH__ #ifdef __FAST_MATH__
push %rax push %rax

View file

@ -20,24 +20,9 @@ typedef unsigned long jmp_buf[26];
typedef long sigjmp_buf[12]; typedef long sigjmp_buf[12];
extern char **environ; /* CRT */ extern char **environ;
extern int __argc; /* CRT */ extern char *program_invocation_name;
extern char **__argv; /* CRT */ extern char *program_invocation_short_name;
extern char **__envp; /* CRT */
extern unsigned long *__auxv; /* CRT */
extern intptr_t __oldstack; /* CRT */
extern uint64_t __nosync; /* SYS */
extern int __strace; /* SYS */
extern int __ftrace; /* SYS */
extern char *program_invocation_name; /* RII */
extern char *program_invocation_short_name; /* RII */
extern uint64_t __syscount; /* RII */
extern uint64_t kStartTsc; /* RII */
extern char kTmpPath[]; /* RII */
extern const char kNtSystemDirectory[]; /* RII */
extern const char kNtWindowsDirectory[]; /* RII */
extern size_t __virtualmax;
extern bool __isworker;
void mcount(void); void mcount(void);
int daemon(int, int); int daemon(int, int);
@ -83,6 +68,21 @@ int sethostname(const char *, size_t);
int acct(const char *); int acct(const char *);
#ifdef COSMO #ifdef COSMO
extern int __argc;
extern char **__argv;
extern char **__envp;
extern unsigned long *__auxv;
extern intptr_t __oldstack;
extern uint64_t __nosync;
extern int __strace;
extern int __ftrace;
extern uint64_t __syscount;
extern uint64_t kStartTsc;
extern char kTmpPath[];
extern const char kNtSystemDirectory[];
extern const char kNtWindowsDirectory[];
extern size_t __virtualmax;
extern bool __isworker;
/* utilities */ /* utilities */
void _intsort(int *, size_t); void _intsort(int *, size_t);
void _longsort(long *, size_t); void _longsort(long *, size_t);

View file

@ -23,6 +23,7 @@
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/nexgen32e/msr.internal.h" #include "libc/nexgen32e/msr.internal.h"
#include "libc/nt/thread.h" #include "libc/nt/thread.h"
#include "libc/sysv/consts/arch.h"
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
#include "libc/thread/tls2.h" #include "libc/thread/tls2.h"
@ -60,8 +61,10 @@ textstartup void __set_tls(struct CosmoTib *tib) {
: "c"(MSR_IA32_FS_BASE), "a"((uint32_t)val), : "c"(MSR_IA32_FS_BASE), "a"((uint32_t)val),
"d"((uint32_t)(val >> 32))); "d"((uint32_t)(val >> 32)));
} }
#else #elif defined(__aarch64__)
register long x28 asm("x28") = (long)tib; register long x28 asm("x28") = (long)tib;
asm volatile("" : "+r"(x28)); asm volatile("" : "+r"(x28));
#else
#error "unsupported architecture"
#endif #endif
} }

View file

@ -231,14 +231,11 @@ syscon mmap MAP_LOCKED 0x00002000 0x00002000 0 0 0 0 0 0
syscon mmap MAP_NORESERVE 0x00004000 0x00004000 0x00000040 0x00000040 0 0 0x00000040 0 # Linux calls it "reserve"; NT calls it "commit"? which is default? syscon mmap MAP_NORESERVE 0x00004000 0x00004000 0x00000040 0x00000040 0 0 0x00000040 0 # Linux calls it "reserve"; NT calls it "commit"? which is default?
syscon mmap MAP_POPULATE 0x00008000 0x00008000 0 0 0x00040000 0 0 0 # MAP_PREFAULT_READ on FreeBSD; can avoid madvise(MADV_WILLNEED) on private file mapping syscon mmap MAP_POPULATE 0x00008000 0x00008000 0 0 0x00040000 0 0 0 # MAP_PREFAULT_READ on FreeBSD; can avoid madvise(MADV_WILLNEED) on private file mapping
syscon mmap MAP_NONBLOCK 0x00010000 0x00010000 0 0 0 0 0 0 syscon mmap MAP_NONBLOCK 0x00010000 0x00010000 0 0 0 0 0 0
syscon mmap MAP_HUGETLB 0x00040000 0x00040000 0 0 0 0 0 0x80000000 # kNtSecLargePages
syscon mmap MAP_SYNC 0x00080000 0x00080000 0 0 0 0 0 0 # perform synchronous page faults for mapping (Linux 4.15+) syscon mmap MAP_SYNC 0x00080000 0x00080000 0 0 0 0 0 0 # perform synchronous page faults for mapping (Linux 4.15+)
syscon mmap MAP_INHERIT -1 -1 -1 -1 -1 -1 0x00000080 -1 # make it inherit across execve() syscon mmap MAP_INHERIT -1 -1 -1 -1 -1 -1 0x00000080 -1 # make it inherit across execve()
syscon mmap MAP_HASSEMAPHORE 0 0 0x00000200 0x00000200 0x00000200 0 0x00000200 0 # does it matter on x86? syscon mmap MAP_HASSEMAPHORE 0 0 0x00000200 0x00000200 0x00000200 0 0x00000200 0 # does it matter on x86?
syscon mmap MAP_NOSYNC 0 0 0 0 0x00000800 0 0 0 # flush to physical media only when necessary rather than gratuitously; be sure to use write() rather than ftruncate() with this! syscon mmap MAP_NOSYNC 0 0 0 0 0x00000800 0 0 0 # flush to physical media only when necessary rather than gratuitously; be sure to use write() rather than ftruncate() with this!
syscon mmap MAP_CONCEAL 0 0 0 0 0x00020000 0x00008000 0x00008000 0 # omit from core dumps; MAP_NOCORE on FreeBSD syscon mmap MAP_CONCEAL 0 0 0 0 0x00020000 0x00008000 0x00008000 0 # omit from core dumps; MAP_NOCORE on FreeBSD
syscon mmap MAP_HUGE_MASK 63 63 0 0 0 0 0 0
syscon mmap MAP_HUGE_SHIFT 26 26 0 0 0 0 0 0
syscon compat MAP_NOCORE 0 0 0 0 0x00020000 0x00008000 0x00008000 0 # use MAP_CONCEAL syscon compat MAP_NOCORE 0 0 0 0 0x00020000 0x00008000 0x00008000 0 # use MAP_CONCEAL
syscon compat MAP_ANON 0x00000020 0x00000020 0x00001000 0x00001000 0x00001000 0x00001000 0x00001000 0x00000020 # bsd consensus; faked nt syscon compat MAP_ANON 0x00000020 0x00000020 0x00001000 0x00001000 0x00001000 0x00001000 0x00001000 0x00000020 # bsd consensus; faked nt
syscon compat MAP_EXECUTABLE 0x00001000 0x00001000 0 0 0 0 0 0 # ignored syscon compat MAP_EXECUTABLE 0x00001000 0x00001000 0 0 0 0 0 0 # ignored

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon mmap,MAP_HUGETLB,0x00040000,0x00040000,0,0,0,0,0,0x80000000

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon mmap,MAP_HUGE_MASK,63,63,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon mmap,MAP_HUGE_SHIFT,26,26,0,0,0,0,0,0

9
libc/sysv/consts/arch.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_ARCH_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_ARCH_H_
#define ARCH_SET_GS 0x1001
#define ARCH_SET_FS 0x1002
#define ARCH_GET_FS 0x1003
#define ARCH_GET_GS 0x1004
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_ARCH_H_ */

View file

@ -13,9 +13,6 @@ extern const int MAP_FILE;
extern const int MAP_FIXED; extern const int MAP_FIXED;
extern const int MAP_FIXED_NOREPLACE; extern const int MAP_FIXED_NOREPLACE;
extern const int MAP_HASSEMAPHORE; extern const int MAP_HASSEMAPHORE;
extern const int MAP_HUGETLB;
extern const int MAP_HUGE_MASK;
extern const int MAP_HUGE_SHIFT;
extern const int MAP_INHERIT; extern const int MAP_INHERIT;
extern const int MAP_LOCKED; extern const int MAP_LOCKED;
extern const int MAP_NONBLOCK; extern const int MAP_NONBLOCK;

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/mem/copyfd.internal.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
@ -34,7 +33,7 @@ void testlib_extract(const char *zip, const char *to, int mode) {
int fdin, fdout; int fdin, fdout;
ASSERT_NE(-1, (fdin = open(zip, O_RDONLY))); ASSERT_NE(-1, (fdin = open(zip, O_RDONLY)));
ASSERT_NE(-1, (fdout = creat(to, mode))); ASSERT_NE(-1, (fdout = creat(to, mode)));
ASSERT_NE(-1, _copyfd(fdin, fdout, -1)); ASSERT_NE(-1, copyfd(fdin, fdout, -1));
ASSERT_NE(-1, close(fdout)); ASSERT_NE(-1, close(fdout));
ASSERT_NE(-1, close(fdin)); ASSERT_NE(-1, close(fdin));
} }

View file

@ -143,5 +143,5 @@ double acos(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(acos, acosl); __weak_reference(acos, acosl);
#endif #endif

View file

@ -55,5 +55,5 @@ double acosh(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(acosh, acoshl); __weak_reference(acosh, acoshl);
#endif #endif

View file

@ -149,5 +149,5 @@ double asin(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(asin, asinl); __weak_reference(asin, asinl);
#endif #endif

View file

@ -66,5 +66,5 @@ double asinh(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(asinh, asinhl); __weak_reference(asinh, asinhl);
#endif #endif

View file

@ -156,5 +156,5 @@ double atan(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(atan, atanl); __weak_reference(atan, atanl);
#endif #endif

View file

@ -155,5 +155,5 @@ atan2(double y, double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(atan2, atan2l); __weak_reference(atan2, atan2l);
#endif #endif

View file

@ -66,5 +66,5 @@ double atanh(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(atanh, atanhl); __weak_reference(atanh, atanhl);
#endif #endif

View file

@ -27,5 +27,5 @@ double cabs(double complex z) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(cabs, cabsl); __weak_reference(cabs, cabsl);
#endif #endif

View file

@ -45,5 +45,5 @@ double complex cacosh(double complex z)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(cacosh, cacoshl); __weak_reference(cacosh, cacoshl);
#endif #endif

View file

@ -24,5 +24,5 @@ double carg(double complex z) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(carg, cargl); __weak_reference(carg, cargl);
#endif #endif

View file

@ -52,5 +52,5 @@ double complex casin(double complex z)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(casin, casinl); __weak_reference(casin, casinl);
#endif #endif

View file

@ -147,5 +147,5 @@ double complex catan(double complex z)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(catan, catanl); __weak_reference(catan, catanl);
#endif #endif

View file

@ -32,5 +32,5 @@ double copysign(double x, double y) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(copysign, copysignl); __weak_reference(copysign, copysignl);
#endif #endif

View file

@ -122,5 +122,5 @@ double cos(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(cos, cosl); __weak_reference(cos, cosl);
#endif #endif

View file

@ -76,3 +76,7 @@ double cosh(double x)
t = __expo2(x, 1.0); t = __expo2(x, 1.0);
return t; return t;
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__weak_reference(cosh, coshl);
#endif

View file

@ -38,6 +38,7 @@
*/ */
#include "libc/math.h" #include "libc/math.h"
#include "libc/tinymath/freebsd.internal.h" #include "libc/tinymath/freebsd.internal.h"
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
asm(".ident\t\"\\n\\n\ asm(".ident\t\"\\n\\n\
FreeBSD libm (BSD-2 License)\\n\ FreeBSD libm (BSD-2 License)\\n\
@ -155,3 +156,5 @@ coshl(long double x)
/* |x| > o_threshold, cosh(x) overflow */ /* |x| > o_threshold, cosh(x) overflow */
RETURNI(huge*huge); RETURNI(huge*huge);
} }
#endif /* long double is long */

View file

@ -170,5 +170,5 @@ double exp(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(exp, expl); __weak_reference(exp, expl);
#endif #endif

View file

@ -57,5 +57,6 @@ double exp10(double x)
__strong_reference(exp10, pow10); __strong_reference(exp10, pow10);
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(exp10, exp10l); __weak_reference(exp10, exp10l);
__weak_reference(exp10, pow10l);
#endif #endif

View file

@ -57,6 +57,6 @@ long double exp10l(long double x)
return powl(10.0, x); return powl(10.0, x);
} }
__strong_reference(exp10l, pow10l); __weak_reference(exp10l, pow10l);
#endif /* long double is long */ #endif /* long double is long */

View file

@ -157,5 +157,5 @@ double exp2(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(exp2, exp2l); __weak_reference(exp2, exp2l);
#endif #endif

View file

@ -238,5 +238,5 @@ double expm1(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(expm1, expm1l); __weak_reference(expm1, expm1l);
#endif #endif

View file

@ -31,5 +31,5 @@ double fabs(double x) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(fabs, fabsl); __weak_reference(fabs, fabsl);
#endif #endif

View file

@ -27,5 +27,5 @@ double fdim(double x, double y) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(fdim, fdiml); __weak_reference(fdim, fdiml);
#endif #endif

View file

@ -96,5 +96,5 @@ double floor(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(floor, floorl); __weak_reference(floor, floorl);
#endif #endif

View file

@ -35,5 +35,5 @@ double fmin(double x, double y) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(fmin, fminl); __weak_reference(fmin, fminl);
#endif #endif

View file

@ -103,3 +103,7 @@ double fmod(double x, double y)
ux.i = uxi; ux.i = uxi;
return ux.f; return ux.f;
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__weak_reference(fmod, fmodl);
#endif

View file

@ -27,6 +27,7 @@
*/ */
#include "libc/math.h" #include "libc/math.h"
#include "libc/tinymath/ldshape.internal.h" #include "libc/tinymath/ldshape.internal.h"
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
asm(".ident\t\"\\n\\n\ asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\ Musl libc (MIT License)\\n\
@ -34,10 +35,13 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\""); asm(".include \"libc/disclaimer.inc\"");
// clang-format off // clang-format off
/**
* Does (𝑥 rem 𝑦) w/ round()-style rounding.
* @return remainder (-|𝑦|,|𝑦|) in %xmm0
* @define 𝑥-trunc(𝑥/𝑦)*𝑦
*/
long double fmodl(long double x, long double y) { long double fmodl(long double x, long double y) {
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
return fmod(x, y);
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
union ldshape ux = {x}, uy = {y}; union ldshape ux = {x}, uy = {y};
int ex = ux.i.se & 0x7fff; int ex = ux.i.se & 0x7fff;
int ey = uy.i.se & 0x7fff; int ey = uy.i.se & 0x7fff;
@ -135,3 +139,5 @@ long double fmodl(long double x, long double y) {
#error "architecture unsupported" #error "architecture unsupported"
#endif #endif
} }
#endif /* long double is long */

View file

@ -58,5 +58,5 @@ double frexp(double x, int *e)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(frexp, frexpl); __weak_reference(frexp, frexpl);
#endif #endif

View file

@ -101,5 +101,5 @@ double hypot(double x, double y)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(hypot, hypotl); __weak_reference(hypot, hypotl);
#endif #endif

View file

@ -63,5 +63,5 @@ int ilogb(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(ilogb, ilogbl); __weak_reference(ilogb, ilogbl);
#endif #endif

View file

@ -1,88 +0,0 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/limits.h"
#include "libc/math.h"
#include "libc/tinymath/internal.h"
#include "libc/tinymath/ldshape.internal.h"
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
// clang-format off
/**
* Returns log𝑥 exponent part of double.
*/
int ilogbl(long double x)
{
#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
// #pragma STDC FENV_ACCESS ON
union ldshape u = {x};
uint64_t m = u.i.m;
int e = u.i.se & 0x7fff;
if (!e) {
if (m == 0) {
FORCE_EVAL(0/0.0f);
return FP_ILOGB0;
}
/* subnormal x */
for (e = -0x3fff+1; m>>63 == 0; e--, m<<=1);
return e;
}
if (e == 0x7fff) {
FORCE_EVAL(0/0.0f);
return m<<1 ? FP_ILOGBNAN : INT_MAX;
}
return e - 0x3fff;
#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
// #pragma STDC FENV_ACCESS ON
union ldshape u = {x};
int e = u.i.se & 0x7fff;
if (!e) {
if (x == 0) {
FORCE_EVAL(0/0.0f);
return FP_ILOGB0;
}
/* subnormal x */
x *= 0x1p120;
return ilogbl(x) - 120;
}
if (e == 0x7fff) {
FORCE_EVAL(0/0.0f);
u.i.se = 0;
return u.f ? FP_ILOGBNAN : INT_MAX;
}
return e - 0x3fff;
#endif
}
#endif /* long double is long */

View file

@ -27,6 +27,7 @@
*/ */
#include "libc/math.h" #include "libc/math.h"
#include "libc/tinymath/kernel.internal.h" #include "libc/tinymath/kernel.internal.h"
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
asm(".ident\t\"\\n\\n\ asm(".ident\t\"\\n\\n\
FreeBSD libm (BSD-2 License)\\n\ FreeBSD libm (BSD-2 License)\\n\
@ -183,3 +184,5 @@ long double __tanl(long double x, long double y, int odd) {
#else #else
#error "architecture unsupported" #error "architecture unsupported"
#endif #endif
#endif /* long double is long */

View file

@ -142,5 +142,5 @@ double log(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(log, logl); __weak_reference(log, logl);
#endif #endif

View file

@ -143,5 +143,5 @@ double log10(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(log10, log10l); __weak_reference(log10, log10l);
#endif #endif

View file

@ -161,5 +161,5 @@ double log1p(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(log1p, log1pl); __weak_reference(log1p, log1pl);
#endif #endif

View file

@ -159,5 +159,5 @@ double log2(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(log2, log2l); __weak_reference(log2, log2l);
#endif #endif

View file

@ -23,3 +23,7 @@ double logb(double x) {
if (!x) return -1 / (x * x); if (!x) return -1 / (x * x);
return ilogb(x); return ilogb(x);
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__weak_reference(logb, logbl);
#endif

View file

@ -45,8 +45,8 @@ __weak_reference(lrint, llrint);
#endif #endif
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(lrint, lrintl); __weak_reference(lrint, lrintl);
#if __SIZEOF_LONG__ == __SIZEOF_LONG_LONG__ #if __SIZEOF_LONG__ == __SIZEOF_LONG_LONG__
__strong_reference(lrint, llrintl); __weak_reference(lrint, llrintl);
#endif #endif
#endif #endif

View file

@ -26,5 +26,5 @@ long lround(double x) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(lround, lroundl); __weak_reference(lround, lroundl);
#endif #endif

View file

@ -33,6 +33,9 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\""); asm(".include \"libc/disclaimer.inc\"");
// clang-format off // clang-format off
/**
* Returns fractional part of 𝑥.
*/
double modf(double x, double *iptr) double modf(double x, double *iptr)
{ {
union {double f; uint64_t i;} u = {x}; union {double f; uint64_t i;} u = {x};
@ -65,3 +68,7 @@ double modf(double x, double *iptr)
*iptr = u.f; *iptr = u.f;
return x - u.f; return x - u.f;
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__weak_reference(modf, modfl);
#endif

View file

@ -26,6 +26,7 @@
*/ */
#include "libc/math.h" #include "libc/math.h"
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
asm(".ident\t\"\\n\\n\ asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\ Musl libc (MIT License)\\n\
@ -33,20 +34,11 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\""); asm(".include \"libc/disclaimer.inc\"");
// clang-format off // clang-format off
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
long double modfl(long double x, long double *iptr)
{
double d;
long double r;
r = modf(x, &d);
*iptr = d;
return r;
}
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
static const long double toint = 1/LDBL_EPSILON; static const long double toint = 1/LDBL_EPSILON;
/**
* Returns fractional part of 𝑥.
*/
long double modfl(long double x, long double *iptr) long double modfl(long double x, long double *iptr)
{ {
union { union {
@ -90,6 +82,4 @@ long double modfl(long double x, long double *iptr)
return -y; return -y;
} }
#else #endif /* long double is long */
#error "architecture unsupported"
#endif

View file

@ -42,5 +42,5 @@ double nearbyint(double x) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(nearbyint, nearbyintl); __weak_reference(nearbyint, nearbyintl);
#endif #endif

View file

@ -65,5 +65,5 @@ double nextafter(double x, double y)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(nextafter, nextafterl); __weak_reference(nextafter, nextafterl);
#endif #endif

View file

@ -381,5 +381,5 @@ double pow(double x, double y)
__weak_reference(pow, __pow_finite); __weak_reference(pow, __pow_finite);
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(pow, powl); __weak_reference(pow, powl);
#endif #endif

View file

@ -28,5 +28,5 @@ double remainder(double x, double y) {
__strong_reference(remainder, drem); __strong_reference(remainder, drem);
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(remainder, remainderl); __weak_reference(remainder, remainderl);
#endif #endif

View file

@ -225,3 +225,7 @@ medium:
y[1] = ty[1]; y[1] = ty[1];
return n; return n;
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__weak_reference(__rem_pio2, __rem_pio2l);
#endif

View file

@ -29,6 +29,7 @@
#include "libc/math.h" #include "libc/math.h"
#include "libc/tinymath/kernel.internal.h" #include "libc/tinymath/kernel.internal.h"
#include "libc/tinymath/ldshape.internal.h" #include "libc/tinymath/ldshape.internal.h"
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
asm(".ident\t\"\\n\\n\ asm(".ident\t\"\\n\\n\
FreeBSD libm (BSD-2 License)\\n\ FreeBSD libm (BSD-2 License)\\n\
@ -200,3 +201,5 @@ int __rem_pio2l(long double x, long double *y)
#else #else
#error "architecture unsupported" #error "architecture unsupported"
#endif #endif
#endif /* long double is long */

View file

@ -117,5 +117,5 @@ end:
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(remquo, remquol); __weak_reference(remquo, remquol);
#endif #endif

View file

@ -66,5 +66,5 @@ double rint(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(rint, rintl); __weak_reference(rint, rintl);
#endif #endif

View file

@ -92,5 +92,5 @@ double round(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(round, roundl); __weak_reference(round, roundl);
#endif #endif

View file

@ -26,5 +26,5 @@ double scalbln(double x, long n) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(scalbln, scalblnl); __weak_reference(scalbln, scalblnl);
#endif #endif

View file

@ -26,5 +26,5 @@ double significand(double x) {
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(significand, significandl); __weak_reference(significand, significandl);
#endif #endif

View file

@ -123,5 +123,5 @@ double sin(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(sin, sinl); __weak_reference(sin, sinl);
#endif #endif

View file

@ -114,5 +114,5 @@ void sincos(double x, double *sin, double *cos)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(sincos, sincosl); __weak_reference(sincos, sincosl);
#endif #endif

View file

@ -75,3 +75,7 @@ double sinh(double x)
t = __expo2(absx, 2*h); t = __expo2(absx, 2*h);
return t; return t;
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__weak_reference(sinh, sinhl);
#endif

View file

@ -39,6 +39,7 @@
#include "libc/intrin/likely.h" #include "libc/intrin/likely.h"
#include "libc/math.h" #include "libc/math.h"
#include "libc/tinymath/freebsd.internal.h" #include "libc/tinymath/freebsd.internal.h"
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
asm(".ident\t\"\\n\\n\ asm(".ident\t\"\\n\\n\
FreeBSD libm (BSD-2 License)\\n\ FreeBSD libm (BSD-2 License)\\n\
@ -154,3 +155,5 @@ sinhl(long double x)
/* |x| > o_threshold, sinh(x) overflow */ /* |x| > o_threshold, sinh(x) overflow */
return x*shuge; return x*shuge;
} }
#endif /* long double is long */

View file

@ -222,5 +222,5 @@ double sqrt(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(sqrt, sqrtl); __weak_reference(sqrt, sqrtl);
#endif #endif

View file

@ -115,5 +115,5 @@ double tan(double x)
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__strong_reference(tan, tanl); __weak_reference(tan, tanl);
#endif #endif

View file

@ -76,3 +76,7 @@ double tanh(double x)
} }
return sign ? -t : t; return sign ? -t : t;
} }
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
__weak_reference(tanh, tanhl);
#endif

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