diff --git a/configure b/configure index 03c193d..0cff13d 100755 --- a/configure +++ b/configure @@ -123,7 +123,7 @@ target= optimize=auto debug=no warnings=no -shared=yes +shared=auto static=yes wrapper=auto @@ -412,12 +412,15 @@ fi tryflag CFLAGS_AUTO -fno-stack-protector tryldflag LDFLAGS_AUTO -Wl,--hash-style=both +test "$shared" = "no" || { # Disable dynamic linking if ld is broken and can't do -Bsymbolic-functions LDFLAGS_DUMMY= tryldflag LDFLAGS_DUMMY -Wl,-Bsymbolic-functions || { +test "$shared" = "yes" && fail "$0: error: linker cannot build shared library" printf "warning: disabling dynamic linking support\n" shared=no } +} # Find compiler runtime library test -z "$LIBCC" && tryldflag LIBCC -lgcc && tryldflag LIBCC -lgcc_eh diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c index 89d081e..f7eab8d 100644 --- a/src/env/__init_tls.c +++ b/src/env/__init_tls.c @@ -11,17 +11,11 @@ int __init_tp(void *p) { pthread_t td = p; td->self = td; - if (__set_thread_area(TP_ADJ(p)) < 0) - return -1; - td->tid = td->pid = __syscall(SYS_set_tid_address, &td->tid); - td->errno_ptr = &td->errno_val; - /* Currently, both of these predicates depend in the same thing: - * successful initialization of the thread pointer. However, in - * the future, we may support setups where setting the thread - * pointer is possible but threads other than the main thread - * cannot work, so it's best to keep the predicates separate. */ + int r = __set_thread_area(TP_ADJ(p)); + if (r < 0) return -1; + if (!r) libc.can_do_threads = 1; libc.has_thread_pointer = 1; - libc.can_do_threads = 1; + td->tid = td->pid = __syscall(SYS_set_tid_address, &td->tid); return 0; } diff --git a/src/errno/__errno_location.c b/src/errno/__errno_location.c index 8419107..49654ef 100644 --- a/src/errno/__errno_location.c +++ b/src/errno/__errno_location.c @@ -3,6 +3,6 @@ int *__errno_location(void) { static int e; - if (libc.has_thread_pointer) return __pthread_self()->errno_ptr; + if (libc.has_thread_pointer) return &__pthread_self()->errno_val; return &e; } diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 2e910b3..650e811 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -18,7 +18,7 @@ struct pthread { uintptr_t sysinfo; uintptr_t canary; pid_t tid, pid; - int tsd_used, errno_val, *errno_ptr; + int tsd_used, errno_val; volatile int cancel, canceldisable, cancelasync; int detached; unsigned char *map_base; diff --git a/src/locale/uselocale.c b/src/locale/uselocale.c index 224ef38..4fc5c64 100644 --- a/src/locale/uselocale.c +++ b/src/locale/uselocale.c @@ -4,7 +4,7 @@ locale_t uselocale(locale_t l) { - pthread_t self = pthread_self(); + pthread_t self = __pthread_self(); locale_t old = self->locale; if (l) self->locale = l; return old; diff --git a/src/misc/getopt.c b/src/misc/getopt.c index f1a1639..8a2e4d5 100644 --- a/src/misc/getopt.c +++ b/src/misc/getopt.c @@ -65,8 +65,11 @@ int getopt(int argc, char * const argv[], const char *optstring) } return '?'; } - optarg = argv[optind++] + optpos; - optpos = 0; + if (optstring[i+2] == ':') optarg = 0; + if (optstring[i+2] != ':' || optpos) { + optarg = argv[optind++] + optpos; + optpos = 0; + } } return c; } diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 5192b4d..35f106d 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -34,7 +34,7 @@ int __res_msend(int nqueries, const unsigned char *const *queries, FILE *f, _f; unsigned char _buf[256]; char line[64], *s, *z; - int timeout = 5000, attempts = 2, retry_interval; + int timeout = 5000, attempts = 2, retry_interval, servfail_retry; union { struct sockaddr_in sin; struct sockaddr_in6 sin6; @@ -152,6 +152,7 @@ int __res_msend(int nqueries, const unsigned char *const *queries, qlens[i], MSG_NOSIGNAL, (void *)&ns[j], sl); t1 = t2; + servfail_retry = 2 * nqueries; } /* Wait for a response, or until time to retry */ @@ -160,12 +161,12 @@ int __res_msend(int nqueries, const unsigned char *const *queries, while ((rlen = recvfrom(fd, answers[next], asize, 0, (void *)&sa, (socklen_t[1]){sl})) >= 0) { - /* Ignore non-identifiable packets (no query id) */ - if (rlen < 2) continue; + /* Ignore non-identifiable packets */ + if (rlen < 4) continue; /* Ignore replies from addresses we didn't send to */ - for (i=0; itid; + int tid = __pthread_self()->tid; if (f->lock == tid) { if (f->lockcount == LONG_MAX) return -1; diff --git a/src/thread/cancel_impl.c b/src/thread/cancel_impl.c index 525d290..41cf2b8 100644 --- a/src/thread/cancel_impl.c +++ b/src/thread/cancel_impl.c @@ -58,7 +58,7 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx) void __testcancel() { if (!libc.has_thread_pointer) return; - pthread_t self = pthread_self(); + pthread_t self = __pthread_self(); if (self->cancel && !self->canceldisable) __cancel(); } diff --git a/src/thread/i386/__set_thread_area.s b/src/thread/i386/__set_thread_area.s index cccf1cd..ad53815 100644 --- a/src/thread/i386/__set_thread_area.s +++ b/src/thread/i386/__set_thread_area.s @@ -12,11 +12,25 @@ __set_thread_area: mov $243,%al int $128 testl %eax,%eax - jnz 1f - movl (%esp),%ecx - leal 3(,%ecx,8),%ecx - movw %cx,%gs + jnz 2f + movl (%esp),%edx + leal 3(,%edx,8),%edx +3: movw %dx,%gs 1: addl $16,%esp popl %ebx ret +2: + mov %ebx,%ecx + xor %ebx,%ebx + xor %edx,%edx + mov %ebx,(%esp) + mov $1,%bl + mov $16,%dl + mov $123,%al + int $128 + testl %eax,%eax + jnz 1b + mov $7,%dl + inc %al + jmp 3b diff --git a/src/thread/pthread_cond_broadcast.c b/src/thread/pthread_cond_broadcast.c index 848e288..0901daf 100644 --- a/src/thread/pthread_cond_broadcast.c +++ b/src/thread/pthread_cond_broadcast.c @@ -28,7 +28,7 @@ int pthread_cond_broadcast(pthread_cond_t *c) /* Perform the futex requeue, waking one waiter unless we know * that the calling thread holds the mutex. */ __syscall(SYS_futex, &c->_c_seq, FUTEX_REQUEUE, - !m->_m_type || (m->_m_lock&INT_MAX)!=pthread_self()->tid, + !m->_m_type || (m->_m_lock&INT_MAX)!=__pthread_self()->tid, INT_MAX, &m->_m_lock); out: diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index 1f25c8e..99d62cc 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -41,7 +41,7 @@ int pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restrict struct cm cm = { .c=c, .m=m }; int r, e=0, seq; - if (m->_m_type && (m->_m_lock&INT_MAX) != pthread_self()->tid) + if (m->_m_type && (m->_m_lock&INT_MAX) != __pthread_self()->tid) return EPERM; if (ts && ts->tv_nsec >= 1000000000UL) diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index e0b5ef1..e9c8160 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -13,7 +13,7 @@ weak_alias(dummy_0, __pthread_tsd_run_dtors); _Noreturn void pthread_exit(void *result) { - pthread_t self = pthread_self(); + pthread_t self = __pthread_self(); sigset_t set; self->result = result; @@ -78,7 +78,7 @@ _Noreturn void pthread_exit(void *result) void __do_cleanup_push(struct __ptcb *cb) { if (!libc.has_thread_pointer) return; - struct pthread *self = pthread_self(); + struct pthread *self = __pthread_self(); cb->__next = self->cancelbuf; self->cancelbuf = cb; } @@ -201,7 +201,6 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp new->stack = stack; new->stack_size = stack - stack_limit; new->pid = self->pid; - new->errno_ptr = &new->errno_val; new->start = entry; new->start_arg = arg; new->self = new; diff --git a/src/thread/pthread_mutex_consistent.c b/src/thread/pthread_mutex_consistent.c index 7dfb904..65da29f 100644 --- a/src/thread/pthread_mutex_consistent.c +++ b/src/thread/pthread_mutex_consistent.c @@ -3,7 +3,7 @@ int pthread_mutex_consistent(pthread_mutex_t *m) { if (m->_m_type < 8) return EINVAL; - if ((m->_m_lock & 0x3fffffff) != pthread_self()->tid) + if ((m->_m_lock & 0x3fffffff) != __pthread_self()->tid) return EPERM; m->_m_type -= 8; return 0; diff --git a/src/thread/pthread_mutex_timedlock.c b/src/thread/pthread_mutex_timedlock.c index c24270d..7b1afc0 100644 --- a/src/thread/pthread_mutex_timedlock.c +++ b/src/thread/pthread_mutex_timedlock.c @@ -10,7 +10,7 @@ int pthread_mutex_timedlock(pthread_mutex_t *restrict m, const struct timespec * while ((r=pthread_mutex_trylock(m)) == EBUSY) { if (!(r=m->_m_lock) || (r&0x40000000)) continue; if ((m->_m_type&3) == PTHREAD_MUTEX_ERRORCHECK - && (r&0x1fffffff) == pthread_self()->tid) + && (r&0x1fffffff) == __pthread_self()->tid) return EDEADLK; a_inc(&m->_m_waiters); diff --git a/src/thread/pthread_mutex_trylock.c b/src/thread/pthread_mutex_trylock.c index db784a7..00ad65d 100644 --- a/src/thread/pthread_mutex_trylock.c +++ b/src/thread/pthread_mutex_trylock.c @@ -8,7 +8,7 @@ int pthread_mutex_trylock(pthread_mutex_t *m) if (m->_m_type == PTHREAD_MUTEX_NORMAL) return a_cas(&m->_m_lock, 0, EBUSY) & EBUSY; - self = pthread_self(); + self = __pthread_self(); tid = self->tid; if (m->_m_type >= 4) { diff --git a/src/thread/pthread_mutex_unlock.c b/src/thread/pthread_mutex_unlock.c index 5fc0f4e..b4bd74b 100644 --- a/src/thread/pthread_mutex_unlock.c +++ b/src/thread/pthread_mutex_unlock.c @@ -13,7 +13,7 @@ int pthread_mutex_unlock(pthread_mutex_t *m) if (m->_m_type != PTHREAD_MUTEX_NORMAL) { if (!m->_m_lock) return EPERM; - self = pthread_self(); + self = __pthread_self(); if ((m->_m_lock&0x1fffffff) != self->tid) return EPERM; if ((m->_m_type&3) == PTHREAD_MUTEX_RECURSIVE && m->_m_count) diff --git a/src/thread/pthread_setcanceltype.c b/src/thread/pthread_setcanceltype.c index ce2fff0..bf0a3f3 100644 --- a/src/thread/pthread_setcanceltype.c +++ b/src/thread/pthread_setcanceltype.c @@ -2,7 +2,7 @@ int pthread_setcanceltype(int new, int *old) { - struct pthread *self = pthread_self(); + struct pthread *self = __pthread_self(); if (new > 1U) return EINVAL; if (old) *old = self->cancelasync; self->cancelasync = new; diff --git a/src/time/__tz.c b/src/time/__tz.c index 6d7173c..92c43a5 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -128,7 +128,7 @@ static void do_tzset() "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0"; s = getenv("TZ"); - if (!s || !*s) s = __gmt; + if (!s || !*s) s = "/etc/localtime"; if (old_tz && !strcmp(s, old_tz)) return; @@ -153,7 +153,8 @@ static void do_tzset() if (*s == ':' || ((p=strchr(s, '/')) && !memchr(s, ',', p-s))) { if (*s == ':') s++; if (*s == '/' || *s == '.') { - if (!libc.secure) map = __map_file(s, &map_size); + if (!libc.secure || !strcmp(s, "/etc/localtime")) + map = __map_file(s, &map_size); } else { size_t l = strlen(s); if (l <= NAME_MAX && !strchr(s, '.')) {