mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
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:
parent
8dc11afcf6
commit
c3440d040c
132 changed files with 539 additions and 587 deletions
|
@ -364,6 +364,28 @@ TARGET_ARCH ?= \
|
|||
-msse3
|
||||
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
|
||||
ifeq ($(MODE), llvm)
|
||||
TARGET_ARCH ?= -msse3
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,14 +42,6 @@
|
|||
|
||||
#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 WEXITSTATUS(s) ((0xff00 & (s)) >> 8)
|
||||
#define WIFCONTINUED(s) ((s) == 0xffff)
|
||||
|
@ -69,11 +61,9 @@ COSMOPOLITAN_C_START_
|
|||
typedef int sig_atomic_t;
|
||||
|
||||
bool32 isatty(int) nosideeffect;
|
||||
char *commandv(const char *, char *, size_t);
|
||||
char *get_current_dir_name(void) dontdiscard;
|
||||
char *getcwd(char *, size_t);
|
||||
char *realpath(const char *, char *);
|
||||
char *replaceuser(const char *) dontdiscard;
|
||||
char *ttyname(int);
|
||||
int access(const char *, int) dontthrow;
|
||||
int chdir(const char *);
|
||||
|
@ -122,7 +112,6 @@ int getpriority(int, unsigned);
|
|||
int getresgid(unsigned *, unsigned *, unsigned *);
|
||||
int getresuid(unsigned *, unsigned *, unsigned *);
|
||||
int getsid(int) nosideeffect libcesque;
|
||||
int gettid(void) libcesque;
|
||||
int ioprio_get(int, int);
|
||||
int ioprio_set(int, int, int);
|
||||
int issetugid(void);
|
||||
|
@ -133,8 +122,6 @@ int lchown(const char *, unsigned, unsigned);
|
|||
int link(const char *, const char *) dontthrow;
|
||||
int linkat(int, const char *, int, const char *, 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 mkdir(const char *, unsigned);
|
||||
int mkdirat(int, const char *, unsigned);
|
||||
|
@ -146,14 +133,10 @@ int nice(int);
|
|||
int open(const char *, int, ...);
|
||||
int openat(int, const char *, int, ...);
|
||||
int pause(void);
|
||||
int personality(uint64_t);
|
||||
int pipe(int[hasatleast 2]);
|
||||
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_madvise(void *, uint64_t, int);
|
||||
int prctl(int, ...);
|
||||
int raise(int);
|
||||
int reboot(int);
|
||||
int remove(const char *);
|
||||
|
@ -161,7 +144,6 @@ int rename(const char *, const char *);
|
|||
int renameat(int, const char *, int, const char *);
|
||||
int rmdir(const char *);
|
||||
int sched_yield(void);
|
||||
int seccomp(unsigned, unsigned, void *);
|
||||
int setegid(unsigned);
|
||||
int seteuid(unsigned);
|
||||
int setfsgid(unsigned);
|
||||
|
@ -182,37 +164,21 @@ int siginterrupt(int, int);
|
|||
int symlink(const char *, const char *);
|
||||
int symlinkat(const char *, int, const char *);
|
||||
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 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 ttyname_r(int, char *, size_t);
|
||||
int unlink(const char *);
|
||||
int unlink_s(const char **);
|
||||
int unlinkat(int, const char *, int);
|
||||
int unveil(const char *, const char *);
|
||||
int usleep(unsigned);
|
||||
int vfork(void) returnstwice;
|
||||
int wait(int *);
|
||||
int waitpid(int, int *, int);
|
||||
long ptrace(int, ...);
|
||||
ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned);
|
||||
ssize_t lseek(int, int64_t, int);
|
||||
ssize_t pread(int, void *, size_t, int64_t);
|
||||
ssize_t pwrite(int, const void *, size_t, int64_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 readlinkat(int, const char *, char *, size_t);
|
||||
ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned);
|
||||
|
@ -225,20 +191,38 @@ unsigned umask(unsigned);
|
|||
void sync(void);
|
||||
|
||||
#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 isdirectory(const char *);
|
||||
bool isexecutable(const char *);
|
||||
bool isregularfile(const char *);
|
||||
bool issymlink(const char *);
|
||||
bool32 ischardev(int) nosideeffect;
|
||||
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, unsigned);
|
||||
bool32 ischardev(int);
|
||||
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
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -103,6 +103,7 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: private \
|
|||
COPTS += \
|
||||
-fno-sanitize=all
|
||||
|
||||
ifneq ($(ARCH), aarch64)
|
||||
# we always want -O3 because:
|
||||
# it makes the code size smaller too
|
||||
# we need -mstringop-strategy=loop because:
|
||||
|
@ -116,6 +117,7 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: private \
|
|||
COPTS += \
|
||||
-O3 \
|
||||
-mstringop-strategy=loop
|
||||
endif
|
||||
|
||||
# we must disable static stack safety because:
|
||||
# these functions use alloca(n)
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
* time. Among the more popular is CLOCK_MONOTONIC. This function has a
|
||||
* zero syscall implementation of that on modern x86.
|
||||
*
|
||||
* nowl l: 45𝑐 15𝑛𝑠
|
||||
* rdtsc l: 13𝑐 4𝑛𝑠
|
||||
* gettimeofday l: 44𝑐 14𝑛𝑠
|
||||
* clock_gettime l: 40𝑐 13𝑛𝑠
|
||||
|
|
|
@ -17,59 +17,34 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
||||
#define CHUNK 32768
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
int e;
|
||||
char *buf;
|
||||
ssize_t rc;
|
||||
size_t i, j, got, sent;
|
||||
rc = 0;
|
||||
if (n) {
|
||||
if ((buf = malloc(CHUNK))) {
|
||||
for (e = errno, i = 0; i < n; i += j) {
|
||||
rc = read(infd, buf, CHUNK);
|
||||
if (rc == -1) {
|
||||
// eintr may interrupt the read operation
|
||||
if (i && errno == EINTR) {
|
||||
// suppress error if partially completed
|
||||
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;
|
||||
ssize_t copyfd(int in, int out, size_t n) {
|
||||
size_t i;
|
||||
char buf[512];
|
||||
ssize_t dr, dw;
|
||||
for (i = 0; i < n; i += dr) {
|
||||
dr = read(in, buf, MIN(n - i, sizeof(buf)));
|
||||
if (dr == -1) return -1;
|
||||
if (!dr) break;
|
||||
dw = write(out, buf, dr);
|
||||
if (dw == -1) return -1;
|
||||
if (dw != dr) {
|
||||
// POSIX requires atomic IO up to PIPE_BUF
|
||||
// The minimum permissible PIPE_BUF is 512
|
||||
__builtin_trap();
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
return i;
|
||||
}
|
|
@ -17,10 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/asan.internal.h"
|
||||
#include "libc/calls/struct/itimerval.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/struct/itimerval.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -41,12 +42,7 @@ int getitimer(int which, struct itimerval *curvalue) {
|
|||
} else {
|
||||
rc = sys_setitimer_nt(which, 0, curvalue);
|
||||
}
|
||||
if (curvalue) {
|
||||
STRACE("getitimer(%d, [{{%'ld, %'ld}, {%'ld, %'ld}}]) → %d% m", which,
|
||||
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);
|
||||
}
|
||||
STRACE("getitimer(%s, [%s]) → %d% m", DescribeItimer(which),
|
||||
DescribeItimerval(rc, curvalue), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -38,13 +38,13 @@ static gettimeofday_f *__gettimeofday = __gettimeofday_init;
|
|||
* Returns system wall time in microseconds, e.g.
|
||||
*
|
||||
* int64_t t;
|
||||
* char p[30];
|
||||
* char p[20];
|
||||
* struct tm tm;
|
||||
* struct timeval tv;
|
||||
* gettimeofday(&tv, 0);
|
||||
* t = tv.tv_sec;
|
||||
* gmtime_r(&t, &tm);
|
||||
* FormatHttpDateTime(p, &tm);
|
||||
* iso8601(p, &tm);
|
||||
* printf("%s\n", p);
|
||||
*
|
||||
* @param tv points to timeval that receives result if non-NULL
|
||||
|
|
|
@ -16,120 +16,49 @@
|
|||
│ 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/sig.internal.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/calls/struct/siginfo.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/calls/struct/timeval.h"
|
||||
#include "libc/sysv/consts/itimer.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
/**
|
||||
* @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;
|
||||
static struct itimerval g_setitimer;
|
||||
|
||||
textwindows void _check_sigalrm(void) {
|
||||
// TODO(jart): use a different timing source
|
||||
// TODO(jart): synchronize across intervals?
|
||||
long double now, elapsed;
|
||||
if (!__hastimer) return;
|
||||
now = nowl();
|
||||
elapsed = now - __lastalrm;
|
||||
if (elapsed > __interval) {
|
||||
__sig_add(0, SIGALRM, SI_TIMER);
|
||||
if (__singleshot) {
|
||||
__hastimer = false;
|
||||
} else {
|
||||
__lastalrm = now;
|
||||
}
|
||||
struct timeval now;
|
||||
if (timeval_iszero(g_setitimer.it_value)) return;
|
||||
now = timeval_real();
|
||||
if (timeval_cmp(now, g_setitimer.it_value) < 0) return;
|
||||
if (timeval_iszero(g_setitimer.it_interval)) {
|
||||
g_setitimer.it_value = timeval_zero;
|
||||
} else {
|
||||
do {
|
||||
g_setitimer.it_value =
|
||||
timeval_add(g_setitimer.it_value, g_setitimer.it_interval);
|
||||
} while (timeval_cmp(now, g_setitimer.it_value) > 0);
|
||||
}
|
||||
__sig_add(0, SIGALRM, SI_TIMER);
|
||||
}
|
||||
|
||||
textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue,
|
||||
struct itimerval *out_opt_oldvalue) {
|
||||
long double elapsed, untilnext;
|
||||
|
||||
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)))) {
|
||||
textwindows int sys_setitimer_nt(int which, const struct itimerval *neu,
|
||||
struct itimerval *old) {
|
||||
if (which != ITIMER_REAL || (neu && (!timeval_isvalid(neu->it_value) ||
|
||||
!timeval_isvalid(neu->it_interval)))) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (out_opt_oldvalue) {
|
||||
if (__hastimer) {
|
||||
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 (old) {
|
||||
old->it_interval = g_setitimer.it_interval;
|
||||
old->it_value = timeval_subz(g_setitimer.it_value, timeval_real());
|
||||
}
|
||||
|
||||
if (newvalue) {
|
||||
if (newvalue->it_interval.tv_sec || newvalue->it_interval.tv_usec ||
|
||||
newvalue->it_value.tv_sec || newvalue->it_value.tv_usec) {
|
||||
__hastimer = true;
|
||||
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;
|
||||
}
|
||||
if (neu) {
|
||||
g_setitimer.it_interval = neu->it_interval;
|
||||
g_setitimer.it_value = timeval_iszero(neu->it_value)
|
||||
? timeval_zero
|
||||
: timeval_add(timeval_real(), neu->it_value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/struct/itimerval.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
|
@ -66,7 +67,6 @@
|
|||
int setitimer(int which, const struct itimerval *newvalue,
|
||||
struct itimerval *oldvalue) {
|
||||
int rc;
|
||||
|
||||
if (IsAsan() &&
|
||||
((newvalue && !__asan_is_valid(newvalue, sizeof(*newvalue))) ||
|
||||
(oldvalue && !__asan_is_valid(oldvalue, sizeof(*oldvalue))))) {
|
||||
|
@ -80,28 +80,7 @@ int setitimer(int which, const struct itimerval *newvalue,
|
|||
} else {
|
||||
rc = sys_setitimer_nt(which, newvalue, oldvalue);
|
||||
}
|
||||
|
||||
#ifdef SYSDEBUG
|
||||
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
|
||||
|
||||
STRACE("setitimer(%s, %s, [%s]) → %d% m", DescribeItimer(which),
|
||||
DescribeItimerval(0, newvalue), DescribeItimerval(rc, oldvalue), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ int sys_getitimer(int, struct itimerval *) _Hide;
|
|||
int sys_setitimer(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 *);
|
||||
#define DescribeTimeval(rc, ts) DescribeTimeval(alloca(45), rc, ts)
|
||||
const char *DescribeItimerval(char[90], int, const struct itimerval *);
|
||||
#define DescribeItimerval(rc, ts) DescribeItimerval(alloca(90), rc, ts)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -14,14 +14,14 @@ int clock_nanosleep(int, int, const struct timespec *, struct timespec *);
|
|||
int futimens(int, const struct timespec[2]);
|
||||
int nanosleep(const struct timespec *, struct timespec *);
|
||||
int utimensat(int, const char *, const struct timespec[2], int);
|
||||
int timespec_getres(struct timespec *, int);
|
||||
int timespec_get(struct timespec *, int);
|
||||
|
||||
#ifdef COSMO
|
||||
/* cosmopolitan libc's non-posix timespec library
|
||||
removed by default due to emacs codebase clash */
|
||||
#define timespec_zero ((struct timespec){0})
|
||||
#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;
|
||||
int64_t timespec_tomicros(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);
|
||||
int timespec_sleep_until(struct timespec);
|
||||
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 *);
|
||||
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 */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -19,13 +19,23 @@ int utimes(const char *, const struct timeval[2]);
|
|||
#ifdef COSMO
|
||||
/* cosmopolitan libc's non-posix timevals library
|
||||
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;
|
||||
struct timeval timeval_real(void);
|
||||
struct timeval timeval_frommicros(int64_t) pureconst;
|
||||
struct timeval timeval_frommillis(int64_t) pureconst;
|
||||
struct timeval timeval_add(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 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 */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/time/struct/timezone.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
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;
|
||||
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_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_INTERNAL_H_ */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=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│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ 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 │
|
||||
|
@ -16,30 +16,17 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
|
||||
// fmod [sic] does (𝑥 rem 𝑦) w/ round()-style rounding.
|
||||
//
|
||||
// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes
|
||||
// @param 𝑦 is the power, also pushed on stack, in reverse order
|
||||
// @return remainder ∈ (-|𝑦|,|𝑦|) in %st
|
||||
// @define 𝑥-truncl(𝑥/𝑦)*𝑦
|
||||
// @see emod()
|
||||
.ftrace1
|
||||
fmodl: .ftrace2
|
||||
push %rbp
|
||||
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
|
||||
/**
|
||||
* Subtracts two nanosecond timestamps.
|
||||
*
|
||||
* Unlike `timespec_sub()` this function will return zero if `x < y`.
|
||||
*/
|
||||
struct timespec timespec_subz(struct timespec x, struct timespec y) {
|
||||
if (timespec_cmp(x, y) > 0) {
|
||||
return timespec_sub(x, y);
|
||||
} else {
|
||||
return timespec_zero;
|
||||
}
|
||||
}
|
31
libc/calls/timeval_real.c
Normal file
31
libc/calls/timeval_real.c
Normal 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
30
libc/calls/timeval_subz.c
Normal 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;
|
||||
}
|
||||
}
|
|
@ -16,10 +16,10 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/itimerval.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/directmap.internal.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)) {
|
||||
return (struct AsanFault){kAsanUnmapped, s};
|
||||
}
|
||||
if ((w = ((uint64_t)(255 & s[0]) << 000 | (uint64_t)(255 & s[1]) << 010 |
|
||||
(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))) {
|
||||
if ((w = READ64LE(s))) {
|
||||
s += __asan_bsf(w) >> 3;
|
||||
return __asan_fault(s, kAsanHeapOverrun);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/arch.h"
|
||||
|
||||
const char *(DescribeArchPrctlCode)(char buf[12], int x) {
|
||||
if (x == ARCH_SET_FS) return "ARCH_SET_FS";
|
||||
|
|
|
@ -24,6 +24,7 @@ const char *DescribeFrame(char[32], int);
|
|||
const char *DescribeFutexOp(char[64], int);
|
||||
const char *DescribeHow(char[12], int);
|
||||
const char *DescribeInOutInt64(char[23], ssize_t, int64_t *);
|
||||
const char *DescribeItimer(char[12], int);
|
||||
const char *DescribeMapFlags(char[64], int);
|
||||
const char *DescribeMapping(char[8], int, int);
|
||||
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 DescribeHow(x) DescribeHow(alloca(12), 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 DescribeMapping(x, y) DescribeMapping(alloca(8), x, y)
|
||||
#define DescribeNtConsoleInFlags(x) DescribeNtConsoleInFlags(alloca(256), x)
|
||||
|
|
29
libc/intrin/describeitimer.c
Normal file
29
libc/intrin/describeitimer.c
Normal 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;
|
||||
}
|
|
@ -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 2020 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,67 +16,26 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
#include "libc/calls/struct/itimerval.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
|
||||
float b32;
|
||||
double b64;
|
||||
long double b80;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
int128_t x;
|
||||
#define N 90
|
||||
|
||||
void int2float(const char *s) {
|
||||
x = strtoi128(s, NULL, 0);
|
||||
if ((0 <= x && x <= UINT32_MAX) && !_startswith(s, "-") &&
|
||||
(!_endswith(s, "l") && !_endswith(s, "L"))) {
|
||||
u32 = x;
|
||||
memcpy(&b32, &u32, 4);
|
||||
s = _gc(xdtoa(b32));
|
||||
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);
|
||||
const char *(DescribeItimerval)(char buf[N], int rc,
|
||||
const struct itimerval *it) {
|
||||
if (!it) return "NULL";
|
||||
if (rc == -1) return "n/a";
|
||||
if ((!IsAsan() && kisdangerous(it)) ||
|
||||
(IsAsan() && !__asan_is_valid(it, sizeof(*it)))) {
|
||||
ksnprintf(buf, N, "%p", it);
|
||||
} else {
|
||||
memcpy(&b80, &x, 16);
|
||||
s = _gc(xdtoa(b80));
|
||||
if (!strchr(s, '.')) s = _gc(xasprintf("%s.", s));
|
||||
s = _gc(xasprintf("%sL", s));
|
||||
puts(s);
|
||||
ksnprintf(buf, N, "{%s, %s}", DescribeTimeval(0, &it->it_interval),
|
||||
DescribeTimeval(0, &it->it_value));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
int2float(argv[i]);
|
||||
}
|
||||
return 0;
|
||||
return buf;
|
||||
}
|
|
@ -31,7 +31,6 @@ const char *(DescribeMapFlags)(char buf[64], int x) {
|
|||
{MAP_FIXED, "FIXED"}, //
|
||||
{MAP_FIXED_NOREPLACE, "FIXED_NOREPLACE"}, //
|
||||
{MAP_CONCEAL, "CONCEAL"}, //
|
||||
{MAP_HUGETLB, "HUGETLB"}, //
|
||||
{MAP_LOCKED, "LOCKED"}, //
|
||||
{MAP_NORESERVE, "NORESERVE"}, //
|
||||
{MAP_NONBLOCK, "NONBLOCK"}, //
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
|
||||
#define N (PAGESIZE / 2 / sizeof(struct DescribeFlags))
|
||||
|
@ -29,17 +31,42 @@
|
|||
* Describes clock_gettime() clock argument.
|
||||
*/
|
||||
const char *(DescribeOpenFlags)(char buf[128], int x) {
|
||||
char *s;
|
||||
char *p;
|
||||
int i, n;
|
||||
const char *pipe;
|
||||
struct DescribeFlags d[N];
|
||||
if (x == -1) return "-1";
|
||||
// TODO(jart): unify DescribeFlags and MagnumStr data structures
|
||||
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR; ++n) {
|
||||
if (n == N) notpossible;
|
||||
p = buf;
|
||||
switch (x & O_ACCMODE) {
|
||||
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) {
|
||||
d[i].flag = MAGNUM_NUMBER(kOpenFlags, i);
|
||||
d[i].name = MAGNUM_STRING(kOpenFlags, i);
|
||||
if (x) {
|
||||
p = stpcpy(p, pipe);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#include "libc/intrin/kprintf.h"
|
||||
|
||||
const char *(DescribeTimeval)(char buf[45], int rc, const struct timeval *tv) {
|
||||
if (rc == -1) return "n/a";
|
||||
if (!tv) return "NULL";
|
||||
if (rc == -1) return "n/a";
|
||||
if ((!IsAsan() && kisdangerous(tv)) ||
|
||||
(IsAsan() && !__asan_is_valid(tv, sizeof(*tv)))) {
|
||||
ksnprintf(buf, 45, "%p", tv);
|
||||
|
|
|
@ -46,11 +46,14 @@ feclearexcept:
|
|||
// maintain exceptions in the sse mxcsr, clear x87 exceptions
|
||||
mov %edi,%ecx
|
||||
and $0x3f,%ecx
|
||||
#ifndef NOX87
|
||||
fnstsw %ax
|
||||
test %eax,%ecx
|
||||
jz 1f
|
||||
fnclex
|
||||
1: stmxcsr -8(%rsp)
|
||||
1:
|
||||
#endif
|
||||
stmxcsr -8(%rsp)
|
||||
and $0x3f,%eax
|
||||
or %eax,-8(%rsp)
|
||||
test %ecx,-8(%rsp)
|
||||
|
@ -96,12 +99,16 @@ fetestexcept:
|
|||
.ftrace2
|
||||
#ifdef __x86_64__
|
||||
and $0x3f,%edi
|
||||
push %rax
|
||||
push $0
|
||||
stmxcsr (%rsp)
|
||||
#ifdef NOX87
|
||||
pop %rax
|
||||
#else
|
||||
pop %rsi
|
||||
fnstsw %ax
|
||||
or %esi,%eax
|
||||
and %edi,%eax
|
||||
#endif
|
||||
ret
|
||||
#elif defined(__aarch64__)
|
||||
and w0,w0,#0x1f
|
||||
|
@ -138,10 +145,12 @@ __fesetround:
|
|||
push %rax
|
||||
xor %eax,%eax
|
||||
mov %edi,%ecx
|
||||
#ifndef NOX87
|
||||
fnstcw (%rsp)
|
||||
andb $0xf3,1(%rsp)
|
||||
or %ch,1(%rsp)
|
||||
fldcw (%rsp)
|
||||
#endif
|
||||
stmxcsr (%rsp)
|
||||
shl $3,%ch
|
||||
andb $0x9f,1(%rsp)
|
||||
|
@ -181,7 +190,9 @@ fegetenv:
|
|||
.ftrace2
|
||||
#ifdef __x86_64__
|
||||
xor %eax,%eax
|
||||
#ifndef NOX87
|
||||
fnstenv (%rdi)
|
||||
#endif
|
||||
stmxcsr 28(%rdi)
|
||||
ret
|
||||
#elif defined(__aarch64__)
|
||||
|
@ -200,14 +211,18 @@ fesetenv:
|
|||
xor %eax,%eax
|
||||
inc %rdi
|
||||
jz 1f
|
||||
#ifndef NOX87
|
||||
fldenv -1(%rdi)
|
||||
#endif
|
||||
ldmxcsr 27(%rdi)
|
||||
ret
|
||||
1: push %rax
|
||||
push %rax
|
||||
pushq $0xffff
|
||||
pushq $0x37f
|
||||
#ifndef NOX87
|
||||
fldenv (%rsp)
|
||||
#endif
|
||||
pushq $0x1f80
|
||||
ldmxcsr (%rsp)
|
||||
add $40,%rsp
|
||||
|
|
|
@ -35,5 +35,5 @@ double fmax(double x, double y) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(fmax, fmaxl);
|
||||
__weak_reference(fmax, fmaxl);
|
||||
#endif
|
||||
|
|
|
@ -69,6 +69,6 @@ double scalbn(double x, int n)
|
|||
|
||||
__strong_reference(scalbn, ldexp);
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(scalbn, ldexpl);
|
||||
__strong_reference(scalbn, scalbnl);
|
||||
__weak_reference(scalbn, ldexpl);
|
||||
__weak_reference(scalbn, scalbnl);
|
||||
#endif
|
||||
|
|
|
@ -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_ */
|
|
@ -45,6 +45,7 @@ cosmo: push %rbp
|
|||
mov %eax,%r12d
|
||||
#endif /* SYSDEBUG */
|
||||
|
||||
#ifndef NOX87
|
||||
// Windows always initializes FPU to douuble precision.
|
||||
// WSL breaks Linux ABI by initializing FPU to double precision.
|
||||
// This code makes long double long again.
|
||||
|
@ -70,6 +71,7 @@ cosmo: push %rbp
|
|||
// d││││rr││││││
|
||||
1: .short 0b00000000000000000001101111111
|
||||
.previous
|
||||
#endif
|
||||
|
||||
#ifdef __FAST_MATH__
|
||||
push %rax
|
||||
|
|
|
@ -20,24 +20,9 @@ typedef unsigned long jmp_buf[26];
|
|||
|
||||
typedef long sigjmp_buf[12];
|
||||
|
||||
extern char **environ; /* CRT */
|
||||
extern int __argc; /* CRT */
|
||||
extern char **__argv; /* CRT */
|
||||
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;
|
||||
extern char **environ;
|
||||
extern char *program_invocation_name;
|
||||
extern char *program_invocation_short_name;
|
||||
|
||||
void mcount(void);
|
||||
int daemon(int, int);
|
||||
|
@ -83,6 +68,21 @@ int sethostname(const char *, size_t);
|
|||
int acct(const char *);
|
||||
|
||||
#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 */
|
||||
void _intsort(int *, size_t);
|
||||
void _longsort(long *, size_t);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/nexgen32e/msr.internal.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/sysv/consts/arch.h"
|
||||
#include "libc/thread/tls.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),
|
||||
"d"((uint32_t)(val >> 32)));
|
||||
}
|
||||
#else
|
||||
#elif defined(__aarch64__)
|
||||
register long x28 asm("x28") = (long)tib;
|
||||
asm volatile("" : "+r"(x28));
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -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_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_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_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_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_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_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
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_HUGETLB,0x00040000,0x00040000,0,0,0,0,0,0x80000000
|
|
@ -1,2 +0,0 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_HUGE_MASK,63,63,0,0,0,0,0,0
|
|
@ -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
9
libc/sysv/consts/arch.h
Normal 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_ */
|
|
@ -13,9 +13,6 @@ extern const int MAP_FILE;
|
|||
extern const int MAP_FIXED;
|
||||
extern const int MAP_FIXED_NOREPLACE;
|
||||
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_LOCKED;
|
||||
extern const int MAP_NONBLOCK;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/copyfd.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
|
@ -34,7 +33,7 @@ void testlib_extract(const char *zip, const char *to, int mode) {
|
|||
int fdin, fdout;
|
||||
ASSERT_NE(-1, (fdin = open(zip, O_RDONLY)));
|
||||
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(fdin));
|
||||
}
|
||||
|
|
|
@ -143,5 +143,5 @@ double acos(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(acos, acosl);
|
||||
__weak_reference(acos, acosl);
|
||||
#endif
|
||||
|
|
|
@ -55,5 +55,5 @@ double acosh(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(acosh, acoshl);
|
||||
__weak_reference(acosh, acoshl);
|
||||
#endif
|
||||
|
|
|
@ -149,5 +149,5 @@ double asin(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(asin, asinl);
|
||||
__weak_reference(asin, asinl);
|
||||
#endif
|
||||
|
|
|
@ -66,5 +66,5 @@ double asinh(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(asinh, asinhl);
|
||||
__weak_reference(asinh, asinhl);
|
||||
#endif
|
||||
|
|
|
@ -156,5 +156,5 @@ double atan(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(atan, atanl);
|
||||
__weak_reference(atan, atanl);
|
||||
#endif
|
||||
|
|
|
@ -155,5 +155,5 @@ atan2(double y, double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(atan2, atan2l);
|
||||
__weak_reference(atan2, atan2l);
|
||||
#endif
|
||||
|
|
|
@ -66,5 +66,5 @@ double atanh(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(atanh, atanhl);
|
||||
__weak_reference(atanh, atanhl);
|
||||
#endif
|
||||
|
|
|
@ -27,5 +27,5 @@ double cabs(double complex z) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(cabs, cabsl);
|
||||
__weak_reference(cabs, cabsl);
|
||||
#endif
|
||||
|
|
|
@ -45,5 +45,5 @@ double complex cacosh(double complex z)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(cacosh, cacoshl);
|
||||
__weak_reference(cacosh, cacoshl);
|
||||
#endif
|
||||
|
|
|
@ -24,5 +24,5 @@ double carg(double complex z) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(carg, cargl);
|
||||
__weak_reference(carg, cargl);
|
||||
#endif
|
||||
|
|
|
@ -52,5 +52,5 @@ double complex casin(double complex z)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(casin, casinl);
|
||||
__weak_reference(casin, casinl);
|
||||
#endif
|
||||
|
|
|
@ -147,5 +147,5 @@ double complex catan(double complex z)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(catan, catanl);
|
||||
__weak_reference(catan, catanl);
|
||||
#endif
|
||||
|
|
|
@ -32,5 +32,5 @@ double copysign(double x, double y) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(copysign, copysignl);
|
||||
__weak_reference(copysign, copysignl);
|
||||
#endif
|
||||
|
|
|
@ -122,5 +122,5 @@ double cos(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(cos, cosl);
|
||||
__weak_reference(cos, cosl);
|
||||
#endif
|
||||
|
|
|
@ -76,3 +76,7 @@ double cosh(double x)
|
|||
t = __expo2(x, 1.0);
|
||||
return t;
|
||||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__weak_reference(cosh, coshl);
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/tinymath/freebsd.internal.h"
|
||||
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
FreeBSD libm (BSD-2 License)\\n\
|
||||
|
@ -155,3 +156,5 @@ coshl(long double x)
|
|||
/* |x| > o_threshold, cosh(x) overflow */
|
||||
RETURNI(huge*huge);
|
||||
}
|
||||
|
||||
#endif /* long double is long */
|
||||
|
|
|
@ -170,5 +170,5 @@ double exp(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(exp, expl);
|
||||
__weak_reference(exp, expl);
|
||||
#endif
|
||||
|
|
|
@ -57,5 +57,6 @@ double exp10(double x)
|
|||
|
||||
__strong_reference(exp10, pow10);
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(exp10, exp10l);
|
||||
__weak_reference(exp10, exp10l);
|
||||
__weak_reference(exp10, pow10l);
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,6 @@ long double exp10l(long double x)
|
|||
return powl(10.0, x);
|
||||
}
|
||||
|
||||
__strong_reference(exp10l, pow10l);
|
||||
__weak_reference(exp10l, pow10l);
|
||||
|
||||
#endif /* long double is long */
|
||||
|
|
|
@ -157,5 +157,5 @@ double exp2(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(exp2, exp2l);
|
||||
__weak_reference(exp2, exp2l);
|
||||
#endif
|
||||
|
|
|
@ -238,5 +238,5 @@ double expm1(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(expm1, expm1l);
|
||||
__weak_reference(expm1, expm1l);
|
||||
#endif
|
||||
|
|
|
@ -31,5 +31,5 @@ double fabs(double x) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(fabs, fabsl);
|
||||
__weak_reference(fabs, fabsl);
|
||||
#endif
|
||||
|
|
|
@ -27,5 +27,5 @@ double fdim(double x, double y) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(fdim, fdiml);
|
||||
__weak_reference(fdim, fdiml);
|
||||
#endif
|
||||
|
|
|
@ -96,5 +96,5 @@ double floor(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(floor, floorl);
|
||||
__weak_reference(floor, floorl);
|
||||
#endif
|
||||
|
|
|
@ -35,5 +35,5 @@ double fmin(double x, double y) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(fmin, fminl);
|
||||
__weak_reference(fmin, fminl);
|
||||
#endif
|
||||
|
|
|
@ -103,3 +103,7 @@ double fmod(double x, double y)
|
|||
ux.i = uxi;
|
||||
return ux.f;
|
||||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__weak_reference(fmod, fmodl);
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.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\
|
||||
|
@ -34,10 +35,13 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
|
|||
asm(".include \"libc/disclaimer.inc\"");
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* Does (𝑥 rem 𝑦) w/ round()-style rounding.
|
||||
* @return remainder ∈ (-|𝑦|,|𝑦|) in %xmm0
|
||||
* @define 𝑥-trunc(𝑥/𝑦)*𝑦
|
||||
*/
|
||||
long double fmodl(long double x, long double y) {
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
return fmod(x, y);
|
||||
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
||||
#if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
|
||||
union ldshape ux = {x}, uy = {y};
|
||||
int ex = ux.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"
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* long double is long */
|
||||
|
|
|
@ -58,5 +58,5 @@ double frexp(double x, int *e)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(frexp, frexpl);
|
||||
__weak_reference(frexp, frexpl);
|
||||
#endif
|
||||
|
|
|
@ -101,5 +101,5 @@ double hypot(double x, double y)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(hypot, hypotl);
|
||||
__weak_reference(hypot, hypotl);
|
||||
#endif
|
||||
|
|
|
@ -63,5 +63,5 @@ int ilogb(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(ilogb, ilogbl);
|
||||
__weak_reference(ilogb, ilogbl);
|
||||
#endif
|
||||
|
|
|
@ -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 */
|
|
@ -27,6 +27,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/tinymath/kernel.internal.h"
|
||||
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
FreeBSD libm (BSD-2 License)\\n\
|
||||
|
@ -183,3 +184,5 @@ long double __tanl(long double x, long double y, int odd) {
|
|||
#else
|
||||
#error "architecture unsupported"
|
||||
#endif
|
||||
|
||||
#endif /* long double is long */
|
||||
|
|
|
@ -142,5 +142,5 @@ double log(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(log, logl);
|
||||
__weak_reference(log, logl);
|
||||
#endif
|
||||
|
|
|
@ -143,5 +143,5 @@ double log10(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(log10, log10l);
|
||||
__weak_reference(log10, log10l);
|
||||
#endif
|
||||
|
|
|
@ -161,5 +161,5 @@ double log1p(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(log1p, log1pl);
|
||||
__weak_reference(log1p, log1pl);
|
||||
#endif
|
||||
|
|
|
@ -159,5 +159,5 @@ double log2(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(log2, log2l);
|
||||
__weak_reference(log2, log2l);
|
||||
#endif
|
||||
|
|
|
@ -23,3 +23,7 @@ double logb(double x) {
|
|||
if (!x) return -1 / (x * x);
|
||||
return ilogb(x);
|
||||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__weak_reference(logb, logbl);
|
||||
#endif
|
||||
|
|
|
@ -45,8 +45,8 @@ __weak_reference(lrint, llrint);
|
|||
#endif
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(lrint, lrintl);
|
||||
__weak_reference(lrint, lrintl);
|
||||
#if __SIZEOF_LONG__ == __SIZEOF_LONG_LONG__
|
||||
__strong_reference(lrint, llrintl);
|
||||
__weak_reference(lrint, llrintl);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -26,5 +26,5 @@ long lround(double x) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(lround, lroundl);
|
||||
__weak_reference(lround, lroundl);
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,9 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
|
|||
asm(".include \"libc/disclaimer.inc\"");
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* Returns fractional part of 𝑥.
|
||||
*/
|
||||
double modf(double x, double *iptr)
|
||||
{
|
||||
union {double f; uint64_t i;} u = {x};
|
||||
|
@ -65,3 +68,7 @@ double modf(double x, double *iptr)
|
|||
*iptr = u.f;
|
||||
return x - u.f;
|
||||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__weak_reference(modf, modfl);
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
│ │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
Musl libc (MIT License)\\n\
|
||||
|
@ -33,20 +34,11 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
|
|||
asm(".include \"libc/disclaimer.inc\"");
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Returns fractional part of 𝑥.
|
||||
*/
|
||||
long double modfl(long double x, long double *iptr)
|
||||
{
|
||||
union {
|
||||
|
@ -90,6 +82,4 @@ long double modfl(long double x, long double *iptr)
|
|||
return -y;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "architecture unsupported"
|
||||
#endif
|
||||
#endif /* long double is long */
|
||||
|
|
|
@ -42,5 +42,5 @@ double nearbyint(double x) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(nearbyint, nearbyintl);
|
||||
__weak_reference(nearbyint, nearbyintl);
|
||||
#endif
|
||||
|
|
|
@ -65,5 +65,5 @@ double nextafter(double x, double y)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(nextafter, nextafterl);
|
||||
__weak_reference(nextafter, nextafterl);
|
||||
#endif
|
||||
|
|
|
@ -381,5 +381,5 @@ double pow(double x, double y)
|
|||
|
||||
__weak_reference(pow, __pow_finite);
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(pow, powl);
|
||||
__weak_reference(pow, powl);
|
||||
#endif
|
||||
|
|
|
@ -28,5 +28,5 @@ double remainder(double x, double y) {
|
|||
|
||||
__strong_reference(remainder, drem);
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(remainder, remainderl);
|
||||
__weak_reference(remainder, remainderl);
|
||||
#endif
|
||||
|
|
|
@ -225,3 +225,7 @@ medium:
|
|||
y[1] = ty[1];
|
||||
return n;
|
||||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__weak_reference(__rem_pio2, __rem_pio2l);
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "libc/math.h"
|
||||
#include "libc/tinymath/kernel.internal.h"
|
||||
#include "libc/tinymath/ldshape.internal.h"
|
||||
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
FreeBSD libm (BSD-2 License)\\n\
|
||||
|
@ -200,3 +201,5 @@ int __rem_pio2l(long double x, long double *y)
|
|||
#else
|
||||
#error "architecture unsupported"
|
||||
#endif
|
||||
|
||||
#endif /* long double is long */
|
||||
|
|
|
@ -117,5 +117,5 @@ end:
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(remquo, remquol);
|
||||
__weak_reference(remquo, remquol);
|
||||
#endif
|
||||
|
|
|
@ -66,5 +66,5 @@ double rint(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(rint, rintl);
|
||||
__weak_reference(rint, rintl);
|
||||
#endif
|
||||
|
|
|
@ -92,5 +92,5 @@ double round(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(round, roundl);
|
||||
__weak_reference(round, roundl);
|
||||
#endif
|
||||
|
|
|
@ -26,5 +26,5 @@ double scalbln(double x, long n) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(scalbln, scalblnl);
|
||||
__weak_reference(scalbln, scalblnl);
|
||||
#endif
|
||||
|
|
|
@ -26,5 +26,5 @@ double significand(double x) {
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(significand, significandl);
|
||||
__weak_reference(significand, significandl);
|
||||
#endif
|
||||
|
|
|
@ -123,5 +123,5 @@ double sin(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(sin, sinl);
|
||||
__weak_reference(sin, sinl);
|
||||
#endif
|
||||
|
|
|
@ -114,5 +114,5 @@ void sincos(double x, double *sin, double *cos)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(sincos, sincosl);
|
||||
__weak_reference(sincos, sincosl);
|
||||
#endif
|
||||
|
|
|
@ -75,3 +75,7 @@ double sinh(double x)
|
|||
t = __expo2(absx, 2*h);
|
||||
return t;
|
||||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__weak_reference(sinh, sinhl);
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "libc/intrin/likely.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/tinymath/freebsd.internal.h"
|
||||
#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024)
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
FreeBSD libm (BSD-2 License)\\n\
|
||||
|
@ -154,3 +155,5 @@ sinhl(long double x)
|
|||
/* |x| > o_threshold, sinh(x) overflow */
|
||||
return x*shuge;
|
||||
}
|
||||
|
||||
#endif /* long double is long */
|
||||
|
|
|
@ -222,5 +222,5 @@ double sqrt(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(sqrt, sqrtl);
|
||||
__weak_reference(sqrt, sqrtl);
|
||||
#endif
|
||||
|
|
|
@ -115,5 +115,5 @@ double tan(double x)
|
|||
}
|
||||
|
||||
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||
__strong_reference(tan, tanl);
|
||||
__weak_reference(tan, tanl);
|
||||
#endif
|
||||
|
|
|
@ -76,3 +76,7 @@ double tanh(double x)
|
|||
}
|
||||
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
Loading…
Reference in a new issue