summaryrefslogtreecommitdiff
path: root/testing/glibc
diff options
context:
space:
mode:
Diffstat (limited to 'testing/glibc')
-rw-r--r--testing/glibc/PKGBUILD53
-rw-r--r--testing/glibc/glibc-2.16-detect-fma.patch72
-rw-r--r--testing/glibc/glibc-2.16-glob-use-size_t.patch52
-rw-r--r--testing/glibc/glibc-2.16-strncasecmp-segfault.patch65
-rw-r--r--testing/glibc/glibc-2.16-strtod-overflow.patch389
-rw-r--r--testing/glibc/glibc-2.16-unlock-mutex.patch775
-rw-r--r--testing/glibc/glibc.install14
-rw-r--r--testing/glibc/nscd.service2
8 files changed, 1402 insertions, 20 deletions
diff --git a/testing/glibc/PKGBUILD b/testing/glibc/PKGBUILD
index 6dc93f31e..0d8b274be 100644
--- a/testing/glibc/PKGBUILD
+++ b/testing/glibc/PKGBUILD
@@ -1,4 +1,4 @@
-# $Id: PKGBUILD 165242 2012-08-14 08:31:14Z allan $
+# $Id: PKGBUILD 169652 2012-10-25 03:25:47Z allan $
# Maintainer: Allan McRae <allan@archlinux.org>
# toolchain build order: linux-api-headers->glibc->binutils->gcc->binutils->glibc
@@ -6,7 +6,7 @@
pkgname=glibc
pkgver=2.16.0
-pkgrel=3
+pkgrel=5
pkgdesc="GNU C Library"
arch=('i686' 'x86_64')
url="http://www.gnu.org/software/libc"
@@ -21,8 +21,12 @@ options=('!strip')
install=glibc.install
source=(http://ftp.gnu.org/gnu/libc/${pkgname}-${pkgver}.tar.xz{,.sig}
glibc-2.15-fix-res_query-assert.patch
- glibc-2.15-revert-c5a0802a.patch
+ glibc-2.16-unlock-mutex.patch
glibc-2.16-rpcgen-cpp-path.patch
+ glibc-2.16-strncasecmp-segfault.patch
+ glibc-2.16-strtod-overflow.patch
+ glibc-2.16-detect-fma.patch
+ glibc-2.16-glob-use-size_t.patch
nscd.rcd
nscd.service
nscd.tmpfiles
@@ -31,14 +35,19 @@ source=(http://ftp.gnu.org/gnu/libc/${pkgname}-${pkgver}.tar.xz{,.sig}
md5sums=('80b181b02ab249524ec92822c0174cf7'
'2a1221a15575820751c325ef4d2fbb90'
'31f415b41197d85d3bbee3d1eecd06a3'
- '0a0383d50d63f1c02919fe9943b82014'
+ '0afcd8c6020d61684aba63ed5f26bd91'
'ea6a43915474e8276e9361eed6a01280'
+ 'f042d37cc8ca3459023431809039bc88'
+ '61d322f7681a85d3293ada5c3ccc2c7e'
+ '2426f593bc43f5499c41d21b57ee0e30'
+ 'a441353901992feda4b15a11a20140a1'
'589d79041aa767a5179eaa4e2737dd3f'
- 'ad8a9af15ab7eeaa23dc7ee85024af9f'
+ 'c1e07c0bec0fe89791bfd9d13fc85edf'
'bccbe5619e75cf1d97312ec3681c605c'
'07ac979b6ab5eeb778d55f041529d623'
'476e9113489f93b348b21e144b6a8fcf')
+
build() {
cd ${srcdir}/${pkgname}-${pkgver}
@@ -46,14 +55,33 @@ build() {
# http://sourceware.org/bugzilla/show_bug.cgi?id=13013
patch -p1 -i ${srcdir}/glibc-2.15-fix-res_query-assert.patch
- # revert commit c5a0802a - causes various hangs
- # https://bugzilla.redhat.com/show_bug.cgi?id=552960
- patch -p1 -i ${srcdir}/glibc-2.15-revert-c5a0802a.patch
+ # prevent hang by locked mutex
+ # http://sourceware.org/git/?p=glibc.git;a=patch;h=c30e8edf
+ patch -p1 -i ${srcdir}/glibc-2.16-unlock-mutex.patch
# prevent need for /lib/cpp symlink
# http://sourceware.org/git/?p=glibc.git;a=commit;h=bf9b740a
patch -p1 -i ${srcdir}/glibc-2.16-rpcgen-cpp-path.patch
+ # strncasecmp segfault on i686
+ # http://sourceware.org/git/?p=glibc.git;a=commit;h=6db8f737
+ patch -p1 -i ${srcdir}/glibc-2.16-strncasecmp-segfault.patch
+
+ # strtod integer/buffer overflow
+ # http://sourceware.org/git/?p=glibc.git;a=commit;h=da1f4319
+ patch -p1 -i ${srcdir}/glibc-2.16-strtod-overflow.patch
+
+ # detect FMA supprt
+ # http://sourceware.org/git/?p=glibc.git;a=commit;h=a5cfcf08
+ patch -p1 -i ${srcdir}/glibc-2.16-detect-fma.patch
+
+ # prevent overflow in globc
+ # http://sourceware.org/git/?p=glibc.git;a=commit;h=6c62f108
+ patch -p1 -i ${srcdir}/glibc-2.16-glob-use-size_t.patch
+
+ # ldconfig does not need to look in /usr/lib64 or /usr/libx32 on Arch Linux
+ sed -i "s#add_system_dir#do_not_add_system_dir#" sysdeps/unix/sysv/linux/x86_64/dl-cache.h
+
cd ${srcdir}
mkdir glibc-build
cd glibc-build
@@ -64,7 +92,7 @@ build() {
export CFLAGS="${CFLAGS} -mno-tls-direct-seg-refs"
fi
- echo "slibdir=/lib" >> configparms
+ echo "slibdir=/usr/lib" >> configparms
# remove hardening options from CFLAGS for building libraries
CFLAGS=${CFLAGS/-fstack-protector/}
@@ -96,14 +124,12 @@ build() {
check() {
cd ${srcdir}/glibc-build
- make -k check
+ make check
}
package() {
cd ${srcdir}/glibc-build
- ln -s usr/lib ${pkgdir}/lib
-
install -dm755 ${pkgdir}/etc
touch ${pkgdir}/etc/ld.so.conf
@@ -111,6 +137,9 @@ package() {
rm -f ${pkgdir}/etc/ld.so.{cache,conf}
+ # eventually this will move to the filesystem package
+ ln -s usr/lib ${pkgdir}/lib
+
install -dm755 ${pkgdir}/{etc/rc.d,usr/{sbin,lib/{,locale,systemd/system,tmpfiles.d}}}
install -m644 ${srcdir}/${pkgname}-${pkgver}/nscd/nscd.conf ${pkgdir}/etc/nscd.conf
diff --git a/testing/glibc/glibc-2.16-detect-fma.patch b/testing/glibc/glibc-2.16-detect-fma.patch
new file mode 100644
index 000000000..daffb9768
--- /dev/null
+++ b/testing/glibc/glibc-2.16-detect-fma.patch
@@ -0,0 +1,72 @@
+diff --git a/sysdeps/x86_64/multiarch/init-arch.c b/sysdeps/x86_64/multiarch/init-arch.c
+index fb44dcf..fed5ab8 100644
+--- a/sysdeps/x86_64/multiarch/init-arch.c
++++ b/sysdeps/x86_64/multiarch/init-arch.c
+@@ -156,6 +156,9 @@ __init_cpu_features (void)
+ /* Determine if AVX is usable. */
+ if (CPUID_AVX)
+ __cpu_features.feature[index_AVX_Usable] |= bit_AVX_Usable;
++ /* Determine if FMA is usable. */
++ if (CPUID_FMA)
++ __cpu_features.feature[index_FMA_Usable] |= bit_FMA_Usable;
+ /* Determine if FMA4 is usable. */
+ if (CPUID_FMA4)
+ __cpu_features.feature[index_FMA4_Usable] |= bit_FMA4_Usable;
+diff --git a/sysdeps/x86_64/multiarch/init-arch.h b/sysdeps/x86_64/multiarch/init-arch.h
+index 45e2651..f33f1c8 100644
+--- a/sysdeps/x86_64/multiarch/init-arch.h
++++ b/sysdeps/x86_64/multiarch/init-arch.h
+@@ -22,7 +22,8 @@
+ #define bit_Fast_Unaligned_Load (1 << 4)
+ #define bit_Prefer_PMINUB_for_stringop (1 << 5)
+ #define bit_AVX_Usable (1 << 6)
+-#define bit_FMA4_Usable (1 << 7)
++#define bit_FMA_Usable (1 << 7)
++#define bit_FMA4_Usable (1 << 8)
+
+ /* CPUID Feature flags. */
+ #define bit_SSE2 (1 << 26)
+@@ -56,6 +57,7 @@
+ # define index_Fast_Unaligned_Load FEATURE_INDEX_1*FEATURE_SIZE
+ # define index_Prefer_PMINUB_for_stringop FEATURE_INDEX_1*FEATURE_SIZE
+ # define index_AVX_Usable FEATURE_INDEX_1*FEATURE_SIZE
++# define index_FMA_Usable FEATURE_INDEX_1*FEATURE_SIZE
+ # define index_FMA4_Usable FEATURE_INDEX_1*FEATURE_SIZE
+
+ #else /* __ASSEMBLER__ */
+@@ -131,6 +133,8 @@ extern const struct cpu_features *__get_cpu_features (void)
+ HAS_CPUID_FLAG (COMMON_CPUID_INDEX_1, ecx, bit_OSXSAVE)
+ # define CPUID_AVX \
+ HAS_CPUID_FLAG (COMMON_CPUID_INDEX_1, ecx, bit_AVX)
++# define CPUID_FMA \
++ HAS_CPUID_FLAG (COMMON_CPUID_INDEX_1, ecx, bit_FMA)
+ # define CPUID_FMA4 \
+ HAS_CPUID_FLAG (COMMON_CPUID_INDEX_80000001, ecx, bit_FMA4)
+
+@@ -140,7 +144,6 @@ extern const struct cpu_features *__get_cpu_features (void)
+ # define HAS_SSSE3 HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_SSSE3)
+ # define HAS_SSE4_1 HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_SSE4_1)
+ # define HAS_SSE4_2 HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_SSE4_2)
+-# define HAS_FMA HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_FMA)
+
+ # define index_Fast_Rep_String FEATURE_INDEX_1
+ # define index_Fast_Copy_Backward FEATURE_INDEX_1
+@@ -148,6 +151,7 @@ extern const struct cpu_features *__get_cpu_features (void)
+ # define index_Prefer_SSE_for_memop FEATURE_INDEX_1
+ # define index_Fast_Unaligned_Load FEATURE_INDEX_1
+ # define index_AVX_Usable FEATURE_INDEX_1
++# define index_FMA_Usable FEATURE_INDEX_1
+ # define index_FMA4_Usable FEATURE_INDEX_1
+
+ # define HAS_ARCH_FEATURE(name) \
+@@ -159,6 +163,7 @@ extern const struct cpu_features *__get_cpu_features (void)
+ # define HAS_PREFER_SSE_FOR_MEMOP HAS_ARCH_FEATURE (Prefer_SSE_for_memop)
+ # define HAS_FAST_UNALIGNED_LOAD HAS_ARCH_FEATURE (Fast_Unaligned_Load)
+ # define HAS_AVX HAS_ARCH_FEATURE (AVX_Usable)
++# define HAS_FMA HAS_ARCH_FEATURE (FMA_Usable)
+ # define HAS_FMA4 HAS_ARCH_FEATURE (FMA4_Usable)
+
+ #endif /* __ASSEMBLER__ */
+--
+1.7.3.4
+
diff --git a/testing/glibc/glibc-2.16-glob-use-size_t.patch b/testing/glibc/glibc-2.16-glob-use-size_t.patch
new file mode 100644
index 000000000..8c5df45be
--- /dev/null
+++ b/testing/glibc/glibc-2.16-glob-use-size_t.patch
@@ -0,0 +1,52 @@
+diff --git a/posix/glob.c b/posix/glob.c
+index 68ea205..87d4f1b 100644
+--- a/posix/glob.c
++++ b/posix/glob.c
+@@ -217,7 +217,7 @@ static int collated_compare (const void *, const void *) __THROW;
+ static const char *
+ next_brace_sub (const char *cp, int flags)
+ {
+- unsigned int depth = 0;
++ size_t depth = 0;
+ while (*cp != '\0')
+ if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
+ {
+@@ -960,7 +960,7 @@ glob (pattern, flags, errfunc, pglob)
+ && S_ISDIR (st.st_mode))
+ : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
+ {
+- int newcount = pglob->gl_pathc + pglob->gl_offs;
++ size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+ char **new_gl_pathv;
+
+ if (newcount > UINTPTR_MAX - (1 + 1)
+@@ -1059,7 +1059,7 @@ glob (pattern, flags, errfunc, pglob)
+ appending the results to PGLOB. */
+ for (i = 0; i < dirs.gl_pathc; ++i)
+ {
+- int old_pathc;
++ size_t old_pathc;
+
+ #ifdef SHELL
+ {
+@@ -1114,7 +1114,7 @@ glob (pattern, flags, errfunc, pglob)
+ /* No matches. */
+ if (flags & GLOB_NOCHECK)
+ {
+- int newcount = pglob->gl_pathc + pglob->gl_offs;
++ size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+ char **new_gl_pathv;
+
+ if (newcount > UINTPTR_MAX - 2
+@@ -1158,7 +1158,7 @@ glob (pattern, flags, errfunc, pglob)
+ }
+ else
+ {
+- int old_pathc = pglob->gl_pathc;
++ size_t old_pathc = pglob->gl_pathc;
+ int orig_flags = flags;
+
+ if (meta & 2)
+--
+1.7.3.4
+
diff --git a/testing/glibc/glibc-2.16-strncasecmp-segfault.patch b/testing/glibc/glibc-2.16-strncasecmp-segfault.patch
new file mode 100644
index 000000000..ce91bbe82
--- /dev/null
+++ b/testing/glibc/glibc-2.16-strncasecmp-segfault.patch
@@ -0,0 +1,65 @@
+diff --git a/string/test-strncasecmp.c b/string/test-strncasecmp.c
+index 6c17530..acfe668 100644
+--- a/string/test-strncasecmp.c
++++ b/string/test-strncasecmp.c
+@@ -1,5 +1,5 @@
+ /* Test and measure strncasecmp functions.
+- Copyright (C) 1999, 2002, 2003, 2005, 2010 Free Software Foundation, Inc.
++ Copyright (C) 1999-2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+@@ -251,9 +251,9 @@ do_random_tests (void)
+ }
+ }
+
+-
++/* Regression test for BZ #12205 */
+ static void
+-check1 (void)
++bz12205 (void)
+ {
+ static char cp [4096+16] __attribute__ ((aligned(4096)));
+ static char gotrel[4096] __attribute__ ((aligned(4096)));
+@@ -270,6 +270,15 @@ check1 (void)
+ check_result (impl, s1, s2, n, exp_result);
+ }
+
++/* Regression test for BZ #14195 */
++static void
++bz14195 (void)
++{
++ const char *empty_string = "";
++ FOR_EACH_IMPL (impl, 0)
++ check_result (impl, empty_string, "", 5, 0);
++}
++
+ int
+ test_main (void)
+ {
+@@ -277,7 +286,8 @@ test_main (void)
+
+ test_init ();
+
+- check1 ();
++ bz12205 ();
++ bz14195 ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+diff --git a/sysdeps/i386/i686/multiarch/strcmp-ssse3.S b/sysdeps/i386/i686/multiarch/strcmp-ssse3.S
+index 5e6321e..9735ad0 100644
+--- a/sysdeps/i386/i686/multiarch/strcmp-ssse3.S
++++ b/sysdeps/i386/i686/multiarch/strcmp-ssse3.S
+@@ -2445,7 +2445,7 @@ L(less16bytes_sncmp):
+ # endif
+ jne L(neq_sncmp)
+ test %cl, %cl
+- je L(eq)
++ je L(eq_sncmp)
+
+ cmp $1, REM
+ je L(eq_sncmp)
+--
+1.7.3.4
+
diff --git a/testing/glibc/glibc-2.16-strtod-overflow.patch b/testing/glibc/glibc-2.16-strtod-overflow.patch
new file mode 100644
index 000000000..526296325
--- /dev/null
+++ b/testing/glibc/glibc-2.16-strtod-overflow.patch
@@ -0,0 +1,389 @@
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index f7811c5..79c9acb 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -68,7 +68,8 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
+ tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
+ tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2 \
+ tst-makecontext2 tst-strtod6 tst-unsetenv1 \
+- tst-makecontext3 bug-getcontext bug-fmtmsg1
++ tst-makecontext3 bug-getcontext bug-fmtmsg1 \
++ tst-strtod-overflow
+
+ include ../Makeconfig
+
+diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
+index 2166a08..a8a7ea8 100644
+--- a/stdlib/strtod_l.c
++++ b/stdlib/strtod_l.c
+@@ -60,6 +60,7 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
+ #include <math.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <stdint.h>
+
+ /* The gmp headers need some configuration frobs. */
+ #define HAVE_ALLOCA 1
+@@ -72,7 +73,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
+ #include "longlong.h"
+ #include "fpioconst.h"
+
+-#define NDEBUG 1
+ #include <assert.h>
+
+
+@@ -174,19 +174,19 @@ extern const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1];
+ /* Return a floating point number of the needed type according to the given
+ multi-precision number after possible rounding. */
+ static FLOAT
+-round_and_return (mp_limb_t *retval, int exponent, int negative,
++round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
+ mp_limb_t round_limb, mp_size_t round_bit, int more_bits)
+ {
+ if (exponent < MIN_EXP - 1)
+ {
+- mp_size_t shift = MIN_EXP - 1 - exponent;
+-
+- if (shift > MANT_DIG)
++ if (exponent < MIN_EXP - 1 - MANT_DIG)
+ {
+ __set_errno (ERANGE);
+ return 0.0;
+ }
+
++ mp_size_t shift = MIN_EXP - 1 - exponent;
++
+ more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0;
+ if (shift == MANT_DIG)
+ /* This is a special case to handle the very seldom case where
+@@ -233,6 +233,9 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
+ __set_errno (ERANGE);
+ }
+
++ if (exponent > MAX_EXP)
++ goto overflow;
++
+ if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0
+ && (more_bits || (retval[0] & 1) != 0
+ || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0))
+@@ -258,6 +261,7 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
+ }
+
+ if (exponent > MAX_EXP)
++ overflow:
+ return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+
+ return MPN2FLOAT (retval, exponent, negative);
+@@ -271,7 +275,7 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
+ factor for the resulting number (see code) multiply by it. */
+ static const STRING_TYPE *
+ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+- int *exponent
++ intmax_t *exponent
+ #ifndef USE_WIDE_CHAR
+ , const char *decimal, size_t decimal_len, const char *thousands
+ #endif
+@@ -301,6 +305,7 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+ cy += __mpn_add_1 (n, n, *nsize, low);
+ if (cy != 0)
+ {
++ assert (*nsize < MPNSIZE);
+ n[*nsize] = cy;
+ ++(*nsize);
+ }
+@@ -335,7 +340,7 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+ }
+ while (--digcnt > 0);
+
+- if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB)
++ if (*exponent > 0 && *exponent <= MAX_DIG_PER_LIMB - cnt)
+ {
+ low *= _tens_in_limb[*exponent];
+ start = _tens_in_limb[cnt + *exponent];
+@@ -355,7 +360,10 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+ cy = __mpn_mul_1 (n, n, *nsize, start);
+ cy += __mpn_add_1 (n, n, *nsize, low);
+ if (cy != 0)
+- n[(*nsize)++] = cy;
++ {
++ assert (*nsize < MPNSIZE);
++ n[(*nsize)++] = cy;
++ }
+ }
+
+ return str;
+@@ -413,7 +421,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ {
+ int negative; /* The sign of the number. */
+ MPN_VAR (num); /* MP representation of the number. */
+- int exponent; /* Exponent of the number. */
++ intmax_t exponent; /* Exponent of the number. */
+
+ /* Numbers starting `0X' or `0x' have to be processed with base 16. */
+ int base = 10;
+@@ -435,7 +443,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ /* Points at the character following the integer and fractional digits. */
+ const STRING_TYPE *expp;
+ /* Total number of digit and number of digits in integer part. */
+- int dig_no, int_no, lead_zero;
++ size_t dig_no, int_no, lead_zero;
+ /* Contains the last character read. */
+ CHAR_TYPE c;
+
+@@ -767,7 +775,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ are all or any is really a fractional digit will be decided
+ later. */
+ int_no = dig_no;
+- lead_zero = int_no == 0 ? -1 : 0;
++ lead_zero = int_no == 0 ? (size_t) -1 : 0;
+
+ /* Read the fractional digits. A special case are the 'american
+ style' numbers like `16.' i.e. with decimal point but without
+@@ -789,12 +797,13 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ (base == 16 && ({ CHAR_TYPE lo = TOLOWER (c);
+ lo >= L_('a') && lo <= L_('f'); })))
+ {
+- if (c != L_('0') && lead_zero == -1)
++ if (c != L_('0') && lead_zero == (size_t) -1)
+ lead_zero = dig_no - int_no;
+ ++dig_no;
+ c = *++cp;
+ }
+ }
++ assert (dig_no <= (uintmax_t) INTMAX_MAX);
+
+ /* Remember start of exponent (if any). */
+ expp = cp;
+@@ -817,24 +826,80 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+
+ if (c >= L_('0') && c <= L_('9'))
+ {
+- int exp_limit;
++ intmax_t exp_limit;
+
+ /* Get the exponent limit. */
+ if (base == 16)
+- exp_limit = (exp_negative ?
+- -MIN_EXP + MANT_DIG + 4 * int_no :
+- MAX_EXP - 4 * int_no + 4 * lead_zero + 3);
++ {
++ if (exp_negative)
++ {
++ assert (int_no <= (uintmax_t) (INTMAX_MAX
++ + MIN_EXP - MANT_DIG) / 4);
++ exp_limit = -MIN_EXP + MANT_DIG + 4 * (intmax_t) int_no;
++ }
++ else
++ {
++ if (int_no)
++ {
++ assert (lead_zero == 0
++ && int_no <= (uintmax_t) INTMAX_MAX / 4);
++ exp_limit = MAX_EXP - 4 * (intmax_t) int_no + 3;
++ }
++ else if (lead_zero == (size_t) -1)
++ {
++ /* The number is zero and this limit is
++ arbitrary. */
++ exp_limit = MAX_EXP + 3;
++ }
++ else
++ {
++ assert (lead_zero
++ <= (uintmax_t) (INTMAX_MAX - MAX_EXP - 3) / 4);
++ exp_limit = (MAX_EXP
++ + 4 * (intmax_t) lead_zero
++ + 3);
++ }
++ }
++ }
+ else
+- exp_limit = (exp_negative ?
+- -MIN_10_EXP + MANT_DIG + int_no :
+- MAX_10_EXP - int_no + lead_zero + 1);
++ {
++ if (exp_negative)
++ {
++ assert (int_no
++ <= (uintmax_t) (INTMAX_MAX + MIN_10_EXP - MANT_DIG));
++ exp_limit = -MIN_10_EXP + MANT_DIG + (intmax_t) int_no;
++ }
++ else
++ {
++ if (int_no)
++ {
++ assert (lead_zero == 0
++ && int_no <= (uintmax_t) INTMAX_MAX);
++ exp_limit = MAX_10_EXP - (intmax_t) int_no + 1;
++ }
++ else if (lead_zero == (size_t) -1)
++ {
++ /* The number is zero and this limit is
++ arbitrary. */
++ exp_limit = MAX_10_EXP + 1;
++ }
++ else
++ {
++ assert (lead_zero
++ <= (uintmax_t) (INTMAX_MAX - MAX_10_EXP - 1));
++ exp_limit = MAX_10_EXP + (intmax_t) lead_zero + 1;
++ }
++ }
++ }
++
++ if (exp_limit < 0)
++ exp_limit = 0;
+
+ do
+ {
+- exponent *= 10;
+- exponent += c - L_('0');
+-
+- if (__builtin_expect (exponent > exp_limit, 0))
++ if (__builtin_expect ((exponent > exp_limit / 10
++ || (exponent == exp_limit / 10
++ && c - L_('0') > exp_limit % 10)), 0))
+ /* The exponent is too large/small to represent a valid
+ number. */
+ {
+@@ -843,7 +908,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ /* We have to take care for special situation: a joker
+ might have written "0.0e100000" which is in fact
+ zero. */
+- if (lead_zero == -1)
++ if (lead_zero == (size_t) -1)
+ result = negative ? -0.0 : 0.0;
+ else
+ {
+@@ -862,6 +927,9 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ /* NOTREACHED */
+ }
+
++ exponent *= 10;
++ exponent += c - L_('0');
++
+ c = *++cp;
+ }
+ while (c >= L_('0') && c <= L_('9'));
+@@ -930,7 +998,14 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ }
+ #endif
+ startp += lead_zero + decimal_len;
+- exponent -= base == 16 ? 4 * lead_zero : lead_zero;
++ assert (lead_zero <= (base == 16
++ ? (uintmax_t) INTMAX_MAX / 4
++ : (uintmax_t) INTMAX_MAX));
++ assert (lead_zero <= (base == 16
++ ? ((uintmax_t) exponent
++ - (uintmax_t) INTMAX_MIN) / 4
++ : ((uintmax_t) exponent - (uintmax_t) INTMAX_MIN)));
++ exponent -= base == 16 ? 4 * (intmax_t) lead_zero : (intmax_t) lead_zero;
+ dig_no -= lead_zero;
+ }
+
+@@ -972,7 +1047,10 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ }
+
+ /* Adjust the exponent for the bits we are shifting in. */
+- exponent += bits - 1 + (int_no - 1) * 4;
++ assert (int_no <= (uintmax_t) (exponent < 0
++ ? (INTMAX_MAX - bits + 1) / 4
++ : (INTMAX_MAX - exponent - bits + 1) / 4));
++ exponent += bits - 1 + ((intmax_t) int_no - 1) * 4;
+
+ while (--dig_no > 0 && idx >= 0)
+ {
+@@ -1024,13 +1102,15 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ really integer digits or belong to the fractional part; i.e. we normalize
+ 123e-2 to 1.23. */
+ {
+- register int incr = (exponent < 0 ? MAX (-int_no, exponent)
+- : MIN (dig_no - int_no, exponent));
++ register intmax_t incr = (exponent < 0
++ ? MAX (-(intmax_t) int_no, exponent)
++ : MIN ((intmax_t) dig_no - (intmax_t) int_no,
++ exponent));
+ int_no += incr;
+ exponent -= incr;
+ }
+
+- if (__builtin_expect (int_no + exponent > MAX_10_EXP + 1, 0))
++ if (__builtin_expect (exponent > MAX_10_EXP + 1 - (intmax_t) int_no, 0))
+ {
+ __set_errno (ERANGE);
+ return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+@@ -1215,7 +1295,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ digits we should have enough bits for the result. The remaining
+ decimal digits give us the information that more bits are following.
+ This can be used while rounding. (Two added as a safety margin.) */
+- if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 2)
++ if ((intmax_t) dig_no > (intmax_t) int_no + (MANT_DIG - bits + 2) / 3 + 2)
+ {
+ dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2;
+ more_bits = 1;
+@@ -1223,7 +1303,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ else
+ more_bits = 0;
+
+- neg_exp = dig_no - int_no - exponent;
++ neg_exp = (intmax_t) dig_no - (intmax_t) int_no - exponent;
+
+ /* Construct the denominator. */
+ densize = 0;
+diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c
+new file mode 100644
+index 0000000..668d55b
+--- /dev/null
++++ b/stdlib/tst-strtod-overflow.c
+@@ -0,0 +1,48 @@
++/* Test for integer/buffer overflow in strtod.
++ Copyright (C) 2012 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
++ <http://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#define EXPONENT "e-2147483649"
++#define SIZE 214748364
++
++static int
++do_test (void)
++{
++ char *p = malloc (1 + SIZE + sizeof (EXPONENT));
++ if (p == NULL)
++ {
++ puts ("malloc failed, cannot test for overflow");
++ return 0;
++ }
++ p[0] = '1';
++ memset (p + 1, '0', SIZE);
++ memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT));
++ double d = strtod (p, NULL);
++ if (d != 0)
++ {
++ printf ("strtod returned wrong value: %a\n", d);
++ return 1;
++ }
++ return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--
+1.7.3.4
+
diff --git a/testing/glibc/glibc-2.16-unlock-mutex.patch b/testing/glibc/glibc-2.16-unlock-mutex.patch
new file mode 100644
index 000000000..0649d3642
--- /dev/null
+++ b/testing/glibc/glibc-2.16-unlock-mutex.patch
@@ -0,0 +1,775 @@
+--- a/nptl/Makefile
++++ b/nptl/Makefile
+@@ -206,7 +206,7 @@ tests = tst-typesizes \
+ tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
+ 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-cond20 tst-cond21 tst-cond22 tst-cond23 tst-cond24 \
+ 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 \
+@@ -274,6 +275,7 @@ gen-as-const-headers = pthread-errnos.sym
+
+ LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst
+
++LDFLAGS-tst-cond24 = $(no-as-needed) -lrt
+
+ include ../Makeconfig
+
+diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+index d14d7de..6761c13 100644
+--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
++++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+@@ -212,8 +212,23 @@ __pthread_cond_timedwait:
+ sete 24(%esp)
+ je 41f
+
+- /* Normal and PI futexes dont mix. Use normal futex functions only
+- if the kernel does not support the PI futex functions. */
++ /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
++ successfully, it has already locked the mutex for us and the
++ pi_flag (24(%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
+@@ -273,9 +288,24 @@ __pthread_cond_timedwait:
+ jne 9f
+
+ 15: cmpl $-ETIMEDOUT, %esi
+- jne 8b
++ 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 24(%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
+
+- addl $1, wakeup_seq(%ebx)
++28: addl $1, wakeup_seq(%ebx)
+ adcl $0, wakeup_seq+4(%ebx)
+ addl $1, cond_futex(%ebx)
+ movl $ETIMEDOUT, %esi
+diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+index 366de69..0af06ac 100644
+--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
++++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+@@ -136,7 +136,6 @@ __pthread_cond_wait:
+ cmpl $PI_BIT, %eax
+ jne 18f
+
+-90:
+ movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
+ movl %ebp, %edx
+ xorl %esi, %esi
+@@ -152,11 +151,22 @@ __pthread_cond_wait:
+ sete 16(%esp)
+ je 19f
+
+- cmpl $-EAGAIN, %eax
+- je 91f
+-
+- /* Normal and PI futexes dont mix. Use normal futex functions only
+- if the kernel does not support the PI futex functions. */
++ /* 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
+@@ -206,12 +216,12 @@ __pthread_cond_wait:
+ cmpl 8(%esp), %edx
+ jne 7f
+ cmpl 4(%esp), %edi
+- je 8b
++ je 22f
+
+ 7: cmpl %ecx, %edx
+ jne 9f
+ cmp %eax, %edi
+- je 8b
++ je 22f
+
+ 9: addl $1, woken_seq(%ebx)
+ adcl $0, woken_seq+4(%ebx)
+@@ -287,6 +297,22 @@ __pthread_cond_wait:
+ 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
+@@ -400,77 +426,6 @@ __pthread_cond_wait:
+ call __lll_unlock_wake
+ jmp 11b
+
+-91:
+-.LcleanupSTART2:
+- /* FUTEX_WAIT_REQUEUE_PI returned EAGAIN. We need to
+- call it again. */
+-
+- /* 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 92f
+-
+-#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
+-
+-92:
+- /* Increment the cond_futex value again, so it can be used as a new
+- expected value. */
+- addl $1, cond_futex(%ebx)
+- movl cond_futex(%ebx), %ebp
+-
+- /* Unlock. */
+- LOCK
+-#if cond_lock == 0
+- subl $1, (%ebx)
+-#else
+- subl $1, cond_lock(%ebx)
+-#endif
+- je 93f
+-#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
+-
+-93:
+- /* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */
+- xorl %ecx, %ecx
+- movl dep_mutex(%ebx), %edi
+- jmp 90b
+-.LcleanupEND2:
+-
+ .size __pthread_cond_wait, .-__pthread_cond_wait
+ versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
+ GLIBC_2_3_2)
+@@ -651,10 +606,6 @@ __condvar_w_cleanup:
+ .long .LcleanupEND-.Lsub_cond_futex
+ .long __condvar_w_cleanup-.LSTARTCODE
+ .uleb128 0
+- .long .LcleanupSTART2-.LSTARTCODE
+- .long .LcleanupEND2-.LcleanupSTART2
+- .long __condvar_w_cleanup-.LSTARTCODE
+- .uleb128 0
+ .long .LcallUR-.LSTARTCODE
+ .long .LENDCODE-.LcallUR
+ .long 0
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+index a1c8ca8..b669abb 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+@@ -103,7 +103,7 @@ __pthread_cond_timedwait:
+ mov %RSI_LP, dep_mutex(%rdi)
+
+ 22:
+- xorl %r15d, %r15d
++ xorb %r15b, %r15b
+
+ #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
+ # ifdef PIC
+@@ -190,18 +190,39 @@ __pthread_cond_timedwait:
+ movl $SYS_futex, %eax
+ syscall
+
+- movl $1, %r15d
++ cmpl $0, %eax
++ sete %r15b
++
+ #ifdef __ASSUME_REQUEUE_PI
+ jmp 62f
+ #else
+- cmpq $-4095, %rax
+- jnae 62f
++ 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: xorl %r15d, %r15d
++60: xorb %r15b, %r15b
+ xorl %eax, %eax
+ /* The following only works like this because we only support
+ two clocks, represented using a single bit. */
+@@ -248,7 +269,23 @@ __pthread_cond_timedwait:
+ ja 39f
+
+ 45: cmpq $-ETIMEDOUT, %r14
+- jne 38b
++ 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)
+@@ -298,7 +335,7 @@ __pthread_cond_timedwait:
+ /* If requeue_pi is used the kernel performs the locking of the
+ mutex. */
+ 41: movq 16(%rsp), %rdi
+- testl %r15d, %r15d
++ testb %r15b, %r15b
+ jnz 64f
+
+ callq __pthread_mutex_cond_lock
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+index 6194852..ec403cd 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+@@ -136,19 +136,36 @@ __pthread_cond_wait:
+ cmpl $PI_BIT, %eax
+ jne 61f
+
+-90:
+ movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
+ movl $SYS_futex, %eax
+ syscall
+
+- movl $1, %r8d
+- cmpq $-EAGAIN, %rax
+- je 91f
++ cmpl $0, %eax
++ sete %r8b
++
+ #ifdef __ASSUME_REQUEUE_PI
+ jmp 62f
+ #else
+- cmpq $-4095, %rax
+- jnae 62f
++ 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
+@@ -161,7 +178,7 @@ __pthread_cond_wait:
+ #else
+ orl %fs:PRIVATE_FUTEX, %esi
+ #endif
+-60: xorl %r8d, %r8d
++60: xorb %r8b, %r8b
+ movl $SYS_futex, %eax
+ syscall
+
+@@ -191,10 +208,10 @@ __pthread_cond_wait:
+ jne 16f
+
+ cmpq 24(%rsp), %r9
+- jbe 8b
++ jbe 19f
+
+ cmpq %rax, %r9
+- jna 8b
++ jna 19f
+
+ incq woken_seq(%rdi)
+
+@@ -236,7 +253,7 @@ __pthread_cond_wait:
+ /* If requeue_pi is used the kernel performs the locking of the
+ mutex. */
+ 11: movq 16(%rsp), %rdi
+- testl %r8d, %r8d
++ testb %r8b, %r8b
+ jnz 18f
+
+ callq __pthread_mutex_cond_lock
+@@ -253,6 +270,23 @@ __pthread_cond_wait:
+ 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
+@@ -331,69 +365,6 @@ __pthread_cond_wait:
+ 13: movq %r10, %rax
+ jmp 14b
+
+-91:
+-.LcleanupSTART2:
+- /* FUTEX_WAIT_REQUEUE_PI returned EAGAIN. We need to
+- call it again. */
+- movq 8(%rsp), %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
+- jz 92f
+-
+-#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
+-92:
+- /* Increment the cond_futex value again, so it can be used as a new
+- expected value. */
+- incl cond_futex(%rdi)
+- movl cond_futex(%rdi), %edx
+-
+- /* Release internal lock. */
+- LOCK
+-#if cond_lock == 0
+- decl (%rdi)
+-#else
+- decl cond_lock(%rdi)
+-#endif
+- jz 93f
+-
+-#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
+-93:
+- /* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */
+- xorq %r10, %r10
+- mov dep_mutex(%rdi), %R8_LP
+- leaq cond_futex(%rdi), %rdi
+- jmp 90b
+-.LcleanupEND2:
+-
+ .size __pthread_cond_wait, .-__pthread_cond_wait
+ versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
+ GLIBC_2_3_2)
+@@ -547,10 +518,6 @@ __condvar_cleanup1:
+ .uleb128 .LcleanupEND-.LcleanupSTART
+ .uleb128 __condvar_cleanup1-.LSTARTCODE
+ .uleb128 0
+- .uleb128 .LcleanupSTART2-.LSTARTCODE
+- .uleb128 .LcleanupEND2-.LcleanupSTART2
+- .uleb128 __condvar_cleanup1-.LSTARTCODE
+- .uleb128 0
+ .uleb128 .LcallUR-.LSTARTCODE
+ .uleb128 .LENDCODE-.LcallUR
+ .uleb128 0
+diff --git a/nptl/tst-cond24.c b/nptl/tst-cond24.c
+new file mode 100644
+index 0000000..2eb2df1
+--- /dev/null
++++ b/nptl/tst-cond24.c
+@@ -0,0 +1,249 @@
++/* Verify that condition variables synchronized by PI mutexes don't hang.
++ Copyright (C) 2012 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
++ <http://www.gnu.org/licenses/>. */
++
++#include <pthread.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/syscall.h>
++#include <unistd.h>
++#include <sys/time.h>
++#include <time.h>
++
++#define THREADS_NUM 5
++#define MAXITER 50000
++
++static pthread_mutex_t mutex;
++static pthread_mutexattr_t mutex_attr;
++static pthread_cond_t cond;
++static pthread_t threads[THREADS_NUM];
++static int pending = 0;
++
++typedef void * (*threadfunc) (void *);
++
++void *
++thread_fun_timed (void *arg)
++{
++ int *ret = arg;
++ int rv, i;
++
++ printf ("Started thread_fun_timed[%d]\n", *ret);
++
++ for (i = 0; i < MAXITER / THREADS_NUM; i++)
++ {
++ rv = pthread_mutex_lock (&mutex);
++ if (rv)
++ {
++ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
++ *ret = 1;
++ goto out;
++ }
++
++ while (!pending)
++ {
++ struct timespec ts;
++ clock_gettime(CLOCK_REALTIME, &ts);
++ ts.tv_sec += 20;
++ rv = pthread_cond_timedwait (&cond, &mutex, &ts);
++
++ /* There should be no timeout either. */
++ if (rv)
++ {
++ printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv);
++ *ret = 1;
++ goto out;
++ }
++ }
++
++ pending--;
++
++ rv = pthread_mutex_unlock (&mutex);
++ if (rv)
++ {
++ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
++ *ret = 1;
++ goto out;
++ }
++ }
++
++ *ret = 0;
++
++out:
++ return ret;
++}
++
++void *
++thread_fun (void *arg)
++{
++ int *ret = arg;
++ int rv, i;
++
++ printf ("Started thread_fun[%d]\n", *ret);
++
++ for (i = 0; i < MAXITER / THREADS_NUM; i++)
++ {
++ rv = pthread_mutex_lock (&mutex);
++ if (rv)
++ {
++ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
++ *ret = 1;
++ goto out;
++ }
++
++ while (!pending)
++ {
++ rv = pthread_cond_wait (&cond, &mutex);
++
++ if (rv)
++ {
++ printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv);
++ *ret = 1;
++ goto out;
++ }
++ }
++
++ pending--;
++
++ rv = pthread_mutex_unlock (&mutex);
++ if (rv)
++ {
++ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
++ *ret = 1;
++ goto out;
++ }
++ }
++
++ *ret = 0;
++
++out:
++ return ret;
++}
++
++static int
++do_test_wait (threadfunc f)
++{
++ int i;
++ int rv;
++ int counter = 0;
++ int retval[THREADS_NUM];
++
++ puts ("Starting test");
++
++ rv = pthread_mutexattr_init (&mutex_attr);
++ if (rv)
++ {
++ printf ("pthread_mutexattr_init: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++
++ rv = pthread_mutexattr_setprotocol (&mutex_attr, PTHREAD_PRIO_INHERIT);
++ if (rv)
++ {
++ printf ("pthread_mutexattr_setprotocol: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++
++ rv = pthread_mutex_init (&mutex, &mutex_attr);
++ if (rv)
++ {
++ printf ("pthread_mutex_init: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++
++ rv = pthread_cond_init (&cond, NULL);
++ if (rv)
++ {
++ printf ("pthread_cond_init: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++
++ for (i = 0; i < THREADS_NUM; i++)
++ {
++ retval[i] = i;
++ rv = pthread_create (&threads[i], NULL, f, &retval[i]);
++ if (rv)
++ {
++ printf ("pthread_create: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++ }
++
++ for (; counter < MAXITER; counter++)
++ {
++ rv = pthread_mutex_lock (&mutex);
++ if (rv)
++ {
++ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++
++ if (!(counter % 100))
++ printf ("counter: %d\n", counter);
++ pending += 1;
++
++ rv = pthread_cond_signal (&cond);
++ if (rv)
++ {
++ printf ("pthread_cond_signal: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++
++ rv = pthread_mutex_unlock (&mutex);
++ if (rv)
++ {
++ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++ }
++
++ for (i = 0; i < THREADS_NUM; i++)
++ {
++ void *ret;
++ rv = pthread_join (threads[i], &ret);
++ if (rv)
++ {
++ printf ("pthread_join: %s(%d)\n", strerror (rv), rv);
++ return 1;
++ }
++ if (ret && *(int *)ret)
++ {
++ printf ("Thread %d returned with an error\n", i);
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++static int
++do_test (void)
++{
++ puts ("Testing pthread_cond_wait");
++ int ret = do_test_wait (thread_fun);
++ if (ret)
++ return ret;
++
++ puts ("Testing pthread_cond_timedwait");
++ return do_test_wait (thread_fun_timed);
++}
++
++#define TIMEOUT 10
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+--
+1.7.3.4
+
diff --git a/testing/glibc/glibc.install b/testing/glibc/glibc.install
index 7f85ade96..4486a3b2d 100644
--- a/testing/glibc/glibc.install
+++ b/testing/glibc/glibc.install
@@ -2,19 +2,19 @@ infodir=usr/share/info
filelist=(libc.info{,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11})
post_upgrade() {
- sbin/ldconfig -r .
- [ -x sbin/init ] && sbin/init u
- usr/sbin/locale-gen
+ ldconfig -r .
+ [[ ! -e sys/fs/cgroup/systemd && -x sbin/init ]] && init u
+ locale-gen
- [ -x usr/bin/install-info ] || return 0
+ [[ -x usr/bin/install-info ]] || return 0
for file in ${filelist[@]}; do
- usr/bin/install-info $infodir/$file.gz $infodir/dir 2> /dev/null
+ install-info $infodir/$file.gz $infodir/dir 2> /dev/null
done
}
pre_remove() {
- [ -x usr/bin/install-info ] || return 0
+ [[ -x usr/bin/install-info ]] || return 0
for file in ${filelist[@]}; do
- usr/bin/install-info --delete $infodir/$file.gz $infodir/dir 2> /dev/null
+ install-info --delete $infodir/$file.gz $infodir/dir 2> /dev/null
done
}
diff --git a/testing/glibc/nscd.service b/testing/glibc/nscd.service
index de5315e9b..bc80a0730 100644
--- a/testing/glibc/nscd.service
+++ b/testing/glibc/nscd.service
@@ -9,7 +9,7 @@ ExecStop=/usr/sbin/nscd --shutdown
ExecReload=/usr/sbin/nscd -i passwd
ExecReload=/usr/sbin/nscd -i group
ExecReload=/usr/sbin/nscd -i hosts
-ExecReload=/usr/sbin/nscd -i service
+ExecReload=/usr/sbin/nscd -i services
Restart=always
PIDFile=/run/nscd/nscd.pid