20 Commits dd1e63c363 ... 23ab04a863

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

+ 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/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
 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 **,
 int __libc_start_main(int (*)(), int, char **,
 	void (*)(), void(*)(), void(*)());
 	void (*)(), void(*)(), void(*)());
 
 
-void _start_c(long *p)
+hidden void _start_c(long *p)
 {
 {
 	int argc = p[0];
 	int argc = p[0];
 	char **argv = (void *)(p+1);
 	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_BASIC_STATS 0x7ffU
 #define STATX_BTIME 0x800U
 #define STATX_BTIME 0x800U
 #define STATX_ALL 0xfffU
 #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_COMPRESSED 0x4
 #define STATX_ATTR_IMMUTABLE 0x10
 #define STATX_ATTR_IMMUTABLE 0x10
@@ -157,7 +160,11 @@ struct statx {
 	uint32_t stx_rdev_minor;
 	uint32_t stx_rdev_minor;
 	uint32_t stx_dev_major;
 	uint32_t stx_dev_major;
 	uint32_t stx_dev_minor;
 	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);
 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"
 #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 catan(double complex z)
 {
 {
 	double complex w;
 	double complex w;
@@ -95,7 +72,7 @@ double complex catan(double complex z)
 	a = 1.0 - x2 - (y * y);
 	a = 1.0 - x2 - (y * y);
 
 
 	t = 0.5 * atan2(2.0 * x, a);
 	t = 0.5 * atan2(2.0 * x, a);
-	w = _redupi(t);
+	w = t;
 
 
 	t = y - 1.0;
 	t = y - 1.0;
 	a = x2 + (t * t);
 	a = x2 + (t * t);

+ 1 - 27
src/complex/catanf.c

@@ -55,32 +55,6 @@
 
 
 #include "complex_impl.h"
 #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 catanf(float complex z)
 {
 {
 	float complex w;
 	float complex w;
@@ -93,7 +67,7 @@ float complex catanf(float complex z)
 	a = 1.0f - x2 - (y * y);
 	a = 1.0f - x2 - (y * y);
 
 
 	t = 0.5f * atan2f(2.0f * x, a);
 	t = 0.5f * atan2f(2.0f * x, a);
-	w = _redupif(t);
+	w = t;
 
 
 	t = y - 1.0f;
 	t = y - 1.0f;
 	a = x2 + (t * t);
 	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);
 	return catan(z);
 }
 }
 #else
 #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 catanl(long double complex z)
 {
 {
 	long double complex w;
 	long double complex w;
@@ -101,7 +79,7 @@ long double complex catanl(long double complex z)
 	a = 1.0L - x2 - (y * y);
 	a = 1.0L - x2 - (y * y);
 
 
 	t = atan2l(2.0L * x, a) * 0.5L;
 	t = atan2l(2.0L * x, a) * 0.5L;
-	w = redupil(t);
+	w = t;
 
 
 	t = y - 1.0L;
 	t = y - 1.0L;
 	a = x2 + (t * t);
 	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;
 		return (mem > LONG_MAX) ? LONG_MAX : mem;
 	case JT_MINSIGSTKSZ & 255:
 	case JT_MINSIGSTKSZ & 255:
 	case JT_SIGSTKSZ & 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)
 		if (values[name] == JT_SIGSTKSZ)
 			val += SIGSTKSZ - MINSIGSTKSZ;
 			val += SIGSTKSZ - MINSIGSTKSZ;
 		return val;
 		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(EALREADY,     "Operation already in progress")
 E(EINPROGRESS,  "Operation in progress")
 E(EINPROGRESS,  "Operation in progress")
 E(ESTALE,       "Stale file handle")
 E(ESTALE,       "Stale file handle")
+E(EUCLEAN,      "Data consistency error")
+E(ENAVAIL,      "Resource not available")
 E(EREMOTEIO,    "Remote I/O error")
 E(EREMOTEIO,    "Remote I/O error")
 E(EDQUOT,       "Quota exceeded")
 E(EDQUOT,       "Quota exceeded")
 E(ENOMEDIUM,    "No medium found")
 E(ENOMEDIUM,    "No medium found")

+ 12 - 0
src/exit/atexit.c

@@ -19,6 +19,7 @@ static struct fl
 	void *a[COUNT];
 	void *a[COUNT];
 } builtin, *head;
 } builtin, *head;
 
 
+static int finished_atexit;
 static int slot;
 static int slot;
 static volatile int lock[1];
 static volatile int lock[1];
 volatile int *const __atexit_lockptr = lock;
 volatile int *const __atexit_lockptr = lock;
@@ -34,6 +35,10 @@ void __funcs_on_exit()
 		func(arg);
 		func(arg);
 		LOCK(lock);
 		LOCK(lock);
 	}
 	}
