20 Commits dd1e63c363 ... 23ab04a863

Author SHA1 Message Date
  Rich Felker 23ab04a863 statx: add new struct statx fields and corresponding mask macros 2 months ago
  Rich Felker 4ca8c26776 statx: fix uninitialized attributes/mask in fallback path 2 months ago
  Gabriel Ravier 251cbb6366 statx: fix ENOSYS emulation not setting stx_rdev_* 2 months ago
  Rich Felker 8c43c56269 sysconf: fix _SC_MINSIGSTKSZ computation to match kernel interpretation 2 months ago
  Rich Felker 300a1f5390 sigaltstack: enforce dynamic MINSIGSTKSZ limit 2 months ago
  Rich Felker 572a2e2eb9 printf: drastically reduce stack usage without [long] double args 3 months ago
  Rich Felker c94a0c16f0 isatty: don't collapse all non-EBADF errors to ENOTTY 3 months ago
  Rich Felker ee18e584bf printf core: replace if(0) blocks around switch cases with explicit gotos 3 months ago
  Rich Felker 06a9647093 iconv: add cp858 3 months ago
  Rich Felker e1b57ede3e catan: remove no-op reduction mod pi and unused code 3 months ago
  Rich Felker ca4e632df4 remove incorrect comment regarding powl exceptional cases 3 months ago
  Rich Felker c851b268bd strerror: add error strings for EUCLEAN and ENAVAIL 3 months ago
  Rich Felker 9c78557af0 use hidden visibility for C entry point function _start_c 3 months ago
  Rich Felker 882aedf6a1 fix lost or delayed wakes in sem_post under certain race conditions 3 months ago
  Baruch Siach b09e3174a6 m68k: fix POLLWRNORM and POLLWRBAND 3 months ago
  Rich Felker 2de6b42605 fix missing make dependency for Scrt1.o due to typo 3 months ago
  Rich Felker cde213f9c3 timer_create: replace pthread barrier with semaphores for thread start 4 months ago
  Rich Felker 9ee6f10407 atexit: fail rather than deadlocking after last handler is called 4 months ago
  Rich Felker 8cca79a72c exit: add back lock to make concurrent calls to exit safe 4 months ago
  Rich Felker ef7d0ae212 move __utc string object to its own translation unit 4 months ago

+ 1 - 1
Makefile

@@ -109,7 +109,7 @@ obj/src/internal/version.o obj/src/internal/version.lo: obj/src/internal/version
 
 obj/crt/rcrt1.o obj/ldso/dlstart.lo obj/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
 
-obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
+obj/crt/crt1.o obj/crt/Scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
 
 obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart.c
 

+ 2 - 0
arch/m68k/bits/poll.h

@@ -0,0 +1,2 @@
+#define POLLWRNORM POLLOUT
+#define POLLWRBAND 256

+ 1 - 1
crt/crt1.c

@@ -11,7 +11,7 @@ weak void _fini();
 int __libc_start_main(int (*)(), int, char **,
 	void (*)(), void(*)(), void(*)());
 
-void _start_c(long *p)
+hidden void _start_c(long *p)
 {
 	int argc = p[0];
 	char **argv = (void *)(p+1);

+ 8 - 1
include/sys/stat.h

@@ -120,6 +120,9 @@ int lchmod(const char *, mode_t);
 #define STATX_BASIC_STATS 0x7ffU
 #define STATX_BTIME 0x800U
 #define STATX_ALL 0xfffU
+#define STATX_MNT_ID 0x1000U
+#define STATX_DIOALIGN 0x2000U
+#define STATX_MNT_ID_UNIQUE 0x4000U
 
 #define STATX_ATTR_COMPRESSED 0x4
 #define STATX_ATTR_IMMUTABLE 0x10
@@ -157,7 +160,11 @@ struct statx {
 	uint32_t stx_rdev_minor;
 	uint32_t stx_dev_major;
 	uint32_t stx_dev_minor;
-	uint64_t __pad1[14];
+	uint64_t stx_mnt_id;
+	uint32_t stx_dio_mem_align;
+	uint32_t stx_dio_offet_align;
+	uint64_t stx_subvol;
+	uint64_t __pad1[11];
 };
 
 int statx(int, const char *__restrict, int, unsigned, struct statx *__restrict);

+ 1 - 24
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);

+ 1 - 27
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);

+ 1 - 23
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);

+ 7 - 2
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;

+ 2 - 0
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")

+ 12 - 0
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;
 

+ 14 - 0
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 (;;) __syscall(SYS_pause);
+
 	__funcs_on_exit();
 	__libc_exit_fini();
 	__stdio_exit();

+ 3 - 1
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;

+ 11 - 0
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"

+ 0 - 8
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"

+ 3 - 1
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;
 		}

+ 11 - 7
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;
 		}

+ 1 - 1
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;
 }

+ 0 - 1
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];

+ 3 - 0
src/time/__utc.c

@@ -0,0 +1,3 @@
+#include "time_impl.h"
+
+const char __utc[] = "UTC";

+ 14 - 4
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;
 };
 
@@ -42,7 +43,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 (;;) {
@@ -99,7 +107,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 +129,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;

+ 2 - 4
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;
 }