From 645c59b3af41ec8a0d12ba99872f185bd96a3d98 Mon Sep 17 00:00:00 2001 From: Alexander Stefanov Date: Mon, 14 Sep 2020 19:56:04 +0000 Subject: [PATCH] 2.32 upgrade --- .abf.yml | 2 +- ...9591e5e8a129e7b73ad0dad3eecbd69482ff.patch | 95 + ...f2500825a84382c2a6a9ac60fc77954533d7.patch | 382 + eglibc-fedora-strict-aliasing.patch | 76 + eglibc-mandriva-ENOTTY-fr-translation.patch | 9 +- eglibc-mandriva-biarch-cpp-defines.patch | 17 - eglibc-mandriva-biarch-utils.patch | 57 - ...mandriva-fix-dns-with-broken-routers.patch | 12 - eglibc-mandriva-nscd-enable.patch | 11 - eglibc-mandriva-nscd-init-should-start.patch | 12 - eglibc-mandriva-string-format-fixes.patch | 44 + gcc-8-fix.patch | 28 - glibc-2.26-no-attribute-leaf-for-clang.patch | 11 - glibc-2.27-clang-_Float.patch | 81 - glibc-2.29-strict-aliasing.patch | 161 +- glibc-2.31.9000-aarch64-compile.patch | 11 + glibc-bench-build.patch | 41 + glibc-c_stubs.patch | 754 ++ glibc-disable-rwlock-elision.patch | 22 + glibc-fedora-__libc_multiple_libcs.patch | 29 +- glibc-fedora-getrlimit-PLT.patch | 45 + glibc-fedora-i386-tls-direct-seg-refs.patch | 18 - glibc-fedora-nptl-linklibc.patch | 25 - glibc-fedora-streams-rh436349.patch | 28 + glibc-fedora-uname-getrlimit.patch | 50 + glibc-new-condvar.patch | 6264 +++++++++++++++++ glibc-rh1315108.patch | 1946 +++++ glibc-rh1335011.patch | 176 + glibc-rtkaio-clock.patch | 102 + glibc-rtkaio-libof.patch | 26 + glibc-rtkaio.patch | 5015 +++++++++++++ glibc.spec | 246 +- glibc_post_upgrade.c | 310 - ldconfig-Os.patch | 31 + ldconfig-format-new.patch | 14 - nptl-getrlimit-compile.patch | 11 + nsswitch.conf | 5 +- 37 files changed, 15389 insertions(+), 778 deletions(-) create mode 100644 2efa9591e5e8a129e7b73ad0dad3eecbd69482ff.patch create mode 100644 4483f2500825a84382c2a6a9ac60fc77954533d7.patch create mode 100644 eglibc-fedora-strict-aliasing.patch delete mode 100644 eglibc-mandriva-biarch-cpp-defines.patch delete mode 100644 eglibc-mandriva-biarch-utils.patch delete mode 100644 eglibc-mandriva-fix-dns-with-broken-routers.patch delete mode 100644 eglibc-mandriva-nscd-enable.patch delete mode 100644 eglibc-mandriva-nscd-init-should-start.patch create mode 100644 eglibc-mandriva-string-format-fixes.patch delete mode 100644 gcc-8-fix.patch delete mode 100644 glibc-2.26-no-attribute-leaf-for-clang.patch delete mode 100644 glibc-2.27-clang-_Float.patch create mode 100644 glibc-2.31.9000-aarch64-compile.patch create mode 100644 glibc-bench-build.patch create mode 100644 glibc-c_stubs.patch create mode 100644 glibc-disable-rwlock-elision.patch create mode 100644 glibc-fedora-getrlimit-PLT.patch delete mode 100644 glibc-fedora-i386-tls-direct-seg-refs.patch delete mode 100644 glibc-fedora-nptl-linklibc.patch create mode 100644 glibc-fedora-streams-rh436349.patch create mode 100644 glibc-fedora-uname-getrlimit.patch create mode 100644 glibc-new-condvar.patch create mode 100644 glibc-rh1315108.patch create mode 100644 glibc-rh1335011.patch create mode 100644 glibc-rtkaio-clock.patch create mode 100644 glibc-rtkaio-libof.patch create mode 100644 glibc-rtkaio.patch delete mode 100644 glibc_post_upgrade.c create mode 100644 ldconfig-Os.patch delete mode 100644 ldconfig-format-new.patch create mode 100644 nptl-getrlimit-compile.patch diff --git a/.abf.yml b/.abf.yml index 0378069..fb3c498 100644 --- a/.abf.yml +++ b/.abf.yml @@ -1,3 +1,3 @@ sources: - glibc-2.31.tar.xz: 55619672e5e13996e264d408949eb4aaa26e7ec8 + glibc-2.32.tar.xz: 71ff0af28bdf4525d7b91ec5d82d1fc002000e91 glibc-manpages.tar.bz2: ca54bfb832b703c8e35170fcc1c1f5470b45ff0f diff --git a/2efa9591e5e8a129e7b73ad0dad3eecbd69482ff.patch b/2efa9591e5e8a129e7b73ad0dad3eecbd69482ff.patch new file mode 100644 index 0000000..645113e --- /dev/null +++ b/2efa9591e5e8a129e7b73ad0dad3eecbd69482ff.patch @@ -0,0 +1,95 @@ +From 2efa9591e5e8a129e7b73ad0dad3eecbd69482ff Mon Sep 17 00:00:00 2001 +From: "Pierre-Loup A. Griffais" +Date: Tue, 30 Jul 2019 16:44:27 -0700 +Subject: [PATCH] HACK: test app for pthread_mutex_lock_any(); should be + tst-mutex* something. + +--- + multimutextestapp/testapp.c | 78 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 78 insertions(+) + create mode 100644 multimutextestapp/testapp.c + +diff --git a/multimutextestapp/testapp.c b/multimutextestapp/testapp.c +new file mode 100644 +index 0000000000..eecf842dbc +--- /dev/null ++++ b/multimutextestapp/testapp.c +@@ -0,0 +1,78 @@ ++#include ++#include ++#include ++#include ++#include ++ ++ ++static pthread_mutex_t m[3]; ++ ++ ++static void * ++tf (void *arg) ++{ ++ int out; ++ int ret = pthread_mutex_lock_any( m, 3, &out ); ++ ++ printf("new thread ret %i out %i!\n", ret, out ); ++ ++ sleep(5); ++ printf("new thread done sleeping!\n"); ++ ++ pthread_mutex_unlock( &m[out] ); ++ ++ return NULL; ++} ++ ++ ++int main(int ac, char**av) ++{ ++ pthread_mutex_init (&m[0], NULL); ++ pthread_mutex_init (&m[1], NULL); ++ pthread_mutex_init (&m[2], NULL); ++ ++ int out; ++ ++ int ret = pthread_mutex_lock_any( m, 3, &out ); ++ ++ printf("main thread ret %i out %i!\n", ret, out ); ++ ++ ++ pthread_t th; ++ if (pthread_create (&th, NULL, tf, NULL) != 0) ++ { ++ puts ("create failed"); ++ return 1; ++ } ++ ++ sleep(1); ++ ++ ret = pthread_mutex_lock_any( m, 3, &out ); ++ ++ printf("main thread ret %i out %i!\n", ret, out ); ++ ++ sleep(1); ++ ++ struct timespec timeoutTime; ++ clock_gettime(CLOCK_REALTIME, &timeoutTime); ++ timeoutTime.tv_sec += 1; ++ ++ ret = pthread_mutex_timedlock_any( m, 3, &timeoutTime, &out ); ++ ++ printf("main thread ret %i out %i!\n", ret, out ); ++ ++ clock_gettime(CLOCK_REALTIME, &timeoutTime); ++ timeoutTime.tv_sec += 3; ++ ++ ret = pthread_mutex_timedlock_any( m, 3, &timeoutTime, &out ); ++ ++ printf("main thread ret %i out %i!\n", ret, out ); ++ ++ pthread_mutex_unlock( &m[out] ); ++ pthread_mutex_unlock( &m[0] ); ++ pthread_mutex_unlock( &m[2] ); ++ ++ printf("DONE unlock!\n"); ++ ++ return 0; ++} diff --git a/4483f2500825a84382c2a6a9ac60fc77954533d7.patch b/4483f2500825a84382c2a6a9ac60fc77954533d7.patch new file mode 100644 index 0000000..67b906e --- /dev/null +++ b/4483f2500825a84382c2a6a9ac60fc77954533d7.patch @@ -0,0 +1,382 @@ +From 4483f2500825a84382c2a6a9ac60fc77954533d7 Mon Sep 17 00:00:00 2001 +From: Mike Lothian +Date: Tue, 4 Feb 2020 11:04:42 +0000 +Subject: [PATCH] Implement pthread_mutex_lock_any() and + pthread_mutex_timedlock_any(). + +On newer Linux kernels, futex supports a WAIT_MULTIPLE operation that can be +used to implement new locking functionality that allows a given application +thread to sleep while waiting for one of multiple given locks to become +available. + +Patch-by: Pierre-Loup A. Griffais +Rebased-by: Mike Lothian +--- + nptl/Makefile | 1 + + nptl/Versions | 2 + + nptl/pthreadP.h | 5 + + nptl/pthread_mutex_lock_any.c | 37 ++++ + nptl/pthread_mutex_timedlock_any.c | 193 ++++++++++++++++++ + sysdeps/nptl/lowlevellock-futex.h | 14 ++ + sysdeps/nptl/pthread.h | 10 + + .../sysv/linux/x86_64/64/libpthread.abilist | 1 + + 8 files changed, 263 insertions(+) + create mode 100644 nptl/pthread_mutex_lock_any.c + create mode 100644 nptl/pthread_mutex_timedlock_any.c + +diff --git a/nptl/Makefile b/nptl/Makefile +index 89569c4f46..11368c93cb 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -97,6 +97,7 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \ + pthread_attr_getstack pthread_attr_setstack \ + pthread_mutex_init pthread_mutex_destroy \ + pthread_mutex_lock pthread_mutex_trylock \ ++ pthread_mutex_lock_any pthread_mutex_timedlock_any \ + pthread_mutex_timedlock pthread_mutex_unlock \ + pthread_mutex_cond_lock \ + pthread_mutexattr_init pthread_mutexattr_destroy \ +diff --git a/nptl/Versions b/nptl/Versions +index aed118e717..df4a8313e2 100644 +--- a/nptl/Versions ++++ b/nptl/Versions +@@ -285,6 +285,8 @@ libpthread { + mtx_init; mtx_lock; mtx_timedlock; mtx_trylock; mtx_unlock; mtx_destroy; + call_once; cnd_broadcast; cnd_destroy; cnd_init; cnd_signal; + cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set; ++ ++ pthread_mutex_lock_any; pthread_mutex_timedlock_any; + } + + GLIBC_2.30 { +diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h +index 6f94d6be31..87f4afff30 100644 +--- a/nptl/pthreadP.h ++++ b/nptl/pthreadP.h +@@ -395,6 +395,11 @@ extern int __pthread_mutex_trylock (pthread_mutex_t *_mutex); + extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex, + const struct timespec *__abstime); ++extern int __pthread_mutex_lock_any (pthread_mutex_t *__mutex, int mutexcount, ++ int *outlocked); ++extern int __pthread_mutex_timedlock_any (pthread_mutex_t *__mutex, int count, ++ const struct timespec *__abstime, ++ int *outlocked); + extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex) + attribute_hidden; + extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex) +diff --git a/nptl/pthread_mutex_lock_any.c b/nptl/pthread_mutex_lock_any.c +new file mode 100644 +index 0000000000..485c213a17 +--- /dev/null ++++ b/nptl/pthread_mutex_lock_any.c +@@ -0,0 +1,37 @@ ++/* Copyright (C) 2002-2019 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pthreadP.h" ++#include ++#include ++#include ++ ++int ++__pthread_mutex_lock_any (pthread_mutex_t *mutexlist, int mutexcount, ++ int *outlocked) ++{ ++ return __pthread_mutex_timedlock_any(mutexlist, mutexcount, NULL, outlocked); ++} ++ ++weak_alias (__pthread_mutex_lock_any, pthread_mutex_lock_any) +diff --git a/nptl/pthread_mutex_timedlock_any.c b/nptl/pthread_mutex_timedlock_any.c +new file mode 100644 +index 0000000000..a95687ce8e +--- /dev/null ++++ b/nptl/pthread_mutex_timedlock_any.c +@@ -0,0 +1,193 @@ ++/* Copyright (C) 2002-2019 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pthreadP.h" ++#include ++#include ++#include ++ ++/* TODO: this probably comes from a kernel header when upstream? */ ++struct futex_wait_block { ++ int *uaddr; ++ int val; ++ int bitset; ++} __attribute__((packed)); ++ ++int ++__pthread_mutex_timedlock_any (pthread_mutex_t *mutexlist, int mutexcount, ++ const struct timespec *abstime, int *outlocked) ++{ ++ /* This requires futex support */ ++#ifndef __NR_futex ++ return ENOTSUP; ++#endif ++ ++ if (mutexlist == NULL) ++ { ++ /* User is asking us if kernel supports the feature. */ ++ ++ /* TODO: how does one check if supported? ++ * I was thinking of trying the ioctl once and then returning the static ++ * cached value, is that OK? ++ */ ++ return 0; ++ } ++ ++ if (mutexlist != NULL && mutexcount <= 0) ++ return EINVAL; ++ ++ if (outlocked == NULL) ++ return EINVAL; ++ ++ int type = PTHREAD_MUTEX_TYPE (mutexlist); ++ ++ for (int i = 1; i < mutexcount; i++) ++ { ++ /* Types have to match, since the PRIVATE flag is OP-global. */ ++ if (PTHREAD_MUTEX_TYPE (&mutexlist[i]) != type) ++ return EINVAL; ++ } ++ ++ int kind = type & PTHREAD_MUTEX_KIND_MASK_NP; ++ ++ /* TODO: implement recursive, errorcheck and adaptive. */ ++ if (kind != PTHREAD_MUTEX_NORMAL) ++ return EINVAL; ++ ++ /* TODO: implement robust. */ ++ if (type & PTHREAD_MUTEX_ROBUST_NORMAL_NP) ++ return EINVAL; ++ ++ /* TODO: implement PI. */ ++ if (type & PTHREAD_MUTEX_PRIO_INHERIT_NP) ++ return EINVAL; ++ ++ /* TODO: implement PP. */ ++ if (type & PTHREAD_MUTEX_PRIO_PROTECT_NP) ++ return EINVAL; ++ ++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid); ++ int result; ++ ++ result = -1; ++ ++ for (int i = 0; i < mutexcount; i++) ++ { ++ if (__lll_trylock (&mutexlist[i].__data.__lock) == 0) ++ { ++ result = i; ++ break; ++ } ++ } ++ ++ while (result == -1) ++ { ++ for (int i = 0; i < mutexcount; i++) ++ { ++ int oldval = atomic_exchange_acq (&mutexlist[i].__data.__lock, 2); ++ ++ if (oldval == 0) ++ { ++ result = i; ++ break; ++ } ++ } ++ ++ if (result == -1) ++ { ++ /* Couldn't get one of the locks immediately, we have to sleep now. */ ++ struct timespec *timeout = NULL; ++ struct timespec rt; ++ ++ if (abstime != NULL) ++ { ++ /* Reject invalid timeouts. */ ++ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) ++ return EINVAL; ++ ++ struct timeval tv; ++ ++ /* Get the current time. */ ++ (void) __gettimeofday (&tv, NULL); ++ ++ /* Compute relative timeout. */ ++ rt.tv_sec = abstime->tv_sec - tv.tv_sec; ++ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; ++ if (rt.tv_nsec < 0) ++ { ++ rt.tv_nsec += 1000000000; ++ --rt.tv_sec; ++ } ++ ++ if (rt.tv_sec < 0) ++ return ETIMEDOUT; ++ ++ timeout = &rt; ++ } ++ ++ struct futex_wait_block waitblock[mutexcount]; ++ ++ for (int i = 0; i < mutexcount; i++) ++ { ++ waitblock[i].uaddr = &mutexlist[i].__data.__lock; ++ waitblock[i].val = 2; ++ waitblock[i].bitset = ~0; ++ } ++ ++ long int __ret; ++ ++ /* Safe to use the flag for the first one, since all their types match. */ ++ int private_flag = PTHREAD_MUTEX_PSHARED (&mutexlist[0]); ++ ++ __ret = lll_futex_timed_wait_multiple (waitblock, mutexcount, timeout, ++ private_flag); ++ ++ if (__ret < 0) ++ return -__ret; /* TODO is this correct? */ ++ ++ /* Have slept, try grabbing the one that woke us up? */ ++ if (atomic_exchange_acq (&mutexlist[__ret].__data.__lock, 2) == 0) ++ { ++ /* We got it, done, loop will end below. */ ++ result = __ret; ++ } ++ } ++ } ++ ++ if (result != -1) ++ { ++ /* Record the ownership. */ ++ mutexlist[result].__data.__owner = id; ++ ++mutexlist[result].__data.__nusers; ++ ++ /* Let the user know which mutex is now locked. */ ++ *outlocked = result; ++ ++ result = 0; ++ } ++ ++ return result; ++} ++ ++weak_alias (__pthread_mutex_timedlock_any, pthread_mutex_timedlock_any) +diff --git a/sysdeps/nptl/lowlevellock-futex.h b/sysdeps/nptl/lowlevellock-futex.h +index 2209ca76a1..83f32bc8e8 100644 +--- a/sysdeps/nptl/lowlevellock-futex.h ++++ b/sysdeps/nptl/lowlevellock-futex.h +@@ -38,6 +38,7 @@ + #define FUTEX_WAKE_BITSET 10 + #define FUTEX_WAIT_REQUEUE_PI 11 + #define FUTEX_CMP_REQUEUE_PI 12 ++#define FUTEX_WAIT_MULTIPLE 13 + #define FUTEX_PRIVATE_FLAG 128 + #define FUTEX_CLOCK_REALTIME 256 + +@@ -73,6 +74,14 @@ + ? -INTERNAL_SYSCALL_ERRNO (__ret) : 0); \ + }) + ++# define lll_futex_syscall_ret(nargs, futexp, op, ...) \ ++ ({ \ ++ long int __ret = INTERNAL_SYSCALL (futex, nargs, futexp, op, \ ++ __VA_ARGS__); \ ++ (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__ret)) \ ++ ? -INTERNAL_SYSCALL_ERRNO (__ret) : __ret); \ ++ }) ++ + /* For most of these macros, the return value is never really used. + Nevertheless, the protocol is that each one returns a negated errno + code for failure or zero for success. (Note that the corresponding +@@ -89,6 +98,11 @@ + __lll_private_flag (FUTEX_WAIT, private), \ + val, timeout) + ++# define lll_futex_timed_wait_multiple(futexp, val, timeout, private) \ ++ lll_futex_syscall_ret (4, futexp, \ ++ __lll_private_flag (FUTEX_WAIT_MULTIPLE, private), \ ++ val, timeout) ++ + /* Verify whether the supplied clockid is supported by + lll_futex_clock_wait_bitset. */ + # define lll_futex_supported_clockid(clockid) \ +diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h +index 8a403cbf36..f1f7332472 100644 +--- a/sysdeps/nptl/pthread.h ++++ b/sysdeps/nptl/pthread.h +@@ -753,7 +753,17 @@ extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) + extern int pthread_mutex_lock (pthread_mutex_t *__mutex) + __THROWNL __nonnull ((1)); + ++/* Lock any one of several mutexes. */ ++extern int pthread_mutex_lock_any (pthread_mutex_t *__mutexlist, ++ int mutexcount, int *outlocked); ++ + #ifdef __USE_XOPEN2K ++/* Lock any one of several mutexes, with timeout. */ ++extern int pthread_mutex_timedlock_any (pthread_mutex_t *__mutexlist, ++ int mutexcount, ++ const struct timespec *__restrict ++ __abstime, int *outlocked); ++ + /* Wait until lock becomes available, or specified time passes. */ + extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + const struct timespec *__restrict +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist +index 971269d2ef..54d966516c 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist +@@ -105,6 +105,7 @@ GLIBC_2.2.5 pthread_kill_other_threads_np F + GLIBC_2.2.5 pthread_mutex_destroy F + GLIBC_2.2.5 pthread_mutex_init F + GLIBC_2.2.5 pthread_mutex_lock F ++GLIBC_2.2.5 pthread_mutex_lock_any F + GLIBC_2.2.5 pthread_mutex_timedlock F + GLIBC_2.2.5 pthread_mutex_trylock F + GLIBC_2.2.5 pthread_mutex_unlock F diff --git a/eglibc-fedora-strict-aliasing.patch b/eglibc-fedora-strict-aliasing.patch new file mode 100644 index 0000000..c02b4f5 --- /dev/null +++ b/eglibc-fedora-strict-aliasing.patch @@ -0,0 +1,76 @@ +--- libc/elf/Makefile.aliasing~ 2012-12-02 22:11:45.000000000 +0100 ++++ libc/elf/Makefile 2012-12-27 19:46:13.396658450 +0100 +@@ -53,6 +53,7 @@ CFLAGS-dl-iterate-phdr.c = $(uses-callba + ifeq ($(unwind-find-fde),yes) + routines += unwind-dw2-fde-glibc + shared-only-routines += unwind-dw2-fde-glibc ++CFLAGS-unwind-dw2-fde-glibc.c += -fno-strict-aliasing + endif + + before-compile = $(objpfx)trusted-dirs.h +--- libc/inet/Makefile.aliasing~ 2012-08-28 16:14:43.000000000 +0200 ++++ libc/inet/Makefile 2012-12-27 19:48:23.933089723 +0100 +@@ -62,6 +62,8 @@ tests-$(OPTION_EGLIBC_ADVANCED_INET6) += + + include ../Rules + ++CFLAGS-tst-inet6_rth.c += -fno-strict-aliasing ++ + ifeq ($(have-thread-library),yes) + + CFLAGS-gethstbyad_r.c = -fexceptions +--- libc/nis/Makefile.aliasing~ 2012-05-12 17:44:41.000000000 +0200 ++++ libc/nis/Makefile 2012-12-27 19:46:13.396658450 +0100 +@@ -80,6 +80,8 @@ libnss_nisplus-inhibit-o = $(filter-out + + include ../Rules + ++CFLAGS-nis_findserv.c += -fno-strict-aliasing ++CFLAGS-ypclnt.c += -fno-strict-aliasing + + $(objpfx)libnss_compat.so: $(objpfx)libnsl.so$(libnsl.so-version) + $(objpfx)libnss_nis.so: $(objpfx)libnsl.so$(libnsl.so-version) \ +--- libc/nss/Makefile.aliasing~ 2012-10-10 17:35:46.000000000 +0200 ++++ libc/nss/Makefile 2012-12-27 19:46:13.396658450 +0100 +@@ -147,6 +147,7 @@ $(libnss_db-dbs:%=$(objpfx)%.c): $(objpf + echo '#include "$<"') > $@.new + mv -f $@.new $@ + ++CFLAGS-files-hosts.c += -fno-strict-aliasing + + $(objpfx)makedb: $(makedb-modules:%=$(objpfx)%.o) + +--- libc/resolv/Makefile.aliasing~ 2012-10-25 19:18:12.000000000 +0200 ++++ libc/resolv/Makefile 2012-12-27 19:46:13.396658450 +0100 +@@ -83,6 +83,7 @@ ifeq (yes,$(have-ssp)) + CFLAGS-libresolv += -fstack-protector + endif + CFLAGS-res_hconf.c = -fexceptions ++CFLAGS-res_send.c += -fno-strict-aliasing + + # The BIND code elicits some harmless warnings. + +cflags += -Wno-strict-prototypes -Wno-write-strings +--- libc/sunrpc/Makefile.aliasing~ 2012-05-26 19:46:57.000000000 +0200 ++++ libc/sunrpc/Makefile 2012-12-27 19:46:13.397658439 +0100 +@@ -164,6 +164,10 @@ sunrpc-CPPFLAGS = -D_RPC_THREAD_SAFE_ + CPPFLAGS += $(sunrpc-CPPFLAGS) + BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS) + ++CFLAGS-clnt_tcp.c += -fno-strict-aliasing ++CFLAGS-clnt_udp.c += -fno-strict-aliasing ++CFLAGS-clnt_unix.c += -fno-strict-aliasing ++ + $(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so +--- libc/sysdeps/powerpc/powerpc64/Makefile.aliasing~ 2012-12-27 19:46:13.392658496 +0100 ++++ libc/sysdeps/powerpc/powerpc64/Makefile 2012-12-27 19:46:13.397658439 +0100 +@@ -37,6 +37,8 @@ CFLAGS-rtld-strnlen.os = $(no-special-re + + CFLAGS-libc-start.c += -fno-asynchronous-unwind-tables + ++CFLAGS-gmon-start.c += -fno-strict-aliasing ++ + ifeq ($(subdir),csu) + sysdep_routines += hp-timing + elide-routines.os += hp-timing diff --git a/eglibc-mandriva-ENOTTY-fr-translation.patch b/eglibc-mandriva-ENOTTY-fr-translation.patch index 73e701f..ecad619 100644 --- a/eglibc-mandriva-ENOTTY-fr-translation.patch +++ b/eglibc-mandriva-ENOTTY-fr-translation.patch @@ -1,8 +1,9 @@ ---- glibc-2.20/po/fr.po.ENOTTYfr~ 2014-09-08 21:27:29.600168512 +0200 -+++ glibc-2.20/po/fr.po 2014-09-08 21:28:29.519419418 +0200 -@@ -6029,7 +6029,7 @@ msgstr "Trop de fichiers ouverts dans le +diff -up glibc-2.32/po/fr.po.44~ glibc-2.32/po/fr.po +--- glibc-2.32/po/fr.po.44~ 2020-08-08 02:26:17.393947894 +0200 ++++ glibc-2.32/po/fr.po 2020-08-08 02:26:49.631443164 +0200 +@@ -5655,7 +5655,7 @@ msgstr "Trop de fichiers ouverts dans le #. TRANS modes on an ordinary file. - #: sysdeps/gnu/errlist.c:286 + #: sysdeps/gnu/errlist.h:173 msgid "Inappropriate ioctl for device" -msgstr "Ioctl() inappropré pour un périphérique" +msgstr "Ioctl() inapproprié pour un périphérique" diff --git a/eglibc-mandriva-biarch-cpp-defines.patch b/eglibc-mandriva-biarch-cpp-defines.patch deleted file mode 100644 index ab53528..0000000 --- a/eglibc-mandriva-biarch-cpp-defines.patch +++ /dev/null @@ -1,17 +0,0 @@ -2004-01-23 Gwenole Beauchesne - - * Makeconfig (%.v.i): Make sure to define __$(base-machine)__ for - biarch asm headers. - -diff -p -up glibc-2.10.1/Makeconfig.orig glibc-2.10.1/Makeconfig ---- glibc-2.10.1/Makeconfig.orig 2009-05-26 23:40:06.000000000 -0300 -+++ glibc-2.10.1/Makeconfig 2009-05-26 23:41:42.000000000 -0300 -@@ -795,7 +795,7 @@ ifeq (yes, $(build-shared)) - %.v.i: $(common-objpfx)config.h $(..)Makeconfig - sed '/^[ ]*%/!s/#.*$$//;/^[ ]*$$/d;s/^[ ]*%/#/' \ - $(filter-out FORCE %.h $(..)Makeconfig,$^) \ -- | $(CC) -E -undef $(CPPFLAGS) -x assembler-with-cpp - \ -+ | $(CC) -E -undef $(CPPFLAGS) -D__$(base-machine)__ -x assembler-with-cpp - \ - > $@T - mv -f $@T $@ - %.v: %.v.i diff --git a/eglibc-mandriva-biarch-utils.patch b/eglibc-mandriva-biarch-utils.patch deleted file mode 100644 index 62c2d2a..0000000 --- a/eglibc-mandriva-biarch-utils.patch +++ /dev/null @@ -1,57 +0,0 @@ -2005-08-29 Gwenole Beauchesne - - * debug/xtrace.sh: Make it biarch capable on 64-bit Linux platforms. - * malloc/memusage.sh: Likewise. - ---- glibc-2.3.5/debug/xtrace.sh.biarch-utils 2005-08-29 12:48:24.000000000 -0400 -+++ glibc-2.3.5/debug/xtrace.sh 2005-08-29 16:58:02.000000000 -0400 -@@ -151,6 +151,23 @@ if test ! -x "$program"; then - help_info - fi - -+# Biarch transmutation. -+host_os=`uname -o` -+host_cpu=`uname -m` -+case $host_os in -+*Linux*) -+ # test if the binary is 32-bit -+ elf32=no -+ if file -L `which $program` | grep -q "ELF 32"; then -+ elf32=yes -+ fi -+esac -+case $host_cpu:$elf32 in -+powerpc64:yes | s390x:yes | sparc64:yes | x86_64:yes) -+ pcprofileso=`echo $pcprofileso | sed -e "s,/lib64/,/lib/,"` -+ ;; -+esac -+ - # We have two modes. If a data file is given simply print the included data. - printf "%-20s %-*s %6s\n" Function $(expr $COLUMNS - 30) File Line - for i in $(seq 1 $COLUMNS); do printf -; done; printf '\n' ---- glibc-2.3.5/malloc/memusage.sh.biarch-utils 2005-03-07 18:44:10.000000000 -0500 -+++ glibc-2.3.5/malloc/memusage.sh 2005-08-29 16:25:12.000000000 -0400 -@@ -205,6 +205,23 @@ if test $# -eq 0; then - do_usage - fi - -+# Biarch transmutation. -+host_os=`uname -o` -+host_cpu=`uname -m` -+case $host_os in -+*Linux*) -+ # test if the binary is 32-bit -+ elf32=no -+ if file -L `which $1` | grep -q "ELF 32"; then -+ elf32=yes -+ fi -+esac -+case $host_cpu:$elf32 in -+powerpc64:yes | s390x:yes | sparc64:yes | x86_64:yes) -+ memusageso=`echo $memusageso | sed -e "s,/lib64/,/lib/,"` -+ ;; -+esac -+ - # This will be in the environment. - add_env="LD_PRELOAD=$memusageso" - diff --git a/eglibc-mandriva-fix-dns-with-broken-routers.patch b/eglibc-mandriva-fix-dns-with-broken-routers.patch deleted file mode 100644 index ab4d856..0000000 --- a/eglibc-mandriva-fix-dns-with-broken-routers.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- glibc-2.15-a316c1f/sysdeps/unix/sysv/linux/check_pf.c.orig 2012-02-11 15:25:40.066658360 -0200 -+++ glibc-2.15-a316c1f/sysdeps/unix/sysv/linux/check_pf.c 2012-02-11 15:25:53.953718622 -0200 -@@ -209,7 +209,8 @@ make_request (int fd, pid_t pid) - } - else - { -- if (!IN6_IS_ADDR_LOOPBACK (address)) -+ if (!IN6_IS_ADDR_LOOPBACK (address) && -+ !IN6_IS_ADDR_LINKLOCAL (address)) - seen_ipv6 = true; - } - } diff --git a/eglibc-mandriva-nscd-enable.patch b/eglibc-mandriva-nscd-enable.patch deleted file mode 100644 index 45fb1dd..0000000 --- a/eglibc-mandriva-nscd-enable.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- glibc-2.3.3/nscd/nscd.init.nscd-enable 2004-08-24 10:31:20.000000000 -0400 -+++ glibc-2.3.3/nscd/nscd.init 2004-08-25 04:41:47.571810880 -0400 -@@ -2,7 +2,7 @@ - # - # nscd: Starts the Name Switch Cache Daemon - # --# chkconfig: - 30 74 -+# chkconfig: 345 30 74 - # description: This is a daemon which handles passwd and group lookups \ - # for running programs and cache the results for the next \ - # query. You should start this daemon if you use \ diff --git a/eglibc-mandriva-nscd-init-should-start.patch b/eglibc-mandriva-nscd-init-should-start.patch deleted file mode 100644 index d7d8756..0000000 --- a/eglibc-mandriva-nscd-init-should-start.patch +++ /dev/null @@ -1,12 +0,0 @@ -https://qa.mandriva.com/show_bug.cgi?id=41055 - ---- glibc-2.8/nscd/nscd.init.orig 2008-05-26 10:33:11.000000000 -0400 -+++ glibc-2.8/nscd/nscd.init 2008-05-26 10:36:56.000000000 -0400 -@@ -13,6 +13,7 @@ - ### BEGIN INIT INFO - # Provides: nscd - # Required-Start: $syslog -+# Should-Start: $network ldap mysqld ypbind - # Default-Stop: 0 1 6 - # Short-Description: Starts the Name Switch Cache Daemon - # Description: This is a daemon which handles passwd and group lookups \ diff --git a/eglibc-mandriva-string-format-fixes.patch b/eglibc-mandriva-string-format-fixes.patch new file mode 100644 index 0000000..80f21c6 --- /dev/null +++ b/eglibc-mandriva-string-format-fixes.patch @@ -0,0 +1,44 @@ +--- glibc-2.16.90-97bc38d7/misc/tst-error1.c.orig 2012-09-26 15:21:29.672179348 -0300 ++++ glibc-2.16.90-97bc38d7/misc/tst-error1.c 2012-09-26 15:21:59.422180301 -0300 +@@ -16,8 +16,8 @@ do_test (int argc, char *argv[]) + for (int i = 0; i < 1000; ++i) + memcpy (&buf[i * (sizeof (str) - 1)], str, sizeof (str)); + error (0, 0, str); +- error (0, 0, buf); +- error (0, 0, buf); ++ error (0, 0, "%s", buf); ++ error (0, 0, "%s", buf); + error (0, 0, str); + return 0; + } +--- glibc-2.16.90-97bc38d7/posix/regexbug1.c.orig 2012-09-26 15:23:13.175182590 -0300 ++++ glibc-2.16.90-97bc38d7/posix/regexbug1.c 2012-09-26 15:23:32.198183235 -0300 +@@ -18,7 +18,7 @@ main (void) + { + char buf[100]; + regerror (reerr, &re, buf, sizeof buf); +- error (EXIT_FAILURE, 0, buf); ++ error (EXIT_FAILURE, 0, "%s", buf); + } + + if (regexec (&re, "002", 2, ma, 0) != 0) +@@ -35,7 +35,7 @@ main (void) + { + char buf[100]; + regerror (reerr, &re, buf, sizeof buf); +- error (EXIT_FAILURE, 0, buf); ++ error (EXIT_FAILURE, 0, "%s", buf); + } + + if (regexec (&re, "002", 2, ma, 0) != 0) +--- glibc-2.16.90-97bc38d7/stdio-common/test-vfprintf.c.orig 2012-09-26 15:23:52.887183970 -0300 ++++ glibc-2.16.90-97bc38d7/stdio-common/test-vfprintf.c 2012-09-26 15:24:13.870184603 -0300 +@@ -92,7 +92,7 @@ main (void) + fprintf (fp, "%s", large); + fprintf (fp, "%.*s", 30000, large); + large[20000] = '\0'; +- fprintf (fp, large); ++ fprintf (fp, "%s", large); + fprintf (fp, "%-1.300000000s", "hello"); + + if (fflush (fp) != 0 || ferror (fp) != 0 || fclose (fp) != 0) diff --git a/gcc-8-fix.patch b/gcc-8-fix.patch deleted file mode 100644 index d19deca..0000000 --- a/gcc-8-fix.patch +++ /dev/null @@ -1,28 +0,0 @@ -Subject: [PATCH] Replace strncpy with memccpy to fix -Wstringop-truncation - -From : https://patchwork.sourceware.org/patch/26437/ - ---- -diff --git a/nis/nss_nisplus/nisplus-parser.c b/nis/nss_nisplus/nisplus-parser.c -index 8dc021e73d..b53284f889 100644 ---- a/nis/nss_nisplus/nisplus-parser.c -+++ b/nis/nss_nisplus/nisplus-parser.c -@@ -87,7 +87,7 @@ _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw, - if (len >= room_left) - goto no_more_room; - -- strncpy (first_unused, numstr, len); -+ memcpy (first_unused, numstr, len); - first_unused[len] = '\0'; - numstr = first_unused; - } -@@ -103,7 +103,7 @@ _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw, - if (len >= room_left) - goto no_more_room; - -- strncpy (first_unused, numstr, len); -+ memcpy (first_unused, numstr, len); - first_unused[len] = '\0'; - numstr = first_unused; - } - diff --git a/glibc-2.26-no-attribute-leaf-for-clang.patch b/glibc-2.26-no-attribute-leaf-for-clang.patch deleted file mode 100644 index 6fe8ea6..0000000 --- a/glibc-2.26-no-attribute-leaf-for-clang.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- glibc-2.26/misc/sys/cdefs.h.omv~ 2018-01-24 11:32:15.276543892 +0100 -+++ glibc-2.26/misc/sys/cdefs.h 2018-01-24 11:32:47.208618287 +0100 -@@ -38,7 +38,7 @@ - - /* All functions, except those with callbacks or those that - synchronize memory, are leaf functions. */ --# if __GNUC_PREREQ (4, 6) && !defined _LIBC -+# if __GNUC_PREREQ (4, 6) && !defined _LIBC && (!defined(__clang__) || __has_attribute(leaf)) - # define __LEAF , __leaf__ - # define __LEAF_ATTR __attribute__ ((__leaf__)) - # else diff --git a/glibc-2.27-clang-_Float.patch b/glibc-2.27-clang-_Float.patch deleted file mode 100644 index 71c582b..0000000 --- a/glibc-2.27-clang-_Float.patch +++ /dev/null @@ -1,81 +0,0 @@ ---- glibc-2.27/bits/floatn-common.h.0134~ 2018-02-01 17:17:18.000000000 +0100 -+++ glibc-2.27/bits/floatn-common.h 2018-03-03 02:32:16.924822310 +0100 -@@ -28,6 +28,7 @@ - where the same definitions, or definitions based only on the macros - in bits/floatn.h, are appropriate for all glibc configurations. */ - -+#ifndef __clang__ /* FIXME reinvestigate with clang 7 */ - /* Defined to 1 if the current compiler invocation provides a - floating-point type with the right format for this type, and this - glibc includes corresponding *fN or *fNx interfaces for it. */ -@@ -36,6 +37,7 @@ - #define __HAVE_FLOAT64 1 - #define __HAVE_FLOAT32X 1 - #define __HAVE_FLOAT128X 0 -+#endif - - /* Defined to 1 if the corresponding __HAVE_ macro is 1 and the - type is the first with its format in the sequence of (the default ---- glibc-2.27/sysdeps/ieee754/ldbl-128/bits/floatn.h.0134~ 2018-02-01 17:17:18.000000000 +0100 -+++ glibc-2.27/sysdeps/ieee754/ldbl-128/bits/floatn.h 2018-03-03 02:32:16.924822310 +0100 -@@ -26,7 +26,11 @@ - floating-point type with the IEEE 754 binary128 format, and this - glibc includes corresponding *f128 interfaces for it. */ - #ifndef __NO_LONG_DOUBLE_MATH --# define __HAVE_FLOAT128 1 -+# if defined(__clang__) -+# define __HAVE_FLOAT128 0 -+# else -+# define __HAVE_FLOAT128 1 -+# endif - #else - /* glibc does not support _Float128 for platforms where long double is - normally binary128 when building with long double as binary64. ---- glibc-2.27/sysdeps/x86/bits/floatn.h.0134~ 2018-02-01 17:17:18.000000000 +0100 -+++ glibc-2.27/sysdeps/x86/bits/floatn.h 2018-03-03 02:34:50.472771373 +0100 -@@ -26,9 +26,9 @@ - glibc includes corresponding *f128 interfaces for it. The required - libgcc support was added some time after the basic compiler - support, for x86_64 and x86. */ --#if (defined __x86_64__ \ -+#if (!defined(__clang__) && (defined __x86_64__ \ - ? __GNUC_PREREQ (4, 3) \ -- : (defined __GNU__ ? __GNUC_PREREQ (4, 5) : __GNUC_PREREQ (4, 4))) -+ : (defined __GNU__ ? __GNUC_PREREQ (4, 5) : __GNUC_PREREQ (4, 4)))) - # define __HAVE_FLOAT128 1 - #else - # define __HAVE_FLOAT128 0 -@@ -42,6 +42,7 @@ - # define __HAVE_DISTINCT_FLOAT128 0 - #endif - -+#ifndef __clang__ /* FIXME reinvestigate with clang 7 */ - /* Defined to 1 if the current compiler invocation provides a - floating-point type with the right format for _Float64x, and this - glibc includes corresponding *f64x interfaces for it. */ -@@ -52,6 +53,7 @@ - the format of _Float128, which must be different from that of long - double. */ - #define __HAVE_FLOAT64X_LONG_DOUBLE 1 -+#endif - - #ifndef __ASSEMBLER__ - -@@ -68,7 +70,7 @@ - - /* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. */ - # if __HAVE_FLOAT128 --# if !__GNUC_PREREQ (7, 0) || defined __cplusplus -+# if !__GNUC_PREREQ (7, 0) || defined __cplusplus || defined __clang__ - /* Add a typedef for older GCC compilers which don't natively support - _Complex _Float128. */ - typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__))); -@@ -82,7 +84,7 @@ typedef _Complex float __cfloat128 __att - # if __HAVE_FLOAT128 - - /* The type _Float128 exists only since GCC 7.0. */ --# if !__GNUC_PREREQ (7, 0) || defined __cplusplus -+# if !__GNUC_PREREQ (7, 0) || defined __cplusplus || defined __clang__ - typedef __float128 _Float128; - # endif - diff --git a/glibc-2.29-strict-aliasing.patch b/glibc-2.29-strict-aliasing.patch index 2ca6880..3639ef7 100644 --- a/glibc-2.29-strict-aliasing.patch +++ b/glibc-2.29-strict-aliasing.patch @@ -1,6 +1,6 @@ -diff -up glibc-2.31/csu/Makefile.59~ glibc-2.31/csu/Makefile ---- glibc-2.31/csu/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/csu/Makefile 2020-02-04 02:34:09.646778297 +0100 +diff -up glibc-2.31.20200715/csu/Makefile.54~ glibc-2.31.20200715/csu/Makefile +--- glibc-2.31.20200715/csu/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/csu/Makefile 2020-07-15 23:58:52.458734215 +0200 @@ -114,7 +114,7 @@ endif asm-CPPFLAGS += -I$(objpfx). @@ -10,9 +10,9 @@ diff -up glibc-2.31/csu/Makefile.59~ glibc-2.31/csu/Makefile include ../Rules -diff -up glibc-2.31/debug/Makefile.59~ glibc-2.31/debug/Makefile ---- glibc-2.31/debug/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/debug/Makefile 2020-02-04 02:34:09.646778297 +0100 +diff -up glibc-2.31.20200715/debug/Makefile.54~ glibc-2.31.20200715/debug/Makefile +--- glibc-2.31.20200715/debug/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/debug/Makefile 2020-07-15 23:58:52.458734215 +0200 @@ -109,6 +109,8 @@ CPPFLAGS-tst-longjmp_chk2.c += -D_FORTIF CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1 @@ -22,10 +22,10 @@ diff -up glibc-2.31/debug/Makefile.59~ glibc-2.31/debug/Makefile # We know these tests have problems with format strings, this is what # we are testing. Disable that warning. They are also testing # deprecated functions (notably gets) so disable that warning as well. -diff -up glibc-2.31/inet/Makefile.59~ glibc-2.31/inet/Makefile ---- glibc-2.31/inet/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/inet/Makefile 2020-02-04 02:34:09.646778297 +0100 -@@ -106,6 +106,20 @@ CFLAGS-getnetgrent_r.c += -fexceptions +diff -up glibc-2.31.20200715/inet/Makefile.54~ glibc-2.31.20200715/inet/Makefile +--- glibc-2.31.20200715/inet/Makefile.54~ 2020-07-15 23:58:52.458734215 +0200 ++++ glibc-2.31.20200715/inet/Makefile 2020-07-15 23:59:22.037104247 +0200 +@@ -109,6 +109,20 @@ CFLAGS-getnetgrent_r.c += -fexceptions CFLAGS-tst-checks-posix.c += -std=c99 CFLAGS-tst-sockaddr.c += -fno-strict-aliasing @@ -45,10 +45,10 @@ diff -up glibc-2.31/inet/Makefile.59~ glibc-2.31/inet/Makefile + endif - ifeq ($(build-static-nss),yes) -diff -up glibc-2.31/libio/libioP.h.59~ glibc-2.31/libio/libioP.h ---- glibc-2.31/libio/libioP.h.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/libio/libioP.h 2020-02-04 02:34:09.648778297 +0100 + # Install the rpc database file. +diff -up glibc-2.31.20200715/libio/libioP.h.54~ glibc-2.31.20200715/libio/libioP.h +--- glibc-2.31.20200715/libio/libioP.h.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/libio/libioP.h 2020-07-15 23:58:52.458734215 +0200 @@ -842,8 +842,8 @@ extern struct _IO_FILE_plus _IO_stderr_; static inline bool _IO_legacy_file (FILE *fp) @@ -71,9 +71,9 @@ diff -up glibc-2.31/libio/libioP.h.59~ glibc-2.31/libio/libioP.h return; #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1) if (_IO_legacy_file (fp)) -diff -up glibc-2.31/libio/Makefile.59~ glibc-2.31/libio/Makefile ---- glibc-2.31/libio/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/libio/Makefile 2020-02-04 02:34:09.646778297 +0100 +diff -up glibc-2.31.20200715/libio/Makefile.54~ glibc-2.31.20200715/libio/Makefile +--- glibc-2.31.20200715/libio/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/libio/Makefile 2020-07-15 23:58:52.458734215 +0200 @@ -154,6 +154,19 @@ CFLAGS-iofopen.c += -fexceptions CFLAGS-iofopen64.c += -fexceptions CFLAGS-oldtmpfile.c += -fexceptions @@ -94,10 +94,10 @@ diff -up glibc-2.31/libio/Makefile.59~ glibc-2.31/libio/Makefile CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\" -diff -up glibc-2.31/locale/Makefile.59~ glibc-2.31/locale/Makefile ---- glibc-2.31/locale/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/locale/Makefile 2020-02-04 02:34:09.646778297 +0100 -@@ -105,6 +105,7 @@ CPPFLAGS-locale-programs = -DLOCALE_PATH +diff -up glibc-2.31.20200715/locale/Makefile.54~ glibc-2.31.20200715/locale/Makefile +--- glibc-2.31.20200715/locale/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/locale/Makefile 2020-07-15 23:58:52.458734215 +0200 +@@ -106,6 +106,7 @@ CPPFLAGS-locale-programs = -DLOCALE_PATH CFLAGS-charmap.c += -Wno-write-strings -Wno-char-subscripts CFLAGS-locfile.c += -Wno-write-strings -Wno-char-subscripts CFLAGS-charmap-dir.c += -Wno-write-strings @@ -105,10 +105,10 @@ diff -up glibc-2.31/locale/Makefile.59~ glibc-2.31/locale/Makefile # Set libof-* for each routine. cpp-srcs-left := $(localedef-modules) $(localedef-aux) $(locale-modules) \ -diff -up glibc-2.31/misc/Makefile.59~ glibc-2.31/misc/Makefile ---- glibc-2.31/misc/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/misc/Makefile 2020-02-04 02:34:09.646778297 +0100 -@@ -137,6 +137,8 @@ CFLAGS-sbrk.op = $(no-stack-protector) +diff -up glibc-2.31.20200715/misc/Makefile.54~ glibc-2.31.20200715/misc/Makefile +--- glibc-2.31.20200715/misc/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/misc/Makefile 2020-07-15 23:58:52.458734215 +0200 +@@ -142,6 +142,8 @@ CFLAGS-sbrk.op = $(no-stack-protector) CFLAGS-brk.o = $(no-stack-protector) CFLAGS-brk.op = $(no-stack-protector) @@ -117,21 +117,21 @@ diff -up glibc-2.31/misc/Makefile.59~ glibc-2.31/misc/Makefile include ../Rules $(objpfx)libg.a: $(dep-dummy-lib); $(make-dummy-lib) -diff -up glibc-2.31/nis/Makefile.59~ glibc-2.31/nis/Makefile ---- glibc-2.31/nis/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/nis/Makefile 2020-02-04 02:34:09.646778297 +0100 -@@ -92,6 +92,7 @@ endif # have-GLIBC_2.28 +diff -up glibc-2.31.20200715/nis/Makefile.54~ glibc-2.31.20200715/nis/Makefile +--- glibc-2.31.20200715/nis/Makefile.54~ 2020-07-15 23:58:52.458734215 +0200 ++++ glibc-2.31.20200715/nis/Makefile 2020-07-15 23:59:49.717449495 +0200 +@@ -52,6 +52,7 @@ endif # have-GLIBC_2.28 include ../Rules +CFLAGS-nis_callback.c += -fno-strict-aliasing - ifeq ($(build-obsolete-nsl),yes) - $(objpfx)libnss_nis.so: $(objpfx)libnsl.so$(libnsl.so-version) \ -diff -up glibc-2.31/nptl/Makefile.59~ glibc-2.31/nptl/Makefile ---- glibc-2.31/nptl/Makefile.59~ 2020-02-04 02:34:09.591778295 +0100 -+++ glibc-2.31/nptl/Makefile 2020-02-04 02:34:09.646778297 +0100 -@@ -231,6 +231,19 @@ CFLAGS-fsync.c += -fexceptions -fasynchr + libnsl-libc = $(common-objpfx)linkobj/libc.so + # Target-specific variable setting to link objects using deprecated +diff -up glibc-2.31.20200715/nptl/Makefile.54~ glibc-2.31.20200715/nptl/Makefile +--- glibc-2.31.20200715/nptl/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/nptl/Makefile 2020-07-15 23:58:52.459734227 +0200 +@@ -254,6 +254,22 @@ CFLAGS-fsync.c += -fexceptions -fasynchr CFLAGS-pt-system.c += -fexceptions @@ -142,18 +142,21 @@ diff -up glibc-2.31/nptl/Makefile.59~ glibc-2.31/nptl/Makefile +CFLAGS-sem_timedwait.c += -fno-strict-aliasing +CFLAGS-sem_post.c += -fno-strict-aliasing +CFLAGS-unwind.c += -fno-strict-aliasing ++CFLAGS-pthread_attr_copy.c += -fno-strict-aliasing +CFLAGS-pthread_cond_common.c += -fno-strict-aliasing +CFLAGS-pthread_cond_destroy.c += -fno-strict-aliasing +CFLAGS-pthread_cond_wait.c += -fno-strict-aliasing +CFLAGS-pthread_cond_signal.c += -fno-strict-aliasing +CFLAGS-pthread_cond_broadcast.c += -fno-strict-aliasing ++CFLAGS-pthread_setattr_default_np.c += -fno-strict-aliasing ++CFLAGS-pthread_getattr_default_np.c += -fno-strict-aliasing + LDLIBS-tst-once5 = -lstdc++ CFLAGS-tst-thread_local1.o = -std=gnu++11 LDLIBS-tst-thread_local1 = -lstdc++ -diff -up glibc-2.31/nscd/Makefile.59~ glibc-2.31/nscd/Makefile ---- glibc-2.31/nscd/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/nscd/Makefile 2020-02-04 02:34:09.646778297 +0100 +diff -up glibc-2.31.20200715/nscd/Makefile.54~ glibc-2.31.20200715/nscd/Makefile +--- glibc-2.31.20200715/nscd/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/nscd/Makefile 2020-07-15 23:58:52.459734227 +0200 @@ -79,6 +79,14 @@ CFLAGS-nscd_gethst_r.c += -fexceptions CFLAGS-nscd_getai.c += -fexceptions CFLAGS-nscd_initgroups.c += -fexceptions @@ -169,20 +172,20 @@ diff -up glibc-2.31/nscd/Makefile.59~ glibc-2.31/nscd/Makefile CPPFLAGS-nscd += -D_FORTIFY_SOURCE=2 ifeq (yesyes,$(have-fpie)$(build-shared)) -diff -up glibc-2.31/nss/Makefile.59~ glibc-2.31/nss/Makefile ---- glibc-2.31/nss/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/nss/Makefile 2020-02-04 02:34:09.647778297 +0100 -@@ -182,3 +182,6 @@ $(objpfx)tst-nss-files-alias-leak: $(lib +diff -up glibc-2.31.20200715/nss/Makefile.54~ glibc-2.31.20200715/nss/Makefile +--- glibc-2.31.20200715/nss/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/nss/Makefile 2020-07-15 23:58:52.459734227 +0200 +@@ -183,3 +183,6 @@ $(objpfx)tst-nss-files-alias-leak: $(lib $(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so $(objpfx)tst-nss-files-alias-truncated: $(libdl) $(objpfx)tst-nss-files-alias-truncated.out: $(objpfx)/libnss_files.so + +CFLAGS-getnssent_r.c += -fno-strict-aliasing +CFLAGS-digits_dots.c += -fno-strict-aliasing -diff -up glibc-2.31/posix/Makefile.59~ glibc-2.31/posix/Makefile ---- glibc-2.31/posix/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/posix/Makefile 2020-02-04 02:34:09.647778297 +0100 -@@ -248,6 +248,13 @@ CFLAGS-execvp.os = -fomit-frame-pointer +diff -up glibc-2.31.20200715/posix/Makefile.54~ glibc-2.31.20200715/posix/Makefile +--- glibc-2.31.20200715/posix/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/posix/Makefile 2020-07-15 23:58:52.459734227 +0200 +@@ -249,6 +249,13 @@ CFLAGS-execvp.os = -fomit-frame-pointer CFLAGS-execlp.os = -fomit-frame-pointer CFLAGS-nanosleep.c += -fexceptions -fasynchronous-unwind-tables @@ -196,9 +199,9 @@ diff -up glibc-2.31/posix/Makefile.59~ glibc-2.31/posix/Makefile tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \ --none random --col --color --colour -diff -up glibc-2.31/resolv/Makefile.59~ glibc-2.31/resolv/Makefile ---- glibc-2.31/resolv/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/resolv/Makefile 2020-02-04 02:34:09.647778297 +0100 +diff -up glibc-2.31.20200715/resolv/Makefile.54~ glibc-2.31.20200715/resolv/Makefile +--- glibc-2.31.20200715/resolv/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/resolv/Makefile 2020-07-15 23:58:52.459734227 +0200 @@ -144,6 +144,19 @@ include ../gen-locales.mk CFLAGS-res_hconf.c += -fexceptions @@ -219,10 +222,10 @@ diff -up glibc-2.31/resolv/Makefile.59~ glibc-2.31/resolv/Makefile # The DNS NSS modules needs the resolver. $(objpfx)libnss_dns.so: $(objpfx)libresolv.so -diff -up glibc-2.31/rt/Makefile.59~ glibc-2.31/rt/Makefile ---- glibc-2.31/rt/Makefile.59~ 2020-02-04 02:34:09.647778297 +0100 -+++ glibc-2.31/rt/Makefile 2020-02-04 02:34:42.832779760 +0100 -@@ -58,6 +58,8 @@ CFLAGS-mq_timedreceive.c += -fexceptions +diff -up glibc-2.31.20200715/rt/Makefile.54~ glibc-2.31.20200715/rt/Makefile +--- glibc-2.31.20200715/rt/Makefile.54~ 2020-07-15 23:58:52.453734152 +0200 ++++ glibc-2.31.20200715/rt/Makefile 2020-07-15 23:58:52.459734227 +0200 +@@ -59,6 +59,8 @@ CFLAGS-mq_timedreceive.c += -fexceptions CFLAGS-mq_timedsend.c += -fexceptions -fasynchronous-unwind-tables CFLAGS-librt-cancellation.c += -fasynchronous-unwind-tables @@ -231,9 +234,9 @@ diff -up glibc-2.31/rt/Makefile.59~ glibc-2.31/rt/Makefile LDFLAGS-rt.so = -Wl,--enable-new-dtags,-z,nodelete $(objpfx)librt.so: $(shared-thread-library) -diff -up glibc-2.31/setjmp/Makefile.59~ glibc-2.31/setjmp/Makefile ---- glibc-2.31/setjmp/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/setjmp/Makefile 2020-02-04 02:34:09.647778297 +0100 +diff -up glibc-2.31.20200715/setjmp/Makefile.54~ glibc-2.31.20200715/setjmp/Makefile +--- glibc-2.31.20200715/setjmp/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/setjmp/Makefile 2020-07-15 23:58:52.459734227 +0200 @@ -31,6 +31,9 @@ tests := tst-setjmp jmpbug bug269-setjm tst-sigsetjmp tst-setjmp-static tests-static := tst-setjmp-static @@ -244,10 +247,10 @@ diff -up glibc-2.31/setjmp/Makefile.59~ glibc-2.31/setjmp/Makefile include ../Rules -diff -up glibc-2.31/stdio-common/Makefile.59~ glibc-2.31/stdio-common/Makefile ---- glibc-2.31/stdio-common/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/stdio-common/Makefile 2020-02-04 02:34:09.647778297 +0100 -@@ -125,6 +125,10 @@ $(objpfx)tst-%-mem.out: $(objpfx)tst-%.o +diff -up glibc-2.31.20200715/stdio-common/Makefile.54~ glibc-2.31.20200715/stdio-common/Makefile +--- glibc-2.31.20200715/stdio-common/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/stdio-common/Makefile 2020-07-15 23:58:52.459734227 +0200 +@@ -152,6 +152,10 @@ $(objpfx)tst-errno-manual.out: tst-errno CFLAGS-vfprintf.c += -Wno-uninitialized CFLAGS-vfwprintf.c += -Wno-uninitialized @@ -258,10 +261,10 @@ diff -up glibc-2.31/stdio-common/Makefile.59~ glibc-2.31/stdio-common/Makefile CFLAGS-tmpfile.c += -fexceptions CFLAGS-tmpfile64.c += -fexceptions -diff -up glibc-2.31/sunrpc/Makefile.59~ glibc-2.31/sunrpc/Makefile ---- glibc-2.31/sunrpc/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/sunrpc/Makefile 2020-02-04 02:34:09.647778297 +0100 -@@ -156,6 +156,21 @@ CFLAGS-pmap_rmt.c += -fexceptions +diff -up glibc-2.31.20200715/sunrpc/Makefile.54~ glibc-2.31.20200715/sunrpc/Makefile +--- glibc-2.31.20200715/sunrpc/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/sunrpc/Makefile 2020-07-15 23:58:52.459734227 +0200 +@@ -97,6 +97,21 @@ CFLAGS-pmap_rmt.c += -fexceptions CFLAGS-clnt_perr.c += -fexceptions CFLAGS-openchild.c += -fexceptions @@ -283,15 +286,27 @@ diff -up glibc-2.31/sunrpc/Makefile.59~ glibc-2.31/sunrpc/Makefile $(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so $(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so $(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so -diff -up glibc-2.31/support/Makefile.59~ glibc-2.31/support/Makefile ---- glibc-2.31/support/Makefile.59~ 2020-02-01 12:52:50.000000000 +0100 -+++ glibc-2.31/support/Makefile 2020-02-04 02:34:09.647778297 +0100 -@@ -188,6 +188,8 @@ CFLAGS-support_paths.c = \ - -DSBINDIR_PATH=\"$(sbindir)\" \ - -DROOTSBINDIR_PATH=\"$(rootsbindir)\" +diff -up glibc-2.31.20200715/support/Makefile.54~ glibc-2.31.20200715/support/Makefile +--- glibc-2.31.20200715/support/Makefile.54~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/support/Makefile 2020-07-15 23:58:52.459734227 +0200 +@@ -185,6 +185,8 @@ ifeq ($(build-shared),yes) + libsupport-inhibit-o += .o + endif +CFLAGS-resolv_test.c = -fno-strict-aliasing + - ifeq (,$(CXX)) - LINKS_DSO_PROGRAM = links-dso-program-c - else + CFLAGS-support_paths.c = \ + -DSRCDIR_PATH=\"`cd .. ; pwd`\" \ + -DOBJDIR_PATH=\"`cd $(objpfx)/..; pwd`\" \ +diff -up glibc-2.32/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h.omv~ glibc-2.32/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h +--- glibc-2.32/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h.omv~ 2020-08-10 05:01:38.876042446 +0200 ++++ glibc-2.32/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h 2020-08-10 05:06:11.774020733 +0200 +@@ -17,6 +17,8 @@ + + #include + ++#pragma GCC diagnostic ignored "-Wstrict-aliasing" ++ + /* The code checks if _rtld_global_ro was realocated before trying to access + the dl_hwcap field. The assembly is to make the compiler not optimize the + test (&_rtld_global_ro != NULL), which is always true in ISO C (but not diff --git a/glibc-2.31.9000-aarch64-compile.patch b/glibc-2.31.9000-aarch64-compile.patch new file mode 100644 index 0000000..de9471e --- /dev/null +++ b/glibc-2.31.9000-aarch64-compile.patch @@ -0,0 +1,11 @@ +diff -up glibc-2.31.20200621/iconv/Makefile.omv~ glibc-2.31.20200621/iconv/Makefile +--- glibc-2.31.20200621/iconv/Makefile.omv~ 2020-06-27 03:39:53.689509570 +0200 ++++ glibc-2.31.20200621/iconv/Makefile 2020-06-27 03:41:42.958406000 +0200 +@@ -53,6 +53,7 @@ install-sbin = iconvconfig + CFLAGS-gconv_cache.c += -DGCONV_DIR='"$(gconvdir)"' + CFLAGS-gconv_conf.c += -DGCONV_PATH='"$(gconvdir)"' + CFLAGS-iconvconfig.c += -DGCONV_PATH='"$(gconvdir)"' -DGCONV_DIR='"$(gconvdir)"' ++CFLAGS-gconv_simple.c += -Wno-error=stringop-overflow + + # Set libof-* for each routine. + cpp-srcs-left := $(iconv_prog-modules) $(iconvconfig-modules) diff --git a/glibc-bench-build.patch b/glibc-bench-build.patch new file mode 100644 index 0000000..a982eef --- /dev/null +++ b/glibc-bench-build.patch @@ -0,0 +1,41 @@ +diff --git a/Makefile.in b/Makefile.in +index 710ce7e..3fe9e73 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -12,7 +12,7 @@ install: + LC_ALL=C; export LC_ALL; \ + $(MAKE) -r PARALLELMFLAGS="$(PARALLELMFLAGS)" -C $(srcdir) objdir=`pwd` $@ + +-bench bench-clean: ++bench bench-clean bench-build: + $(MAKE) -C $(srcdir)/benchtests $(PARALLELMFLAGS) objdir=`pwd` $@ + + # Convenience target to rebuild ULPs for all math tests. +diff --git a/Rules b/Rules +index 4f9cdf3..42d0368 100644 +--- a/Rules ++++ b/Rules +@@ -83,7 +83,7 @@ common-generated += dummy.o dummy.c + + # This makes all the auxiliary and test programs. + +-.PHONY: others tests bench ++.PHONY: others tests bench bench-build + + ifeq ($(build-programs),yes) + others: $(addprefix $(objpfx),$(others) $(sysdep-others) $(extra-objs)) +diff --git a/benchtests/Makefile b/benchtests/Makefile +index fd3036d..7cbceaa 100644 +--- a/benchtests/Makefile ++++ b/benchtests/Makefile +@@ -103,6 +103,10 @@ bench-clean: + + bench: $(timing-type) $(gen-locales) bench-set bench-func bench-malloc + ++bench-build: bench-set-build bench-func-build ++bench-set-build: $(binaries-benchset) ++bench-func-build: $(binaries-bench) $(binaries-bench-malloc) ++ + bench-set: $(binaries-benchset) + for run in $^; do \ + echo "Running $${run}"; \ diff --git a/glibc-c_stubs.patch b/glibc-c_stubs.patch new file mode 100644 index 0000000..934f0d0 --- /dev/null +++ b/glibc-c_stubs.patch @@ -0,0 +1,754 @@ +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/Banner glibc-2.17-931-g30bbc0c.new/c_stubs/Banner +--- glibc-2.17-931-g30bbc0c/c_stubs/Banner 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/Banner 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1 @@ ++The C stubs add-on version 2.1.2. +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/ChangeLog glibc-2.17-931-g30bbc0c.new/c_stubs/ChangeLog +--- glibc-2.17-931-g30bbc0c/c_stubs/ChangeLog 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/ChangeLog 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,46 @@ ++2006-03-01 Jakub Jelinek ++ ++ * configure (libc_add_on_canonical, libc_add_on_subdir): Set. ++ ++2001-08-07 Jakub Jelinek ++ ++ * gconv_stubs.c (__gconv_lookup_alias): Remove. ++ (__gconv_NOOP, __gconv_compare_alias, __gconv_release_cache, ++ __gconv_release_step): New. ++ ++2001-06-07 Jakub Jelinek ++ ++ * gconv_stubs.c (__gconv_lookup_alias): New. ++ ++2000-02-27 Cristian Gafton ++ ++ * gconv_stubs.c: Return __gconv_OK for: ++ __gconv_transform_ascii_internal ++ __gconv_transform_ucs2little_internal ++ __gconv_transform_utf16_internal ++ __gconv_transform_utf8_internal ++ __gconv_transform_ucs2_internal ++ ++2000-02-25 Cristian Gafton ++ ++ * gconv_stubs.c: add __c_stubs_is_compiled_in so we can detect when ++ the library is linked in. ++ ++Wed Dec 8 13:47:25 1999 Ivan Brunello ++ ++ * Makefile (extra-objs): Changed stubs.o to gconv_stubs.o. ++ ++Sun Dec 5 11:32:17 1999 H.J. Lu ++ ++ * gconv_stubs.c: Renamed from stubs.c. ++ Support glibc 2.1.x. ++ ++Mon Aug 23 16:42:05 1999 H.J. Lu ++ ++ * Banner: New. ++ * COPYING.LIB: Likewise. ++ * Makefile: Likewise. ++ * README: Likewise. ++ * configure: Likewise. ++ * stubs.c: Likewise. ++ * test-stdio.c: Likewise. +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/configure glibc-2.17-931-g30bbc0c.new/c_stubs/configure +--- glibc-2.17-931-g30bbc0c/c_stubs/configure 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/configure 2013-08-16 16:26:11.637020805 +0530 +@@ -0,0 +1,5 @@ ++# This is only to keep the GNU C library configure mechanism happy. ++# This is a shell script fragment sourced by the main configure script. ++ ++libc_add_on_canonical= ++libc_add_on_subdirs=. +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/COPYING.LIB glibc-2.17-931-g30bbc0c.new/c_stubs/COPYING.LIB +--- glibc-2.17-931-g30bbc0c/c_stubs/COPYING.LIB 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/COPYING.LIB 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,482 @@ ++ GNU LIBRARY GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1991 Free Software Foundation, Inc. ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++[This is the first released version of the library GPL. It is ++ numbered 2 because it goes with version 2 of the ordinary GPL.] ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++Licenses are intended to guarantee your freedom to share and change ++free software--to make sure the software is free for all its users. ++ ++ This license, the Library General Public License, applies to some ++specially designated Free Software Foundation software, and to any ++other libraries whose authors decide to use it. You can use it for ++your libraries, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if ++you distribute copies of the library, or if you modify it. ++ ++ For example, if you distribute copies of the library, whether gratis ++or for a fee, you must give the recipients all the rights that we gave ++you. You must make sure that they, too, receive or can get the source ++code. If you link a program with the library, you must provide ++complete object files to the recipients so that they can relink them ++with the library, after making changes to the library and recompiling ++it. And you must show them these terms so they know their rights. ++ ++ Our method of protecting your rights has two steps: (1) copyright ++the library, and (2) offer you this license which gives you legal ++permission to copy, distribute and/or modify the library. ++ ++ Also, for each distributor's protection, we want to make certain ++that everyone understands that there is no warranty for this free ++library. If the library is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original ++version, so that any problems introduced by others will not reflect on ++the original authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that companies distributing free ++software will individually obtain patent licenses, thus in effect ++transforming the program into proprietary software. To prevent this, ++we have made it clear that any patent must be licensed for everyone's ++free use or not licensed at all. ++ ++ Most GNU software, including some libraries, is covered by the ordinary ++GNU General Public License, which was designed for utility programs. This ++license, the GNU Library General Public License, applies to certain ++designated libraries. This license is quite different from the ordinary ++one; be sure to read it in full, and don't assume that anything in it is ++the same as in the ordinary license. ++ ++ The reason we have a separate public license for some libraries is that ++they blur the distinction we usually make between modifying or adding to a ++program and simply using it. Linking a program with a library, without ++changing the library, is in some sense simply using the library, and is ++analogous to running a utility program or application program. However, in ++a textual and legal sense, the linked executable is a combined work, a ++derivative of the original library, and the ordinary General Public License ++treats it as such. ++ ++ Because of this blurred distinction, using the ordinary General ++Public License for libraries did not effectively promote software ++sharing, because most developers did not use the libraries. We ++concluded that weaker conditions might promote sharing better. ++ ++ However, unrestricted linking of non-free programs would deprive the ++users of those programs of all benefit from the free status of the ++libraries themselves. This Library General Public License is intended to ++permit developers of non-free programs to use free libraries, while ++preserving your freedom as a user of such programs to change the free ++libraries that are incorporated in them. (We have not seen how to achieve ++this as regards changes in header files, but we have achieved it as regards ++changes in the actual functions of the Library.) The hope is that this ++will lead to faster development of free libraries. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. Pay close attention to the difference between a ++"work based on the library" and a "work that uses the library". The ++former contains code derived from the library, while the latter only ++works together with the library. ++ ++ Note that it is possible for a library to be covered by the ordinary ++General Public License rather than by this special one. ++ ++ GNU LIBRARY GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License Agreement applies to any software library which ++contains a notice placed by the copyright holder or other authorized ++party saying it may be distributed under the terms of this Library ++General Public License (also called "this License"). Each licensee is ++addressed as "you". ++ ++ A "library" means a collection of software functions and/or data ++prepared so as to be conveniently linked with application programs ++(which use some of those functions and data) to form executables. ++ ++ The "Library", below, refers to any such software library or work ++which has been distributed under these terms. A "work based on the ++Library" means either the Library or any derivative work under ++copyright law: that is to say, a work containing the Library or a ++portion of it, either verbatim or with modifications and/or translated ++straightforwardly into another language. (Hereinafter, translation is ++included without limitation in the term "modification".) ++ ++ "Source code" for a work means the preferred form of the work for ++making modifications to it. For a library, complete source code means ++all the source code for all modules it contains, plus any associated ++interface definition files, plus the scripts used to control compilation ++and installation of the library. ++ ++ Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running a program using the Library is not restricted, and output from ++such a program is covered only if its contents constitute a work based ++on the Library (independent of the use of the Library in a tool for ++writing it). Whether that is true depends on what the Library does ++and what the program that uses the Library does. ++ ++ 1. You may copy and distribute verbatim copies of the Library's ++complete source code as you receive it, in any medium, provided that ++you conspicuously and appropriately publish on each copy an ++appropriate copyright notice and disclaimer of warranty; keep intact ++all the notices that refer to this License and to the absence of any ++warranty; and distribute a copy of this License along with the ++Library. ++ ++ You may charge a fee for the physical act of transferring a copy, ++and you may at your option offer warranty protection in exchange for a ++fee. ++ ++ 2. You may modify your copy or copies of the Library or any portion ++of it, thus forming a work based on the Library, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) The modified work must itself be a software library. ++ ++ b) You must cause the files modified to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ c) You must cause the whole of the work to be licensed at no ++ charge to all third parties under the terms of this License. ++ ++ d) If a facility in the modified Library refers to a function or a ++ table of data to be supplied by an application program that uses ++ the facility, other than as an argument passed when the facility ++ is invoked, then you must make a good faith effort to ensure that, ++ in the event an application does not supply such function or ++ table, the facility still operates, and performs whatever part of ++ its purpose remains meaningful. ++ ++ (For example, a function in a library to compute square roots has ++ a purpose that is entirely well-defined independent of the ++ application. Therefore, Subsection 2d requires that any ++ application-supplied function or table used by this function must ++ be optional: if the application does not supply it, the square ++ root function must still compute square roots.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Library, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Library, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote ++it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Library. ++ ++In addition, mere aggregation of another work not based on the Library ++with the Library (or with a work based on the Library) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may opt to apply the terms of the ordinary GNU General Public ++License instead of this License to a given copy of the Library. To do ++this, you must alter all the notices that refer to this License, so ++that they refer to the ordinary GNU General Public License, version 2, ++instead of to this License. (If a newer version than version 2 of the ++ordinary GNU General Public License has appeared, then you can specify ++that version instead if you wish.) Do not make any other change in ++these notices. ++ ++ Once this change is made in a given copy, it is irreversible for ++that copy, so the ordinary GNU General Public License applies to all ++subsequent copies and derivative works made from that copy. ++ ++ This option is useful when you wish to copy part of the code of ++the Library into a program that is not a library. ++ ++ 4. You may copy and distribute the Library (or a portion or ++derivative of it, under Section 2) in object code or executable form ++under the terms of Sections 1 and 2 above provided that you accompany ++it with the complete corresponding machine-readable source code, which ++must be distributed under the terms of Sections 1 and 2 above on a ++medium customarily used for software interchange. ++ ++ If distribution of object code is made by offering access to copy ++from a designated place, then offering equivalent access to copy the ++source code from the same place satisfies the requirement to ++distribute the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 5. A program that contains no derivative of any portion of the ++Library, but is designed to work with the Library by being compiled or ++linked with it, is called a "work that uses the Library". Such a ++work, in isolation, is not a derivative work of the Library, and ++therefore falls outside the scope of this License. ++ ++ However, linking a "work that uses the Library" with the Library ++creates an executable that is a derivative of the Library (because it ++contains portions of the Library), rather than a "work that uses the ++library". The executable is therefore covered by this License. ++Section 6 states terms for distribution of such executables. ++ ++ When a "work that uses the Library" uses material from a header file ++that is part of the Library, the object code for the work may be a ++derivative work of the Library even though the source code is not. ++Whether this is true is especially significant if the work can be ++linked without the Library, or if the work is itself a library. The ++threshold for this to be true is not precisely defined by law. ++ ++ If such an object file uses only numerical parameters, data ++structure layouts and accessors, and small macros and small inline ++functions (ten lines or less in length), then the use of the object ++file is unrestricted, regardless of whether it is legally a derivative ++work. (Executables containing this object code plus portions of the ++Library will still fall under Section 6.) ++ ++ Otherwise, if the work is a derivative of the Library, you may ++distribute the object code for the work under the terms of Section 6. ++Any executables containing that work also fall under Section 6, ++whether or not they are linked directly with the Library itself. ++ ++ 6. As an exception to the Sections above, you may also compile or ++link a "work that uses the Library" with the Library to produce a ++work containing portions of the Library, and distribute that work ++under terms of your choice, provided that the terms permit ++modification of the work for the customer's own use and reverse ++engineering for debugging such modifications. ++ ++ You must give prominent notice with each copy of the work that the ++Library is used in it and that the Library and its use are covered by ++this License. You must supply a copy of this License. If the work ++during execution displays copyright notices, you must include the ++copyright notice for the Library among them, as well as a reference ++directing the user to the copy of this License. Also, you must do one ++of these things: ++ ++ a) Accompany the work with the complete corresponding ++ machine-readable source code for the Library including whatever ++ changes were used in the work (which must be distributed under ++ Sections 1 and 2 above); and, if the work is an executable linked ++ with the Library, with the complete machine-readable "work that ++ uses the Library", as object code and/or source code, so that the ++ user can modify the Library and then relink to produce a modified ++ executable containing the modified Library. (It is understood ++ that the user who changes the contents of definitions files in the ++ Library will not necessarily be able to recompile the application ++ to use the modified definitions.) ++ ++ b) Accompany the work with a written offer, valid for at ++ least three years, to give the same user the materials ++ specified in Subsection 6a, above, for a charge no more ++ than the cost of performing this distribution. ++ ++ c) If distribution of the work is made by offering access to copy ++ from a designated place, offer equivalent access to copy the above ++ specified materials from the same place. ++ ++ d) Verify that the user has already received a copy of these ++ materials or that you have already sent this user a copy. ++ ++ For an executable, the required form of the "work that uses the ++Library" must include any data and utility programs needed for ++reproducing the executable from it. However, as a special exception, ++the source code distributed need not include anything that is normally ++distributed (in either source or binary form) with the major ++components (compiler, kernel, and so on) of the operating system on ++which the executable runs, unless that component itself accompanies ++the executable. ++ ++ It may happen that this requirement contradicts the license ++restrictions of other proprietary libraries that do not normally ++accompany the operating system. Such a contradiction means you cannot ++use both them and the Library together in an executable that you ++distribute. ++ ++ 7. You may place library facilities that are a work based on the ++Library side-by-side in a single library together with other library ++facilities not covered by this License, and distribute such a combined ++library, provided that the separate distribution of the work based on ++the Library and of the other library facilities is otherwise ++permitted, and provided that you do these two things: ++ ++ a) Accompany the combined library with a copy of the same work ++ based on the Library, uncombined with any other library ++ facilities. This must be distributed under the terms of the ++ Sections above. ++ ++ b) Give prominent notice with the combined library of the fact ++ that part of it is a work based on the Library, and explaining ++ where to find the accompanying uncombined form of the same work. ++ ++ 8. You may not copy, modify, sublicense, link with, or distribute ++the Library except as expressly provided under this License. Any ++attempt otherwise to copy, modify, sublicense, link with, or ++distribute the Library is void, and will automatically terminate your ++rights under this License. However, parties who have received copies, ++or rights, from you under this License will not have their licenses ++terminated so long as such parties remain in full compliance. ++ ++ 9. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Library or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Library (or any work based on the ++Library), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Library or works based on it. ++ ++ 10. Each time you redistribute the Library (or any work based on the ++Library), the recipient automatically receives a license from the ++original licensor to copy, distribute, link with or modify the Library ++subject to these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 11. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Library at all. For example, if a patent ++license would not permit royalty-free redistribution of the Library by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Library. ++ ++If any portion of this section is held invalid or unenforceable under any ++particular circumstance, the balance of the section is intended to apply, ++and the section as a whole is intended to apply in other circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 12. If the distribution and/or use of the Library is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Library under this License may add ++an explicit geographical distribution limitation excluding those countries, ++so that distribution is permitted only in or among countries not thus ++excluded. In such case, this License incorporates the limitation as if ++written in the body of this License. ++ ++ 13. The Free Software Foundation may publish revised and/or new ++versions of the Library General Public License from time to time. ++Such new versions will be similar in spirit to the present version, ++but may differ in detail to address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Library ++specifies a version number of this License which applies to it and ++"any later version", you have the option of following the terms and ++conditions either of that version or of any later version published by ++the Free Software Foundation. If the Library does not specify a ++license version number, you may choose any version ever published by ++the Free Software Foundation. ++ ++ 14. If you wish to incorporate parts of the Library into other free ++programs whose distribution conditions are incompatible with these, ++write to the author to ask for permission. For software which is ++copyrighted by the Free Software Foundation, write to the Free ++Software Foundation; we sometimes make exceptions for this. Our ++decision will be guided by the two goals of preserving the free status ++of all derivatives of our free software and of promoting the sharing ++and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO ++WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. ++EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR ++OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY ++KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE ++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE ++LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME ++THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ++ ++ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN ++WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY ++AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU ++FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR ++CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE ++LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING ++RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A ++FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF ++SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ Appendix: How to Apply These Terms to Your New Libraries ++ ++ If you develop a new library, and you want it to be of the greatest ++possible use to the public, we recommend making it free software that ++everyone can redistribute and change. You can do so by permitting ++redistribution under these terms (or, alternatively, under the terms of the ++ordinary General Public License). ++ ++ To apply these terms, attach the following notices to the library. It is ++safest to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least the ++"copyright" line and a pointer to where the full notice is found. ++ ++ ++ Copyright (C) ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with this library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, ++ MA 02111-1307, USA ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the library, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the ++ library `Frob' (a library for tweaking knobs) written by James Random Hacker. ++ ++ , 1 April 1990 ++ Ty Coon, President of Vice ++ ++That's all there is to it! +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/gconv_stubs.c glibc-2.17-931-g30bbc0c.new/c_stubs/gconv_stubs.c +--- glibc-2.17-931-g30bbc0c/c_stubs/gconv_stubs.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/gconv_stubs.c 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,126 @@ ++/* Provide gconv stub functions for the minimum static binaries. ++ Copyright (C) 1999, 2001, 2003, 2004 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library General Public License as ++ published by the Free Software Foundation; either version 2 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If not, ++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. */ ++ ++#include ++#include ++#include ++#include ++#if __GNUC_PREREQ(3, 3) ++# include ++#else ++# include ++#endif ++ ++__libc_lock_define_initialized (, __gconv_lock) ++ ++/* hack for self identification */ ++int __c_stubs_is_compiled_in; ++ ++/* Don't drag in the dynamic linker. */ ++void *__libc_stack_end; ++ ++int attribute_hidden ++__gconv_OK (void) ++{ ++#if __GLIBC__ > 2 || __GLIBC_MINOR__ > 1 ++ return __GCONV_OK; ++#else ++ return GCONV_OK; ++#endif ++} ++ ++int attribute_hidden ++__gconv_NOCONV (void) ++{ ++#if __GLIBC__ > 2 || __GLIBC_MINOR__ > 1 ++ return __GCONV_NOCONV; ++#else ++ return GCONV_NOCONV; ++#endif ++} ++ ++void attribute_hidden ++__gconv_NOOP (void) ++{ ++} ++ ++int ++internal_function ++__gconv_compare_alias (const char *name1, const char *name2) ++{ ++ return strcmp (name1, name2); ++} ++ ++wint_t ++__gconv_btwoc_ascii (struct __gconv_step *step, unsigned char c) ++{ ++ if (c < 0x80) ++ return c; ++ else ++ return WEOF; ++} ++ ++ ++#if __GNUC_PREREQ(3, 3) ++# undef strong_alias ++# define strong_alias(impl, name) \ ++ __typeof (name) name __attribute__ ((alias (#impl))) ++#endif ++ ++strong_alias (__gconv_OK, ++ __gconv_close_transform); ++strong_alias (__gconv_OK, ++ __gconv_close); ++ ++strong_alias (__gconv_NOCONV, ++ __gconv); ++strong_alias (__gconv_NOCONV, ++ __gconv_find_transform); ++strong_alias (__gconv_NOCONV, ++ __gconv_open); ++ ++/* These transformations should not fail in normal conditions */ ++strong_alias (__gconv_OK, ++ __gconv_transform_ascii_internal); ++strong_alias (__gconv_OK, ++ __gconv_transform_utf16_internal); ++strong_alias (__gconv_OK, ++ __gconv_transform_utf8_internal); ++strong_alias (__gconv_OK, ++ __gconv_transform_ucs2_internal); ++ ++/* We can assume no conversion for these ones */ ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_ascii); ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_ucs2); ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_ucs4); ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_utf16); ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_utf8); ++ ++strong_alias (__gconv_NOCONV, ++ __gconv_transliterate); ++ ++strong_alias (__gconv_NOOP, ++ __gconv_release_cache); ++strong_alias (__gconv_NOOP, ++ __gconv_release_step); +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/Makefile glibc-2.17-931-g30bbc0c.new/c_stubs/Makefile +--- glibc-2.17-931-g30bbc0c/c_stubs/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/Makefile 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,46 @@ ++# Copyright (C) 1999 Free Software Foundation, Inc. ++# This file is part of the GNU C Library. ++ ++# The GNU C Library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Library General Public License as ++# published by the Free Software Foundation; either version 2 of the ++# License, or (at your option) any later version. ++ ++# The GNU C Library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Library General Public License for more details. ++ ++# You should have received a copy of the GNU Library General Public ++# License along with the GNU C Library; see the file COPYING.LIB. If not, ++# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++# ++# Sub-makefile for the C stub add-on library. ++# ++subdir := c_stubs ++ ++tests-static := test-stdio ++tests := $(tests-static) ++ ++libc_stubs-objs := gconv_stubs.o ++ ++install-lib := libc_stubs.a ++non-lib.a := libc_stubs.a ++ ++extra-objs := gconv_stubs.o libc_stubs.a ++ ++include ../Makeconfig ++ ++CPPFLAGS += -I../iconv ++ ++include ../Rules ++ ++$(objpfx)libc_stubs.a: $(addprefix $(objpfx), $(libc_stubs-objs)) ++ -rm -f $@ ++ $(CC) -nostdlib -nostartfiles -r -o $@ $^ ++ ++lib: $(objpfx)libc_stubs.a ++ ++$(objpfx)test-stdio: $(objpfx)libc_stubs.a +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/README glibc-2.17-931-g30bbc0c.new/c_stubs/README +--- glibc-2.17-931-g30bbc0c/c_stubs/README 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/README 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,8 @@ ++This is a stub add-on library for the GNU C library version 2.1.2 and ++above. It is used to create the smaller static binaries by stubbing ++out the gconv related functions. The resulting binaries may not have ++all the functionalities. ++ ++H.J. Lu ++hjl@gnu.org ++12/05/1999 +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/test-stdio.c glibc-2.17-931-g30bbc0c.new/c_stubs/test-stdio.c +--- glibc-2.17-931-g30bbc0c/c_stubs/test-stdio.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/test-stdio.c 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,8 @@ ++#include ++ ++int ++main (void) ++{ ++ printf ("Hello world\n"); ++ return 0; ++} diff --git a/glibc-disable-rwlock-elision.patch b/glibc-disable-rwlock-elision.patch new file mode 100644 index 0000000..b782da0 --- /dev/null +++ b/glibc-disable-rwlock-elision.patch @@ -0,0 +1,22 @@ +diff -urN glibc-2.20.mod/sysdeps/unix/sysv/linux/x86/elision-conf.c glibc-2.20/sysdeps/unix/sysv/linux/x86/elision-conf.c +--- glibc-2.20.mod/sysdeps/unix/sysv/linux/x86/elision-conf.c 2014-09-27 00:25:46.443462345 -0400 ++++ glibc-2.20/sysdeps/unix/sysv/linux/x86/elision-conf.c 2014-09-27 00:29:53.586615813 -0400 +@@ -62,12 +62,16 @@ + char **argv __attribute__ ((unused)), + char **environ) + { +- __elision_available = HAS_RTM; + #ifdef ENABLE_LOCK_ELISION ++ __elision_available = HAS_RTM; + __pthread_force_elision = __libc_enable_secure ? 0 : __elision_available; +-#endif + if (!HAS_RTM) + __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks */ ++#else ++ __elision_available = 0; ++ __pthread_force_elision = 0; ++ __elision_aconf.retry_try_xbegin = 0; ++#endif + } + + #ifdef SHARED diff --git a/glibc-fedora-__libc_multiple_libcs.patch b/glibc-fedora-__libc_multiple_libcs.patch index b7ec122..dc0e950 100644 --- a/glibc-fedora-__libc_multiple_libcs.patch +++ b/glibc-fedora-__libc_multiple_libcs.patch @@ -1,6 +1,7 @@ ---- glibc-2.25.51/elf/dl-init.c.0044~ 2017-07-11 16:44:14.000000000 +0200 -+++ glibc-2.25.51/elf/dl-init.c 2017-07-11 18:44:49.173115475 +0200 -@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int +diff -up glibc-2.31.20200715/elf/dl-init.c.13~ glibc-2.31.20200715/elf/dl-init.c +--- glibc-2.31.20200715/elf/dl-init.c.13~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/elf/dl-init.c 2020-07-15 23:52:46.296238095 +0200 +@@ -120,8 +120,6 @@ _dl_init (struct link_map *main_map, int while (i-- > 0) call_init (main_map->l_initfini[i], argc, argv, env); @@ -9,9 +10,10 @@ _dl_starting_up = 0; -#endif } ---- glibc-2.25.51/elf/dl-support.c.0044~ 2017-07-11 16:44:14.000000000 +0200 -+++ glibc-2.25.51/elf/dl-support.c 2017-07-11 18:44:49.173115475 +0200 -@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli +diff -up glibc-2.31.20200715/elf/dl-support.c.13~ glibc-2.31.20200715/elf/dl-support.c +--- glibc-2.31.20200715/elf/dl-support.c.13~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/elf/dl-support.c 2020-07-15 23:52:46.296238095 +0200 +@@ -120,10 +120,8 @@ struct r_scope_elem _dl_initial_searchli .r_nlist = 1, }; @@ -22,17 +24,18 @@ /* Random data provided by the kernel. */ void *_dl_random; ---- glibc-2.25.51/elf/rtld.c.0044~ 2017-07-11 16:44:14.000000000 +0200 -+++ glibc-2.25.51/elf/rtld.c 2017-07-11 18:45:48.606706875 +0200 -@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_ - return iter->previous->name; +diff -up glibc-2.31.20200715/elf/rtld.c.13~ glibc-2.31.20200715/elf/rtld.c +--- glibc-2.31.20200715/elf/rtld.c.13~ 2020-07-15 17:58:07.000000000 +0200 ++++ glibc-2.31.20200715/elf/rtld.c 2020-07-15 23:57:44.187875422 +0200 +@@ -316,7 +316,6 @@ audit_list_count (struct audit_list *lis + return naudit; } -#ifndef HAVE_INLINED_SYSCALLS /* Set nonzero during loading and initialization of executable and libraries, cleared before the executable's entry point runs. This must not be initialized to nonzero, because the unused dynamic -@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_ +@@ -326,7 +325,6 @@ audit_list_count (struct audit_list *lis never be called. */ int _dl_starting_up = 0; rtld_hidden_def (_dl_starting_up) @@ -40,9 +43,9 @@ /* This is the structure which defines all variables global to ld.so (except those which cannot be added for some reason). */ -@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr, +@@ -1178,10 +1176,8 @@ dl_main (const ElfW(Phdr) *phdr, /* Process the environment variable which control the behaviour. */ - process_envvars (&mode); + process_envvars (&mode, &audit_list); -#ifndef HAVE_INLINED_SYSCALLS /* Set up a flag which tells we are just starting. */ diff --git a/glibc-fedora-getrlimit-PLT.patch b/glibc-fedora-getrlimit-PLT.patch new file mode 100644 index 0000000..bd77bb3 --- /dev/null +++ b/glibc-fedora-getrlimit-PLT.patch @@ -0,0 +1,45 @@ +From 70d0a630700f602a457832383161d261fe222db5 Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Thu, 1 Jul 2010 13:14:26 +0200 +Subject: [PATCH] Fix PLT reference + +* include/sys/resource.h (__getrlimit): Add hidden proto. +* sysdeps/unix/sysv/linux/i386/getrlimit.c: Add libc_hidden_weak. +* sysdeps/mach/hurd/getrlimit.c: Add libc_hidden_def. +* resource/getrlimit.c: Likewise. + +--- + ChangeLog | 7 +++++++ + include/sys/resource.h | 1 + + resource/getrlimit.c | 1 + + sysdeps/mach/hurd/getrlimit.c | 1 + + sysdeps/unix/sysv/linux/i386/getrlimit.c | 1 + + 5 files changed, 11 insertions(+), 0 deletions(-) + +--- a/include/sys/resource.h ++++ b/include/sys/resource.h +@@ -14,5 +14,6 @@ extern int __getrusage (enum __rusage_who __who, struct rusage *__usage) + + extern int __setrlimit (enum __rlimit_resource __resource, + const struct rlimit *__rlimits); ++libc_hidden_proto (__getrlimit) + #endif + #endif +--- a/resource/getrlimit.c ++++ b/resource/getrlimit.c +@@ -27,6 +27,7 @@ __getrlimit (enum __rlimit_resource resource, struct rlimit *rlimits) + __set_errno (ENOSYS); + return -1; + } ++libc_hidden_def (__getrlimit) + weak_alias (__getrlimit, getrlimit) + + stub_warning (getrlimit) +--- a/sysdeps/mach/hurd/getrlimit.c ++++ b/sysdeps/mach/hurd/getrlimit.c +@@ -43,4 +43,5 @@ __getrlimit (enum __rlimit_resource resource, struct rlimit *rlimits) + + return 0; + } ++libc_hidden_def (__getrlimit) + weak_alias (__getrlimit, getrlimit) diff --git a/glibc-fedora-i386-tls-direct-seg-refs.patch b/glibc-fedora-i386-tls-direct-seg-refs.patch deleted file mode 100644 index 80c0f0d..0000000 --- a/glibc-fedora-i386-tls-direct-seg-refs.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -Nrup a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile ---- a/sysdeps/i386/Makefile 2012-06-05 07:42:49.000000000 -0600 -+++ b/sysdeps/i386/Makefile 2012-06-07 12:15:21.826318641 -0600 -@@ -62,6 +64,14 @@ endif - - ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS))) - defines += -DNO_TLS_DIRECT_SEG_REFS -+else -+# .a libraries are not performance critical and so we -+# build them without direct TLS segment references -+# always. -+CPPFLAGS-.o += -DNO_TLS_DIRECT_SEG_REFS -+CFLAGS-.o += -mno-tls-direct-seg-refs -+CPPFLAGS-.oS += -DNO_TLS_DIRECT_SEG_REFS -+CFLAGS-.oS += -mno-tls-direct-seg-refs - endif - - ifeq ($(subdir),elf) diff --git a/glibc-fedora-nptl-linklibc.patch b/glibc-fedora-nptl-linklibc.patch deleted file mode 100644 index dcfb808..0000000 --- a/glibc-fedora-nptl-linklibc.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff -up glibc-2.27.20180720/nptl/Makefile.0034~ glibc-2.27.20180720/nptl/Makefile ---- glibc-2.27.20180720/nptl/Makefile.0034~ 2018-07-20 02:29:28.763982849 +0200 -+++ glibc-2.27.20180720/nptl/Makefile 2018-07-20 02:33:04.128058315 +0200 -@@ -623,14 +623,18 @@ $(addprefix $(objpfx), \ - $(tests) $(tests-internal) $(xtests) $(test-srcs))): \ - $(objpfx)libpthread.so - $(objpfx)tst-unload: $(libdl) --# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so, -+# $(objpfx)linklibc.so is used instead of $(common-objpfx)libc.so, - # since otherwise libpthread.so comes before libc.so when linking. - $(addprefix $(objpfx), $(tests-reverse)): \ -- $(objpfx)../libc.so $(objpfx)libpthread.so --$(objpfx)../libc.so: $(common-objpfx)libc.so ; -+ $(objpfx)linklibc.so $(objpfx)libpthread.so -+$(objpfx)linklibc.so: $(common-objpfx)libc.so ; - $(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a - - $(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so -+ -+$(objpfx)linklibc.so: $(common-objpfx)libc.so -+ ln -s ../libc.so $@ -+generated += libclink.so - else - $(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a - endif diff --git a/glibc-fedora-streams-rh436349.patch b/glibc-fedora-streams-rh436349.patch new file mode 100644 index 0000000..9334f19 --- /dev/null +++ b/glibc-fedora-streams-rh436349.patch @@ -0,0 +1,28 @@ +This is part of commit glibc-2.3.3-1564-gd0b6ac6 + +* Fri Mar 14 2008 Jakub Jelinek 2.7.90-11 +- remove , define _XOPEN_STREAMS -1 (#436349) + +diff -Nrup a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h +--- a/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600 ++++ b/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600 +@@ -188,4 +188,7 @@ + /* Typed memory objects are not available. */ + #define _POSIX_TYPED_MEMORY_OBJECTS -1 + ++/* Streams are not available. */ ++#define _XOPEN_STREAMS -1 ++ + #endif /* bits/posix_opt.h */ +diff -Nrup a/streams/Makefile b/streams/Makefile +--- a/streams/Makefile 2012-06-05 07:42:49.000000000 -0600 ++++ b/streams/Makefile 2012-06-07 12:15:21.824318649 -0600 +@@ -20,7 +20,7 @@ + + include ../Makeconfig + +-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h ++#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h + routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach + + include ../Rules diff --git a/glibc-fedora-uname-getrlimit.patch b/glibc-fedora-uname-getrlimit.patch new file mode 100644 index 0000000..dedb836 --- /dev/null +++ b/glibc-fedora-uname-getrlimit.patch @@ -0,0 +1,50 @@ +From cde99cd2b7b16a6113acb054e89d490047932a9f Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Thu, 8 Apr 2010 11:18:26 +0200 +Subject: [PATCH] Don't call uname or getrlimit in libpthread init function + +* sysdeps/unix/sysv/linux/i386/Versions: Export __uname under +GLIBC_PRIVATE. +* nptl/Versions: Export __getrlimit under GLIBC_PRIVATE. +* sysdeps/unix/sysv/linux/i386/smp.h: Call __uname instead of uname. +* nptl/nptl-init.c: Call __getrlimit instead of getrlimit. + +--- + ChangeLog | 8 ++++++++ + nptl/Versions | 1 + + nptl/nptl-init.c | 2 +- + sysdeps/unix/sysv/linux/i386/Versions | 6 ++++++ + sysdeps/unix/sysv/linux/i386/smp.h | 2 +- + 5 files changed, 17 insertions(+), 2 deletions(-) + create mode 100644 sysdeps/unix/sysv/linux/i386/Versions + +--- a/nptl/Version ++++ b/nptl/Versions +@@ -30,6 +30,7 @@ libc { + __libc_pthread_init; + __libc_current_sigrtmin_private; __libc_current_sigrtmax_private; + __libc_allocate_rtsig_private; ++ __getrlimit; + } + } + +--- a/sysdeps/unix/sysv/linux/i386/Versions ++++ b/sysdeps/unix/sysv/linux/i386/Versions +@@ -53,5 +53,6 @@ + } + GLIBC_PRIVATE { + __modify_ldt; ++ __uname; + } + } +--- a/sysdeps/unix/sysv/linux/i386/smp.h ++++ b/sysdeps/unix/sysv/linux/i386/smp.h +@@ -36,7 +36,7 @@ is_smp_system (void) + char *cp; + + /* Try reading the number using `sysctl' first. */ +- if (uname (&u.uts) == 0) ++ if (__uname (&u.uts) == 0) + cp = u.uts.version; + else + { diff --git a/glibc-new-condvar.patch b/glibc-new-condvar.patch new file mode 100644 index 0000000..747bf0d --- /dev/null +++ b/glibc-new-condvar.patch @@ -0,0 +1,6264 @@ +commit db7d3860a02a6617d4d77324185aa0547cc58391 +Author: Torvald Riegel +Date: Sun Nov 10 15:43:14 2013 +0100 + + New condvar implementation that provides stronger ordering guarantees. + +diff --git a/nptl/DESIGN-condvar.txt b/nptl/DESIGN-condvar.txt +deleted file mode 100644 +index 4845251..0000000 +--- a/nptl/DESIGN-condvar.txt ++++ /dev/null +@@ -1,134 +0,0 @@ +-Conditional Variable pseudocode. +-================================ +- +- int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex); +- int pthread_cond_signal (pthread_cond_t *cv); +- int pthread_cond_broadcast (pthread_cond_t *cv); +- +-struct pthread_cond_t { +- +- unsigned int cond_lock; +- +- internal mutex +- +- uint64_t total_seq; +- +- Total number of threads using the conditional variable. +- +- uint64_t wakeup_seq; +- +- sequence number for next wakeup. +- +- uint64_t woken_seq; +- +- sequence number of last woken thread. +- +- uint32_t broadcast_seq; +- +-} +- +- +-struct cv_data { +- +- pthread_cond_t *cv; +- +- uint32_t bc_seq +- +-} +- +- +- +-cleanup_handler(cv_data) +-{ +- cv = cv_data->cv; +- lll_lock(cv->lock); +- +- if (cv_data->bc_seq == cv->broadcast_seq) { +- ++cv->wakeup_seq; +- ++cv->woken_seq; +- } +- +- /* make sure no signal gets lost. */ +- FUTEX_WAKE(cv->wakeup_seq, ALL); +- +- lll_unlock(cv->lock); +-} +- +- +-cond_timedwait(cv, mutex, timeout): +-{ +- lll_lock(cv->lock); +- mutex_unlock(mutex); +- +- cleanup_push +- +- ++cv->total_seq; +- val = seq = cv->wakeup_seq; +- cv_data.bc = cv->broadcast_seq; +- cv_data.cv = cv; +- +- while (1) { +- +- lll_unlock(cv->lock); +- +- enable_async(&cv_data); +- +- ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); +- +- restore_async +- +- lll_lock(cv->lock); +- +- if (bc != cv->broadcast_seq) +- goto bc_out; +- +- val = cv->wakeup_seq; +- +- if (val != seq && cv->woken_seq != val) { +- ret = 0; +- break; +- } +- +- if (ret == TIMEDOUT) { +- ++cv->wakeup_seq; +- break; +- } +- } +- +- ++cv->woken_seq; +- +- bc_out: +- lll_unlock(cv->lock); +- +- cleanup_pop +- +- mutex_lock(mutex); +- +- return ret; +-} +- +-cond_signal(cv) +-{ +- lll_lock(cv->lock); +- +- if (cv->total_seq > cv->wakeup_seq) { +- ++cv->wakeup_seq; +- FUTEX_WAKE(cv->wakeup_seq, 1); +- } +- +- lll_unlock(cv->lock); +-} +- +-cond_broadcast(cv) +-{ +- lll_lock(cv->lock); +- +- if (cv->total_seq > cv->wakeup_seq) { +- cv->wakeup_seq = cv->total_seq; +- cv->woken_seq = cv->total_seq; +- ++cv->broadcast_seq; +- FUTEX_WAKE(cv->wakeup_seq, ALL); +- } +- +- lll_unlock(cv->lock); +-} +diff --git a/nptl/Makefile b/nptl/Makefile +index 89fdc8b..50a85a6 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -71,7 +71,7 @@ libpthread-routines = nptl-init vars events version \ + pthread_rwlockattr_getkind_np \ + pthread_rwlockattr_setkind_np \ + pthread_cond_init pthread_cond_destroy \ +- pthread_cond_wait pthread_cond_timedwait \ ++ pthread_cond_wait \ + pthread_cond_signal pthread_cond_broadcast \ + old_pthread_cond_init old_pthread_cond_destroy \ + old_pthread_cond_wait old_pthread_cond_timedwait \ +@@ -178,7 +178,6 @@ CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables + CFLAGS-pthread_once.c = $(uses-callbacks) -fexceptions \ + -fasynchronous-unwind-tables + CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables +-CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables + CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables + CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables + +@@ -216,7 +215,7 @@ tests = tst-typesizes \ + tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ + tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ + tst-cond20 tst-cond21 tst-cond22 tst-cond23 tst-cond24 tst-cond25 \ +- tst-cond-except \ ++ tst-cond26 tst-cond27 tst-cond28 tst-cond-except \ + tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ + tst-robust6 tst-robust7 tst-robust8 tst-robust9 \ + tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \ +@@ -280,8 +279,7 @@ test-srcs = tst-oddstacklimit + # Files which must not be linked with libpthread. + tests-nolibpthread = tst-unload + +-gen-as-const-headers = pthread-errnos.sym \ +- lowlevelcond.sym lowlevelrwlock.sym \ ++gen-as-const-headers = pthread-errnos.sym lowlevelrwlock.sym \ + lowlevelbarrier.sym unwindbuf.sym \ + lowlevelrobustlock.sym pthread-pi-defines.sym + +diff --git a/nptl/lowlevelcond.sym b/nptl/lowlevelcond.sym +deleted file mode 100644 +index 18e1ada..0000000 +--- a/nptl/lowlevelcond.sym ++++ /dev/null +@@ -1,16 +0,0 @@ +-#include +-#include +-#include +-#include +- +--- +- +-cond_lock offsetof (pthread_cond_t, __data.__lock) +-cond_futex offsetof (pthread_cond_t, __data.__futex) +-cond_nwaiters offsetof (pthread_cond_t, __data.__nwaiters) +-total_seq offsetof (pthread_cond_t, __data.__total_seq) +-wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) +-woken_seq offsetof (pthread_cond_t, __data.__woken_seq) +-dep_mutex offsetof (pthread_cond_t, __data.__mutex) +-broadcast_seq offsetof (pthread_cond_t, __data.__broadcast_seq) +-nwaiters_shift COND_NWAITERS_SHIFT +diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c +index 881d098..6848d61 100644 +--- a/nptl/pthread_cond_broadcast.c ++++ b/nptl/pthread_cond_broadcast.c +@@ -23,69 +23,74 @@ + #include + #include + #include ++#include + + #include + #include + + ++/* See __pthread_cond_wait for a high-level description of the algorithm. */ + int +-__pthread_cond_broadcast (cond) +- pthread_cond_t *cond; ++__pthread_cond_broadcast (pthread_cond_t *cond) + { +- LIBC_PROBE (cond_broadcast, 1, cond); ++ unsigned int gen, wseq, ssent; + +- int pshared = (cond->__data.__mutex == (void *) ~0l) ++ /* See comment in __pthread_cond_signal. */ ++ int pshared = (atomic_load_relaxed (&cond->__data.__mutex) == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; +- /* Make sure we are alone. */ +- lll_lock (cond->__data.__lock, pshared); +- +- /* Are there any waiters to be woken? */ +- if (cond->__data.__total_seq > cond->__data.__wakeup_seq) +- { +- /* Yes. Mark them all as woken. */ +- cond->__data.__wakeup_seq = cond->__data.__total_seq; +- cond->__data.__woken_seq = cond->__data.__total_seq; +- cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2; +- int futex_val = cond->__data.__futex; +- /* Signal that a broadcast happened. */ +- ++cond->__data.__broadcast_seq; +- +- /* We are done. */ +- lll_unlock (cond->__data.__lock, pshared); + +- /* Wake everybody. */ +- pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; +- +- /* Do not use requeue for pshared condvars. */ +- if (mut == (void *) ~0l +- || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT) +- goto wake_all; ++ LIBC_PROBE (cond_broadcast, 1, cond); + +-#if (defined lll_futex_cmp_requeue_pi \ +- && defined __ASSUME_REQUEUE_PI) +- if (USE_REQUEUE_PI (mut)) +- { +- if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX, +- &mut->__data.__lock, futex_val, +- LLL_PRIVATE) == 0) +- return 0; +- } +- else +-#endif +- /* lll_futex_requeue returns 0 for success and non-zero +- for errors. */ +- if (!__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, +- INT_MAX, &mut->__data.__lock, +- futex_val, LLL_PRIVATE), 0)) +- return 0; ++ /* We use the same approach for broadcasts as for normal signals but wake ++ all waiters (i.e., we try to set SIGNALS_SENT to WSEQ). However, to ++ prevent an excessive number of spurious wake-ups, we need to check ++ whether we read values for SIGNALS_SENT and WSEQ that are from one ++ generation; otherwise, we could read a not-yet-reset WSEQ and a reset ++ SIGNAL_SENT, resulting in a very large number of spurious wake-ups that ++ we make available. Checking the generation won't prevent an ABA problem ++ for the CAS in the loop below when the generation changes between our ++ generation check and the CAS; however, in this case, we just add a still ++ reasonable number of spurious wake-ups (i.e., equal to the number of ++ waiters than were actually blocked on the condvar at some point in the ++ past). Therefore, we first load the current generation. We need ++ acquire MO here to make sure that we next read values for WSEQ and ++ SIGNALS_SENT from this or a later generation (see the matching release ++ MOs in __pthread_cond_wait). */ ++ gen = atomic_load_acquire (&cond->__data.__generation); ++ wseq = atomic_load_relaxed (&cond->__data.__wseq); ++ ssent = atomic_load_relaxed (&cond->__data.__signals_sent); ++ do ++ { + +-wake_all: +- lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared); +- return 0; ++ /* If the generation changed concurrently, then we could have been ++ positioned in the earlier generation; thus, all waiters we must wake ++ have been or will be woken during the quiescence period. The other ++ conditions are the same as in __pthread_cond_signal. ++ We add an acquire-MO fence to ensure that loading the stores to WSEQ ++ and SIGNALS_SENT that we read from above happened before we read ++ GENERATION a second time, which allows us to detect if we read ++ partially reset state or state from a new generation (see ++ __pthread_cond_wait and the matching release MO stores there). */ ++ atomic_thread_fence_acquire (); ++ if (gen != atomic_load_relaxed (&cond->__data.__generation) ++ || ssent >= wseq || wseq >= __PTHREAD_COND_WSEQ_THRESHOLD) ++ return 0; + } +- +- /* We are done. */ +- lll_unlock (cond->__data.__lock, pshared); ++ while (!atomic_compare_exchange_weak_relaxed (&cond->__data.__signals_sent, ++ &ssent, wseq)); ++ ++ /* XXX Could we skip the futex_wake if not necessary (eg, if there are just ++ spinning waiters)? This would need additional communication but could it ++ be more efficient than the kernel-side communication? Should we spin for ++ a while to see if our signal was consumed in the meantime? */ ++ /* TODO Use futex_requeue on the mutex? Could increase broadcast scalability ++ if there are many waiters, but this depends on the scalability of the ++ mutex. It also prevents use of lock elision, and requires all waiters ++ to put the mutex in contended state when they re-acquire it, independent ++ of whether they were woken by a broadcast or not. Notes that we can only ++ requeue if the mutex is set already (ie, we had waiters already). */ ++ /* XXX Really INT_MAX? Would WSEQ-SIGNALS_SENT be possible? Useful? */ ++ lll_futex_wake (&cond->__data.__signals_sent, INT_MAX, pshared); + + return 0; + } +diff --git a/nptl/pthread_cond_destroy.c b/nptl/pthread_cond_destroy.c +index 410e52d..7c9cf13 100644 +--- a/nptl/pthread_cond_destroy.c ++++ b/nptl/pthread_cond_destroy.c +@@ -20,67 +20,94 @@ + #include + #include "pthreadP.h" + #include +- +- ++#include ++ ++ ++/* See __pthread_cond_wait for a high-level description of the algorithm. ++ ++ A correct program must make sure that no waiters are blocked on the condvar ++ when it is destroyed, and that there are no concurrent signals or ++ broadcasts. To wake waiters reliably, the program must signal or ++ broadcast while holding the mutex or after having held the mutex. It must ++ also ensure that no signal or broadcast are still pending to unblock ++ waiters; IOW, because waiters can wake up spuriously, the program must ++ effectively ensure that destruction happens after the execution of those ++ signal or broadcast calls. ++ Thus, we can assume that any waiters that are still accessing the condvar ++ will either (1) have been woken but not yet confirmed that they woke up or ++ (2) wait for quiescence to finish (i.e., the only steps they will perform ++ are waiting on GENERATION and then decrementing QUIESCENCE_WAITERS; all ++ other steps related to quiescence are performed by waiters before they ++ release the mutex). ++ Thus, if we are not yet in an ongoing quiescence state, we just make ++ the last concurrently confirming waiter believe we are so that it notifies ++ us; then we wait for QUIESCENCE_WAITERS to finish waiting for the end of ++ the quiescence state. */ + int +-__pthread_cond_destroy (cond) +- pthread_cond_t *cond; ++__pthread_cond_destroy (pthread_cond_t *cond) + { +- int pshared = (cond->__data.__mutex == (void *) ~0l) ++ unsigned int wseq, val; ++ ++ /* See comment in __pthread_cond_signal. */ ++ int pshared = (atomic_load_relaxed (&cond->__data.__mutex) == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + LIBC_PROBE (cond_destroy, 1, cond); + +- /* Make sure we are alone. */ +- lll_lock (cond->__data.__lock, pshared); +- +- if (cond->__data.__total_seq > cond->__data.__wakeup_seq) +- { +- /* If there are still some waiters which have not been +- woken up, this is an application bug. */ +- lll_unlock (cond->__data.__lock, pshared); +- return EBUSY; +- } +- +- /* Tell pthread_cond_*wait that this condvar is being destroyed. */ +- cond->__data.__total_seq = -1ULL; +- +- /* If there are waiters which have been already signalled or +- broadcasted, but still are using the pthread_cond_t structure, +- pthread_cond_destroy needs to wait for them. */ +- unsigned int nwaiters = cond->__data.__nwaiters; +- +- if (nwaiters >= (1 << COND_NWAITERS_SHIFT)) ++ /* If we are already in the quiescence state, then signals and broadcasts ++ will not modify SIGNALS_SENT anymore because all waiters will wake up ++ anyway (and we don't have to synchronize between signal/broadcast and the ++ reset of SIGNALS_SENT when quiescence is finished). Thus, never do the ++ following check in this case; it cannot be reliably anyway, and is also ++ just recommended by POSIX. */ ++ wseq = atomic_load_relaxed (&cond->__data.__wseq); ++ if (wseq != __PTHREAD_COND_WSEQ_THRESHOLD ++ && wseq > atomic_load_relaxed (&cond->__data.__signals_sent)) ++ return EBUSY; ++ ++ /* Waiters can either be (1) pending to confirm that they have been woken ++ or (2) spinning/blocking on GENERATION to become odd. Thus, we first ++ need to make sure that any waiter woken by the program has finished the ++ condvar-internal synchronization (i.e., it has confirmed the wake-up). ++ We use the quiescence mechanism to get notified when all of them are ++ finished by adding the right amount of artificial confirmed waiters. ++ XXX Or is just relaxed MO sufficient because happens-before is ++ established through the total modification order on CONFIRMED? */ ++ if (atomic_fetch_add_acq_rel (&cond->__data.__confirmed, ++ __PTHREAD_COND_WSEQ_THRESHOLD - wseq) ++ < wseq) + { +- /* Wake everybody on the associated mutex in case there are +- threads that have been requeued to it. +- Without this, pthread_cond_destroy could block potentially +- for a long time or forever, as it would depend on other +- thread's using the mutex. +- When all threads waiting on the mutex are woken up, pthread_cond_wait +- only waits for threads to acquire and release the internal +- condvar lock. */ +- if (cond->__data.__mutex != NULL +- && cond->__data.__mutex != (void *) ~0l) ++ /* There are waiters that haven't yet confirmed. If we have an even ++ number for generation, wait until it is changed by the last waiter ++ to confirm. (The last waiter will increase to WSEQ_THRESHOLD, so ++ it will increase GENERATION to an odd value.) We need acquire MO ++ to make any waiters' accesses to the condvar happen before we ++ destroy it.*/ ++ while (1) + { +- pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; +- lll_futex_wake (&mut->__data.__lock, INT_MAX, +- PTHREAD_MUTEX_PSHARED (mut)); ++ val = atomic_load_acquire (&cond->__data.__generation); ++ if ((val & 1) != 1) ++ lll_futex_wait (&cond->__data.__generation, val, pshared); ++ else ++ break; + } ++ } + +- do +- { +- lll_unlock (cond->__data.__lock, pshared); +- +- lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared); +- +- lll_lock (cond->__data.__lock, pshared); +- +- nwaiters = cond->__data.__nwaiters; +- } +- while (nwaiters >= (1 << COND_NWAITERS_SHIFT)); ++ /* If we are in a quiescence period, we also need to wait for those waiters ++ that are waiting for quiescence to finish. Note that we cannot have ++ pushed waiters into this state by artificially introducing quiescence ++ above, so we also do not wake any such waiters. As above, we need ++ acquire MO. */ ++ while (1) ++ { ++ val = atomic_load_acquire (&cond->__data.__quiescence_waiters); ++ if (val > 0) ++ lll_futex_wait (&cond->__data.__quiescence_waiters, val, pshared); ++ else ++ break; + } + ++ /* The memory the condvar occupies can now be reused. */ + return 0; + } + versioned_symbol (libpthread, __pthread_cond_destroy, +diff --git a/nptl/pthread_cond_init.c b/nptl/pthread_cond_init.c +index ce954c7..b3aa779 100644 +--- a/nptl/pthread_cond_init.c ++++ b/nptl/pthread_cond_init.c +@@ -28,18 +28,17 @@ __pthread_cond_init (cond, cond_attr) + { + struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr; + +- cond->__data.__lock = LLL_LOCK_INITIALIZER; +- cond->__data.__futex = 0; +- cond->__data.__nwaiters = (icond_attr != NULL +- ? ((icond_attr->value >> 1) +- & ((1 << COND_NWAITERS_SHIFT) - 1)) +- : CLOCK_REALTIME); +- cond->__data.__total_seq = 0; +- cond->__data.__wakeup_seq = 0; +- cond->__data.__woken_seq = 0; ++ cond->__data.__wseq = 0; ++ cond->__data.__signals_sent = 0; ++ cond->__data.__confirmed = 0; ++ cond->__data.__generation = 0; + cond->__data.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0 + ? NULL : (void *) ~0l); +- cond->__data.__broadcast_seq = 0; ++ cond->__data.__quiescence_waiters = 0; ++ cond->__data.__clockid = (icond_attr != NULL ++ ? ((icond_attr->value >> 1) ++ & ((1 << COND_CLOCK_BITS) - 1)) ++ : CLOCK_REALTIME); + + LIBC_PROBE (cond_init, 2, cond, cond_attr); + +diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c +index ba32f40..86968e9 100644 +--- a/nptl/pthread_cond_signal.c ++++ b/nptl/pthread_cond_signal.c +@@ -22,60 +22,88 @@ + #include + #include + #include ++#include + + #include + #include + #include + + ++/* See __pthread_cond_wait for a high-level description of the algorithm. */ + int +-__pthread_cond_signal (cond) +- pthread_cond_t *cond; ++__pthread_cond_signal (pthread_cond_t *cond) + { +- int pshared = (cond->__data.__mutex == (void *) ~0l) ++ unsigned int wseq, ssent; ++ ++ /* MUTEX might get modified concurrently, but relaxed memory order is fine: ++ In case of a shared condvar, the field will be set to value ~0l during ++ initialization of the condvar (which happens before any signaling) and ++ is immutable afterwards; otherwise, the field will never be set to a ++ value of ~0l. */ ++ int pshared = (atomic_load_relaxed (&cond->__data.__mutex) == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + LIBC_PROBE (cond_signal, 1, cond); + +- /* Make sure we are alone. */ +- lll_lock (cond->__data.__lock, pshared); +- +- /* Are there any waiters to be woken? */ +- if (cond->__data.__total_seq > cond->__data.__wakeup_seq) ++ /* Load the waiter sequence number, which represents our relative ordering ++ to any waiters. Also load the number of signals sent so far. ++ We do not need stronger MOs for both loads nor an atomic snapshot of both ++ because: ++ 1) We can pick any position that is allowed by external happens-before ++ constraints. In particular, if another __pthread_cond_wait call ++ happened before us, this waiter must be eligible for being woken by ++ us. The only way do establish such a happens-before is by signaling ++ while holding the mutex associated with the condvar and ensuring that ++ the signal's critical section happens after the waiter. Thus, the ++ mutex ensures that we see this waiter's wseq increase. ++ 2) Once we pick a position, we do not need to communicate this to the ++ program via a happens-before that we set up: First, any wake-up could ++ be a spurious wake-up, so the program must not interpret a wake-up as ++ an indication that the waiter happened before a particular signal; ++ second, a program cannot detect whether a waiter has not yet been ++ woken (i.e., it cannot distinguish between a non-woken waiter and one ++ that has been woken but hasn't resumed execution yet), and thus it ++ cannot try to deduce that a signal happened before a particular ++ waiter. ++ 3) The load of WSEQ does not need to constrain which value we load for ++ SIGNALS_SENT: If we read an older value for SIGNALS_SENT (compared to ++ what would have been current if we had an atomic snapshot of both), ++ we might send a signal even if we don't need to; thus, we just get a ++ spurious wakeup. If we read a more recent value (again, compared to ++ an atomic snapshot), then some other signal interfered and might have ++ taken "our" position in the waiter/wake-up sequence; thus the waiters ++ we had to wake will get woken either way. ++ Note that we do not need to check whether the generation changed ++ concurrently: If it would change, we would just skip any signaling ++ because we could have been positioned in the earlier generation -- all ++ the waiters we would have to wake will have been woken during the ++ quiescence period. Thus, at worst we will cause one additional spurious ++ wake-up if we don't detect this. */ ++ wseq = atomic_load_relaxed (&cond->__data.__wseq); ++ ssent = atomic_load_relaxed (&cond->__data.__signals_sent); ++ do + { +- /* Yes. Mark one of them as woken. */ +- ++cond->__data.__wakeup_seq; +- ++cond->__data.__futex; +- +-#if (defined lll_futex_cmp_requeue_pi \ +- && defined __ASSUME_REQUEUE_PI) +- pthread_mutex_t *mut = cond->__data.__mutex; +- +- if (USE_REQUEUE_PI (mut) +- /* This can only really fail with a ENOSYS, since nobody can modify +- futex while we have the cond_lock. */ +- && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0, +- &mut->__data.__lock, +- cond->__data.__futex, pshared) == 0) +- { +- lll_unlock (cond->__data.__lock, pshared); +- return 0; +- } +- else +-#endif +- /* Wake one. */ +- if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex, +- 1, 1, +- &cond->__data.__lock, +- pshared), 0)) +- return 0; +- +- /* Fallback if neither of them work. */ +- lll_futex_wake (&cond->__data.__futex, 1, pshared); ++ /* If we don't have more waiters than signals or are in a quiescence ++ period, just return because all waiters we must wake have been or ++ will be woken. See above for further details. */ ++ if (ssent >= wseq || wseq >= __PTHREAD_COND_WSEQ_THRESHOLD) ++ return 0; + } +- +- /* We are done. */ +- lll_unlock (cond->__data.__lock, pshared); ++ /* Using a CAS loop here instead of a fetch-and-increment avoids one source ++ of spurious wake-ups, namely several signalers racing to wake up a fewer ++ number of waiters and thus also waking subsequent waiters spuriously. ++ The cost of this is somewhat more contention on SIGNALS_SENT on archs ++ that offer atomic fetch-and-increment. ++ TODO Relaxed MO is sufficient here. ++ */ ++ while (!atomic_compare_exchange_weak_relaxed (&cond->__data.__signals_sent, ++ &ssent, ssent + 1)); ++ ++ /* XXX Could we skip the futex_wake if not necessary (eg, if there are just ++ spinning waiters)? This would need additional communication but could it ++ be more efficient than the kernel-side communication? Should we spin for ++ a while to see if our signal was consumed in the meantime? */ ++ lll_futex_wake (&cond->__data.__signals_sent, 1, pshared); + + return 0; + } +diff --git a/nptl/pthread_cond_timedwait.c b/nptl/pthread_cond_timedwait.c +deleted file mode 100644 +index bf80467..0000000 +--- a/nptl/pthread_cond_timedwait.c ++++ /dev/null +@@ -1,268 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Martin Schwidefsky , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#ifndef HAVE_CLOCK_GETTIME_VSYSCALL +-# undef INTERNAL_VSYSCALL +-# define INTERNAL_VSYSCALL INTERNAL_SYSCALL +-# undef INLINE_VSYSCALL +-# define INLINE_VSYSCALL INLINE_SYSCALL +-#else +-# include +-#endif +- +-/* Cleanup handler, defined in pthread_cond_wait.c. */ +-extern void __condvar_cleanup (void *arg) +- __attribute__ ((visibility ("hidden"))); +- +-struct _condvar_cleanup_buffer +-{ +- int oldtype; +- pthread_cond_t *cond; +- pthread_mutex_t *mutex; +- unsigned int bc_seq; +-}; +- +-int +-__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, +- const struct timespec *abstime) +-{ +- struct _pthread_cleanup_buffer buffer; +- struct _condvar_cleanup_buffer cbuffer; +- int result = 0; +- +- /* Catch invalid parameters. */ +- if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) +- return EINVAL; +- +- int pshared = (cond->__data.__mutex == (void *) ~0l) +- ? LLL_SHARED : LLL_PRIVATE; +- +-#if (defined lll_futex_timed_wait_requeue_pi \ +- && defined __ASSUME_REQUEUE_PI) +- int pi_flag = 0; +-#endif +- +- /* Make sure we are alone. */ +- lll_lock (cond->__data.__lock, pshared); +- +- /* Now we can release the mutex. */ +- int err = __pthread_mutex_unlock_usercnt (mutex, 0); +- if (err) +- { +- lll_unlock (cond->__data.__lock, pshared); +- return err; +- } +- +- /* We have one new user of the condvar. */ +- ++cond->__data.__total_seq; +- ++cond->__data.__futex; +- cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT; +- +- /* Work around the fact that the kernel rejects negative timeout values +- despite them being valid. */ +- if (__glibc_unlikely (abstime->tv_sec < 0)) +- goto timeout; +- +- /* Remember the mutex we are using here. If there is already a +- different address store this is a bad user bug. Do not store +- anything for pshared condvars. */ +- if (cond->__data.__mutex != (void *) ~0l) +- cond->__data.__mutex = mutex; +- +- /* Prepare structure passed to cancellation handler. */ +- cbuffer.cond = cond; +- cbuffer.mutex = mutex; +- +- /* Before we block we enable cancellation. Therefore we have to +- install a cancellation handler. */ +- __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); +- +- /* The current values of the wakeup counter. The "woken" counter +- must exceed this value. */ +- unsigned long long int val; +- unsigned long long int seq; +- val = seq = cond->__data.__wakeup_seq; +- /* Remember the broadcast counter. */ +- cbuffer.bc_seq = cond->__data.__broadcast_seq; +- +- while (1) +- { +-#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ +- || !defined lll_futex_timed_wait_bitset) +- struct timespec rt; +- { +-# ifdef __NR_clock_gettime +- INTERNAL_SYSCALL_DECL (err); +- (void) INTERNAL_VSYSCALL (clock_gettime, err, 2, +- (cond->__data.__nwaiters +- & ((1 << COND_NWAITERS_SHIFT) - 1)), +- &rt); +- /* Convert the absolute timeout value to a relative timeout. */ +- rt.tv_sec = abstime->tv_sec - rt.tv_sec; +- rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec; +-# else +- /* Get the current time. So far we support only one clock. */ +- struct timeval tv; +- (void) __gettimeofday (&tv, NULL); +- +- /* Convert the absolute timeout value to a relative timeout. */ +- rt.tv_sec = abstime->tv_sec - tv.tv_sec; +- rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +-# endif +- } +- if (rt.tv_nsec < 0) +- { +- rt.tv_nsec += 1000000000; +- --rt.tv_sec; +- } +- /* Did we already time out? */ +- if (__glibc_unlikely (rt.tv_sec < 0)) +- { +- if (cbuffer.bc_seq != cond->__data.__broadcast_seq) +- goto bc_out; +- +- goto timeout; +- } +-#endif +- +- unsigned int futex_val = cond->__data.__futex; +- +- /* Prepare to wait. Release the condvar futex. */ +- lll_unlock (cond->__data.__lock, pshared); +- +- /* Enable asynchronous cancellation. Required by the standard. */ +- cbuffer.oldtype = __pthread_enable_asynccancel (); +- +-/* REQUEUE_PI was implemented after FUTEX_CLOCK_REALTIME, so it is sufficient +- to check just the former. */ +-#if (defined lll_futex_timed_wait_requeue_pi \ +- && defined __ASSUME_REQUEUE_PI) +- /* If pi_flag remained 1 then it means that we had the lock and the mutex +- but a spurious waker raced ahead of us. Give back the mutex before +- going into wait again. */ +- if (pi_flag) +- { +- __pthread_mutex_cond_lock_adjust (mutex); +- __pthread_mutex_unlock_usercnt (mutex, 0); +- } +- pi_flag = USE_REQUEUE_PI (mutex); +- +- if (pi_flag) +- { +- unsigned int clockbit = (cond->__data.__nwaiters & 1 +- ? 0 : FUTEX_CLOCK_REALTIME); +- err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex, +- futex_val, abstime, clockbit, +- &mutex->__data.__lock, +- pshared); +- pi_flag = (err == 0); +- } +- else +-#endif +- +- { +-#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ +- || !defined lll_futex_timed_wait_bitset) +- /* Wait until woken by signal or broadcast. */ +- err = lll_futex_timed_wait (&cond->__data.__futex, +- futex_val, &rt, pshared); +-#else +- unsigned int clockbit = (cond->__data.__nwaiters & 1 +- ? 0 : FUTEX_CLOCK_REALTIME); +- err = lll_futex_timed_wait_bitset (&cond->__data.__futex, futex_val, +- abstime, clockbit, pshared); +-#endif +- } +- +- /* Disable asynchronous cancellation. */ +- __pthread_disable_asynccancel (cbuffer.oldtype); +- +- /* We are going to look at shared data again, so get the lock. */ +- lll_lock (cond->__data.__lock, pshared); +- +- /* If a broadcast happened, we are done. */ +- if (cbuffer.bc_seq != cond->__data.__broadcast_seq) +- goto bc_out; +- +- /* Check whether we are eligible for wakeup. */ +- val = cond->__data.__wakeup_seq; +- if (val != seq && cond->__data.__woken_seq != val) +- break; +- +- /* Not woken yet. Maybe the time expired? */ +- if (__glibc_unlikely (err == -ETIMEDOUT)) +- { +- timeout: +- /* Yep. Adjust the counters. */ +- ++cond->__data.__wakeup_seq; +- ++cond->__data.__futex; +- +- /* The error value. */ +- result = ETIMEDOUT; +- break; +- } +- } +- +- /* Another thread woken up. */ +- ++cond->__data.__woken_seq; +- +- bc_out: +- +- cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT; +- +- /* If pthread_cond_destroy was called on this variable already, +- notify the pthread_cond_destroy caller all waiters have left +- and it can be successfully destroyed. */ +- if (cond->__data.__total_seq == -1ULL +- && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT)) +- lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); +- +- /* We are done with the condvar. */ +- lll_unlock (cond->__data.__lock, pshared); +- +- /* The cancellation handling is back to normal, remove the handler. */ +- __pthread_cleanup_pop (&buffer, 0); +- +- /* Get the mutex before returning. */ +-#if (defined lll_futex_timed_wait_requeue_pi \ +- && defined __ASSUME_REQUEUE_PI) +- if (pi_flag) +- { +- __pthread_mutex_cond_lock_adjust (mutex); +- err = 0; +- } +- else +-#endif +- err = __pthread_mutex_cond_lock (mutex); +- +- return err ?: result; +-} +- +-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +- GLIBC_2_3_2); +diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c +index 0d6558b..2106bf6 100644 +--- a/nptl/pthread_cond_wait.c ++++ b/nptl/pthread_cond_wait.c +@@ -22,216 +22,555 @@ + #include + #include + #include +-#include ++#include ++#include + + #include + #include ++#include ++ ++#ifndef HAVE_CLOCK_GETTIME_VSYSCALL ++# undef INTERNAL_VSYSCALL ++# define INTERNAL_VSYSCALL INTERNAL_SYSCALL ++# undef INLINE_VSYSCALL ++# define INLINE_VSYSCALL INLINE_SYSCALL ++#else ++# include ++#endif + + struct _condvar_cleanup_buffer + { + int oldtype; + pthread_cond_t *cond; + pthread_mutex_t *mutex; +- unsigned int bc_seq; + }; + +- +-void +-__attribute__ ((visibility ("hidden"))) +-__condvar_cleanup (void *arg) ++static __always_inline void ++__condvar_confirm_wakeup (pthread_cond_t *cond, int pshared) + { +- struct _condvar_cleanup_buffer *cbuffer = +- (struct _condvar_cleanup_buffer *) arg; +- unsigned int destroying; +- int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l) +- ? LLL_SHARED : LLL_PRIVATE; +- +- /* We are going to modify shared data. */ +- lll_lock (cbuffer->cond->__data.__lock, pshared); +- +- if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq) ++ /* Confirm that we have been woken. If the number of confirmations reaches ++ WSEQ_THRESHOLD, we must be in a quiescence period (i.e., WSEQ must be ++ equal to WSEQ_THRESHOLD). ++ We use acquire-release MO to ensure that accesses to this generation's ++ condvar state happen before any reset of the condvar. ++ XXX Or is just relaxed MO sufficient because happens-before is ++ established through the total modification order on CONFIRMED? */ ++ if (atomic_fetch_add_acq_rel (&cond->__data.__confirmed, 1) ++ == __PTHREAD_COND_WSEQ_THRESHOLD - 1) + { +- /* This thread is not waiting anymore. Adjust the sequence counters +- appropriately. We do not increment WAKEUP_SEQ if this would +- bump it over the value of TOTAL_SEQ. This can happen if a thread +- was woken and then canceled. */ +- if (cbuffer->cond->__data.__wakeup_seq +- < cbuffer->cond->__data.__total_seq) +- { +- ++cbuffer->cond->__data.__wakeup_seq; +- ++cbuffer->cond->__data.__futex; +- } +- ++cbuffer->cond->__data.__woken_seq; ++ /* Need release MO to make our accesses to the condvar happen before ++ the reset that some other thread will execute. */ ++ atomic_fetch_add_release (&cond->__data.__generation, 1); ++ lll_futex_wake (&cond->__data.__generation, INT_MAX, pshared); + } + +- cbuffer->cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT; ++} ++ ++/* Cancel waiting after having registered as a waiter already. ++ We must not consume another waiter's signal, so we must add an artificial ++ signal. If we are the first blocked waiter (i.e., SEQ == SIGNALS_SENT, ++ SEQ being our position in WSEQ), then an artificial signal is obviously ++ fine. If we are blocked (i.e., SEQ > SIGNALS_SENT), then a fake signal ++ might lead to spurious wake-ups of waiters with a smaller position in WSEQ; ++ however, not adding the artificial signal could prevent wake-up of waiters ++ with a larger position in WSEQ because we weren't actually waiting yet ++ effectively consume a signal because we have reserved a slot in WSEQ. If ++ we are not blocked anymore (i.e., SEQ < SIGNALS_SENT), we still have to ++ add the artificial signal if there are still unblocked threads (i.e., ++ SIGNALS_SENT < WSEQ). */ ++static __always_inline void ++__condvar_cancel_waiting (pthread_cond_t *cond, int pshared) ++{ ++ unsigned int wseq, ssent; + +- /* If pthread_cond_destroy was called on this variable already, +- notify the pthread_cond_destroy caller all waiters have left +- and it can be successfully destroyed. */ +- destroying = 0; +- if (cbuffer->cond->__data.__total_seq == -1ULL +- && cbuffer->cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT)) ++ /* Add an artificial signal. See __pthread_cond_signal. */ ++ wseq = atomic_load_relaxed (&cond->__data.__wseq); ++ ssent = atomic_load_relaxed (&cond->__data.__signals_sent); ++ do + { +- lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1, pshared); +- destroying = 1; ++ if (ssent >= wseq || wseq >= __PTHREAD_COND_WSEQ_THRESHOLD) ++ break; + } ++ while (!atomic_compare_exchange_weak_relaxed (&cond->__data.__signals_sent, ++ &ssent, ssent + 1)); ++} + +- /* We are done. */ +- lll_unlock (cbuffer->cond->__data.__lock, pshared); +- +- /* Wake everybody to make sure no condvar signal gets lost. */ +- if (! destroying) +- lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX, pshared); +- +- /* Get the mutex before returning unless asynchronous cancellation +- is in effect. We don't try to get the mutex if we already own it. */ +- if (!(USE_REQUEUE_PI (cbuffer->mutex)) +- || ((cbuffer->mutex->__data.__lock & FUTEX_TID_MASK) +- != THREAD_GETMEM (THREAD_SELF, tid))) +- { +- __pthread_mutex_cond_lock (cbuffer->mutex); +- } +- else +- __pthread_mutex_cond_lock_adjust (cbuffer->mutex); ++/* Clean-up for cancellation of waiters waiting for normal signals. We cancel ++ our registration as a waiter, confirm we have woken up, and re-acquire the ++ mutex. */ ++static void ++__condvar_cleanup_waiting (void *arg) ++{ ++ struct _condvar_cleanup_buffer *cbuffer = ++ (struct _condvar_cleanup_buffer *) arg; ++ pthread_cond_t *cond = cbuffer->cond; ++ /* See comment in __pthread_cond_signal. */ ++ int pshared = (atomic_load_relaxed (&cond->__data.__mutex) == (void *) ~0l) ++ ? LLL_SHARED : LLL_PRIVATE; ++ ++ __condvar_cancel_waiting (cond, pshared); ++ __condvar_confirm_wakeup (cond, pshared); ++ ++ /* Cancellation can happen after we have been woken by a signal's ++ futex_wake (unlike when we cancel waiting due to a timeout on futex_wait, ++ for example). We do provide an artificial signal in ++ __condvar_cancel_waiting, but we still can have consumed a futex_wake ++ that should have woken another waiter. We cannot reliably wake this ++ waiter because there might be other, non-eligible waiters that started ++ to block after we have been cancelled; therefore, we need to wake all ++ blocked waiters to really undo our consumption of the futex_wake. */ ++ /* XXX Once we have implemented a form of cancellation that is just enabled ++ during futex_wait, we can try to optimize this. */ ++ lll_futex_wake (&cond->__data.__signals_sent, INT_MAX, pshared); ++ ++ /* XXX If locking the mutex fails, should we just stop execution? This ++ might be better than silently ignoring the error. */ ++ __pthread_mutex_cond_lock (cbuffer->mutex); + } + ++/* Clean-up for cancellation of waiters waiting on quiescence to finish. */ ++static void ++__condvar_cleanup_quiescence (void *arg) ++{ ++ struct _condvar_cleanup_buffer *cbuffer = ++ (struct _condvar_cleanup_buffer *) arg; ++ pthread_cond_t *cond = cbuffer->cond; ++ /* See comment in __pthread_cond_signal. */ ++ int pshared = (atomic_load_relaxed (&cond->__data.__mutex) == (void *) ~0l) ++ ? LLL_SHARED : LLL_PRIVATE; + +-int +-__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) ++ /* See __pthread_cond_wait. */ ++ if (atomic_fetch_add_release (&cond->__data.__quiescence_waiters, -1) == 1) ++ lll_futex_wake (&cond->__data.__quiescence_waiters, INT_MAX, ++ pshared); ++ ++ /* XXX If locking the mutex fails, should we just stop execution? This ++ might be better than silently ignoring the error. */ ++ __pthread_mutex_cond_lock (cbuffer->mutex); ++} ++ ++/* This condvar implementation guarantees that all calls to signal and ++ broadcast and all of the three virtually atomic parts of each call to wait ++ (i.e., (1) releasing the mutex and blocking, (2) unblocking, and (3) re- ++ acquiring the mutex) happen in some total order that is consistent with the ++ happens-before relations in the calling program. However, this order does ++ not necessarily result in additional happens-before relations being ++ established (which aligns well with spurious wake-ups being allowed). ++ ++ All waiters acquire a certain position in a waiter sequence, WSEQ. Signals ++ and broadcasts acquire a position or a whole interval in the SIGNALS_SENT ++ sequence. Waiters are allowed to wake up if either SIGNALS_SENT is larger ++ or equal to their position in WSEQ, or if they have been blocked on a ++ certain futex and selected by the kernel to wake up after a signal or ++ broadcast woke threads that were blocked on this futex. This is also the ++ primary source for spurious wake-ups: For waiters W1 and W2 with W2's ++ position in WSEQ larger than W1's, if W2 blocks earlier than W1 using this ++ futex, then a signal will wake both W1 and W2. However, having the ++ possibility of waking waiters spuriously simplifies the algorithm and ++ allows for a lean implementation. ++ ++ Futexes only compare 32b values when deciding whether to block a thread, ++ but we need to distinguish more than 1<<32 states for the condvar. Unlike ++ mutexes, which are just free/acquired/contended, the position of waiters ++ and signals matters because of the requirement of them forming a total ++ order. Therefore, to avoid ABA issues and prevent potential lost wake-ups, ++ we need to safely reset WSEQ and SIGNALS_SENT. We do so by quiescing the ++ condvar once WSEQ reaches a threshold (WSEQ_THRESHOLD): We wait for all ++ waiters to confirm that they have woken up by incrementing the CONFIRMED ++ counter, and then reset the condvar state. Waiters arriving in this ++ quiescence period (i.e., the time between WSEQ reaching WSEQ_THRESHOLD and ++ the reset being complete) will wake up spuriously. ++ To avoid ABA issues for broadcasts that could lead to excessive numbers of ++ spurious wake-ups, we maintain a GENERATION counter that increases ++ whenever we enter and exit a quiescence period; waiters also use this ++ counter to communicate when the quiescence period can be finished by ++ incrementing GENERATION to an odd value. ++ When waiters wait for quiescence to finish, they will have pending accesses ++ to the condvar even though they are not registered as waiters. Therefore, ++ we count this number of waiters in QUIESCENCE_WAITERS; destruction of the ++ condvar will not take place until there are no such waiters anymore. ++ ++ WSEQ is only modified while holding MUTEX, but signals and broadcasts read ++ it without holding the mutex (see both functions for an explanation why ++ this is safe). SIGNALS_SENT is only modified with CAS operations by ++ signals and broadcast; the only exception is the reset of the condvar ++ during quiescence (but this is fine due to how signals and broadcasts ++ update SIGNALS_SENT). CONFIRMED is accessed by just waiters with atomic ++ operations, and reset during quiescence. GENERATION is modified by waiters ++ during quiescence handling, and used by broadcasts to check whether a ++ snapshot of WSEQ and SIGNALS_SENT happened within a single generation. ++ QUIESCENCE_WAITERS is only modified by waiters that wait for quiescence to ++ finish. ++ ++ The common-case state is WSEQ < WSEQ_THRESHOLD and GENERATION being even. ++ CONFIRMED is always smaller or equal to WSEQ except during reset. ++ SIGNALS_SENT can be larger than WSEQ, but this happens just during reset ++ or if a signal or broadcast tripped over a reset or the hardware reordered ++ in a funny way, in which case we just get a few more spurious wake-ups ++ (see __pthread_cond_broadcast for details on how we minimize that). ++ If WSEQ equals WSEQ_THRESHOLD, then incoming waiters will wait for all ++ waiters in the current generation to finish, or they will reset the condvar ++ and start a new generation. If GENERATION is odd, the condvar state is ++ ready for being reset. ++ ++ Limitations: ++ * This condvar isn't designed to allow for more than ++ WSEQ_THRESHOLD * (1 << (sizeof(GENERATION) * 8 - 1)) calls to ++ __pthread_cond_wait. It probably only suffers from potential ABA issues ++ afterwards, but this hasn't been checked nor tested. ++ * More than (1 << (sizeof(QUIESCENCE_WAITERS) * 8) -1 concurrent waiters ++ are not supported. ++ * Beyond what is allowed as errors by POSIX or documented, we can also ++ return the following errors: ++ * EPERM if MUTEX is a recursive mutex and the caller doesn't own it. ++ * EOWNERDEAD or ENOTRECOVERABLE when using robust mutexes. Unlike ++ for other errors, this can happen when we re-acquire the mutex; this ++ isn't allowed by POSIX (which requires all errors to virtually happen ++ before we release the mutex or change the condvar state), but there's ++ nothing we can do really. ++ * EAGAIN if MUTEX is a recursive mutex and trying to lock it exceeded ++ the maximum number of recursive locks. The caller cannot expect to own ++ MUTEX. ++ * When using PTHREAD_MUTEX_PP_* mutexes, we can also return all errors ++ returned by __pthread_tpp_change_priority. We will already have ++ released the mutex in such cases, so the caller cannot expect to own ++ MUTEX. ++ ++ Other notes: ++ * Instead of the normal mutex unlock / lock functions, we use ++ __pthread_mutex_unlock_usercnt(m, 0) / __pthread_mutex_cond_lock(m) ++ because those will not change the mutex-internal users count, so that it ++ can be detected when a condvar is still associated with a particular ++ mutex because there is a waiter blocked on this condvar using this mutex. ++*/ ++static __always_inline int ++__pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex, ++ const struct timespec *abstime) + { + struct _pthread_cleanup_buffer buffer; + struct _condvar_cleanup_buffer cbuffer; ++ const int maxspin = 0; + int err; +- int pshared = (cond->__data.__mutex == (void *) ~0l) +- ? LLL_SHARED : LLL_PRIVATE; ++ int result = 0; ++ unsigned int spin, seq, gen, ssent; + +-#if (defined lll_futex_wait_requeue_pi \ +- && defined __ASSUME_REQUEUE_PI) +- int pi_flag = 0; +-#endif ++ /* We (can assume to) hold the mutex, so there are no concurrent ++ modifications. */ ++ int pshared = (atomic_load_relaxed (&cond->__data.__mutex) == (void *) ~0l) ++ ? LLL_SHARED : LLL_PRIVATE; + + LIBC_PROBE (cond_wait, 2, cond, mutex); + +- /* Make sure we are alone. */ +- lll_lock (cond->__data.__lock, pshared); ++ /* Remember the mutex we are using here, unless it's a pshared condvar. ++ Users must ensure that a condvar is associated with exactly one mutex, ++ so we cannot store an incorrect address if the program is correct. */ ++ if (pshared != LLL_SHARED) ++ atomic_store_relaxed (&cond->__data.__mutex, mutex); ++ ++ /* Acquire a position (SEQ) in the waiter sequence (WSEQ) iff this will not ++ cause overflow. We use an an atomic operation because signals and ++ broadcasts may read while not holding the mutex. We do not need release ++ MO here because we do not need to establish any happens-before relation ++ with signalers (see __pthread_cond_signal). */ ++ seq = atomic_load_relaxed (&cond->__data.__wseq); ++ if (__glibc_likely (seq < __PTHREAD_COND_WSEQ_THRESHOLD)) ++ atomic_store_relaxed (&cond->__data.__wseq, seq + 1); ++ ++ /* If we reached WSEQ_THRESHOLD, we need to quiesce the condvar. */ ++ if (seq >= __PTHREAD_COND_WSEQ_THRESHOLD - 1) ++ { ++ /* If we are the waiter that triggered quiescence, we need to still ++ confirm that we have woken up (which can update GENERATION if we are ++ the last one active). ++ XXX We probably do not need to wake anyone because we still hold the ++ mutex so no other waiter can observe that we started quiescence. */ ++ if (seq == __PTHREAD_COND_WSEQ_THRESHOLD - 1) ++ __condvar_confirm_wakeup (cond, pshared); ++ /* Check whether all waiters in the current generation have confirmed ++ that they do not wait anymore (and thus don't use the condvar state ++ anymore), and either reset or wait for this to happen. We do that ++ while holding the mutex so we will never see WSEQ==WSEQ_THRESHOLD and ++ an even value for GENERATION that is already a new generation. We ++ need acquire MO on the load to ensure that we happen after the last ++ of the current generation's waiters confirmed that it isn't using the ++ condvar anymore (see below). ++ Note that in both cases, we must not actually wait for any signal to ++ arrive but wake up spuriously. This allows signalers to not take ++ actively part in quiescence because they can assume that if they ++ hit a quiescence period, all waiters they might have to wake will ++ wake up on their own. */ ++ gen = atomic_load_acquire (&cond->__data.__generation); ++ if ((gen & 1) != 0) ++ { ++ /* No waiter uses the condvar currently, so we can reset. ++ This barrier / release-MO fence is necessary to match the ++ acquire-MO fence in __pthread_cond_broadcast. It makes sure that ++ if a broadcast sees one of the values stored during reset, it ++ will also observe an even value for GENERATION (i.e., broadcast ++ can check whether it read condvar state that was from different ++ generations or partially reset). We store atomically because ++ the fence, according to the memory model, only has the desired ++ effect in combination with atomic operations. */ ++ atomic_thread_fence_release (); ++ atomic_store_relaxed (&cond->__data.__wseq, 0); ++ atomic_store_relaxed (&cond->__data.__signals_sent, 0); ++ atomic_store_relaxed (&cond->__data.__confirmed, 0); ++ /* Need release MO to make sure that if a broadcast loads the new ++ generation, it will also observe a fully reset condvar. */ ++ atomic_fetch_add_release (&cond->__data.__generation, 1); ++ /* TODO Discuss issues around PI support on quiescence. */ ++ lll_futex_wake (&cond->__data.__generation, INT_MAX, pshared); ++ /* We haven't released the mutex, so we can just return. */ ++ return 0; ++ } ++ else ++ { ++ /* There are still some waiters that haven't yet confirmed to not be ++ using the condvar anymore. Wake all of them if this hasn't ++ happened yet. Relaxed MO is sufficient because we only need to ++ max out SIGNALS_SENT and we still hold the mutex, so a new ++ generation cannot have been started concurrently. */ ++ ssent = atomic_load_relaxed (&cond->__data.__signals_sent); ++ while (1) ++ { ++ if (ssent == __PTHREAD_COND_WSEQ_THRESHOLD) ++ break; ++ if (atomic_compare_exchange_weak_relaxed ( ++ &cond->__data.__signals_sent, &ssent, ++ __PTHREAD_COND_WSEQ_THRESHOLD)) ++ { ++ /* If we made any signals available, wake up all waiters ++ blocked on the futex. */ ++ lll_futex_wake (&cond->__data.__signals_sent, INT_MAX, ++ pshared); ++ break; ++ } ++ } ++ /* Now wait until no waiter is using the condvar anymore, and wake ++ up spuriously. Don't hold the mutex while we wait. We also ++ need to tell __pthread_cond_destroy that we will have pending ++ accesses to the condvar state; we do so before we release the ++ mutex to make sure that this is visible to destruction. */ ++ atomic_fetch_add_relaxed (&cond->__data.__quiescence_waiters, 1); ++ err = __pthread_mutex_unlock_usercnt (mutex, 0); ++ ++ if (__glibc_likely (err == 0)) ++ { ++ /* Enable asynchronous cancellation before we block, as required ++ by the standard. In the cancellation handler, we just do ++ the same steps as after a normal futex wake-up. */ ++ cbuffer.cond = cond; ++ cbuffer.mutex = mutex; ++ __pthread_cleanup_push (&buffer, __condvar_cleanup_quiescence, ++ &cbuffer); ++ cbuffer.oldtype = __pthread_enable_asynccancel (); ++ ++ /* We don't really need to care whether the futex_wait fails ++ because a spurious wake-up is just fine. */ ++ /* TODO Spin on generation (with acquire MO)? */ ++ /* TODO Discuss issues around PI support on quiescence. */ ++ lll_futex_wait (&cond->__data.__generation, gen, pshared); ++ ++ /* Stopped blocking; disable cancellation. */ ++ __pthread_disable_asynccancel (cbuffer.oldtype); ++ __pthread_cleanup_pop (&buffer, 0); ++ } ++ /* Notify __pthread_cond_destroy that we won't access the condvar ++ anymore. Release MO to make our accesses happen before ++ destruction. */ ++ if (atomic_fetch_add_release (&cond->__data.__quiescence_waiters, -1) ++ == 1) ++ lll_futex_wake (&cond->__data.__quiescence_waiters, INT_MAX, ++ pshared); ++ ++ /* If unlocking the mutex returned an error, we haven't released it. ++ We have decremented QUIESCENCE_WAITERS already, so we can just ++ return here. */ ++ if (__glibc_unlikely (err != 0)) ++ return err; ++ ++ /* Re-acquire the mutex, and just wake up spuriously. */ ++ /* XXX Rather abort on errors that are disallowed by POSIX? */ ++ return __pthread_mutex_cond_lock (mutex); ++ } ++ } + +- /* Now we can release the mutex. */ ++ /* Now that we are registered as a waiter, we can release the mutex. ++ Waiting on the condvar must be atomic with releasing the mutex, so if ++ the mutex is used to establish a happens-before relation with any ++ signaler, the waiter must be visible to the latter; thus, we release the ++ mutex after registering as waiter. ++ If releasing the mutex fails, we just cancel our registration as a ++ waiter and confirm that we have woken up. */ + err = __pthread_mutex_unlock_usercnt (mutex, 0); +- if (__glibc_unlikely (err)) ++ if (__glibc_unlikely (err != 0)) + { +- lll_unlock (cond->__data.__lock, pshared); ++ __condvar_cancel_waiting (cond, pshared); ++ __condvar_confirm_wakeup (cond, pshared); + return err; + } + +- /* We have one new user of the condvar. */ +- ++cond->__data.__total_seq; +- ++cond->__data.__futex; +- cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT; +- +- /* Remember the mutex we are using here. If there is already a +- different address store this is a bad user bug. Do not store +- anything for pshared condvars. */ +- if (cond->__data.__mutex != (void *) ~0l) +- cond->__data.__mutex = mutex; +- +- /* Prepare structure passed to cancellation handler. */ ++ /* We might block on a futex, so push the cancellation handler. */ + cbuffer.cond = cond; + cbuffer.mutex = mutex; +- +- /* Before we block we enable cancellation. Therefore we have to +- install a cancellation handler. */ +- __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); +- +- /* The current values of the wakeup counter. The "woken" counter +- must exceed this value. */ +- unsigned long long int val; +- unsigned long long int seq; +- val = seq = cond->__data.__wakeup_seq; +- /* Remember the broadcast counter. */ +- cbuffer.bc_seq = cond->__data.__broadcast_seq; +- +- do ++ __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer); ++ ++ /* Loop until we might have been woken, which is the case if either (1) more ++ signals have been sent than what is our position in the waiter sequence ++ or (2) the kernel woke us after we blocked in a futex_wait operation. We ++ have to consider the latter independently of the former because the ++ kernel might wake in an order that is different from the waiter sequence ++ we determined (and we don't know in which order the individual waiters' ++ futex_wait calls were actually processed in the kernel). ++ We do not need acquire MO for the load from SIGNALS_SENT because we do ++ not need to establish a happens-before with the sender of the signal; ++ because every wake-up could be spurious, the program has to check its ++ condition associated with the condvar anyway and must use suitable ++ synchronization to do so. IOW, we ensure that the virtual ordering of ++ waiters and signalers is consistent with happens-before, but we do not ++ transfer this order back into happens-before. Also see the comments ++ in __pthread_cond_signal. */ ++ ssent = atomic_load_relaxed (&cond->__data.__signals_sent); ++ spin = maxspin; ++ while (ssent <= seq) + { +- unsigned int futex_val = cond->__data.__futex; +- /* Prepare to wait. Release the condvar futex. */ +- lll_unlock (cond->__data.__lock, pshared); +- +- /* Enable asynchronous cancellation. Required by the standard. */ +- cbuffer.oldtype = __pthread_enable_asynccancel (); +- +-#if (defined lll_futex_wait_requeue_pi \ +- && defined __ASSUME_REQUEUE_PI) +- /* If pi_flag remained 1 then it means that we had the lock and the mutex +- but a spurious waker raced ahead of us. Give back the mutex before +- going into wait again. */ +- if (pi_flag) +- { +- __pthread_mutex_cond_lock_adjust (mutex); +- __pthread_mutex_unlock_usercnt (mutex, 0); +- } +- pi_flag = USE_REQUEUE_PI (mutex); +- +- if (pi_flag) +- { +- err = lll_futex_wait_requeue_pi (&cond->__data.__futex, +- futex_val, &mutex->__data.__lock, +- pshared); +- +- pi_flag = (err == 0); +- } ++ if (spin > 0) ++ spin--; + else ++ { ++ if (abstime == NULL) ++ { ++ /* Enable asynchronous cancellation before we block, as required ++ by the standard. */ ++ cbuffer.oldtype = __pthread_enable_asynccancel (); ++ /* Block using SIGNALS_SENT as futex. If we get woken due to a ++ concurrent change to the number of signals sent (i.e., ++ EAGAIN is returned), we fall back to spinning and ++ eventually will try to block again. All other possible ++ errors returned from the futex_wait call are either ++ programming errors, or similar to EAGAIN (i.e., EINTR ++ on a spurious wake-up by the futex). Otherwise, we have ++ been woken by a real signal, so the kernel picked us for the ++ wake-up, and we can stop waiting. */ ++ err = lll_futex_wait (&cond->__data.__signals_sent, ssent, ++ pshared); ++ /* Stopped blocking; disable cancellation. */ ++ __pthread_disable_asynccancel (cbuffer.oldtype); ++ if (err == 0) ++ break; ++ } ++ else ++ { ++ /* Block, but with a timeout. */ ++ /* Work around the fact that the kernel rejects negative timeout ++ values despite them being valid. */ ++ if (__glibc_unlikely (abstime->tv_sec < 0)) ++ goto timeout; ++ ++#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ ++ || !defined lll_futex_timed_wait_bitset) ++ struct timespec rt; ++ { ++# ifdef __NR_clock_gettime ++ INTERNAL_SYSCALL_DECL (err); ++ (void) INTERNAL_VSYSCALL (clock_gettime, err, 2, ++ cond->__data.__clockid, &rt); ++ /* Convert the absolute timeout value to a relative ++ timeout. */ ++ rt.tv_sec = abstime->tv_sec - rt.tv_sec; ++ rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec; ++# else ++ /* Get the current time. So far, we support only one ++ clock. */ ++ struct timeval tv; ++ (void) __gettimeofday (&tv, NULL); ++ /* Convert the absolute timeout value to a relative ++ timeout. */ ++ rt.tv_sec = abstime->tv_sec - tv.tv_sec; ++ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; ++# endif ++ } ++ if (rt.tv_nsec < 0) ++ { ++ rt.tv_nsec += 1000000000; ++ --rt.tv_sec; ++ } ++ /* Did we already time out? */ ++ if (__glibc_unlikely (rt.tv_sec < 0)) ++ goto timeout; ++ ++ /* Enable asynchronous cancellation before we block, as required ++ by the standard. */ ++ cbuffer.oldtype = __pthread_enable_asynccancel (); ++ err = lll_futex_timed_wait (&cond->__data.__signals_sent, ssent, ++ &rt, pshared); ++ ++#else ++ unsigned int clockbit = (cond->__data.__clockid == 1 ++ ? 0 : FUTEX_CLOCK_REALTIME); ++ /* Enable asynchronous cancellation before we block, as required ++ by the standard. */ ++ cbuffer.oldtype = __pthread_enable_asynccancel (); ++ err = lll_futex_timed_wait_bitset (&cond->__data.__signals_sent, ++ ssent, abstime, clockbit, pshared); + #endif +- /* Wait until woken by signal or broadcast. */ +- lll_futex_wait (&cond->__data.__futex, futex_val, pshared); +- +- /* Disable asynchronous cancellation. */ +- __pthread_disable_asynccancel (cbuffer.oldtype); +- +- /* We are going to look at shared data again, so get the lock. */ +- lll_lock (cond->__data.__lock, pshared); +- +- /* If a broadcast happened, we are done. */ +- if (cbuffer.bc_seq != cond->__data.__broadcast_seq) +- goto bc_out; ++ /* Stopped blocking; disable cancellation. */ ++ __pthread_disable_asynccancel (cbuffer.oldtype); ++ ++ if (err == 0) ++ break; ++ else if (__glibc_unlikely (err == -ETIMEDOUT)) ++ { ++ timeout: ++ /* When we timed out, we effectively cancel waiting. */ ++ __condvar_cancel_waiting (cond, pshared); ++ result = ETIMEDOUT; ++ break; ++ } ++ } ++ ++ spin = maxspin; ++ } + +- /* Check whether we are eligible for wakeup. */ +- val = cond->__data.__wakeup_seq; ++ /* (Spin-)Wait until enough signals have been sent. */ ++ ssent = atomic_load_relaxed (&cond->__data.__signals_sent); + } +- while (val == seq || cond->__data.__woken_seq == val); +- +- /* Another thread woken up. */ +- ++cond->__data.__woken_seq; +- +- bc_out: +- +- cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT; + +- /* If pthread_cond_destroy was called on this varaible already, +- notify the pthread_cond_destroy caller all waiters have left +- and it can be successfully destroyed. */ +- if (cond->__data.__total_seq == -1ULL +- && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT)) +- lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); ++ /* We won't block on a futex anymore. */ ++ __pthread_cleanup_pop (&buffer, 0); + +- /* We are done with the condvar. */ +- lll_unlock (cond->__data.__lock, pshared); ++ /* Confirm that we have been woken. We do that before acquiring the mutex ++ to reduce the latency of dealing with quiescence, and to allow that ++ pthread_cond_destroy can be executed while having acquired the mutex. ++ Neither signalers nor waiters will wait for quiescence to complete ++ while they hold the mutex. */ ++ __condvar_confirm_wakeup (cond, pshared); ++ ++ /* Woken up; now re-acquire the mutex. If this doesn't fail, return RESULT, ++ which is set to ETIMEDOUT if a timeout occured, or zero otherwise. */ ++ err = __pthread_mutex_cond_lock (mutex); ++ /* XXX Rather abort on errors that are disallowed by POSIX? */ ++ return (err != 0) ? err : result; ++} + +- /* The cancellation handling is back to normal, remove the handler. */ +- __pthread_cleanup_pop (&buffer, 0); ++int ++__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) ++{ ++ return __pthread_cond_wait_common (cond, mutex, NULL); ++} + +- /* Get the mutex before returning. Not needed for PI. */ +-#if (defined lll_futex_wait_requeue_pi \ +- && defined __ASSUME_REQUEUE_PI) +- if (pi_flag) +- { +- __pthread_mutex_cond_lock_adjust (mutex); +- return 0; +- } +- else +-#endif +- return __pthread_mutex_cond_lock (mutex); ++int ++__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, ++ const struct timespec *abstime) ++{ ++ /* Check parameter validity. This should also tell the compiler that ++ it can assume that abstime is not NULL. */ ++ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) ++ return EINVAL; ++ return __pthread_cond_wait_common (cond, mutex, abstime); + } + + versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, + GLIBC_2_3_2); ++versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, ++ GLIBC_2_3_2); +diff --git a/nptl/pthread_condattr_getclock.c b/nptl/pthread_condattr_getclock.c +index 020d21a..2ad585b 100644 +--- a/nptl/pthread_condattr_getclock.c ++++ b/nptl/pthread_condattr_getclock.c +@@ -25,6 +25,6 @@ pthread_condattr_getclock (attr, clock_id) + clockid_t *clock_id; + { + *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1) +- & ((1 << COND_NWAITERS_SHIFT) - 1)); ++ & ((1 << COND_CLOCK_BITS) - 1)); + return 0; + } +diff --git a/nptl/pthread_condattr_setclock.c b/nptl/pthread_condattr_setclock.c +index 0748d78..cb8d8dd 100644 +--- a/nptl/pthread_condattr_setclock.c ++++ b/nptl/pthread_condattr_setclock.c +@@ -36,11 +36,11 @@ pthread_condattr_setclock (attr, clock_id) + return EINVAL; + + /* Make sure the value fits in the bits we reserved. */ +- assert (clock_id < (1 << COND_NWAITERS_SHIFT)); ++ assert (clock_id < (1 << COND_CLOCK_BITS)); + + int *valuep = &((struct pthread_condattr *) attr)->value; + +- *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1)) ++ *valuep = ((*valuep & ~(((1 << COND_CLOCK_BITS) - 1) << 1)) + | (clock_id << 1)); + + return 0; +diff --git a/nptl/tst-cond1.c b/nptl/tst-cond1.c +index 64f90e0..fab2b19 100644 +--- a/nptl/tst-cond1.c ++++ b/nptl/tst-cond1.c +@@ -73,6 +73,9 @@ do_test (void) + + puts ("parent: wait for condition"); + ++ /* This test will fail on spurious wake-ups, which are allowed; however, ++ the current implementation shouldn't produce spurious wake-ups in the ++ scenario we are testing here. */ + err = pthread_cond_wait (&cond, &mut); + if (err != 0) + error (EXIT_FAILURE, err, "parent: cannot wait fir signal"); +diff --git a/nptl/tst-cond18.c b/nptl/tst-cond18.c +index ceeb1aa..b14ed79 100644 +--- a/nptl/tst-cond18.c ++++ b/nptl/tst-cond18.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + pthread_cond_t cv = PTHREAD_COND_INITIALIZER; + pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +@@ -43,6 +44,26 @@ tf (void *id) + pthread_mutex_unlock (&lock); + + pthread_mutex_lock (&lock); ++#ifdef TEST_QUIESCENCE ++ /* Make sure we're triggering quiescence regularly by simply ++ increasing all of WSEQ, SIGNALS_SENT, and CONFIRMED. ++ We have acquire the lock, so there's no concurrent registration ++ of waiters nor quiescence reset; thus, WSEQ is not concurrently ++ modified, and when we increase CONFIRMED, we can never reach ++ the threshold (but CONFIRMED can be concurrently modified). ++ Also, there's no other thread doing signals, so we're the only ++ one modifying SIGNALS_SENT. */ ++ unsigned int seq = atomic_load_relaxed (&cv.__data.__wseq); ++ if (seq < __PTHREAD_COND_WSEQ_THRESHOLD - 3 * count) ++ { ++ unsigned int d = __PTHREAD_COND_WSEQ_THRESHOLD - 3 * count ++ - seq; ++ atomic_store_relaxed (&cv.__data.__wseq, seq + d); ++ atomic_store_relaxed (&cv.__data.__signals_sent, ++ atomic_load_relaxed (&cv.__data.__signals_sent) + d); ++ atomic_fetch_add_relaxed (&cv.__data.__confirmed, d); ++ } ++#endif + int njobs = rand () % (count + 1); + nn = njobs; + if ((rand () % 30) == 0) +diff --git a/nptl/tst-cond20.c b/nptl/tst-cond20.c +index 9de062a..5122370 100644 +--- a/nptl/tst-cond20.c ++++ b/nptl/tst-cond20.c +@@ -82,6 +82,7 @@ do_test (void) + puts ("barrier_init failed"); + return 1; + } ++ /* We simply don't test quiescence in the first round. See below. */ + + pthread_mutex_lock (&mut); + +@@ -96,7 +97,10 @@ do_test (void) + + for (i = 0; i < ROUNDS; ++i) + { +- pthread_cond_wait (&cond2, &mut); ++ /* Make sure we discard spurious wake-ups. */ ++ do ++ pthread_cond_wait (&cond2, &mut); ++ while (count != N); + + if (i & 1) + pthread_mutex_unlock (&mut); +@@ -150,6 +154,14 @@ do_test (void) + printf ("pthread_cond_init failed: %s\n", strerror (err)); + return 1; + } ++#ifdef TEST_QUIESCENCE ++ /* This results in the condvar being in a quiescence state as soon as ++ some or all of the waiters have started to block. Note that we ++ must not put it immediately in the quiescence state because we ++ need some of the waiters to change the generation etc. */ ++ cond.__data.__wseq = cond.__data.__signals_sent = cond.__data.__confirmed ++ =__PTHREAD_COND_WSEQ_THRESHOLD - i % N - 1; ++#endif + } + + for (i = 0; i < N; ++i) +diff --git a/nptl/tst-cond22.c b/nptl/tst-cond22.c +index bd978e5..1ee5188 100644 +--- a/nptl/tst-cond22.c ++++ b/nptl/tst-cond22.c +@@ -106,10 +106,10 @@ do_test (void) + status = 1; + } + +- printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n", +- c.__data.__lock, c.__data.__futex, c.__data.__total_seq, +- c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex, +- c.__data.__nwaiters, c.__data.__broadcast_seq); ++ printf ("cond = { %u, %u, %u, %u, %p, %u }\n", ++ c.__data.__wseq, c.__data.__signals_sent, c.__data.__confirmed, ++ c.__data.__generation, c.__data.__mutex, ++ c.__data.__quiescence_waiters); + + if (pthread_create (&th, NULL, tf, (void *) 1l) != 0) + { +@@ -148,10 +148,10 @@ do_test (void) + status = 1; + } + +- printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n", +- c.__data.__lock, c.__data.__futex, c.__data.__total_seq, +- c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex, +- c.__data.__nwaiters, c.__data.__broadcast_seq); ++ printf ("cond = { %u, %u, %u, %u, %p, %u }\n", ++ c.__data.__wseq, c.__data.__signals_sent, c.__data.__confirmed, ++ c.__data.__generation, c.__data.__mutex, ++ c.__data.__quiescence_waiters); + + return status; + } +diff --git a/nptl/tst-cond25.c b/nptl/tst-cond25.c +index be0bec4..ddc37a0 100644 +--- a/nptl/tst-cond25.c ++++ b/nptl/tst-cond25.c +@@ -216,6 +216,14 @@ do_test_wait (thr_func f) + printf ("cond_init failed: %s\n", strerror (ret)); + goto out; + } ++#ifdef TEST_QUIESCENCE ++ /* This results in the condvar being in a quiescence state as soon as ++ some or all of the waiters have started to block. Note that we ++ must not put it immediately in the quiescence state because we ++ need some of the waiters to change the generation etc. */ ++ cond.__data.__wseq = cond.__data.__signals_sent = cond.__data.__confirmed ++ =__PTHREAD_COND_WSEQ_THRESHOLD - i % NUM - 1; ++#endif + + if ((ret = pthread_mutex_init (&mutex, &attr)) != 0) + { +diff --git a/nptl/tst-cond26.c b/nptl/tst-cond26.c +new file mode 100644 +index 0000000..b611d62 +--- /dev/null ++++ b/nptl/tst-cond26.c +@@ -0,0 +1,2 @@ ++#define TEST_QUIESCENCE 1 ++#include "tst-cond20.c" +diff --git a/nptl/tst-cond27.c b/nptl/tst-cond27.c +new file mode 100644 +index 0000000..8668a24 +--- /dev/null ++++ b/nptl/tst-cond27.c +@@ -0,0 +1,2 @@ ++#define TEST_QUIESCENCE 1 ++#include "tst-cond25.c" +diff --git a/nptl/tst-cond28.c b/nptl/tst-cond28.c +new file mode 100644 +index 0000000..7fc3b6b +--- /dev/null ++++ b/nptl/tst-cond28.c +@@ -0,0 +1,2 @@ ++#define TEST_QUIESCENCE 1 ++#include "tst-cond18.c" +diff --git a/sysdeps/aarch64/nptl/bits/pthreadtypes.h b/sysdeps/aarch64/nptl/bits/pthreadtypes.h +index 0e4795e..c9ae0d6 100644 +--- a/sysdeps/aarch64/nptl/bits/pthreadtypes.h ++++ b/sysdeps/aarch64/nptl/bits/pthreadtypes.h +@@ -90,14 +90,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + long int __align; +diff --git a/sysdeps/arm/nptl/bits/pthreadtypes.h b/sysdeps/arm/nptl/bits/pthreadtypes.h +index 9f2efc2..f84c272 100644 +--- a/sysdeps/arm/nptl/bits/pthreadtypes.h ++++ b/sysdeps/arm/nptl/bits/pthreadtypes.h +@@ -93,14 +93,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/hppa/nptl/bits/pthreadtypes.h b/sysdeps/hppa/nptl/bits/pthreadtypes.h +index 845629d..fcd45c9 100644 +--- a/sysdeps/hppa/nptl/bits/pthreadtypes.h ++++ b/sysdeps/hppa/nptl/bits/pthreadtypes.h +@@ -119,23 +119,19 @@ typedef union + start of the 4-word lock structure, the next four words + are set all to 1 by the Linuxthreads + PTHREAD_COND_INITIALIZER. */ +- int __lock __attribute__ ((aligned(16))); ++ unsigned int __wseq __attribute__ ((aligned(16))); + /* Tracks the initialization of this structure: + 0 initialized with NPTL PTHREAD_COND_INITIALIZER. + 1 initialized with Linuxthreads PTHREAD_COND_INITIALIZER. + 2 initialization in progress. */ + int __initializer; +- unsigned int __futex; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- /* In the old Linuxthreads this would have been the start +- of the pthread_fastlock status word. */ +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; +- /* The NPTL pthread_cond_t is exactly the same size as +- the Linuxthreads version, there are no words to spare. */ ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/ia64/nptl/bits/pthreadtypes.h b/sysdeps/ia64/nptl/bits/pthreadtypes.h +index e9762f5..9477f9a 100644 +--- a/sysdeps/ia64/nptl/bits/pthreadtypes.h ++++ b/sysdeps/ia64/nptl/bits/pthreadtypes.h +@@ -90,14 +90,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + long int __align; +diff --git a/sysdeps/m68k/nptl/bits/pthreadtypes.h b/sysdeps/m68k/nptl/bits/pthreadtypes.h +index 0e2bcdd..40fdec1 100644 +--- a/sysdeps/m68k/nptl/bits/pthreadtypes.h ++++ b/sysdeps/m68k/nptl/bits/pthreadtypes.h +@@ -93,14 +93,14 @@ typedef union + { + struct + { +- int __lock __attribute__ ((__aligned__ (4))); +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq __attribute__ ((__aligned__ (4))); ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/microblaze/nptl/bits/pthreadtypes.h b/sysdeps/microblaze/nptl/bits/pthreadtypes.h +index b8bd828..58a0daa 100644 +--- a/sysdeps/microblaze/nptl/bits/pthreadtypes.h ++++ b/sysdeps/microblaze/nptl/bits/pthreadtypes.h +@@ -91,14 +91,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/mips/nptl/bits/pthreadtypes.h b/sysdeps/mips/nptl/bits/pthreadtypes.h +index 8cf4547..4267568 100644 +--- a/sysdeps/mips/nptl/bits/pthreadtypes.h ++++ b/sysdeps/mips/nptl/bits/pthreadtypes.h +@@ -122,14 +122,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/nios2/nptl/bits/pthreadtypes.h b/sysdeps/nios2/nptl/bits/pthreadtypes.h +index 4a20803..d35bd01 100644 +--- a/sysdeps/nios2/nptl/bits/pthreadtypes.h ++++ b/sysdeps/nios2/nptl/bits/pthreadtypes.h +@@ -93,14 +93,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h +index 8f5cfa4..726a760 100644 +--- a/sysdeps/nptl/internaltypes.h ++++ b/sysdeps/nptl/internaltypes.h +@@ -68,20 +68,13 @@ struct pthread_condattr + { + /* Combination of values: + +- Bit 0 : flag whether conditional variable will be sharable between +- processes. +- +- Bit 1-7: clock ID. */ ++ Bit 0 : flag whether conditional variable will be ++ sharable between processes. ++ Bit 1-COND_CLOCK_BITS: Clock ID. COND_CLOCK_BITS is the number of bits ++ needed to represent the ID of the clock. */ + int value; + }; +- +- +-/* The __NWAITERS field is used as a counter and to house the number +- of bits for other purposes. COND_CLOCK_BITS is the number +- of bits needed to represent the ID of the clock. COND_NWAITERS_SHIFT +- is the number of bits reserved for other purposes like the clock. */ +-#define COND_CLOCK_BITS 1 +-#define COND_NWAITERS_SHIFT 1 ++#define COND_CLOCK_BITS 1 + + + /* Read-write lock variable attribute data structure. */ +diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h +index 70ff250..3749f08 100644 +--- a/sysdeps/nptl/pthread.h ++++ b/sysdeps/nptl/pthread.h +@@ -185,7 +185,7 @@ enum + + + /* Conditional variable handling. */ +-#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } } ++#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, (void *) 0, 0, 0 } } + + + /* Cleanup buffers */ +diff --git a/sysdeps/s390/nptl/bits/pthreadtypes.h b/sysdeps/s390/nptl/bits/pthreadtypes.h +index 1f3bb14..d96dbbe 100644 +--- a/sysdeps/s390/nptl/bits/pthreadtypes.h ++++ b/sysdeps/s390/nptl/bits/pthreadtypes.h +@@ -142,14 +142,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/sh/nptl/bits/pthreadtypes.h b/sysdeps/sh/nptl/bits/pthreadtypes.h +index 5940232..412e831 100644 +--- a/sysdeps/sh/nptl/bits/pthreadtypes.h ++++ b/sysdeps/sh/nptl/bits/pthreadtypes.h +@@ -93,14 +93,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/sparc/nptl/bits/pthreadtypes.h b/sysdeps/sparc/nptl/bits/pthreadtypes.h +index 6faf8b2..5e72d77 100644 +--- a/sysdeps/sparc/nptl/bits/pthreadtypes.h ++++ b/sysdeps/sparc/nptl/bits/pthreadtypes.h +@@ -122,14 +122,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/tile/nptl/bits/pthreadtypes.h b/sysdeps/tile/nptl/bits/pthreadtypes.h +index 1f6553d..bb521b7 100644 +--- a/sysdeps/tile/nptl/bits/pthreadtypes.h ++++ b/sysdeps/tile/nptl/bits/pthreadtypes.h +@@ -122,14 +122,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h +index 7121d0b..5d42d70 100644 +--- a/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h ++++ b/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h +@@ -89,14 +89,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/unix/sysv/linux/hppa/internaltypes.h b/sysdeps/unix/sysv/linux/hppa/internaltypes.h +index 651ce2e..d649657 100644 +--- a/sysdeps/unix/sysv/linux/hppa/internaltypes.h ++++ b/sysdeps/unix/sysv/linux/hppa/internaltypes.h +@@ -46,32 +46,38 @@ fails because __initializer is zero, and the structure will be used as + is correctly. */ + + #define cond_compat_clear(var) \ +-({ \ +- int tmp = 0; \ +- var->__data.__lock = 0; \ +- var->__data.__futex = 0; \ +- var->__data.__mutex = NULL; \ +- /* Clear __initializer last, to indicate initialization is done. */ \ +- __asm__ __volatile__ ("stw,ma %1,0(%0)" \ +- : : "r" (&var->__data.__initializer), "r" (tmp) : "memory"); \ ++({ \ ++ int tmp = 0; \ ++ var->__data.__wseq = 0; \ ++ var->__data.__signals_sent = 0; \ ++ var->__data.__confirmed = 0; \ ++ var->__data.__generation = 0; \ ++ var->__data.__mutex = NULL; \ ++ var->__data.__quiescence_waiters = 0; \ ++ var->__data.__clockid = 0; \ ++ /* Clear __initializer last, to indicate initialization is done. */ \ ++ /* This synchronizes-with the acquire load below. */ \ ++ atomic_store_release (&var->__data.__initializer, 0); \ + }) + + #define cond_compat_check_and_clear(var) \ + ({ \ +- int ret; \ +- volatile int *value = &var->__data.__initializer; \ +- if ((ret = atomic_compare_and_exchange_val_acq(value, 2, 1))) \ ++ int v; \ ++ int *value = &var->__data.__initializer; \ ++ /* This synchronizes-with the release store above. */ \ ++ while ((v = atomic_load_acquire (value)) != 0) \ + { \ +- if (ret == 1) \ ++ if (v == 1 \ ++ /* Relaxed MO is fine; it only matters who's first. */ \ ++ && atomic_compare_exchange_acquire_weak_relaxed (value, 1, 2)) \ + { \ +- /* Initialize structure. */ \ ++ /* We're first; initialize structure. */ \ + cond_compat_clear (var); \ ++ break; \ + } \ + else \ +- { \ +- /* Yield until structure is initialized. */ \ +- while (*value == 2) sched_yield (); \ +- } \ ++ /* Yield before we re-check initialization status. */ \ ++ sched_yield (); \ + } \ + }) + +diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c +deleted file mode 100644 +index 6199013..0000000 +--- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c ++++ /dev/null +@@ -1,43 +0,0 @@ +-/* Copyright (C) 2009-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Carlos O'Donell , 2009. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library. If not, see +- . */ +- +-#ifndef INCLUDED_SELF +-# define INCLUDED_SELF +-# include +-#else +-# include +-# include +-# include +-# include +-int +-__pthread_cond_timedwait (cond, mutex, abstime) +- pthread_cond_t *cond; +- pthread_mutex_t *mutex; +- const struct timespec *abstime; +-{ +- cond_compat_check_and_clear (cond); +- return __pthread_cond_timedwait_internal (cond, mutex, abstime); +-} +-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +- GLIBC_2_3_2); +-# undef versioned_symbol +-# define versioned_symbol(lib, local, symbol, version) +-# undef __pthread_cond_timedwait +-# define __pthread_cond_timedwait __pthread_cond_timedwait_internal +-# include_next +-#endif +diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c +index 5e1506f..1496730 100644 +--- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c ++++ b/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c +@@ -34,9 +34,22 @@ __pthread_cond_wait (cond, mutex) + } + versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, + GLIBC_2_3_2); ++int ++__pthread_cond_timedwait (cond, mutex, abstime) ++ pthread_cond_t *cond; ++ pthread_mutex_t *mutex; ++ const struct timespec *abstime; ++{ ++ cond_compat_check_and_clear (cond); ++ return __pthread_cond_timedwait_internal (cond, mutex, abstime); ++} ++versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, ++ GLIBC_2_3_2); + # undef versioned_symbol + # define versioned_symbol(lib, local, symbol, version) + # undef __pthread_cond_wait + # define __pthread_cond_wait __pthread_cond_wait_internal ++# undef __pthread_cond_timedwait ++# define __pthread_cond_timedwait __pthread_cond_timedwait_internal + # include_next + #endif +diff --git a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S b/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S +deleted file mode 100644 +index 5ddd5ac..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S ++++ /dev/null +@@ -1,241 +0,0 @@ +-/* Copyright (C) 2002-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- .text +- +- /* int pthread_cond_broadcast (pthread_cond_t *cond) */ +- .globl __pthread_cond_broadcast +- .type __pthread_cond_broadcast, @function +- .align 16 +-__pthread_cond_broadcast: +- cfi_startproc +- pushl %ebx +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%ebx, 0) +- pushl %esi +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%esi, 0) +- pushl %edi +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%edi, 0) +- pushl %ebp +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%ebp, 0) +- cfi_remember_state +- +- movl 20(%esp), %ebx +- +- LIBC_PROBE (cond_broadcast, 1, %edx) +- +- /* Get internal lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-#else +- cmpxchgl %edx, cond_lock(%ebx) +-#endif +- jnz 1f +- +-2: addl $cond_futex, %ebx +- movl total_seq+4-cond_futex(%ebx), %eax +- movl total_seq-cond_futex(%ebx), %ebp +- cmpl wakeup_seq+4-cond_futex(%ebx), %eax +- ja 3f +- jb 4f +- cmpl wakeup_seq-cond_futex(%ebx), %ebp +- jna 4f +- +- /* Cause all currently waiting threads to recognize they are +- woken up. */ +-3: movl %ebp, wakeup_seq-cond_futex(%ebx) +- movl %eax, wakeup_seq-cond_futex+4(%ebx) +- movl %ebp, woken_seq-cond_futex(%ebx) +- movl %eax, woken_seq-cond_futex+4(%ebx) +- addl %ebp, %ebp +- addl $1, broadcast_seq-cond_futex(%ebx) +- movl %ebp, (%ebx) +- +- /* Get the address of the mutex used. */ +- movl dep_mutex-cond_futex(%ebx), %edi +- +- /* Unlock. */ +- LOCK +- subl $1, cond_lock-cond_futex(%ebx) +- jne 7f +- +- /* Don't use requeue for pshared condvars. */ +-8: cmpl $-1, %edi +- je 9f +- +- /* Do not use requeue for pshared condvars. */ +- testl $PS_BIT, MUTEX_KIND(%edi) +- jne 9f +- +- /* Requeue to a non-robust PI mutex if the PI bit is set and +- the robust bit is not set. */ +- movl MUTEX_KIND(%edi), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- je 81f +- +- /* Wake up all threads. */ +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx +-#else +- movl %gs:PRIVATE_FUTEX, %ecx +- orl $FUTEX_CMP_REQUEUE, %ecx +-#endif +- movl $SYS_futex, %eax +- movl $0x7fffffff, %esi +- movl $1, %edx +- /* Get the address of the futex involved. */ +-# if MUTEX_FUTEX != 0 +- addl $MUTEX_FUTEX, %edi +-# endif +-/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter. +- ENTER_KERNEL */ +- int $0x80 +- +- /* For any kind of error, which mainly is EAGAIN, we try again +- with WAKE. The general test also covers running on old +- kernels. */ +- cmpl $0xfffff001, %eax +- jae 9f +- +-6: xorl %eax, %eax +- popl %ebp +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebp) +- popl %edi +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%edi) +- popl %esi +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%esi) +- popl %ebx +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebx) +- ret +- +- cfi_restore_state +- +-81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx +- movl $SYS_futex, %eax +- movl $0x7fffffff, %esi +- movl $1, %edx +- /* Get the address of the futex involved. */ +-# if MUTEX_FUTEX != 0 +- addl $MUTEX_FUTEX, %edi +-# endif +- int $0x80 +- +- /* For any kind of error, which mainly is EAGAIN, we try again +- with WAKE. The general test also covers running on old +- kernels. */ +- cmpl $0xfffff001, %eax +- jb 6b +- jmp 9f +- +- /* Initial locking failed. */ +-1: +-#if cond_lock == 0 +- movl %ebx, %edx +-#else +- leal cond_lock(%ebx), %edx +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_lock_wait +- jmp 2b +- +- .align 16 +- /* Unlock. */ +-4: LOCK +- subl $1, cond_lock-cond_futex(%ebx) +- je 6b +- +- /* Unlock in loop requires wakeup. */ +-5: leal cond_lock-cond_futex(%ebx), %eax +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_futex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- jmp 6b +- +- /* Unlock in loop requires wakeup. */ +-7: leal cond_lock-cond_futex(%ebx), %eax +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_futex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- jmp 8b +- +-9: /* The futex requeue functionality is not available. */ +- movl $0x7fffffff, %edx +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_futex(%ebx) +- sete %cl +- subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAKE, %ecx +- movl $SYS_futex, %eax +- ENTER_KERNEL +- jmp 6b +- cfi_endproc +- .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +-versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, +- GLIBC_2_3_2) +diff --git a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S b/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S +deleted file mode 100644 +index 8f4d937..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S ++++ /dev/null +@@ -1,216 +0,0 @@ +-/* Copyright (C) 2002-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- .text +- +- /* int pthread_cond_signal (pthread_cond_t *cond) */ +- .globl __pthread_cond_signal +- .type __pthread_cond_signal, @function +- .align 16 +-__pthread_cond_signal: +- +- cfi_startproc +- pushl %ebx +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%ebx, 0) +- pushl %edi +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%edi, 0) +- cfi_remember_state +- +- movl 12(%esp), %edi +- +- LIBC_PROBE (cond_signal, 1, %edi) +- +- /* Get internal lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %edx, (%edi) +-#else +- cmpxchgl %edx, cond_lock(%edi) +-#endif +- jnz 1f +- +-2: leal cond_futex(%edi), %ebx +- movl total_seq+4(%edi), %eax +- movl total_seq(%edi), %ecx +- cmpl wakeup_seq+4(%edi), %eax +-#if cond_lock != 0 +- /* Must use leal to preserve the flags. */ +- leal cond_lock(%edi), %edi +-#endif +- ja 3f +- jb 4f +- cmpl wakeup_seq-cond_futex(%ebx), %ecx +- jbe 4f +- +- /* Bump the wakeup number. */ +-3: addl $1, wakeup_seq-cond_futex(%ebx) +- adcl $0, wakeup_seq-cond_futex+4(%ebx) +- addl $1, (%ebx) +- +- /* Wake up one thread. */ +- pushl %esi +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%esi, 0) +- pushl %ebp +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%ebp, 0) +- +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_futex(%ebx) +- sete %cl +- je 8f +- +- movl dep_mutex-cond_futex(%ebx), %edx +- /* Requeue to a non-robust PI mutex if the PI bit is set and +- the robust bit is not set. */ +- movl MUTEX_KIND(%edx), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- je 9f +- +-8: subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAKE_OP, %ecx +- movl $SYS_futex, %eax +- movl $1, %edx +- movl $1, %esi +- movl $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp +- /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for +- sysenter. +- ENTER_KERNEL */ +- int $0x80 +- popl %ebp +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebp) +- popl %esi +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%esi) +- +- /* For any kind of error, we try again with WAKE. +- The general test also covers running on old kernels. */ +- cmpl $-4095, %eax +- jae 7f +- +-6: xorl %eax, %eax +- popl %edi +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%edi) +- popl %ebx +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebx) +- ret +- +- cfi_restore_state +- +-9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx +- movl $SYS_futex, %eax +- movl $1, %edx +- xorl %esi, %esi +- movl dep_mutex-cond_futex(%ebx), %edi +- movl (%ebx), %ebp +- /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for +- sysenter. +- ENTER_KERNEL */ +- int $0x80 +- popl %ebp +- popl %esi +- +- leal -cond_futex(%ebx), %edi +- +- /* For any kind of error, we try again with WAKE. +- The general test also covers running on old kernels. */ +- cmpl $-4095, %eax +- jb 4f +- +-7: +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- orl $FUTEX_WAKE, %ecx +- +- movl $SYS_futex, %eax +- /* %edx should be 1 already from $FUTEX_WAKE_OP syscall. +- movl $1, %edx */ +- ENTER_KERNEL +- +- /* Unlock. Note that at this point %edi always points to +- cond_lock. */ +-4: LOCK +- subl $1, (%edi) +- je 6b +- +- /* Unlock in loop requires wakeup. */ +-5: movl %edi, %eax +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_futex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- jmp 6b +- +- /* Initial locking failed. */ +-1: +-#if cond_lock == 0 +- movl %edi, %edx +-#else +- leal cond_lock(%edi), %edx +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%edi) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_lock_wait +- jmp 2b +- +- cfi_endproc +- .size __pthread_cond_signal, .-__pthread_cond_signal +-versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, +- GLIBC_2_3_2) +diff --git a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +deleted file mode 100644 +index 130c090..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S ++++ /dev/null +@@ -1,973 +0,0 @@ +-/* Copyright (C) 2002-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- .text +- +-/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, +- const struct timespec *abstime) */ +- .globl __pthread_cond_timedwait +- .type __pthread_cond_timedwait, @function +- .align 16 +-__pthread_cond_timedwait: +-.LSTARTCODE: +- cfi_startproc +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +-#endif +- +- pushl %ebp +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%ebp, 0) +- pushl %edi +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%edi, 0) +- pushl %esi +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%esi, 0) +- pushl %ebx +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%ebx, 0) +- +- movl 20(%esp), %ebx +- movl 28(%esp), %ebp +- +- LIBC_PROBE (cond_timedwait, 3, %ebx, 24(%esp), %ebp) +- +- cmpl $1000000000, 4(%ebp) +- movl $EINVAL, %eax +- jae 18f +- +- /* Stack frame: +- +- esp + 32 +- +--------------------------+ +- esp + 24 | timeout value | +- +--------------------------+ +- esp + 20 | futex pointer | +- +--------------------------+ +- esp + 16 | pi-requeued flag | +- +--------------------------+ +- esp + 12 | old broadcast_seq value | +- +--------------------------+ +- esp + 4 | old wake_seq value | +- +--------------------------+ +- esp + 0 | old cancellation mode | +- +--------------------------+ +- */ +- +-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +-# ifdef PIC +- LOAD_PIC_REG (cx) +- cmpl $0, __have_futex_clock_realtime@GOTOFF(%ecx) +-# else +- cmpl $0, __have_futex_clock_realtime +-# endif +- je .Lreltmo +-#endif +- +- /* Get internal lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-#else +- cmpxchgl %edx, cond_lock(%ebx) +-#endif +- jnz 1f +- +- /* Store the reference to the mutex. If there is already a +- different value in there this is a bad user bug. */ +-2: cmpl $-1, dep_mutex(%ebx) +- movl 24(%esp), %eax +- je 17f +- movl %eax, dep_mutex(%ebx) +- +- /* Unlock the mutex. */ +-17: xorl %edx, %edx +- call __pthread_mutex_unlock_usercnt +- +- testl %eax, %eax +- jne 16f +- +- addl $1, total_seq(%ebx) +- adcl $0, total_seq+4(%ebx) +- addl $1, cond_futex(%ebx) +- addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) +- +-#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +-# define FRAME_SIZE 24 +-#else +-# define FRAME_SIZE 32 +-#endif +- subl $FRAME_SIZE, %esp +- cfi_adjust_cfa_offset(FRAME_SIZE) +- cfi_remember_state +- +- /* Get and store current wakeup_seq value. */ +- movl wakeup_seq(%ebx), %edi +- movl wakeup_seq+4(%ebx), %edx +- movl broadcast_seq(%ebx), %eax +- movl %edi, 4(%esp) +- movl %edx, 8(%esp) +- movl %eax, 12(%esp) +- +- /* Reset the pi-requeued flag. */ +- movl $0, 16(%esp) +- +- cmpl $0, (%ebp) +- movl $-ETIMEDOUT, %esi +- js 6f +- +-8: movl cond_futex(%ebx), %edi +- movl %edi, 20(%esp) +- +- /* Unlock. */ +- LOCK +-#if cond_lock == 0 +- subl $1, (%ebx) +-#else +- subl $1, cond_lock(%ebx) +-#endif +- jne 3f +- +-.LcleanupSTART: +-4: call __pthread_enable_asynccancel +- movl %eax, (%esp) +- +- leal (%ebp), %esi +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- sete %cl +- je 40f +- +- movl dep_mutex(%ebx), %edi +- /* Requeue to a non-robust PI mutex if the PI bit is set and +- the robust bit is not set. */ +- movl MUTEX_KIND(%edi), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- jne 40f +- +- movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx +- /* The following only works like this because we only support +- two clocks, represented using a single bit. */ +- testl $1, cond_nwaiters(%ebx) +- /* XXX Need to implement using sete instead of a jump. */ +- jne 42f +- orl $FUTEX_CLOCK_REALTIME, %ecx +- +-42: movl 20(%esp), %edx +- addl $cond_futex, %ebx +-.Ladd_cond_futex_pi: +- movl $SYS_futex, %eax +- ENTER_KERNEL +- subl $cond_futex, %ebx +-.Lsub_cond_futex_pi: +- movl %eax, %esi +- /* Set the pi-requeued flag only if the kernel has returned 0. The +- kernel does not hold the mutex on ETIMEDOUT or any other error. */ +- cmpl $0, %eax +- sete 16(%esp) +- je 41f +- +- /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns +- successfully, it has already locked the mutex for us and the +- pi_flag (16(%esp)) is set to denote that fact. However, if another +- thread changed the futex value before we entered the wait, the +- syscall may return an EAGAIN and the mutex is not locked. We go +- ahead with a success anyway since later we look at the pi_flag to +- decide if we got the mutex or not. The sequence numbers then make +- sure that only one of the threads actually wake up. We retry using +- normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal +- and PI futexes don't mix. +- +- Note that we don't check for EAGAIN specifically; we assume that the +- only other error the futex function could return is EAGAIN (barring +- the ETIMEOUT of course, for the timeout case in futex) since +- anything else would mean an error in our function. It is too +- expensive to do that check for every call (which is quite common in +- case of a large number of threads), so it has been skipped. */ +- cmpl $-ENOSYS, %eax +- jne 41f +- xorl %ecx, %ecx +- +-40: subl $1, %ecx +- movl $0, 16(%esp) +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAIT_BITSET, %ecx +- /* The following only works like this because we only support +- two clocks, represented using a single bit. */ +- testl $1, cond_nwaiters(%ebx) +- jne 30f +- orl $FUTEX_CLOCK_REALTIME, %ecx +-30: +- movl 20(%esp), %edx +- movl $0xffffffff, %ebp +- addl $cond_futex, %ebx +-.Ladd_cond_futex: +- movl $SYS_futex, %eax +- ENTER_KERNEL +- subl $cond_futex, %ebx +-.Lsub_cond_futex: +- movl 28+FRAME_SIZE(%esp), %ebp +- movl %eax, %esi +- +-41: movl (%esp), %eax +- call __pthread_disable_asynccancel +-.LcleanupEND: +- +- /* Lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-#else +- cmpxchgl %edx, cond_lock(%ebx) +-#endif +- jnz 5f +- +-6: movl broadcast_seq(%ebx), %eax +- cmpl 12(%esp), %eax +- jne 23f +- +- movl woken_seq(%ebx), %eax +- movl woken_seq+4(%ebx), %ecx +- +- movl wakeup_seq(%ebx), %edi +- movl wakeup_seq+4(%ebx), %edx +- +- cmpl 8(%esp), %edx +- jne 7f +- cmpl 4(%esp), %edi +- je 15f +- +-7: cmpl %ecx, %edx +- jne 9f +- cmp %eax, %edi +- jne 9f +- +-15: cmpl $-ETIMEDOUT, %esi +- je 28f +- +- /* We need to go back to futex_wait. If we're using requeue_pi, then +- release the mutex we had acquired and go back. */ +- movl 16(%esp), %edx +- test %edx, %edx +- jz 8b +- +- /* Adjust the mutex values first and then unlock it. The unlock +- should always succeed or else the kernel did not lock the mutex +- correctly. */ +- movl dep_mutex(%ebx), %eax +- call __pthread_mutex_cond_lock_adjust +- xorl %edx, %edx +- call __pthread_mutex_unlock_usercnt +- jmp 8b +- +-28: addl $1, wakeup_seq(%ebx) +- adcl $0, wakeup_seq+4(%ebx) +- addl $1, cond_futex(%ebx) +- movl $ETIMEDOUT, %esi +- jmp 14f +- +-23: xorl %esi, %esi +- jmp 24f +- +-9: xorl %esi, %esi +-14: addl $1, woken_seq(%ebx) +- adcl $0, woken_seq+4(%ebx) +- +-24: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) +- +- /* Wake up a thread which wants to destroy the condvar object. */ +- movl total_seq(%ebx), %eax +- andl total_seq+4(%ebx), %eax +- cmpl $0xffffffff, %eax +- jne 25f +- movl cond_nwaiters(%ebx), %eax +- andl $~((1 << nwaiters_shift) - 1), %eax +- jne 25f +- +- addl $cond_nwaiters, %ebx +- movl $SYS_futex, %eax +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_nwaiters(%ebx) +- sete %cl +- subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAKE, %ecx +- movl $1, %edx +- ENTER_KERNEL +- subl $cond_nwaiters, %ebx +- +-25: LOCK +-#if cond_lock == 0 +- subl $1, (%ebx) +-#else +- subl $1, cond_lock(%ebx) +-#endif +- jne 10f +- +-11: movl 24+FRAME_SIZE(%esp), %eax +- /* With requeue_pi, the mutex lock is held in the kernel. */ +- movl 16(%esp), %ecx +- testl %ecx, %ecx +- jnz 27f +- +- call __pthread_mutex_cond_lock +-26: addl $FRAME_SIZE, %esp +- cfi_adjust_cfa_offset(-FRAME_SIZE) +- +- /* We return the result of the mutex_lock operation if it failed. */ +- testl %eax, %eax +-#ifdef HAVE_CMOV +- cmovel %esi, %eax +-#else +- jne 22f +- movl %esi, %eax +-22: +-#endif +- +-18: popl %ebx +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebx) +- popl %esi +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%esi) +- popl %edi +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%edi) +- popl %ebp +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebp) +- +- ret +- +- cfi_restore_state +- +-27: call __pthread_mutex_cond_lock_adjust +- xorl %eax, %eax +- jmp 26b +- +- cfi_adjust_cfa_offset(-FRAME_SIZE); +- /* Initial locking failed. */ +-1: +-#if cond_lock == 0 +- movl %ebx, %edx +-#else +- leal cond_lock(%ebx), %edx +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_lock_wait +- jmp 2b +- +- /* The initial unlocking of the mutex failed. */ +-16: +- LOCK +-#if cond_lock == 0 +- subl $1, (%ebx) +-#else +- subl $1, cond_lock(%ebx) +-#endif +- jne 18b +- +- movl %eax, %esi +-#if cond_lock == 0 +- movl %ebx, %eax +-#else +- leal cond_lock(%ebx), %eax +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- +- movl %esi, %eax +- jmp 18b +- +- cfi_adjust_cfa_offset(FRAME_SIZE) +- +- /* Unlock in loop requires wakeup. */ +-3: +-#if cond_lock == 0 +- movl %ebx, %eax +-#else +- leal cond_lock(%ebx), %eax +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- jmp 4b +- +- /* Locking in loop failed. */ +-5: +-#if cond_lock == 0 +- movl %ebx, %edx +-#else +- leal cond_lock(%ebx), %edx +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_lock_wait +- jmp 6b +- +- /* Unlock after loop requires wakeup. */ +-10: +-#if cond_lock == 0 +- movl %ebx, %eax +-#else +- leal cond_lock(%ebx), %eax +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- jmp 11b +- +-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +- cfi_adjust_cfa_offset(-FRAME_SIZE) +-.Lreltmo: +- /* Get internal lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-# if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-# else +- cmpxchgl %edx, cond_lock(%ebx) +-# endif +- jnz 101f +- +- /* Store the reference to the mutex. If there is already a +- different value in there this is a bad user bug. */ +-102: cmpl $-1, dep_mutex(%ebx) +- movl 24(%esp), %eax +- je 117f +- movl %eax, dep_mutex(%ebx) +- +- /* Unlock the mutex. */ +-117: xorl %edx, %edx +- call __pthread_mutex_unlock_usercnt +- +- testl %eax, %eax +- jne 16b +- +- addl $1, total_seq(%ebx) +- adcl $0, total_seq+4(%ebx) +- addl $1, cond_futex(%ebx) +- addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) +- +- subl $FRAME_SIZE, %esp +- cfi_adjust_cfa_offset(FRAME_SIZE) +- +- /* Get and store current wakeup_seq value. */ +- movl wakeup_seq(%ebx), %edi +- movl wakeup_seq+4(%ebx), %edx +- movl broadcast_seq(%ebx), %eax +- movl %edi, 4(%esp) +- movl %edx, 8(%esp) +- movl %eax, 12(%esp) +- +- /* Reset the pi-requeued flag. */ +- movl $0, 16(%esp) +- +- /* Get the current time. */ +-108: movl %ebx, %edx +-# ifdef __NR_clock_gettime +- /* Get the clock number. */ +- movl cond_nwaiters(%ebx), %ebx +- andl $((1 << nwaiters_shift) - 1), %ebx +- /* Only clocks 0 and 1 are allowed so far. Both are handled in the +- kernel. */ +- leal 24(%esp), %ecx +- movl $__NR_clock_gettime, %eax +- ENTER_KERNEL +- movl %edx, %ebx +- +- /* Compute relative timeout. */ +- movl (%ebp), %ecx +- movl 4(%ebp), %edx +- subl 24(%esp), %ecx +- subl 28(%esp), %edx +-# else +- /* Get the current time. */ +- leal 24(%esp), %ebx +- xorl %ecx, %ecx +- movl $__NR_gettimeofday, %eax +- ENTER_KERNEL +- movl %edx, %ebx +- +- /* Compute relative timeout. */ +- movl 28(%esp), %eax +- movl $1000, %edx +- mul %edx /* Milli seconds to nano seconds. */ +- movl (%ebp), %ecx +- movl 4(%ebp), %edx +- subl 24(%esp), %ecx +- subl %eax, %edx +-# endif +- jns 112f +- addl $1000000000, %edx +- subl $1, %ecx +-112: testl %ecx, %ecx +- movl $-ETIMEDOUT, %esi +- js 106f +- +- /* Store relative timeout. */ +-121: movl %ecx, 24(%esp) +- movl %edx, 28(%esp) +- +- movl cond_futex(%ebx), %edi +- movl %edi, 20(%esp) +- +- /* Unlock. */ +- LOCK +-# if cond_lock == 0 +- subl $1, (%ebx) +-# else +- subl $1, cond_lock(%ebx) +-# endif +- jne 103f +- +-.LcleanupSTART2: +-104: call __pthread_enable_asynccancel +- movl %eax, (%esp) +- +- leal 24(%esp), %esi +-# if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-# endif +- cmpl $-1, dep_mutex(%ebx) +- sete %cl +- subl $1, %ecx +-# ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-# else +- andl %gs:PRIVATE_FUTEX, %ecx +-# endif +-# if FUTEX_WAIT != 0 +- addl $FUTEX_WAIT, %ecx +-# endif +- movl 20(%esp), %edx +- addl $cond_futex, %ebx +-.Ladd_cond_futex2: +- movl $SYS_futex, %eax +- ENTER_KERNEL +- subl $cond_futex, %ebx +-.Lsub_cond_futex2: +- movl %eax, %esi +- +-141: movl (%esp), %eax +- call __pthread_disable_asynccancel +-.LcleanupEND2: +- +- +- /* Lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-# if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-# else +- cmpxchgl %edx, cond_lock(%ebx) +-# endif +- jnz 105f +- +-106: movl broadcast_seq(%ebx), %eax +- cmpl 12(%esp), %eax +- jne 23b +- +- movl woken_seq(%ebx), %eax +- movl woken_seq+4(%ebx), %ecx +- +- movl wakeup_seq(%ebx), %edi +- movl wakeup_seq+4(%ebx), %edx +- +- cmpl 8(%esp), %edx +- jne 107f +- cmpl 4(%esp), %edi +- je 115f +- +-107: cmpl %ecx, %edx +- jne 9b +- cmp %eax, %edi +- jne 9b +- +-115: cmpl $-ETIMEDOUT, %esi +- je 28b +- +- jmp 8b +- +- cfi_adjust_cfa_offset(-FRAME_SIZE) +- /* Initial locking failed. */ +-101: +-# if cond_lock == 0 +- movl %ebx, %edx +-# else +- leal cond_lock(%ebx), %edx +-# endif +-# if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-# endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-# if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-# endif +- call __lll_lock_wait +- jmp 102b +- +- cfi_adjust_cfa_offset(FRAME_SIZE) +- +- /* Unlock in loop requires wakeup. */ +-103: +-# if cond_lock == 0 +- movl %ebx, %eax +-# else +- leal cond_lock(%ebx), %eax +-# endif +-# if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-# endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-# if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-# endif +- call __lll_unlock_wake +- jmp 104b +- +- /* Locking in loop failed. */ +-105: +-# if cond_lock == 0 +- movl %ebx, %edx +-# else +- leal cond_lock(%ebx), %edx +-# endif +-# if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-# endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-# if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-# endif +- call __lll_lock_wait +- jmp 106b +-#endif +- +- .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +- GLIBC_2_3_2) +- +- +- .type __condvar_tw_cleanup2, @function +-__condvar_tw_cleanup2: +- subl $cond_futex, %ebx +- .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2 +- .type __condvar_tw_cleanup, @function +-__condvar_tw_cleanup: +- movl %eax, %esi +- +- /* Get internal lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-#else +- cmpxchgl %edx, cond_lock(%ebx) +-#endif +- jz 1f +- +-#if cond_lock == 0 +- movl %ebx, %edx +-#else +- leal cond_lock(%ebx), %edx +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_lock_wait +- +-1: movl broadcast_seq(%ebx), %eax +- cmpl 12(%esp), %eax +- jne 3f +- +- /* We increment the wakeup_seq counter only if it is lower than +- total_seq. If this is not the case the thread was woken and +- then canceled. In this case we ignore the signal. */ +- movl total_seq(%ebx), %eax +- movl total_seq+4(%ebx), %edi +- cmpl wakeup_seq+4(%ebx), %edi +- jb 6f +- ja 7f +- cmpl wakeup_seq(%ebx), %eax +- jbe 7f +- +-6: addl $1, wakeup_seq(%ebx) +- adcl $0, wakeup_seq+4(%ebx) +- addl $1, cond_futex(%ebx) +- +-7: addl $1, woken_seq(%ebx) +- adcl $0, woken_seq+4(%ebx) +- +-3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) +- +- /* Wake up a thread which wants to destroy the condvar object. */ +- xorl %edi, %edi +- movl total_seq(%ebx), %eax +- andl total_seq+4(%ebx), %eax +- cmpl $0xffffffff, %eax +- jne 4f +- movl cond_nwaiters(%ebx), %eax +- andl $~((1 << nwaiters_shift) - 1), %eax +- jne 4f +- +- addl $cond_nwaiters, %ebx +- movl $SYS_futex, %eax +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_nwaiters(%ebx) +- sete %cl +- subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAKE, %ecx +- movl $1, %edx +- ENTER_KERNEL +- subl $cond_nwaiters, %ebx +- movl $1, %edi +- +-4: LOCK +-#if cond_lock == 0 +- subl $1, (%ebx) +-#else +- subl $1, cond_lock(%ebx) +-#endif +- je 2f +- +-#if cond_lock == 0 +- movl %ebx, %eax +-#else +- leal cond_lock(%ebx), %eax +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- +- /* Wake up all waiters to make sure no signal gets lost. */ +-2: testl %edi, %edi +- jnz 5f +- addl $cond_futex, %ebx +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_futex(%ebx) +- sete %cl +- subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAKE, %ecx +- movl $SYS_futex, %eax +- movl $0x7fffffff, %edx +- ENTER_KERNEL +- +- /* Lock the mutex only if we don't own it already. This only happens +- in case of PI mutexes, if we got cancelled after a successful +- return of the futex syscall and before disabling async +- cancellation. */ +-5: movl 24+FRAME_SIZE(%esp), %eax +- movl MUTEX_KIND(%eax), %ebx +- andl $(ROBUST_BIT|PI_BIT), %ebx +- cmpl $PI_BIT, %ebx +- jne 8f +- +- movl (%eax), %ebx +- andl $TID_MASK, %ebx +- cmpl %ebx, %gs:TID +- jne 8f +- /* We managed to get the lock. Fix it up before returning. */ +- call __pthread_mutex_cond_lock_adjust +- jmp 9f +- +-8: call __pthread_mutex_cond_lock +- +-9: movl %esi, (%esp) +-.LcallUR: +- call _Unwind_Resume +- hlt +-.LENDCODE: +- cfi_endproc +- .size __condvar_tw_cleanup, .-__condvar_tw_cleanup +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit # @LPStart format (omit) +- .byte DW_EH_PE_omit # @TType format (omit) +- .byte DW_EH_PE_sdata4 # call-site format +- # DW_EH_PE_sdata4 +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .long .LcleanupSTART-.LSTARTCODE +- .long .Ladd_cond_futex_pi-.LcleanupSTART +- .long __condvar_tw_cleanup-.LSTARTCODE +- .uleb128 0 +- .long .Ladd_cond_futex_pi-.LSTARTCODE +- .long .Lsub_cond_futex_pi-.Ladd_cond_futex_pi +- .long __condvar_tw_cleanup2-.LSTARTCODE +- .uleb128 0 +- .long .Lsub_cond_futex_pi-.LSTARTCODE +- .long .Ladd_cond_futex-.Lsub_cond_futex_pi +- .long __condvar_tw_cleanup-.LSTARTCODE +- .uleb128 0 +- .long .Ladd_cond_futex-.LSTARTCODE +- .long .Lsub_cond_futex-.Ladd_cond_futex +- .long __condvar_tw_cleanup2-.LSTARTCODE +- .uleb128 0 +- .long .Lsub_cond_futex-.LSTARTCODE +- .long .LcleanupEND-.Lsub_cond_futex +- .long __condvar_tw_cleanup-.LSTARTCODE +- .uleb128 0 +-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +- .long .LcleanupSTART2-.LSTARTCODE +- .long .Ladd_cond_futex2-.LcleanupSTART2 +- .long __condvar_tw_cleanup-.LSTARTCODE +- .uleb128 0 +- .long .Ladd_cond_futex2-.LSTARTCODE +- .long .Lsub_cond_futex2-.Ladd_cond_futex2 +- .long __condvar_tw_cleanup2-.LSTARTCODE +- .uleb128 0 +- .long .Lsub_cond_futex2-.LSTARTCODE +- .long .LcleanupEND2-.Lsub_cond_futex2 +- .long __condvar_tw_cleanup-.LSTARTCODE +- .uleb128 0 +-#endif +- .long .LcallUR-.LSTARTCODE +- .long .LENDCODE-.LcallUR +- .long 0 +- .uleb128 0 +-.Lcstend: +- +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align 4 +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, 4 +-DW.ref.__gcc_personality_v0: +- .long __gcc_personality_v0 +-#endif +diff --git a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +deleted file mode 100644 +index ec3538f..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S ++++ /dev/null +@@ -1,641 +0,0 @@ +-/* Copyright (C) 2002-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- +- .text +- +-/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ +- .globl __pthread_cond_wait +- .type __pthread_cond_wait, @function +- .align 16 +-__pthread_cond_wait: +-.LSTARTCODE: +- cfi_startproc +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +-#endif +- +- pushl %ebp +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%ebp, 0) +- pushl %edi +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%edi, 0) +- pushl %esi +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%esi, 0) +- pushl %ebx +- cfi_adjust_cfa_offset(4) +- cfi_rel_offset(%ebx, 0) +- +- xorl %esi, %esi +- movl 20(%esp), %ebx +- +- LIBC_PROBE (cond_wait, 2, 24(%esp), %ebx) +- +- /* Get internal lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-#else +- cmpxchgl %edx, cond_lock(%ebx) +-#endif +- jnz 1f +- +- /* Store the reference to the mutex. If there is already a +- different value in there this is a bad user bug. */ +-2: cmpl $-1, dep_mutex(%ebx) +- movl 24(%esp), %eax +- je 15f +- movl %eax, dep_mutex(%ebx) +- +- /* Unlock the mutex. */ +-15: xorl %edx, %edx +- call __pthread_mutex_unlock_usercnt +- +- testl %eax, %eax +- jne 12f +- +- addl $1, total_seq(%ebx) +- adcl $0, total_seq+4(%ebx) +- addl $1, cond_futex(%ebx) +- addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) +- +-#define FRAME_SIZE 20 +- subl $FRAME_SIZE, %esp +- cfi_adjust_cfa_offset(FRAME_SIZE) +- cfi_remember_state +- +- /* Get and store current wakeup_seq value. */ +- movl wakeup_seq(%ebx), %edi +- movl wakeup_seq+4(%ebx), %edx +- movl broadcast_seq(%ebx), %eax +- movl %edi, 4(%esp) +- movl %edx, 8(%esp) +- movl %eax, 12(%esp) +- +- /* Reset the pi-requeued flag. */ +-8: movl $0, 16(%esp) +- movl cond_futex(%ebx), %ebp +- +- /* Unlock. */ +- LOCK +-#if cond_lock == 0 +- subl $1, (%ebx) +-#else +- subl $1, cond_lock(%ebx) +-#endif +- jne 3f +- +-.LcleanupSTART: +-4: call __pthread_enable_asynccancel +- movl %eax, (%esp) +- +- xorl %ecx, %ecx +- cmpl $-1, dep_mutex(%ebx) +- sete %cl +- je 18f +- +- movl dep_mutex(%ebx), %edi +- /* Requeue to a non-robust PI mutex if the PI bit is set and +- the robust bit is not set. */ +- movl MUTEX_KIND(%edi), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- jne 18f +- +- movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx +- movl %ebp, %edx +- xorl %esi, %esi +- addl $cond_futex, %ebx +-.Ladd_cond_futex_pi: +- movl $SYS_futex, %eax +- ENTER_KERNEL +- subl $cond_futex, %ebx +-.Lsub_cond_futex_pi: +- /* Set the pi-requeued flag only if the kernel has returned 0. The +- kernel does not hold the mutex on error. */ +- cmpl $0, %eax +- sete 16(%esp) +- je 19f +- +- /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns +- successfully, it has already locked the mutex for us and the +- pi_flag (16(%esp)) is set to denote that fact. However, if another +- thread changed the futex value before we entered the wait, the +- syscall may return an EAGAIN and the mutex is not locked. We go +- ahead with a success anyway since later we look at the pi_flag to +- decide if we got the mutex or not. The sequence numbers then make +- sure that only one of the threads actually wake up. We retry using +- normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal +- and PI futexes don't mix. +- +- Note that we don't check for EAGAIN specifically; we assume that the +- only other error the futex function could return is EAGAIN since +- anything else would mean an error in our function. It is too +- expensive to do that check for every call (which is quite common in +- case of a large number of threads), so it has been skipped. */ +- cmpl $-ENOSYS, %eax +- jne 19f +- xorl %ecx, %ecx +- +-18: subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +-#if FUTEX_WAIT != 0 +- addl $FUTEX_WAIT, %ecx +-#endif +- movl %ebp, %edx +- addl $cond_futex, %ebx +-.Ladd_cond_futex: +- movl $SYS_futex, %eax +- ENTER_KERNEL +- subl $cond_futex, %ebx +-.Lsub_cond_futex: +- +-19: movl (%esp), %eax +- call __pthread_disable_asynccancel +-.LcleanupEND: +- +- /* Lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-#else +- cmpxchgl %edx, cond_lock(%ebx) +-#endif +- jnz 5f +- +-6: movl broadcast_seq(%ebx), %eax +- cmpl 12(%esp), %eax +- jne 16f +- +- movl woken_seq(%ebx), %eax +- movl woken_seq+4(%ebx), %ecx +- +- movl wakeup_seq(%ebx), %edi +- movl wakeup_seq+4(%ebx), %edx +- +- cmpl 8(%esp), %edx +- jne 7f +- cmpl 4(%esp), %edi +- je 22f +- +-7: cmpl %ecx, %edx +- jne 9f +- cmp %eax, %edi +- je 22f +- +-9: addl $1, woken_seq(%ebx) +- adcl $0, woken_seq+4(%ebx) +- +- /* Unlock */ +-16: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) +- +- /* Wake up a thread which wants to destroy the condvar object. */ +- movl total_seq(%ebx), %eax +- andl total_seq+4(%ebx), %eax +- cmpl $0xffffffff, %eax +- jne 17f +- movl cond_nwaiters(%ebx), %eax +- andl $~((1 << nwaiters_shift) - 1), %eax +- jne 17f +- +- addl $cond_nwaiters, %ebx +- movl $SYS_futex, %eax +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_nwaiters(%ebx) +- sete %cl +- subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAKE, %ecx +- movl $1, %edx +- ENTER_KERNEL +- subl $cond_nwaiters, %ebx +- +-17: LOCK +-#if cond_lock == 0 +- subl $1, (%ebx) +-#else +- subl $1, cond_lock(%ebx) +-#endif +- jne 10f +- +- /* With requeue_pi, the mutex lock is held in the kernel. */ +-11: movl 24+FRAME_SIZE(%esp), %eax +- movl 16(%esp), %ecx +- testl %ecx, %ecx +- jnz 21f +- +- call __pthread_mutex_cond_lock +-20: addl $FRAME_SIZE, %esp +- cfi_adjust_cfa_offset(-FRAME_SIZE); +- +-14: popl %ebx +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebx) +- popl %esi +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%esi) +- popl %edi +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%edi) +- popl %ebp +- cfi_adjust_cfa_offset(-4) +- cfi_restore(%ebp) +- +- /* We return the result of the mutex_lock operation. */ +- ret +- +- cfi_restore_state +- +-21: call __pthread_mutex_cond_lock_adjust +- xorl %eax, %eax +- jmp 20b +- +- cfi_adjust_cfa_offset(-FRAME_SIZE); +- +- /* We need to go back to futex_wait. If we're using requeue_pi, then +- release the mutex we had acquired and go back. */ +-22: movl 16(%esp), %edx +- test %edx, %edx +- jz 8b +- +- /* Adjust the mutex values first and then unlock it. The unlock +- should always succeed or else the kernel did not lock the mutex +- correctly. */ +- movl dep_mutex(%ebx), %eax +- call __pthread_mutex_cond_lock_adjust +- xorl %edx, %edx +- call __pthread_mutex_unlock_usercnt +- jmp 8b +- +- /* Initial locking failed. */ +-1: +-#if cond_lock == 0 +- movl %ebx, %edx +-#else +- leal cond_lock(%ebx), %edx +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_lock_wait +- jmp 2b +- +- /* The initial unlocking of the mutex failed. */ +-12: +- LOCK +-#if cond_lock == 0 +- subl $1, (%ebx) +-#else +- subl $1, cond_lock(%ebx) +-#endif +- jne 14b +- +- movl %eax, %esi +-#if cond_lock == 0 +- movl %ebx, %eax +-#else +- leal cond_lock(%ebx), %eax +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- +- movl %esi, %eax +- jmp 14b +- +- cfi_adjust_cfa_offset(FRAME_SIZE) +- +- /* Unlock in loop requires wakeup. */ +-3: +-#if cond_lock == 0 +- movl %ebx, %eax +-#else +- leal cond_lock(%ebx), %eax +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- jmp 4b +- +- /* Locking in loop failed. */ +-5: +-#if cond_lock == 0 +- movl %ebx, %edx +-#else +- leal cond_lock(%ebx), %edx +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_lock_wait +- jmp 6b +- +- /* Unlock after loop requires wakeup. */ +-10: +-#if cond_lock == 0 +- movl %ebx, %eax +-#else +- leal cond_lock(%ebx), %eax +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- jmp 11b +- +- .size __pthread_cond_wait, .-__pthread_cond_wait +-versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, +- GLIBC_2_3_2) +- +- +- .type __condvar_w_cleanup2, @function +-__condvar_w_cleanup2: +- subl $cond_futex, %ebx +- .size __condvar_w_cleanup2, .-__condvar_w_cleanup2 +-.LSbl4: +- .type __condvar_w_cleanup, @function +-__condvar_w_cleanup: +- movl %eax, %esi +- +- /* Get internal lock. */ +- movl $1, %edx +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %edx, (%ebx) +-#else +- cmpxchgl %edx, cond_lock(%ebx) +-#endif +- jz 1f +- +-#if cond_lock == 0 +- movl %ebx, %edx +-#else +- leal cond_lock(%ebx), %edx +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_lock_wait +- +-1: movl broadcast_seq(%ebx), %eax +- cmpl 12(%esp), %eax +- jne 3f +- +- /* We increment the wakeup_seq counter only if it is lower than +- total_seq. If this is not the case the thread was woken and +- then canceled. In this case we ignore the signal. */ +- movl total_seq(%ebx), %eax +- movl total_seq+4(%ebx), %edi +- cmpl wakeup_seq+4(%ebx), %edi +- jb 6f +- ja 7f +- cmpl wakeup_seq(%ebx), %eax +- jbe 7f +- +-6: addl $1, wakeup_seq(%ebx) +- adcl $0, wakeup_seq+4(%ebx) +- addl $1, cond_futex(%ebx) +- +-7: addl $1, woken_seq(%ebx) +- adcl $0, woken_seq+4(%ebx) +- +-3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) +- +- /* Wake up a thread which wants to destroy the condvar object. */ +- xorl %edi, %edi +- movl total_seq(%ebx), %eax +- andl total_seq+4(%ebx), %eax +- cmpl $0xffffffff, %eax +- jne 4f +- movl cond_nwaiters(%ebx), %eax +- andl $~((1 << nwaiters_shift) - 1), %eax +- jne 4f +- +- addl $cond_nwaiters, %ebx +- movl $SYS_futex, %eax +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_nwaiters(%ebx) +- sete %cl +- subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAKE, %ecx +- movl $1, %edx +- ENTER_KERNEL +- subl $cond_nwaiters, %ebx +- movl $1, %edi +- +-4: LOCK +-#if cond_lock == 0 +- subl $1, (%ebx) +-#else +- subl $1, cond_lock(%ebx) +-#endif +- je 2f +- +-#if cond_lock == 0 +- movl %ebx, %eax +-#else +- leal cond_lock(%ebx), %eax +-#endif +-#if (LLL_SHARED-LLL_PRIVATE) > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex(%ebx) +- setne %cl +- subl $1, %ecx +- andl $(LLL_SHARED-LLL_PRIVATE), %ecx +-#if LLL_PRIVATE != 0 +- addl $LLL_PRIVATE, %ecx +-#endif +- call __lll_unlock_wake +- +- /* Wake up all waiters to make sure no signal gets lost. */ +-2: testl %edi, %edi +- jnz 5f +- addl $cond_futex, %ebx +-#if FUTEX_PRIVATE_FLAG > 255 +- xorl %ecx, %ecx +-#endif +- cmpl $-1, dep_mutex-cond_futex(%ebx) +- sete %cl +- subl $1, %ecx +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %ecx +-#else +- andl %gs:PRIVATE_FUTEX, %ecx +-#endif +- addl $FUTEX_WAKE, %ecx +- movl $SYS_futex, %eax +- movl $0x7fffffff, %edx +- ENTER_KERNEL +- +- /* Lock the mutex only if we don't own it already. This only happens +- in case of PI mutexes, if we got cancelled after a successful +- return of the futex syscall and before disabling async +- cancellation. */ +-5: movl 24+FRAME_SIZE(%esp), %eax +- movl MUTEX_KIND(%eax), %ebx +- andl $(ROBUST_BIT|PI_BIT), %ebx +- cmpl $PI_BIT, %ebx +- jne 8f +- +- movl (%eax), %ebx +- andl $TID_MASK, %ebx +- cmpl %ebx, %gs:TID +- jne 8f +- /* We managed to get the lock. Fix it up before returning. */ +- call __pthread_mutex_cond_lock_adjust +- jmp 9f +- +-8: call __pthread_mutex_cond_lock +- +-9: movl %esi, (%esp) +-.LcallUR: +- call _Unwind_Resume +- hlt +-.LENDCODE: +- cfi_endproc +- .size __condvar_w_cleanup, .-__condvar_w_cleanup +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit # @LPStart format (omit) +- .byte DW_EH_PE_omit # @TType format (omit) +- .byte DW_EH_PE_sdata4 # call-site format +- # DW_EH_PE_sdata4 +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .long .LcleanupSTART-.LSTARTCODE +- .long .Ladd_cond_futex_pi-.LcleanupSTART +- .long __condvar_w_cleanup-.LSTARTCODE +- .uleb128 0 +- .long .Ladd_cond_futex_pi-.LSTARTCODE +- .long .Lsub_cond_futex_pi-.Ladd_cond_futex_pi +- .long __condvar_w_cleanup2-.LSTARTCODE +- .uleb128 0 +- .long .Lsub_cond_futex_pi-.LSTARTCODE +- .long .Ladd_cond_futex-.Lsub_cond_futex_pi +- .long __condvar_w_cleanup-.LSTARTCODE +- .uleb128 0 +- .long .Ladd_cond_futex-.LSTARTCODE +- .long .Lsub_cond_futex-.Ladd_cond_futex +- .long __condvar_w_cleanup2-.LSTARTCODE +- .uleb128 0 +- .long .Lsub_cond_futex-.LSTARTCODE +- .long .LcleanupEND-.Lsub_cond_futex +- .long __condvar_w_cleanup-.LSTARTCODE +- .uleb128 0 +- .long .LcallUR-.LSTARTCODE +- .long .LENDCODE-.LcallUR +- .long 0 +- .uleb128 0 +-.Lcstend: +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align 4 +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, 4 +-DW.ref.__gcc_personality_v0: +- .long __gcc_personality_v0 +-#endif +diff --git a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S b/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S +deleted file mode 100644 +index 9a4006a..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/pthread_cond_broadcast.S" +diff --git a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S b/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S +deleted file mode 100644 +index 59f93b6..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/pthread_cond_signal.S" +diff --git a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S +deleted file mode 100644 +index d96af08..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/pthread_cond_timedwait.S" +diff --git a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S +deleted file mode 100644 +index 9696972..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/pthread_cond_wait.S" +diff --git a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S b/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S +deleted file mode 100644 +index 9a4006a..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/pthread_cond_broadcast.S" +diff --git a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S b/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S +deleted file mode 100644 +index 59f93b6..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/pthread_cond_signal.S" +diff --git a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S +deleted file mode 100644 +index 0e8d7ff..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S ++++ /dev/null +@@ -1,20 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#define HAVE_CMOV 1 +-#include "../i486/pthread_cond_timedwait.S" +diff --git a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S +deleted file mode 100644 +index 9696972..0000000 +--- a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* Copyright (C) 2003-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2003. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include "../i486/pthread_cond_wait.S" +diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +index 7cbdb2c..70b65d3 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +@@ -128,14 +128,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S +deleted file mode 100644 +index df635af..0000000 +--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S ++++ /dev/null +@@ -1,179 +0,0 @@ +-/* Copyright (C) 2002-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- .text +- +- /* int pthread_cond_broadcast (pthread_cond_t *cond) */ +- .globl __pthread_cond_broadcast +- .type __pthread_cond_broadcast, @function +- .align 16 +-__pthread_cond_broadcast: +- +- LIBC_PROBE (cond_broadcast, 1, %rdi) +- +- /* Get internal lock. */ +- movl $1, %esi +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, cond_lock(%rdi) +-#endif +- jnz 1f +- +-2: addq $cond_futex, %rdi +- movq total_seq-cond_futex(%rdi), %r9 +- cmpq wakeup_seq-cond_futex(%rdi), %r9 +- jna 4f +- +- /* Cause all currently waiting threads to recognize they are +- woken up. */ +- movq %r9, wakeup_seq-cond_futex(%rdi) +- movq %r9, woken_seq-cond_futex(%rdi) +- addq %r9, %r9 +- movl %r9d, (%rdi) +- incl broadcast_seq-cond_futex(%rdi) +- +- /* Get the address of the mutex used. */ +- mov dep_mutex-cond_futex(%rdi), %R8_LP +- +- /* Unlock. */ +- LOCK +- decl cond_lock-cond_futex(%rdi) +- jne 7f +- +-8: cmp $-1, %R8_LP +- je 9f +- +- /* Do not use requeue for pshared condvars. */ +- testl $PS_BIT, MUTEX_KIND(%r8) +- jne 9f +- +- /* Requeue to a PI mutex if the PI bit is set. */ +- movl MUTEX_KIND(%r8), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- je 81f +- +- /* Wake up all threads. */ +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %esi +-#else +- movl %fs:PRIVATE_FUTEX, %esi +- orl $FUTEX_CMP_REQUEUE, %esi +-#endif +- movl $SYS_futex, %eax +- movl $1, %edx +- movl $0x7fffffff, %r10d +- syscall +- +- /* For any kind of error, which mainly is EAGAIN, we try again +- with WAKE. The general test also covers running on old +- kernels. */ +- cmpq $-4095, %rax +- jae 9f +- +-10: xorl %eax, %eax +- retq +- +- /* Wake up all threads. */ +-81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi +- movl $SYS_futex, %eax +- movl $1, %edx +- movl $0x7fffffff, %r10d +- syscall +- +- /* For any kind of error, which mainly is EAGAIN, we try again +- with WAKE. The general test also covers running on old +- kernels. */ +- cmpq $-4095, %rax +- jb 10b +- jmp 9f +- +- .align 16 +- /* Unlock. */ +-4: LOCK +- decl cond_lock-cond_futex(%rdi) +- jne 5f +- +-6: xorl %eax, %eax +- retq +- +- /* Initial locking failed. */ +-1: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_lock_wait +-#if cond_lock != 0 +- subq $cond_lock, %rdi +-#endif +- jmp 2b +- +- /* Unlock in loop requires wakeup. */ +-5: addq $cond_lock-cond_futex, %rdi +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- jmp 6b +- +- /* Unlock in loop requires wakeup. */ +-7: addq $cond_lock-cond_futex, %rdi +- cmp $-1, %R8_LP +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- subq $cond_lock-cond_futex, %rdi +- jmp 8b +- +-9: /* The futex requeue functionality is not available. */ +- cmp $-1, %R8_LP +- movl $0x7fffffff, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE, %eax +- movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi +- cmove %eax, %esi +-#else +- movl $0, %eax +- movl %fs:PRIVATE_FUTEX, %esi +- cmove %eax, %esi +- orl $FUTEX_WAKE, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- jmp 10b +- .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +-versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, +- GLIBC_2_3_2) +diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S +deleted file mode 100644 +index 0e8fe0c..0000000 +--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S ++++ /dev/null +@@ -1,164 +0,0 @@ +-/* Copyright (C) 2002-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- +- .text +- +- /* int pthread_cond_signal (pthread_cond_t *cond) */ +- .globl __pthread_cond_signal +- .type __pthread_cond_signal, @function +- .align 16 +-__pthread_cond_signal: +- +- LIBC_PROBE (cond_signal, 1, %rdi) +- +- /* Get internal lock. */ +- movq %rdi, %r8 +- movl $1, %esi +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, cond_lock(%rdi) +-#endif +- jnz 1f +- +-2: addq $cond_futex, %rdi +- movq total_seq(%r8), %rcx +- cmpq wakeup_seq(%r8), %rcx +- jbe 4f +- +- /* Bump the wakeup number. */ +- addq $1, wakeup_seq(%r8) +- addl $1, (%rdi) +- +- /* Wake up one thread. */ +- LP_OP(cmp) $-1, dep_mutex(%r8) +- movl $FUTEX_WAKE_OP, %esi +- movl $1, %edx +- movl $SYS_futex, %eax +- je 8f +- +- /* Get the address of the mutex used. */ +- mov dep_mutex(%r8), %RCX_LP +- movl MUTEX_KIND(%rcx), %r11d +- andl $(ROBUST_BIT|PI_BIT), %r11d +- cmpl $PI_BIT, %r11d +- je 9f +- +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi +-#else +- orl %fs:PRIVATE_FUTEX, %esi +-#endif +- +-8: movl $1, %r10d +-#if cond_lock != 0 +- addq $cond_lock, %r8 +-#endif +- movl $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d +- syscall +-#if cond_lock != 0 +- subq $cond_lock, %r8 +-#endif +- /* For any kind of error, we try again with WAKE. +- The general test also covers running on old kernels. */ +- cmpq $-4095, %rax +- jae 7f +- +- xorl %eax, %eax +- retq +- +- /* Wake up one thread and requeue none in the PI Mutex case. */ +-9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi +- movq %rcx, %r8 +- xorq %r10, %r10 +- movl (%rdi), %r9d // XXX Can this be right? +- syscall +- +- leaq -cond_futex(%rdi), %r8 +- +- /* For any kind of error, we try again with WAKE. +- The general test also covers running on old kernels. */ +- cmpq $-4095, %rax +- jb 4f +- +-7: +-#ifdef __ASSUME_PRIVATE_FUTEX +- andl $FUTEX_PRIVATE_FLAG, %esi +-#else +- andl %fs:PRIVATE_FUTEX, %esi +-#endif +- orl $FUTEX_WAKE, %esi +- movl $SYS_futex, %eax +- /* %rdx should be 1 already from $FUTEX_WAKE_OP syscall. +- movl $1, %edx */ +- syscall +- +- /* Unlock. */ +-4: LOCK +-#if cond_lock == 0 +- decl (%r8) +-#else +- decl cond_lock(%r8) +-#endif +- jne 5f +- +-6: xorl %eax, %eax +- retq +- +- /* Initial locking failed. */ +-1: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_lock_wait +-#if cond_lock != 0 +- subq $cond_lock, %rdi +-#endif +- jmp 2b +- +- /* Unlock in loop requires wakeup. */ +-5: +- movq %r8, %rdi +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- jmp 6b +- .size __pthread_cond_signal, .-__pthread_cond_signal +-versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, +- GLIBC_2_3_2) +diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +deleted file mode 100644 +index 15b872d..0000000 +--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S ++++ /dev/null +@@ -1,623 +0,0 @@ +-/* Copyright (C) 2002-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +- +- .text +- +- +-/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, +- const struct timespec *abstime) */ +- .globl __pthread_cond_timedwait +- .type __pthread_cond_timedwait, @function +- .align 16 +-__pthread_cond_timedwait: +-.LSTARTCODE: +- cfi_startproc +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +-#endif +- +- pushq %r12 +- cfi_adjust_cfa_offset(8) +- cfi_rel_offset(%r12, 0) +- pushq %r13 +- cfi_adjust_cfa_offset(8) +- cfi_rel_offset(%r13, 0) +- pushq %r14 +- cfi_adjust_cfa_offset(8) +- cfi_rel_offset(%r14, 0) +- pushq %r15 +- cfi_adjust_cfa_offset(8) +- cfi_rel_offset(%r15, 0) +-#define FRAME_SIZE (32+8) +- subq $FRAME_SIZE, %rsp +- cfi_adjust_cfa_offset(FRAME_SIZE) +- cfi_remember_state +- +- LIBC_PROBE (cond_timedwait, 3, %rdi, %rsi, %rdx) +- +- cmpq $1000000000, 8(%rdx) +- movl $EINVAL, %eax +- jae 48f +- +- /* Stack frame: +- +- rsp + 48 +- +--------------------------+ +- rsp + 32 | timeout value | +- +--------------------------+ +- rsp + 24 | old wake_seq value | +- +--------------------------+ +- rsp + 16 | mutex pointer | +- +--------------------------+ +- rsp + 8 | condvar pointer | +- +--------------------------+ +- rsp + 4 | old broadcast_seq value | +- +--------------------------+ +- rsp + 0 | old cancellation mode | +- +--------------------------+ +- */ +- +- LP_OP(cmp) $-1, dep_mutex(%rdi) +- +- /* Prepare structure passed to cancellation handler. */ +- movq %rdi, 8(%rsp) +- movq %rsi, 16(%rsp) +- movq %rdx, %r13 +- +- je 22f +- mov %RSI_LP, dep_mutex(%rdi) +- +-22: +- xorb %r15b, %r15b +- +- /* Get internal lock. */ +- movl $1, %esi +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, cond_lock(%rdi) +-#endif +- jnz 31f +- +- /* Unlock the mutex. */ +-32: movq 16(%rsp), %rdi +- xorl %esi, %esi +- callq __pthread_mutex_unlock_usercnt +- +- testl %eax, %eax +- jne 46f +- +- movq 8(%rsp), %rdi +- incq total_seq(%rdi) +- incl cond_futex(%rdi) +- addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) +- +- /* Get and store current wakeup_seq value. */ +- movq 8(%rsp), %rdi +- movq wakeup_seq(%rdi), %r9 +- movl broadcast_seq(%rdi), %edx +- movq %r9, 24(%rsp) +- movl %edx, 4(%rsp) +- +- cmpq $0, (%r13) +- movq $-ETIMEDOUT, %r14 +- js 36f +- +-38: movl cond_futex(%rdi), %r12d +- +- /* Unlock. */ +- LOCK +-#if cond_lock == 0 +- decl (%rdi) +-#else +- decl cond_lock(%rdi) +-#endif +- jne 33f +- +-.LcleanupSTART1: +-34: callq __pthread_enable_asynccancel +- movl %eax, (%rsp) +- +- movq %r13, %r10 +- movl $FUTEX_WAIT_BITSET, %esi +- LP_OP(cmp) $-1, dep_mutex(%rdi) +- je 60f +- +- mov dep_mutex(%rdi), %R8_LP +- /* Requeue to a non-robust PI mutex if the PI bit is set and +- the robust bit is not set. */ +- movl MUTEX_KIND(%r8), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- jne 61f +- +- movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi +- xorl %eax, %eax +- /* The following only works like this because we only support +- two clocks, represented using a single bit. */ +- testl $1, cond_nwaiters(%rdi) +- movl $FUTEX_CLOCK_REALTIME, %edx +- cmove %edx, %eax +- orl %eax, %esi +- movq %r12, %rdx +- addq $cond_futex, %rdi +- movl $SYS_futex, %eax +- syscall +- +- cmpl $0, %eax +- sete %r15b +- +-#ifdef __ASSUME_REQUEUE_PI +- jmp 62f +-#else +- je 62f +- +- /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns +- successfully, it has already locked the mutex for us and the +- pi_flag (%r15b) is set to denote that fact. However, if another +- thread changed the futex value before we entered the wait, the +- syscall may return an EAGAIN and the mutex is not locked. We go +- ahead with a success anyway since later we look at the pi_flag to +- decide if we got the mutex or not. The sequence numbers then make +- sure that only one of the threads actually wake up. We retry using +- normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal +- and PI futexes don't mix. +- +- Note that we don't check for EAGAIN specifically; we assume that the +- only other error the futex function could return is EAGAIN (barring +- the ETIMEOUT of course, for the timeout case in futex) since +- anything else would mean an error in our function. It is too +- expensive to do that check for every call (which is quite common in +- case of a large number of threads), so it has been skipped. */ +- cmpl $-ENOSYS, %eax +- jne 62f +- +- subq $cond_futex, %rdi +-#endif +- +-61: movl $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi +-60: xorb %r15b, %r15b +- xorl %eax, %eax +- /* The following only works like this because we only support +- two clocks, represented using a single bit. */ +- testl $1, cond_nwaiters(%rdi) +- movl $FUTEX_CLOCK_REALTIME, %edx +- movl $0xffffffff, %r9d +- cmove %edx, %eax +- orl %eax, %esi +- movq %r12, %rdx +- addq $cond_futex, %rdi +- movl $SYS_futex, %eax +- syscall +-62: movq %rax, %r14 +- +- movl (%rsp), %edi +- callq __pthread_disable_asynccancel +-.LcleanupEND1: +- +- /* Lock. */ +- movq 8(%rsp), %rdi +- movl $1, %esi +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, cond_lock(%rdi) +-#endif +- jne 35f +- +-36: movl broadcast_seq(%rdi), %edx +- +- movq woken_seq(%rdi), %rax +- +- movq wakeup_seq(%rdi), %r9 +- +- cmpl 4(%rsp), %edx +- jne 53f +- +- cmpq 24(%rsp), %r9 +- jbe 45f +- +- cmpq %rax, %r9 +- ja 39f +- +-45: cmpq $-ETIMEDOUT, %r14 +- je 99f +- +- /* We need to go back to futex_wait. If we're using requeue_pi, then +- release the mutex we had acquired and go back. */ +- test %r15b, %r15b +- jz 38b +- +- /* Adjust the mutex values first and then unlock it. The unlock +- should always succeed or else the kernel did not lock the +- mutex correctly. */ +- movq %r8, %rdi +- callq __pthread_mutex_cond_lock_adjust +- xorl %esi, %esi +- callq __pthread_mutex_unlock_usercnt +- /* Reload cond_var. */ +- movq 8(%rsp), %rdi +- jmp 38b +- +-99: incq wakeup_seq(%rdi) +- incl cond_futex(%rdi) +- movl $ETIMEDOUT, %r14d +- jmp 44f +- +-53: xorq %r14, %r14 +- jmp 54f +- +-39: xorq %r14, %r14 +-44: incq woken_seq(%rdi) +- +-54: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) +- +- /* Wake up a thread which wants to destroy the condvar object. */ +- cmpq $0xffffffffffffffff, total_seq(%rdi) +- jne 55f +- movl cond_nwaiters(%rdi), %eax +- andl $~((1 << nwaiters_shift) - 1), %eax +- jne 55f +- +- addq $cond_nwaiters, %rdi +- LP_OP(cmp) $-1, dep_mutex-cond_nwaiters(%rdi) +- movl $1, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE, %eax +- movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi +- cmove %eax, %esi +-#else +- movl $0, %eax +- movl %fs:PRIVATE_FUTEX, %esi +- cmove %eax, %esi +- orl $FUTEX_WAKE, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- subq $cond_nwaiters, %rdi +- +-55: LOCK +-#if cond_lock == 0 +- decl (%rdi) +-#else +- decl cond_lock(%rdi) +-#endif +- jne 40f +- +- /* If requeue_pi is used the kernel performs the locking of the +- mutex. */ +-41: movq 16(%rsp), %rdi +- testb %r15b, %r15b +- jnz 64f +- +- callq __pthread_mutex_cond_lock +- +-63: testq %rax, %rax +- cmoveq %r14, %rax +- +-48: addq $FRAME_SIZE, %rsp +- cfi_adjust_cfa_offset(-FRAME_SIZE) +- popq %r15 +- cfi_adjust_cfa_offset(-8) +- cfi_restore(%r15) +- popq %r14 +- cfi_adjust_cfa_offset(-8) +- cfi_restore(%r14) +- popq %r13 +- cfi_adjust_cfa_offset(-8) +- cfi_restore(%r13) +- popq %r12 +- cfi_adjust_cfa_offset(-8) +- cfi_restore(%r12) +- +- retq +- +- cfi_restore_state +- +-64: callq __pthread_mutex_cond_lock_adjust +- movq %r14, %rax +- jmp 48b +- +- /* Initial locking failed. */ +-31: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_lock_wait +- jmp 32b +- +- /* Unlock in loop requires wakeup. */ +-33: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- jmp 34b +- +- /* Locking in loop failed. */ +-35: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_lock_wait +-#if cond_lock != 0 +- subq $cond_lock, %rdi +-#endif +- jmp 36b +- +- /* Unlock after loop requires wakeup. */ +-40: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- jmp 41b +- +- /* The initial unlocking of the mutex failed. */ +-46: movq 8(%rsp), %rdi +- movq %rax, (%rsp) +- LOCK +-#if cond_lock == 0 +- decl (%rdi) +-#else +- decl cond_lock(%rdi) +-#endif +- jne 47f +- +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- +-47: movq (%rsp), %rax +- jmp 48b +- +- .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +- GLIBC_2_3_2) +- +- +- .align 16 +- .type __condvar_cleanup2, @function +-__condvar_cleanup2: +- /* Stack frame: +- +- rsp + 72 +- +--------------------------+ +- rsp + 64 | %r12 | +- +--------------------------+ +- rsp + 56 | %r13 | +- +--------------------------+ +- rsp + 48 | %r14 | +- +--------------------------+ +- rsp + 24 | unused | +- +--------------------------+ +- rsp + 16 | mutex pointer | +- +--------------------------+ +- rsp + 8 | condvar pointer | +- +--------------------------+ +- rsp + 4 | old broadcast_seq value | +- +--------------------------+ +- rsp + 0 | old cancellation mode | +- +--------------------------+ +- */ +- +- movq %rax, 24(%rsp) +- +- /* Get internal lock. */ +- movq 8(%rsp), %rdi +- movl $1, %esi +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, cond_lock(%rdi) +-#endif +- jz 1f +- +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_lock_wait +-#if cond_lock != 0 +- subq $cond_lock, %rdi +-#endif +- +-1: movl broadcast_seq(%rdi), %edx +- cmpl 4(%rsp), %edx +- jne 3f +- +- /* We increment the wakeup_seq counter only if it is lower than +- total_seq. If this is not the case the thread was woken and +- then canceled. In this case we ignore the signal. */ +- movq total_seq(%rdi), %rax +- cmpq wakeup_seq(%rdi), %rax +- jbe 6f +- incq wakeup_seq(%rdi) +- incl cond_futex(%rdi) +-6: incq woken_seq(%rdi) +- +-3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) +- +- /* Wake up a thread which wants to destroy the condvar object. */ +- xorq %r12, %r12 +- cmpq $0xffffffffffffffff, total_seq(%rdi) +- jne 4f +- movl cond_nwaiters(%rdi), %eax +- andl $~((1 << nwaiters_shift) - 1), %eax +- jne 4f +- +- LP_OP(cmp) $-1, dep_mutex(%rdi) +- leaq cond_nwaiters(%rdi), %rdi +- movl $1, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE, %eax +- movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi +- cmove %eax, %esi +-#else +- movl $0, %eax +- movl %fs:PRIVATE_FUTEX, %esi +- cmove %eax, %esi +- orl $FUTEX_WAKE, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- subq $cond_nwaiters, %rdi +- movl $1, %r12d +- +-4: LOCK +-#if cond_lock == 0 +- decl (%rdi) +-#else +- decl cond_lock(%rdi) +-#endif +- je 2f +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- +- /* Wake up all waiters to make sure no signal gets lost. */ +-2: testq %r12, %r12 +- jnz 5f +- addq $cond_futex, %rdi +- LP_OP(cmp) $-1, dep_mutex-cond_futex(%rdi) +- movl $0x7fffffff, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE, %eax +- movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi +- cmove %eax, %esi +-#else +- movl $0, %eax +- movl %fs:PRIVATE_FUTEX, %esi +- cmove %eax, %esi +- orl $FUTEX_WAKE, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- +- /* Lock the mutex only if we don't own it already. This only happens +- in case of PI mutexes, if we got cancelled after a successful +- return of the futex syscall and before disabling async +- cancellation. */ +-5: movq 16(%rsp), %rdi +- movl MUTEX_KIND(%rdi), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- jne 7f +- +- movl (%rdi), %eax +- andl $TID_MASK, %eax +- cmpl %eax, %fs:TID +- jne 7f +- /* We managed to get the lock. Fix it up before returning. */ +- callq __pthread_mutex_cond_lock_adjust +- jmp 8f +- +-7: callq __pthread_mutex_cond_lock +- +-8: movq 24(%rsp), %rdi +- movq FRAME_SIZE(%rsp), %r15 +- movq FRAME_SIZE+8(%rsp), %r14 +- movq FRAME_SIZE+16(%rsp), %r13 +- movq FRAME_SIZE+24(%rsp), %r12 +-.LcallUR: +- call _Unwind_Resume@PLT +- hlt +-.LENDCODE: +- cfi_endproc +- .size __condvar_cleanup2, .-__condvar_cleanup2 +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit # @LPStart format +- .byte DW_EH_PE_omit # @TType format +- .byte DW_EH_PE_uleb128 # call-site format +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART1-.LSTARTCODE +- .uleb128 .LcleanupEND1-.LcleanupSTART1 +- .uleb128 __condvar_cleanup2-.LSTARTCODE +- .uleb128 0 +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-.Lcstend: +- +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align LP_SIZE +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, LP_SIZE +-DW.ref.__gcc_personality_v0: +- ASM_ADDR __gcc_personality_v0 +-#endif +diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S +deleted file mode 100644 +index 2e564a7..0000000 +--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S ++++ /dev/null +@@ -1,555 +0,0 @@ +-/* Copyright (C) 2002-2015 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2002. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +- +- .text +- +-/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ +- .globl __pthread_cond_wait +- .type __pthread_cond_wait, @function +- .align 16 +-__pthread_cond_wait: +-.LSTARTCODE: +- cfi_startproc +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +-#endif +- +-#define FRAME_SIZE (32+8) +- leaq -FRAME_SIZE(%rsp), %rsp +- cfi_adjust_cfa_offset(FRAME_SIZE) +- +- /* Stack frame: +- +- rsp + 32 +- +--------------------------+ +- rsp + 24 | old wake_seq value | +- +--------------------------+ +- rsp + 16 | mutex pointer | +- +--------------------------+ +- rsp + 8 | condvar pointer | +- +--------------------------+ +- rsp + 4 | old broadcast_seq value | +- +--------------------------+ +- rsp + 0 | old cancellation mode | +- +--------------------------+ +- */ +- +- LIBC_PROBE (cond_wait, 2, %rdi, %rsi) +- +- LP_OP(cmp) $-1, dep_mutex(%rdi) +- +- /* Prepare structure passed to cancellation handler. */ +- movq %rdi, 8(%rsp) +- movq %rsi, 16(%rsp) +- +- je 15f +- mov %RSI_LP, dep_mutex(%rdi) +- +- /* Get internal lock. */ +-15: movl $1, %esi +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, cond_lock(%rdi) +-#endif +- jne 1f +- +- /* Unlock the mutex. */ +-2: movq 16(%rsp), %rdi +- xorl %esi, %esi +- callq __pthread_mutex_unlock_usercnt +- +- testl %eax, %eax +- jne 12f +- +- movq 8(%rsp), %rdi +- incq total_seq(%rdi) +- incl cond_futex(%rdi) +- addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) +- +- /* Get and store current wakeup_seq value. */ +- movq 8(%rsp), %rdi +- movq wakeup_seq(%rdi), %r9 +- movl broadcast_seq(%rdi), %edx +- movq %r9, 24(%rsp) +- movl %edx, 4(%rsp) +- +- /* Unlock. */ +-8: movl cond_futex(%rdi), %edx +- LOCK +-#if cond_lock == 0 +- decl (%rdi) +-#else +- decl cond_lock(%rdi) +-#endif +- jne 3f +- +-.LcleanupSTART: +-4: callq __pthread_enable_asynccancel +- movl %eax, (%rsp) +- +- xorq %r10, %r10 +- LP_OP(cmp) $-1, dep_mutex(%rdi) +- leaq cond_futex(%rdi), %rdi +- movl $FUTEX_WAIT, %esi +- je 60f +- +- mov dep_mutex-cond_futex(%rdi), %R8_LP +- /* Requeue to a non-robust PI mutex if the PI bit is set and +- the robust bit is not set. */ +- movl MUTEX_KIND(%r8), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- jne 61f +- +- movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi +- movl $SYS_futex, %eax +- syscall +- +- cmpl $0, %eax +- sete %r8b +- +-#ifdef __ASSUME_REQUEUE_PI +- jmp 62f +-#else +- je 62f +- +- /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns +- successfully, it has already locked the mutex for us and the +- pi_flag (%r8b) is set to denote that fact. However, if another +- thread changed the futex value before we entered the wait, the +- syscall may return an EAGAIN and the mutex is not locked. We go +- ahead with a success anyway since later we look at the pi_flag to +- decide if we got the mutex or not. The sequence numbers then make +- sure that only one of the threads actually wake up. We retry using +- normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal +- and PI futexes don't mix. +- +- Note that we don't check for EAGAIN specifically; we assume that the +- only other error the futex function could return is EAGAIN since +- anything else would mean an error in our function. It is too +- expensive to do that check for every call (which is quite common in +- case of a large number of threads), so it has been skipped. */ +- cmpl $-ENOSYS, %eax +- jne 62f +- +-# ifndef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAIT, %esi +-# endif +-#endif +- +-61: +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi +-#else +- orl %fs:PRIVATE_FUTEX, %esi +-#endif +-60: xorb %r8b, %r8b +- movl $SYS_futex, %eax +- syscall +- +-62: movl (%rsp), %edi +- callq __pthread_disable_asynccancel +-.LcleanupEND: +- +- /* Lock. */ +- movq 8(%rsp), %rdi +- movl $1, %esi +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, cond_lock(%rdi) +-#endif +- jnz 5f +- +-6: movl broadcast_seq(%rdi), %edx +- +- movq woken_seq(%rdi), %rax +- +- movq wakeup_seq(%rdi), %r9 +- +- cmpl 4(%rsp), %edx +- jne 16f +- +- cmpq 24(%rsp), %r9 +- jbe 19f +- +- cmpq %rax, %r9 +- jna 19f +- +- incq woken_seq(%rdi) +- +- /* Unlock */ +-16: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) +- +- /* Wake up a thread which wants to destroy the condvar object. */ +- cmpq $0xffffffffffffffff, total_seq(%rdi) +- jne 17f +- movl cond_nwaiters(%rdi), %eax +- andl $~((1 << nwaiters_shift) - 1), %eax +- jne 17f +- +- addq $cond_nwaiters, %rdi +- LP_OP(cmp) $-1, dep_mutex-cond_nwaiters(%rdi) +- movl $1, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE, %eax +- movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi +- cmove %eax, %esi +-#else +- movl $0, %eax +- movl %fs:PRIVATE_FUTEX, %esi +- cmove %eax, %esi +- orl $FUTEX_WAKE, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- subq $cond_nwaiters, %rdi +- +-17: LOCK +-#if cond_lock == 0 +- decl (%rdi) +-#else +- decl cond_lock(%rdi) +-#endif +- jne 10f +- +- /* If requeue_pi is used the kernel performs the locking of the +- mutex. */ +-11: movq 16(%rsp), %rdi +- testb %r8b, %r8b +- jnz 18f +- +- callq __pthread_mutex_cond_lock +- +-14: leaq FRAME_SIZE(%rsp), %rsp +- cfi_adjust_cfa_offset(-FRAME_SIZE) +- +- /* We return the result of the mutex_lock operation. */ +- retq +- +- cfi_adjust_cfa_offset(FRAME_SIZE) +- +-18: callq __pthread_mutex_cond_lock_adjust +- xorl %eax, %eax +- jmp 14b +- +- /* We need to go back to futex_wait. If we're using requeue_pi, then +- release the mutex we had acquired and go back. */ +-19: testb %r8b, %r8b +- jz 8b +- +- /* Adjust the mutex values first and then unlock it. The unlock +- should always succeed or else the kernel did not lock the mutex +- correctly. */ +- movq 16(%rsp), %rdi +- callq __pthread_mutex_cond_lock_adjust +- movq %rdi, %r8 +- xorl %esi, %esi +- callq __pthread_mutex_unlock_usercnt +- /* Reload cond_var. */ +- movq 8(%rsp), %rdi +- jmp 8b +- +- /* Initial locking failed. */ +-1: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_lock_wait +- jmp 2b +- +- /* Unlock in loop requires wakeup. */ +-3: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- /* The call preserves %rdx. */ +- callq __lll_unlock_wake +-#if cond_lock != 0 +- subq $cond_lock, %rdi +-#endif +- jmp 4b +- +- /* Locking in loop failed. */ +-5: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_lock_wait +-#if cond_lock != 0 +- subq $cond_lock, %rdi +-#endif +- jmp 6b +- +- /* Unlock after loop requires wakeup. */ +-10: +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- jmp 11b +- +- /* The initial unlocking of the mutex failed. */ +-12: movq %rax, %r10 +- movq 8(%rsp), %rdi +- LOCK +-#if cond_lock == 0 +- decl (%rdi) +-#else +- decl cond_lock(%rdi) +-#endif +- je 13f +- +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_unlock_wake +- +-13: movq %r10, %rax +- jmp 14b +- +- .size __pthread_cond_wait, .-__pthread_cond_wait +-versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, +- GLIBC_2_3_2) +- +- +- .align 16 +- .type __condvar_cleanup1, @function +- .globl __condvar_cleanup1 +- .hidden __condvar_cleanup1 +-__condvar_cleanup1: +- /* Stack frame: +- +- rsp + 32 +- +--------------------------+ +- rsp + 24 | unused | +- +--------------------------+ +- rsp + 16 | mutex pointer | +- +--------------------------+ +- rsp + 8 | condvar pointer | +- +--------------------------+ +- rsp + 4 | old broadcast_seq value | +- +--------------------------+ +- rsp + 0 | old cancellation mode | +- +--------------------------+ +- */ +- +- movq %rax, 24(%rsp) +- +- /* Get internal lock. */ +- movq 8(%rsp), %rdi +- movl $1, %esi +- xorl %eax, %eax +- LOCK +-#if cond_lock == 0 +- cmpxchgl %esi, (%rdi) +-#else +- cmpxchgl %esi, cond_lock(%rdi) +-#endif +- jz 1f +- +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- callq __lll_lock_wait +-#if cond_lock != 0 +- subq $cond_lock, %rdi +-#endif +- +-1: movl broadcast_seq(%rdi), %edx +- cmpl 4(%rsp), %edx +- jne 3f +- +- /* We increment the wakeup_seq counter only if it is lower than +- total_seq. If this is not the case the thread was woken and +- then canceled. In this case we ignore the signal. */ +- movq total_seq(%rdi), %rax +- cmpq wakeup_seq(%rdi), %rax +- jbe 6f +- incq wakeup_seq(%rdi) +- incl cond_futex(%rdi) +-6: incq woken_seq(%rdi) +- +-3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) +- +- /* Wake up a thread which wants to destroy the condvar object. */ +- xorl %ecx, %ecx +- cmpq $0xffffffffffffffff, total_seq(%rdi) +- jne 4f +- movl cond_nwaiters(%rdi), %eax +- andl $~((1 << nwaiters_shift) - 1), %eax +- jne 4f +- +- LP_OP(cmp) $-1, dep_mutex(%rdi) +- leaq cond_nwaiters(%rdi), %rdi +- movl $1, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE, %eax +- movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi +- cmove %eax, %esi +-#else +- movl $0, %eax +- movl %fs:PRIVATE_FUTEX, %esi +- cmove %eax, %esi +- orl $FUTEX_WAKE, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- subq $cond_nwaiters, %rdi +- movl $1, %ecx +- +-4: LOCK +-#if cond_lock == 0 +- decl (%rdi) +-#else +- decl cond_lock(%rdi) +-#endif +- je 2f +-#if cond_lock != 0 +- addq $cond_lock, %rdi +-#endif +- LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) +- movl $LLL_PRIVATE, %eax +- movl $LLL_SHARED, %esi +- cmovne %eax, %esi +- /* The call preserves %rcx. */ +- callq __lll_unlock_wake +- +- /* Wake up all waiters to make sure no signal gets lost. */ +-2: testl %ecx, %ecx +- jnz 5f +- addq $cond_futex, %rdi +- LP_OP(cmp) $-1, dep_mutex-cond_futex(%rdi) +- movl $0x7fffffff, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE, %eax +- movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi +- cmove %eax, %esi +-#else +- movl $0, %eax +- movl %fs:PRIVATE_FUTEX, %esi +- cmove %eax, %esi +- orl $FUTEX_WAKE, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- +- /* Lock the mutex only if we don't own it already. This only happens +- in case of PI mutexes, if we got cancelled after a successful +- return of the futex syscall and before disabling async +- cancellation. */ +-5: movq 16(%rsp), %rdi +- movl MUTEX_KIND(%rdi), %eax +- andl $(ROBUST_BIT|PI_BIT), %eax +- cmpl $PI_BIT, %eax +- jne 7f +- +- movl (%rdi), %eax +- andl $TID_MASK, %eax +- cmpl %eax, %fs:TID +- jne 7f +- /* We managed to get the lock. Fix it up before returning. */ +- callq __pthread_mutex_cond_lock_adjust +- jmp 8f +- +- +-7: callq __pthread_mutex_cond_lock +- +-8: movq 24(%rsp), %rdi +-.LcallUR: +- call _Unwind_Resume@PLT +- hlt +-.LENDCODE: +- cfi_endproc +- .size __condvar_cleanup1, .-__condvar_cleanup1 +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit # @LPStart format +- .byte DW_EH_PE_omit # @TType format +- .byte DW_EH_PE_uleb128 # call-site format +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART-.LSTARTCODE +- .uleb128 .LcleanupEND-.LcleanupSTART +- .uleb128 __condvar_cleanup1-.LSTARTCODE +- .uleb128 0 +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-.Lcstend: +- +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align LP_SIZE +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, LP_SIZE +-DW.ref.__gcc_personality_v0: +- ASM_ADDR __gcc_personality_v0 +-#endif +diff --git a/sysdeps/x86/bits/pthreadtypes.h b/sysdeps/x86/bits/pthreadtypes.h +index 4460615..0898455 100644 +--- a/sysdeps/x86/bits/pthreadtypes.h ++++ b/sysdeps/x86/bits/pthreadtypes.h +@@ -140,14 +140,14 @@ typedef union + { + struct + { +- int __lock; +- unsigned int __futex; +- __extension__ unsigned long long int __total_seq; +- __extension__ unsigned long long int __wakeup_seq; +- __extension__ unsigned long long int __woken_seq; ++ unsigned int __wseq; ++#define __PTHREAD_COND_WSEQ_THRESHOLD (~ (unsigned int) 0) ++ unsigned int __signals_sent; ++ unsigned int __confirmed; ++ unsigned int __generation; + void *__mutex; +- unsigned int __nwaiters; +- unsigned int __broadcast_seq; ++ unsigned int __quiescence_waiters; ++ int __clockid; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; diff --git a/glibc-rh1315108.patch b/glibc-rh1315108.patch new file mode 100644 index 0000000..8b4e5fc --- /dev/null +++ b/glibc-rh1315108.patch @@ -0,0 +1,1946 @@ +From the upstream branch fw/extend_alloca. + +commit dc79f9aa56933dc8b475209f9a4059965b50ea26 +Author: Florian Weimer +Date: Sun Mar 1 18:29:47 2015 +0100 + + nscd restart: Use malloc instead of extend_alloca + + This introduces a separate function, read_cmdline, which reads the + contents of /proc/self/cmdline into a heap-allocated buffer. + + [BZ #18023] + * nscd/connections.c (read_cmdline): New function. + (restart): Use it. Update comment. + +commit 9bed8b7fca7867d3027b66ce3985a75136aed013 +Author: Florian Weimer +Date: Sun Mar 1 15:14:19 2015 +0100 + + getgrent_next_nss (compat-initgroups): Remove alloca fallback + + If the caller-supplied buffer is not large enough, fall back directly + malloc. + + The previous __libc_use_alloca check was incorrect because it did not + take into account that extend_alloca may fail to merge allocations, so + it would underestimate the stack space being used by roughly a factor + of two. + + [BZ #18023] + * nis/nss_compat/compat-initgroups.c (getgrent_next_nss): Fall + back to malloc directly, without stack allocations. + +commit c95cc759ecb21f812872934ac55518aef28cf46b +Author: Florian Weimer +Date: Sun Mar 1 16:03:01 2015 +0100 + + _dl_map_object_deps: Use struct scratch_buffer instead of extend_alloca + + The function comment suggests that _dl_map_object_deps cannot use + malloc, but it already allocates the l_initfini array on the heap, so + the additional allocation should be acceptable. + + [BZ #18023] + * elf/dl-deps.c (_dl_map_object_deps): Use struct + scratch_buffer instead of extend_alloca. + +commit e38bff4db6f03d1fab732737f43a25160c3e4703 +Author: Florian Weimer +Date: Sun Mar 1 16:18:21 2015 +0100 + + _nss_nis_initgroups_dyn: Use struct scratch_buffer instead of extend_alloca + + Also adjusts the internal function get_uid. + + [BZ #18023] + * nis/nss_nis/nis-initgroups.c (get_uid, _nss_nis_initgroups_dyn): + Use struct scratch_buffer instead of extend_alloca. + +commit 8825d4709a686a870d313cc602d489ddd5354a08 +Author: Florian Weimer +Date: Sun Mar 1 18:55:33 2015 +0100 + + nscd: Use struct scratch_buffer instead of extend_alloca in most caches + + This replaces the ERANGE retry loops with loops which have heap + fallback. Heap allocation might actually be required for extremely + large NSS results. + + [BZ #18023] + * nscd/grpcache.c (addgrbyX): Use struct scratch_buffer instead + of extend_alloca. + * nscd/hstcache.c (addhstbyX): Likewise. + * nscd/pwdcache.c (addpwbyX): Likewise. + * nscd/servicescache.c (addservbyX): Likewise. + +commit 140d8711d446f5193b04b56e714ddf8d0eddbf62 +Author: Florian Weimer +Date: Sun Mar 1 18:59:48 2015 +0100 + + nscd: Switch to struct scratch_buffer in adhstaiX + + The pre-allocation of the three scratch buffers increased the initial + stack size somewhat, but if retries are needed, the previous version + used more stack space if extend_alloca could not merge allocations. + Lack of alloca accounting also means could be problematic with + extremely large NSS responses, too. + + [BZ #18023] + * nscd/aicache.c (addhstaiX): Use struct scratch_buffer instead + of extend_alloca. + +commit 1af14faef808f03276766e5ee6d9ee7dc9053fba +Author: Florian Weimer +Date: Sun Mar 1 19:03:01 2015 +0100 + + getent: Switch to struct scratch_buffer in initgroups_keys + + The retry loop is slightly different here because getgrouplist + provides size information, so scratch_buffer_set_array_size can be + used to grow the buffer in a more precise fashion. + + [BZ #18023] + * nss/getent.c (initgroups_keys): Use struct scratch_buffer + instead of extend_alloca. + +commit 9b71d3b4df6dd4e49f7638d1d936c921c50fa3d9 +Author: Florian Weimer +Date: Sun Mar 1 19:09:00 2015 +0100 + + nss_files: Use struct scratch_buffer instead of extend_alloca + + In both _nss_files_gethostbyname3_r and _nss_files_initgroups_dyn, + __libc_use_alloca was misused because it was not taken into account + that extend_alloca can fail to merge allocations. + + [BZ #18023] + * nss/nss_files/files-hosts.c (_nss_files_gethostbyname3_r): + Use struct scratch_buffer instead of extend_alloca. + * nss/nss_files/files-initgroups.c (_nss_files_initgroups_dyn): + Likewise. + +commit 11c2a8bad9ca5fe510b73c0204b3dcf703f14d5c +Author: Florian Weimer +Date: Sun Mar 1 19:11:55 2015 +0100 + + gethostid (Linux variant): Switch to struct scratch_buffer + + Previously, extend_alloca was used without alloca accounting, + which could have been problematic with large NSS results. + + [BZ #18023] + * sysdeps/unix/sysv/linux/gethostid.c (gethostid): Use struct + scratch_buffer instead of extend_alloca. + +commit 6de00dd8a3a76d0b7586393451e65ad6c2721a71 +Author: Florian Weimer +Date: Sun Mar 1 19:14:29 2015 +0100 + + getlogin_r (Linux variant): Switch to struct scratch_buffer + + This corrects the alloca accounting as a side effect. It was not off + if extend_alloca failed to merge allocations. + + [BZ #18023] + * sysdeps/unix/sysv/linux/getlogin_r.c (__getlogin_r_loginuid): + Use struct scratch_buffer instead of extend_alloca. + +commit 488063238ee5c87b66c6982b1b6d508e30e44386 +Author: Florian Weimer +Date: Sun Mar 1 19:48:31 2015 +0100 + + wordexp: Rewrite parse_tilde to use struct scratch_buffer + + [BZ #18023] + * posix/wordexp.c (parse_tilde): Use struct scratch_buffer + instead of extend_alloca. + +commit 7b4c16db30304b83a5d1e913d1a8f7e90a8c398c +Author: Florian Weimer +Date: Sun Mar 1 19:49:50 2015 +0100 + + glob: Rewrite to use struct scratch_buffer instead of extend_alloca + + [BZ #18023] + * posix/glob.c (glob): Use struct scratch_buffer instead of + extend_alloca. + +commit 683543bbb3e2c1b17554c4096d00c2980f39a802 +Author: Florian Weimer +Date: Sun Mar 1 23:22:45 2015 +0100 + + Remove macros extend_alloca, extend_alloca_account [BZ #18023] + + And also the helper macro stackinfo_alloca_round. + + extend_alloca simply does not work on x86_64 and current i386 because + its peculiar stack alignment rules. + + Here's an analysis of the _dl_fini situation (before the removal of + extend_alloca). + + Dump of assembler code for function _dl_fini: + <+0>: push %rbp + <+1>: mov %rsp,%rbp + <+4>: push %r15 + <+6>: push %r14 + <+8>: push %r13 + <+10>: push %r12 + <+12>: push %rbx + <+13>: sub $0x38,%rsp + + The function pushes 6 registers on the stack and allocates 0x38 bytes, + which means that %rsp is a multiple of 16 after function prologue. + + The initial alloca allocation does not change %rsp alignment: + + <+210>: shr $0x4,%rcx + <+214>: shl $0x4,%rcx + <+218>: sub %rcx,%rsp + + %r15 is the address of the previous stack allocation, it is used below. + + This is the extend_alloca reallocation branch: + + <+734>: add $0xf,%rdx + <+738>: and $0xfffffffffffffff0,%rdx + <+742>: lea 0x1e(%rdx),%rcx + <+746>: shr $0x4,%rcx + <+750>: shl $0x4,%rcx + <+754>: sub %rcx,%rsp + <+757>: lea 0xf(%rsp),%rcx + <+762>: and $0xfffffffffffffff0,%rcx + <+766>: lea (%rcx,%rdx,1),%rsi + <+770>: cmp %rsi,%r15 + <+773>: je 0x7f963940b673 <_dl_fini+787> + <+775>: mov %rdx,-0x58(%rbp) + <+787>: add %rdx,-0x58(%rbp) + + (a) %rdx, the new requested size, is rounded up to a multiple of 16 + (+734, %+738), and the result is stored in %rdx@738. + + (b) %rdx@738 + 31 is rounded down to a multiple of 16, the result is + stored in rcx@750 (+742, +746, +750). So %rcx@750 == %rdx@738 + 16. + + (c) %rcx@750 bytes are allocated on the stack (+754). %rsp is rounded + upwards to a multiple of 16, result is stored in %rcx@762 (+757, +762). + This does not change the value of %rsp because it already was a multiple + of 16. + + (d) %rsi@766 == %rcx@762 + %rdx@738 is compared against %r15. But this + comparison is always false because we allocated 16 extra bytes on the + stack in (b), which were reserved for the alignment in (c), but in fact + unused. We are left with a gap in stack usage, and the comparison is + always false. + + (@XXX refers to register values after executing the instruction at + offset +XXX.) + + If the alignment gap was actually used because of different alignment + for %rsp, then the comparison failure would still occur because the gap + would not have been added after this reallocation, but before the + previous allocation. + + As a result, extend_alloca is never able to merge allocations. It also + turns out that the interface is difficult to use, especially in + cojunction with alloca account (which is rarely optional). + + [BZ #18023] + * include/alloca.h (stackinfo_alloca_round, extend_alloca, + extend_alloca_account): Remove. +Index: b/elf/dl-deps.c +=================================================================== +--- a/elf/dl-deps.c ++++ b/elf/dl-deps.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include + +@@ -184,9 +185,8 @@ _dl_map_object_deps (struct link_map *ma + /* Pointer to last unique object. */ + tail = &known[nlist - 1]; + +- /* No alloca'd space yet. */ +- struct link_map **needed_space = NULL; +- size_t needed_space_bytes = 0; ++ struct scratch_buffer needed_space; ++ scratch_buffer_init (&needed_space); + + /* Process each element of the search list, loading each of its + auxiliary objects and immediate dependencies. Auxiliary objects +@@ -217,13 +217,12 @@ _dl_map_object_deps (struct link_map *ma + if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL + && l != map && l->l_ldnum > 0) + { +- size_t new_size = l->l_ldnum * sizeof (struct link_map *); +- +- if (new_size > needed_space_bytes) +- needed_space +- = extend_alloca (needed_space, needed_space_bytes, new_size); +- +- needed = needed_space; ++ /* l->l_ldnum includes space for the terminating NULL. */ ++ if (!scratch_buffer_set_array_size ++ (&needed_space, l->l_ldnum, sizeof (struct link_map *))) ++ _dl_signal_error (ENOMEM, map->l_name, NULL, ++ N_("cannot allocate dependency buffer")); ++ needed = needed_space.data; + } + + if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG]) +@@ -463,8 +462,11 @@ _dl_map_object_deps (struct link_map *ma + struct link_map **l_initfini = (struct link_map **) + malloc ((2 * nneeded + 1) * sizeof needed[0]); + if (l_initfini == NULL) +- _dl_signal_error (ENOMEM, map->l_name, NULL, +- N_("cannot allocate dependency list")); ++ { ++ scratch_buffer_free (&needed_space); ++ _dl_signal_error (ENOMEM, map->l_name, NULL, ++ N_("cannot allocate dependency list")); ++ } + l_initfini[0] = l; + memcpy (&l_initfini[1], needed, nneeded * sizeof needed[0]); + memcpy (&l_initfini[nneeded + 1], l_initfini, +@@ -482,6 +484,8 @@ _dl_map_object_deps (struct link_map *ma + } + + out: ++ scratch_buffer_free (&needed_space); ++ + if (errno == 0 && errno_saved != 0) + __set_errno (errno_saved); + +Index: b/include/alloca.h +=================================================================== +--- a/include/alloca.h ++++ b/include/alloca.h +@@ -20,57 +20,17 @@ libc_hidden_proto (__libc_alloca_cutoff) + + #include + +-#ifndef stackinfo_alloca_round +-# define stackinfo_alloca_round(l) (((l) + 15) & -16) +-#endif +- +-#if _STACK_GROWS_DOWN +-# define extend_alloca(buf, len, newlen) \ +- (__typeof (buf)) ({ size_t __newlen = stackinfo_alloca_round (newlen); \ +- char *__newbuf = __alloca (__newlen); \ +- if (__newbuf + __newlen == (char *) (buf)) \ +- len += __newlen; \ +- else \ +- len = __newlen; \ +- __newbuf; }) +-#elif _STACK_GROWS_UP +-# define extend_alloca(buf, len, newlen) \ +- (__typeof (buf)) ({ size_t __newlen = stackinfo_alloca_round (newlen); \ +- char *__newbuf = __alloca (__newlen); \ +- char *__buf = (char *) (buf); \ +- if (__buf + len == __newbuf) \ +- { \ +- len += __newlen; \ +- __newbuf = __buf; \ +- } \ +- else \ +- len = __newlen; \ +- __newbuf; }) +-#else +-# define extend_alloca(buf, len, newlen) \ +- __alloca (((len) = (newlen))) +-#endif +- + #if defined stackinfo_get_sp && defined stackinfo_sub_sp + # define alloca_account(size, avar) \ + ({ void *old__ = stackinfo_get_sp (); \ + void *m__ = __alloca (size); \ + avar += stackinfo_sub_sp (old__); \ + m__; }) +-# define extend_alloca_account(buf, len, newlen, avar) \ +- ({ void *old__ = stackinfo_get_sp (); \ +- void *m__ = extend_alloca (buf, len, newlen); \ +- avar += stackinfo_sub_sp (old__); \ +- m__; }) + #else + # define alloca_account(size, avar) \ + ({ size_t s__ = (size); \ + avar += s__; \ + __alloca (s__); }) +-# define extend_alloca_account(buf, len, newlen, avar) \ +- ({ size_t s__ = (newlen); \ +- avar += s__; \ +- extend_alloca (buf, len, s__); }) + #endif + + #endif +Index: b/nis/nss_compat/compat-initgroups.c +=================================================================== +--- a/nis/nss_compat/compat-initgroups.c ++++ b/nis/nss_compat/compat-initgroups.c +@@ -310,7 +310,6 @@ getgrent_next_nss (ent_t *ent, char *buf + overwrite the pointer with one to a bigger buffer. */ + char *tmpbuf = buffer; + size_t tmplen = buflen; +- bool use_malloc = false; + + for (int i = 0; i < mystart; i++) + { +@@ -319,29 +318,26 @@ getgrent_next_nss (ent_t *ent, char *buf + == NSS_STATUS_TRYAGAIN + && *errnop == ERANGE) + { +- if (__libc_use_alloca (tmplen * 2)) +- { +- if (tmpbuf == buffer) +- { +- tmplen *= 2; +- tmpbuf = __alloca (tmplen); +- } +- else +- tmpbuf = extend_alloca (tmpbuf, tmplen, tmplen * 2); +- } +- else +- { +- tmplen *= 2; +- char *newbuf = realloc (use_malloc ? tmpbuf : NULL, tmplen); +- +- if (newbuf == NULL) +- { +- status = NSS_STATUS_TRYAGAIN; +- goto done; +- } +- use_malloc = true; +- tmpbuf = newbuf; +- } ++ /* Check for overflow. */ ++ if (__glibc_unlikely (tmplen * 2 < tmplen)) ++ { ++ __set_errno (ENOMEM); ++ status = NSS_STATUS_TRYAGAIN; ++ goto done; ++ } ++ /* Increase the size. Make sure that we retry ++ with a reasonable size. */ ++ tmplen *= 2; ++ if (tmplen < 1024) ++ tmplen = 1024; ++ if (tmpbuf != buffer) ++ free (tmpbuf); ++ tmpbuf = malloc (tmplen); ++ if (__glibc_unlikely (tmpbuf == NULL)) ++ { ++ status = NSS_STATUS_TRYAGAIN; ++ goto done; ++ } + } + + if (__builtin_expect (status != NSS_STATUS_NOTFOUND, 1)) +@@ -369,7 +365,7 @@ getgrent_next_nss (ent_t *ent, char *buf + status = NSS_STATUS_NOTFOUND; + + done: +- if (use_malloc) ++ if (tmpbuf != buffer) + free (tmpbuf); + } + +Index: b/nis/nss_nis/nis-initgroups.c +=================================================================== +--- a/nis/nss_nis/nis-initgroups.c ++++ b/nis/nss_nis/nis-initgroups.c +@@ -16,7 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-#include + #include + #include + #include +@@ -27,6 +26,7 @@ + #include + #include + #include ++#include + + #include "nss-nis.h" + #include +@@ -120,27 +120,30 @@ internal_getgrent_r (struct group *grp, + static int + get_uid (const char *user, uid_t *uidp) + { +- size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); +- char *buf = (char *) alloca (buflen); ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + + while (1) + { + struct passwd result; + struct passwd *resp; + +- int r = getpwnam_r (user, &result, buf, buflen, &resp); ++ int r = getpwnam_r (user, &result, tmpbuf.data, tmpbuf.length, &resp); + if (r == 0 && resp != NULL) + { + *uidp = resp->pw_uid; ++ scratch_buffer_free (&tmpbuf); + return 0; + } + + if (r != ERANGE) + break; + +- buf = extend_alloca (buf, buflen, 2 * buflen); ++ if (!scratch_buffer_grow (&tmpbuf)) ++ return 1; + } + ++ scratch_buffer_free (&tmpbuf); + return 1; + } + +@@ -254,8 +257,6 @@ _nss_nis_initgroups_dyn (const char *use + } + + struct group grpbuf, *g; +- size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); +- char *tmpbuf; + enum nss_status status; + intern_t intern = { NULL, NULL, 0 }; + gid_t *groups = *groupsp; +@@ -264,15 +265,21 @@ _nss_nis_initgroups_dyn (const char *use + if (status != NSS_STATUS_SUCCESS) + return status; + +- tmpbuf = __alloca (buflen); ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + + while (1) + { + while ((status = +- internal_getgrent_r (&grpbuf, tmpbuf, buflen, errnop, ++ internal_getgrent_r (&grpbuf, tmpbuf.data, tmpbuf.length, errnop, + &intern)) == NSS_STATUS_TRYAGAIN + && *errnop == ERANGE) +- tmpbuf = extend_alloca (tmpbuf, buflen, 2 * buflen); ++ if (!scratch_buffer_grow (&tmpbuf)) ++ { ++ status = NSS_STATUS_TRYAGAIN; ++ *errnop = errno; ++ goto done; ++ } + + if (status != NSS_STATUS_SUCCESS) + { +@@ -331,6 +338,7 @@ done: + intern.start = intern.start->next; + free (intern.next); + } ++ scratch_buffer_free (&tmpbuf); + + return status; + } +Index: b/nscd/aicache.c +=================================================================== +--- a/nscd/aicache.c ++++ b/nscd/aicache.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include "dbg_log.h" + #include "nscd.h" +@@ -113,10 +114,13 @@ addhstaiX (struct database_dyn *db, int + int old_res_options = _res.options; + _res.options &= ~RES_USE_INET6; + +- size_t tmpbuf6len = 1024; +- char *tmpbuf6 = alloca (tmpbuf6len); +- size_t tmpbuf4len = 0; +- char *tmpbuf4 = NULL; ++ struct scratch_buffer tmpbuf6; ++ scratch_buffer_init (&tmpbuf6); ++ struct scratch_buffer tmpbuf4; ++ scratch_buffer_init (&tmpbuf4); ++ struct scratch_buffer canonbuf; ++ scratch_buffer_init (&canonbuf); ++ + int32_t ttl = INT32_MAX; + ssize_t total = 0; + char *key_copy = NULL; +@@ -129,6 +133,7 @@ addhstaiX (struct database_dyn *db, int + int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL }; + int naddrs = 0; + size_t addrslen = 0; ++ + char *canon = NULL; + size_t canonlen; + +@@ -143,12 +148,17 @@ addhstaiX (struct database_dyn *db, int + at = &atmem; + rc6 = 0; + herrno = 0; +- status[1] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len, ++ status[1] = DL_CALL_FCT (fct4, (key, &at, ++ tmpbuf6.data, tmpbuf6.length, + &rc6, &herrno, &ttl)); + if (rc6 != ERANGE || (herrno != NETDB_INTERNAL + && herrno != TRY_AGAIN)) + break; +- tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len); ++ if (!scratch_buffer_grow (&tmpbuf6)) ++ { ++ rc6 = ENOMEM; ++ break; ++ } + } + + if (rc6 != 0 && herrno == NETDB_INTERNAL) +@@ -226,41 +236,38 @@ addhstaiX (struct database_dyn *db, int + while (1) + { + rc6 = 0; +- status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], tmpbuf6, +- tmpbuf6len, &rc6, &herrno, &ttl, ++ status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], ++ tmpbuf6.data, tmpbuf6.length, ++ &rc6, &herrno, &ttl, + &canon)); + if (rc6 != ERANGE || herrno != NETDB_INTERNAL) + break; +- tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len); ++ if (!scratch_buffer_grow (&tmpbuf6)) ++ { ++ rc6 = ENOMEM; ++ break; ++ } + } + + if (rc6 != 0 && herrno == NETDB_INTERNAL) + goto out; + +- /* If the IPv6 lookup has been successful do not use the +- buffer used in that lookup, use a new one. */ +- if (status[0] == NSS_STATUS_SUCCESS && rc6 == 0) +- { +- tmpbuf4len = 512; +- tmpbuf4 = alloca (tmpbuf4len); +- } +- else +- { +- tmpbuf4len = tmpbuf6len; +- tmpbuf4 = tmpbuf6; +- } +- + /* Next collect IPv4 information. */ + while (1) + { + rc4 = 0; +- status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1], tmpbuf4, +- tmpbuf4len, &rc4, &herrno, ++ status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1], ++ tmpbuf4.data, tmpbuf4.length, ++ &rc4, &herrno, + ttl == INT32_MAX ? &ttl : NULL, + canon == NULL ? &canon : NULL)); + if (rc4 != ERANGE || herrno != NETDB_INTERNAL) + break; +- tmpbuf4 = extend_alloca (tmpbuf4, tmpbuf4len, 2 * tmpbuf4len); ++ if (!scratch_buffer_grow (&tmpbuf4)) ++ { ++ rc4 = ENOMEM; ++ break; ++ } + } + + if (rc4 != 0 && herrno == NETDB_INTERNAL) +@@ -286,13 +293,11 @@ addhstaiX (struct database_dyn *db, int + cfct = __nss_lookup_function (nip, "getcanonname_r"); + if (cfct != NULL) + { +- const size_t max_fqdn_len = 256; +- char *buf = alloca (max_fqdn_len); + char *s; + int rc; + +- if (DL_CALL_FCT (cfct, (key, buf, max_fqdn_len, &s, +- &rc, &herrno)) ++ if (DL_CALL_FCT (cfct, (key, canonbuf.data, canonbuf.length, ++ &s, &rc, &herrno)) + == NSS_STATUS_SUCCESS) + canon = s; + else +@@ -321,18 +326,20 @@ addhstaiX (struct database_dyn *db, int + addrfamily = AF_INET6; + } + +- size_t tmpbuflen = 512; +- char *tmpbuf = alloca (tmpbuflen); + int rc; + while (1) + { + rc = __gethostbyaddr2_r (addr, addrlen, addrfamily, +- &hstent_mem, tmpbuf, tmpbuflen, ++ &hstent_mem, ++ canonbuf.data, canonbuf.length, + &hstent, &herrno, NULL); + if (rc != ERANGE || herrno != NETDB_INTERNAL) + break; +- tmpbuf = extend_alloca (tmpbuf, tmpbuflen, +- tmpbuflen * 2); ++ if (!scratch_buffer_grow (&canonbuf)) ++ { ++ rc = ENOMEM; ++ break; ++ } + } + + if (rc == 0) +@@ -560,6 +567,10 @@ next_nip: + dh->usable = false; + } + ++ scratch_buffer_free (&tmpbuf6); ++ scratch_buffer_free (&tmpbuf4); ++ scratch_buffer_free (&canonbuf); ++ + return timeout; + } + +Index: b/nscd/connections.c +=================================================================== +--- a/nscd/connections.c ++++ b/nscd/connections.c +@@ -1353,64 +1353,83 @@ request from '%s' [%ld] not handled due + } + } + +- +-/* Restart the process. */ +-static void +-restart (void) ++static char * ++read_cmdline (size_t *size) + { +- /* First determine the parameters. We do not use the parameters +- passed to main() since in case nscd is started by running the +- dynamic linker this will not work. Yes, this is not the usual +- case but nscd is part of glibc and we occasionally do this. */ +- size_t buflen = 1024; +- char *buf = alloca (buflen); +- size_t readlen = 0; + int fd = open ("/proc/self/cmdline", O_RDONLY); +- if (fd == -1) +- { +- dbg_log (_("\ +-cannot open /proc/self/cmdline: %s; disabling paranoia mode"), +- strerror (errno)); +- +- paranoia = 0; +- return; ++ if (fd < 0) ++ return NULL; ++ size_t current = 0; ++ size_t limit = 1024; ++ char *buffer = malloc (limit); ++ if (buffer == NULL) ++ { ++ close (fd); ++ errno = ENOMEM; ++ return NULL; + } +- + while (1) + { +- ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen, +- buflen - readlen)); +- if (n == -1) ++ if (current == limit) + { +- dbg_log (_("\ +-cannot read /proc/self/cmdline: %s; disabling paranoia mode"), +- strerror (errno)); ++ char *newptr; ++ if (2 * limit < limit ++ || (newptr = realloc (buffer, 2 * limit)) == NULL) ++ { ++ free (buffer); ++ close (fd); ++ errno = ENOMEM; ++ return NULL; ++ } ++ buffer = newptr; ++ limit *= 2; ++ } + ++ ssize_t n = TEMP_FAILURE_RETRY (read (fd, buffer + current, ++ limit - current)); ++ if (n == -1) ++ { ++ int e = errno; ++ free (buffer); + close (fd); +- paranoia = 0; +- return; ++ errno = e; ++ return NULL; + } +- +- readlen += n; +- +- if (readlen < buflen) ++ if (n == 0) + break; +- +- /* We might have to extend the buffer. */ +- size_t old_buflen = buflen; +- char *newp = extend_alloca (buf, buflen, 2 * buflen); +- buf = memmove (newp, buf, old_buflen); ++ current += n; + } + + close (fd); ++ *size = current; ++ return buffer; ++} ++ ++ ++/* Restart the process. */ ++static void ++restart (void) ++{ ++ /* First determine the parameters. We do not use the parameters ++ passed to main() because then nscd would would use the system ++ libc after restarting even if it was started by a non-system ++ dynamic linker during glibc testing. */ ++ size_t readlen; ++ char *cmdline = read_cmdline (&readlen); ++ if (cmdline == NULL) ++ { ++ dbg_log (_("\ ++cannot open /proc/self/cmdline: %m; disabling paranoia mode")); ++ paranoia = 0; ++ return; ++ } + + /* Parse the command line. Worst case scenario: every two + characters form one parameter (one character plus NUL). */ + char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0])); + int argc = 0; + +- char *cp = buf; +- while (cp < buf + readlen) ++ for (char *cp = cmdline; cp < cmdline + readlen;) + { + argv[argc++] = cp; + cp = (char *) rawmemchr (cp, '\0') + 1; +@@ -1427,6 +1446,7 @@ cannot change to old UID: %s; disabling + strerror (errno)); + + paranoia = 0; ++ free (cmdline); + return; + } + +@@ -1438,6 +1458,7 @@ cannot change to old GID: %s; disabling + + ignore_value (setuid (server_uid)); + paranoia = 0; ++ free (cmdline); + return; + } + } +@@ -1455,6 +1476,7 @@ cannot change to old working directory: + ignore_value (setgid (server_gid)); + } + paranoia = 0; ++ free (cmdline); + return; + } + +@@ -1503,6 +1525,7 @@ cannot change to old working directory: + dbg_log (_("cannot change current working directory to \"/\": %s"), + strerror (errno)); + paranoia = 0; ++ free (cmdline); + + /* Reenable the databases. */ + time_t now = time (NULL); +Index: b/nscd/grpcache.c +=================================================================== +--- a/nscd/grpcache.c ++++ b/nscd/grpcache.c +@@ -16,7 +16,6 @@ + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +-#include + #include + #include + #include +@@ -32,6 +31,7 @@ + #include + #include + #include ++#include + + #include "nscd.h" + #include "dbg_log.h" +@@ -448,12 +448,12 @@ addgrbyX (struct database_dyn *db, int f + look again in the table whether the dataset is now available. We + simply insert it. It does not matter if it is in there twice. The + pruning function only will look at the timestamp. */ +- size_t buflen = 1024; +- char *buffer = (char *) alloca (buflen); ++ + struct group resultbuf; + struct group *grp; +- bool use_malloc = false; + int errval = 0; ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + + if (__glibc_unlikely (debug_level > 0)) + { +@@ -463,43 +463,24 @@ addgrbyX (struct database_dyn *db, int f + dbg_log (_("Reloading \"%s\" in group cache!"), keystr); + } + +- while (lookup (req->type, key, &resultbuf, buffer, buflen, &grp) != 0 ++ while (lookup (req->type, key, &resultbuf, ++ tmpbuf.data, tmpbuf.length, &grp) != 0 + && (errval = errno) == ERANGE) +- { +- errno = 0; +- +- if (__glibc_unlikely (buflen > 32768)) +- { +- char *old_buffer = buffer; +- buflen *= 2; +- buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); +- if (buffer == NULL) +- { +- /* We ran out of memory. We cannot do anything but +- sending a negative response. In reality this should +- never happen. */ +- grp = NULL; +- buffer = old_buffer; +- +- /* We set the error to indicate this is (possibly) a +- temporary error and that it does not mean the entry +- is not available at all. */ +- errval = EAGAIN; +- break; +- } +- use_malloc = true; +- } +- else +- /* Allocate a new buffer on the stack. If possible combine it +- with the previously allocated buffer. */ +- buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); +- } ++ if (!scratch_buffer_grow (&tmpbuf)) ++ { ++ /* We ran out of memory. We cannot do anything but sending a ++ negative response. In reality this should never ++ happen. */ ++ grp = NULL; ++ /* We set the error to indicate this is (possibly) a temporary ++ error and that it does not mean the entry is not available ++ at all. */ ++ errval = EAGAIN; ++ break; ++ } + + time_t timeout = cache_addgr (db, fd, req, keystr, grp, uid, he, dh, errval); +- +- if (use_malloc) +- free (buffer); +- ++ scratch_buffer_free (&tmpbuf); + return timeout; + } + +Index: b/nscd/hstcache.c +=================================================================== +--- a/nscd/hstcache.c ++++ b/nscd/hstcache.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include "nscd.h" + #include "dbg_log.h" +@@ -463,11 +464,8 @@ addhstbyX (struct database_dyn *db, int + look again in the table whether the dataset is now available. We + simply insert it. It does not matter if it is in there twice. The + pruning function only will look at the timestamp. */ +- int buflen = 1024; +- char *buffer = (char *) alloca (buflen); + struct hostent resultbuf; + struct hostent *hst; +- bool use_malloc = false; + int errval = 0; + int32_t ttl = INT32_MAX; + +@@ -487,46 +485,30 @@ addhstbyX (struct database_dyn *db, int + dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str); + } + +- while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst, &ttl) != 0 ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); ++ ++ while (lookup (req->type, key, &resultbuf, ++ tmpbuf.data, tmpbuf.length, &hst, &ttl) != 0 + && h_errno == NETDB_INTERNAL + && (errval = errno) == ERANGE) +- { +- errno = 0; +- +- if (__glibc_unlikely (buflen > 32768)) +- { +- char *old_buffer = buffer; +- buflen *= 2; +- buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); +- if (buffer == NULL) +- { +- /* We ran out of memory. We cannot do anything but +- sending a negative response. In reality this should +- never happen. */ +- hst = NULL; +- buffer = old_buffer; +- +- /* We set the error to indicate this is (possibly) a +- temporary error and that it does not mean the entry +- is not available at all. */ +- h_errno = TRY_AGAIN; +- errval = EAGAIN; +- break; +- } +- use_malloc = true; +- } +- else +- /* Allocate a new buffer on the stack. If possible combine it +- with the previously allocated buffer. */ +- buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); +- } ++ if (!scratch_buffer_grow (&tmpbuf)) ++ { ++ /* We ran out of memory. We cannot do anything but sending a ++ negative response. In reality this should never ++ happen. */ ++ hst = NULL; ++ /* We set the error to indicate this is (possibly) a temporary ++ error and that it does not mean the entry is not ++ available at all. */ ++ h_errno = TRY_AGAIN; ++ errval = EAGAIN; ++ break; ++ } + + time_t timeout = cache_addhst (db, fd, req, key, hst, uid, he, dh, + h_errno == TRY_AGAIN ? errval : 0, ttl); +- +- if (use_malloc) +- free (buffer); +- ++ scratch_buffer_free (&tmpbuf); + return timeout; + } + +Index: b/nscd/pwdcache.c +=================================================================== +--- a/nscd/pwdcache.c ++++ b/nscd/pwdcache.c +@@ -16,7 +16,6 @@ + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +-#include + #include + #include + #include +@@ -32,6 +31,7 @@ + #include + #include + #include ++#include + + #include "nscd.h" + #include "dbg_log.h" +@@ -426,12 +426,11 @@ addpwbyX (struct database_dyn *db, int f + look again in the table whether the dataset is now available. We + simply insert it. It does not matter if it is in there twice. The + pruning function only will look at the timestamp. */ +- size_t buflen = 1024; +- char *buffer = (char *) alloca (buflen); + struct passwd resultbuf; + struct passwd *pwd; +- bool use_malloc = false; + int errval = 0; ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + + if (__glibc_unlikely (debug_level > 0)) + { +@@ -441,45 +440,26 @@ addpwbyX (struct database_dyn *db, int f + dbg_log (_("Reloading \"%s\" in password cache!"), keystr); + } + +- while (lookup (req->type, key, &resultbuf, buffer, buflen, &pwd) != 0 ++ while (lookup (req->type, key, &resultbuf, ++ tmpbuf.data, tmpbuf.length, &pwd) != 0 + && (errval = errno) == ERANGE) +- { +- errno = 0; +- +- if (__glibc_unlikely (buflen > 32768)) +- { +- char *old_buffer = buffer; +- buflen *= 2; +- buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); +- if (buffer == NULL) +- { +- /* We ran out of memory. We cannot do anything but +- sending a negative response. In reality this should +- never happen. */ +- pwd = NULL; +- buffer = old_buffer; +- +- /* We set the error to indicate this is (possibly) a +- temporary error and that it does not mean the entry +- is not available at all. */ +- errval = EAGAIN; +- break; +- } +- use_malloc = true; +- } +- else +- /* Allocate a new buffer on the stack. If possible combine it +- with the previously allocated buffer. */ +- buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); +- } ++ if (!scratch_buffer_grow (&tmpbuf)) ++ { ++ /* We ran out of memory. We cannot do anything but sending a ++ negative response. In reality this should never ++ happen. */ ++ pwd = NULL; ++ /* We set the error to indicate this is (possibly) a temporary ++ error and that it does not mean the entry is not available ++ at all. */ ++ errval = EAGAIN; ++ break; ++ } + + /* Add the entry to the cache. */ + time_t timeout = cache_addpw (db, fd, req, keystr, pwd, c_uid, he, dh, + errval); +- +- if (use_malloc) +- free (buffer); +- ++ scratch_buffer_free (&tmpbuf); + return timeout; + } + +Index: b/nscd/servicescache.c +=================================================================== +--- a/nscd/servicescache.c ++++ b/nscd/servicescache.c +@@ -16,7 +16,6 @@ + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +-#include + #include + #include + #include +@@ -25,6 +24,7 @@ + #include + #include + #include ++#include + + #include "nscd.h" + #include "dbg_log.h" +@@ -374,12 +374,11 @@ addservbyX (struct database_dyn *db, int + look again in the table whether the dataset is now available. We + simply insert it. It does not matter if it is in there twice. The + pruning function only will look at the timestamp. */ +- size_t buflen = 1024; +- char *buffer = (char *) alloca (buflen); + struct servent resultbuf; + struct servent *serv; +- bool use_malloc = false; + int errval = 0; ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + + if (__glibc_unlikely (debug_level > 0)) + { +@@ -389,43 +388,24 @@ addservbyX (struct database_dyn *db, int + dbg_log (_("Reloading \"%s\" in services cache!"), key); + } + +- while (lookup (req->type, key, &resultbuf, buffer, buflen, &serv) != 0 ++ while (lookup (req->type, key, &resultbuf, ++ tmpbuf.data, tmpbuf.length, &serv) != 0 + && (errval = errno) == ERANGE) +- { +- errno = 0; +- +- if (__glibc_unlikely (buflen > 32768)) +- { +- char *old_buffer = buffer; +- buflen *= 2; +- buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); +- if (buffer == NULL) +- { +- /* We ran out of memory. We cannot do anything but +- sending a negative response. In reality this should +- never happen. */ +- serv = NULL; +- buffer = old_buffer; +- +- /* We set the error to indicate this is (possibly) a +- temporary error and that it does not mean the entry +- is not available at all. */ +- errval = EAGAIN; +- break; +- } +- use_malloc = true; +- } +- else +- /* Allocate a new buffer on the stack. If possible combine it +- with the previously allocated buffer. */ +- buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); +- } ++ if (!scratch_buffer_grow (&tmpbuf)) ++ { ++ /* We ran out of memory. We cannot do anything but sending a ++ negative response. In reality this should never ++ happen. */ ++ serv = NULL; ++ /* We set the error to indicate this is (possibly) a temporary ++ error and that it does not mean the entry is not available ++ at all. */ ++ errval = EAGAIN; ++ break; ++ } + + time_t timeout = cache_addserv (db, fd, req, key, serv, uid, he, dh, errval); +- +- if (use_malloc) +- free (buffer); +- ++ scratch_buffer_free (&tmpbuf); + return timeout; + } + +Index: b/nss/getent.c +=================================================================== +--- a/nss/getent.c ++++ b/nss/getent.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + /* Get libc version number. */ + #include +@@ -477,30 +478,34 @@ netgroup_keys (int number, char *key[]) + static int + initgroups_keys (int number, char *key[]) + { +- int ngrps = 100; +- size_t grpslen = ngrps * sizeof (gid_t); +- gid_t *grps = alloca (grpslen); +- + if (number == 0) + { + fprintf (stderr, _("Enumeration not supported on %s\n"), "initgroups"); + return 3; + } + ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); ++ + for (int i = 0; i < number; ++i) + { ++ ssize_t ngrps = tmpbuf.length / sizeof (gid_t); + int no = ngrps; + int n; +- while ((n = getgrouplist (key[i], -1, grps, &no)) == -1 ++ while ((n = getgrouplist (key[i], -1, tmpbuf.data, &no)) == -1 + && no > ngrps) + { +- grps = extend_alloca (grps, grpslen, no * sizeof (gid_t)); +- ngrps = no; ++ if (!scratch_buffer_set_array_size (&tmpbuf, no, sizeof (gid_t))) ++ { ++ fprintf (stderr, _("Could not allocate group list: %m\n")); ++ return 3; ++ } + } + + if (n == -1) + return 1; + ++ const gid_t *grps = tmpbuf.data; + printf ("%-21s", key[i]); + for (int j = 0; j < n; ++j) + if (grps[j] != -1) +@@ -508,6 +513,8 @@ initgroups_keys (int number, char *key[] + putchar_unlocked ('\n'); + } + ++ scratch_buffer_free (&tmpbuf); ++ + return 0; + } + +Index: b/nss/nss_files/files-hosts.c +=================================================================== +--- a/nss/nss_files/files-hosts.c ++++ b/nss/nss_files/files-hosts.c +@@ -22,7 +22,7 @@ + #include + #include + #include +- ++#include + + /* Get implementation for some internal functions. */ + #include "../resolv/mapv4v6addr.h" +@@ -145,15 +145,12 @@ _nss_files_gethostbyname3_r (const char + && _res_hconf.flags & HCONF_FLAG_MULTI) + { + /* We have to get all host entries from the file. */ +- size_t tmp_buflen = MIN (buflen, 4096); +- char tmp_buffer_stack[tmp_buflen] +- __attribute__ ((__aligned__ (__alignof__ (struct hostent_data)))); +- char *tmp_buffer = tmp_buffer_stack; + struct hostent tmp_result_buf; + int naddrs = 1; + int naliases = 0; + char *bufferend; +- bool tmp_buffer_malloced = false; ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + + while (result->h_aliases[naliases] != NULL) + ++naliases; +@@ -161,9 +158,9 @@ _nss_files_gethostbyname3_r (const char + bufferend = (char *) &result->h_aliases[naliases + 1]; + + again: +- while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer, +- tmp_buflen, errnop, herrnop, af, +- flags)) ++ while ((status = internal_getent (stream, &tmp_result_buf, ++ tmpbuf.data, tmpbuf.length, ++ errnop, herrnop, af, flags)) + == NSS_STATUS_SUCCESS) + { + int matches = 1; +@@ -287,54 +284,13 @@ _nss_files_gethostbyname3_r (const char + } + } + +- if (status == NSS_STATUS_TRYAGAIN) +- { +- size_t newsize = 2 * tmp_buflen; +- if (tmp_buffer_malloced) +- { +- char *newp = realloc (tmp_buffer, newsize); +- if (newp != NULL) +- { +- assert ((((uintptr_t) newp) +- & (__alignof__ (struct hostent_data) - 1)) +- == 0); +- tmp_buffer = newp; +- tmp_buflen = newsize; +- goto again; +- } +- } +- else if (!__libc_use_alloca (buflen + newsize)) +- { +- tmp_buffer = malloc (newsize); +- if (tmp_buffer != NULL) +- { +- assert ((((uintptr_t) tmp_buffer) +- & (__alignof__ (struct hostent_data) - 1)) +- == 0); +- tmp_buffer_malloced = true; +- tmp_buflen = newsize; +- goto again; +- } +- } +- else +- { +- tmp_buffer +- = extend_alloca (tmp_buffer, tmp_buflen, +- newsize +- + __alignof__ (struct hostent_data)); +- tmp_buffer = (char *) (((uintptr_t) tmp_buffer +- + __alignof__ (struct hostent_data) +- - 1) +- & ~(__alignof__ (struct hostent_data) +- - 1)); +- goto again; +- } +- } ++ if (status == NSS_STATUS_TRYAGAIN ++ && scratch_buffer_grow (&tmpbuf)) ++ goto again; + else + status = NSS_STATUS_SUCCESS; + out: +- if (tmp_buffer_malloced) +- free (tmp_buffer); ++ scratch_buffer_free (&tmpbuf); + } + + internal_endent (&stream); +Index: b/nss/nss_files/files-initgroups.c +=================================================================== +--- a/nss/nss_files/files-initgroups.c ++++ b/nss/nss_files/files-initgroups.c +@@ -16,7 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-#include + #include + #include + #include +@@ -25,6 +24,7 @@ + #include + #include + #include ++#include + + enum nss_status + _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, +@@ -46,9 +46,8 @@ _nss_files_initgroups_dyn (const char *u + enum nss_status status = NSS_STATUS_SUCCESS; + bool any = false; + +- size_t buflen = 1024; +- void *buffer = alloca (buflen); +- bool buffer_use_malloc = false; ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + + gid_t *groups = *groupsp; + +@@ -67,26 +66,16 @@ _nss_files_initgroups_dyn (const char *u + } + + struct group grp; +- int res = _nss_files_parse_grent (line, &grp, buffer, buflen, errnop); ++ int res = _nss_files_parse_grent (line, &grp, ++ tmpbuf.data, tmpbuf.length, errnop); + if (res == -1) + { +- size_t newbuflen = 2 * buflen; +- if (buffer_use_malloc || ! __libc_use_alloca (buflen + newbuflen)) ++ if (!scratch_buffer_grow (&tmpbuf)) + { +- void *newbuf = realloc (buffer_use_malloc ? buffer : NULL, +- newbuflen); +- if (newbuf == NULL) +- { +- *errnop = ENOMEM; +- status = NSS_STATUS_TRYAGAIN; +- goto out; +- } +- buffer = newbuf; +- buflen = newbuflen; +- buffer_use_malloc = true; ++ *errnop = ENOMEM; ++ status = NSS_STATUS_TRYAGAIN; ++ goto out; + } +- else +- buffer = extend_alloca (buffer, buflen, newbuflen); + /* Reread current line, the parser has clobbered it. */ + fsetpos (stream, &pos); + continue; +@@ -132,8 +121,7 @@ _nss_files_initgroups_dyn (const char *u + + out: + /* Free memory. */ +- if (buffer_use_malloc) +- free (buffer); ++ scratch_buffer_free (&tmpbuf); + free (line); + + fclose (stream); +Index: b/posix/glob.c +=================================================================== +--- a/posix/glob.c ++++ b/posix/glob.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + /* Outcomment the following line for production quality code. */ + /* #define NDEBUG 1 */ +@@ -293,7 +294,7 @@ glob (const char *pattern, int flags, in + glob_t dirs; + int retval = 0; + #ifdef _LIBC +- size_t alloca_used = 0; ++ size_t alloca_used = sizeof (struct scratch_buffer); + #endif + + if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) +@@ -650,33 +651,13 @@ glob (const char *pattern, int flags, in + { + struct passwd *p; + # if defined HAVE_GETPWNAM_R || defined _LIBC +- long int pwbuflen = GETPW_R_SIZE_MAX (); +- char *pwtmpbuf; + struct passwd pwbuf; +- int malloc_pwtmpbuf = 0; + int save = errno; ++ struct scratch_buffer pwtmpbuf; ++ scratch_buffer_init (&pwtmpbuf); + +-# ifndef _LIBC +- if (pwbuflen == -1) +- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. +- Try a moderate value. */ +- pwbuflen = 1024; +-# endif +- if (__libc_use_alloca (alloca_used + pwbuflen)) +- pwtmpbuf = alloca_account (pwbuflen, alloca_used); +- else +- { +- pwtmpbuf = malloc (pwbuflen); +- if (pwtmpbuf == NULL) +- { +- retval = GLOB_NOSPACE; +- goto out; +- } +- malloc_pwtmpbuf = 1; +- } +- +- while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) +- != 0) ++ while (getpwnam_r (name, &pwbuf, ++ pwtmpbuf.data, pwtmpbuf.length, &p) != 0) + { + if (errno != ERANGE) + { +@@ -684,67 +665,37 @@ glob (const char *pattern, int flags, in + break; + } + +- if (!malloc_pwtmpbuf +- && __libc_use_alloca (alloca_used +- + 2 * pwbuflen)) +- pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen, +- 2 * pwbuflen, +- alloca_used); +- else ++ if (!scratch_buffer_grow (&pwtmpbuf)) + { +- char *newp = realloc (malloc_pwtmpbuf +- ? pwtmpbuf : NULL, +- 2 * pwbuflen); +- if (newp == NULL) +- { +- if (__glibc_unlikely (malloc_pwtmpbuf)) +- free (pwtmpbuf); +- retval = GLOB_NOSPACE; +- goto out; +- } +- pwtmpbuf = newp; +- pwbuflen = 2 * pwbuflen; +- malloc_pwtmpbuf = 1; ++ retval = GLOB_NOSPACE; ++ goto out; + } + __set_errno (save); + } + # else +- p = getpwnam (name); ++ p = getpwnam (namebuf.data); + # endif + if (p != NULL) + { +- if (!malloc_pwtmpbuf) +- home_dir = p->pw_dir; +- else ++ home_dir = strdup (p->pw_dir); ++ malloc_home_dir = 1; ++ if (home_dir == NULL) + { +- size_t home_dir_len = strlen (p->pw_dir) + 1; +- if (__libc_use_alloca (alloca_used + home_dir_len)) +- home_dir = alloca_account (home_dir_len, +- alloca_used); +- else +- { +- home_dir = malloc (home_dir_len); +- if (home_dir == NULL) +- { +- free (pwtmpbuf); +- retval = GLOB_NOSPACE; +- goto out; +- } +- malloc_home_dir = 1; +- } +- memcpy (home_dir, p->pw_dir, home_dir_len); +- +- free (pwtmpbuf); ++ scratch_buffer_free (&pwtmpbuf); ++ retval = GLOB_NOSPACE; ++ goto out; + } + } ++ scratch_buffer_free (&pwtmpbuf); + } + } + if (home_dir == NULL || home_dir[0] == '\0') + { ++ if (malloc_home_dir) ++ free (home_dir); ++ malloc_home_dir = 0; + if (flags & GLOB_TILDE_CHECK) + { +- if (__glibc_unlikely (malloc_home_dir)) +- free (home_dir); + retval = GLOB_NOMATCH; + goto out; + } +@@ -865,57 +816,24 @@ glob (const char *pattern, int flags, in + { + struct passwd *p; + # if defined HAVE_GETPWNAM_R || defined _LIBC +- long int buflen = GETPW_R_SIZE_MAX (); +- char *pwtmpbuf; +- int malloc_pwtmpbuf = 0; + struct passwd pwbuf; + int save = errno; ++ struct scratch_buffer pwtmpbuf; ++ scratch_buffer_init (&pwtmpbuf); + +-# ifndef _LIBC +- if (buflen == -1) +- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a +- moderate value. */ +- buflen = 1024; +-# endif +- if (__libc_use_alloca (alloca_used + buflen)) +- pwtmpbuf = alloca_account (buflen, alloca_used); +- else +- { +- pwtmpbuf = malloc (buflen); +- if (pwtmpbuf == NULL) +- { +- nomem_getpw: +- if (__glibc_unlikely (malloc_user_name)) +- free (user_name); +- retval = GLOB_NOSPACE; +- goto out; +- } +- malloc_pwtmpbuf = 1; +- } +- +- while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) ++ while (getpwnam_r (user_name, &pwbuf, ++ pwtmpbuf.data, pwtmpbuf.length, &p) != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } +- if (!malloc_pwtmpbuf +- && __libc_use_alloca (alloca_used + 2 * buflen)) +- pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen, +- 2 * buflen, alloca_used); +- else ++ ++ if (!scratch_buffer_grow (&pwtmpbuf)) + { +- char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL, +- 2 * buflen); +- if (newp == NULL) +- { +- if (__glibc_unlikely (malloc_pwtmpbuf)) +- free (pwtmpbuf); +- goto nomem_getpw; +- } +- pwtmpbuf = newp; +- malloc_pwtmpbuf = 1; ++ retval = GLOB_NOSPACE; ++ goto out; + } + __set_errno (save); + } +@@ -944,8 +862,7 @@ glob (const char *pattern, int flags, in + dirname = malloc (home_len + rest_len + 1); + if (dirname == NULL) + { +- if (__glibc_unlikely (malloc_pwtmpbuf)) +- free (pwtmpbuf); ++ scratch_buffer_free (&pwtmpbuf); + retval = GLOB_NOSPACE; + goto out; + } +@@ -957,13 +874,11 @@ glob (const char *pattern, int flags, in + dirlen = home_len + rest_len; + dirname_modified = 1; + +- if (__glibc_unlikely (malloc_pwtmpbuf)) +- free (pwtmpbuf); ++ scratch_buffer_free (&pwtmpbuf); + } + else + { +- if (__glibc_unlikely (malloc_pwtmpbuf)) +- free (pwtmpbuf); ++ scratch_buffer_free (&pwtmpbuf); + + if (flags & GLOB_TILDE_CHECK) + /* We have to regard it as an error if we cannot find the +Index: b/posix/wordexp.c +=================================================================== +--- a/posix/wordexp.c ++++ b/posix/wordexp.c +@@ -17,7 +17,6 @@ + License along with the GNU C Library; if not, see + . */ + +-#include + #include + #include + #include +@@ -41,6 +40,7 @@ + #include + #include + #include ++#include + + #include + #include <_itoa.h> +@@ -308,12 +308,7 @@ parse_tilde (char **word, size_t *word_l + if (i == 1 + *offset) + { + /* Tilde appears on its own */ +- uid_t uid; +- struct passwd pwd, *tpwd; +- int buflen = 1000; + char* home; +- char* buffer; +- int result; + + /* POSIX.2 says ~ expands to $HOME and if HOME is unset the + results are unspecified. We do a lookup on the uid if +@@ -328,25 +323,38 @@ parse_tilde (char **word, size_t *word_l + } + else + { +- uid = __getuid (); +- buffer = __alloca (buflen); +- +- while ((result = __getpwuid_r (uid, &pwd, buffer, buflen, &tpwd)) != 0 ++ struct passwd pwd, *tpwd; ++ uid_t uid = __getuid (); ++ int result; ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); ++ ++ while ((result = __getpwuid_r (uid, &pwd, ++ tmpbuf.data, tmpbuf.length, ++ &tpwd)) != 0 + && errno == ERANGE) +- buffer = extend_alloca (buffer, buflen, buflen + 1000); ++ if (!scratch_buffer_grow (&tmpbuf)) ++ return WRDE_NOSPACE; + + if (result == 0 && tpwd != NULL && pwd.pw_dir != NULL) + { + *word = w_addstr (*word, word_length, max_length, pwd.pw_dir); + if (*word == NULL) +- return WRDE_NOSPACE; ++ { ++ scratch_buffer_free (&tmpbuf); ++ return WRDE_NOSPACE; ++ } + } + else + { + *word = w_addchar (*word, word_length, max_length, '~'); + if (*word == NULL) +- return WRDE_NOSPACE; ++ { ++ scratch_buffer_free (&tmpbuf); ++ return WRDE_NOSPACE; ++ } + } ++ scratch_buffer_free (&tmpbuf); + } + } + else +@@ -354,13 +362,15 @@ parse_tilde (char **word, size_t *word_l + /* Look up user name in database to get home directory */ + char *user = strndupa (&words[1 + *offset], i - (1 + *offset)); + struct passwd pwd, *tpwd; +- int buflen = 1000; +- char* buffer = __alloca (buflen); + int result; ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + +- while ((result = __getpwnam_r (user, &pwd, buffer, buflen, &tpwd)) != 0 ++ while ((result = __getpwnam_r (user, &pwd, tmpbuf.data, tmpbuf.length, ++ &tpwd)) != 0 + && errno == ERANGE) +- buffer = extend_alloca (buffer, buflen, buflen + 1000); ++ if (!scratch_buffer_grow (&tmpbuf)) ++ return WRDE_NOSPACE; + + if (result == 0 && tpwd != NULL && pwd.pw_dir) + *word = w_addstr (*word, word_length, max_length, pwd.pw_dir); +@@ -372,6 +382,8 @@ parse_tilde (char **word, size_t *word_l + *word = w_addstr (*word, word_length, max_length, user); + } + ++ scratch_buffer_free (&tmpbuf); ++ + *offset = i - 1; + } + return *word ? 0 : WRDE_NOSPACE; +Index: b/sysdeps/unix/sysv/linux/gethostid.c +=================================================================== +--- a/sysdeps/unix/sysv/linux/gethostid.c ++++ b/sysdeps/unix/sysv/linux/gethostid.c +@@ -63,13 +63,12 @@ sethostid (long int id) + # include + # include + # include ++# include + + long int + gethostid (void) + { + char hostname[MAXHOSTNAMELEN + 1]; +- size_t buflen; +- char *buffer; + struct hostent hostbuf, *hp; + int32_t id; + struct in_addr in; +@@ -94,23 +93,26 @@ gethostid (void) + /* This also fails. Return and arbitrary value. */ + return 0; + +- buflen = 1024; +- buffer = __alloca (buflen); ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + + /* To get the IP address we need to know the host name. */ +- while (__gethostbyname_r (hostname, &hostbuf, buffer, buflen, &hp, &herr) +- != 0 ++ while (__gethostbyname_r (hostname, &hostbuf, ++ tmpbuf.data, tmpbuf.length, &hp, &herr) != 0 + || hp == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) +- return 0; ++ { ++ scratch_buffer_free (&tmpbuf); ++ return 0; ++ } + else +- /* Enlarge buffer. */ +- buffer = extend_alloca (buffer, buflen, 2 * buflen); ++ if (!scratch_buffer_grow (&tmpbuf)) ++ return 0; + + in.s_addr = 0; + memcpy (&in, hp->h_addr, + (int) sizeof (in) < hp->h_length ? (int) sizeof (in) : hp->h_length); +- ++ scratch_buffer_free (&tmpbuf); + /* For the return value to be not exactly the IP address we do some + bit fiddling. */ + return (int32_t) (in.s_addr << 16 | in.s_addr >> 16); +Index: b/sysdeps/unix/sysv/linux/getlogin_r.c +=================================================================== +--- a/sysdeps/unix/sysv/linux/getlogin_r.c ++++ b/sysdeps/unix/sysv/linux/getlogin_r.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #define STATIC static + static int getlogin_r_fd0 (char *name, size_t namesize); +@@ -54,28 +55,19 @@ __getlogin_r_loginuid (char *name, size_ + endp == uidbuf || *endp != '\0')) + return -1; + +- size_t buflen = 1024; +- char *buf = alloca (buflen); +- bool use_malloc = false; + struct passwd pwd; + struct passwd *tpwd; + int result = 0; + int res; ++ struct scratch_buffer tmpbuf; ++ scratch_buffer_init (&tmpbuf); + +- while ((res = __getpwuid_r (uid, &pwd, buf, buflen, &tpwd)) == ERANGE) +- if (__libc_use_alloca (2 * buflen)) +- buf = extend_alloca (buf, buflen, 2 * buflen); +- else ++ while ((res = __getpwuid_r (uid, &pwd, ++ tmpbuf.data, tmpbuf.length, &tpwd)) == ERANGE) ++ if (!scratch_buffer_grow (&tmpbuf)) + { +- buflen *= 2; +- char *newp = realloc (use_malloc ? buf : NULL, buflen); +- if (newp == NULL) +- { +- result = ENOMEM; +- goto out; +- } +- buf = newp; +- use_malloc = true; ++ result = ENOMEM; ++ goto out; + } + + if (res != 0 || tpwd == NULL) +@@ -95,9 +87,7 @@ __getlogin_r_loginuid (char *name, size_ + memcpy (name, pwd.pw_name, needed); + + out: +- if (use_malloc) +- free (buf); +- ++ scratch_buffer_free (&tmpbuf); + return result; + } + diff --git a/glibc-rh1335011.patch b/glibc-rh1335011.patch new file mode 100644 index 0000000..8738f9a --- /dev/null +++ b/glibc-rh1335011.patch @@ -0,0 +1,176 @@ +Revert these two upstream commits, to unbreak ASAN: + +commit e91bd7465816f474617dcb4bbfe72f3594c5783c +Author: Adhemerval Zanella +Date: Thu Mar 31 10:51:51 2016 -0300 + + Fix tst-dlsym-error build + + This patch fixes the new test tst-dlsym-error build on aarch64 + (and possible other architectures as well) due missing strchrnul + definition. + + * elf/tst-dlsym-error.c: Include for strchrnul. + +commit 7d45c163d00c88d5875a112343c4ea3e61349e6b +Author: Florian Weimer +Date: Thu Mar 31 11:26:55 2016 +0200 + + Report dlsym, dlvsym lookup errors using dlerror [BZ #19509] + + * elf/dl-lookup.c (_dl_lookup_symbol_x): Report error even if + skip_map != NULL. + * elf/tst-dlsym-error.c: New file. + * elf/Makefile (tests): Add tst-dlsym-error. + (tst-dlsym-error): Link against libdl. + +Index: b/elf/Makefile +=================================================================== +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -149,7 +149,7 @@ tests += loadtest restest1 preloadtest l + tst-nodelete) \ + tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ + tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ +- tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error ++ tst-nodelete2 tst-audit11 tst-audit12 + # reldep9 + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout +@@ -1258,5 +1258,3 @@ $(objpfx)tst-prelink-cmp.out: tst-prelin + $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig + $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' '$(test-wrapper-env)' > $@; \ + $(evaluate-test) +- +-$(objpfx)tst-dlsym-error: $(libdl) +Index: b/elf/dl-lookup.c +=================================================================== +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -858,6 +858,7 @@ _dl_lookup_symbol_x (const char *undef_n + if (__glibc_unlikely (current_value.s == NULL)) + { + if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) ++ && skip_map == NULL + && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)) + { + /* We could find no value for a strong reference. */ +Index: b/elf/tst-dlsym-error.c +=================================================================== +--- a/elf/tst-dlsym-error.c ++++ /dev/null +@@ -1,114 +0,0 @@ +-/* Test error reporting for dlsym, dlvsym failures. +- Copyright (C) 2016 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +-#include +- +-/* Used to disambiguate symbol names. */ +-static int counter; +- +-static void +-test_one (void *handle, const char *name, void *(func) (void *, const char *), +- const char *suffix) +-{ +- ++counter; +- char symbol[32]; +- snprintf (symbol, sizeof (symbol), "no_such_symbol_%d", counter); +- char *expected_message; +- if (asprintf (&expected_message, ": undefined symbol: %s%s", +- symbol, suffix) < 0) +- { +- printf ("error: asprintf: %m\n"); +- abort (); +- } +- +- void *addr = func (handle, symbol); +- if (addr != NULL) +- { +- printf ("error: %s: found symbol \"no_such_symbol\"\n", name); +- abort (); +- } +- const char *message = dlerror (); +- if (message == NULL) +- { +- printf ("error: %s: missing error message\n", name); +- abort (); +- } +- const char *message_without_path = strchrnul (message, ':'); +- if (strcmp (message_without_path, expected_message) != 0) +- { +- printf ("error: %s: unexpected error message: %s\n", name, message); +- abort (); +- } +- free (expected_message); +- +- message = dlerror (); +- if (message != NULL) +- { +- printf ("error: %s: unexpected error message: %s\n", name, message); +- abort (); +- } +-} +- +-static void +-test_handles (const char *name, void *(func) (void *, const char *), +- const char *suffix) +-{ +- test_one (RTLD_DEFAULT, name, func, suffix); +- test_one (RTLD_NEXT, name, func, suffix); +- +- void *handle = dlopen (LIBC_SO, RTLD_LAZY); +- if (handle == NULL) +- { +- printf ("error: cannot dlopen %s: %s\n", LIBC_SO, dlerror ()); +- abort (); +- } +- test_one (handle, name, func, suffix); +- dlclose (handle); +-} +- +-static void * +-dlvsym_no_such_version (void *handle, const char *name) +-{ +- return dlvsym (handle, name, "NO_SUCH_VERSION"); +-} +- +-static void * +-dlvsym_glibc_private (void *handle, const char *name) +-{ +- return dlvsym (handle, name, "GLIBC_PRIVATE"); +-} +- +-static int +-do_test (void) +-{ +- test_handles ("dlsym", dlsym, ""); +- test_handles ("dlvsym", dlvsym_no_such_version, +- ", version NO_SUCH_VERSION"); +- test_handles ("dlvsym", dlvsym_glibc_private, +- ", version GLIBC_PRIVATE"); +- +- return 0; +-} +- +- +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" diff --git a/glibc-rtkaio-clock.patch b/glibc-rtkaio-clock.patch new file mode 100644 index 0000000..4aff826 --- /dev/null +++ b/glibc-rtkaio-clock.patch @@ -0,0 +1,102 @@ +# +# Based on the following upstream commit: +# +# commit 6e6249d0b461b952d0f544792372663feb6d792a +# Author: Roland McGrath +# Date: Wed Oct 24 14:50:46 2012 -0700 +# +# BZ#14743: Move clock_* symbols from librt to libc. +# +# We remove the clock* functions from librtkaio.so.1 and +# use those provided in libc.so.6, matching librt.so. +# +--- glibc-2.21-63-gebf27d1.mod/rtkaio/clock-compat.c 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.21-63-gebf27d1/rtkaio/clock-compat.c 2015-02-12 01:28:59.615026597 -0500 +@@ -0,0 +1,2 @@ ++#define librt librtkaio ++#include +diff -urN glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_getcpuclockid.c glibc-2.21-59-gd35273f/rtkaio/kaio_clock_getcpuclockid.c +--- glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_getcpuclockid.c 2015-02-11 13:00:55.105400863 -0500 ++++ glibc-2.21-59-gd35273f/rtkaio/kaio_clock_getcpuclockid.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1 +0,0 @@ +-#include +diff -urN glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_getres.c glibc-2.21-59-gd35273f/rtkaio/kaio_clock_getres.c +--- glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_getres.c 2015-02-11 13:00:55.105400863 -0500 ++++ glibc-2.21-59-gd35273f/rtkaio/kaio_clock_getres.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1 +0,0 @@ +-#include +diff -urN glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_gettime.c glibc-2.21-59-gd35273f/rtkaio/kaio_clock_gettime.c +--- glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_gettime.c 2015-02-11 13:00:55.109400738 -0500 ++++ glibc-2.21-59-gd35273f/rtkaio/kaio_clock_gettime.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1 +0,0 @@ +-#include +diff -urN glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_nanosleep.c glibc-2.21-59-gd35273f/rtkaio/kaio_clock_nanosleep.c +--- glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_nanosleep.c 2015-02-11 13:00:55.115400552 -0500 ++++ glibc-2.21-59-gd35273f/rtkaio/kaio_clock_nanosleep.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1 +0,0 @@ +-#include +diff -urN glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_settime.c glibc-2.21-59-gd35273f/rtkaio/kaio_clock_settime.c +--- glibc-2.21-59-gd35273f.mod/rtkaio/kaio_clock_settime.c 2015-02-11 13:00:55.110400708 -0500 ++++ glibc-2.21-59-gd35273f/rtkaio/kaio_clock_settime.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1 +0,0 @@ +-#include +diff -urN glibc-2.21-59-gd35273f.mod/rtkaio/kaio_get_clockfreq.c glibc-2.21-59-gd35273f/rtkaio/kaio_get_clockfreq.c +--- glibc-2.21-59-gd35273f.mod/rtkaio/kaio_get_clockfreq.c 2015-02-11 13:00:55.118400459 -0500 ++++ glibc-2.21-59-gd35273f/rtkaio/kaio_get_clockfreq.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1 +0,0 @@ +-#include +diff -urN glibc-2.21-59-gd35273f.mod/rtkaio/Makefile glibc-2.21-59-gd35273f/rtkaio/Makefile +--- glibc-2.21-59-gd35273f.mod/rtkaio/Makefile 2015-02-11 13:00:55.107400801 -0500 ++++ glibc-2.21-59-gd35273f/rtkaio/Makefile 2015-02-11 22:46:46.930374298 -0500 +@@ -25,9 +25,6 @@ + aio_read64 aio_return aio_suspend aio_write \ + aio_write64 lio_listio lio_listio64 aio_sigqueue \ + aio_notify +-clock-routines := get_clockfreq clock_getcpuclockid \ +- clock_getres clock_gettime clock_settime \ +- clock_nanosleep + timer-routines := timer_create timer_delete timer_getoverr \ + timer_gettime timer_settime + shm-routines := shm_open shm_unlink +@@ -36,8 +33,9 @@ + mq_timedreceive + + librtkaio-routines = $(patsubst %,k%,$(aio-routines)) \ +- $(patsubst %,kaio_%,$(clock-routines) $(timer-routines) \ +- $(shm-routines) $(mq-routines)) ++ $(patsubst %,kaio_%,$(timer-routines) \ ++ $(shm-routines) $(mq-routines)) \ ++ clock-compat + + tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \ + tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \ +@@ -64,7 +62,6 @@ + include $(..)Rules + + CFLAGS-kaio_suspend.c = -fexceptions +-CFLAGS-kaio_clock_nanosleep.c = -fexceptions -fasynchronous-unwind-tables + CFLAGS-kaio_librt-cancellation.c = -fasynchronous-unwind-tables + + LDFLAGS-rtkaio.so = -Wl,-soname=lib$(libprefix)rt.so$(librt.so-version) \ +@@ -88,9 +85,6 @@ + else + $(addprefix $(objpfx),$(tests)): $(objpfx)librtkaio.a $(static-thread-library) + endif +-ifeq (yes,$(build-bounded)) +-$(tests:%=$(objpfx)%-bp): $(objpfx)librtkaio_b.a $(bounded-thread-library) +-endif + + tst-mqueue7-ARGS = -- $(built-program-file) + +diff -urN glibc-2.21-59-gd35273f.mod/rtkaio/Versions glibc-2.21-59-gd35273f/rtkaio/Versions +--- glibc-2.21-59-gd35273f.mod/rtkaio/Versions 2015-02-11 13:00:55.118400459 -0500 ++++ glibc-2.21-59-gd35273f/rtkaio/Versions 2015-02-11 22:36:11.974051389 -0500 +@@ -6,7 +6,7 @@ + aio_suspend64; aio_write; aio_write64; lio_listio; lio_listio64; + } + GLIBC_2.2 { +- # c* ++ # These have moved to libc and are still here only for compatibility. + clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; + clock_nanosleep; + diff --git a/glibc-rtkaio-libof.patch b/glibc-rtkaio-libof.patch new file mode 100644 index 0000000..3db525e --- /dev/null +++ b/glibc-rtkaio-libof.patch @@ -0,0 +1,26 @@ +diff -pruN glibc-2.21-649-gae5eae7/rtkaio/Makefile glibc-2.21-649-gae5eae7.new/rtkaio/Makefile +--- glibc-2.21-649-gae5eae7/rtkaio/Makefile 2015-07-27 22:57:05.742601066 +0530 ++++ glibc-2.21-649-gae5eae7.new/rtkaio/Makefile 2015-07-27 23:33:09.892874337 +0530 +@@ -66,7 +66,9 @@ CFLAGS-kaio_librt-cancellation.c = -fasy + + LDFLAGS-rtkaio.so = -Wl,-soname=lib$(libprefix)rt.so$(librt.so-version) \ + -Wl,--enable-new-dtags,-z,nodelete +-CPPFLAGS-librtkaio += -DIS_IN_librt=1 -I$(..)rt ++# Resort to this ugliness of undefining and defining MODULE_NAME because ++# setting libof-<> to librt has many more side-effects that we want to avoid. ++CPPFLAGS-librtkaio += -I$(..)rt -UMODULE_NAME -DMODULE_NAME=librt + + rpath-dirs := $(patsubst rt,rtkaio,$(rpath-dirs)) + +diff -pruN glibc-2.21-649-gae5eae7/rtkaio/sysdeps/unix/sysv/linux/syscalls.list glibc-2.21-649-gae5eae7.new/rtkaio/sysdeps/unix/sysv/linux/syscalls.list +--- glibc-2.21-649-gae5eae7/rtkaio/sysdeps/unix/sysv/linux/syscalls.list 2015-07-27 22:47:23.073776396 +0530 ++++ glibc-2.21-649-gae5eae7.new/rtkaio/sysdeps/unix/sysv/linux/syscalls.list 2015-07-27 23:33:09.892874337 +0530 +@@ -1,5 +1,5 @@ + # File name Caller Syscall name Args Strong name Weak names + +-kaio_mq_timedsend - mq_timedsend Ci:ipiip __GI_mq_timedsend mq_timedsend +-kaio_mq_timedreceive - mq_timedreceive Ci:ipipp __GI_mq_timedreceive mq_timedreceive +-kaio_mq_setattr - mq_getsetattr i:ipp __GI_mq_setattr mq_setattr ++kaio_mq_timedsend - mq_timedsend Ci:ipiip __mq_timedsend mq_timedsend ++kaio_mq_timedreceive - mq_timedreceive Ci:ipipp __mq_timedreceive mq_timedreceive ++kaio_mq_setattr - mq_getsetattr i:ipp mq_setattr diff --git a/glibc-rtkaio.patch b/glibc-rtkaio.patch new file mode 100644 index 0000000..f5940d6 --- /dev/null +++ b/glibc-rtkaio.patch @@ -0,0 +1,5015 @@ +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Banner glibc-2.17-931-g30bbc0c.new/rtkaio/Banner +--- glibc-2.17-931-g30bbc0c/rtkaio/Banner 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Banner 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++RT using linux kernel aio +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/ChangeLog glibc-2.17-931-g30bbc0c.new/rtkaio/ChangeLog +--- glibc-2.17-931-g30bbc0c/rtkaio/ChangeLog 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/ChangeLog 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,255 @@ ++2009-10-30 Andreas Schwab ++ ++ * tst-aiod.h: Include . ++ ++2009-09-30 Andreas Schwab ++ ++ * sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S: New ++ file. ++ ++2007-12-12 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_read.c (aio_read64): Define to ++ something else while including kaio_misc.h. ++ * sysdeps/unix/sysv/linux/kaio_write.c (aio_write64): Likewise. ++ ++2007-08-01 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_misc.h (AIO_MISC_NOTIFY, ++ AIO_MISC_WAIT): Add LLL_PRIVATE as last argument to lll_futex_*wait. ++ ++2006-09-15 Jakub Jelinek ++ ++ [BZ #3138] ++ * rt/tst-aiod.c (do_prepare): Give name_len type size_t. ++ * rt/tst-aiod64.c (do_prepare): Likewise. ++ ++2006-09-07 Jakub Jelinek ++ ++ * tst-aiod2.c: Adjust test for new semantics of lio_listio. ++ * tst-aiod3.c: The thread is now supposed to be created. ++ ++ * Makefile: Use $(..) in place of ../. ++ (tests): Add tst-aio{8,9,10}, tst-cpuclock{1,2}, tst-cputimer{1,2,3} ++ and tst-clock2. ++ (CPPFLAGS-librtkaio): Append -I$(..)rt. ++ * Versions.def (librtkaio): Add GLIBC_2.4 version. ++ * sysdeps/unix/sysv/linux/kaio_misc.c (wait_for_kernel_requests) ++ [!DONT_NEED_AIO_MISC_COND]: Don't use condvar, use AIO_MISC_WAIT. ++ * sysdeps/unix/sysv/linux/kaio_misc.h [HAVE_FORCED_UNWIND] ++ (DONT_NEED_AIO_MISC_COND, AIO_MISC_NOTIFY, AIO_MISC_WAIT): Define. ++ (struct waitlist) [DONT_NEED_AIO_MISC_COND]: Remove cond. ++ * sysdeps/unix/sysv/linux/kaio_suspend.c (struct clparam) ++ [DONT_NEED_AIO_MISC_COND]: Remove cond. ++ (cleanup) [DONT_NEED_AIO_MISC_COND]: Lock __aio_requests_mutex on ++ entry. Don't destroy param->cond. ++ (aio_suspend): Fail if nent is negative. ++ (aio_suspend) [DONT_NEED_AIO_MISC_COND]: Don't use cond, use ++ AIO_MISC_WAIT. ++ * sysdeps/unix/sysv/linux/klio_listio.c (lio_listio): Renamed to... ++ (lio_listio_internal): ... this. Don't use cond, but AIO_MISC_WAIT, ++ if DONT_NEED_AIO_MISC_COND. Remove mode parameter check. Only set ++ sigevent type to SIGEV_NONE if LIO_NO_INDIVIDUAL_EVENT is set. ++ (__lio_listio_21): New function. Compatiblity version which sets ++ LIO_NO_INDIVIDUAL_EVENT before calling lio_listio_internal. ++ (__lio_listio_item_notify): New function. ++ * sysdeps/unix/sysv/linux/klio_listio64.c: Define __lio_listio_21 and ++ __lio_listio_item_notify macros. ++ * aio.h: Removed. ++ * configure.in: New file ++ * configure: Regenerated. ++ * sysdeps/rtkaio/kaio_cancel.c: Moved to... ++ * kaio_cancel.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_error.c: Moved to... ++ * kaio_error.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_fsync.c: Moved to... ++ * kaio_fsync.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_misc.c: Moved to... ++ * kaio_misc.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_notify.c: Moved to... ++ * kaio_notify.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_read.c: Moved to... ++ * kaio_read.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_read64.c: Moved to... ++ * kaio_read64.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_return.c: Moved to... ++ * kaio_return.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_sigqueue.c: Moved to... ++ * kaio_sigqueue.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_suspend.c: Moved to... ++ * kaio_suspend.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_write.c: Moved to... ++ * kaio_write.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_write64.c: Moved to... ++ * kaio_write64.c: ... here. New file. ++ * sysdeps/rtkaio/klio_listio.c: Moved to... ++ * klio_listio.c: ... here. New file. ++ * sysdeps/rtkaio/klio_listio64.c: Moved to... ++ * klio_listio64.c: ... here. New file. ++ * sysdeps/pthread/Versions: New file. ++ * tst-aio8.c: New file. ++ * tst-aio9.c: New file. ++ * tst-aio10.c: New file. ++ * tst-clock2.c: New file. ++ * tst-cpuclock1.c: New file. ++ * tst-cpuclock2.c: New file. ++ * tst-cputimer1.c: New file. ++ * tst-cputimer2.c: New file. ++ * tst-cputimer3.c: New file. ++ * sysdeps/unix/sysv/linux/sparc/Makefile: New file. ++ * sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c: New file. ++ * sysdeps/unix/sysv/linux/sparc/sparc64/Versions: New file. ++ * sysdeps/mips/Makefile: Removed. ++ * sysdeps/unix/mips/rtkaio-sysdep.S: Removed. ++ * sysdeps/unix/sysv/linux/hppa/Versions: Removed. ++ * sysdeps/unix/sysv/linux/hppa/kaio_cancel.c: Removed. ++ ++2006-07-19 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_misc.c: Include atomic.h. ++ (kernel_callback): Ensure __return_value is updated before ++ __error_code is set. ++ ++2006-05-11 Jakub Jelinek ++ ++ * Makefile (tests): Add tst-mqueue{8,9}, tst-timer5 and ++ tst-aiod{,64,2,3,4,5}. ++ (LDFLAGS-rtkaio.so): Add -Wl,--enable-new-dtags,-z,nodelete. ++ * sysdeps/unix/sysv/linux/kaio_misc.h: Include signal.h and ++ sysdep.h. ++ (aio_start_notify_thread, aio_create_helper_thread): Define ++ for !BROKEN_THREAD_SIGNALS. ++ (__aio_start_notify_thread, __aio_create_helper_thread): New ++ functions for !BROKEN_THREAD_SIGNALS. ++ * sysdeps/unix/sysv/linux/kaio_misc.c: Include sys/sysmacros.h. ++ (aio_create_helper_thread): Define if not yet defined. ++ (__aio_create_helper_thread): New function. ++ (__aio_wait_for_events): Pass 1 rather than 0 as min_nr to ++ io_getevents. ++ (handle_kernel_aio): Likewise. ++ (__aio_create_kernel_thread): Use aio_create_helper_thread. ++ (__aio_enqueue_user_request): Likewise. ++ (handle_fildes_io): Likewise. Remove noreturn attribute, ++ return NULL instead of calling pthread_exit (NULL). ++ (__aio_enqueue_request_ctx): Call fcntl and fxstat64 to avoid using ++ kaio on non-O_DIRECT non-/dev/raw* filedescriptors. For LIO_SYNC ++ and LIO_DSYNC also set kctx to KCTX_NONE. ++ * sysdeps/unix/sysv/linux/kaio_suspend.c (aio_suspend): Don't start ++ handle_kernel_aio thread if ktotal is zero. ++ * sysdeps/pthread/Makefile (tests): Add tst-mqueue8x. ++ (CFLAGS-tst-mqueue8x.c): Add -fexceptions. ++ * Versions.def (librtkaio): Add GLIBC_2.3.4 version. ++ * kaio_mq_close.c: New file. ++ * kaio_mq_getattr.c: New file. ++ * kaio_mq_notify.c: New file. ++ * kaio_mq_open.c: New file. ++ * kaio_mq_receive.c: New file. ++ * kaio_mq_send.c: New file. ++ * kaio_mq_setattr.c: New file. ++ * kaio_mq_timedreceive.c: New file. ++ * kaio_mq_timedsend.c: New file. ++ * kaio_mq_unlink.c: New file. ++ * sysdeps/pthread/tst-mqueue8x.c: New file. ++ * sysdeps/unix/sysv/linux/syscalls.list: New file. ++ * tst-mqueue8.c: New file. ++ * tst-mqueue9.c: New file. ++ * tst-timer5.c: New file. ++ * tst-aiod.h: New file. ++ * tst-aiod.c: New test. ++ * tst-aiod64.c: New test. ++ * tst-aiod2.c: New test. ++ * tst-aiod3.c: New test. ++ * tst-aiod4.c: New test. ++ * tst-aiod5.c: New test. ++ * sysdeps/mips/Makefile: New file. ++ * sysdeps/unix/alpha/Makefile: New file. ++ * sysdeps/unix/alpha/rtkaio-sysdep.S: New file. ++ * sysdeps/unix/mips/rtkaio-sysdep.S: New file. ++ * sysdeps/unix/sysv/linux/Makefile: New file. ++ * sysdeps/unix/sysv/linux/s390/Makefile: New file. ++ * sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S: New file. ++ * sysdeps/unix/sysv/linux/powerpc/Makefile: New file. ++ * sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c: New file. ++ * sysdeps/unix/sysv/linux/ia64/Makefile: New file. ++ * sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S: New file. ++ ++2004-04-17 Jakub Jelinek ++ ++ * rt/Makefile (mq-routines): Set. ++ (librt-routines): Use it. ++ (tests): Add tst-mqueue{1,2,3,4,5,6,7} and tst-timer{3,4}. ++ (tst-mqueue7-ARGS): Set. ++ * rt/Versions (librt): Add mq_*@@GLIBC_2.3.4. ++ * rt/tst-mqueue1.c: New file. ++ * rt/tst-mqueue2.c: New file. ++ * rt/tst-mqueue3.c: New file. ++ * rt/tst-mqueue4.c: New file. ++ * rt/tst-mqueue5.c: New file. ++ * rt/tst-mqueue6.c: New file. ++ * rt/tst-mqueue7.c: New file. ++ * rt/tst-timer3.c: New file. ++ * rt/tst-timer4.c: New file. ++ ++2003-08-14 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_misc.c (wait_for_kernel_requests): ++ New function. ++ (handle_fildes_io): Use it for LIO_SYNC and LIO_DSYNC. ++ ++ * sysdeps/pthread/Makefile (CPPFLAGS): Add -DBROKEN_THREAD_SIGNALS ++ for rtkaio/linuxthreads combo. ++ * sysdeps/unix/sysv/linux/kaio_misc.c (__aio_enqueue_request_ctx): ++ Only set caller_pid if BROKEN_THREAD_SIGNALS. ++ * sysdeps/unix/sysv/linux/kaio_misc.h (struct waitlist, ++ struct requestlist): Remove caller_pid unless BROKEN_THREAD_SIGNALS. ++ (__aio_notify_only): Remove last argument if not ++ BROKEN_THREAD_SIGNALS. ++ * sysdeps/unix/sysv/linux/kaio_suspend.c (aio_suspend): Only set ++ caller_pid if not BROKEN_THREAD_SIGNALS. ++ * sysdeps/unix/sysv/linux/klio_listio.c (lio_listio): Likewise. ++ Remove last argument in call to __aio_notify_only unless ++ BROKEN_THREAD_SIGNALS. ++ ++ * tst-aio.c: Avoid test duplication. Include rt/aio.c instead. ++ * tst-aio2.c: Similarly. ++ * tst-aio3.c: Similarly. ++ * tst-aio4.c: Similarly. ++ * tst-aio5.c: Similarly. ++ * tst-aio6.c: Similarly. ++ * tst-aio64.c: Similarly. ++ * tst-aio7.c: Similarly. ++ * tst-clock.c: Similarly. ++ * tst-clock_nanosleep.c: Similarly. ++ * tst-shm.c: Similarly. ++ * tst-timer2.c: Similarly. ++ ++2003-07-29 Roland McGrath ++ ++ * rt/tst-timer2.c: New file. ++ * rt/Makefile (tests): Add it. ++ ++2003-07-25 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_cancel.c (aio_cancel): Attempt ++ to cancel kioctx != KCTX_NONE requests even if second argument ++ to aio_cancel is NULL. ++ ++2003-07-24 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_cancel.c (aio_cancel): Return ++ AIO_ALLDONE if aiocbp != NULL and has already completed. Return ++ -1/EINVAL if aiocbp->aio_fildes does not match fildes. ++ ++ * sysdeps/unix/sysv/linux/alpha/kaio_cancel.c: New file. ++ * sysdeps/unix/sysv/linux/hppa/kaio_cancel.c: New file. ++ * sysdeps/unix/sysv/linux/sparc/kaio_cancel.c: New file. ++ * sysdeps/unix/sysv/linux/kaio_cancel.c (aio_cancel): Attempt ++ to cancel request handled by kernel (so far just if aiocbp != NULL). ++ * sysdeps/unix/sysv/linux/kaio_misc.c (__aio_remove_krequest): Fix ++ assertion, req->kioctx must NOT be KCTX_NONE. ++ * sysdeps/unix/sysv/linux/kaio_misc.h (__aio_remove_krequest): New ++ prototype. ++ ++2003-07-23 Jakub Jelinek ++ ++ * New add-on. +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/configure glibc-2.17-931-g30bbc0c.new/rtkaio/configure +--- glibc-2.17-931-g30bbc0c/rtkaio/configure 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/configure 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,4 @@ ++# This file is generated from configure.in by Autoconf. DO NOT EDIT! ++ ++libc_add_on_canonical= ++libc_add_on_subdirs=. +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/configure.in glibc-2.17-931-g30bbc0c.new/rtkaio/configure.in +--- glibc-2.17-931-g30bbc0c/rtkaio/configure.in 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/configure.in 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,5 @@ ++dnl glibc configure fragment for rtkaio add-on ++GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. ++ ++libc_add_on_canonical= ++libc_add_on_subdirs=. +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Depend glibc-2.17-931-g30bbc0c.new/rtkaio/Depend +--- glibc-2.17-931-g30bbc0c/rtkaio/Depend 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Depend 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++rt +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_cancel.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_cancel.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_cancel.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_cancel.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_getcpuclockid.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_getcpuclockid.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_getcpuclockid.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_getcpuclockid.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_getres.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_getres.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_getres.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_getres.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_gettime.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_gettime.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_gettime.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_gettime.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_nanosleep.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_nanosleep.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_nanosleep.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_nanosleep.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_settime.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_settime.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_settime.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_settime.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_error.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_error.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_error.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_error.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_fsync.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_fsync.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_fsync.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_fsync.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_get_clockfreq.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_get_clockfreq.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_get_clockfreq.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_get_clockfreq.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_misc.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_misc.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_misc.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_misc.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_close.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_close.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_close.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_close.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_getattr.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_getattr.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_getattr.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_getattr.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_notify.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_notify.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_notify.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_notify.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_open.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_open.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_open.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_open.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_receive.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_receive.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_receive.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_receive.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_send.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_send.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_send.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_send.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_setattr.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_setattr.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_setattr.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_setattr.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_timedreceive.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_timedreceive.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_timedreceive.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_timedreceive.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_timedsend.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_timedsend.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_timedsend.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_timedsend.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_unlink.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_unlink.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_unlink.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_unlink.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_notify.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_notify.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_notify.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_notify.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_read64.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_read64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_read64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_read64.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_read.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_read.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_read.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_read.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_return.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_return.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_return.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_return.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_shm_open.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_shm_open.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_shm_open.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_shm_open.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_shm_unlink.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_shm_unlink.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_shm_unlink.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_shm_unlink.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_sigqueue.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_sigqueue.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_sigqueue.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_sigqueue.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_suspend.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_suspend.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_suspend.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_suspend.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_create.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_create.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_create.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_create.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_delete.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_delete.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_delete.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_delete.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_getoverr.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_getoverr.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_getoverr.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_getoverr.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_gettime.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_gettime.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_gettime.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_gettime.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_settime.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_settime.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_settime.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_settime.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_write64.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_write64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_write64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_write64.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_write.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_write.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_write.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_write.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/klio_listio64.c glibc-2.17-931-g30bbc0c.new/rtkaio/klio_listio64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/klio_listio64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/klio_listio64.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/klio_listio.c glibc-2.17-931-g30bbc0c.new/rtkaio/klio_listio.c +--- glibc-2.17-931-g30bbc0c/rtkaio/klio_listio.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/klio_listio.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Makefile 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1,106 @@ ++# Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. ++# This file is part of the GNU C Library. ++ ++# The GNU C Library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2.1 of the License, or (at your option) any later version. ++ ++# The GNU C Library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++ ++# You should have received a copy of the GNU Lesser General Public ++# License along with the GNU C Library; if not, write to the Free ++# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++# 02111-1307 USA. ++ ++# ++# Sub-makefile for real-time kaio portion of the library. ++# ++subdir := rtkaio ++ ++aio-routines := aio_cancel aio_error aio_fsync aio_misc aio_read \ ++ aio_read64 aio_return aio_suspend aio_write \ ++ aio_write64 lio_listio lio_listio64 aio_sigqueue \ ++ aio_notify ++clock-routines := get_clockfreq clock_getcpuclockid \ ++ clock_getres clock_gettime clock_settime \ ++ clock_nanosleep ++timer-routines := timer_create timer_delete timer_getoverr \ ++ timer_gettime timer_settime ++shm-routines := shm_open shm_unlink ++mq-routines := mq_open mq_close mq_unlink mq_getattr mq_setattr \ ++ mq_notify mq_send mq_receive mq_timedsend \ ++ mq_timedreceive ++ ++librtkaio-routines = $(patsubst %,k%,$(aio-routines)) \ ++ $(patsubst %,kaio_%,$(clock-routines) $(timer-routines) \ ++ $(shm-routines) $(mq-routines)) ++ ++tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \ ++ tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \ ++ tst-aio7 tst-aio8 tst-aio9 tst-aio10 \ ++ tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \ ++ tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \ ++ tst-timer3 tst-timer4 tst-timer5 \ ++ tst-cpuclock1 tst-cpuclock2 \ ++ tst-cputimer1 tst-cputimer2 tst-cputimer3 \ ++ tst-clock2 \ ++ tst-aiod tst-aiod64 tst-aiod2 tst-aiod3 tst-aiod4 tst-aiod5 ++ ++extra-libs := librtkaio ++extra-libs-others := $(extra-libs) ++ ++include $(..)Makeconfig ++ ++ifeq (yesyes,$(build-shared)$(elf)) ++generated += librt.so$(librt.so-version) ++ ++$(objpfx)librt.so$(librt.so-version): $(objpfx)librtkaio.so; $(make-link) ++endif ++ ++include $(..)Rules ++ ++CFLAGS-kaio_suspend.c = -fexceptions ++CFLAGS-kaio_clock_nanosleep.c = -fexceptions -fasynchronous-unwind-tables ++CFLAGS-kaio_librt-cancellation.c = -fasynchronous-unwind-tables ++ ++LDFLAGS-rtkaio.so = -Wl,-soname=lib$(libprefix)rt.so$(librt.so-version) \ ++ -Wl,--enable-new-dtags,-z,nodelete ++CPPFLAGS-librtkaio += -DIS_IN_librt=1 -I$(..)rt ++ ++rpath-dirs := $(patsubst rt,rtkaio,$(rpath-dirs)) ++ ++ifeq (yesyes,$(build-shared)$(elf)) ++others: $(objpfx)librt.so$(librt.so-version) ++endif ++ ++# Depend on libc.so so a DT_NEEDED is generated in the shared objects. ++# This ensures they will load libc.so for needed symbols if loaded by ++# a statically-linked program that hasn't already loaded it. ++$(objpfx)librtkaio.so: $(common-objpfx)libc.so $(common-objpfx)libc_nonshared.a \ ++ $(shared-thread-library) \ ++ $(if $(filter yes,$(elf)), $(elf-objpfx)ld.so) ++ ++ifeq (yes,$(build-shared)) ++$(addprefix $(objpfx),$(tests)): $(objpfx)librtkaio.so $(shared-thread-library) ++else ++$(addprefix $(objpfx),$(tests)): $(objpfx)librtkaio.a $(static-thread-library) ++endif ++ifeq (yes,$(build-bounded)) ++$(tests:%=$(objpfx)%-bp): $(objpfx)librtkaio_b.a $(bounded-thread-library) ++endif ++ ++tst-mqueue7-ARGS = -- $(built-program-file) ++ ++ifeq (yes,$(build-static-nss)) ++otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \ ++ $(resolvobjdir)/libresolv.a ++endif ++ ++# FIXME: This is a placeholder to let the tests run to conclusion. This needs ++# a real abilist file. ++$(objpfx)check-abi-librtkaio.out: ++ touch $@ +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/shlib-versions glibc-2.17-931-g30bbc0c.new/rtkaio/shlib-versions +--- glibc-2.17-931-g30bbc0c/rtkaio/shlib-versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/shlib-versions 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,1 @@ ++librtkaio=1 +diff --git a/sysdeps/unix/sysv/linux/mips/shlib-versions b/sysdeps/unix/sysv/linux/mips/shlib-versions +index c5bd7db..06f28ea 100644 +--- a/sysdeps/unix/sysv/linux/mips/shlib-versions ++++ b/sysdeps/unix/sysv/linux/mips/shlib-versions +@@ -23,5 +23,6 @@ libnss_hesiod=2 GLIBC_2.0 GLIBC_2.2 + libnsl=1 GLIBC_2.0 GLIBC_2.2 + + librt=1 GLIBC_2.0 GLIBC_2.2 ++librtkaio=1 GLIBC_2.0 GLIBC_2.2 + + libpthread=0 GLIBC_2.0 GLIBC_2.2 +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/kaio_timer_routines.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/kaio_timer_routines.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/kaio_timer_routines.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/kaio_timer_routines.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/librtkaio-cancellation.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/librtkaio-cancellation.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/librtkaio-cancellation.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/librtkaio-cancellation.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/Makefile 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,39 @@ ++ifeq ($(filter nptl,$(sorted-subdirs)),nptl) ++ ++ifeq ($(subdir),rtkaio) ++librtkaio-sysdep_routines += kaio_timer_routines librtkaio-cancellation rtkaio-unwind-resume ++librtkaio-shared-only-routines += rtkaio-unwind-resume ++tests += tst-cancel17 tst-cancelx17 ++CPPFLAGS-kaio_timer_routines.c = -I../nptl ++CFLAGS-librtkaio-cancellation.c += -fexceptions -fasynchronous-unwind-tables ++CFLAGS-rtkaio-unwind-resume.c += -fexceptions -fasynchronous-unwind-tables ++CFLAGS-tst-cancelx17.c += -fexceptions ++ ++ifeq (yes,$(build-shared)) ++$(objpfx)tst-timer: $(objpfx)librtkaio.so $(shared-thread-library) ++else ++$(objpfx)tst-timer: $(objpfx)librtkaio.a $(static-thread-library) ++endif ++ ++ifeq ($(have-forced-unwind),yes) ++tests += tst-mqueue8x ++CFLAGS-tst-mqueue8x.c += -fexceptions ++endif ++endif ++ ++endif ++ ++ifeq ($(filter linuxthreads,$(sorted-subdirs)),linuxthreads) ++ ++ifeq ($(subdir),rtkaio) ++librtkaio-sysdep_routines += kaio_timer_routines ++CPPFLAGS += -DBROKEN_THREAD_SIGNALS ++ ++ifeq (yes,$(build-shared)) ++$(objpfx)tst-timer: $(objpfx)librtkaio.so $(shared-thread-library) ++else ++$(objpfx)tst-timer: $(objpfx)librtkaio.a $(static-thread-library) ++endif ++endif ++ ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/rtkaio-unwind-resume.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/rtkaio-unwind-resume.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/rtkaio-unwind-resume.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/rtkaio-unwind-resume.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-cancel17.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-cancel17.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-cancel17.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-cancel17.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-cancelx17.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-cancelx17.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-cancelx17.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-cancelx17.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include "tst-cancel17.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-mqueue8x.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-mqueue8x.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-mqueue8x.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-mqueue8x.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include_next +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-timer.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-timer.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-timer.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-timer.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include_next +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/Versions 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,7 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.4 { ++ lio_listio; lio_listio64; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/alpha/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/alpha/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/alpha/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/alpha/Makefile 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-sysdep_routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/alpha/kaio_cancel.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/alpha/kaio_cancel.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/alpha/kaio_cancel.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/alpha/kaio_cancel.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,33 @@ ++#include ++ ++#define aio_cancel64 XXX ++#include ++#undef aio_cancel64 ++#include ++ ++extern __typeof (aio_cancel) __new_aio_cancel; ++extern __typeof (aio_cancel) __old_aio_cancel; ++ ++#define aio_cancel __new_aio_cancel ++ ++#include ++ ++#undef aio_cancel ++strong_alias (__new_aio_cancel, __new_aio_cancel64); ++versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); ++versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); ++ ++#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) ++ ++#undef ECANCELED ++#define aio_cancel __old_aio_cancel ++#define ECANCELED 125 ++ ++#include ++ ++#undef aio_cancel ++strong_alias (__old_aio_cancel, __old_aio_cancel64); ++compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); ++compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/alpha/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/alpha/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/alpha/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/alpha/Versions 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,6 @@ ++librtkaio { ++ GLIBC_2.3 { ++ # AIO functions. ++ aio_cancel; aio_cancel64; ++ } ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_cancel.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_cancel.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_cancel.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_cancel.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,240 @@ ++/* Cancel requests associated with given file descriptor. ++ Copyright (C) 1997, 1998, 2000, 2002, 2003, 2005 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++/* We use an UGLY hack to prevent gcc from finding us cheating. The ++ implementation of aio_cancel and aio_cancel64 are identical and so ++ we want to avoid code duplication by using aliases. But gcc sees ++ the different parameter lists and prints a warning. We define here ++ a function so that aio_cancel64 has no prototype. */ ++#ifndef aio_cancel ++#define aio_cancel64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_cancel64 ++#endif ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++#include ++#include ++#include ++ ++int ++aio_cancel (fildes, aiocbp) ++ int fildes; ++ struct aiocb *aiocbp; ++{ ++ struct requestlist *req = NULL; ++ int result = AIO_ALLDONE; ++ ++ /* If fildes is invalid, error. */ ++ if (fcntl (fildes, F_GETFL) < 0) ++ { ++ __set_errno (EBADF); ++ return -1; ++ } ++ ++ /* Request the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ /* We are asked to cancel a specific AIO request. */ ++ if (aiocbp != NULL) ++ { ++ /* If the AIO request is not for this descriptor it has no value ++ to look for the request block. */ ++ if (aiocbp->aio_fildes != fildes) ++ { ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ __set_errno (EINVAL); ++ return -1; ++ } ++ else if (aiocbp->__error_code == EINPROGRESS) ++ { ++ struct requestlist *last = NULL; ++ ++ req = __aio_find_req_fd (fildes); ++ ++ if (req != NULL) ++ while (req->aiocbp != (aiocb_union *) aiocbp) ++ { ++ last = req; ++ req = req->next_prio; ++ if (req == NULL) ++ break; ++ } ++ ++ if (req != NULL) ++ { ++ /* Don't remove the entry if a thread is already working on ++ it. */ ++ if (req->running == allocated) ++ { ++ result = AIO_NOTCANCELED; ++ req = NULL; ++ } ++ else ++ { ++ /* We can remove the entry. */ ++ __aio_remove_request (last, req, 0); ++ ++ result = AIO_CANCELED; ++ ++ req->next_prio = NULL; ++ } ++ } ++ else ++ { ++ /* Try kernel requests. */ ++ req = __aio_find_req ((aiocb_union *) aiocbp); ++ ++ if (req == NULL) ++ { ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ assert (req->kioctx != KCTX_NONE); ++ ++ /* If kernel is working on it, try cancelling it. */ ++ if (req->running == allocated) ++ { ++ struct kio_event ev; ++ INTERNAL_SYSCALL_DECL (err); ++ int res; ++ ++ res = INTERNAL_SYSCALL (io_cancel, err, 3, __aio_kioctx, ++ &req->kiocb, &ev); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ result = AIO_NOTCANCELED; ++ req = NULL; ++ } ++ else ++ req->running = queued; ++ } ++ if (req != NULL) ++ { ++ /* We can remove the entry. */ ++ __aio_remove_krequest (req); ++ result = AIO_CANCELED; ++ req->next_prio = NULL; ++ } ++ } ++ } ++ } ++ else ++ { ++ /* Find the beginning of the list of all requests for this ++ desriptor. */ ++ req = __aio_find_req_fd (fildes); ++ ++ /* If any request is worked on by a thread it must be the first. ++ So either we can delete all requests or all but the first. */ ++ if (req != NULL) ++ { ++ if (req->running == allocated) ++ { ++ struct requestlist *old = req; ++ req = req->next_prio; ++ old->next_prio = NULL; ++ ++ result = AIO_NOTCANCELED; ++ ++ if (req != NULL) ++ __aio_remove_request (old, req, 1); ++ } ++ else ++ { ++ result = AIO_CANCELED; ++ ++ /* We can remove the entry. */ ++ __aio_remove_request (NULL, req, 1); ++ } ++ } ++ ++ if (result != AIO_NOTCANCELED) ++ { ++ /* Try to cancel kernel requests. */ ++ struct requestlist *kreq = __aio_find_kreq_fd (fildes); ++ ++ while (kreq) ++ { ++ struct requestlist *next; ++ ++ /* If kernel is working on it, try cancelling it. */ ++ if (kreq->running == allocated) ++ { ++ struct kio_event ev; ++ INTERNAL_SYSCALL_DECL (err); ++ int res; ++ ++ res = INTERNAL_SYSCALL (io_cancel, err, 3, __aio_kioctx, ++ &kreq->kiocb, &ev); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ result = AIO_NOTCANCELED; ++ break; ++ } ++ else ++ kreq->running = queued; ++ } ++ next = kreq->next_prio; ++ __aio_remove_krequest (kreq); ++ result = AIO_CANCELED; ++ kreq->next_prio = NULL; ++ assert (kreq->running == yes || kreq->running == queued); ++ kreq->aiocbp->aiocb.__error_code = ECANCELED; ++ kreq->aiocbp->aiocb.__return_value = -1; ++ __aio_notify (kreq); ++ __aio_free_request (kreq); ++ kreq = next; ++ } ++ } ++ } ++ ++ /* Mark requests as canceled and send signal. */ ++ while (req != NULL) ++ { ++ struct requestlist *old = req; ++ assert (req->running == yes || req->running == queued); ++ req->aiocbp->aiocb.__error_code = ECANCELED; ++ req->aiocbp->aiocb.__return_value = -1; ++ __aio_notify (req); ++ req = req->next_prio; ++ __aio_free_request (old); ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ return result; ++} ++ ++#ifndef aio_cancel ++weak_alias (aio_cancel, aio_cancel64) ++#endif ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_error.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_error.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_error.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_error.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,54 @@ ++/* Return error status of asynchronous I/O request. ++ Copyright (C) 1997, 2002, 2003 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++/* We use an UGLY hack to prevent gcc from finding us cheating. The ++ implementation of aio_error and aio_error64 are identical and so ++ we want to avoid code duplication by using aliases. But gcc sees ++ the different parameter lists and prints a warning. We define here ++ a function so that aio_error64 has no prototype. */ ++#define aio_error64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_error64 ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++ ++int ++aio_error (aiocbp) ++ const struct aiocb *aiocbp; ++{ ++ int ret = aiocbp->__error_code; ++ ++ if (ret == EINPROGRESS) ++ { ++ __aio_read_one_event (); ++ ret = aiocbp->__error_code; ++ } ++ return ret; ++} ++ ++weak_alias (aio_error, aio_error64) ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_fsync.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_fsync.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_fsync.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_fsync.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,6 @@ ++#define aio_fsync64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_fsync64 ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,1139 @@ ++/* Handle general operations. ++ Copyright (C) 1997,1998,1999,2000,2001,2002,2003,2006,2010 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef aio_create_helper_thread ++# define aio_create_helper_thread __aio_create_helper_thread ++ ++extern inline int ++__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg) ++{ ++ pthread_attr_t attr; ++ ++ /* Make sure the thread is created detached. */ ++ pthread_attr_init (&attr); ++ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); ++ ++ int ret = pthread_create (threadp, &attr, tf, arg); ++ ++ (void) pthread_attr_destroy (&attr); ++ return ret; ++} ++ ++#endif ++ ++ ++static void add_request_to_runlist (struct requestlist *newrequest) ++ internal_function; ++static int add_request_to_list (struct requestlist *newrequest, int fildes, ++ int prio) ++ internal_function; ++static void * handle_kernel_aio (void *arg); ++static void kernel_callback (kctx_t ctx, struct kiocb *kiocb, long res, ++ long res2); ++ ++/* Pool of request list entries. */ ++static struct requestlist **pool; ++ ++/* Number of total and allocated pool entries. */ ++static size_t pool_max_size; ++static size_t pool_size; ++ ++/* Kernel AIO context. */ ++kctx_t __aio_kioctx = KCTX_NONE; ++int __have_no_kernel_aio; ++int __kernel_thread_started; ++ ++/* We implement a two dimensional array but allocate each row separately. ++ The macro below determines how many entries should be used per row. ++ It should better be a power of two. */ ++#define ENTRIES_PER_ROW 32 ++ ++/* How many rows we allocate at once. */ ++#define ROWS_STEP 8 ++ ++/* List of available entries. */ ++static struct requestlist *freelist; ++ ++/* List of request waiting to be processed. */ ++static struct requestlist *runlist; ++ ++/* Structure list of all currently processed requests. */ ++static struct requestlist *requests, *krequests; ++ ++/* Number of threads currently running. */ ++static int nthreads; ++ ++/* Number of threads waiting for work to arrive. */ ++static int idle_thread_count; ++ ++ ++/* These are the values used to optimize the use of AIO. The user can ++ overwrite them by using the `aio_init' function. */ ++static struct aioinit optim = ++{ ++ 20, /* int aio_threads; Maximal number of threads. */ ++ 64, /* int aio_num; Number of expected simultanious requests. */ ++ 0, ++ 0, ++ 0, ++ 0, ++ 1, ++ 0 ++}; ++ ++ ++/* Since the list is global we need a mutex protecting it. */ ++pthread_mutex_t __aio_requests_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; ++ ++/* When you add a request to the list and there are idle threads present, ++ you signal this condition variable. When a thread finishes work, it waits ++ on this condition variable for a time before it actually exits. */ ++pthread_cond_t __aio_new_request_notification = PTHREAD_COND_INITIALIZER; ++ ++ ++/* Functions to handle request list pool. */ ++static struct requestlist * ++get_elem (void) ++{ ++ struct requestlist *result; ++ ++ if (freelist == NULL) ++ { ++ struct requestlist *new_row; ++ int cnt; ++ ++ assert (sizeof (struct aiocb) == sizeof (struct aiocb64)); ++ ++ if (pool_size + 1 >= pool_max_size) ++ { ++ size_t new_max_size = pool_max_size + ROWS_STEP; ++ struct requestlist **new_tab; ++ ++ new_tab = (struct requestlist **) ++ realloc (pool, new_max_size * sizeof (struct requestlist *)); ++ ++ if (new_tab == NULL) ++ return NULL; ++ ++ pool_max_size = new_max_size; ++ pool = new_tab; ++ } ++ ++ /* Allocate the new row. */ ++ cnt = pool_size == 0 ? optim.aio_num : ENTRIES_PER_ROW; ++ new_row = (struct requestlist *) calloc (cnt, ++ sizeof (struct requestlist)); ++ if (new_row == NULL) ++ return NULL; ++ ++ pool[pool_size++] = new_row; ++ ++ /* Put all the new entries in the freelist. */ ++ do ++ { ++ new_row->next_prio = freelist; ++ freelist = new_row++; ++ } ++ while (--cnt > 0); ++ } ++ ++ result = freelist; ++ freelist = freelist->next_prio; ++ ++ return result; ++} ++ ++ ++void ++internal_function ++__aio_free_request (struct requestlist *elem) ++{ ++ elem->running = no; ++ elem->next_prio = freelist; ++ freelist = elem; ++} ++ ++ ++struct requestlist * ++internal_function ++__aio_find_req (aiocb_union *elem) ++{ ++ struct requestlist *runp; ++ int fildes = elem->aiocb.aio_fildes; ++ int i; ++ ++ for (i = 0; i < 2; i++) ++ { ++ runp = i ? requests : krequests; ++ ++ while (runp != NULL && runp->aiocbp->aiocb.aio_fildes < fildes) ++ runp = runp->next_fd; ++ ++ if (runp != NULL) ++ { ++ if (runp->aiocbp->aiocb.aio_fildes != fildes) ++ runp = NULL; ++ else ++ while (runp != NULL && runp->aiocbp != elem) ++ runp = runp->next_prio; ++ if (runp != NULL) ++ return runp; ++ } ++ } ++ ++ return NULL; ++} ++ ++ ++struct requestlist * ++internal_function ++__aio_find_req_fd (int fildes) ++{ ++ struct requestlist *runp = requests; ++ ++ while (runp != NULL && runp->aiocbp->aiocb.aio_fildes < fildes) ++ runp = runp->next_fd; ++ ++ return (runp != NULL && runp->aiocbp->aiocb.aio_fildes == fildes ++ ? runp : NULL); ++} ++ ++ ++struct requestlist * ++internal_function ++__aio_find_kreq_fd (int fildes) ++{ ++ struct requestlist *runp = krequests; ++ ++ while (runp != NULL && runp->aiocbp->aiocb.aio_fildes < fildes) ++ runp = runp->next_fd; ++ ++ return (runp != NULL && runp->aiocbp->aiocb.aio_fildes == fildes ++ ? runp : NULL); ++} ++ ++ ++void ++internal_function ++__aio_remove_request (struct requestlist *last, struct requestlist *req, ++ int all) ++{ ++ assert (req->running == yes || req->running == queued ++ || req->running == done); ++ assert (req->kioctx == KCTX_NONE); ++ ++ if (last != NULL) ++ last->next_prio = all ? NULL : req->next_prio; ++ else ++ { ++ if (all || req->next_prio == NULL) ++ { ++ if (req->last_fd != NULL) ++ req->last_fd->next_fd = req->next_fd; ++ else ++ requests = req->next_fd; ++ if (req->next_fd != NULL) ++ req->next_fd->last_fd = req->last_fd; ++ } ++ else ++ { ++ if (req->last_fd != NULL) ++ req->last_fd->next_fd = req->next_prio; ++ else ++ requests = req->next_prio; ++ ++ if (req->next_fd != NULL) ++ req->next_fd->last_fd = req->next_prio; ++ ++ req->next_prio->last_fd = req->last_fd; ++ req->next_prio->next_fd = req->next_fd; ++ ++ /* Mark this entry as runnable. */ ++ req->next_prio->running = yes; ++ } ++ ++ if (req->running == yes) ++ { ++ struct requestlist *runp = runlist; ++ ++ last = NULL; ++ while (runp != NULL) ++ { ++ if (runp == req) ++ { ++ if (last == NULL) ++ runlist = runp->next_run; ++ else ++ last->next_run = runp->next_run; ++ break; ++ } ++ last = runp; ++ runp = runp->next_run; ++ } ++ } ++ } ++} ++ ++void ++internal_function ++__aio_remove_krequest (struct requestlist *req) ++{ ++ assert (req->running == yes || req->running == queued ++ || req->running == done); ++ assert (req->kioctx != KCTX_NONE); ++ ++ if (req->prev_prio != NULL) ++ { ++ req->prev_prio->next_prio = req->next_prio; ++ if (req->next_prio != NULL) ++ req->next_prio->prev_prio = req->prev_prio; ++ } ++ else if (req->next_prio == NULL) ++ { ++ if (req->last_fd != NULL) ++ req->last_fd->next_fd = req->next_fd; ++ else ++ krequests = req->next_fd; ++ if (req->next_fd != NULL) ++ req->next_fd->last_fd = req->last_fd; ++ } ++ else ++ { ++ if (req->last_fd != NULL) ++ req->last_fd->next_fd = req->next_prio; ++ else ++ krequests = req->next_prio; ++ if (req->next_fd != NULL) ++ req->next_fd->last_fd = req->next_prio; ++ ++ req->next_prio->prev_prio = NULL; ++ req->next_prio->last_fd = req->last_fd; ++ req->next_prio->next_fd = req->next_fd; ++ } ++} ++ ++ ++/* The thread handler. */ ++static void *handle_fildes_io (void *arg); ++static int wait_for_kernel_requests (int fildes); ++ ++ ++/* User optimization. */ ++void ++__aio_init (const struct aioinit *init) ++{ ++ /* Get the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ /* Only allow writing new values if the table is not yet allocated. */ ++ if (pool == NULL) ++ { ++ optim.aio_threads = init->aio_threads < 1 ? 1 : init->aio_threads; ++ optim.aio_num = (init->aio_num < ENTRIES_PER_ROW ++ ? ENTRIES_PER_ROW ++ : init->aio_num & ~ENTRIES_PER_ROW); ++ } ++ ++ if (init->aio_idle_time != 0) ++ optim.aio_idle_time = init->aio_idle_time; ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++} ++weak_alias (__aio_init, aio_init) ++ ++static void ++kernel_callback (kctx_t ctx, struct kiocb *kiocb, long res, long res2) ++{ ++ struct requestlist *req = (struct requestlist *)kiocb; ++ long errcode = 0; ++ ++ if (res < 0 && res > -1000) ++ { ++ errcode = -res; ++ res = -1; ++ } ++ req->aiocbp->aiocb.__return_value = res; ++ atomic_write_barrier (); ++ req->aiocbp->aiocb.__error_code = errcode; ++ __aio_notify (req); ++ assert (req->running == allocated); ++ req->running = done; ++ __aio_remove_krequest (req); ++ __aio_free_request (req); ++} ++ ++void ++internal_function ++__aio_read_one_event (void) ++{ ++ struct kio_event ev[10]; ++ struct timespec ts; ++ int count, i; ++ ++ if (__aio_kioctx == KCTX_NONE) ++ return; ++ ts.tv_sec = 0; ++ ts.tv_nsec = 0; ++ do ++ { ++ INTERNAL_SYSCALL_DECL (err); ++ count = INTERNAL_SYSCALL (io_getevents, err, 5, __aio_kioctx, 0, 10, ++ ev, &ts); ++ if (INTERNAL_SYSCALL_ERROR_P (count, err) || count == 0) ++ break; ++ pthread_mutex_lock (&__aio_requests_mutex); ++ for (i = 0; i < count; i++) ++ { ++ void (*cb)(kctx_t, struct kiocb *, long, long); ++ ++ cb = (void *) (uintptr_t) ev[i].kioe_data; ++ cb (__aio_kioctx, (struct kiocb *) (uintptr_t) ev[i].kioe_obj, ++ ev[i].kioe_res, ev[i].kioe_res2); ++ } ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ } ++ while (count == 10); ++} ++ ++int ++internal_function ++__aio_wait_for_events (kctx_t kctx, const struct timespec *timespec) ++{ ++ int ret, i; ++ struct kio_event ev[10]; ++ struct timespec ts; ++ INTERNAL_SYSCALL_DECL (err); ++ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ts.tv_sec = 0; ++ ts.tv_nsec = 0; ++ do ++ { ++ ret = INTERNAL_SYSCALL (io_getevents, err, 5, kctx, 1, 10, ev, ++ timespec); ++ if (INTERNAL_SYSCALL_ERROR_P (ret, err) || ret == 0) ++ break; ++ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ for (i = 0; i < ret; i++) ++ { ++ void (*cb)(kctx_t, struct kiocb *, long, long); ++ ++ cb = (void *) (uintptr_t) ev[i].kioe_data; ++ cb (kctx, (struct kiocb *) (uintptr_t) ev[i].kioe_obj, ++ ev[i].kioe_res, ev[i].kioe_res2); ++ } ++ if (ret < 10) ++ return 0; ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ timespec = &ts; ++ } ++ while (1); ++ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ return (timespec != &ts ++ && INTERNAL_SYSCALL_ERROR_P (ret, err) ++ && INTERNAL_SYSCALL_ERRNO (ret, err) == ETIMEDOUT) ? ETIMEDOUT : 0; ++} ++ ++int ++internal_function ++__aio_create_kernel_thread (void) ++{ ++ pthread_t thid; ++ ++ if (__kernel_thread_started) ++ return 0; ++ ++ if (aio_create_helper_thread (&thid, handle_kernel_aio, NULL) != 0) ++ return -1; ++ __kernel_thread_started = 1; ++ return 0; ++} ++ ++static void * ++handle_kernel_aio (void *arg __attribute__((unused))) ++{ ++ int ret, i; ++ INTERNAL_SYSCALL_DECL (err); ++ struct kio_event ev[10]; ++ ++ for (;;) ++ { ++ ret = INTERNAL_SYSCALL (io_getevents, err, 5, __aio_kioctx, 1, 10, ev, ++ NULL); ++ if (INTERNAL_SYSCALL_ERROR_P (ret, err) || ret == 0) ++ continue; ++ pthread_mutex_lock (&__aio_requests_mutex); ++ for (i = 0; i < ret; i++) ++ { ++ void (*cb)(kctx_t, struct kiocb *, long, long); ++ ++ cb = (void *) (uintptr_t) ev[i].kioe_data; ++ cb (__aio_kioctx, (struct kiocb *) (uintptr_t) ev[i].kioe_obj, ++ ev[i].kioe_res, ev[i].kioe_res2); ++ } ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ } ++ return NULL; ++} ++ ++static int ++internal_function ++add_request_to_list (struct requestlist *newp, int fildes, int prio) ++{ ++ struct requestlist *last, *runp, *reqs; ++ ++ last = NULL; ++ reqs = newp->kioctx != KCTX_NONE ? krequests : requests; ++ runp = reqs; ++ ++ /* First look whether the current file descriptor is currently ++ worked with. */ ++ while (runp != NULL ++ && runp->aiocbp->aiocb.aio_fildes < fildes) ++ { ++ last = runp; ++ runp = runp->next_fd; ++ } ++ ++ if (runp != NULL ++ && runp->aiocbp->aiocb.aio_fildes == fildes) ++ { ++ /* The current file descriptor is worked on. It makes no sense ++ to start another thread since this new thread would fight ++ with the running thread for the resources. But we also cannot ++ say that the thread processing this desriptor shall immediately ++ after finishing the current job process this request if there ++ are other threads in the running queue which have a higher ++ priority. */ ++ ++ /* Simply enqueue it after the running one according to the ++ priority. */ ++ while (runp->next_prio != NULL ++ && runp->next_prio->aiocbp->aiocb.__abs_prio >= prio) ++ runp = runp->next_prio; ++ ++ newp->next_prio = runp->next_prio; ++ runp->next_prio = newp; ++ if (newp->kioctx != KCTX_NONE) ++ { ++ newp->prev_prio = runp; ++ if (newp->next_prio != NULL) ++ newp->next_prio->prev_prio = newp; ++ } ++ return queued; ++ } ++ else ++ { ++ /* Enqueue this request for a new descriptor. */ ++ if (last == NULL) ++ { ++ newp->last_fd = NULL; ++ newp->next_fd = reqs; ++ if (reqs != NULL) ++ reqs->last_fd = newp; ++ if (newp->kioctx != KCTX_NONE) ++ krequests = newp; ++ else ++ requests = newp; ++ } ++ else ++ { ++ newp->next_fd = last->next_fd; ++ newp->last_fd = last; ++ last->next_fd = newp; ++ if (newp->next_fd != NULL) ++ newp->next_fd->last_fd = newp; ++ } ++ ++ newp->next_prio = NULL; ++ if (newp->kioctx != KCTX_NONE) ++ newp->prev_prio = NULL; ++ return yes; ++ } ++} ++ ++static int ++internal_function ++__aio_enqueue_user_request (struct requestlist *newp) ++{ ++ int result = 0; ++ int running = add_request_to_list (newp, newp->aiocbp->aiocb.aio_fildes, ++ newp->aiocbp->aiocb.__abs_prio); ++ ++ if (running == yes) ++ { ++ /* We try to create a new thread for this file descriptor. The ++ function which gets called will handle all available requests ++ for this descriptor and when all are processed it will ++ terminate. ++ ++ If no new thread can be created or if the specified limit of ++ threads for AIO is reached we queue the request. */ ++ ++ /* See if we need to and are able to create a thread. */ ++ if (nthreads < optim.aio_threads && idle_thread_count == 0) ++ { ++ pthread_t thid; ++ ++ running = newp->running = allocated; ++ ++ /* Now try to start a thread. */ ++ result = aio_create_helper_thread (&thid, handle_fildes_io, newp); ++ if (result == 0) ++ /* We managed to enqueue the request. All errors which can ++ happen now can be recognized by calls to `aio_return' and ++ `aio_error'. */ ++ ++nthreads; ++ else ++ { ++ /* Reset the running flag. The new request is not running. */ ++ running = newp->running = yes; ++ ++ if (nthreads == 0) ++ { ++ /* We cannot create a thread in the moment and there is ++ also no thread running. This is a problem. `errno' is ++ set to EAGAIN if this is only a temporary problem. */ ++ __aio_remove_request (NULL, newp, 0); ++ } ++ else ++ result = 0; ++ } ++ } ++ } ++ ++ /* Enqueue the request in the run queue if it is not yet running. */ ++ if (running == yes && result == 0) ++ { ++ add_request_to_runlist (newp); ++ ++ /* If there is a thread waiting for work, then let it know that we ++ have just given it something to do. */ ++ if (idle_thread_count > 0) ++ pthread_cond_signal (&__aio_new_request_notification); ++ } ++ ++ if (result == 0) ++ newp->running = running; ++ return result; ++} ++ ++/* The main function of the async I/O handling. It enqueues requests ++ and if necessary starts and handles threads. */ ++struct requestlist * ++internal_function ++__aio_enqueue_request_ctx (aiocb_union *aiocbp, int operation, kctx_t kctx) ++{ ++ int policy, prio, result; ++ struct sched_param param; ++ struct requestlist *newp; ++ int op = (operation & 0xffff); ++ ++ if (op == LIO_SYNC || op == LIO_DSYNC) ++ { ++ aiocbp->aiocb.aio_reqprio = 0; ++ /* FIXME: Kernel doesn't support sync yet. */ ++ operation &= ~LIO_KTHREAD; ++ kctx = KCTX_NONE; ++ } ++ else if (aiocbp->aiocb.aio_reqprio < 0 ++ || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX) ++ { ++ /* Invalid priority value. */ ++ __set_errno (EINVAL); ++ aiocbp->aiocb.__error_code = EINVAL; ++ aiocbp->aiocb.__return_value = -1; ++ return NULL; ++ } ++ ++ if ((operation & LIO_KTHREAD) || kctx != KCTX_NONE) ++ { ++ /* io_* is only really asynchronous for O_DIRECT or /dev/raw*. */ ++ int fl = __fcntl (aiocbp->aiocb.aio_fildes, F_GETFL); ++ if (fl < 0 || (fl & O_DIRECT) == 0) ++ { ++ struct stat64 st; ++ if (__fxstat64 (_STAT_VER, aiocbp->aiocb.aio_fildes, &st) < 0 ++ || ! S_ISCHR (st.st_mode) ++ || major (st.st_rdev) != 162) ++ { ++ operation &= ~LIO_KTHREAD; ++ kctx = KCTX_NONE; ++ } ++ } ++ } ++ ++ /* Compute priority for this request. */ ++ pthread_getschedparam (pthread_self (), &policy, ¶m); ++ prio = param.sched_priority - aiocbp->aiocb.aio_reqprio; ++ ++ /* Get the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ if (operation & LIO_KTHREAD) ++ { ++ if (__aio_kioctx == KCTX_NONE && !__have_no_kernel_aio) ++ { ++ int res; ++ INTERNAL_SYSCALL_DECL (err); ++ ++ __aio_kioctx = 0; ++ do ++ res = INTERNAL_SYSCALL (io_setup, err, 2, 1024, &__aio_kioctx); ++ while (INTERNAL_SYSCALL_ERROR_P (res, err) ++ && INTERNAL_SYSCALL_ERRNO (res, err) == EINTR); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ __have_no_kernel_aio = 1; ++ __aio_kioctx = KCTX_NONE; ++ } ++ } ++ ++ kctx = __aio_kioctx; ++ ++ if (kctx != KCTX_NONE && !__kernel_thread_started ++ && ((operation & LIO_KTHREAD_REQUIRED) ++ || aiocbp->aiocb.aio_sigevent.sigev_notify != SIGEV_NONE)) ++ { ++ if (__aio_create_kernel_thread () < 0) ++ kctx = KCTX_NONE; ++ } ++ } ++ ++ /* Get a new element for the waiting list. */ ++ newp = get_elem (); ++ if (newp == NULL) ++ { ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ __set_errno (EAGAIN); ++ return NULL; ++ } ++ newp->aiocbp = aiocbp; ++#ifdef BROKEN_THREAD_SIGNALS ++ newp->caller_pid = (aiocbp->aiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL ++ ? getpid () : 0); ++#endif ++ newp->waiting = NULL; ++ newp->kioctx = kctx; ++ ++ aiocbp->aiocb.__abs_prio = prio; ++ aiocbp->aiocb.__policy = policy; ++ aiocbp->aiocb.aio_lio_opcode = op; ++ aiocbp->aiocb.__error_code = EINPROGRESS; ++ aiocbp->aiocb.__return_value = 0; ++ ++ if (newp->kioctx != KCTX_NONE) ++ { ++ int res; ++ INTERNAL_SYSCALL_DECL (err); ++ ++ aiocb_union *aiocbp = newp->aiocbp; ++ struct kiocb *kiocbs[] __attribute__((unused)) = { &newp->kiocb }; ++ ++ newp->kiocb.kiocb_data = (uintptr_t) kernel_callback; ++ switch (op & 127) ++ { ++ case LIO_READ: newp->kiocb.kiocb_lio_opcode = IO_CMD_PREAD; break; ++ case LIO_WRITE: newp->kiocb.kiocb_lio_opcode = IO_CMD_PWRITE; break; ++ case LIO_SYNC: ++ case LIO_DSYNC: newp->kiocb.kiocb_lio_opcode = IO_CMD_FSYNC; break; ++ } ++ if (op & 128) ++ newp->kiocb.kiocb_offset = aiocbp->aiocb64.aio_offset; ++ else ++ newp->kiocb.kiocb_offset = aiocbp->aiocb.aio_offset; ++ newp->kiocb.kiocb_fildes = aiocbp->aiocb.aio_fildes; ++ newp->kiocb.kiocb_buf = (uintptr_t) aiocbp->aiocb.aio_buf; ++ newp->kiocb.kiocb_nbytes = aiocbp->aiocb.aio_nbytes; ++ /* FIXME. */ ++ newp->kiocb.kiocb_req_prio = 0; ++ res = INTERNAL_SYSCALL (io_submit, err, 3, newp->kioctx, 1, kiocbs); ++ if (! INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ newp->running = allocated; ++ add_request_to_list (newp, aiocbp->aiocb.aio_fildes, prio); ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ return newp; ++ } ++ newp->kioctx = KCTX_NONE; ++ } ++ ++ result = __aio_enqueue_user_request (newp); ++ if (result) ++ { ++ /* Something went wrong. */ ++ __aio_free_request (newp); ++ aiocbp->aiocb.__error_code = result; ++ __set_errno (result); ++ newp = NULL; ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ return newp; ++} ++ ++ ++static int ++wait_for_kernel_requests (int fildes) ++{ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ struct requestlist *kreq = __aio_find_kreq_fd (fildes), *req; ++ int nent = 0; ++ int ret = 0; ++ ++ req = kreq; ++ while (req) ++ { ++ if (req->running == allocated) ++ ++nent; ++ req = req->next_prio; ++ } ++ ++ if (nent) ++ { ++ if (__aio_create_kernel_thread () < 0) ++ { ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ return -1; ++ } ++ ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t cond = PTHREAD_COND_INITIALIZER; ++#endif ++ struct waitlist waitlist[nent]; ++ int cnt = 0; ++ ++ while (kreq) ++ { ++ if (kreq->running == allocated) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ waitlist[cnt].cond = &cond; ++#endif ++ waitlist[cnt].result = NULL; ++ waitlist[cnt].next = kreq->waiting; ++ waitlist[cnt].counterp = &nent; ++ waitlist[cnt].sigevp = NULL; ++#ifdef BROKEN_THREAD_SIGNALS ++ waitlist[cnt].caller_pid = 0; /* Not needed. */ ++#endif ++ kreq->waiting = &waitlist[cnt++]; ++ } ++ kreq = kreq->next_prio; ++ } ++ ++#ifdef DONT_NEED_AIO_MISC_COND ++ AIO_MISC_WAIT (ret, nent, NULL, 0); ++#else ++ do ++ pthread_cond_wait (&cond, &__aio_requests_mutex); ++ while (nent); ++ ++ pthread_cond_destroy (&cond); ++#endif ++ } ++ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ return ret; ++} ++ ++ ++static void * ++handle_fildes_io (void *arg) ++{ ++ pthread_t self = pthread_self (); ++ struct sched_param param; ++ struct requestlist *runp = (struct requestlist *) arg; ++ aiocb_union *aiocbp; ++ int policy; ++ int fildes; ++ ++ pthread_getschedparam (self, &policy, ¶m); ++ ++ do ++ { ++ /* If runp is NULL, then we were created to service the work queue ++ in general, not to handle any particular request. In that case we ++ skip the "do work" stuff on the first pass, and go directly to the ++ "get work off the work queue" part of this loop, which is near the ++ end. */ ++ if (runp == NULL) ++ pthread_mutex_lock (&__aio_requests_mutex); ++ else ++ { ++ /* Hopefully this request is marked as running. */ ++ assert (runp->running == allocated); ++ ++ /* Update our variables. */ ++ aiocbp = runp->aiocbp; ++ fildes = aiocbp->aiocb.aio_fildes; ++ ++ /* Change the priority to the requested value (if necessary). */ ++ if (aiocbp->aiocb.__abs_prio != param.sched_priority ++ || aiocbp->aiocb.__policy != policy) ++ { ++ param.sched_priority = aiocbp->aiocb.__abs_prio; ++ policy = aiocbp->aiocb.__policy; ++ pthread_setschedparam (self, policy, ¶m); ++ } ++ ++ /* Process request pointed to by RUNP. We must not be disturbed ++ by signals. */ ++ if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_READ) ++ { ++ if (aiocbp->aiocb.aio_lio_opcode & 128) ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (__pread64 (fildes, (void *) ++ aiocbp->aiocb64.aio_buf, ++ aiocbp->aiocb64.aio_nbytes, ++ aiocbp->aiocb64.aio_offset)); ++ else ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (pread (fildes, ++ (void *) aiocbp->aiocb.aio_buf, ++ aiocbp->aiocb.aio_nbytes, ++ aiocbp->aiocb.aio_offset)); ++ ++ if (aiocbp->aiocb.__return_value == -1 && errno == ESPIPE) ++ /* The Linux kernel is different from others. It returns ++ ESPIPE if using pread on a socket. Other platforms ++ simply ignore the offset parameter and behave like ++ read. */ ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (read (fildes, ++ (void *) aiocbp->aiocb64.aio_buf, ++ aiocbp->aiocb64.aio_nbytes)); ++ } ++ else if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_WRITE) ++ { ++ if (aiocbp->aiocb.aio_lio_opcode & 128) ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (__pwrite64 (fildes, (const void *) ++ aiocbp->aiocb64.aio_buf, ++ aiocbp->aiocb64.aio_nbytes, ++ aiocbp->aiocb64.aio_offset)); ++ else ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (__libc_pwrite (fildes, (const void *) ++ aiocbp->aiocb.aio_buf, ++ aiocbp->aiocb.aio_nbytes, ++ aiocbp->aiocb.aio_offset)); ++ ++ if (aiocbp->aiocb.__return_value == -1 && errno == ESPIPE) ++ /* The Linux kernel is different from others. It returns ++ ESPIPE if using pwrite on a socket. Other platforms ++ simply ignore the offset parameter and behave like ++ write. */ ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (write (fildes, ++ (void *) aiocbp->aiocb64.aio_buf, ++ aiocbp->aiocb64.aio_nbytes)); ++ } ++ else if (aiocbp->aiocb.aio_lio_opcode == LIO_DSYNC ++ || aiocbp->aiocb.aio_lio_opcode == LIO_SYNC) ++ { ++ if (wait_for_kernel_requests (fildes) < 0) ++ { ++ aiocbp->aiocb.__return_value = -1; ++ __set_errno (ENOMEM); ++ } ++ else if (aiocbp->aiocb.aio_lio_opcode == LIO_DSYNC) ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (fdatasync (fildes)); ++ else ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (fsync (fildes)); ++ } ++ else ++ { ++ /* This is an invalid opcode. */ ++ aiocbp->aiocb.__return_value = -1; ++ __set_errno (EINVAL); ++ } ++ ++ /* Get the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ /* In theory we would need here a write memory barrier since the ++ callers test using aio_error() whether the request finished ++ and once this value != EINPROGRESS the field __return_value ++ must be committed to memory. ++ ++ But since the pthread_mutex_lock call involves write memory ++ barriers as well it is not necessary. */ ++ ++ if (aiocbp->aiocb.__return_value == -1) ++ aiocbp->aiocb.__error_code = errno; ++ else ++ aiocbp->aiocb.__error_code = 0; ++ ++ /* Send the signal to notify about finished processing of the ++ request. */ ++ __aio_notify (runp); ++ ++ /* For debugging purposes we reset the running flag of the ++ finished request. */ ++ assert (runp->running == allocated); ++ runp->running = done; ++ ++ /* Now dequeue the current request. */ ++ __aio_remove_request (NULL, runp, 0); ++ if (runp->next_prio != NULL) ++ add_request_to_runlist (runp->next_prio); ++ ++ /* Free the old element. */ ++ __aio_free_request (runp); ++ } ++ ++ runp = runlist; ++ ++ /* If the runlist is empty, then we sleep for a while, waiting for ++ something to arrive in it. */ ++ if (runp == NULL && optim.aio_idle_time >= 0) ++ { ++ struct timeval now; ++ struct timespec wakeup_time; ++ ++ ++idle_thread_count; ++ gettimeofday (&now, NULL); ++ wakeup_time.tv_sec = now.tv_sec + optim.aio_idle_time; ++ wakeup_time.tv_nsec = now.tv_usec * 1000; ++ if (wakeup_time.tv_nsec > 1000000000) ++ { ++ wakeup_time.tv_nsec -= 1000000000; ++ ++wakeup_time.tv_sec; ++ } ++ pthread_cond_timedwait (&__aio_new_request_notification, ++ &__aio_requests_mutex, ++ &wakeup_time); ++ --idle_thread_count; ++ runp = runlist; ++ } ++ ++ if (runp == NULL) ++ --nthreads; ++ else ++ { ++ assert (runp->running == yes); ++ runp->running = allocated; ++ runlist = runp->next_run; ++ ++ /* If we have a request to process, and there's still another in ++ the run list, then we need to either wake up or create a new ++ thread to service the request that is still in the run list. */ ++ if (runlist != NULL) ++ { ++ /* There are at least two items in the work queue to work on. ++ If there are other idle threads, then we should wake them ++ up for these other work elements; otherwise, we should try ++ to create a new thread. */ ++ if (idle_thread_count > 0) ++ pthread_cond_signal (&__aio_new_request_notification); ++ else if (nthreads < optim.aio_threads) ++ { ++ pthread_t thid; ++ ++ /* Now try to start a thread. If we fail, no big deal, ++ because we know that there is at least one thread (us) ++ that is working on AIO operations. */ ++ if (aio_create_helper_thread (&thid, handle_fildes_io, NULL) ++ == 0) ++ ++nthreads; ++ } ++ } ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ } ++ while (runp != NULL); ++ ++ return NULL; ++} ++ ++ ++/* Free allocated resources. */ ++libc_freeres_fn (free_res) ++{ ++ size_t row; ++ ++ for (row = 0; row < pool_max_size; ++row) ++ free (pool[row]); ++ ++ free (pool); ++} ++ ++ ++/* Add newrequest to the runlist. The __abs_prio flag of newrequest must ++ be correctly set to do this. Also, you had better set newrequest's ++ "running" flag to "yes" before you release your lock or you'll throw an ++ assertion. */ ++static void ++internal_function ++add_request_to_runlist (struct requestlist *newrequest) ++{ ++ int prio = newrequest->aiocbp->aiocb.__abs_prio; ++ struct requestlist *runp; ++ ++ if (runlist == NULL || runlist->aiocbp->aiocb.__abs_prio < prio) ++ { ++ newrequest->next_run = runlist; ++ runlist = newrequest; ++ } ++ else ++ { ++ runp = runlist; ++ ++ while (runp->next_run != NULL ++ && runp->next_run->aiocbp->aiocb.__abs_prio >= prio) ++ runp = runp->next_run; ++ ++ newrequest->next_run = runp->next_run; ++ runp->next_run = newrequest; ++ } ++} ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,329 @@ ++/* Copyright (C) 1997,1999,2000,2001,2002,2003,2006 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#ifndef _AIO_MISC_H ++ ++#include ++ ++#if !defined __NR_io_setup || !defined __NR_io_destroy \ ++ || !defined __NR_io_getevents || !defined __NR_io_submit \ ++ || !defined __NR_io_cancel ++ ++#include ++ ++#else ++ ++#define _AIO_MISC_H 1 ++#define USE_KAIO 1 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_FORCED_UNWIND ++ ++/* We define a special synchronization primitive for AIO. POSIX ++ conditional variables would be ideal but the pthread_cond_*wait ++ operations do not return on EINTR. This is a requirement for ++ correct aio_suspend and lio_listio implementations. */ ++ ++#include ++#include ++#include ++ ++# define DONT_NEED_AIO_MISC_COND 1 ++ ++# define AIO_MISC_NOTIFY(waitlist) \ ++ do { \ ++ if (*waitlist->counterp > 0 && --*waitlist->counterp == 0) \ ++ lll_futex_wake (waitlist->counterp, 1, LLL_PRIVATE); \ ++ } while (0) ++ ++# define AIO_MISC_WAIT(result, futex, timeout, cancel) \ ++ do { \ ++ volatile int *futexaddr = &futex; \ ++ int oldval = futex; \ ++ \ ++ if (oldval != 0) \ ++ { \ ++ pthread_mutex_unlock (&__aio_requests_mutex); \ ++ \ ++ int oldtype; \ ++ if (cancel) \ ++ oldtype = LIBC_CANCEL_ASYNC (); \ ++ \ ++ int status; \ ++ do \ ++ { \ ++ status = lll_futex_timed_wait (futexaddr, oldval, timeout, \ ++ LLL_PRIVATE); \ ++ if (status != -EWOULDBLOCK) \ ++ break; \ ++ \ ++ oldval = *futexaddr; \ ++ } \ ++ while (oldval != 0); \ ++ \ ++ if (cancel) \ ++ LIBC_CANCEL_RESET (oldtype); \ ++ \ ++ if (status == -EINTR) \ ++ result = EINTR; \ ++ else if (status == -ETIMEDOUT) \ ++ result = EAGAIN; \ ++ else \ ++ assert (status == 0 || status == -EWOULDBLOCK); \ ++ \ ++ pthread_mutex_lock (&__aio_requests_mutex); \ ++ } \ ++ } while (0) ++ ++#endif ++ ++typedef unsigned long kctx_t; ++#define KCTX_NONE ~0UL ++extern kctx_t __aio_kioctx; ++ ++enum ++{ ++ IO_CMD_PREAD, ++ IO_CMD_PWRITE, ++ IO_CMD_FSYNC, ++ IO_CMD_FDSYNC, ++ IO_CMD_PREADX, ++ IO_CMD_POLL ++}; ++ ++struct kiocb ++{ ++ uint64_t kiocb_data; ++ uint64_t kiocb_key; ++ uint16_t kiocb_lio_opcode; ++ int16_t kiocb_req_prio; ++ uint32_t kiocb_fildes; ++ uint64_t kiocb_buf; ++ uint64_t kiocb_nbytes; ++ int64_t kiocb_offset; ++ int64_t __pad3, __pad4; ++}; ++ ++struct kio_event ++{ ++ uint64_t kioe_data; ++ uint64_t kioe_obj; ++ int64_t kioe_res; ++ int64_t kioe_res2; ++}; ++ ++/* Extend the operation enum. */ ++enum ++{ ++ LIO_DSYNC = LIO_NOP + 1, ++ LIO_SYNC, ++ LIO_READ64 = LIO_READ | 128, ++ LIO_WRITE64 = LIO_WRITE | 128, ++ LIO_KTHREAD = 0x10000, ++ LIO_KTHREAD_REQUIRED = 0x20000 ++}; ++ ++ ++/* Union of the two request types. */ ++typedef union ++ { ++ struct aiocb aiocb; ++ struct aiocb64 aiocb64; ++ } aiocb_union; ++ ++ ++/* Used to synchronize. */ ++struct waitlist ++ { ++ struct waitlist *next; ++ ++ /* The next two fields is used in synchronous io_listio' operations. */ ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t *cond; ++#endif ++ int *result; ++ ++ volatile int *counterp; ++ /* The next field is used in asynchronous `lio_listio' operations. */ ++ struct sigevent *sigevp; ++#ifdef BROKEN_THREAD_SIGNALS ++ /* XXX See requestlist, it's used to work around the broken signal ++ handling in Linux. */ ++ pid_t caller_pid; ++#endif ++ }; ++ ++ ++/* Status of a request. */ ++enum ++{ ++ no, ++ queued, ++ yes, ++ allocated, ++ done ++}; ++ ++ ++/* Used to queue requests.. */ ++struct requestlist ++ { ++ struct kiocb kiocb; ++ kctx_t kioctx; ++ ++ int running; ++ ++ struct requestlist *last_fd; ++ struct requestlist *next_fd; ++ struct requestlist *next_prio; ++ struct requestlist *next_run; ++ /* For kioctx != KCTX_NONE requests we are doubly linked. */ ++#define prev_prio next_run ++ ++ /* Pointer to the actual data. */ ++ aiocb_union *aiocbp; ++ ++#ifdef BROKEN_THREAD_SIGNALS ++ /* PID of the initiator thread. ++ XXX This is only necessary for the broken signal handling on Linux. */ ++ pid_t caller_pid; ++#endif ++ ++ /* List of waiting processes. */ ++ struct waitlist *waiting; ++ }; ++ ++ ++/* Lock for global I/O list of requests. */ ++extern pthread_mutex_t __aio_requests_mutex attribute_hidden; ++ ++ ++/* Enqueue request. */ ++extern struct requestlist *__aio_enqueue_request_ctx (aiocb_union *aiocbp, ++ int operation, ++ kctx_t kctx) ++ attribute_hidden internal_function; ++ ++#define __aio_enqueue_request(aiocbp, operation) \ ++ __aio_enqueue_request_ctx (aiocbp, operation | LIO_KTHREAD, KCTX_NONE) ++ ++/* Find request entry for given AIO control block. */ ++extern struct requestlist *__aio_find_req (aiocb_union *elem) ++ attribute_hidden internal_function; ++ ++/* Find request entry for given file descriptor. */ ++extern struct requestlist *__aio_find_req_fd (int fildes) ++ attribute_hidden internal_function; ++ ++/* Find request entry for given file descriptor. */ ++extern struct requestlist *__aio_find_kreq_fd (int fildes) ++ attribute_hidden internal_function; ++ ++/* Remove request from the list. */ ++extern void __aio_remove_request (struct requestlist *last, ++ struct requestlist *req, int all) ++ attribute_hidden internal_function; ++ ++extern void __aio_remove_krequest (struct requestlist *req) ++ attribute_hidden internal_function; ++ ++/* Release the entry for the request. */ ++extern void __aio_free_request (struct requestlist *req) ++ attribute_hidden internal_function; ++ ++/* Notify initiator of request and tell this everybody listening. */ ++extern void __aio_notify (struct requestlist *req) ++ attribute_hidden internal_function; ++ ++/* Notify initiator of request. */ ++#ifdef BROKEN_THREAD_SIGNALS ++extern int __aio_notify_only (struct sigevent *sigev, pid_t caller_pid) ++ attribute_hidden internal_function; ++#else ++extern int __aio_notify_only (struct sigevent *sigev) ++ attribute_hidden internal_function; ++#endif ++ ++/* Send the signal. */ ++extern int __aio_sigqueue (int sig, const union sigval val, pid_t caller_pid) ++ attribute_hidden internal_function; ++ ++extern int __aio_wait_for_events (kctx_t kctx, const struct timespec *timeout) ++ attribute_hidden internal_function; ++ ++extern void __aio_read_one_event (void) attribute_hidden internal_function; ++ ++extern int __aio_create_kernel_thread (void) ++ attribute_hidden internal_function; ++ ++extern int __have_no_kernel_aio attribute_hidden; ++extern int __kernel_thread_started attribute_hidden; ++ ++#ifndef BROKEN_THREAD_SIGNALS ++# define aio_start_notify_thread __aio_start_notify_thread ++# define aio_create_helper_thread __aio_create_helper_thread ++ ++extern inline void ++__aio_start_notify_thread (void) ++{ ++ sigset_t ss; ++ sigemptyset (&ss); ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); ++} ++ ++extern inline int ++__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg) ++{ ++ pthread_attr_t attr; ++ ++ /* Make sure the thread is created detached. */ ++ pthread_attr_init (&attr); ++ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); ++ ++ /* The helper thread needs only very little resources. */ ++ (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); ++ ++ /* Block all signals in the helper thread. To do this thoroughly we ++ temporarily have to block all signals here. */ ++ sigset_t ss; ++ sigset_t oss; ++ sigfillset (&ss); ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); ++ ++ int ret = pthread_create (threadp, &attr, tf, arg); ++ ++ /* Restore the signal mask. */ ++ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, ++ _NSIG / 8); ++ ++ (void) pthread_attr_destroy (&attr); ++ return ret; ++} ++#endif ++ ++#endif ++#endif /* aio_misc.h */ +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_notify.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_notify.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_notify.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_notify.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,2 @@ ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_read64.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_read64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_read64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_read64.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,2 @@ ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_read.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_read.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_read.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_read.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,4 @@ ++#define aio_read64 __renamed_aio_read64 ++#include ++#undef aio_read64 ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_return.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_return.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_return.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_return.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,50 @@ ++/* Return exit value of asynchronous I/O request. ++ Copyright (C) 1997, 2002, 2003 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++ ++/* We use an UGLY hack to prevent gcc from finding us cheating. The ++ implementation of aio_return and aio_return64 are identical and so ++ we want to avoid code duplication by using aliases. But gcc sees ++ the different parameter lists and prints a warning. We define here ++ a function so that aio_return64 has no prototype. */ ++#define aio_return64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_return64 ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++ ++ssize_t ++aio_return (aiocbp) ++ struct aiocb *aiocbp; ++{ ++ if (aiocbp->__error_code == EINPROGRESS) ++ __aio_read_one_event (); ++ return aiocbp->__return_value; ++} ++ ++weak_alias (aio_return, aio_return64) ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_sigqueue.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_sigqueue.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_sigqueue.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_sigqueue.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,2 @@ ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,327 @@ ++/* Suspend until termination of a requests. ++ Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2006 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++ ++/* We use an UGLY hack to prevent gcc from finding us cheating. The ++ implementations of aio_suspend and aio_suspend64 are identical and so ++ we want to avoid code duplication by using aliases. But gcc sees ++ the different parameter lists and prints a warning. We define here ++ a function so that aio_suspend64 has no prototype. */ ++#define aio_suspend64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_suspend64 ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++ ++struct clparam ++{ ++ const struct aiocb *const *list; ++ struct waitlist *waitlist; ++ struct requestlist **requestlist; ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t *cond; ++#endif ++ int nent; ++}; ++ ++ ++static void ++cleanup (void *arg) ++{ ++#ifdef DONT_NEED_AIO_MISC_COND ++ /* Acquire the mutex. If pthread_cond_*wait is used this would ++ happen implicitly. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++#endif ++ ++ const struct clparam *param = (const struct clparam *) arg; ++ ++ /* Now remove the entry in the waiting list for all requests ++ which didn't terminate. */ ++ int cnt = param->nent; ++ while (cnt-- > 0) ++ if (param->list[cnt] != NULL ++ && param->list[cnt]->__error_code == EINPROGRESS) ++ { ++ struct waitlist **listp; ++ ++ assert (param->requestlist[cnt] != NULL); ++ ++ /* There is the chance that we cannot find our entry anymore. This ++ could happen if the request terminated and restarted again. */ ++ listp = ¶m->requestlist[cnt]->waiting; ++ while (*listp != NULL && *listp != ¶m->waitlist[cnt]) ++ listp = &(*listp)->next; ++ ++ if (*listp != NULL) ++ *listp = (*listp)->next; ++ } ++ ++#ifndef DONT_NEED_AIO_MISC_COND ++ /* Release the conditional variable. */ ++ (void) pthread_cond_destroy (param->cond); ++#endif ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++} ++ ++ ++int ++aio_suspend (list, nent, timeout) ++ const struct aiocb *const list[]; ++ int nent; ++ const struct timespec *timeout; ++{ ++ if (__builtin_expect (nent < 0, 0)) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ struct waitlist waitlist[nent]; ++ struct requestlist *requestlist[nent]; ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t cond = PTHREAD_COND_INITIALIZER; ++#endif ++ int cnt; ++ int result = 0; ++ int cntr = 1; ++ int total = 0, ktotal = 0; ++ ++ /* Request the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ /* There is not yet a finished request. Signal the request that ++ we are working for it. */ ++ for (cnt = 0; cnt < nent; ++cnt) ++ if (list[cnt] != NULL) ++ { ++ if (list[cnt]->__error_code == EINPROGRESS) ++ { ++ requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]); ++ ++ if (requestlist[cnt] != NULL) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ waitlist[cnt].cond = &cond; ++#endif ++ waitlist[cnt].result = NULL; ++ waitlist[cnt].next = requestlist[cnt]->waiting; ++ waitlist[cnt].counterp = &cntr; ++ waitlist[cnt].sigevp = NULL; ++#ifdef BROKEN_THREAD_SIGNALS ++ waitlist[cnt].caller_pid = 0; /* Not needed. */ ++#endif ++ requestlist[cnt]->waiting = &waitlist[cnt]; ++ total++; ++ if (requestlist[cnt]->kioctx != KCTX_NONE) ++ ktotal++; ++ } ++ else ++ /* We will never suspend. */ ++ break; ++ } ++ else ++ /* We will never suspend. */ ++ break; ++ } ++ ++ ++ /* Only if none of the entries is NULL or finished to be wait. */ ++ if (cnt == nent && total) ++ { ++ struct clparam clparam = ++ { ++ .list = list, ++ .waitlist = waitlist, ++ .requestlist = requestlist, ++#ifndef DONT_NEED_AIO_MISC_COND ++ .cond = &cond, ++#endif ++ .nent = nent ++ }; ++ ++ pthread_cleanup_push (cleanup, &clparam); ++ ++ if (!__kernel_thread_started && ktotal) ++ { ++ /* If the kernel aio thread was not started yet all requests ++ are served by the kernel and there are no other threads running, ++ read events with mutex hold, so that nobody else can get them ++ instead of us here. */ ++ if (SINGLE_THREAD_P && total == ktotal) ++ { ++ if (timeout == NULL) ++ { ++ while (cntr == 1) ++ __aio_wait_for_events (__aio_kioctx, NULL); ++ } ++ else ++ { ++ struct timeval now; ++ struct timespec abstime, ts; ++ ++ __gettimeofday (&now, NULL); ++ abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000; ++ abstime.tv_sec = timeout->tv_sec + now.tv_sec; ++ if (abstime.tv_nsec >= 1000000000) ++ { ++ abstime.tv_nsec -= 1000000000; ++ abstime.tv_sec += 1; ++ } ++ ++ for (;;) ++ { ++ result = __aio_wait_for_events (__aio_kioctx, timeout); ++ if (cntr < 1) ++ break; ++ if (result == ETIMEDOUT) ++ break; ++ ++ __gettimeofday (&now, NULL); ++ if (now.tv_sec > abstime.tv_sec ++ || (now.tv_sec == abstime.tv_sec ++ && now.tv_usec * 1000 >= abstime.tv_nsec)) ++ break; ++ ++ ts.tv_nsec = abstime.tv_nsec - now.tv_usec * 1000; ++ ts.tv_sec = abstime.tv_sec - now.tv_sec; ++ if (abstime.tv_nsec < now.tv_usec * 1000) ++ { ++ ts.tv_nsec += 1000000000; ++ ts.tv_sec -= 1; ++ } ++ timeout = &ts; ++ } ++ ++ if (cntr < 1) ++ result = 0; ++ else ++ result = ETIMEDOUT; ++ } ++ total = 0; ++ } ++ else if (__aio_create_kernel_thread () < 0) ++ { ++ total = 0; ++ __set_errno (ENOMEM); ++ result = -1; ++ } ++ } ++ ++ if (total == 0) ++ /* Suspending was handled above. */ ++ ; ++#ifdef DONT_NEED_AIO_MISC_COND ++ else ++ AIO_MISC_WAIT (result, cntr, timeout, 1); ++#else ++ else if (timeout == NULL) ++ result = pthread_cond_wait (&cond, &__aio_requests_mutex); ++ else ++ { ++ /* We have to convert the relative timeout value into an ++ absolute time value with pthread_cond_timedwait expects. */ ++ struct timeval now; ++ struct timespec abstime; ++ ++ __gettimeofday (&now, NULL); ++ abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000; ++ abstime.tv_sec = timeout->tv_sec + now.tv_sec; ++ if (abstime.tv_nsec >= 1000000000) ++ { ++ abstime.tv_nsec -= 1000000000; ++ abstime.tv_sec += 1; ++ } ++ ++ result = pthread_cond_timedwait (&cond, &__aio_requests_mutex, ++ &abstime); ++ } ++#endif ++ ++ pthread_cleanup_pop (0); ++ } ++ ++ /* Now remove the entry in the waiting list for all requests ++ which didn't terminate. */ ++ while (cnt-- > 0) ++ if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS) ++ { ++ struct waitlist **listp; ++ ++ assert (requestlist[cnt] != NULL); ++ ++ /* There is the chance that we cannot find our entry anymore. This ++ could happen if the request terminated and restarted again. */ ++ listp = &requestlist[cnt]->waiting; ++ while (*listp != NULL && *listp != &waitlist[cnt]) ++ listp = &(*listp)->next; ++ ++ if (*listp != NULL) ++ *listp = (*listp)->next; ++ } ++ ++#ifndef DONT_NEED_AIO_MISC_COND ++ /* Release the conditional variable. */ ++ if (__builtin_expect (pthread_cond_destroy (&cond) != 0, 0)) ++ /* This must never happen. */ ++ abort (); ++#endif ++ ++ if (result != 0) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ /* An error occurred. Possibly it's ETIMEDOUT. We have to translate ++ the timeout error report of `pthread_cond_timedwait' to the ++ form expected from `aio_suspend'. */ ++ if (result == ETIMEDOUT) ++ __set_errno (EAGAIN); ++ else ++#endif ++ __set_errno (result); ++ ++ result = -1; ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ return result; ++} ++ ++weak_alias (aio_suspend, aio_suspend64) ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_write64.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_write64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_write64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_write64.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,2 @@ ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_write.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_write.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_write.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_write.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,4 @@ ++#define aio_write64 __renamed_aio_write64 ++#include ++#undef aio_write64 ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/klio_listio64.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/klio_listio64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/klio_listio64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/klio_listio64.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,40 @@ ++/* Enqueue and list of read or write requests, 64bit offset version. ++ Copyright (C) 1997, 1998, 1999, 2003, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define lio_listio lio_listio64 ++#define __lio_listio_21 __lio_listio64_21 ++#define __lio_listio_item_notify __lio_listio64_item_notify ++#define aiocb aiocb64 ++#define LIO_OPCODE_BASE 128 ++#include ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/klio_listio.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/klio_listio.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/klio_listio.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/klio_listio.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,322 @@ ++/* Enqueue and list of read or write requests. ++ Copyright (C) 1997,1998,1999,2000,2001,2002,2003,2005,2006 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#ifndef lio_listio ++#include ++#include ++#include ++#include ++#include ++ ++#define LIO_OPCODE_BASE 0 ++#endif ++ ++#include ++ ++ ++/* We need this special structure to handle asynchronous I/O. */ ++struct async_waitlist ++ { ++ int counter; ++ struct sigevent sigev; ++ struct waitlist list[0]; ++ }; ++ ++ ++/* The code in glibc 2.1 to glibc 2.4 issued only one event when all ++ requests submitted with lio_listio finished. The existing practice ++ is to issue events for the individual requests as well. This is ++ what the new code does. */ ++#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_4) ++# define LIO_MODE(mode) ((mode) & 127) ++# define NO_INDIVIDUAL_EVENT_P(mode) ((mode) & 128) ++#else ++# define LIO_MODE(mode) mode ++# define NO_INDIVIDUAL_EVENT_P(mode) 0 ++#endif ++ ++ ++static int ++lio_listio_internal (int mode, struct aiocb *const list[], int nent, ++ struct sigevent *sig) ++{ ++ struct sigevent defsigev; ++ struct requestlist *requests[nent]; ++ int cnt; ++ volatile int total = 0; ++ int result = 0, op = 0; ++ kctx_t kctx = KCTX_NONE; ++ ++ if (sig == NULL) ++ { ++ defsigev.sigev_notify = SIGEV_NONE; ++ sig = &defsigev; ++ } ++ ++ /* Request the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ if (LIO_MODE (mode) == LIO_WAIT && ! __have_no_kernel_aio && nent > 0) ++ { ++ int res; ++ INTERNAL_SYSCALL_DECL (err); ++ ++ kctx = 0; ++ do ++ res = INTERNAL_SYSCALL (io_setup, err, 2, nent, &kctx); ++ while (INTERNAL_SYSCALL_ERROR_P (res, err) ++ && INTERNAL_SYSCALL_ERRNO (res, err) == EINTR); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ kctx = KCTX_NONE; ++ if (INTERNAL_SYSCALL_ERRNO (res, err) == ENOSYS) ++ __have_no_kernel_aio = 1; ++ } ++ } ++ else if (LIO_MODE (mode) == LIO_NOWAIT) ++ { ++ op = LIO_KTHREAD; ++ if (sig->sigev_notify != SIGEV_NONE) ++ op = LIO_KTHREAD | LIO_KTHREAD_REQUIRED; ++ } ++ op |= LIO_OPCODE_BASE; ++ ++ /* Now we can enqueue all requests. Since we already acquired the ++ mutex the enqueue function need not do this. */ ++ for (cnt = 0; cnt < nent; ++cnt) ++ if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP) ++ { ++ if (NO_INDIVIDUAL_EVENT_P (mode)) ++ list[cnt]->aio_sigevent.sigev_notify = SIGEV_NONE; ++ requests[cnt] ++ = __aio_enqueue_request_ctx ((aiocb_union *) list[cnt], ++ list[cnt]->aio_lio_opcode | op, ++ kctx); ++ ++ if (requests[cnt] != NULL) ++ /* Successfully enqueued. */ ++ ++total; ++ else ++ /* Signal that we've seen an error. `errno' and the error code ++ of the aiocb will tell more. */ ++ result = -1; ++ } ++ else ++ requests[cnt] = NULL; ++ ++ if (total == 0) ++ { ++ /* We don't have anything to do except signalling if we work ++ asynchronously. */ ++ ++ if (kctx != KCTX_NONE) ++ { ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL (io_destroy, err, 1, kctx); ++ } ++ ++ /* Release the mutex. We do this before raising a signal since the ++ signal handler might do a `siglongjmp' and then the mutex is ++ locked forever. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ if (LIO_MODE (mode) == LIO_NOWAIT) ++ { ++#ifdef BROKEN_THREAD_SIGNALS ++ __aio_notify_only (sig, ++ sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0); ++#else ++ __aio_notify_only (sig); ++#endif ++ } ++ ++ return result; ++ } ++ else if (LIO_MODE (mode) == LIO_WAIT) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t cond = PTHREAD_COND_INITIALIZER; ++ int oldstate; ++#endif ++ struct waitlist waitlist[nent]; ++ volatile int ktotal = 0; ++ ++ total = 0; ++ for (cnt = 0; cnt < nent; ++cnt) ++ { ++ assert (requests[cnt] == NULL || list[cnt] != NULL); ++ ++ if (requests[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP) ++ { ++ if (requests[cnt]->kioctx != KCTX_NONE) ++ { ++ assert (requests[cnt]->kioctx == kctx); ++ waitlist[cnt].counterp = &ktotal; ++ ++ktotal; ++ } ++ else ++ { ++ waitlist[cnt].counterp = &total; ++ ++total; ++ } ++#ifndef DONT_NEED_AIO_MISC_COND ++ waitlist[cnt].cond = &cond; ++#endif ++ waitlist[cnt].result = &result; ++ waitlist[cnt].next = requests[cnt]->waiting; ++ waitlist[cnt].sigevp = NULL; ++#ifdef BROKEN_THREAD_SIGNALS ++ waitlist[cnt].caller_pid = 0; /* Not needed. */ ++#endif ++ requests[cnt]->waiting = &waitlist[cnt]; ++ } ++ } ++ ++ while (ktotal > 0) ++ __aio_wait_for_events (kctx, NULL); ++#ifdef DONT_NEED_AIO_MISC_COND ++ AIO_MISC_WAIT (result, total, NULL, 0); ++#else ++ /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancellation ++ points we must be careful. We added entries to the waiting lists ++ which we must remove. So defer cancellation for now. */ ++ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); ++ ++ while (total > 0) ++ pthread_cond_wait (&cond, &__aio_requests_mutex); ++ ++ /* Now it's time to restore the cancellation state. */ ++ pthread_setcancelstate (oldstate, NULL); ++ ++ /* Release the conditional variable. */ ++ if (pthread_cond_destroy (&cond) != 0) ++ /* This must never happen. */ ++ abort (); ++#endif ++ ++ if (kctx != KCTX_NONE) ++ { ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL (io_destroy, err, 1, kctx); ++ } ++ ++ /* If any of the I/O requests failed, return -1 and set errno. */ ++ if (result != 0) ++ { ++ __set_errno (result == EINTR ? EINTR : EIO); ++ result = -1; ++ } ++ } ++ else if (sig->sigev_notify != SIGEV_NONE) ++ { ++ struct async_waitlist *waitlist; ++ ++ waitlist = (struct async_waitlist *) ++ malloc (sizeof (struct async_waitlist) ++ + (nent * sizeof (struct waitlist))); ++ ++ if (waitlist == NULL) ++ { ++ __set_errno (EAGAIN); ++ result = -1; ++ } ++ else ++ { ++#ifdef BROKEN_THREAD_SIGNALS ++ pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0; ++#endif ++ total = 0; ++ ++ for (cnt = 0; cnt < nent; ++cnt) ++ { ++ assert (requests[cnt] == NULL || list[cnt] != NULL); ++ ++ if (requests[cnt] != NULL ++ && list[cnt]->aio_lio_opcode != LIO_NOP) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ waitlist->list[cnt].cond = NULL; ++#endif ++ waitlist->list[cnt].result = NULL; ++ waitlist->list[cnt].next = requests[cnt]->waiting; ++ waitlist->list[cnt].counterp = &waitlist->counter; ++ waitlist->list[cnt].sigevp = &waitlist->sigev; ++#ifdef BROKEN_THREAD_SIGNALS ++ waitlist->list[cnt].caller_pid = caller_pid; ++#endif ++ requests[cnt]->waiting = &waitlist->list[cnt]; ++ ++total; ++ } ++ } ++ ++ waitlist->counter = total; ++ waitlist->sigev = *sig; ++ } ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ return result; ++} ++ ++ ++#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_4) ++int ++attribute_compat_text_section ++__lio_listio_21 (int mode, struct aiocb *const list[], int nent, ++ struct sigevent *sig) ++{ ++ /* Check arguments. */ ++ if (mode != LIO_WAIT && mode != LIO_NOWAIT) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ return lio_listio_internal (mode | LIO_NO_INDIVIDUAL_EVENT, list, nent, sig); ++} ++compat_symbol (librt, __lio_listio_21, lio_listio, GLIBC_2_1); ++#endif ++ ++ ++int ++__lio_listio_item_notify (int mode, struct aiocb *const list[], int nent, ++ struct sigevent *sig) ++{ ++ /* Check arguments. */ ++ if (mode != LIO_WAIT && mode != LIO_NOWAIT) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ return lio_listio_internal (mode, list, nent, sig); ++} ++versioned_symbol (librt, __lio_listio_item_notify, lio_listio, GLIBC_2_4); ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/Makefile 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,4 @@ ++ifeq ($(subdir),rtkaio) ++CFLAGS-kaio_mq_send.c += -fexceptions ++CFLAGS-kaio_mq_receive.c += -fexceptions ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/s390-64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/s390-64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/s390-64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/s390-64/Versions 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/kaio_cancel.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/kaio_cancel.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/kaio_cancel.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/kaio_cancel.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,33 @@ ++#include ++ ++#define aio_cancel64 XXX ++#include ++#undef aio_cancel64 ++#include ++ ++extern __typeof (aio_cancel) __new_aio_cancel; ++extern __typeof (aio_cancel) __old_aio_cancel; ++ ++#define aio_cancel __new_aio_cancel ++ ++#include ++ ++#undef aio_cancel ++strong_alias (__new_aio_cancel, __new_aio_cancel64); ++versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); ++versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); ++ ++#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) ++ ++#undef ECANCELED ++#define aio_cancel __old_aio_cancel ++#define ECANCELED 125 ++ ++#include ++ ++#undef aio_cancel ++strong_alias (__old_aio_cancel, __old_aio_cancel64); ++compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); ++compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/Makefile 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/sparc64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/sparc64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/sparc64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/sparc64/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,6 @@ ++librtkaio { ++ GLIBC_2.3 { ++ # AIO functions. ++ aio_cancel; aio_cancel64; ++ } ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/syscalls.list glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/syscalls.list +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/syscalls.list 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/syscalls.list 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,5 @@ ++# File name Caller Syscall name Args Strong name Weak names ++ ++kaio_mq_timedsend - mq_timedsend Ci:ipiip __GI_mq_timedsend mq_timedsend ++kaio_mq_timedreceive - mq_timedreceive Ci:ipipp __GI_mq_timedreceive mq_timedreceive ++kaio_mq_setattr - mq_getsetattr i:ipp __GI_mq_setattr mq_setattr +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/x86_64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/x86_64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/x86_64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/x86_64/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio10.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio10.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio10.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio10.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio2.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio3.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio4.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio4.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio4.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio4.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio5.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio5.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio5.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio5.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio64.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio64.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio6.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio6.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio6.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio6.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio7.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio7.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio7.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio7.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio8.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio8.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio8.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio8.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio9.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio9.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio9.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio9.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod2.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1,128 @@ ++/* Test for notification mechanism in lio_listio. ++ Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 2000. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++ ++static pthread_barrier_t b; ++ ++ ++static void ++thrfct (sigval_t arg) ++{ ++ int e = pthread_barrier_wait (&b); ++ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) ++ { ++ puts ("thread: barrier_wait failed"); ++ exit (1); ++ } ++} ++ ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ char name[] = "/tmp/aio2.XXXXXX"; ++ int fd; ++ struct aiocb *arr[1]; ++ struct aiocb cb; ++ static const char buf[] = "Hello World\n"; ++ ++ fd = mkstemp (name); ++ if (fd == -1) ++ { ++ printf ("cannot open temp name: %m\n"); ++ return 1; ++ } ++ ++ unlink (name); ++ ++ if (pthread_barrier_init (&b, NULL, 2) != 0) ++ { ++ puts ("barrier_init failed"); ++ return 1; ++ } ++ ++ arr[0] = &cb; ++ ++ void *p; ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ int err = posix_memalign (&p, sz, sz); ++ if (err) ++ { ++ errno = err; ++ printf ("cannot allocate memory: %m\n"); ++ return 1; ++ } ++ memcpy (p, buf, sizeof (buf) - 1); ++ memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1); ++ printf ("Using O_DIRECT with block size %d\n", sz); ++ } ++ else ++ { ++ p = (void *) buf; ++ sz = sizeof (buf) - 1; ++ } ++ ++ cb.aio_fildes = fd; ++ cb.aio_lio_opcode = LIO_WRITE; ++ cb.aio_reqprio = 0; ++ cb.aio_buf = p; ++ cb.aio_nbytes = sz; ++ cb.aio_offset = 0; ++ cb.aio_sigevent.sigev_notify = SIGEV_THREAD; ++ cb.aio_sigevent.sigev_notify_function = thrfct; ++ cb.aio_sigevent.sigev_notify_attributes = NULL; ++ cb.aio_sigevent.sigev_value.sival_ptr = NULL; ++ ++ if (lio_listio (LIO_WAIT, arr, 1, NULL) < 0) ++ { ++ if (errno == ENOSYS) ++ { ++ puts ("no aio support in this configuration"); ++ return 0; ++ } ++ printf ("lio_listio failed: %m\n"); ++ return 1; ++ } ++ ++ puts ("lio_listio returned"); ++ ++ int e = pthread_barrier_wait (&b); ++ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) ++ { ++ puts ("barrier_wait failed"); ++ return 1; ++ } ++ ++ puts ("all OK"); ++ ++ return 0; ++} ++ ++#include "../test-skeleton.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod3.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,131 @@ ++/* Test for notification mechanism in lio_listio. ++ Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++ ++static pthread_barrier_t b; ++ ++ ++static void ++thrfct (sigval_t arg) ++{ ++ int e = pthread_barrier_wait (&b); ++ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) ++ { ++ puts ("child: barrier_wait failed"); ++ exit (1); ++ } ++} ++ ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ char name[] = "/tmp/aio3.XXXXXX"; ++ int fd; ++ struct aiocb *arr[1]; ++ struct aiocb cb; ++ static const char buf[] = "Hello World\n"; ++ ++ fd = mkstemp (name); ++ if (fd == -1) ++ { ++ printf ("cannot open temp name: %m\n"); ++ return 1; ++ } ++ ++ unlink (name); ++ ++ if (pthread_barrier_init (&b, NULL, 2) != 0) ++ { ++ puts ("barrier_init failed"); ++ return 1; ++ } ++ ++ arr[0] = &cb; ++ ++ void *p; ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ int err = posix_memalign (&p, sz, sz); ++ if (err) ++ { ++ errno = err; ++ printf ("cannot allocate memory: %m\n"); ++ return 1; ++ } ++ memcpy (p, buf, sizeof (buf) - 1); ++ memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1); ++ printf ("Using O_DIRECT with block size %d\n", sz); ++ } ++ else ++ { ++ p = (void *) buf; ++ sz = sizeof (buf) - 1; ++ } ++ ++ cb.aio_fildes = fd; ++ cb.aio_lio_opcode = LIO_WRITE; ++ cb.aio_reqprio = 0; ++ cb.aio_buf = p; ++ cb.aio_nbytes = sz; ++ cb.aio_offset = 0; ++ cb.aio_sigevent.sigev_notify = SIGEV_THREAD; ++ cb.aio_sigevent.sigev_notify_function = thrfct; ++ cb.aio_sigevent.sigev_notify_attributes = NULL; ++ cb.aio_sigevent.sigev_value.sival_ptr = NULL; ++ ++ if (lio_listio (LIO_NOWAIT, arr, 1, NULL) < 0) ++ { ++ if (errno == ENOSYS) ++ { ++ puts ("no aio support in this configuration"); ++ return 0; ++ } ++ printf ("lio_listio failed: %m\n"); ++ return 1; ++ } ++ ++ if (aio_suspend ((const struct aiocb *const *) arr, 1, NULL) < 0) ++ { ++ printf ("aio_suspend failed: %m\n"); ++ return 1; ++ } ++ ++ int e = pthread_barrier_wait (&b); ++ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) ++ { ++ puts ("parent: barrier_wait failed"); ++ return 1; ++ } ++ ++ puts ("all OK"); ++ ++ return 0; ++} ++ ++#include "../test-skeleton.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod4.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod4.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod4.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod4.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,182 @@ ++/* Test for completion signal handling. ++ Copyright (C) 2000, 2001, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++/* We might need a bit longer timeout. */ ++#define TIMEOUT 10 /* sec */ ++ ++int my_signo; ++ ++volatile sig_atomic_t flag; ++ ++ ++static void ++sighandler (const int signo) ++{ ++ flag = signo; ++} ++ ++static int ++wait_flag (void) ++{ ++ while (flag == 0) ++ { ++ puts ("Sleeping..."); ++ sleep (1); ++ } ++ ++ if (flag != my_signo) ++ { ++ printf ("signal handler received wrong signal, flag is %d\n", flag); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#ifndef SIGRTMIN ++# define SIGRTMIN -1 ++# define SIGRTMAX -1 ++#endif ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ char name[] = "/tmp/aio4.XXXXXX"; ++ int fd; ++ struct aiocb *arr[1]; ++ struct aiocb cb; ++ static const char buf[] = "Hello World\n"; ++ struct aioinit init = {10, 20, 0}; ++ struct sigaction sa; ++ struct sigevent ev; ++ ++ if (SIGRTMIN == -1) ++ { ++ printf ("RT signals not supported.\n"); ++ return 0; ++ } ++ ++ /* Select a signal from the middle of the available choices... */ ++ my_signo = (SIGRTMAX + SIGRTMIN) / 2; ++ ++ fd = mkstemp (name); ++ if (fd == -1) ++ { ++ printf ("cannot open temp name: %m\n"); ++ return 1; ++ } ++ ++ unlink (name); ++ ++ /* Test also aio_init. */ ++ aio_init (&init); ++ ++ arr[0] = &cb; ++ ++ void *p; ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ int err = posix_memalign (&p, sz, sz); ++ if (err) ++ { ++ errno = err; ++ printf ("cannot allocate memory: %m\n"); ++ return 1; ++ } ++ memcpy (p, buf, sizeof (buf) - 1); ++ memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1); ++ printf ("Using O_DIRECT with block size %d\n", sz); ++ } ++ else ++ { ++ p = (void *) buf; ++ sz = sizeof (buf) - 1; ++ } ++ ++ cb.aio_fildes = fd; ++ cb.aio_lio_opcode = LIO_WRITE; ++ cb.aio_reqprio = 0; ++ cb.aio_buf = p; ++ cb.aio_nbytes = sz; ++ cb.aio_offset = 0; ++ cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; ++ cb.aio_sigevent.sigev_notify_function = NULL; ++ cb.aio_sigevent.sigev_notify_attributes = NULL; ++ cb.aio_sigevent.sigev_signo = my_signo; ++ cb.aio_sigevent.sigev_value.sival_ptr = NULL; ++ ++ ev.sigev_notify = SIGEV_SIGNAL; ++ ev.sigev_notify_function = NULL; ++ ev.sigev_notify_attributes = NULL; ++ ev.sigev_signo = my_signo; ++ ++ sa.sa_handler = sighandler; ++ sigemptyset (&sa.sa_mask); ++ sa.sa_flags = SA_RESTART; ++ ++ if (sigaction (my_signo, &sa, NULL) < 0) ++ { ++ printf ("sigaction failed: %m\n"); ++ return 1; ++ } ++ ++ flag = 0; ++ /* First use aio_write. */ ++ if (aio_write (arr[0]) < 0) ++ { ++ if (errno == ENOSYS) ++ { ++ puts ("no aio support in this configuration"); ++ return 0; ++ } ++ printf ("aio_write failed: %m\n"); ++ return 1; ++ } ++ ++ if (wait_flag ()) ++ return 1; ++ ++ puts ("aio_write OK"); ++ ++ flag = 0; ++ /* Again with lio_listio. */ ++ if (lio_listio (LIO_NOWAIT, arr, 1, &ev) < 0) ++ { ++ printf ("lio_listio failed: %m\n"); ++ return 1; ++ } ++ ++ if (wait_flag ()) ++ return 1; ++ ++ puts ("all OK"); ++ ++ return 0; ++} ++ ++#include "../test-skeleton.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod5.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod5.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod5.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod5.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,152 @@ ++/* Test for completion thread handling. ++ Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++/* We might need a bit longer timeout. */ ++#define TIMEOUT 10 /* sec */ ++ ++#define MY_SIVAL 27 ++ ++volatile sig_atomic_t flag; ++ ++ ++static void ++callback (sigval_t s) ++{ ++ flag = s.sival_int; ++} ++ ++static int ++wait_flag (void) ++{ ++ while (flag == 0) ++ { ++ puts ("Sleeping..."); ++ sleep (1); ++ } ++ ++ if (flag != MY_SIVAL) ++ { ++ printf ("signal handler received wrong signal, flag is %d\n", flag); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ char name[] = "/tmp/aio5.XXXXXX"; ++ int fd; ++ struct aiocb *arr[1]; ++ struct aiocb cb; ++ static const char buf[] = "Hello World\n"; ++ struct sigevent ev; ++ ++ fd = mkstemp (name); ++ if (fd == -1) ++ { ++ printf ("cannot open temp name: %m\n"); ++ return 1; ++ } ++ ++ unlink (name); ++ ++ arr[0] = &cb; ++ ++ void *p; ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ int err = posix_memalign (&p, sz, sz); ++ if (err) ++ { ++ errno = err; ++ printf ("cannot allocate memory: %m\n"); ++ return 1; ++ } ++ memcpy (p, buf, sizeof (buf) - 1); ++ memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1); ++ printf ("Using O_DIRECT with block size %d\n", sz); ++ } ++ else ++ { ++ p = (void *) buf; ++ sz = sizeof (buf) - 1; ++ } ++ ++ cb.aio_fildes = fd; ++ cb.aio_lio_opcode = LIO_WRITE; ++ cb.aio_reqprio = 0; ++ cb.aio_buf = p; ++ cb.aio_nbytes = sz; ++ cb.aio_offset = 0; ++ cb.aio_sigevent.sigev_notify = SIGEV_THREAD; ++ cb.aio_sigevent.sigev_notify_function = callback; ++ cb.aio_sigevent.sigev_notify_attributes = NULL; ++ cb.aio_sigevent.sigev_value.sival_int = MY_SIVAL; ++ ++ ev.sigev_notify = SIGEV_THREAD; ++ ev.sigev_notify_function = callback; ++ ev.sigev_notify_attributes = NULL; ++ ev.sigev_value.sival_int = MY_SIVAL; ++ ++ /* First use aio_write. */ ++ if (aio_write (arr[0]) < 0) ++ { ++ if (errno == ENOSYS) ++ { ++ puts ("no aio support in this configuration"); ++ return 0; ++ } ++ printf ("aio_write failed: %m\n"); ++ return 1; ++ } ++ ++ if (wait_flag ()) ++ return 1; ++ ++ puts ("aio_write OK"); ++ ++ flag = 0; ++ /* Again with lio_listio. */ ++ if (lio_listio (LIO_NOWAIT, arr, 1, &ev) < 0) ++ { ++ printf ("lio_listio failed: %m\n"); ++ return 1; ++ } ++ ++ if (wait_flag ()) ++ return 1; ++ ++ puts ("all OK"); ++ ++ return 0; ++} ++ ++#include "../test-skeleton.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod64.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod64.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1,308 @@ ++/* Tests for 64bit AIO in librt. ++ Copyright (C) 1998, 1999, 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1998. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#define _LARGEFILE_SOURCE 1 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++ ++/* Prototype for our test function. */ ++extern void do_prepare (int argc, char *argv[]); ++extern int do_test (int argc, char *argv[]); ++ ++/* We have a preparation function. */ ++#define PREPARE do_prepare ++ ++/* We might need a bit longer timeout. */ ++#define TIMEOUT 20 /* sec */ ++ ++/* This defines the `main' function and some more. */ ++#include ++ ++ ++/* These are for the temporary file we generate. */ ++char *name; ++int fd; ++char *tmpbuf; ++int blksz = 100; ++ ++void ++do_prepare (int argc, char *argv[]) ++{ ++ size_t name_len; ++ ++ name_len = strlen (test_dir); ++ name = malloc (name_len + sizeof ("/aioXXXXXX")); ++ mempcpy (mempcpy (name, test_dir, name_len), ++ "/aioXXXXXX", sizeof ("/aioXXXXXX")); ++ add_temp_file (name); ++ ++ /* Open our test file. */ ++ fd = mkstemp (name); ++ if (fd == -1) ++ error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); ++ ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ blksz = sz; ++ printf ("Using O_DIRECT with block size %d\n", blksz); ++ } ++} ++ ++ ++static int ++test_file (const void *buf, size_t size, int fd, const char *msg) ++{ ++ struct stat st; ++ char *tmp = tmpbuf; ++ ++ errno = 0; ++ if (fstat (fd, &st) < 0) ++ { ++ error (0, errno, "%s: failed stat", msg); ++ return 1; ++ } ++ ++ if (st.st_size != (off_t) size) ++ { ++ error (0, errno, "%s: wrong size: %lu, should be %lu", ++ msg, (unsigned long int) st.st_size, (unsigned long int) size); ++ return 1; ++ } ++ ++ if (pread (fd, tmp, size, 0) != (ssize_t) size) ++ { ++ error (0, errno, "%s: failed pread", msg); ++ return 1; ++ } ++ ++ if (memcmp (buf, tmp, size) != 0) ++ { ++ error (0, errno, "%s: failed comparison", msg); ++ return 1; ++ } ++ ++ printf ("%s test ok\n", msg); ++ ++ return 0; ++} ++ ++ ++static int ++do_wait (struct aiocb64 **cbp, size_t nent, int allowed_err) ++{ ++ int go_on; ++ size_t cnt; ++ int result = 0; ++ ++ do ++ { ++ aio_suspend64 ((const struct aiocb64 *const *) cbp, nent, NULL); ++ go_on = 0; ++ for (cnt = 0; cnt < nent; ++cnt) ++ if (cbp[cnt] != NULL) ++ { ++ if (aio_error64 (cbp[cnt]) == EINPROGRESS) ++ go_on = 1; ++ else ++ { ++ if (aio_return64 (cbp[cnt]) == -1 ++ && (allowed_err == 0 ++ || aio_error64 (cbp[cnt]) != allowed_err)) ++ { ++ error (0, aio_error64 (cbp[cnt]), "Operation failed\n"); ++ result = 1; ++ } ++ cbp[cnt] = NULL; ++ } ++ } ++ } ++ while (go_on); ++ ++ return result; ++} ++ ++ ++int ++do_test (int argc, char *argv[]) ++{ ++ struct aiocb64 cbs[10]; ++ struct aiocb64 cbs_fsync; ++ struct aiocb64 *cbp[10]; ++ struct aiocb64 *cbp_fsync[1]; ++ char *buf; ++ size_t cnt; ++ int result = 0; ++ ++ buf = mmap (NULL, 20 * blksz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); ++ tmpbuf = buf + 10 * blksz; ++ if (buf == MAP_FAILED) ++ { ++ error (0, errno, "mmap failed"); ++ return 1; ++ } ++ ++ /* Preparation. */ ++ for (cnt = 0; cnt < 10; ++cnt) ++ { ++ cbs[cnt].aio_fildes = fd; ++ cbs[cnt].aio_reqprio = 0; ++ cbs[cnt].aio_buf = memset (&buf[cnt * blksz], '0' + cnt, blksz); ++ cbs[cnt].aio_nbytes = blksz; ++ cbs[cnt].aio_offset = cnt * blksz; ++ cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE; ++ ++ cbp[cnt] = &cbs[cnt]; ++ } ++ ++ /* First a simple test. */ ++ for (cnt = 10; cnt > 0; ) ++ if (aio_write64 (cbp[--cnt]) < 0 && errno == ENOSYS) ++ { ++ error (0, 0, "no aio support in this configuration"); ++ return 0; ++ } ++ /* Wait 'til the results are there. */ ++ result |= do_wait (cbp, 10, 0); ++ /* Test this. */ ++ result |= test_file (buf, 10 * blksz, fd, "aio_write"); ++ ++ /* Read now as we've written it. */ ++ memset (buf, '\0', 10 * blksz); ++ /* Issue the commands. */ ++ for (cnt = 10; cnt > 0; ) ++ { ++ --cnt; ++ cbp[cnt] = &cbs[cnt]; ++ aio_read64 (cbp[cnt]); ++ } ++ /* Wait 'til the results are there. */ ++ result |= do_wait (cbp, 10, 0); ++ /* Test this. */ ++ for (cnt = 0; cnt < 10 * blksz; ++cnt) ++ if (buf[cnt] != '0' + (cnt / blksz)) ++ { ++ result = 1; ++ error (0, 0, "comparison failed for aio_read test"); ++ break; ++ } ++ ++ if (cnt == 10 * blksz) ++ puts ("aio_read test ok"); ++ ++ /* Remove the test file contents. */ ++ if (ftruncate64 (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Test lio_listio. */ ++ for (cnt = 0; cnt < 10; ++cnt) ++ { ++ cbs[cnt].aio_lio_opcode = LIO_WRITE; ++ cbp[cnt] = &cbs[cnt]; ++ } ++ /* Issue the command. */ ++ lio_listio64 (LIO_WAIT, cbp, 10, NULL); ++ /* ...and immediately test it since we started it in wait mode. */ ++ result |= test_file (buf, 10 * blksz, fd, "lio_listio (write)"); ++ ++ /* Test aio_fsync. */ ++ cbs_fsync.aio_fildes = fd; ++ cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE; ++ cbp_fsync[0] = &cbs_fsync; ++ ++ /* Remove the test file contents first. */ ++ if (ftruncate64 (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ aio_write64 (cbp[--cnt]); ++ ++ if (aio_fsync64 (O_SYNC, &cbs_fsync) < 0) ++ { ++ error (0, errno, "aio_fsync failed\n"); ++ result = 1; ++ } ++ result |= do_wait (cbp_fsync, 1, 0); ++ ++ /* ...and test since all data should be on disk now. */ ++ result |= test_file (buf, 10 * blksz, fd, "aio_fsync (aio_write)"); ++ ++ /* Test aio_cancel. */ ++ /* Remove the test file contents first. */ ++ if (ftruncate64 (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ aio_write64 (cbp[--cnt]); ++ ++ /* Cancel all requests. */ ++ if (aio_cancel64 (fd, NULL) == -1) ++ printf ("aio_cancel64 (fd, NULL) cannot cancel anything\n"); ++ ++ result |= do_wait (cbp, 10, ECANCELED); ++ ++ /* Another test for aio_cancel. */ ++ /* Remove the test file contents first. */ ++ if (ftruncate64 (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ { ++ --cnt; ++ cbp[cnt] = &cbs[cnt]; ++ aio_write64 (cbp[cnt]); ++ } ++ puts ("finished3"); ++ ++ /* Cancel all requests. */ ++ for (cnt = 10; cnt > 0; ) ++ if (aio_cancel64 (fd, cbp[--cnt]) == -1) ++ /* This is not an error. The request can simply be finished. */ ++ printf ("aio_cancel64 (fd, cbp[%Zd]) cannot be canceled\n", cnt); ++ puts ("finished2"); ++ ++ result |= do_wait (cbp, 10, ECANCELED); ++ ++ puts ("finished"); ++ ++ return result; ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1,307 @@ ++/* Tests for AIO in librt. ++ Copyright (C) 1998, 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1998. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++ ++/* Prototype for our test function. */ ++extern void do_prepare (int argc, char *argv[]); ++extern int do_test (int argc, char *argv[]); ++ ++/* We have a preparation function. */ ++#define PREPARE do_prepare ++ ++/* We might need a bit longer timeout. */ ++#define TIMEOUT 20 /* sec */ ++ ++/* This defines the `main' function and some more. */ ++#include ++ ++ ++/* These are for the temporary file we generate. */ ++char *name; ++int fd; ++char *tmpbuf; ++int blksz = 100; ++ ++void ++do_prepare (int argc, char *argv[]) ++{ ++ size_t name_len; ++ ++ name_len = strlen (test_dir); ++ name = malloc (name_len + sizeof ("/aioXXXXXX")); ++ mempcpy (mempcpy (name, test_dir, name_len), ++ "/aioXXXXXX", sizeof ("/aioXXXXXX")); ++ add_temp_file (name); ++ ++ /* Open our test file. */ ++ fd = mkstemp (name); ++ if (fd == -1) ++ error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); ++ ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ blksz = sz; ++ printf ("Using O_DIRECT with block size %d\n", blksz); ++ } ++} ++ ++ ++static int ++test_file (const void *buf, size_t size, int fd, const char *msg) ++{ ++ struct stat st; ++ char *tmp = tmpbuf; ++ ++ errno = 0; ++ if (fstat (fd, &st) < 0) ++ { ++ error (0, errno, "%s: failed stat", msg); ++ return 1; ++ } ++ ++ if (st.st_size != (off_t) size) ++ { ++ error (0, errno, "%s: wrong size: %lu, should be %lu", ++ msg, (unsigned long int) st.st_size, (unsigned long int) size); ++ return 1; ++ } ++ ++ if (pread (fd, tmp, size, 0) != (ssize_t) size) ++ { ++ error (0, errno, "%s: failed pread", msg); ++ return 1; ++ } ++ ++ if (memcmp (buf, tmp, size) != 0) ++ { ++ error (0, errno, "%s: failed comparison", msg); ++ return 1; ++ } ++ ++ printf ("%s test ok\n", msg); ++ ++ return 0; ++} ++ ++ ++static int ++do_wait (struct aiocb **cbp, size_t nent, int allowed_err) ++{ ++ int go_on; ++ size_t cnt; ++ int result = 0; ++ ++ do ++ { ++ aio_suspend ((const struct aiocb *const *) cbp, nent, NULL); ++ go_on = 0; ++ for (cnt = 0; cnt < nent; ++cnt) ++ if (cbp[cnt] != NULL) ++ { ++ if (aio_error (cbp[cnt]) == EINPROGRESS) ++ go_on = 1; ++ else ++ { ++ if (aio_return (cbp[cnt]) == -1 ++ && (allowed_err == 0 ++ || aio_error (cbp[cnt]) != allowed_err)) ++ { ++ error (0, aio_error (cbp[cnt]), "Operation failed\n"); ++ result = 1; ++ } ++ cbp[cnt] = NULL; ++ } ++ } ++ } ++ while (go_on); ++ ++ return result; ++} ++ ++ ++int ++do_test (int argc, char *argv[]) ++{ ++ struct aiocb cbs[10]; ++ struct aiocb cbs_fsync; ++ struct aiocb *cbp[10]; ++ struct aiocb *cbp_fsync[1]; ++ char *buf; ++ size_t cnt; ++ int result = 0; ++ ++ buf = mmap (NULL, 20 * blksz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); ++ tmpbuf = buf + 10 * blksz; ++ if (buf == MAP_FAILED) ++ { ++ error (0, errno, "mmap failed"); ++ return 1; ++ } ++ ++ /* Preparation. */ ++ for (cnt = 0; cnt < 10; ++cnt) ++ { ++ cbs[cnt].aio_fildes = fd; ++ cbs[cnt].aio_reqprio = 0; ++ cbs[cnt].aio_buf = memset (&buf[cnt * blksz], '0' + cnt, blksz); ++ cbs[cnt].aio_nbytes = blksz; ++ cbs[cnt].aio_offset = cnt * blksz; ++ cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE; ++ ++ cbp[cnt] = &cbs[cnt]; ++ } ++ ++ /* First a simple test. */ ++ for (cnt = 10; cnt > 0; ) ++ if (aio_write (cbp[--cnt]) < 0 && errno == ENOSYS) ++ { ++ error (0, 0, "no aio support in this configuration"); ++ return 0; ++ } ++ /* Wait 'til the results are there. */ ++ result |= do_wait (cbp, 10, 0); ++ /* Test this. */ ++ result |= test_file (buf, 10 * blksz, fd, "aio_write"); ++ ++ /* Read now as we've written it. */ ++ memset (buf, '\0', 10 * blksz); ++ /* Issue the commands. */ ++ for (cnt = 10; cnt > 0; ) ++ { ++ --cnt; ++ cbp[cnt] = &cbs[cnt]; ++ aio_read (cbp[cnt]); ++ } ++ /* Wait 'til the results are there. */ ++ result |= do_wait (cbp, 10, 0); ++ /* Test this. */ ++ for (cnt = 0; cnt < 10 * blksz; ++cnt) ++ if (buf[cnt] != '0' + (cnt / blksz)) ++ { ++ result = 1; ++ error (0, 0, "comparison failed for aio_read test"); ++ break; ++ } ++ ++ if (cnt == 10 * blksz) ++ puts ("aio_read test ok"); ++ ++ /* Remove the test file contents. */ ++ if (ftruncate (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Test lio_listio. */ ++ for (cnt = 0; cnt < 10; ++cnt) ++ { ++ cbs[cnt].aio_lio_opcode = LIO_WRITE; ++ cbp[cnt] = &cbs[cnt]; ++ } ++ /* Issue the command. */ ++ lio_listio (LIO_WAIT, cbp, 10, NULL); ++ /* ...and immediately test it since we started it in wait mode. */ ++ result |= test_file (buf, 10 * blksz, fd, "lio_listio (write)"); ++ ++ /* Test aio_fsync. */ ++ cbs_fsync.aio_fildes = fd; ++ cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE; ++ cbp_fsync[0] = &cbs_fsync; ++ ++ /* Remove the test file contents first. */ ++ if (ftruncate (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ aio_write (cbp[--cnt]); ++ ++ if (aio_fsync (O_SYNC, &cbs_fsync) < 0) ++ { ++ error (0, errno, "aio_fsync failed\n"); ++ result = 1; ++ } ++ result |= do_wait (cbp_fsync, 1, 0); ++ ++ /* ...and test since all data should be on disk now. */ ++ result |= test_file (buf, 10 * blksz, fd, "aio_fsync (aio_write)"); ++ ++ /* Test aio_cancel. */ ++ /* Remove the test file contents first. */ ++ if (ftruncate (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ aio_write (cbp[--cnt]); ++ ++ /* Cancel all requests. */ ++ if (aio_cancel (fd, NULL) == -1) ++ printf ("aio_cancel (fd, NULL) cannot cancel anything\n"); ++ ++ result |= do_wait (cbp, 10, ECANCELED); ++ ++ /* Another test for aio_cancel. */ ++ /* Remove the test file contents first. */ ++ if (ftruncate (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ { ++ --cnt; ++ cbp[cnt] = &cbs[cnt]; ++ aio_write (cbp[cnt]); ++ } ++ puts ("finished3"); ++ ++ /* Cancel all requests. */ ++ for (cnt = 10; cnt > 0; ) ++ if (aio_cancel (fd, cbp[--cnt]) == -1) ++ /* This is not an error. The request can simply be finished. */ ++ printf ("aio_cancel (fd, cbp[%Zd]) cannot be canceled\n", cnt); ++ puts ("finished2"); ++ ++ result |= do_wait (cbp, 10, ECANCELED); ++ ++ puts ("finished"); ++ ++ return result; ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod.h glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod.h +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod.h 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod.h 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,53 @@ ++/* Tests for AIO in librt. ++ Copyright (C) 1998, 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1998. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++set_o_direct (int fd) ++{ ++ int ret = -1; ++#ifdef O_DIRECT ++ if (fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_DIRECT) >= 0) ++ { ++ int pgsz = sysconf (_SC_PAGESIZE); ++ char *buf = mmap (NULL, 16 * pgsz, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANON, -1, 0); ++ if (buf != MAP_FAILED) ++ { ++ memset (buf, 0, 16 * pgsz); ++ for (int sz = 256; sz <= 16 * pgsz; sz *= 2) ++ if (write (fd, buf, sz) > 0) ++ { ++ ret = sz; ++ break; ++ } ++ ftruncate64 (fd, 0); ++ munmap (buf, 16 * pgsz); ++ } ++ if (ret < 0) ++ fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) & ~O_DIRECT); ++ } ++#endif ++ return ret; ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-clock2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-clock2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock2.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-clock.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-clock.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-clock_nanosleep.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock_nanosleep.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-clock_nanosleep.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock_nanosleep.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cpuclock1.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cpuclock1.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cpuclock1.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cpuclock1.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cpuclock2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cpuclock2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cpuclock2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cpuclock2.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer1.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer1.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer1.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer1.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer2.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer3.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue1.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue1.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue1.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue1.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue2.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue3.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue4.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue4.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue4.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue4.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue5.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue5.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue5.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue5.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue6.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue6.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue6.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue6.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue7.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue7.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue7.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue7.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue8.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue8.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue8.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue8.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue9.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue9.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue9.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue9.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue.h glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue.h +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue.h 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue.h 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-shm.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-shm.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-shm.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-shm.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer2.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer3.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer4.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer4.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer4.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer4.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer5.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer5.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer5.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer5.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Versions 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1,25 @@ ++librtkaio { ++ GLIBC_2.1 { ++ # AIO functions. ++ aio_cancel; aio_cancel64; aio_error; aio_error64; aio_fsync; aio_fsync64; ++ aio_init; aio_read; aio_read64; aio_return; aio_return64; aio_suspend; ++ aio_suspend64; aio_write; aio_write64; lio_listio; lio_listio64; ++ } ++ GLIBC_2.2 { ++ # c* ++ clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; ++ clock_nanosleep; ++ ++ # s* ++ shm_open; shm_unlink; ++ ++ # t* ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++ GLIBC_2.3.4 { ++ # m* ++ mq_open; mq_close; mq_unlink; mq_getattr; mq_setattr; ++ mq_notify; mq_send; mq_receive; mq_timedsend; mq_timedreceive; ++ } ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Versions.def glibc-2.17-931-g30bbc0c.new/rtkaio/Versions.def +--- glibc-2.17-931-g30bbc0c/rtkaio/Versions.def 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Versions.def 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1,8 @@ ++librtkaio { ++ GLIBC_2.1 ++ GLIBC_2.2 ++ GLIBC_2.3 ++ GLIBC_2.3.3 ++ GLIBC_2.3.4 ++ GLIBC_2.4 ++} diff --git a/glibc.spec b/glibc.spec index bd13cd5..2b4c3a5 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,4 +1,4 @@ -%bcond_with crosscompilers +%bcond_without crosscompilers %ifarch %{ix86} %{arm} # FIXME add riscv32-linux when glibc starts supporting it # FIXME Determine why (and fix) 32-bit platform to x86_64-linux crosscompilers @@ -19,18 +19,12 @@ %define _libdir32 %{_prefix}/lib %define _libdirn32 %{_prefix}/lib32 -%define ver 2.31 -%define linaro %{nil} +%define ver 2.32 +%define fullver 2.32 %define oname glibc %define major 6 -%if "%{linaro}" != "" -%define fullver %{ver}-%{linaro} -%define source_dir glibc-linaro-%{fullver} -%else -%define fullver %{ver} %define source_dir %{oname}-%{ver} -%endif %define checklist %{_builddir}/%{source_dir}/Check.list %define libc %mklibname c %{major} %define devname %mklibname -d c @@ -38,15 +32,14 @@ %define multilibc libc%{major} %define _disable_rebuild_configure 1 -%bcond_with lto -%if !%{with lto} + +# (tpg) 2020-08-20 by default glibc is not designed to make use of LTO %define _disable_lto 1 -%endif %define _disable_ld_no_undefined 1 # (tpg) optimize it a bit -%global optflags %{optflags} -O3 +%global optflags %{optflags} -O3 -Wno-error=stringop-overflow -fno-strict-aliasing %global platform %{_target_vendor}-%{_target_os}%{?_gnu} %global target_cpu %{_target_cpu} @@ -73,11 +66,12 @@ %ifarch %{aarch64} # Before increasing, please make sure all # boxes we support can be updated: -# As of 2018/06/08: -# Opteron server boxes have 4.4.x +# As of 2020/07/15: +# Synquacer, Macchiatobin and friends have mainline # Rockchip 3399 has 4.4.x # Gemini PDA has 3.18.x -%define enablekernel 3.18.0 +# Nexus 5X has 3.10.x +%define enablekernel 3.10.0 %else # (tpg) some popular clouds will fail with error "FATAL: kernel too old" # when running our docker or building it. Let's be safe and pretend it's 2015. @@ -107,38 +101,26 @@ %endif # build documentation by default -%bcond_with doc +%bcond_without doc %bcond_with pdf # enable utils by default %bcond_without utils -# If devel-rpm-generators is used, explicitly -# force it to automatically detect bitness of ELF -# executable despite system-wide value of this macro, -# because here in glibc 32 and 64 bit *.so are mixed -%global __develgen_auto_bitness 1 - #----------------------------------------------------------------------- Summary: The GNU libc libraries Name: %{cross_prefix}%{oname} Epoch: 6 -%if "%{linaro}" != "" -Version: %{ver}_%{linaro} -Source0: http://cbuild.validation.linaro.org/snapshots/glibc-linaro-%{fullver}.tar.xz -%else Version: %{ver} Source0: http://ftp.gnu.org/gnu/glibc/%{oname}-%{ver}.tar.xz #if %(test $(echo %{version}.0 |cut -d. -f3) -lt 90 && echo 1 || echo 0) #Source1: http://ftp.gnu.org/gnu/glibc/%{oname}-%{ver}.tar.xz.sig #endif -%endif -Release: 7 +Release: 2 License: LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ Group: System/Libraries Url: http://www.gnu.org/software/libc/ # From Fedora -Source2: glibc_post_upgrade.c Source3: glibc-manpages.tar.bz2 Source5: glibc-check.sh Source10: libc-lock.h @@ -153,7 +135,6 @@ Source1003: locales.sysconfig #----------------------------------------------------------------------- # fedora patches -Patch21: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-i386-tls-direct-seg-refs.patch Patch25: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-linux-tcsetattr.patch Patch26: eglibc-fedora-locale-euro.patch Patch27: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-localedata-rh61908.patch @@ -164,7 +145,6 @@ Patch30: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-lo Patch31: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-locarchive.patch Patch32: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-manual-dircategory.patch Patch33: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-nis-rh188246.patch -Patch34: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-nptl-linklibc.patch Patch35: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-fedora-ppc-unwind.patch Patch36: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-aarch64-tls-fixes.patch Patch38: http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/plain/glibc-arm-hardfloat-3.patch @@ -194,14 +174,9 @@ Patch85: https://github.com/clearlinux-pkgs/glibc/blob/master/spinaphore.patch Patch86: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/large-page-huge-page.patch Patch87: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/use_madv_free.patch Patch88: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/malloc_tune.patch -Patch89: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/ldconfig-format-new.patch # (tpg) CLR disabled this patch #Patch90: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/ldconfig-Os.patch -%if %{with lto} -Patch91: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/mathlto.patch -%endif Patch92: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/pause.patch -Patch99: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/gcc-8-fix.patch Patch100: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/spin-smarter.patch Patch101: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/nostackshrink.patch @@ -214,34 +189,27 @@ Patch101: https://raw.githubusercontent.com/clearlinux-pkgs/glibc/master/nostack #----------------------------------------------------------------------- # OpenMandriva patches Patch1000: eglibc-mandriva-localedef-archive-follow-symlinks.patch -Patch1001: eglibc-mandriva-fix-dns-with-broken-routers.patch Patch1002: eglibc-mandriva-nss-upgrade.patch Patch1003: eglibc-mandriva-share-locale.patch Patch1004: eglibc-mandriva-nsswitch.conf.patch Patch1005: eglibc-mandriva-xterm-xvt.patch -Patch1006: eglibc-mandriva-nscd-enable.patch Patch1007: eglibc-mandriva-nscd-no-host-cache.patch -Patch1009: eglibc-mandriva-nscd-init-should-start.patch Patch1010: eglibc-mandriva-timezone.patch -Patch1011: eglibc-mandriva-biarch-cpp-defines.patch Patch1012: eglibc-mandriva-ENOTTY-fr-translation.patch -Patch1013: eglibc-mandriva-biarch-utils.patch -Patch1015: glibc-2.26-no-attribute-leaf-for-clang.patch Patch1018: eglibc-mandriva-testsuite-ldbl-bits.patch Patch1019: eglibc-mandriva-testsuite-rt-notparallel.patch Patch1020: glibc-2.19-no-__builtin_va_arg_pack-with-clang.patch -#Patch1021: eglibc-mandriva-no-leaf-attribute.patch # http://sourceware.org/bugzilla/show_bug.cgi?id=14995 # http://sourceware.org/bugzilla/attachment.cgi?id=6795 Patch1029: glibc-2.19-nscd-socket-and-pid-moved-from-varrun-to-run.patch Patch1033: glibc-2.25-force-use-ld-bfd.patch -Patch1034: glibc-2.27-clang-_Float.patch Patch1035: glibc-2.29-aarch64-buildfix.patch Patch1036: glibc-2.29-strict-aliasing.patch Patch1037: glibc-2.29-SIG_BLOCK.patch +Patch1038: glibc-2.31.9000-aarch64-compile.patch +Patch1039: https://github.com/FireBurn/glibc/commit/4483f2500825a84382c2a6a9ac60fc77954533d7.patch +Patch1040: https://github.com/FireBurn/glibc/commit/2efa9591e5e8a129e7b73ad0dad3eecbd69482ff.patch -# do not remove this BR - it helps to bootstrap the generator -BuildRequires: devel-rpm-generators BuildRequires: autoconf2.5 BuildRequires: %{cross_prefix}binutils >= 2.30-7 BuildRequires: %{cross_prefix}gcc @@ -314,11 +282,138 @@ Linux system will not function. required = '%{enablekernel}' rel = posix.uname("%r") if rpm.vercmp(rel, required) < 0 then - error("FATAL: kernel too old", 0) + error("FATAL: installed kernel is too old for glibc", 0) end %post -p -os.execute("/usr/sbin/glibc_post_upgrade") +-- We use lua's posix.exec because there may be no shell that we can +-- run during glibc upgrade. +function post_exec (program, ...) + local pid = posix.fork () + if pid == 0 then + assert (posix.exec (program, ...)) + elseif pid > 0 then + posix.wait (pid) + end +end + +-- (1) Remove multilib libraries from previous installs. +-- In order to support in-place upgrades, we must immediately remove +-- obsolete platform directories after installing a new glibc +-- version. RPM only deletes files removed by updates near the end +-- of the transaction. If we did not remove the obsolete platform +-- directories here, they may be preferred by the dynamic linker +-- during the execution of subsequent RPM scriptlets, likely +-- resulting in process startup failures. + +-- Full set of libraries glibc may install. +install_libs = { "anl", "BrokenLocale", "c", "dl", "m", "mvec", + "nss_compat", "nss_db", "nss_dns", "nss_files", + "nss_hesiod", "pthread", "resolv", "rt", "SegFault", + "thread_db", "util" } + +-- We are going to remove these libraries. Generally speaking we remove +-- all core libraries in the multilib directory. +-- We employ a tight match where X.Y is in [2.0,9.9*], so we would +-- match "libc-2.0.so" and so on up to "libc-9.9*". +remove_regexps = {} +for i = 1, #install_libs do + remove_regexps[i] = ("lib" .. install_libs[i] + .. "%%-[2-9]%%.[0-9]+%%.so$") +end + +-- Two exceptions: +remove_regexps[#install_libs + 1] = "libthread_db%%-1%%.0%%.so" +remove_regexps[#install_libs + 2] = "libSegFault%%.so" + +-- We are going to search these directories. +local remove_dirs = { "%{_libdir}/i686", + "%{_libdir}/i686/nosegneg", + "%{_libdir}/power6", + "%{_libdir}/power7", + "%{_libdir}/power8" } + +-- Walk all the directories with files we need to remove... +for _, rdir in ipairs (remove_dirs) do + if posix.access (rdir) then + -- If the directory exists we look at all the files... + local remove_files = posix.files (rdir) + for rfile in remove_files do + for _, rregexp in ipairs (remove_regexps) do + -- Does it match the regexp? + local dso = string.match (rfile, rregexp) + if (dso ~= nil) then + -- Removing file... + os.remove (rdir .. '/' .. rfile) + end + end + end + end +end + +-- (2) Update /etc/ld.so.conf +-- Next we update /etc/ld.so.conf to ensure that it starts with +-- a literal "include ld.so.conf.d/*.conf". + +local ldsoconf = "/etc/ld.so.conf" +local ldsoconf_tmp = "/etc/glibc_post_upgrade.ld.so.conf" + +if posix.access (ldsoconf) then + + -- We must have a "include ld.so.conf.d/*.conf" line. + local have_include = false + for line in io.lines (ldsoconf) do + -- This must match, and we don't ignore whitespace. + if string.match (line, "^include ld.so.conf.d/%%*%%.conf$") ~= nil then + have_include = true + end + end + + if not have_include then + -- Insert "include ld.so.conf.d/*.conf" line at the start of the + -- file. We only support one of these post upgrades running at + -- a time (temporary file name is fixed). + local tmp_fd = io.open (ldsoconf_tmp, "w") + if tmp_fd ~= nil then + tmp_fd:write ("include ld.so.conf.d/*.conf\n") + for line in io.lines (ldsoconf) do + tmp_fd:write (line .. "\n") + end + tmp_fd:close () + local res = os.rename (ldsoconf_tmp, ldsoconf) + if res == nil then + io.stdout:write ("Error: Unable to update configuration file (rename).\n") + end + else + io.stdout:write ("Error: Unable to update configuration file (open).\n") + end + end +end + +-- (3) Rebuild ld.so.cache early. +-- If the format of the cache changes then we need to rebuild +-- the cache early to avoid any problems running binaries with +-- the new glibc. + +-- Note: We use _prefix because Fedora's UsrMove says so. +post_exec ("/sbin/ldconfig") + +-- (4) Update gconv modules cache. +-- If the /usr/lib/gconv/gconv-modules.cache exists, then update it +-- with the latest set of modules that were just installed. +-- We assume that the cache is in _libdir/gconv and called +-- "gconv-modules.cache". + +local iconv_dir = "%{_libdir}/gconv" +local iconv_cache = iconv_dir .. "/gconv-modules.cache" +if (posix.utime (iconv_cache) == 0) then + post_exec ("%{_sbindir}/iconvconfig", + "-o", iconv_cache, + "--nostdlib", + iconv_dir) +else + io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n") +end %transfiletriggerin -p -- /lib/ /lib64/ /usr/lib/ /usr/lib64/ /etc/ld.so.conf.d/ os.execute("/sbin/ldconfig -X") @@ -376,6 +471,7 @@ LANG variable to their preferred language in their %{expand:%(sh %{S:1000} "Catalan" "ca" "ca_AD" "ca_ES" "ca_FR" "ca_IT")} %{expand:%(sh %{S:1000} "Chechen" "ce" "ce_RU")} %{expand:%(sh %{S:1000} "Cherokee" "chr" "chr_US")} +%{expand:%(sh %{S:1000} "Central Kurdish" "ckb" "ckb_IQ")} %{expand:%(sh %{S:1000} "Crimean Tatar" "crh" "crh_UA")} %{expand:%(sh %{S:1000} "Czech" "cs" "cs_CZ")} %{expand:%(sh %{S:1000} "Chuvash" "cv" "cv_RU")} @@ -552,9 +648,6 @@ LANG variable to their preferred language in their %doc %{_docdir}/glibc/gai.conf %doc %{_docdir}/glibc/COPYING %doc %{_docdir}/glibc/COPYING.LIB -%{_mandir}/man1/* -%{_mandir}/man8/rpcinfo.8* -%{_mandir}/man8/ld.so* %{_localedir}/locale.alias /sbin/sln %{_prefix}/libexec/getconf @@ -567,7 +660,7 @@ LANG variable to their preferred language in their %exclude %{_prefix}/libexec/getconf/XBS5_ILP32_OFF32 %exclude %{_prefix}/libexec/getconf/XBS5_ILP32_OFFBIG %endif -%{_slibdir}/ld-%{fullver}.so +%{_slibdir}/ld-[0-9]*.so %if %isarch %{ix86} %{_slibdir}/ld-linux.so.2 %endif @@ -620,9 +713,7 @@ LANG variable to their preferred language in their %{_bindir}/sprof %{_bindir}/tzselect %{_sbindir}/iconvconfig -%{_sbindir}/glibc_post_upgrade /sbin/ldconfig -%{_mandir}/man8/ldconfig* %ghost %{_sysconfdir}/ld.so.cache %dir %{_var}/cache/ldconfig %ghost %{_var}/cache/ldconfig/aux-cache @@ -630,7 +721,7 @@ LANG variable to their preferred language in their %else %if %isarch mips mipsel %if %{build_biarch} -%{_slibdir32}/ld-%{fullver}.so +%{_slibdir32}/ld-[0-9]*.so %{_slibdir32}/ld.so.1 %{_slibdir32}/lib*-[.0-9]*.so %{_slibdir32}/lib*.so.[0-9]* @@ -667,7 +758,7 @@ library and the standard math library. Without these two libraries, a Linux system will not function. %files -n %{multilibc} -%{_slibdir32}/ld-%{fullver}.so +%{_slibdir32}/ld-[0-9]*.so %{_slibdir32}/ld-linux*.so.2 %{_slibdir32}/lib*-[.0-9]*.so %{_slibdir32}/lib*.so.[0-9]* @@ -789,7 +880,7 @@ library. %{_libdir}/libdl.a %{_libdir}/libm.a # Versioned libm.a seems to be generated only on x86_64 -%optional %{_libdir}/libm-%{version}.a +%optional %{_libdir}/libm-[0-9]*.a %{_libdir}/libpthread.a %{_libdir}/libresolv.a %{_libdir}/librt.a @@ -1031,11 +1122,7 @@ function BuildGlibc() { BuildCompFlags="" # -Wall is just added to get conditionally %%optflags printed... # cut -flto flag -%if %{with lto} - BuildFlags="$(rpm --target ${arch}-%{_target_os} -D '%__common_cflags_with_ssp -Wall' -E %%{optflags} | sed -e 's# -fPIC##g' -e 's#-m64##' -e 's#-gdwarf-4##;s#-g1##;s#-g##' -e 's#-m[36][24]##' -e 's#-O[s2]#-O3#')" -%else BuildFlags="$(rpm --target ${arch}-%{_target_os} -D '%__common_cflags_with_ssp -Wall' -E %%{optflags} | sed -e 's# -fPIC##g' -e 's#-m64##' -e 's#-gdwarf-4##;s#-g1##;s#-g##' -e 's#-flto##' -e 's#-m[36][24]##' -e 's#-O[s2]#-O3#')" -%endif case $arch in i[3-6]86) %ifarch %{x86_64} @@ -1119,9 +1206,7 @@ function BuildGlibc() { # undefined reference to __aeabi_unwind_cpp_pr0 BuildFlags="-funwind-tables -fasynchronous-unwind-tables $BuildFlags" %endif -%if !%{with lto} BuildFlags="$BuildFlags -fno-lto" -%endif if [ "$arch" = 'i586' ] || [ "$arch" = 'i686' ]; then # Work around https://sourceware.org/ml/libc-alpha/2015-10/msg00745.html @@ -1205,6 +1290,7 @@ echo CC="$BuildCC" CXX="$BuildCXX" CFLAGS="$BuildFlags -Wno-error" ARFLAGS="$ARF --disable-profile \ --enable-static \ --disable-nss-crypt \ + --disable-crypt \ $(WithSelinux) \ %if !%{with nscd} --disable-build-nscd \ @@ -1273,17 +1359,10 @@ for i in %{targets}; do esac mkdir -p obj-${TRIPLET} cd obj-${TRIPLET} -%if %{with lto} - CFLAGS="$(rpm --target ${i} --eval '%%{optflags} -fuse-ld=bfd -fno-strict-aliasing -Wno-error' |sed -e 's,-m[36][24],,;s,-Werror[^ ]*,,g')" \ - CXXFLAGS="$(rpm --target ${i} --eval '%%{optflags} -fuse-ld=bfd -fno-strict-aliasing -Wno-error' |sed -e 's,-m[36][24],,;s,-Werror[^ ]*,,g')" \ - ASFLAGS="$(rpm --target ${i} --eval '%%{optflags} -fuse-ld=bfd -fno-strict-aliasing -Wno-error' |sed -e 's,-m[36][24],,;s,-Werror[^ ]*,,g')" \ - LDFLAGS="$(rpm --target ${i} --eval '%%{ldflags} -fuse-ld=bfd -fno-strict-aliasing -Wno-error' |sed -e 's,-m[36][24],,')" \ -%else CFLAGS="$(rpm --target ${i} --eval '%%{optflags} -fuse-ld=bfd -fno-strict-aliasing -Wno-error' |sed -e 's,-m[36][24],,;s,-flto,,g;s,-Werror[^ ]*,,g')" \ CXXFLAGS="$(rpm --target ${i} --eval '%%{optflags} -fuse-ld=bfd -fno-strict-aliasing -Wno-error' |sed -e 's,-m[36][24],,;s,-flto,,g;s,-Werror[^ ]*,,g')" \ ASFLAGS="$(rpm --target ${i} --eval '%%{optflags} -fuse-ld=bfd -fno-strict-aliasing -Wno-error' |sed -e 's,-m[36][24],,;s,-flto,,g;s,-Werror[^ ]*,,g')" \ LDFLAGS="$(rpm --target ${i} --eval '%%{ldflags} -fuse-ld=bfd -fno-strict-aliasing -Wno-error' |sed -e 's,-m[36][24],,;s,-flto,,g')" \ -%endif CC="${TRIPLET}-gcc ${CFLAGS}" \ ../configure \ --prefix=%{_prefix}/${TRIPLET} \ @@ -1294,7 +1373,11 @@ for i in %{targets}; do # We set CXX to empty to prevent links-dso-program from being built # (it may not work -- if we're using a bootstrap version of gcc, # there's no libstdc++ or libgcc_s) - %make_build CXX="" LIBGD=no + # the " || make ..." part is a workaround for the build failing on + # aarch64 boxes with lots of cores while building the iconv converters + # for the i686 crosscompiler. This should be fixed properly at some + # point. + %make_build CXX="" LIBGD=no || make CXX="" LIBGD=no cd .. done %endif @@ -1335,16 +1418,6 @@ export BIARCH_BUILDING=1 esac %endif -%if "%{name}" == "glibc" - -# post install wrapper -gcc -static -Lbuild-%{target_cpu}-linux %{optflags} -Os %{SOURCE2} -o build-%{target_cpu}-linux/glibc_post_upgrade \ - '-DLIBTLS="/%{_lib}/tls/"' \ - '-DGCONV_MODULES_DIR="%{_libdir}/gconv"' \ - '-DLD_SO_CONF="/etc/ld.so.conf"' \ - '-DICONVCONFIG="%{_sbindir}/iconvconfig"' -%endif - #----------------------------------------------------------------------- %if "%{target_cpu}" != "i686" @@ -1384,6 +1457,10 @@ for i in %{long_targets}; do cd .. # We don't need all the bits and pieces with a crosscompiler rm -rf %{buildroot}%{_prefix}/$i/bin %{buildroot}%{_prefix}/$i/sbin %{buildroot}%{_prefix}/$i/var %{buildroot}%{_prefix}/$i/share %{buildroot}%{_prefix}/$i/etc + # We need to get rid of this hardcode at some point so the sysroot can + # double as a chroot... But we probably can't do this before the FS + # changes, it breaks second stage gcc crosscompilers + # sed -i -e "s,%{_prefix}/$i,,g" %{buildroot}%{_prefix}/$i/lib/libc.so done %endif @@ -1437,11 +1514,6 @@ make install_root=%{buildroot} install -C build-%{target_cpu}-linux done %endif -%if "%{name}" == "glibc" - install -m700 build-%{target_cpu}-linux/glibc_post_upgrade -D %{buildroot}%{_sbindir}/glibc_post_upgrade - sh manpages/Script.sh -%endif - # Install extra glibc libraries function InstallGlibc() { local BuildDir="$1" diff --git a/glibc_post_upgrade.c b/glibc_post_upgrade.c deleted file mode 100644 index 0171d67..0000000 --- a/glibc_post_upgrade.c +++ /dev/null @@ -1,310 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LD_SO_CONF "/etc/ld.so.conf" -#define ICONVCONFIG "/usr/sbin/iconvconfig" - -#define verbose_exec(failcode, path...) \ - do \ - { \ - char *const arr[] = { path, NULL }; \ - vexec (failcode, arr); \ - } while (0) - -__attribute__((noinline)) void vexec (int failcode, char *const path[]); -__attribute__((noinline)) void says (const char *str); -__attribute__((noinline)) void sayn (long num); -__attribute__((noinline)) void message (char *const path[]); -__attribute__((noinline)) int check_elf (const char *name); - -int -main (void) -{ - struct stat statbuf; - char initpath[256]; - - char buffer[4096]; - struct pref { - char *p; - int len; - } prefix[] = { { "libc-", 5 }, { "libm-", 5 }, - { "librt-", 6 }, { "libpthread-", 11 }, - { "librtkaio-", 10 }, { "libthread_db-", 13 } }; - int i, j, fd; - off_t base; - ssize_t ret; - - /* In order to support in-place upgrades, we must immediately remove - obsolete platform directories after installing a new glibc - version. RPM only deletes files removed by updates near the end - of the transaction. If we did not remove the obsolete platform - directories here, they would be preferred by the dynamic linker - during the execution of subsequent RPM scriptlets, likely - resulting in process startup failures. */ - const char *remove_dirs[] = - { -#if defined (__i386__) - "/lib/i686", - "/lib/i686/nosegneg", -#elif defined (__powerpc64__) && _CALL_ELF != 2 - "/lib64/power6", -#endif - }; - for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j) - { - size_t rmlen = strlen (remove_dirs[j]); - fd = open (remove_dirs[j], O_RDONLY); - if (fd >= 0 - && (ret = getdirentries (fd, buffer, sizeof (buffer), &base)) - >= (ssize_t) offsetof (struct dirent, d_name)) - { - for (base = 0; base + offsetof (struct dirent, d_name) < ret; ) - { - struct dirent *d = (struct dirent *) (buffer + base); - - for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++) - if (! strncmp (d->d_name, prefix[i].p, prefix[i].len)) - { - char *p = d->d_name + prefix[i].len; - - while (*p == '.' || (*p >= '0' && *p <= '9')) p++; - if (p[0] == 's' && p[1] == 'o' && p[2] == '\0' - && p + 3 - d->d_name - < sizeof (initpath) - rmlen - 1) - { - memcpy (initpath, remove_dirs[j], rmlen); - initpath[rmlen] = '/'; - strcpy (initpath + rmlen + 1, d->d_name); - unlink (initpath); - break; - } - } - base += d->d_reclen; - } - close (fd); - } - } - - int ldsocfd = open (LD_SO_CONF, O_RDONLY); - struct stat ldsocst; - if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0) - { - char p[ldsocst.st_size + 1]; - if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size) - { - p[ldsocst.st_size] = '\0'; - if (strstr (p, "include ld.so.conf.d/*.conf") == NULL) - { - close (ldsocfd); - ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC); - if (ldsocfd >= 0) - { - size_t slen = strlen ("include ld.so.conf.d/*.conf\n"); - if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen) - != slen - || write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size) - _exit (109); - } - } - } - if (ldsocfd >= 0) - close (ldsocfd); - } - - /* If installing bi-arch glibc, rpm sometimes doesn't unpack all files - before running one of the lib's %post scriptlet. /sbin/ldconfig will - then be run by the other arch's %post. */ - if (! access ("/sbin/ldconfig", X_OK)) - verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig", "-X"); - - if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL)) - { - char *iconv_cache = GCONV_MODULES_DIR"/gconv-modules.cache"; - char *iconv_dir = GCONV_MODULES_DIR; - verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig", - "-o", iconv_cache, - "--nostdlib", iconv_dir); - } - - /* Check if systemctl is available for further systemd deamon restart*/ - if (access ("/bin/systemctl", X_OK)) - _exit (0); - - /* Check if we are not inside of some chroot, because we'd just - timeout and leave /etc/initrunlvl. - - On more modern systems this test is not sufficient to detect - if we're in a chroot. */ - if (readlink ("/proc/1/exe", initpath, 256) <= 0 || - readlink ("/proc/1/root", initpath, 256) <= 0) - _exit (0); - - /* Here's another well known way to detect chroot, at least on an - ext and xfs filesystems and assuming nothing mounted on the chroot's - root. - # (tpg) Possible 2017 solutions - # 1. check if inode for "/" is in 0 between 4096 range, - # as this may get into account almost all firesystems? - # 2. check if /proc/1/cgroup output does contain word docker or lxc - # - if (stat ("/", &statbuf) != 0 - || (statbuf.st_ino != 2 - && statbuf.st_ino != 128)) - _exit (0); */ - - if (check_elf ("/proc/1/exe")) - verbose_exec (116, "/bin/systemctl", "/bin/systemctl", "daemon-reexec"); - - /* Check if we can safely condrestart sshd. */ - if (access ("/bin/systemctl", X_OK) == 0 - && access ("/usr/sbin/sshd", X_OK) == 0 - && access ("/bin/sh", F_OK) == 0) - { - if (check_elf ("/usr/sbin/sshd")) - verbose_exec (-121, "/bin/systemctl", "/bin/systemctl", "-q", "try-restart", "sshd.service"); - } - - _exit(0); -} - -void -vexec (int failcode, char *const path[]) -{ - pid_t pid; - int status, save_errno; - int devnull = 0; - - if (failcode < 0) - { - devnull = 1; - failcode = -failcode; - } - pid = vfork (); - if (pid == 0) - { - int fd; - if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0) - { - dup2 (fd, 1); - dup2 (fd, 2); - close (fd); - } - execv (path[0], path + 1); - save_errno = errno; - message (path); - says (" exec failed with errno "); - sayn (save_errno); - says ("\n"); - _exit (failcode); - } - else if (pid < 0) - { - save_errno = errno; - message (path); - says (" fork failed with errno "); - sayn (save_errno); - says ("\n"); - _exit (failcode + 1); - } - if (waitpid (0, &status, 0) != pid || !WIFEXITED (status)) - { - message (path); - says (" child terminated abnormally\n"); - _exit (failcode + 2); - } - if (WEXITSTATUS (status)) - { - message (path); - says (" child exited with exit code "); - sayn (WEXITSTATUS (status)); - says ("\n"); - _exit (WEXITSTATUS (status)); - } -} - -void -says (const char *str) -{ - write (1, str, strlen (str)); -} - -void -sayn (long num) -{ - char string[sizeof (long) * 3 + 1]; - char *p = string + sizeof (string) - 1; - - *p = '\0'; - if (num == 0) - *--p = '0'; - else - while (num) - { - *--p = '0' + num % 10; - num = num / 10; - } - - says (p); -} - -void -message (char *const path[]) -{ - says ("/usr/sbin/glibc_post_upgrade: While trying to execute "); - says (path[0]); -} - -int -check_elf (const char *name) -{ - /* Play safe, if we can't open or read, assume it might be - ELF for the current arch. */ - int ret = 1; - int fd = open (name, O_RDONLY); - if (fd >= 0) - { - Elf32_Ehdr ehdr; - if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version)) - == offsetof (Elf32_Ehdr, e_version)) - { - ret = 0; - if (ehdr.e_ident[EI_CLASS] - == (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32)) - { -#if defined __i386__ - ret = ehdr.e_machine == EM_386; -#elif defined __x86_64__ - ret = ehdr.e_machine == EM_X86_64; -#elif defined __powerpc64__ - ret = ehdr.e_machine == EM_PPC64; -#elif defined __powerpc__ - ret = ehdr.e_machine == EM_PPC; -#elif defined __s390__ || defined __s390x__ - ret = ehdr.e_machine == EM_S390; -#elif defined __x86_64__ - ret = ehdr.e_machine == EM_X86_64; -#elif defined __sparc__ - if (sizeof (long) == 8) - ret = ehdr.e_machine == EM_SPARCV9; - else - ret = (ehdr.e_machine == EM_SPARC - || ehdr.e_machine == EM_SPARC32PLUS); -#else - ret = 1; -#endif - } - } - close (fd); - } - return ret; -} diff --git a/ldconfig-Os.patch b/ldconfig-Os.patch new file mode 100644 index 0000000..f9c5749 --- /dev/null +++ b/ldconfig-Os.patch @@ -0,0 +1,31 @@ +--- glibc-2.27/elf/Makefile.0092~ 2018-02-01 17:17:18.000000000 +0100 ++++ glibc-2.27/elf/Makefile 2018-02-02 20:23:42.959165917 +0100 +@@ -74,9 +74,9 @@ define elide-stack-protector + $(if $(filter $(@F),$(patsubst %,%$(1),$(2))), $(no-stack-protector)) + endef + +-CFLAGS-.o += $(call elide-stack-protector,.o,$(elide-routines.os)) +-CFLAGS-.op += $(call elide-stack-protector,.op,$(elide-routines.os)) +-CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines)) ++CFLAGS-.o += $(call elide-stack-protector,.o,$(elide-routines.os)) -Os ++CFLAGS-.op += $(call elide-stack-protector,.op,$(elide-routines.os)) -Os ++CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines)) -Os + + ifeq ($(unwind-find-fde),yes) + routines += unwind-dw2-fde-glibc +@@ -561,11 +561,11 @@ $(objpfx)ldconfig: $(ldconfig-modules:%= + + SYSCONF-FLAGS := -D'SYSCONFDIR="$(sysconfdir)"' + CFLAGS-ldconfig.c += $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' \ +- -D'SLIBDIR="$(slibdir)"' ++ -D'SLIBDIR="$(slibdir)"' -Os + libof-ldconfig = ldconfig +-CFLAGS-dl-cache.c += $(SYSCONF-FLAGS) +-CFLAGS-cache.c += $(SYSCONF-FLAGS) +-CFLAGS-rtld.c += $(SYSCONF-FLAGS) ++CFLAGS-dl-cache.c += $(SYSCONF-FLAGS) -Os ++CFLAGS-cache.c += $(SYSCONF-FLAGS) -Os ++CFLAGS-rtld.c += $(SYSCONF-FLAGS) -Os + + cpp-srcs-left := $(all-rtld-routines:=.os) + lib := rtld diff --git a/ldconfig-format-new.patch b/ldconfig-format-new.patch deleted file mode 100644 index 2af0d48..0000000 --- a/ldconfig-format-new.patch +++ /dev/null @@ -1,14 +0,0 @@ -Subject: Make ldconfig default to "new" cache format. -Index: glibc-2.21/elf/ldconfig.c -=================================================================== ---- glibc-2.21.orig/elf/ldconfig.c 2015-03-03 14:53:52.206995018 +0000 -+++ glibc-2.21/elf/ldconfig.c 2015-03-03 14:54:00.094995204 +0000 -@@ -95,7 +95,7 @@ - - /* Format to support. */ - /* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */ --int opt_format = 1; -+int opt_format = 2; - - /* Build cache. */ - static int opt_build_cache = 1; diff --git a/nptl-getrlimit-compile.patch b/nptl-getrlimit-compile.patch new file mode 100644 index 0000000..2052b19 --- /dev/null +++ b/nptl-getrlimit-compile.patch @@ -0,0 +1,11 @@ +--- libc/nptl/nptl-init.c.bero~ 2012-12-01 23:55:26.722754391 +0100 ++++ libc/nptl/nptl-init.c 2012-12-01 23:55:42.725950817 +0100 +@@ -414,7 +414,7 @@ __pthread_initialize_minimal_internal (v + /* Determine the default allowed stack size. This is the size used + in case the user does not specify one. */ + struct rlimit limit; +- if (__getrlimit (RLIMIT_STACK, &limit) != 0 ++ if (getrlimit (RLIMIT_STACK, &limit) != 0 + || limit.rlim_cur == RLIM_INFINITY) + /* The system limit is not usable. Use an architecture-specific + default. */ diff --git a/nsswitch.conf b/nsswitch.conf index 1c17b3f..738af5b 100644 --- a/nsswitch.conf +++ b/nsswitch.conf @@ -46,10 +46,7 @@ passwd: files systemd shadow: files systemd group: files systemd -# If you want to give systemd-resolved a try (and don't mind it -# changing your hostname while X is running...), add -# resolve [!UNAVAIL=return] after files. -hosts: files dns myhostname nis wins mdns4_minimal +hosts: files resolve [!UNAVAIL=return] dns myhostname nis wins mdns4_minimal networks: files services: files