+	/* Unlock to prevent deadlock if a global dtor
+	 * attempts to call atexit. */
+	finished_atexit = 1;
+	UNLOCK(lock);
 }
 }
 
 
 void __cxa_finalize(void *dso)
 void __cxa_finalize(void *dso)
@@ -44,6 +49,13 @@ int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
 {
 {
 	LOCK(lock);
 	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 */
 	/* Defer initialization of head so it can be in BSS */
 	if (!head) head = &builtin;
 	if (!head) head = &builtin;
 
 

+ 14 - 0
src/exit/exit.c

@@ -1,6 +1,9 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdint.h>
 #include "libc.h"
 #include "libc.h"
+#include "pthread_impl.h"
+#include "atomic.h"
+#include "syscall.h"
 
 
 static void dummy()
 static void dummy()
 {
 {
@@ -26,6 +29,17 @@ weak_alias(libc_exit_fini, __libc_exit_fini);
 
 
 _Noreturn void exit(int code)
 _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();
 	__funcs_on_exit();
 	__libc_exit_fini();
 	__libc_exit_fini();
 	__stdio_exit();
 	__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);
 	ret = fstatat(dirfd, path, &st, flags);
 	if (ret) return ret;
 	if (ret) return ret;
 
 
+	*stx = (struct statx){0};
 	stx->stx_dev_major = major(st.st_dev);
 	stx->stx_dev_major = major(st.st_dev);
 	stx->stx_dev_minor = minor(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_ino = st.st_ino;
 	stx->stx_mode = st.st_mode;
 	stx->stx_mode = st.st_mode;
 	stx->stx_nlink = st.st_nlink;
 	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_mtime.tv_nsec = st.st_mtim.tv_nsec;
 	stx->stx_ctime.tv_sec = st.st_ctim.tv_sec;
 	stx->stx_ctime.tv_sec = st.st_ctim.tv_sec;
 	stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec;
 	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;
 	stx->stx_mask = STATX_BASIC_STATS;
 
 
 	return 0;
 	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"
 "\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"
 "\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"
 "cp866\0"
 "\0\40"
 "\0\40"
 "\337\201\27\236\170\343\221\127\236\171\347\241\227\236\172"
 "\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
  *    IEEE     0,8700       60000      6.5e-18      1.0e-18
  * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.
  * 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"
 #include "libm.h"

+ 3 - 1
src/signal/sigaltstack.c

@@ -1,11 +1,13 @@
 #include <signal.h>
 #include <signal.h>
 #include <errno.h>
 #include <errno.h>
+#include <unistd.h>
 #include "syscall.h"
 #include "syscall.h"
 
 
 int sigaltstack(const stack_t *restrict ss, stack_t *restrict old)
 int sigaltstack(const stack_t *restrict ss, stack_t *restrict old)
 {
 {
 	if (ss) {
 	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;
 			errno = ENOMEM;
 			return -1;
 			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)];
 typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
 #endif
 #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;
 	uint32_t *a, *d, *r, *z;
 	int e2=0, e, i, j, l;
 	int e2=0, e, i, j, l;
 	char buf[9+LDBL_MANT_DIG/4], *s;
 	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':
 		case 'x': case 'X':
 			a = fmt_x(arg.i, z, t&32);
 			a = fmt_x(arg.i, z, t&32);
 			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
 			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
-			if (0) {
+			goto ifmt_tail;
 		case 'o':
 		case 'o':
 			a = fmt_o(arg.i, z);
 			a = fmt_o(arg.i, z);
 			if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
 			if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
-			} if (0) {
+			goto ifmt_tail;
 		case 'd': case 'i':
 		case 'd': case 'i':
 			pl=1;
 			pl=1;
 			if (arg.i>INTMAX_MAX) {
 			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;
 			} else pl=0;
 		case 'u':
 		case 'u':
 			a = fmt_u(arg.i, z);
 			a = fmt_u(arg.i, z);
-			}
+		ifmt_tail:
 			if (xp && p<0) goto overflow;
 			if (xp && p<0) goto overflow;
 			if (xp) fl &= ~ZERO_PAD;
 			if (xp) fl &= ~ZERO_PAD;
 			if (!arg.i && !p) {
 			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':
 		case 'E': case 'F': case 'G': case 'A':
 		case 'E': case 'F': case 'G': case 'A':
 			if (xp && p<0) goto overflow;
 			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;
 			if (l<0) goto overflow;
 			continue;
 			continue;
 		}
 		}

+ 1 - 1
src/thread/sem_post.c

@@ -16,6 +16,6 @@ int sem_post(sem_t *sem)
 		if (waiters <= 1)
 		if (waiters <= 1)
 			new &= ~0x80000000;
 			new &= ~0x80000000;
 	} while (a_cas(sem->__val, val, new) != val);
 	} 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;
 	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 std_name[TZNAME_MAX+1];
 static char dst_name[TZNAME_MAX+1];
 static char dst_name[TZNAME_MAX+1];
-const char __utc[] = "UTC";
 
 
 static int dst_off;
 static int dst_off;
 static int r0[5], r1[5];
 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 <time.h>
 #include <setjmp.h>
 #include <setjmp.h>
 #include <limits.h>
 #include <limits.h>
+#include <semaphore.h>
 #include "pthread_impl.h"
 #include "pthread_impl.h"
 #include "atomic.h"
 #include "atomic.h"
 
 
@@ -12,7 +13,7 @@ struct ksigevent {
 };
 };
 
 
 struct start_args {
 struct start_args {
-	pthread_barrier_t b;
+	sem_t sem1, sem2;
 	struct sigevent *sev;
 	struct sigevent *sev;
 };
 };
 
 
@@ -42,7 +43,14 @@ static void *start(void *arg)
 	void (*notify)(union sigval) = args->sev->sigev_notify_function;
 	void (*notify)(union sigval) = args->sev->sigev_notify_function;
 	union sigval val = args->sev->sigev_value;
 	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)
 	if (self->cancel)
 		return 0;
 		return 0;
 	for (;;) {
 	for (;;) {
@@ -99,7 +107,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
 		else
 		else
 			pthread_attr_init(&attr);
 			pthread_attr_init(&attr);
 		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 		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;
 		args.sev = evp;
 
 
 		__block_app_sigs(&set);
 		__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->cancel = 1;
 		}
 		}
 		td->timer_id = timerid;
 		td->timer_id = timerid;
-		pthread_barrier_wait(&args.b);
+		sem_post(&args.sem1);
+		while (sem_wait(&args.sem2));
 		if (timerid < 0) return -1;
 		if (timerid < 0) return -1;
 		*res = (void *)(INTPTR_MIN | (uintptr_t)td>>1);
 		*res = (void *)(INTPTR_MIN | (uintptr_t)td>>1);
 		break;
 		break;

+ 2 - 4
src/unistd/isatty.c

@@ -6,8 +6,6 @@
 int isatty(int fd)
 int isatty(int fd)
 {
 {
 	struct winsize wsz;
 	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;
 }
 }