diff options
Diffstat (limited to 'src')
53 files changed, 296 insertions, 145 deletions
diff --git a/src/complex/catan.c b/src/complex/catan.c index ccc2fb53..b4fe552a 100644 --- a/src/complex/catan.c +++ b/src/complex/catan.c @@ -60,29 +60,6 @@ #include "complex_impl.h" -#define MAXNUM 1.0e308 - -static const double DP1 = 3.14159265160560607910E0; -static const double DP2 = 1.98418714791870343106E-9; -static const double DP3 = 1.14423774522196636802E-17; - -static double _redupi(double x) -{ - double t; - long i; - - t = x/M_PI; - if (t >= 0.0) - t += 0.5; - else - t -= 0.5; - - i = t; /* the multiple */ - t = i; - t = ((x - t * DP1) - t * DP2) - t * DP3; - return t; -} - double complex catan(double complex z) { double complex w; @@ -95,7 +72,7 @@ double complex catan(double complex z) a = 1.0 - x2 - (y * y); t = 0.5 * atan2(2.0 * x, a); - w = _redupi(t); + w = t; t = y - 1.0; a = x2 + (t * t); diff --git a/src/complex/catanf.c b/src/complex/catanf.c index 1d569f2d..faaa907a 100644 --- a/src/complex/catanf.c +++ b/src/complex/catanf.c @@ -55,32 +55,6 @@ #include "complex_impl.h" -#define MAXNUMF 1.0e38F - -static const double DP1 = 3.140625; -static const double DP2 = 9.67502593994140625E-4; -static const double DP3 = 1.509957990978376432E-7; - -static const float float_pi = M_PI; - -static float _redupif(float xx) -{ - float x, t; - long i; - - x = xx; - t = x/float_pi; - if (t >= 0.0f) - t += 0.5f; - else - t -= 0.5f; - - i = t; /* the multiple */ - t = i; - t = ((x - t * DP1) - t * DP2) - t * DP3; - return t; -} - float complex catanf(float complex z) { float complex w; @@ -93,7 +67,7 @@ float complex catanf(float complex z) a = 1.0f - x2 - (y * y); t = 0.5f * atan2f(2.0f * x, a); - w = _redupif(t); + w = t; t = y - 1.0f; a = x2 + (t * t); diff --git a/src/complex/catanl.c b/src/complex/catanl.c index e62526c0..cd2d2b00 100644 --- a/src/complex/catanl.c +++ b/src/complex/catanl.c @@ -67,28 +67,6 @@ long double complex catanl(long double complex z) return catan(z); } #else -static const long double PIL = 3.141592653589793238462643383279502884197169L; -static const long double DP1 = 3.14159265358979323829596852490908531763125L; -static const long double DP2 = 1.6667485837041756656403424829301998703007e-19L; -static const long double DP3 = 1.8830410776607851167459095484560349402753e-39L; - -static long double redupil(long double x) -{ - long double t; - long i; - - t = x / PIL; - if (t >= 0.0L) - t += 0.5L; - else - t -= 0.5L; - - i = t; /* the multiple */ - t = i; - t = ((x - t * DP1) - t * DP2) - t * DP3; - return t; -} - long double complex catanl(long double complex z) { long double complex w; @@ -101,7 +79,7 @@ long double complex catanl(long double complex z) a = 1.0L - x2 - (y * y); t = atan2l(2.0L * x, a) * 0.5L; - w = redupil(t); + w = t; t = y - 1.0L; a = x2 + (t * t); diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index 60d3e745..8dd5c725 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -220,8 +220,13 @@ long sysconf(int name) return (mem > LONG_MAX) ? LONG_MAX : mem; case JT_MINSIGSTKSZ & 255: case JT_SIGSTKSZ & 255: ; - long val = __getauxval(AT_MINSIGSTKSZ); - if (val < MINSIGSTKSZ) val = MINSIGSTKSZ; + /* Value from auxv/kernel is only sigfame size. Clamp it + * to at least 1k below arch's traditional MINSIGSTKSZ, + * then add 1k of working space for signal handler. */ + unsigned long sigframe_sz = __getauxval(AT_MINSIGSTKSZ); + if (sigframe_sz < MINSIGSTKSZ - 1024) + sigframe_sz = MINSIGSTKSZ - 1024; + unsigned val = sigframe_sz + 1024; if (values[name] == JT_SIGSTKSZ) val += SIGSTKSZ - MINSIGSTKSZ; return val; diff --git a/src/dirent/posix_getdents.c b/src/dirent/posix_getdents.c index b19e8127..26c16ac6 100644 --- a/src/dirent/posix_getdents.c +++ b/src/dirent/posix_getdents.c @@ -3,7 +3,7 @@ #include <errno.h> #include "syscall.h" -int posix_getdents(int fd, void *buf, size_t len, int flags) +ssize_t posix_getdents(int fd, void *buf, size_t len, int flags) { if (flags) return __syscall_ret(-EOPNOTSUPP); if (len>INT_MAX) len = INT_MAX; diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h index 14925907..0398b5b6 100644 --- a/src/errno/__strerror.h +++ b/src/errno/__strerror.h @@ -97,6 +97,8 @@ E(ESHUTDOWN, "Cannot send after socket shutdown") E(EALREADY, "Operation already in progress") E(EINPROGRESS, "Operation in progress") E(ESTALE, "Stale file handle") +E(EUCLEAN, "Data consistency error") +E(ENAVAIL, "Resource not available") E(EREMOTEIO, "Remote I/O error") E(EDQUOT, "Quota exceeded") E(ENOMEDIUM, "No medium found") diff --git a/src/exit/atexit.c b/src/exit/atexit.c index 854e9fdd..92c91c9d 100644 --- a/src/exit/atexit.c +++ b/src/exit/atexit.c @@ -19,6 +19,7 @@ static struct fl void *a[COUNT]; } builtin, *head; +static int finished_atexit; static int slot; static volatile int lock[1]; volatile int *const __atexit_lockptr = lock; @@ -34,6 +35,10 @@ void __funcs_on_exit() func(arg); LOCK(lock); } + /* Unlock to prevent deadlock if a global dtor + * attempts to call atexit. */ + finished_atexit = 1; + UNLOCK(lock); } void __cxa_finalize(void *dso) @@ -44,6 +49,13 @@ int __cxa_atexit(void (*func)(void *), void *arg, void *dso) { LOCK(lock); + /* Prevent dtors from registering further atexit + * handlers that would never be run. */ + if (finished_atexit) { + UNLOCK(lock); + return -1; + } + /* Defer initialization of head so it can be in BSS */ if (!head) head = &builtin; diff --git a/src/exit/exit.c b/src/exit/exit.c index a6869b37..17b33cc6 100644 --- a/src/exit/exit.c +++ b/src/exit/exit.c @@ -1,6 +1,9 @@ #include <stdlib.h> #include <stdint.h> #include "libc.h" +#include "pthread_impl.h" +#include "atomic.h" +#include "syscall.h" static void dummy() { @@ -26,6 +29,17 @@ weak_alias(libc_exit_fini, __libc_exit_fini); _Noreturn void exit(int code) { + /* Handle potentially concurrent or recursive calls to exit, + * whose behaviors have traditionally been undefined by the + * standards. Using a custom lock here avoids pulling in lock + * machinery and lets us trap recursive calls while supporting + * multiple threads contending to be the one to exit(). */ + static volatile int exit_lock[1]; + int tid = __pthread_self()->tid; + int prev = a_cas(exit_lock, 0, tid); + if (prev == tid) a_crash(); + else if (prev) for (;;) __sys_pause(); + __funcs_on_exit(); __libc_exit_fini(); __stdio_exit(); diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 33d981f9..2d8a5c13 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -391,6 +391,17 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, #define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__) #define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__)) +#ifdef SYS_pause +#define __sys_pause() __syscall(SYS_pause) +#define __sys_pause_cp() __syscall_cp(SYS_pause) +#else +#define __sys_pause() __syscall(SYS_ppoll, 0, 0, 0, 0) +#define __sys_pause_cp() __syscall_cp(SYS_ppoll, 0, 0, 0, 0) +#endif + +#define sys_pause() __syscall_ret(__sys_pause()) +#define sys_pause_cp() __syscall_ret(__sys_pause_cp()) + #ifdef SYS_wait4 #define __sys_wait4(a,b,c,d) __syscall(SYS_wait4,a,b,c,d) #define __sys_wait4_cp(a,b,c,d) __syscall_cp(SYS_wait4,a,b,c,d) diff --git a/src/ldso/loongarch64/tlsdesc.s b/src/ldso/loongarch64/tlsdesc.s new file mode 100644 index 00000000..4b6ea0e5 --- /dev/null +++ b/src/ldso/loongarch64/tlsdesc.s @@ -0,0 +1,37 @@ +.text +.global __tlsdesc_static +.hidden __tlsdesc_static +.type __tlsdesc_static,%function +__tlsdesc_static: + ld.d $a0, $a0, 8 + jr $ra +# size_t __tlsdesc_dynamic(size_t *a) +# { +# struct {size_t modidx,off;} *p = (void*)a[1]; +# size_t *dtv = *(size_t**)(tp - 8); +# return dtv[p->modidx] + p->off - tp; +# } +.global __tlsdesc_dynamic +.hidden __tlsdesc_dynamic +.type __tlsdesc_dynamic,%function +__tlsdesc_dynamic: + addi.d $sp, $sp, -16 + st.d $t1, $sp, 0 + st.d $t2, $sp, 8 + + ld.d $t2, $tp, -8 # t2=dtv + + ld.d $a0, $a0, 8 # a0=&{modidx,off} + ld.d $t1, $a0, 8 # t1=off + ld.d $a0, $a0, 0 # a0=modidx + slli.d $a0, $a0, 3 # a0=8*modidx + + add.d $a0, $a0, $t2 # a0=dtv+8*modidx + ld.d $a0, $a0, 0 # a0=dtv[modidx] + add.d $a0, $a0, $t1 # a0=dtv[modidx]+off + sub.d $a0, $a0, $tp # a0=dtv[modidx]+off-tp + + ld.d $t1, $sp, 0 + ld.d $t2, $sp, 8 + addi.d $sp, $sp, 16 + jr $ra diff --git a/src/legacy/getusershell.c b/src/legacy/getusershell.c index 5fecdec2..1c5d98ec 100644 --- a/src/legacy/getusershell.c +++ b/src/legacy/getusershell.c @@ -25,8 +25,10 @@ char *getusershell(void) ssize_t l; if (!f) setusershell(); if (!f) return 0; - l = getline(&line, &linesize, f); - if (l <= 0) return 0; + do { + l = getline(&line, &linesize, f); + if (l <= 0) return 0; + } while (line[0] == '#' || line[0] == '\n'); if (line[l-1]=='\n') line[l-1]=0; return line; } diff --git a/src/linux/renameat2.c b/src/linux/renameat2.c new file mode 100644 index 00000000..b8060388 --- /dev/null +++ b/src/linux/renameat2.c @@ -0,0 +1,11 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include "syscall.h" + +int renameat2(int oldfd, const char *old, int newfd, const char *new, unsigned flags) +{ +#ifdef SYS_renameat + if (!flags) return syscall(SYS_renameat, oldfd, old, newfd, new); +#endif + return syscall(SYS_renameat2, oldfd, old, newfd, new, flags); +} diff --git a/src/linux/statx.c b/src/linux/statx.c index 4616bff4..4fb96e4b 100644 --- a/src/linux/statx.c +++ b/src/linux/statx.c @@ -19,8 +19,11 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct ret = fstatat(dirfd, path, &st, flags); if (ret) return ret; + *stx = (struct statx){0}; stx->stx_dev_major = major(st.st_dev); stx->stx_dev_minor = minor(st.st_dev); + stx->stx_rdev_major = major(st.st_rdev); + stx->stx_rdev_minor = minor(st.st_rdev); stx->stx_ino = st.st_ino; stx->stx_mode = st.st_mode; stx->stx_nlink = st.st_nlink; @@ -35,7 +38,6 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec; stx->stx_ctime.tv_sec = st.st_ctim.tv_sec; stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec; - stx->stx_btime = (struct statx_timestamp){.tv_sec=0, .tv_nsec=0}; stx->stx_mask = STATX_BASIC_STATS; return 0; diff --git a/src/locale/bind_textdomain_codeset.c b/src/locale/bind_textdomain_codeset.c index 5ebfd5e8..240e83ed 100644 --- a/src/locale/bind_textdomain_codeset.c +++ b/src/locale/bind_textdomain_codeset.c @@ -5,7 +5,9 @@ char *bind_textdomain_codeset(const char *domainname, const char *codeset) { - if (codeset && strcasecmp(codeset, "UTF-8")) + if (codeset && strcasecmp(codeset, "UTF-8")) { errno = EINVAL; - return NULL; + return 0; + } + return "UTF-8"; } diff --git a/src/locale/codepages.h b/src/locale/codepages.h index 4e236ef3..a254f0f5 100644 --- a/src/locale/codepages.h +++ b/src/locale/codepages.h @@ -286,6 +286,17 @@ "\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55" "\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50" +"cp858\0" +"\0\40" +"\307\360\223\216\70\344\200\123\316\71\352\254\203\316\73\356\260\103\114\61" +"\311\230\143\14\75\366\310\263\117\76\377\130\303\15\76\243\140\163\15\135" +"\341\264\63\217\76\361\104\243\212\56\277\270\302\112\57\274\204\262\312\56" +"\140\207\55\66\315\72\7\43\14\60\251\104\375\163\321\113\213\122\212\315" +"\67\363\274\163\316\63\367\74\316\60\110\13\175\65\325\116\373\254\65\51" +"\360\100\243\314\62\310\220\334\214\63\317\340\134\163\327\134\233\302\314\326" +"\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55" +"\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50" + "cp866\0" "\0\40" "\337\201\27\236\170\343\221\127\236\171\347\241\227\236\172" diff --git a/src/locale/iconv.c b/src/locale/iconv.c index 7fb2e1ef..52178950 100644 --- a/src/locale/iconv.c +++ b/src/locale/iconv.c @@ -339,6 +339,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri } else if (d-159 <= 252-159) { c++; d -= 159; + } else { + goto ilseq; } if (c>=84) goto ilseq; c = jis0208[c][d]; @@ -500,7 +502,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (c >= 93 || d >= 94) { c += (0xa1-0x81); d += 0xa1; - if (c >= 93 || c>=0xc6-0x81 && d>0x52) + if (c > 0xc6-0x81 || c==0xc6-0x81 && d>0x52) goto ilseq; if (d-'A'<26) d = d-'A'; else if (d-'a'<26) d = d-'a'+26; @@ -543,6 +545,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (*outb < k) goto toobig; memcpy(*out, tmp, k); } else k = wctomb_utf8(*out, c); + /* This failure condition should be unreachable, but + * is included to prevent decoder bugs from translating + * into advancement outside the output buffer range. */ + if (k>4) goto ilseq; *out += k; *outb -= k; break; diff --git a/src/math/powl.c b/src/math/powl.c index 6f64ea71..9eb22162 100644 --- a/src/math/powl.c +++ b/src/math/powl.c @@ -57,14 +57,6 @@ * IEEE 0,8700 60000 6.5e-18 1.0e-18 * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed. * - * - * ERROR MESSAGES: - * - * message condition value returned - * pow overflow x**y > MAXNUM INFINITY - * pow underflow x**y < 1/MAXNUM 0.0 - * pow domain x<0 and y noninteger 0.0 - * */ #include "libm.h" diff --git a/src/misc/mntent.c b/src/misc/mntent.c index 78bf0cd0..76f9c162 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -81,7 +81,7 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle len = strlen(linebuf); if (len > INT_MAX) continue; for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len; - sscanf(linebuf, " %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %d %d", + sscanf(linebuf, " %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %d %d", n, n+1, n+2, n+3, n+4, n+5, n+6, n+7, &mnt->mnt_freq, &mnt->mnt_passno); } while (linebuf[n[0]] == '#' || n[1]==len); @@ -115,5 +115,13 @@ int addmntent(FILE *f, const struct mntent *mnt) char *hasmntopt(const struct mntent *mnt, const char *opt) { - return strstr(mnt->mnt_opts, opt); + size_t l = strlen(opt); + char *p = mnt->mnt_opts; + for (;;) { + if (!strncmp(p, opt, l) && (!p[l] || p[l]==',' || p[l]=='=')) + return p; + p = strchr(p, ','); + if (!p) return 0; + p++; + } } diff --git a/src/mq/x32/mq_open.c b/src/mq/x32/mq_open.c new file mode 100644 index 00000000..23481959 --- /dev/null +++ b/src/mq/x32/mq_open.c @@ -0,0 +1,22 @@ +#include <mqueue.h> +#include <fcntl.h> +#include <stdarg.h> +#include "syscall.h" + +mqd_t mq_open(const char *name, int flags, ...) +{ + mode_t mode = 0; + struct mq_attr *attr = 0; + long long attrbuf[8]; + if (*name == '/') name++; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, mode_t); + attr = va_arg(ap, struct mq_attr *); + if (attr) for (int i=0; i<8; i++) + attrbuf[i] = *(long *)((char *)attr + i*sizeof(long)); + va_end(ap); + } + return syscall(SYS_mq_open, name, flags, mode, attr?attrbuf:0); +} diff --git a/src/mq/x32/mq_setattr.c b/src/mq/x32/mq_setattr.c new file mode 100644 index 00000000..0c631175 --- /dev/null +++ b/src/mq/x32/mq_setattr.c @@ -0,0 +1,14 @@ +#include <mqueue.h> +#include "syscall.h" + +int mq_setattr(mqd_t mqd, const struct mq_attr *restrict new, struct mq_attr *restrict old) +{ + long long attr[8]; + if (new) for (int i=0; i<8; i++) + attr[i] = *(long *)((char *)new + i*sizeof(long)); + int ret = __syscall(SYS_mq_getsetattr, mqd, new?attr:0, old?attr:0); + if (ret < 0) return __syscall_ret(ret); + if (old) for (int i=0; i<8; i++) + *(long *)((char *)old + i*sizeof(long)) = attr[i]; + return 0; +} diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c index 931192e2..47cbdc00 100644 --- a/src/multibyte/mbsnrtowcs.c +++ b/src/multibyte/mbsnrtowcs.c @@ -2,11 +2,13 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, size_t wn, mbstate_t *restrict st) { + static unsigned internal_state; size_t l, cnt=0, n2; wchar_t *ws, wbuf[256]; const char *s = *src; const char *tmp_s; + if (!st) st = (void *)&internal_state; if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf; else ws = wcs; @@ -41,8 +43,8 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, si s = 0; break; } - /* have to roll back partial character */ - *(unsigned *)st = 0; + s += n; + n -= n; break; } s += l; n -= l; diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c index 4bfef2c5..f442f47d 100644 --- a/src/network/inet_ntop.c +++ b/src/network/inet_ntop.c @@ -34,7 +34,12 @@ const char *inet_ntop(int af, const void *restrict a0, char *restrict s, socklen for (i=best=0, max=2; buf[i]; i++) { if (i && buf[i] != ':') continue; j = strspn(buf+i, ":0"); - if (j>max) best=i, max=j; + /* The leading sequence of zeros (best==0) is + * disadvantaged compared to sequences elsewhere + * as it doesn't have a leading colon. One extra + * character is required for another sequence to + * beat it fairly. */ + if (j>max+(best==0)) best=i, max=j; } if (max>3) { buf[best] = buf[best+1] = ':'; diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 86c2fcf4..fcb52513 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -83,8 +83,8 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, int fd; int timeout, attempts, retry_interval, servfail_retry; union { - struct sockaddr_in sin; struct sockaddr_in6 sin6; + struct sockaddr_in sin; } sa = {0}, ns[MAXNS] = {{0}}; socklen_t sl = sizeof sa.sin; int nns = 0; diff --git a/src/signal/riscv32/restore.s b/src/signal/riscv32/restore.s index 40012c75..5a0af695 100644 --- a/src/signal/riscv32/restore.s +++ b/src/signal/riscv32/restore.s @@ -1,7 +1,9 @@ .global __restore +.hidden __restore .type __restore, %function __restore: .global __restore_rt +.hidden __restore_rt .type __restore_rt, %function __restore_rt: li a7, 139 # SYS_rt_sigreturn diff --git a/src/signal/riscv64/restore.s b/src/signal/riscv64/restore.s index 40012c75..5a0af695 100644 --- a/src/signal/riscv64/restore.s +++ b/src/signal/riscv64/restore.s @@ -1,7 +1,9 @@ .global __restore +.hidden __restore .type __restore, %function __restore: .global __restore_rt +.hidden __restore_rt .type __restore_rt, %function __restore_rt: li a7, 139 # SYS_rt_sigreturn diff --git a/src/signal/sigaltstack.c b/src/signal/sigaltstack.c index d3a6e821..616625c5 100644 --- a/src/signal/sigaltstack.c +++ b/src/signal/sigaltstack.c @@ -1,11 +1,13 @@ #include <signal.h> #include <errno.h> +#include <unistd.h> #include "syscall.h" int sigaltstack(const stack_t *restrict ss, stack_t *restrict old) { if (ss) { - if (!(ss->ss_flags & SS_DISABLE) && ss->ss_size < MINSIGSTKSZ) { + size_t min = sysconf(_SC_MINSIGSTKSZ); + if (!(ss->ss_flags & SS_DISABLE) && ss->ss_size < min) { errno = ENOMEM; return -1; } diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c index bc317acc..53789b23 100644 --- a/src/signal/siglongjmp.c +++ b/src/signal/siglongjmp.c @@ -5,5 +5,10 @@ _Noreturn void siglongjmp(sigjmp_buf buf, int ret) { + /* If sigsetjmp was called with nonzero savemask flag, the address + * longjmp will return to is inside of sigsetjmp. The signal mask + * will then be restored in the returned-to context instead of here, + * which matters if the context we are returning from may not have + * sufficient stack space for signal delivery. */ longjmp(buf, ret); } diff --git a/src/signal/sigpause.c b/src/signal/sigpause.c index 363d2fec..1587c391 100644 --- a/src/signal/sigpause.c +++ b/src/signal/sigpause.c @@ -4,6 +4,6 @@ int sigpause(int sig) { sigset_t mask; sigprocmask(0, 0, &mask); - sigdelset(&mask, sig); + if (sigdelset(&mask, sig)) return -1; return sigsuspend(&mask); } diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c index d2d89475..5356553d 100644 --- a/src/stdio/__stdio_write.c +++ b/src/stdio/__stdio_write.c @@ -11,6 +11,11 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len) size_t rem = iov[0].iov_len + iov[1].iov_len; int iovcnt = 2; ssize_t cnt; + + if (!iov->iov_len) { + iov++; + iovcnt--; + } for (;;) { cnt = syscall(SYS_writev, f->fd, iov, iovcnt); if (cnt == rem) { diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 360d723a..76733997 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -178,10 +178,14 @@ static char *fmt_u(uintmax_t x, char *s) typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; #endif -static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) +static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t, int ps) { - uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion - + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion + int bufsize = (ps==BIGLPRE) + ? (LDBL_MANT_DIG+28)/29 + 1 + // mantissa expansion + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9 // exponent expansion + : (DBL_MANT_DIG+28)/29 + 1 + + (DBL_MAX_EXP+DBL_MANT_DIG+28+8)/9; + uint32_t big[bufsize]; uint32_t *a, *d, *r, *z; int e2=0, e, i, j, l; char buf[9+LDBL_MANT_DIG/4], *s; @@ -557,11 +561,11 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, case 'x': case 'X': a = fmt_x(arg.i, z, t&32); if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2; - if (0) { + goto ifmt_tail; case 'o': a = fmt_o(arg.i, z); if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1; - } if (0) { + goto ifmt_tail; case 'd': case 'i': pl=1; if (arg.i>INTMAX_MAX) { @@ -573,7 +577,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, } else pl=0; case 'u': a = fmt_u(arg.i, z); - } + ifmt_tail: if (xp && p<0) goto overflow; if (xp) fl &= ~ZERO_PAD; if (!arg.i && !p) { @@ -618,7 +622,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, case 'e': case 'f': case 'g': case 'a': case 'E': case 'F': case 'G': case 'A': if (xp && p<0) goto overflow; - l = fmt_fp(f, arg.f, w, p, fl, t); + l = fmt_fp(f, arg.f, w, p, fl, t, ps); if (l<0) goto overflow; continue; } diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c index 314ddc29..ab79dc6f 100644 --- a/src/stdlib/qsort.c +++ b/src/stdlib/qsort.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 by Valentin Ochs +/* Copyright (C) 2011 by Lynn Ochs * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to diff --git a/src/string/strcasestr.c b/src/string/strcasestr.c index af109f36..dc598bc3 100644 --- a/src/string/strcasestr.c +++ b/src/string/strcasestr.c @@ -4,6 +4,7 @@ char *strcasestr(const char *h, const char *n) { size_t l = strlen(n); + if (!l) return (char *)h; for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h; return 0; } diff --git a/src/termios/cfgetospeed.c b/src/termios/cfgetospeed.c index 55fa6f55..de46a1d8 100644 --- a/src/termios/cfgetospeed.c +++ b/src/termios/cfgetospeed.c @@ -9,5 +9,5 @@ speed_t cfgetospeed(const struct termios *tio) speed_t cfgetispeed(const struct termios *tio) { - return cfgetospeed(tio); + return (tio->c_cflag & CIBAUD) / (CIBAUD/CBAUD); } diff --git a/src/termios/cfsetospeed.c b/src/termios/cfsetospeed.c index c9cbdd9d..3eab092a 100644 --- a/src/termios/cfsetospeed.c +++ b/src/termios/cfsetospeed.c @@ -16,7 +16,11 @@ int cfsetospeed(struct termios *tio, speed_t speed) int cfsetispeed(struct termios *tio, speed_t speed) { - return speed ? cfsetospeed(tio, speed) : 0; + if (speed & ~CBAUD) { + errno = EINVAL; + return -1; + } + tio->c_cflag &= ~CIBAUD; + tio->c_cflag |= speed * (CIBAUD/CBAUD); + return 0; } - -weak_alias(cfsetospeed, cfsetspeed); diff --git a/src/termios/cfsetspeed.c b/src/termios/cfsetspeed.c new file mode 100644 index 00000000..2c369db9 --- /dev/null +++ b/src/termios/cfsetspeed.c @@ -0,0 +1,11 @@ +#define _BSD_SOURCE +#include <termios.h> +#include <sys/ioctl.h> +#include <errno.h> + +int cfsetspeed(struct termios *tio, speed_t speed) +{ + int r = cfsetospeed(tio, speed); + if (!r) cfsetispeed(tio, 0); + return r; +} diff --git a/src/thread/aarch64/clone.s b/src/thread/aarch64/clone.s index e3c83395..9ac272bd 100644 --- a/src/thread/aarch64/clone.s +++ b/src/thread/aarch64/clone.s @@ -24,7 +24,8 @@ __clone: // parent ret // child -1: ldp x1,x0,[sp],#16 +1: mov fp, 0 + ldp x1,x0,[sp],#16 blr x1 mov x8,#93 // SYS_exit svc #0 diff --git a/src/thread/arm/clone.s b/src/thread/arm/clone.s index bb0965da..4ff0c0e8 100644 --- a/src/thread/arm/clone.s +++ b/src/thread/arm/clone.s @@ -19,7 +19,8 @@ __clone: ldmfd sp!,{r4,r5,r6,r7} bx lr -1: mov r0,r6 +1: mov fp,#0 + mov r0,r6 bl 3f 2: mov r7,#1 svc 0 diff --git a/src/thread/loongarch64/clone.s b/src/thread/loongarch64/clone.s index a165b365..cb4aacfc 100644 --- a/src/thread/loongarch64/clone.s +++ b/src/thread/loongarch64/clone.s @@ -22,6 +22,7 @@ __clone: beqz $a0, 1f # whether child process jirl $zero, $ra, 0 # parent process return 1: + move $fp, $zero ld.d $t8, $sp, 0 # function pointer ld.d $a0, $sp, 8 # argument pointer jirl $ra, $t8, 0 # call the user's function diff --git a/src/thread/m68k/clone.s b/src/thread/m68k/clone.s index f6dfa06f..0134cf4e 100644 --- a/src/thread/m68k/clone.s +++ b/src/thread/m68k/clone.s @@ -18,7 +18,8 @@ __clone: beq 1f movem.l (%sp)+,%d2-%d5 rts -1: move.l %a1,-(%sp) +1: suba.l %fp,%fp + move.l %a1,-(%sp) jsr (%a0) move.l #1,%d0 trap #0 diff --git a/src/thread/microblaze/clone.s b/src/thread/microblaze/clone.s index b68cc5fc..64e3f074 100644 --- a/src/thread/microblaze/clone.s +++ b/src/thread/microblaze/clone.s @@ -22,7 +22,8 @@ __clone: rtsd r15, 8 nop -1: lwi r3, r1, 0 +1: add r19, r0, r0 + lwi r3, r1, 0 lwi r5, r1, 4 brald r15, r3 nop diff --git a/src/thread/mips/clone.s b/src/thread/mips/clone.s index 04463385..229b987e 100644 --- a/src/thread/mips/clone.s +++ b/src/thread/mips/clone.s @@ -27,7 +27,8 @@ __clone: addu $sp, $sp, 16 jr $ra nop -1: lw $25, 0($sp) +1: move $fp, $0 + lw $25, 0($sp) lw $4, 4($sp) jalr $25 nop diff --git a/src/thread/mips64/clone.s b/src/thread/mips64/clone.s index 2d86899a..8de3db6c 100644 --- a/src/thread/mips64/clone.s +++ b/src/thread/mips64/clone.s @@ -25,7 +25,8 @@ __clone: nop jr $ra nop -1: ld $25, 0($sp) # function pointer +1: move $fp, $0 + ld $25, 0($sp) # function pointer ld $4, 8($sp) # argument pointer jalr $25 # call the user's function nop diff --git a/src/thread/mipsn32/clone.s b/src/thread/mipsn32/clone.s index 4d3c8c7a..9571231a 100644 --- a/src/thread/mipsn32/clone.s +++ b/src/thread/mipsn32/clone.s @@ -25,7 +25,8 @@ __clone: nop jr $ra nop -1: lw $25, 0($sp) # function pointer +1: move $fp, $0 + lw $25, 0($sp) # function pointer lw $4, 4($sp) # argument pointer jalr $25 # call the user's function nop diff --git a/src/thread/or1k/clone.s b/src/thread/or1k/clone.s index 2473ac20..b41488a2 100644 --- a/src/thread/or1k/clone.s +++ b/src/thread/or1k/clone.s @@ -6,6 +6,8 @@ .hidden __clone .type __clone,@function __clone: + l.xori r11, r0, -4 + l.and r4, r4, r11 l.addi r4, r4, -8 l.sw 0(r4), r3 l.sw 4(r4), r6 @@ -23,7 +25,8 @@ __clone: l.jr r9 l.nop -1: l.lwz r11, 0(r1) +1: l.ori r2, r0, 0 + l.lwz r11, 0(r1) l.jalr r11 l.lwz r3, 4(r1) diff --git a/src/thread/riscv32/clone.s b/src/thread/riscv32/clone.s index 3102239d..e2116e33 100644 --- a/src/thread/riscv32/clone.s +++ b/src/thread/riscv32/clone.s @@ -8,6 +8,7 @@ .type __clone, %function __clone: # Save func and arg to stack + andi a1, a1, -16 addi a1, a1, -16 sw a0, 0(a1) sw a3, 4(a1) diff --git a/src/thread/riscv64/clone.s b/src/thread/riscv64/clone.s index db908248..0e6f41a8 100644 --- a/src/thread/riscv64/clone.s +++ b/src/thread/riscv64/clone.s @@ -8,6 +8,7 @@ .type __clone, %function __clone: # Save func and arg to stack + andi a1, a1, -16 addi a1, a1, -16 sd a0, 0(a1) sd a3, 8(a1) diff --git a/src/thread/s390x/__tls_get_offset.s b/src/thread/s390x/__tls_get_offset.s index 8ee92de8..405f118b 100644 --- a/src/thread/s390x/__tls_get_offset.s +++ b/src/thread/s390x/__tls_get_offset.s @@ -1,17 +1,17 @@ .global __tls_get_offset .type __tls_get_offset,%function __tls_get_offset: - stmg %r14, %r15, 112(%r15) - aghi %r15, -160 + ear %r0, %a0 + sllg %r0, %r0, 32 + ear %r0, %a1 - la %r2, 0(%r2, %r12) - brasl %r14, __tls_get_addr + la %r1, 0(%r2, %r12) - ear %r1, %a0 - sllg %r1, %r1, 32 - ear %r1, %a1 + lg %r3, 0(%r1) + sllg %r4, %r3, 3 + lg %r5, 8(%r0) + lg %r2, 0(%r4, %r5) + ag %r2, 8(%r1) + sgr %r2, %r0 - sgr %r2, %r1 - - lmg %r14, %r15, 272(%r15) br %r14 diff --git a/src/thread/sem_post.c b/src/thread/sem_post.c index 5c2517f2..1c8f763c 100644 --- a/src/thread/sem_post.c +++ b/src/thread/sem_post.c @@ -16,6 +16,6 @@ int sem_post(sem_t *sem) if (waiters <= 1) new &= ~0x80000000; } while (a_cas(sem->__val, val, new) != val); - if (val<0) __wake(sem->__val, waiters>1 ? 1 : -1, priv); + if (val<0 || waiters) __wake(sem->__val, waiters>1 ? 1 : -1, priv); return 0; } diff --git a/src/time/__tz.c b/src/time/__tz.c index c34b3eb7..54ed4cf6 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -24,7 +24,6 @@ weak_alias(__tzname, tzname); static char std_name[TZNAME_MAX+1]; static char dst_name[TZNAME_MAX+1]; -const char __utc[] = "UTC"; static int dst_off; static int r0[5], r1[5]; diff --git a/src/time/__utc.c b/src/time/__utc.c new file mode 100644 index 00000000..9e8bfc58 --- /dev/null +++ b/src/time/__utc.c @@ -0,0 +1,3 @@ +#include "time_impl.h" + +const char __utc[] = "UTC"; diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 9216b3ab..cc6c2236 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -1,6 +1,7 @@ #include <time.h> #include <setjmp.h> #include <limits.h> +#include <semaphore.h> #include "pthread_impl.h" #include "atomic.h" @@ -12,7 +13,7 @@ struct ksigevent { }; struct start_args { - pthread_barrier_t b; + sem_t sem1, sem2; struct sigevent *sev; }; @@ -21,10 +22,16 @@ static void dummy_0() } weak_alias(dummy_0, __pthread_tsd_run_dtors); +static void timer_handler(int sig, siginfo_t *si, void *ctx) +{ +} + static void cleanup_fromsig(void *p) { pthread_t self = __pthread_self(); __pthread_tsd_run_dtors(); + __block_app_sigs(0); + __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGTIMER_SET, 0, _NSIG/8); self->cancel = 0; self->cancelbuf = 0; self->canceldisable = 0; @@ -42,7 +49,14 @@ static void *start(void *arg) void (*notify)(union sigval) = args->sev->sigev_notify_function; union sigval val = args->sev->sigev_value; - pthread_barrier_wait(&args->b); + /* The two-way semaphore synchronization ensures that we see + * self->cancel set by the parent if timer creation failed or + * self->timer_id if it succeeded, and informs the parent that + * we are done accessing the arguments so that the parent can + * proceed past their block lifetime. */ + while (sem_wait(&args->sem1)); + sem_post(&args->sem2); + if (self->cancel) return 0; for (;;) { @@ -90,7 +104,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict break; case SIGEV_THREAD: if (!init) { - struct sigaction sa = { .sa_handler = SIG_DFL }; + struct sigaction sa = { + .sa_sigaction = timer_handler, + .sa_flags = SA_SIGINFO | SA_RESTART + }; __libc_sigaction(SIGTIMER, &sa, 0); a_store(&init, 1); } @@ -99,7 +116,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict else pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_barrier_init(&args.b, 0, 2); + sem_init(&args.sem1, 0, 0); + sem_init(&args.sem2, 0, 0); args.sev = evp; __block_app_sigs(&set); @@ -120,7 +138,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict td->cancel = 1; } td->timer_id = timerid; - pthread_barrier_wait(&args.b); + sem_post(&args.sem1); + while (sem_wait(&args.sem2)); if (timerid < 0) return -1; *res = (void *)(INTPTR_MIN | (uintptr_t)td>>1); break; diff --git a/src/unistd/isatty.c b/src/unistd/isatty.c index 75a9c186..21222eda 100644 --- a/src/unistd/isatty.c +++ b/src/unistd/isatty.c @@ -6,8 +6,6 @@ int isatty(int fd) { struct winsize wsz; - unsigned long r = syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz); - if (r == 0) return 1; - if (errno != EBADF) errno = ENOTTY; - return 0; + /* +1 converts from error status (0/-1) to boolean (1/0) */ + return syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz) + 1; } diff --git a/src/unistd/pause.c b/src/unistd/pause.c index 90bbf4ca..90cc8db5 100644 --- a/src/unistd/pause.c +++ b/src/unistd/pause.c @@ -3,9 +3,5 @@ int pause(void) { -#ifdef SYS_pause - return syscall_cp(SYS_pause); -#else - return syscall_cp(SYS_ppoll, 0, 0, 0, 0); -#endif + return sys_pause_cp(); } |