diff options
33 files changed, 13368 insertions, 0 deletions
@@ -0,0 +1 @@ +/glibc-2.31.tar.xz diff --git a/Avoid-ldbl-96-stack-corruption-from-range-reduction-.patch b/Avoid-ldbl-96-stack-corruption-from-range-reduction-.patch new file mode 100644 index 0000000..09522fa --- /dev/null +++ b/Avoid-ldbl-96-stack-corruption-from-range-reduction-.patch @@ -0,0 +1,126 @@ +From 9f997ceca28f0634ad78a1ca95b84265f7801ff4 Mon Sep 17 00:00:00 2001 +From: Joseph Myers <joseph@codesourcery.com> +Date: Wed, 12 Feb 2020 23:31:56 +0000 +Subject: [PATCH] Avoid ldbl-96 stack corruption from range reduction of + pseudo-zero (bug 25487). + +Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero +argument (an representation where all the significand bits, including +the explicit high bit, are zero, but the exponent is not zero, which +is not a valid representation for the long double type). + +Although this is not a valid long double representation, existing +practice in this area (see bug 4586, originally marked invalid but +subsequently fixed) is that we still seek to avoid invalid memory +accesses as a result, in case of programs that treat arbitrary binary +data as long double representations, although the invalid +representations of the ldbl-96 format do not need to be consistently +handled the same as any particular valid representation. + +This patch makes the range reduction detect pseudo-zero and unnormal +representations that would otherwise go to __kernel_rem_pio2, and +returns a NaN for them instead of continuing with the range reduction +process. (Pseudo-zero and unnormal representations whose unbiased +exponent is less than -1 have already been safely returned from the +function before this point without going through the rest of range +reduction.) Pseudo-zero representations would previously result in +the value passed to __kernel_rem_pio2 being all-zero, which is +definitely unsafe; unnormal representations would previously result in +a value passed whose high bit is zero, which might well be unsafe +since that is not a form of input expected by __kernel_rem_pio2. + +Tested for x86_64. + +(cherry picked from commit 9333498794cde1d5cca518badf79533a24114b6f) +--- + sysdeps/ieee754/ldbl-96/Makefile | 3 ++- + sysdeps/ieee754/ldbl-96/e_rem_pio2l.c | 12 +++++++++ + sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c | 41 ++++++++++++++++++++++++++++++ + 4 files changed, 60 insertions(+), 1 deletion(-) + create mode 100644 sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c + +diff --git a/sysdeps/ieee754/ldbl-96/Makefile b/sysdeps/ieee754/ldbl-96/Makefile +index 995e90d..318628a 100644 +--- a/sysdeps/ieee754/ldbl-96/Makefile ++++ b/sysdeps/ieee754/ldbl-96/Makefile +@@ -17,5 +17,6 @@ + # <https://www.gnu.org/licenses/>. + + ifeq ($(subdir),math) +-tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 ++tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo ++CFLAGS-test-sinl-pseudo.c += -fstack-protector-all + endif +diff --git a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c +index 5f74232..bcdf201 100644 +--- a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c ++++ b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c +@@ -210,6 +210,18 @@ __ieee754_rem_pio2l (long double x, long double *y) + return 0; + } + ++ if ((i0 & 0x80000000) == 0) ++ { ++ /* Pseudo-zero and unnormal representations are not valid ++ representations of long double. We need to avoid stack ++ corruption in __kernel_rem_pio2, which expects input in a ++ particular normal form, but those representations do not need ++ to be consistently handled like any particular floating-point ++ value. */ ++ y[1] = y[0] = __builtin_nanl (""); ++ return 0; ++ } ++ + /* Split the 64 bits of the mantissa into three 24-bit integers + stored in a double array. */ + exp = j0 - 23; +diff --git a/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c +new file mode 100644 +index 0000000..f59b977 +--- /dev/null ++++ b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c +@@ -0,0 +1,41 @@ ++/* Test sinl for pseudo-zeros and unnormals for ldbl-96 (bug 25487). ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <math.h> ++#include <math_ldbl.h> ++#include <stdint.h> ++ ++static int ++do_test (void) ++{ ++ for (int i = 0; i < 64; i++) ++ { ++ uint64_t sig = i == 63 ? 0 : 1ULL << i; ++ long double ld; ++ SET_LDOUBLE_WORDS (ld, 0x4141, ++ sig >> 32, sig & 0xffffffffULL); ++ /* The requirement is that no stack overflow occurs when the ++ pseudo-zero or unnormal goes through range reduction. */ ++ volatile long double ldr; ++ ldr = sinl (ld); ++ (void) ldr; ++ } ++ return 0; ++} ++ ++#include <support/test-driver.c> +-- +2.7.4 + diff --git a/Disable-warnings-due-to-deprecated-libselinux-symbol.patch b/Disable-warnings-due-to-deprecated-libselinux-symbol.patch new file mode 100644 index 0000000..25e6d57 --- /dev/null +++ b/Disable-warnings-due-to-deprecated-libselinux-symbol.patch @@ -0,0 +1,104 @@ +From 04726be814c6fd6d9cf974e15d684dd3ac1a180e Mon Sep 17 00:00:00 2001 +From: Arjun Shankar <arjun@redhat.com> +Date: Thu, 23 Jul 2020 12:20:38 +0200 +Subject: [PATCH] Disable warnings due to deprecated libselinux symbols used by + nss and nscd + +The SELinux API deprecated several symbols in its 3.1 release, including +security_context_t, matchpathcon, avc_init, and sidput, which are used in +makedb and nscd. While the usage of these should eventually be replaced by +newer interfaces, this commit disables GCC warnings due to the use of the +above symbols. + +Reviewed-by: Carlos O'Donell <carlos@redhat.com> +Tested-by: Carlos O'Donell <carlos@redhat.com> +--- + nscd/selinux.c | 15 +++++++++++++++ + nss/makedb.c | 9 +++++++++ + 2 files changed, 24 insertions(+) + +diff --git a/nscd/selinux.c b/nscd/selinux.c +index a4ea8008e2..1ebf924826 100644 +--- a/nscd/selinux.c ++++ b/nscd/selinux.c +@@ -33,6 +33,7 @@ + #ifdef HAVE_LIBAUDIT + # include <libaudit.h> + #endif ++#include <libc-diag.h> + + #include "dbg_log.h" + #include "selinux.h" +@@ -320,6 +321,12 @@ avc_free_lock (void *lock) + } + + ++/* avc_init (along with several other symbols) was marked as deprecated by the ++ SELinux API starting from version 3.1. We use it here, but should ++ eventually switch to the newer API. */ ++DIAG_PUSH_NEEDS_COMMENT ++DIAG_IGNORE_NEEDS_COMMENT (10, "-Wdeprecated-declarations"); ++ + /* Initialize the user space access vector cache (AVC) for NSCD along with + log/thread/lock callbacks. */ + void +@@ -335,7 +342,14 @@ nscd_avc_init (void) + audit_init (); + #endif + } ++DIAG_POP_NEEDS_COMMENT ++ + ++/* security_context_t and sidput (along with several other symbols) were marked ++ as deprecated by the SELinux API starting from version 3.1. We use them ++ here, but should eventually switch to the newer API. */ ++DIAG_PUSH_NEEDS_COMMENT ++DIAG_IGNORE_NEEDS_COMMENT (10, "-Wdeprecated-declarations"); + + /* Check the permission from the caller (via getpeercon) to nscd. + Returns 0 if access is allowed, 1 if denied, and -1 on error. +@@ -422,6 +436,7 @@ out: + + return rc; + } ++DIAG_POP_NEEDS_COMMENT + + + /* Wrapper to get AVC statistics. */ +diff --git a/nss/makedb.c b/nss/makedb.c +index 8e389a1683..8e1e8ec9ad 100644 +--- a/nss/makedb.c ++++ b/nss/makedb.c +@@ -38,6 +38,7 @@ + #include <sys/stat.h> + #include <sys/uio.h> + #include "nss_db/nss_db.h" ++#include <libc-diag.h> + + /* Get libc version number. */ + #include "../version.h" +@@ -841,6 +842,13 @@ print_database (int fd) + + + #ifdef HAVE_SELINUX ++ ++/* security_context_t and matchpathcon (along with several other symbols) were ++ marked as deprecated by the SELinux API starting from version 3.1. We use ++ them here, but should eventually switch to the newer API. */ ++DIAG_PUSH_NEEDS_COMMENT ++DIAG_IGNORE_NEEDS_COMMENT (10, "-Wdeprecated-declarations"); ++ + static void + set_file_creation_context (const char *outname, mode_t mode) + { +@@ -870,6 +878,7 @@ set_file_creation_context (const char *outname, mode_t mode) + freecon (ctx); + } + } ++DIAG_POP_NEEDS_COMMENT + + static void + reset_file_creation_context (void) +-- +2.23.0 + diff --git a/Fix-CVE-2020-27618-iconv-Accept-redundant-shift-sequences.patch b/Fix-CVE-2020-27618-iconv-Accept-redundant-shift-sequences.patch new file mode 100644 index 0000000..c26139f --- /dev/null +++ b/Fix-CVE-2020-27618-iconv-Accept-redundant-shift-sequences.patch @@ -0,0 +1,56 @@ +From 9a99c682144bdbd40792ebf822fe9264e0376fb5 Mon Sep 17 00:00:00 2001 +From: Arjun Shankar <arjun@redhat.com> +Date: Wed, 4 Nov 2020 12:19:38 +0100 +Subject: [PATCH] iconv: Accept redundant shift sequences in IBM1364 [BZ + #26224] + +The IBM1364, IBM1371, IBM1388, IBM1390 and IBM1399 character sets +share converter logic (iconvdata/ibm1364.c) which would reject +redundant shift sequences when processing input in these character +sets. This led to a hang in the iconv program (CVE-2020-27618). + +This commit adjusts the converter to ignore redundant shift sequences +and adds test cases for iconv_prog hangs that would be triggered upon +their rejection. This brings the implementation in line with other +converters that also ignore redundant shift sequences (e.g. IBM930 +etc., fixed in commit 692de4b3960d). + +Reviewed-by: Carlos O'Donell <carlos@redhat.com> +--- + iconvdata/ibm1364.c | 14 ++------------ + 1 files changed, 2 insertions(+), 12 deletions(-) + +diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c +index 49e7267ab45..521f0825b7f 100644 +--- a/iconvdata/ibm1364.c ++++ b/iconvdata/ibm1364.c +@@ -158,24 +158,14 @@ enum + \ + if (__builtin_expect (ch, 0) == SO) \ + { \ +- /* Shift OUT, change to DBCS converter. */ \ +- if (curcs == db) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ + curcs = db; \ + ++inptr; \ + continue; \ + } \ + if (__builtin_expect (ch, 0) == SI) \ + { \ +- /* Shift IN, change to SBCS converter. */ \ +- if (curcs == sb) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift IN, change to SBCS converter (redundant escape okay). */ \ + curcs = sb; \ + ++inptr; \ + continue; \ +-- +2.25.1 + diff --git a/Fix-CVE-2020-6096-001.patch b/Fix-CVE-2020-6096-001.patch new file mode 100644 index 0000000..d3a3d67 --- /dev/null +++ b/Fix-CVE-2020-6096-001.patch @@ -0,0 +1,189 @@ +From 79a4fa341b8a89cb03f84564fd72abaa1a2db394 Mon Sep 17 00:00:00 2001 +From: Evgeny Eremin <e.eremin@omprussia.ru> +Date: Wed, 8 Jul 2020 14:18:19 +0200 +Subject: [PATCH] arm: CVE-2020-6096: fix memcpy and memmove for negative + length [BZ #25620] + +Unsigned branch instructions could be used for r2 to fix the wrong +behavior when a negative length is passed to memcpy and memmove. +This commit fixes the generic arm implementation of memcpy amd memmove. +--- + sysdeps/arm/memcpy.S | 24 ++++++++++-------------- + sysdeps/arm/memmove.S | 24 ++++++++++-------------- + 2 files changed, 20 insertions(+), 28 deletions(-) + +diff --git a/sysdeps/arm/memcpy.S b/sysdeps/arm/memcpy.S +index 510e8adaf2..bcfbc51d99 100644 +--- a/sysdeps/arm/memcpy.S ++++ b/sysdeps/arm/memcpy.S +@@ -68,7 +68,7 @@ ENTRY(memcpy) + cfi_remember_state + + subs r2, r2, #4 +- blt 8f ++ blo 8f + ands ip, r0, #3 + PLD( pld [r1, #0] ) + bne 9f +@@ -82,7 +82,7 @@ ENTRY(memcpy) + cfi_rel_offset (r6, 4) + cfi_rel_offset (r7, 8) + cfi_rel_offset (r8, 12) +- blt 5f ++ blo 5f + + CALGN( ands ip, r1, #31 ) + CALGN( rsb r3, ip, #32 ) +@@ -98,9 +98,9 @@ ENTRY(memcpy) + #endif + + PLD( pld [r1, #0] ) +-2: PLD( subs r2, r2, #96 ) ++2: PLD( cmp r2, #96 ) + PLD( pld [r1, #28] ) +- PLD( blt 4f ) ++ PLD( blo 4f ) + PLD( pld [r1, #60] ) + PLD( pld [r1, #92] ) + +@@ -108,9 +108,7 @@ ENTRY(memcpy) + 4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr} + subs r2, r2, #32 + stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr} +- bge 3b +- PLD( cmn r2, #96 ) +- PLD( bge 4b ) ++ bhs 3b + + 5: ands ip, r2, #28 + rsb ip, ip, #32 +@@ -222,7 +220,7 @@ ENTRY(memcpy) + strbge r4, [r0], #1 + subs r2, r2, ip + strb lr, [r0], #1 +- blt 8b ++ blo 8b + ands ip, r1, #3 + beq 1b + +@@ -236,7 +234,7 @@ ENTRY(memcpy) + .macro forward_copy_shift pull push + + subs r2, r2, #28 +- blt 14f ++ blo 14f + + CALGN( ands ip, r1, #31 ) + CALGN( rsb ip, ip, #32 ) +@@ -253,9 +251,9 @@ ENTRY(memcpy) + cfi_rel_offset (r10, 16) + + PLD( pld [r1, #0] ) +- PLD( subs r2, r2, #96 ) ++ PLD( cmp r2, #96 ) + PLD( pld [r1, #28] ) +- PLD( blt 13f ) ++ PLD( blo 13f ) + PLD( pld [r1, #60] ) + PLD( pld [r1, #92] ) + +@@ -280,9 +278,7 @@ ENTRY(memcpy) + mov ip, ip, PULL #\pull + orr ip, ip, lr, PUSH #\push + stmia r0!, {r3, r4, r5, r6, r7, r8, r10, ip} +- bge 12b +- PLD( cmn r2, #96 ) +- PLD( bge 13b ) ++ bhs 12b + + pop {r5 - r8, r10} + cfi_adjust_cfa_offset (-20) +diff --git a/sysdeps/arm/memmove.S b/sysdeps/arm/memmove.S +index 954037ef3a..0d07b76ee6 100644 +--- a/sysdeps/arm/memmove.S ++++ b/sysdeps/arm/memmove.S +@@ -85,7 +85,7 @@ ENTRY(memmove) + add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 +- blt 8f ++ blo 8f + ands ip, r0, #3 + PLD( pld [r1, #-4] ) + bne 9f +@@ -99,7 +99,7 @@ ENTRY(memmove) + cfi_rel_offset (r6, 4) + cfi_rel_offset (r7, 8) + cfi_rel_offset (r8, 12) +- blt 5f ++ blo 5f + + CALGN( ands ip, r1, #31 ) + CALGN( sbcsne r4, ip, r2 ) @ C is always set here +@@ -114,9 +114,9 @@ ENTRY(memmove) + #endif + + PLD( pld [r1, #-4] ) +-2: PLD( subs r2, r2, #96 ) ++2: PLD( cmp r2, #96 ) + PLD( pld [r1, #-32] ) +- PLD( blt 4f ) ++ PLD( blo 4f ) + PLD( pld [r1, #-64] ) + PLD( pld [r1, #-96] ) + +@@ -124,9 +124,7 @@ ENTRY(memmove) + 4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr} + subs r2, r2, #32 + stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr} +- bge 3b +- PLD( cmn r2, #96 ) +- PLD( bge 4b ) ++ bhs 3b + + 5: ands ip, r2, #28 + rsb ip, ip, #32 +@@ -237,7 +235,7 @@ ENTRY(memmove) + strbge r4, [r0, #-1]! + subs r2, r2, ip + strb lr, [r0, #-1]! +- blt 8b ++ blo 8b + ands ip, r1, #3 + beq 1b + +@@ -251,7 +249,7 @@ ENTRY(memmove) + .macro backward_copy_shift push pull + + subs r2, r2, #28 +- blt 14f ++ blo 14f + + CALGN( ands ip, r1, #31 ) + CALGN( rsb ip, ip, #32 ) +@@ -268,9 +266,9 @@ ENTRY(memmove) + cfi_rel_offset (r10, 16) + + PLD( pld [r1, #-4] ) +- PLD( subs r2, r2, #96 ) ++ PLD( cmp r2, #96 ) + PLD( pld [r1, #-32] ) +- PLD( blt 13f ) ++ PLD( blo 13f ) + PLD( pld [r1, #-64] ) + PLD( pld [r1, #-96] ) + +@@ -295,9 +293,7 @@ ENTRY(memmove) + mov r4, r4, PUSH #\push + orr r4, r4, r3, PULL #\pull + stmdb r0!, {r4 - r8, r10, ip, lr} +- bge 12b +- PLD( cmn r2, #96 ) +- PLD( bge 13b ) ++ bhs 12b + + pop {r5 - r8, r10} + cfi_adjust_cfa_offset (-20) +-- +2.19.1 + diff --git a/Fix-CVE-2020-6096-002.patch b/Fix-CVE-2020-6096-002.patch new file mode 100644 index 0000000..3d65fae --- /dev/null +++ b/Fix-CVE-2020-6096-002.patch @@ -0,0 +1,107 @@ +From beea361050728138b82c57dda0c4810402d342b9 Mon Sep 17 00:00:00 2001 +From: Alexander Anisimov <a.anisimov@omprussia.ru> +Date: Wed, 8 Jul 2020 14:18:31 +0200 +Subject: [PATCH] arm: CVE-2020-6096: Fix multiarch memcpy for negative length + [BZ #25620] + +Unsigned branch instructions could be used for r2 to fix the wrong +behavior when a negative length is passed to memcpy. +This commit fixes the armv7 version. +--- + sysdeps/arm/armv7/multiarch/memcpy_impl.S | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/sysdeps/arm/armv7/multiarch/memcpy_impl.S b/sysdeps/arm/armv7/multiarch/memcpy_impl.S +index bf4ac7077f..379bb56fc9 100644 +--- a/sysdeps/arm/armv7/multiarch/memcpy_impl.S ++++ b/sysdeps/arm/armv7/multiarch/memcpy_impl.S +@@ -268,7 +268,7 @@ ENTRY(memcpy) + + mov dst, dstin /* Preserve dstin, we need to return it. */ + cmp count, #64 +- bge .Lcpy_not_short ++ bhs .Lcpy_not_short + /* Deal with small copies quickly by dropping straight into the + exit block. */ + +@@ -351,10 +351,10 @@ ENTRY(memcpy) + + 1: + subs tmp2, count, #64 /* Use tmp2 for count. */ +- blt .Ltail63aligned ++ blo .Ltail63aligned + + cmp tmp2, #512 +- bge .Lcpy_body_long ++ bhs .Lcpy_body_long + + .Lcpy_body_medium: /* Count in tmp2. */ + #ifdef USE_VFP +@@ -378,7 +378,7 @@ ENTRY(memcpy) + add src, src, #64 + vstr d1, [dst, #56] + add dst, dst, #64 +- bge 1b ++ bhs 1b + tst tmp2, #0x3f + beq .Ldone + +@@ -412,7 +412,7 @@ ENTRY(memcpy) + ldrd A_l, A_h, [src, #64]! + strd A_l, A_h, [dst, #64]! + subs tmp2, tmp2, #64 +- bge 1b ++ bhs 1b + tst tmp2, #0x3f + bne 1f + ldr tmp2,[sp], #FRAME_SIZE +@@ -482,7 +482,7 @@ ENTRY(memcpy) + add src, src, #32 + + subs tmp2, tmp2, #prefetch_lines * 64 * 2 +- blt 2f ++ blo 2f + 1: + cpy_line_vfp d3, 0 + cpy_line_vfp d4, 64 +@@ -494,7 +494,7 @@ ENTRY(memcpy) + add dst, dst, #2 * 64 + add src, src, #2 * 64 + subs tmp2, tmp2, #prefetch_lines * 64 +- bge 1b ++ bhs 1b + + 2: + cpy_tail_vfp d3, 0 +@@ -615,8 +615,8 @@ ENTRY(memcpy) + 1: + pld [src, #(3 * 64)] + subs count, count, #64 +- ldrmi tmp2, [sp], #FRAME_SIZE +- bmi .Ltail63unaligned ++ ldrlo tmp2, [sp], #FRAME_SIZE ++ blo .Ltail63unaligned + pld [src, #(4 * 64)] + + #ifdef USE_NEON +@@ -633,7 +633,7 @@ ENTRY(memcpy) + neon_load_multi d0-d3, src + neon_load_multi d4-d7, src + subs count, count, #64 +- bmi 2f ++ blo 2f + 1: + pld [src, #(4 * 64)] + neon_store_multi d0-d3, dst +@@ -641,7 +641,7 @@ ENTRY(memcpy) + neon_store_multi d4-d7, dst + neon_load_multi d4-d7, src + subs count, count, #64 +- bpl 1b ++ bhs 1b + 2: + neon_store_multi d0-d3, dst + neon_store_multi d4-d7, dst +-- +2.19.1 + diff --git a/Fix-avx2-strncmp-offset-compare-condition-check-BZ-2.patch b/Fix-avx2-strncmp-offset-compare-condition-check-BZ-2.patch new file mode 100644 index 0000000..a613744 --- /dev/null +++ b/Fix-avx2-strncmp-offset-compare-condition-check-BZ-2.patch @@ -0,0 +1,52 @@ +From 75870237ff3bb363447b03f4b0af100227570910 Mon Sep 17 00:00:00 2001 +From: Sunil K Pandey <skpgkp1@gmail.com> +Date: Fri, 12 Jun 2020 08:57:16 -0700 +Subject: [PATCH] Fix avx2 strncmp offset compare condition check [BZ #25933] + +strcmp-avx2.S: In avx2 strncmp function, strings are compared in +chunks of 4 vector size(i.e. 32x4=128 byte for avx2). After first 4 +vector size comparison, code must check whether it already passed +the given offset. This patch implement avx2 offset check condition +for strncmp function, if both string compare same for first 4 vector +size. +--- + sysdeps/x86_64/multiarch/strcmp-avx2.S | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S +index 5f88a68262..d42b04b54f 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S +@@ -591,7 +591,14 @@ L(loop_cross_page_2_vec): + movl $(PAGE_SIZE / (VEC_SIZE * 4) - 1), %esi + + testq %rdi, %rdi ++# ifdef USE_AS_STRNCMP ++ /* At this point, if %rdi value is 0, it already tested ++ VEC_SIZE*4+%r10 byte starting from %rax. This label ++ checks whether strncmp maximum offset reached or not. */ ++ je L(string_nbyte_offset_check) ++# else + je L(back_to_loop) ++# endif + tzcntq %rdi, %rcx + addq %r10, %rcx + /* Adjust for number of bytes skipped. */ +@@ -627,6 +634,14 @@ L(loop_cross_page_2_vec): + VZEROUPPER + ret + ++# ifdef USE_AS_STRNCMP ++L(string_nbyte_offset_check): ++ leaq (VEC_SIZE * 4)(%r10), %r10 ++ cmpq %r10, %r11 ++ jbe L(zero) ++ jmp L(back_to_loop) ++# endif ++ + .p2align 4 + L(cross_page_loop): + /* Check one byte/dword at a time. */ +-- +2.19.1 + diff --git a/Fix-double-free-in-__printf_fp_l-bug-26214.patch b/Fix-double-free-in-__printf_fp_l-bug-26214.patch new file mode 100644 index 0000000..996179e --- /dev/null +++ b/Fix-double-free-in-__printf_fp_l-bug-26214.patch @@ -0,0 +1,36 @@ +From ede56038e50235cd1ca7de3602c9491d3b84b49b Mon Sep 17 00:00:00 2001 +From: Joseph Myers <joseph@codesourcery.com> +Date: Thu, 9 Jul 2020 21:51:49 +0000 +Subject: [PATCH] Fix double free in __printf_fp_l (bug 26214). + +__printf_fp_l has a double free bug in the case where it allocates +memory with malloc internally, then has an I/O error while outputting +trailing padding and tries to free that already-freed memory when the +error occurs. This patch fixes this by setting the relevant pointer +to NULL after the first free (the only free of this pointer that isn't +immediately followed by returning from the function). + +note that this patch is parts of the origin one. + +Tested for x86_64 and x86. +--- + stdio-common/printf_fp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c +index 66ab59ba..c310eb8e 100644 +--- a/stdio-common/printf_fp.c ++++ b/stdio-common/printf_fp.c +@@ -1250,6 +1250,9 @@ __printf_fp_l (FILE *fp, locale_t loc, + { + free (buffer); + free (wbuffer); ++ /* Avoid a double free if the subsequent PADN encounters an ++ I/O error. */ ++ wbuffer = NULL; + } + } + +-- +2.23.0 + diff --git a/Fix-memory-leak-in-__printf_fp_l-bug-26215.patch b/Fix-memory-leak-in-__printf_fp_l-bug-26215.patch new file mode 100644 index 0000000..d888746 --- /dev/null +++ b/Fix-memory-leak-in-__printf_fp_l-bug-26215.patch @@ -0,0 +1,87 @@ +From 90663e9c814a919fa1fb41a878c06ef2fae58ed2 Mon Sep 17 00:00:00 2001 +From: Joseph Myers <joseph@codesourcery.com> +Date: Thu, 9 Jul 2020 21:52:24 +0000 +Subject: [PATCH] Fix memory leak in __printf_fp_l (bug 26215). + +__printf_fp_l has a memory leak in the case of some I/O errors, where +both buffer and wbuffer have been malloced but the handling of I/O +errors only frees wbuffer. This patch fixes this by moving the +declaration of buffer to an outer scope and ensuring that it is freed +when wbuffer is freed. + +note that this patch is parts of the origin one. + +Tested for x86_64 and x86. +--- + stdio-common/printf_fp.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c +index c310eb8e..b88e9cc6 100644 +--- a/stdio-common/printf_fp.c ++++ b/stdio-common/printf_fp.c +@@ -72,7 +72,10 @@ + if (putc (outc, fp) == EOF) \ + { \ + if (buffer_malloced) \ +- free (wbuffer); \ ++ { \ ++ free (buffer); \ ++ free (wbuffer); \ ++ } \ + return -1; \ + } \ + ++done; \ +@@ -87,7 +90,10 @@ + if (PUT (fp, wide ? (const char *) wptr : ptr, outlen) != outlen) \ + { \ + if (buffer_malloced) \ +- free (wbuffer); \ ++ { \ ++ free (buffer); \ ++ free (wbuffer); \ ++ } \ + return -1; \ + } \ + ptr += outlen; \ +@@ -110,7 +116,10 @@ + if (PAD (fp, ch, len) != len) \ + { \ + if (buffer_malloced) \ +- free (wbuffer); \ ++ { \ ++ free (buffer); \ ++ free (wbuffer); \ ++ } \ + return -1; \ + } \ + done += len; \ +@@ -259,7 +268,8 @@ __printf_fp_l (FILE *fp, locale_t loc, + + /* Buffer in which we produce the output. */ + wchar_t *wbuffer = NULL; +- /* Flag whether wbuffer is malloc'ed or not. */ ++ char *buffer = NULL; ++ /* Flag whether wbuffer and buffer are malloc'ed or not. */ + int buffer_malloced = 0; + + p.expsign = 0; +@@ -1172,7 +1182,6 @@ __printf_fp_l (FILE *fp, locale_t loc, + PADN ('0', width); + + { +- char *buffer = NULL; + char *buffer_end = NULL; + char *cp = NULL; + char *tmpptr; +@@ -1252,6 +1261,7 @@ __printf_fp_l (FILE *fp, locale_t loc, + free (wbuffer); + /* Avoid a double free if the subsequent PADN encounters an + I/O error. */ ++ buffer = NULL; + wbuffer = NULL; + } + } +-- +2.23.0 + diff --git a/Fix-strtod-multiple-precision-division-bug-bug-26137.patch b/Fix-strtod-multiple-precision-division-bug-bug-26137.patch new file mode 100644 index 0000000..43bcf34 --- /dev/null +++ b/Fix-strtod-multiple-precision-division-bug-bug-26137.patch @@ -0,0 +1,3646 @@ +From 09555b9721d090f7917f8221be2613a4d6a9b0f6 Mon Sep 17 00:00:00 2001 +From: Joseph Myers <joseph@codesourcery.com> +Date: Tue, 30 Jun 2020 23:04:06 +0000 +Subject: [PATCH] Fix strtod multiple-precision division bug (bug 26137). + +Bug 26137 reports spurious "inexact" exceptions from strtod, on 32-bit +systems only, for a decimal argument that is exactly 1 + 2^-32. In +fact the same issue also appears for 1 + 2^-64 and 1 + 2^-96 as +arguments to strtof128 on 32-bit systems, and 1 + 2^-64 as an argument +to strtof128 on 64-bit systems. In FE_DOWNWARD or FE_TOWARDZERO mode, +the return value is also incorrect. + +The problem is in the multiple-precision division logic used in the +case of dividing by a denominator that occupies at least three GMP +limbs. There was a comment "The division does not work if the upper +limb of the two-limb mumerator is greater than the denominator.", but +in fact there were problems for the case of equality (that is, where +the high limbs are equal, offset by some multiple of the GMP limb +size) as well. In such cases, the code used "quot = ~(mp_limb_t) 0;" +(with subsequent correction if that is an overestimate), because +udiv_qrnnd does not support the case of equality, but it's possible +for the shifted numerator to be greater than or equal to the +denominator, in which case that is an underestimate. To avoid that, +this patch changes the ">" condition to ">=", meaning the first +division is done with a zero high word. + +The tests added are all 1 + 2^-n for n from 1 to 113 except for those +that were already present in tst-strtod-round-data. + +Tested for x86_64 and x86. +--- + stdlib/strtod_l.c | 4 +- + stdlib/tst-strtod-round-data | 110 + + stdlib/tst-strtod-round-data.h | 3465 ++++++++++++++++++++++++++++++++ + 3 files changed, 3577 insertions(+), 2 deletions(-) + +diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c +index a3836fc12e..158da787a2 100644 +--- a/stdlib/strtod_l.c ++++ b/stdlib/strtod_l.c +@@ -1648,8 +1648,8 @@ ____STRTOF_INTERNAL (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group, + d1 = den[densize - 2]; + + /* The division does not work if the upper limb of the two-limb +- numerator is greater than the denominator. */ +- if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0) ++ numerator is greater or equal to than the denominator. */ ++ if (__mpn_cmp (num, &den[densize - numsize], numsize) >= 0) + num[numsize++] = 0; + + if (numsize < densize) +diff --git a/stdlib/tst-strtod-round-data b/stdlib/tst-strtod-round-data +index 8a898ddb0e..84ab705709 100644 +--- a/stdlib/tst-strtod-round-data ++++ b/stdlib/tst-strtod-round-data +@@ -155,3 +155,113 @@ + -179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 + -1189731495357231765085759326628007130763444687096510237472674821233261358180483686904488595472612039915115437484839309258897667381308687426274524698341565006080871634366004897522143251619531446845952345709482135847036647464830984784714280967845614138476044338404886122905286855313236158695999885790106357018120815363320780964323712757164290613406875202417365323950267880089067517372270610835647545755780793431622213451903817859630690311343850657539360649645193283178291767658965405285113556134369793281725888015908414675289832538063419234888599898980623114025121674472051872439321323198402942705341366951274739014593816898288994445173400364617928377138074411345791848573595077170437644191743889644885377684738322240608239079061399475675334739784016491742621485229014847672335977897158397334226349734811441653077758250988926030894789604676153104257260141806823027588003441951455327701598071281589597169413965608439504983171255062282026626200048042149808200002060993433681237623857880627479727072877482838438705048034164633337013385405998040701908662387301605018188262573723766279240798931717708807901740265407930976419648877869604017517691938687988088008944251258826969688364194133945780157844364946052713655454906327187428531895100278695119323496808703630436193927592692344820812834297364478686862064169042458555136532055050508189891866846863799917647547291371573500701015197559097453040033031520683518216494195636696077748110598284901343611469214274121810495077979275556645164983850062051066517084647369464036640569339464837172183352956873912042640003611618789278195710052094562761306703551840330110645101995435167626688669627763820604342480357906415354212732946756073006907088870496125050068156659252761297664065498347492661798824062312210409274584565587264846417650160123175874034726261957289081466197651553830744424709698634753627770356227126145052549125229448040149114795681359875968512808575244271871455454084894986155020794806980939215658055319165641681105966454159951476908583129721503298816585142073061480888021769818338417129396878371459575846052583142928447249703698548125295775920936450022651427249949580708203966082847550921891152133321048011973883636577825533325988852156325439335021315312134081390451021255363707903495916963125924201167877190108935255914539488216897117943269373608639074472792751116715127106396425081353553137213552890539802602978645319795100976432939091924660228878912900654210118287298298707382159717184569540515403029173307292454391789568674219640761451173600617752186991913366837033887201582071625868247133104513315097274713442728340606642890406496636104443217752811227470029162858093727701049646499540220983981932786613204254226464243689610107429923197638681545837561773535568984536053627234424277105760924864023781629665526314910906960488073475217005121136311870439925762508666032566213750416695719919674223210606724721373471234021613540712188239909701971943944347480314217903886317767779921539892177334344368907550318800833546852344370327089284147501640589448482001254237386680074457341910933774891959681016516069106149905572425810895586938833067490204900368624166301968553005687040285095450484840073528643826570403767157286512380255109954518857013476588189300004138849715883139866071547574816476727635116435462804401112711392529180570794193422686818353212799068972247697191474268157912195973794192807298886952361100880264258801320928040011928153970801130741339550003299015924978259936974358726286143980520112454369271114083747919007803406596321353417004068869443405472140675963640997405009225803505672726465095506267339268892424364561897661906898424186770491035344080399248327097911712881140170384182058601614758284200750183500329358499691864066590539660709069537381601887679046657759654588001937117771344698326428792622894338016112445533539447087462049763409147542099248815521395929388007711172017894897793706604273480985161028815458787911160979113422433557549170905442026397275695283207305331845419990749347810524006194197200591652147867193696254337864981603833146354201700628817947177518115217674352016511172347727727075220056177748218928597158346744541337107358427757919660562583883823262178961691787226118865632764934288772405859754877759869235530653929937901193611669007472354746360764601872442031379944139824366828698790212922996174192728625891720057612509349100482545964152046477925114446500732164109099345259799455690095576788686397487061948854749024863607921857834205793797188834779656273479112388585706424836379072355410286787018527401653934219888361061949671961055068686961468019035629749424086587195041004404915266476272761070511568387063401264136517237211409916458796347624949215904533937210937520465798300175408017538862312719042361037129338896586028150046596078872444365564480545689033575955702988396719744528212984142578483954005084264327730840985420021409069485412320805268520094146798876110414583170390473982488899228091818213934288295679717369943152460447027290669964066815 + +0x.80000000000000000000000000000001p1025 ++1.5 ++1.25 ++1.125 ++1.0625 ++1.03125 ++1.015625 ++1.0078125 ++1.00390625 ++1.001953125 ++1.0009765625 ++1.00048828125 ++1.000244140625 ++1.0001220703125 ++1.00006103515625 ++1.000030517578125 ++1.0000152587890625 ++1.00000762939453125 ++1.000003814697265625 ++1.0000019073486328125 ++1.00000095367431640625 ++1.000000476837158203125 ++1.0000000298023223876953125 ++1.00000001490116119384765625 ++1.000000007450580596923828125 ++1.0000000037252902984619140625 ++1.00000000186264514923095703125 ++1.000000000931322574615478515625 ++1.0000000004656612873077392578125 ++1.00000000023283064365386962890625 ++1.000000000116415321826934814453125 ++1.0000000000582076609134674072265625 ++1.00000000002910383045673370361328125 ++1.000000000014551915228366851806640625 ++1.0000000000072759576141834259033203125 ++1.00000000000363797880709171295166015625 ++1.000000000001818989403545856475830078125 ++1.0000000000009094947017729282379150390625 ++1.00000000000045474735088646411895751953125 ++1.000000000000227373675443232059478759765625 ++1.0000000000001136868377216160297393798828125 ++1.00000000000005684341886080801486968994140625 ++1.000000000000028421709430404007434844970703125 ++1.0000000000000142108547152020037174224853515625 ++1.00000000000000710542735760100185871124267578125 ++1.000000000000003552713678800500929355621337890625 ++1.0000000000000017763568394002504646778106689453125 ++1.00000000000000088817841970012523233890533447265625 ++1.000000000000000444089209850062616169452667236328125 ++1.0000000000000002220446049250313080847263336181640625 ++1.00000000000000011102230246251565404236316680908203125 ++1.000000000000000055511151231257827021181583404541015625 ++1.0000000000000000277555756156289135105907917022705078125 ++1.00000000000000001387778780781445675529539585113525390625 ++1.000000000000000006938893903907228377647697925567626953125 ++1.0000000000000000034694469519536141888238489627838134765625 ++1.00000000000000000173472347597680709441192448139190673828125 ++1.000000000000000000867361737988403547205962240695953369140625 ++1.0000000000000000004336808689942017736029811203479766845703125 ++1.00000000000000000021684043449710088680149056017398834228515625 ++1.000000000000000000108420217248550443400745280086994171142578125 ++1.0000000000000000000542101086242752217003726400434970855712890625 ++1.00000000000000000002710505431213761085018632002174854278564453125 ++1.000000000000000000013552527156068805425093160010874271392822265625 ++1.0000000000000000000067762635780344027125465800054371356964111328125 ++1.00000000000000000000338813178901720135627329000271856784820556640625 ++1.000000000000000000001694065894508600678136645001359283924102783203125 ++1.0000000000000000000008470329472543003390683225006796419620513916015625 ++1.00000000000000000000042351647362715016953416125033982098102569580078125 ++1.000000000000000000000211758236813575084767080625169910490512847900390625 ++1.0000000000000000000001058791184067875423835403125849552452564239501953125 ++1.00000000000000000000005293955920339377119177015629247762262821197509765625 ++1.000000000000000000000026469779601696885595885078146238811314105987548828125 ++1.0000000000000000000000132348898008484427979425390731194056570529937744140625 ++1.00000000000000000000000661744490042422139897126953655970282852649688720703125 ++1.000000000000000000000003308722450212110699485634768279851414263248443603515625 ++1.0000000000000000000000016543612251060553497428173841399257071316242218017578125 ++1.00000000000000000000000082718061255302767487140869206996285356581211090087890625 ++1.000000000000000000000000413590306276513837435704346034981426782906055450439453125 ++1.0000000000000000000000002067951531382569187178521730174907133914530277252197265625 ++1.00000000000000000000000010339757656912845935892608650874535669572651386260986328125 ++1.000000000000000000000000051698788284564229679463043254372678347863256931304931640625 ++1.0000000000000000000000000258493941422821148397315216271863391739316284656524658203125 ++1.00000000000000000000000001292469707114105741986576081359316958696581423282623291015625 ++1.000000000000000000000000006462348535570528709932880406796584793482907116413116455078125 ++1.0000000000000000000000000032311742677852643549664402033982923967414535582065582275390625 ++1.00000000000000000000000000161558713389263217748322010169914619837072677910327911376953125 ++1.000000000000000000000000000807793566946316088741610050849573099185363389551639556884765625 ++1.0000000000000000000000000004038967834731580443708050254247865495926816947758197784423828125 ++1.00000000000000000000000000020194839173657902218540251271239327479634084738790988922119140625 ++1.000000000000000000000000000100974195868289511092701256356196637398170423693954944610595703125 ++1.0000000000000000000000000000504870979341447555463506281780983186990852118469774723052978515625 ++1.00000000000000000000000000002524354896707237777317531408904915934954260592348873615264892578125 ++1.000000000000000000000000000012621774483536188886587657044524579674771302961744368076324462890625 ++1.0000000000000000000000000000063108872417680944432938285222622898373856514808721840381622314453125 ++1.00000000000000000000000000000315544362088404722164691426113114491869282574043609201908111572265625 ++1.000000000000000000000000000001577721810442023610823457130565572459346412870218046009540557861328125 ++1.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625 ++1.00000000000000000000000000000039443045261050590270586428264139311483660321755451150238513946533203125 ++1.000000000000000000000000000000197215226305252951352932141320696557418301608777255751192569732666015625 ++1.0000000000000000000000000000000986076131526264756764660706603482787091508043886278755962848663330078125 ++1.00000000000000000000000000000004930380657631323783823303533017413935457540219431393779814243316650390625 ++1.000000000000000000000000000000024651903288156618919116517665087069677287701097156968899071216583251953125 ++1.0000000000000000000000000000000123259516440783094595582588325435348386438505485784844495356082916259765625 ++1.00000000000000000000000000000000616297582203915472977912941627176741932192527428924222476780414581298828125 ++1.000000000000000000000000000000003081487911019577364889564708135883709660962637144621112383902072906494140625 ++1.0000000000000000000000000000000015407439555097886824447823540679418548304813185723105561919510364532470703125 ++1.00000000000000000000000000000000077037197775489434122239117703397092741524065928615527809597551822662353515625 ++1.000000000000000000000000000000000385185988877447170611195588516985463707620329643077639047987759113311767578125 ++1.0000000000000000000000000000000001925929944387235853055977942584927318538101648215388195239938795566558837890625 ++1.00000000000000000000000000000000009629649721936179265279889712924636592690508241076940976199693977832794189453125 +diff --git a/stdlib/tst-strtod-round-data.h b/stdlib/tst-strtod-round-data.h +index 5ac25f7b29..8899d15f9b 100644 +--- a/stdlib/tst-strtod-round-data.h ++++ b/stdlib/tst-strtod-round-data.h +@@ -11972,4 +11972,3469 @@ static const struct test tests[] = { + 0x1p+1024, false, + 0x1p+1024, false, + 0x1.0000000000000000000000000001p+1024, false), ++ TEST ("1.5", ++ true, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ true, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ true, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ true, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ true, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ true, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false, ++ 0x1.8p+0, false), ++ TEST ("1.25", ++ true, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ true, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ true, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ true, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ true, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ true, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false, ++ 0x1.4p+0, false), ++ TEST ("1.125", ++ true, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ true, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ true, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ true, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ true, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ true, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false, ++ 0x1.2p+0, false), ++ TEST ("1.0625", ++ true, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ true, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ true, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ true, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ true, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ true, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false, ++ 0x1.1p+0, false), ++ TEST ("1.03125", ++ true, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ true, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ true, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ true, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ true, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ true, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false, ++ 0x1.08p+0, false), ++ TEST ("1.015625", ++ true, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ true, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ true, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ true, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ true, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ true, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false, ++ 0x1.04p+0, false), ++ TEST ("1.0078125", ++ true, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ true, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ true, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ true, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ true, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ true, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false, ++ 0x1.02p+0, false), ++ TEST ("1.00390625", ++ true, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ true, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ true, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ true, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ true, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ true, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false, ++ 0x1.01p+0, false), ++ TEST ("1.001953125", ++ true, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ true, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ true, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ true, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ true, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ true, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false, ++ 0x1.008p+0, false), ++ TEST ("1.0009765625", ++ true, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ true, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ true, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ true, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ true, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ true, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false, ++ 0x1.004p+0, false), ++ TEST ("1.00048828125", ++ true, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ true, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ true, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ true, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ true, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ true, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false, ++ 0x1.002p+0, false), ++ TEST ("1.000244140625", ++ true, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ true, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ true, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ true, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ true, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ true, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false, ++ 0x1.001p+0, false), ++ TEST ("1.0001220703125", ++ true, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ true, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ true, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ true, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ true, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ true, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false, ++ 0x1.0008p+0, false), ++ TEST ("1.00006103515625", ++ true, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ true, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ true, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ true, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ true, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ true, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false, ++ 0x1.0004p+0, false), ++ TEST ("1.000030517578125", ++ true, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ true, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ true, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ true, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ true, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ true, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false, ++ 0x1.0002p+0, false), ++ TEST ("1.0000152587890625", ++ true, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ true, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ true, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ true, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ true, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ true, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false, ++ 0x1.0001p+0, false), ++ TEST ("1.00000762939453125", ++ true, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ true, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ true, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ true, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ true, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ true, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false, ++ 0x1.00008p+0, false), ++ TEST ("1.000003814697265625", ++ true, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ true, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ true, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ true, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ true, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ true, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false, ++ 0x1.00004p+0, false), ++ TEST ("1.0000019073486328125", ++ true, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ true, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ true, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ true, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ true, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ true, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false, ++ 0x1.00002p+0, false), ++ TEST ("1.00000095367431640625", ++ true, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ true, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ true, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ true, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ true, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ true, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false, ++ 0x1.00001p+0, false), ++ TEST ("1.000000476837158203125", ++ true, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ true, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ true, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ true, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ true, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ true, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false, ++ 0x1.000008p+0, false), ++ TEST ("1.0000000298023223876953125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ true, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ true, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ true, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ true, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false, ++ 0x1.0000008p+0, false), ++ TEST ("1.00000001490116119384765625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ true, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ true, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ true, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ true, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false, ++ 0x1.0000004p+0, false), ++ TEST ("1.000000007450580596923828125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ true, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ true, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ true, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ true, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false, ++ 0x1.0000002p+0, false), ++ TEST ("1.0000000037252902984619140625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ true, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ true, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ true, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ true, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false, ++ 0x1.0000001p+0, false), ++ TEST ("1.00000000186264514923095703125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ true, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ true, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ true, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ true, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false, ++ 0x1.00000008p+0, false), ++ TEST ("1.000000000931322574615478515625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ true, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ true, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ true, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ true, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false, ++ 0x1.00000004p+0, false), ++ TEST ("1.0000000004656612873077392578125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ true, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ true, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ true, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ true, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false, ++ 0x1.00000002p+0, false), ++ TEST ("1.00000000023283064365386962890625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ true, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ true, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ true, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ true, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false, ++ 0x1.00000001p+0, false), ++ TEST ("1.000000000116415321826934814453125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ true, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ true, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ true, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ true, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false, ++ 0x1.000000008p+0, false), ++ TEST ("1.0000000000582076609134674072265625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ true, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ true, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ true, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ true, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false, ++ 0x1.000000004p+0, false), ++ TEST ("1.00000000002910383045673370361328125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ true, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ true, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ true, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ true, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false, ++ 0x1.000000002p+0, false), ++ TEST ("1.000000000014551915228366851806640625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ true, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ true, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ true, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ true, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false, ++ 0x1.000000001p+0, false), ++ TEST ("1.0000000000072759576141834259033203125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ true, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ true, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ true, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ true, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false, ++ 0x1.0000000008p+0, false), ++ TEST ("1.00000000000363797880709171295166015625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ true, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ true, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ true, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ true, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false, ++ 0x1.0000000004p+0, false), ++ TEST ("1.000000000001818989403545856475830078125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ true, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ true, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ true, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ true, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false, ++ 0x1.0000000002p+0, false), ++ TEST ("1.0000000000009094947017729282379150390625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ true, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ true, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ true, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ true, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false, ++ 0x1.0000000001p+0, false), ++ TEST ("1.00000000000045474735088646411895751953125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ true, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ true, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ true, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ true, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false, ++ 0x1.00000000008p+0, false), ++ TEST ("1.000000000000227373675443232059478759765625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ true, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ true, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ true, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ true, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false, ++ 0x1.00000000004p+0, false), ++ TEST ("1.0000000000001136868377216160297393798828125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ true, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ true, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ true, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ true, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false, ++ 0x1.00000000002p+0, false), ++ TEST ("1.00000000000005684341886080801486968994140625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ true, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ true, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ true, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ true, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false, ++ 0x1.00000000001p+0, false), ++ TEST ("1.000000000000028421709430404007434844970703125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ true, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ true, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ true, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ true, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false, ++ 0x1.000000000008p+0, false), ++ TEST ("1.0000000000000142108547152020037174224853515625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ true, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ true, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ true, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ true, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false, ++ 0x1.000000000004p+0, false), ++ TEST ("1.00000000000000710542735760100185871124267578125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ true, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ true, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ true, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ true, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false, ++ 0x1.000000000002p+0, false), ++ TEST ("1.000000000000003552713678800500929355621337890625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ true, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ true, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ true, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ true, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false, ++ 0x1.000000000001p+0, false), ++ TEST ("1.0000000000000017763568394002504646778106689453125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ true, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ true, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ true, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ true, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false, ++ 0x1.0000000000008p+0, false), ++ TEST ("1.00000000000000088817841970012523233890533447265625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ true, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ true, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ true, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ true, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false, ++ 0x1.0000000000004p+0, false), ++ TEST ("1.000000000000000444089209850062616169452667236328125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ true, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ true, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ true, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ true, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false, ++ 0x1.0000000000002p+0, false), ++ TEST ("1.0000000000000002220446049250313080847263336181640625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ true, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false, ++ 0x1.0000000000001p+0, false), ++ TEST ("1.00000000000000011102230246251565404236316680908203125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ true, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ true, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ true, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false, ++ 0x1.00000000000008p+0, false), ++ TEST ("1.000000000000000055511151231257827021181583404541015625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ true, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ true, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ true, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false, ++ 0x1.00000000000004p+0, false), ++ TEST ("1.0000000000000000277555756156289135105907917022705078125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ true, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ true, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ true, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false, ++ 0x1.00000000000002p+0, false), ++ TEST ("1.00000000000000001387778780781445675529539585113525390625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ true, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ true, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ true, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false, ++ 0x1.00000000000001p+0, false), ++ TEST ("1.000000000000000006938893903907228377647697925567626953125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ true, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ true, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ true, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false, ++ 0x1.000000000000008p+0, false), ++ TEST ("1.0000000000000000034694469519536141888238489627838134765625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ true, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ true, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ true, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false, ++ 0x1.000000000000004p+0, false), ++ TEST ("1.0000000000000000017347234759768070944119244813919067382812" ++ "5", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ true, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ true, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ true, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false, ++ 0x1.000000000000002p+0, false), ++ TEST ("1.0000000000000000008673617379884035472059622406959533691406" ++ "25", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ true, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ true, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ true, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false, ++ 0x1.000000000000001p+0, false), ++ TEST ("1.0000000000000000004336808689942017736029811203479766845703" ++ "125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ true, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ true, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ true, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false, ++ 0x1.0000000000000008p+0, false), ++ TEST ("1.0000000000000000002168404344971008868014905601739883422851" ++ "5625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ true, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ true, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ true, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false, ++ 0x1.0000000000000004p+0, false), ++ TEST ("1.0000000000000000001084202172485504434007452800869941711425" ++ "78125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ true, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false, ++ 0x1.0000000000000002p+0, false), ++ TEST ("1.0000000000000000000542101086242752217003726400434970855712" ++ "890625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000001p+0, false, ++ 0x1.0000000000000001p+0, false, ++ 0x1.0000000000000001p+0, false, ++ 0x1.0000000000000001p+0, false, ++ true, ++ 0x1.0000000000000001p+0, false, ++ 0x1.0000000000000001p+0, false, ++ 0x1.0000000000000001p+0, false, ++ 0x1.0000000000000001p+0, false), ++ TEST ("1.0000000000000000000271050543121376108501863200217485427856" ++ "4453125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000008p+0, false, ++ 0x1.00000000000000008p+0, false, ++ 0x1.00000000000000008p+0, false, ++ 0x1.00000000000000008p+0, false, ++ true, ++ 0x1.00000000000000008p+0, false, ++ 0x1.00000000000000008p+0, false, ++ 0x1.00000000000000008p+0, false, ++ 0x1.00000000000000008p+0, false), ++ TEST ("1.0000000000000000000135525271560688054250931600108742713928" ++ "22265625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000004p+0, false, ++ 0x1.00000000000000004p+0, false, ++ 0x1.00000000000000004p+0, false, ++ 0x1.00000000000000004p+0, false, ++ true, ++ 0x1.00000000000000004p+0, false, ++ 0x1.00000000000000004p+0, false, ++ 0x1.00000000000000004p+0, false, ++ 0x1.00000000000000004p+0, false), ++ TEST ("1.0000000000000000000067762635780344027125465800054371356964" ++ "111328125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000002p+0, false, ++ 0x1.00000000000000002p+0, false, ++ 0x1.00000000000000002p+0, false, ++ 0x1.00000000000000002p+0, false, ++ true, ++ 0x1.00000000000000002p+0, false, ++ 0x1.00000000000000002p+0, false, ++ 0x1.00000000000000002p+0, false, ++ 0x1.00000000000000002p+0, false), ++ TEST ("1.0000000000000000000033881317890172013562732900027185678482" ++ "0556640625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000001p+0, false, ++ 0x1.00000000000000001p+0, false, ++ 0x1.00000000000000001p+0, false, ++ 0x1.00000000000000001p+0, false, ++ true, ++ 0x1.00000000000000001p+0, false, ++ 0x1.00000000000000001p+0, false, ++ 0x1.00000000000000001p+0, false, ++ 0x1.00000000000000001p+0, false), ++ TEST ("1.0000000000000000000016940658945086006781366450013592839241" ++ "02783203125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000008p+0, false, ++ 0x1.000000000000000008p+0, false, ++ 0x1.000000000000000008p+0, false, ++ 0x1.000000000000000008p+0, false, ++ true, ++ 0x1.000000000000000008p+0, false, ++ 0x1.000000000000000008p+0, false, ++ 0x1.000000000000000008p+0, false, ++ 0x1.000000000000000008p+0, false), ++ TEST ("1.0000000000000000000008470329472543003390683225006796419620" ++ "513916015625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000004p+0, false, ++ 0x1.000000000000000004p+0, false, ++ 0x1.000000000000000004p+0, false, ++ 0x1.000000000000000004p+0, false, ++ true, ++ 0x1.000000000000000004p+0, false, ++ 0x1.000000000000000004p+0, false, ++ 0x1.000000000000000004p+0, false, ++ 0x1.000000000000000004p+0, false), ++ TEST ("1.0000000000000000000004235164736271501695341612503398209810" ++ "2569580078125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000002p+0, false, ++ 0x1.000000000000000002p+0, false, ++ 0x1.000000000000000002p+0, false, ++ 0x1.000000000000000002p+0, false, ++ true, ++ 0x1.000000000000000002p+0, false, ++ 0x1.000000000000000002p+0, false, ++ 0x1.000000000000000002p+0, false, ++ 0x1.000000000000000002p+0, false), ++ TEST ("1.0000000000000000000002117582368135750847670806251699104905" ++ "12847900390625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000001p+0, false, ++ 0x1.000000000000000001p+0, false, ++ 0x1.000000000000000001p+0, false, ++ 0x1.000000000000000001p+0, false, ++ true, ++ 0x1.000000000000000001p+0, false, ++ 0x1.000000000000000001p+0, false, ++ 0x1.000000000000000001p+0, false, ++ 0x1.000000000000000001p+0, false), ++ TEST ("1.0000000000000000000001058791184067875423835403125849552452" ++ "564239501953125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000008p+0, false, ++ 0x1.0000000000000000008p+0, false, ++ 0x1.0000000000000000008p+0, false, ++ 0x1.0000000000000000008p+0, false, ++ true, ++ 0x1.0000000000000000008p+0, false, ++ 0x1.0000000000000000008p+0, false, ++ 0x1.0000000000000000008p+0, false, ++ 0x1.0000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000529395592033937711917701562924776226" ++ "2821197509765625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000004p+0, false, ++ 0x1.0000000000000000004p+0, false, ++ 0x1.0000000000000000004p+0, false, ++ 0x1.0000000000000000004p+0, false, ++ true, ++ 0x1.0000000000000000004p+0, false, ++ 0x1.0000000000000000004p+0, false, ++ 0x1.0000000000000000004p+0, false, ++ 0x1.0000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000264697796016968855958850781462388113" ++ "14105987548828125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000002p+0, false, ++ 0x1.0000000000000000002p+0, false, ++ 0x1.0000000000000000002p+0, false, ++ 0x1.0000000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000002p+0, false, ++ 0x1.0000000000000000002p+0, false, ++ 0x1.0000000000000000002p+0, false, ++ 0x1.0000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000132348898008484427979425390731194056" ++ "570529937744140625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000001p+0, false, ++ 0x1.0000000000000000001p+0, false, ++ 0x1.0000000000000000001p+0, false, ++ 0x1.0000000000000000001p+0, false, ++ true, ++ 0x1.0000000000000000001p+0, false, ++ 0x1.0000000000000000001p+0, false, ++ 0x1.0000000000000000001p+0, false, ++ 0x1.0000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000066174449004242213989712695365597028" ++ "2852649688720703125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000008p+0, false, ++ 0x1.00000000000000000008p+0, false, ++ 0x1.00000000000000000008p+0, false, ++ 0x1.00000000000000000008p+0, false, ++ true, ++ 0x1.00000000000000000008p+0, false, ++ 0x1.00000000000000000008p+0, false, ++ 0x1.00000000000000000008p+0, false, ++ 0x1.00000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000033087224502121106994856347682798514" ++ "14263248443603515625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000004p+0, false, ++ 0x1.00000000000000000004p+0, false, ++ 0x1.00000000000000000004p+0, false, ++ 0x1.00000000000000000004p+0, false, ++ true, ++ 0x1.00000000000000000004p+0, false, ++ 0x1.00000000000000000004p+0, false, ++ 0x1.00000000000000000004p+0, false, ++ 0x1.00000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000016543612251060553497428173841399257" ++ "071316242218017578125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000002p+0, false, ++ 0x1.00000000000000000002p+0, false, ++ 0x1.00000000000000000002p+0, false, ++ 0x1.00000000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000002p+0, false, ++ 0x1.00000000000000000002p+0, false, ++ 0x1.00000000000000000002p+0, false, ++ 0x1.00000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000008271806125530276748714086920699628" ++ "5356581211090087890625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000001p+0, false, ++ 0x1.00000000000000000001p+0, false, ++ 0x1.00000000000000000001p+0, false, ++ 0x1.00000000000000000001p+0, false, ++ true, ++ 0x1.00000000000000000001p+0, false, ++ 0x1.00000000000000000001p+0, false, ++ 0x1.00000000000000000001p+0, false, ++ 0x1.00000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000004135903062765138374357043460349814" ++ "26782906055450439453125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000008p+0, false, ++ 0x1.000000000000000000008p+0, false, ++ 0x1.000000000000000000008p+0, false, ++ 0x1.000000000000000000008p+0, false, ++ true, ++ 0x1.000000000000000000008p+0, false, ++ 0x1.000000000000000000008p+0, false, ++ 0x1.000000000000000000008p+0, false, ++ 0x1.000000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000002067951531382569187178521730174907" ++ "133914530277252197265625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000004p+0, false, ++ 0x1.000000000000000000004p+0, false, ++ 0x1.000000000000000000004p+0, false, ++ 0x1.000000000000000000004p+0, false, ++ true, ++ 0x1.000000000000000000004p+0, false, ++ 0x1.000000000000000000004p+0, false, ++ 0x1.000000000000000000004p+0, false, ++ 0x1.000000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000001033975765691284593589260865087453" ++ "5669572651386260986328125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000002p+0, false, ++ 0x1.000000000000000000002p+0, false, ++ 0x1.000000000000000000002p+0, false, ++ 0x1.000000000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000002p+0, false, ++ 0x1.000000000000000000002p+0, false, ++ 0x1.000000000000000000002p+0, false, ++ 0x1.000000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000000516987882845642296794630432543726" ++ "78347863256931304931640625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000001p+0, false, ++ 0x1.000000000000000000001p+0, false, ++ 0x1.000000000000000000001p+0, false, ++ 0x1.000000000000000000001p+0, false, ++ true, ++ 0x1.000000000000000000001p+0, false, ++ 0x1.000000000000000000001p+0, false, ++ 0x1.000000000000000000001p+0, false, ++ 0x1.000000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000000258493941422821148397315216271863" ++ "391739316284656524658203125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000008p+0, false, ++ 0x1.0000000000000000000008p+0, false, ++ 0x1.0000000000000000000008p+0, false, ++ 0x1.0000000000000000000008p+0, false, ++ true, ++ 0x1.0000000000000000000008p+0, false, ++ 0x1.0000000000000000000008p+0, false, ++ 0x1.0000000000000000000008p+0, false, ++ 0x1.0000000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000000129246970711410574198657608135931" ++ "6958696581423282623291015625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000004p+0, false, ++ 0x1.0000000000000000000004p+0, false, ++ 0x1.0000000000000000000004p+0, false, ++ 0x1.0000000000000000000004p+0, false, ++ true, ++ 0x1.0000000000000000000004p+0, false, ++ 0x1.0000000000000000000004p+0, false, ++ 0x1.0000000000000000000004p+0, false, ++ 0x1.0000000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000000064623485355705287099328804067965" ++ "84793482907116413116455078125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000002p+0, false, ++ 0x1.0000000000000000000002p+0, false, ++ 0x1.0000000000000000000002p+0, false, ++ 0x1.0000000000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000002p+0, false, ++ 0x1.0000000000000000000002p+0, false, ++ 0x1.0000000000000000000002p+0, false, ++ 0x1.0000000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000000032311742677852643549664402033982" ++ "923967414535582065582275390625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000001p+0, false, ++ 0x1.0000000000000000000001p+0, false, ++ 0x1.0000000000000000000001p+0, false, ++ 0x1.0000000000000000000001p+0, false, ++ true, ++ 0x1.0000000000000000000001p+0, false, ++ 0x1.0000000000000000000001p+0, false, ++ 0x1.0000000000000000000001p+0, false, ++ 0x1.0000000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000000016155871338926321774832201016991" ++ "4619837072677910327911376953125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000008p+0, false, ++ 0x1.00000000000000000000008p+0, false, ++ 0x1.00000000000000000000008p+0, false, ++ 0x1.00000000000000000000008p+0, false, ++ true, ++ 0x1.00000000000000000000008p+0, false, ++ 0x1.00000000000000000000008p+0, false, ++ 0x1.00000000000000000000008p+0, false, ++ 0x1.00000000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000000008077935669463160887416100508495" ++ "73099185363389551639556884765625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000004p+0, false, ++ 0x1.00000000000000000000004p+0, false, ++ 0x1.00000000000000000000004p+0, false, ++ 0x1.00000000000000000000004p+0, false, ++ true, ++ 0x1.00000000000000000000004p+0, false, ++ 0x1.00000000000000000000004p+0, false, ++ 0x1.00000000000000000000004p+0, false, ++ 0x1.00000000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000000004038967834731580443708050254247" ++ "865495926816947758197784423828125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000002p+0, false, ++ 0x1.00000000000000000000002p+0, false, ++ 0x1.00000000000000000000002p+0, false, ++ 0x1.00000000000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000002p+0, false, ++ 0x1.00000000000000000000002p+0, false, ++ 0x1.00000000000000000000002p+0, false, ++ 0x1.00000000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000000002019483917365790221854025127123" ++ "9327479634084738790988922119140625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000001p+0, false, ++ 0x1.00000000000000000000001p+0, false, ++ 0x1.00000000000000000000001p+0, false, ++ 0x1.00000000000000000000001p+0, false, ++ true, ++ 0x1.00000000000000000000001p+0, false, ++ 0x1.00000000000000000000001p+0, false, ++ 0x1.00000000000000000000001p+0, false, ++ 0x1.00000000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000000001009741958682895110927012563561" ++ "96637398170423693954944610595703125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000000008p+0, false, ++ 0x1.000000000000000000000008p+0, false, ++ 0x1.000000000000000000000008p+0, false, ++ 0x1.000000000000000000000008p+0, false, ++ true, ++ 0x1.000000000000000000000008p+0, false, ++ 0x1.000000000000000000000008p+0, false, ++ 0x1.000000000000000000000008p+0, false, ++ 0x1.000000000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000000000504870979341447555463506281780" ++ "983186990852118469774723052978515625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000000004p+0, false, ++ 0x1.000000000000000000000004p+0, false, ++ 0x1.000000000000000000000004p+0, false, ++ 0x1.000000000000000000000004p+0, false, ++ true, ++ 0x1.000000000000000000000004p+0, false, ++ 0x1.000000000000000000000004p+0, false, ++ 0x1.000000000000000000000004p+0, false, ++ 0x1.000000000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000000000252435489670723777731753140890" ++ "4915934954260592348873615264892578125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000000002p+0, false, ++ 0x1.000000000000000000000002p+0, false, ++ 0x1.000000000000000000000002p+0, false, ++ 0x1.000000000000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000000002p+0, false, ++ 0x1.000000000000000000000002p+0, false, ++ 0x1.000000000000000000000002p+0, false, ++ 0x1.000000000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000000000126217744835361888865876570445" ++ "24579674771302961744368076324462890625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000000001p+0, false, ++ 0x1.000000000000000000000001p+0, false, ++ 0x1.000000000000000000000001p+0, false, ++ 0x1.000000000000000000000001p+0, false, ++ true, ++ 0x1.000000000000000000000001p+0, false, ++ 0x1.000000000000000000000001p+0, false, ++ 0x1.000000000000000000000001p+0, false, ++ 0x1.000000000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000000000063108872417680944432938285222" ++ "622898373856514808721840381622314453125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000008p+0, false, ++ true, ++ 0x1.0000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000000000031554436208840472216469142611" ++ "3114491869282574043609201908111572265625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000004p+0, false, ++ true, ++ 0x1.0000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000000000015777218104420236108234571305" ++ "65572459346412870218046009540557861328125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000000000007888609052210118054117285652" ++ "827862296732064351090230047702789306640625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.0000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000001p+0, false, ++ true, ++ 0x1.0000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000000000003944304526105059027058642826" ++ "4139311483660321755451150238513946533203125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000000008p+0, false, ++ 0x1.00000000000000000000000008p+0, false, ++ 0x1.00000000000000000000000008p+0, false, ++ 0x1.00000000000000000000000008p+0, false, ++ true, ++ 0x1.00000000000000000000000008p+0, false, ++ 0x1.00000000000000000000000008p+0, false, ++ 0x1.00000000000000000000000008p+0, false, ++ 0x1.00000000000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000000000001972152263052529513529321413" ++ "20696557418301608777255751192569732666015625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000000004p+0, false, ++ 0x1.00000000000000000000000004p+0, false, ++ 0x1.00000000000000000000000004p+0, false, ++ 0x1.00000000000000000000000004p+0, false, ++ true, ++ 0x1.00000000000000000000000004p+0, false, ++ 0x1.00000000000000000000000004p+0, false, ++ 0x1.00000000000000000000000004p+0, false, ++ 0x1.00000000000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000000000000986076131526264756764660706" ++ "603482787091508043886278755962848663330078125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000000002p+0, false, ++ 0x1.00000000000000000000000002p+0, false, ++ 0x1.00000000000000000000000002p+0, false, ++ 0x1.00000000000000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000000002p+0, false, ++ 0x1.00000000000000000000000002p+0, false, ++ 0x1.00000000000000000000000002p+0, false, ++ 0x1.00000000000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000000000000493038065763132378382330353" ++ "3017413935457540219431393779814243316650390625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.00000000000000000000000001p+0, false, ++ 0x1.00000000000000000000000001p+0, false, ++ 0x1.00000000000000000000000001p+0, false, ++ 0x1.00000000000000000000000001p+0, false, ++ true, ++ 0x1.00000000000000000000000001p+0, false, ++ 0x1.00000000000000000000000001p+0, false, ++ 0x1.00000000000000000000000001p+0, false, ++ 0x1.00000000000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000000000000246519032881566189191165176" ++ "65087069677287701097156968899071216583251953125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ true, ++ 0x1.000000000000000000000000008p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ true, ++ 0x1.000000000000000000000000008p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ 0x1.000000000000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000000000000123259516440783094595582588" ++ "325435348386438505485784844495356082916259765625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ true, ++ 0x1.000000000000000000000000004p+0, false, ++ 0x1.000000000000000000000000004p+0, false, ++ 0x1.000000000000000000000000004p+0, false, ++ 0x1.000000000000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000000000000061629758220391547297791294" ++ "1627176741932192527428924222476780414581298828125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ true, ++ 0x1.000000000000000000000000002p+0, false, ++ 0x1.000000000000000000000000002p+0, false, ++ 0x1.000000000000000000000000002p+0, false, ++ 0x1.000000000000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000000000000030814879110195773648895647" ++ "08135883709660962637144621112383902072906494140625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ true, ++ 0x1.000000000000000000000000001p+0, false, ++ 0x1.000000000000000000000000001p+0, false, ++ 0x1.000000000000000000000000001p+0, false, ++ 0x1.000000000000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000000000000015407439555097886824447823" ++ "540679418548304813185723105561919510364532470703125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ true, ++ 0x1.0000000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000000008p+0, false, ++ 0x1.0000000000000000000000000008p+0, false), ++ TEST ("1.0000000000000000000000000000000007703719777548943412223911" ++ "7703397092741524065928615527809597551822662353515625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ true, ++ 0x1.0000000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000000004p+0, false, ++ 0x1.0000000000000000000000000004p+0, false), ++ TEST ("1.0000000000000000000000000000000003851859888774471706111955" ++ "88516985463707620329643077639047987759113311767578125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ true, ++ 0x1.0000000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000000002p+0, false, ++ 0x1.0000000000000000000000000002p+0, false), ++ TEST ("1.0000000000000000000000000000000001925929944387235853055977" ++ "942584927318538101648215388195239938795566558837890625", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ true, ++ 0x1.0000000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000000001p+0, false, ++ 0x1.0000000000000000000000000001p+0, false), ++ TEST ("1.0000000000000000000000000000000000962964972193617926527988" ++ "9712924636592690508241076940976199693977832794189453125", ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000001p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000002p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.000000000000000000000000008p+0, false, ++ false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1p+0, false, ++ 0x1.0000000000000000000000000001p+0, false), + }; +-- +2.19.1 + diff --git a/Fix-use-after-free-in-glob-when-expanding-user-bug-2.patch b/Fix-use-after-free-in-glob-when-expanding-user-bug-2.patch new file mode 100644 index 0000000..0156323 --- /dev/null +++ b/Fix-use-after-free-in-glob-when-expanding-user-bug-2.patch @@ -0,0 +1,63 @@ +From ddc650e9b3dc916eab417ce9f79e67337b05035c Mon Sep 17 00:00:00 2001 +From: Andreas Schwab <schwab@suse.de> +Date: Wed, 19 Feb 2020 17:21:46 +0100 +Subject: [PATCH] Fix use-after-free in glob when expanding ~user (bug 25414) + +The value of `end_name' points into the value of `dirname', thus don't +deallocate the latter before the last use of the former. +--- + posix/glob.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/posix/glob.c b/posix/glob.c +index cba9cd18198..4580cefb9fa 100644 +--- a/posix/glob.c ++++ b/posix/glob.c +@@ -827,31 +827,32 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), + { + size_t home_len = strlen (p->pw_dir); + size_t rest_len = end_name == NULL ? 0 : strlen (end_name); +- char *d; ++ char *d, *newp; ++ bool use_alloca = glob_use_alloca (alloca_used, ++ home_len + rest_len + 1); + +- if (__glibc_unlikely (malloc_dirname)) +- free (dirname); +- malloc_dirname = 0; +- +- if (glob_use_alloca (alloca_used, home_len + rest_len + 1)) +- dirname = alloca_account (home_len + rest_len + 1, +- alloca_used); ++ if (use_alloca) ++ newp = alloca_account (home_len + rest_len + 1, alloca_used); + else + { +- dirname = malloc (home_len + rest_len + 1); +- if (dirname == NULL) ++ newp = malloc (home_len + rest_len + 1); ++ if (newp == NULL) + { + scratch_buffer_free (&pwtmpbuf); + retval = GLOB_NOSPACE; + goto out; + } +- malloc_dirname = 1; + } +- d = mempcpy (dirname, p->pw_dir, home_len); ++ d = mempcpy (newp, p->pw_dir, home_len); + if (end_name != NULL) + d = mempcpy (d, end_name, rest_len); + *d = '\0'; + ++ if (__glibc_unlikely (malloc_dirname)) ++ free (dirname); ++ dirname = newp; ++ malloc_dirname = !use_alloca; ++ + dirlen = home_len + rest_len; + dirname_modified = 1; + } +-- +2.19.1 + diff --git a/Handle-SEM_STAT_ANY-the-same-way-as-SEM_STAT-so-that.patch b/Handle-SEM_STAT_ANY-the-same-way-as-SEM_STAT-so-that.patch new file mode 100644 index 0000000..f03cb35 --- /dev/null +++ b/Handle-SEM_STAT_ANY-the-same-way-as-SEM_STAT-so-that.patch @@ -0,0 +1,41 @@ +From 574500a108be1d2a6a0dc97a075c9e98371aba Tue Sep 29 17:10:20 2020 +From: Dmitry V. Levin <ldv@altlinux.org> +Date: Tue, 29 Sep 2020 17:10:20 +0800 +Subject: [PATCH] Handle SEM_STAT_ANY the same way as SEM_STAT so that the + buffer argument of SEM_STAT_ANY is properly passed to the kernel and back. + +--- + sysdeps/unix/sysv/linux/semctl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c +index 0c3eb093..15ed333b 100644 +--- a/sysdeps/unix/sysv/linux/semctl.c ++++ b/sysdeps/unix/sysv/linux/semctl.c +@@ -72,6 +72,7 @@ __new_semctl (int semid, int semnum, int cmd, ...) + case IPC_STAT: /* arg.buf */ + case IPC_SET: + case SEM_STAT: ++ case SEM_STAT_ANY: + case IPC_INFO: /* arg.__buf */ + case SEM_INFO: + va_start (ap, cmd); +@@ -127,6 +128,7 @@ __semctl_mode16 (int semid, int semnum, int cmd, ...) + case IPC_STAT: /* arg.buf */ + case IPC_SET: + case SEM_STAT: ++ case SEM_STAT_ANY: + case IPC_INFO: /* arg.__buf */ + case SEM_INFO: + va_start (ap, cmd); +@@ -160,6 +162,7 @@ __old_semctl (int semid, int semnum, int cmd, ...) + case IPC_STAT: /* arg.buf */ + case IPC_SET: + case SEM_STAT: ++ case SEM_STAT_ANY: + case IPC_INFO: /* arg.__buf */ + case SEM_INFO: + va_start (ap, cmd); +-- +2.23.0 + diff --git a/LanguageList b/LanguageList new file mode 100644 index 0000000..7ae6391 --- /dev/null +++ b/LanguageList @@ -0,0 +1,196 @@ +glibc-langpack-aa +glibc-langpack-af +glibc-langpack-agr +glibc-langpack-ak +glibc-langpack-am +glibc-langpack-an +glibc-langpack-anp +glibc-langpack-ar +glibc-langpack-as +glibc-langpack-ast +glibc-langpack-ayc +glibc-langpack-az +glibc-langpack-be +glibc-langpack-bem +glibc-langpack-ber +glibc-langpack-bg +glibc-langpack-bhb +glibc-langpack-bho +glibc-langpack-bi +glibc-langpack-bn +glibc-langpack-bo +glibc-langpack-br +glibc-langpack-brx +glibc-langpack-bs +glibc-langpack-byn +glibc-langpack-ca +glibc-langpack-ce +glibc-langpack-chr +glibc-langpack-cmn +glibc-langpack-crh +glibc-langpack-cs +glibc-langpack-csb +glibc-langpack-cv +glibc-langpack-cy +glibc-langpack-da +glibc-langpack-de +glibc-langpack-doi +glibc-langpack-dsb +glibc-langpack-dv +glibc-langpack-dz +glibc-langpack-el +glibc-langpack-en +glibc-langpack-eo +glibc-langpack-es +glibc-langpack-et +glibc-langpack-eu +glibc-langpack-fa +glibc-langpack-ff +glibc-langpack-fi +glibc-langpack-fil +glibc-langpack-fo +glibc-langpack-fr +glibc-langpack-fur +glibc-langpack-fy +glibc-langpack-ga +glibc-langpack-gd +glibc-langpack-gez +glibc-langpack-gl +glibc-langpack-gu +glibc-langpack-gv +glibc-langpack-ha +glibc-langpack-hak +glibc-langpack-he +glibc-langpack-hi +glibc-langpack-hif +glibc-langpack-hne +glibc-langpack-hr +glibc-langpack-hsb +glibc-langpack-ht +glibc-langpack-hu +glibc-langpack-hy +glibc-langpack-ia +glibc-langpack-id +glibc-langpack-ig +glibc-langpack-ik +glibc-langpack-is +glibc-langpack-it +glibc-langpack-iu +glibc-langpack-ja +glibc-langpack-ka +glibc-langpack-kab +glibc-langpack-kk +glibc-langpack-kl +glibc-langpack-km +glibc-langpack-kn +glibc-langpack-ko +glibc-langpack-kok +glibc-langpack-ks +glibc-langpack-ku +glibc-langpack-kw +glibc-langpack-ky +glibc-langpack-lb +glibc-langpack-lg +glibc-langpack-li +glibc-langpack-lij +glibc-langpack-ln +glibc-langpack-lo +glibc-langpack-lt +glibc-langpack-lv +glibc-langpack-lzh +glibc-langpack-mag +glibc-langpack-mai +glibc-langpack-mfe +glibc-langpack-mg +glibc-langpack-mhr +glibc-langpack-mi +glibc-langpack-miq +glibc-langpack-mjw +glibc-langpack-mk +glibc-langpack-ml +glibc-langpack-mn +glibc-langpack-mni +glibc-langpack-mr +glibc-langpack-ms +glibc-langpack-mt +glibc-langpack-my +glibc-langpack-nan +glibc-langpack-nb +glibc-langpack-nds +glibc-langpack-ne +glibc-langpack-nhn +glibc-langpack-niu +glibc-langpack-nl +glibc-langpack-nn +glibc-langpack-nr +glibc-langpack-nso +glibc-langpack-oc +glibc-langpack-om +glibc-langpack-or +glibc-langpack-os +glibc-langpack-pa +glibc-langpack-pap +glibc-langpack-pl +glibc-langpack-ps +glibc-langpack-pt +glibc-langpack-quz +glibc-langpack-raj +glibc-langpack-ro +glibc-langpack-ru +glibc-langpack-rw +glibc-langpack-sa +glibc-langpack-sah +glibc-langpack-sat +glibc-langpack-sc +glibc-langpack-sd +glibc-langpack-se +glibc-langpack-sgs +glibc-langpack-shn +glibc-langpack-shs +glibc-langpack-si +glibc-langpack-sid +glibc-langpack-sk +glibc-langpack-sl +glibc-langpack-sm +glibc-langpack-so +glibc-langpack-sq +glibc-langpack-sr +glibc-langpack-ss +glibc-langpack-st +glibc-langpack-sv +glibc-langpack-sw +glibc-langpack-szl +glibc-langpack-ta +glibc-langpack-tcy +glibc-langpack-te +glibc-langpack-tg +glibc-langpack-th +glibc-langpack-the +glibc-langpack-ti +glibc-langpack-tig +glibc-langpack-tk +glibc-langpack-tl +glibc-langpack-tn +glibc-langpack-to +glibc-langpack-tpi +glibc-langpack-tr +glibc-langpack-ts +glibc-langpack-tt +glibc-langpack-ug +glibc-langpack-uk +glibc-langpack-unm +glibc-langpack-ur +glibc-langpack-uz +glibc-langpack-ve +glibc-langpack-vi +glibc-langpack-wa +glibc-langpack-wae +glibc-langpack-wal +glibc-langpack-wo +glibc-langpack-xh +glibc-langpack-yi +glibc-langpack-yo +glibc-langpack-yue +glibc-langpack-yuw +glibc-langpack-zh +glibc-langpack-zu diff --git a/LicenseList b/LicenseList new file mode 100644 index 0000000..bcffe7a --- /dev/null +++ b/LicenseList @@ -0,0 +1,26 @@ +In general, GPLv2+ is used by programs, LGPLv2+ is used for +libraries. + +LGPLv2+ with exceptions is used for things that are linked directly +into dynamically linked programs and shared libraries (e.g. crt +files, lib*_nonshared.a). Historically, this exception also applies +to parts of libio. + +GPLv2+ with exceptions is used for parts of the Arm unwinder. + +GFDL is used for the documentation. + +Some other licenses are used in various places (BSD, Inner-Net, +ISC, Public Domain). + +HSRL and FSFAP are only used in test cases, which currently do not +ship in binary RPMs, so they are not listed here. MIT is used for +scripts/install-sh, which does not ship, either. + +GPLv3+ is used by manual/texinfo.tex, which we do not use. + +LGPLv3+ is used by some Hurd code, which we do not build. + +LGPLv2 is used in one place (time/timespec_get.c, by mistake), but +it is not actually compiled, so it does not matter for libraries. + diff --git a/Reset-converter-state-after-second-wchar_t-output-Bu.patch b/Reset-converter-state-after-second-wchar_t-output-Bu.patch new file mode 100644 index 0000000..b616737 --- /dev/null +++ b/Reset-converter-state-after-second-wchar_t-output-Bu.patch @@ -0,0 +1,251 @@ +From c580e6466d6da8262820cdbad19f32c5546226cf Mon Sep 17 00:00:00 2001 +From: Carlos O'Donell <carlos@redhat.com> +Date: Fri, 27 Mar 2020 17:03:36 -0400 +Subject: [PATCH] Reset converter state after second wchar_t output (Bug 25734) + +An input BIG5-HKSCS character may be converted into at most 2 wchar_t +characters. After outputting the second whcar_t character (which was +saved in the converter state) we must reset the state. If we fail +to reset the state we will be stuck continually copying that +character to the output even if we have further input to consider. + +We add a new test case that covers the 4 BIG5-HKSCS characters +that may become 2 wchar_t characters. + +Reviewed-by: Tom Honermann <tom@honermann.net> +--- + iconvdata/Makefile | 17 ++- + iconvdata/big5hkscs.c | 3 + + iconvdata/tst-iconv-big5-hkscs-to-2ucs4.c | 160 ++++++++++++++++++++++ + 3 files changed, 176 insertions(+), 4 deletions(-) + create mode 100644 iconvdata/tst-iconv-big5-hkscs-to-2ucs4.c + +diff --git a/iconvdata/Makefile b/iconvdata/Makefile +index c83962f351b..4ec2741cdce 100644 +--- a/iconvdata/Makefile ++++ b/iconvdata/Makefile +@@ -73,7 +73,7 @@ modules.so := $(addsuffix .so, $(modules)) + ifeq (yes,$(build-shared)) + tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ + tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ +- bug-iconv10 bug-iconv11 bug-iconv12 ++ bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 + ifeq ($(have-thread-library),yes) + tests += bug-iconv3 + endif +@@ -275,16 +275,21 @@ endif + endif + endif + +-include ../Rules +- + ifeq ($(run-built-tests),yes) +-LOCALES := de_DE.UTF-8 ++LOCALES := \ ++ de_DE.UTF-8 \ ++ zh_HK.BIG5-HKSCS \ ++ $(NULL) ++ + include ../gen-locales.mk + + $(objpfx)bug-iconv6.out: $(gen-locales) + $(objpfx)tst-iconv7.out: $(gen-locales) ++$(objpfx)tst-iconv-big5-hkscs-to-2ucs4.out: $(gen-locales) + endif + ++include ../Rules ++ + # Set libof-* for each routine. + cpp-srcs-left := $(modules) $(generated-modules) $(libJIS-routines) \ + $(libKSC-routines) $(libGB-routines) $(libCNS-routines) \ +@@ -340,3 +345,7 @@ tst-tables-clean: + + $(objpfx)gconv-modules: gconv-modules + cat $(sysdeps-gconv-modules) $^ > $@ ++ ++# Test requires BIG5HKSCS. ++$(objpfx)tst-iconv-big5-hkscs-to-2ucs4.out: $(objpfx)gconv-modules \ ++ $(addprefix $(objpfx),$(modules.so)) +diff --git a/iconvdata/big5hkscs.c b/iconvdata/big5hkscs.c +index 01fcfeba76b..ef325119b18 100644 +--- a/iconvdata/big5hkscs.c ++++ b/iconvdata/big5hkscs.c +@@ -17895,6 +17895,9 @@ static struct + else \ + ++inptr; \ + } \ ++ else \ ++ /* Clear the queue and proceed to output the saved character. */ \ ++ *statep = 0; \ + \ + put32 (outptr, ch); \ + outptr += 4; \ +diff --git a/iconvdata/tst-iconv-big5-hkscs-to-2ucs4.c b/iconvdata/tst-iconv-big5-hkscs-to-2ucs4.c +new file mode 100644 +index 00000000000..8389adebf27 +--- /dev/null ++++ b/iconvdata/tst-iconv-big5-hkscs-to-2ucs4.c +@@ -0,0 +1,160 @@ ++/* Verify the BIG5HKSCS outputs that generate 2 wchar_t's (Bug 25734). ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <string.h> ++#include <locale.h> ++#include <wchar.h> ++#include <support/check.h> ++#include <support/support.h> ++ ++/* A few BIG5-HKSCS characters map in two unicode code points. ++ They are: ++ /x88/x62 => <U00CA><U0304> ++ /x88/x64 => <U00CA><U030C> ++ /x88/xa3 => <U00EA><U0304> ++ /x88/xa5 => <U00EA><U030C> ++ Each of these is special cased in iconvdata/big5hkscs.c. ++ This test ensures that we correctly reset the shift state after ++ outputting any of these characters. We do this by converting ++ each them followed by converting an ASCII character. If we fail ++ to reset the shift state (bug 25734) then we'll see the last ++ character in the queue output again. */ ++ ++/* Each test has name, input bytes, and expected wide character ++ output. */ ++struct testdata { ++ const char *name; ++ const char input[3]; ++ wchar_t expected[3]; ++}; ++ ++/* In BIG5-HKSCS (2008) there are 4 characters that generate multiple ++ wide characters. */ ++struct testdata tests[4] = { ++ /* <H-8862>X => <U+00CA><U+0304>X */ ++ { "<H-8862>", "\x88\x62\x58", { 0x00CA, 0x0304, 0x0058 } }, ++ /* <H-8864>X => <U+00CA><U+030C>X */ ++ { "<H-8864>", "\x88\x64\x58", { 0x00CA, 0x030C, 0x0058 } }, ++ /* <H-88A3>X => <U+00EA><U+0304>X */ ++ { "<H-88A3>", "\x88\xa3\x58", { 0x00EA, 0x0304, 0x0058 } }, ++ /* <H-88A5>X => <U+00EA><U+030C>X */ ++ { "<H-88A5>", "\x88\xa5\x58", { 0x00EA, 0x030C, 0x0058 } } ++}; ++ ++/* Each test is of the form: ++ - Translate first code sequence (two bytes) ++ - Translate second (zero bytes) ++ - Translate the third (one byte). */ ++static int ++check_conversion (struct testdata test) ++{ ++ int err = 0; ++ wchar_t wc; ++ mbstate_t st; ++ size_t ret; ++ const char *mbs = test.input; ++ int consumed = 0; ++ /* Input is always 3 bytes long. */ ++ int inlen = 3; ++ ++ memset (&st, 0, sizeof (st)); ++ /* First conversion: Consumes first 2 bytes. */ ++ ret = mbrtowc (&wc, mbs, inlen - consumed, &st); ++ if (ret != 2) ++ { ++ printf ("error: First conversion consumed only %zd bytes.\n", ret); ++ err++; ++ } ++ /* Advance the two consumed bytes. */ ++ mbs += ret; ++ consumed += ret; ++ if (wc != test.expected[0]) ++ { ++ printf ("error: Result of first conversion was wrong.\n"); ++ err++; ++ } ++ /* Second conversion: Consumes 0 bytes. */ ++ ret = mbrtowc (&wc, mbs, inlen - consumed, &st); ++ if (ret != 0) ++ { ++ printf ("error: Second conversion consumed only %zd bytes.\n", ret); ++ err++; ++ } ++ /* Advance the zero consumed bytes. */ ++ mbs += ret; ++ consumed += ret; ++ if (wc != test.expected[1]) ++ { ++ printf ("error: Result of second conversion was wrong.\n"); ++ err++; ++ } ++ /* After the second conversion the state of the converter should be ++ in the initial state. It is in the initial state because the two ++ input BIG5-HKSCS bytes have been consumed and the 2 wchar_t's have ++ been output. */ ++ if (mbsinit (&st) == 0) ++ { ++ printf ("error: Converter not in initial state.\n"); ++ err++; ++ } ++ /* Third conversion: Consumes 1 byte (it's an ASCII character). */ ++ ret = mbrtowc (&wc, mbs, inlen - consumed, &st); ++ if (ret != 1) ++ { ++ printf ("error: Third conversion consumed only %zd bytes.\n", ret); ++ err++; ++ } ++ /* Advance the one byte. */ ++ mbs += ret; ++ consumed += ret; ++ if (wc != test.expected[2]) ++ { ++ printf ("error: Result of third conversion was wrong.\n"); ++ err++; ++ } ++ /* Return 0 if we saw no errors. */ ++ return err; ++} ++ ++static int ++do_test (void) ++{ ++ int err = 0; ++ int ret; ++ /* Testing BIG5-HKSCS. */ ++ setlocale (LC_ALL, "zh_HK.BIG5-HKSCS"); ++ ++ /* Run all the special conversions. */ ++ for (int i = 0; i < (sizeof (tests) / sizeof (struct testdata)); i++) ++ { ++ printf ("Running test for %s\n", tests[i].name); ++ ret = check_conversion (tests[i]); ++ if (ret > 0) ++ printf ("Test %s failed.\n", tests[i].name); ++ err += ret; ++ } ++ ++ /* Fail if any conversion had an error. */ ++ if (err > 0) ++ FAIL_EXIT1 ("One or more conversions failed."); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +-- +2.19.1 + diff --git a/bench.mk b/bench.mk new file mode 100644 index 0000000..dfe46bd --- /dev/null +++ b/bench.mk @@ -0,0 +1,77 @@ +objpfx = $(prefix)/$(ver)/usr/libexec/glibc-benchtests/ + +bench-math := acos acosh asin asinh atan atanh cos cosh exp exp2 ffs ffsll \ + log log2 modf pow rint sin sincos sinh sqrt tan tanh + +bench-pthread := pthread_once + +bench := $(bench-math) $(bench-pthread) + +run-bench := $(prefix)/$(ver)/lib64/ld-linux-x86-64.so.2 --library-path $(prefix)/$(ver)/lib64 $${run} + +# String function benchmarks. +string-bench := bcopy bzero memccpy memchr memcmp memcpy memmem memmove \ + mempcpy memset rawmemchr stpcpy stpncpy strcasecmp strcasestr \ + strcat strchr strchrnul strcmp strcpy strcspn strlen \ + strncasecmp strncat strncmp strncpy strnlen strpbrk strrchr \ + strspn strstr strcpy_chk stpcpy_chk memrchr strsep strtok +string-bench-all := $(string-bench) + +stdlib-bench := strtod + +benchset := $(string-bench-all) $(stdlib-bench) + +bench-malloc := malloc-thread + +binaries-bench := $(addprefix $(objpfx)bench-,$(bench)) +binaries-benchset := $(addprefix $(objpfx)bench-,$(benchset)) +binaries-bench-malloc := $(addprefix $(objpfx)bench-,$(bench-malloc)) + +DETAILED_OPT := + +ifdef DETAILED + DETAILED_OPT := -d +endif + +bench: bench-set bench-func bench-malloc + +bench-set: $(binaries-benchset) + for run in $^; do \ + outfile=$(prefix)/$$(basename $${run}.$(ver).out); \ + echo "Running $${run}"; \ + $(run-bench) > $${outfile}.tmp; \ + mv $${outfile}{.tmp,}; \ + done + +bench-malloc: $(binaries-bench-malloc) + run=$(objpfx)bench-malloc-thread; \ + outfile=$(prefix)/$$(basename $${run}.$(ver).out); \ + for thr in 1 8 16 32; do \ + echo "Running $${run} $${thr}"; \ + $(run-bench) $${thr} > $${outfile}.tmp; \ + mv $${outfile}{.tmp,}; \ + done + +# Build and execute the benchmark functions. This target generates JSON +# formatted bench.out. Each of the programs produce independent JSON output, +# so one could even execute them individually and process it using any JSON +# capable language or tool. +bench-func: $(binaries-bench) + { echo "{\"timing_type\": \"hp-timing\","; \ + echo " \"functions\": {"; \ + for run in $^; do \ + if ! [ "x$${run}" = "x$<" ]; then \ + echo ","; \ + fi; \ + echo "Running $${run}" >&2; \ + $(run-bench) $(DETAILED_OPT); \ + done; \ + echo; \ + echo " }"; \ + echo "}"; } > $(prefix)/bench.$(ver).out-tmp; \ + if [ -f $(prefix)/bench.$(ver).out ]; then \ + mv -f $(prefix)/bench.$(ver).out{,.old}; \ + fi; \ + mv -f $(prefix)/bench.$(ver).out{-tmp,} +# scripts/validate_benchout.py bench.out \ +# scripts/benchout.schema.json diff --git a/build-extra-libpthreadcond-so.patch b/build-extra-libpthreadcond-so.patch new file mode 100644 index 0000000..8d80f07 --- /dev/null +++ b/build-extra-libpthreadcond-so.patch @@ -0,0 +1,4935 @@ +From 808cf7c45e187c1889867ac83d047abfdf81c7a3 Mon Sep 17 00:00:00 2001
+From: root <root@localhost.localdomain>
+Date: Fri, 14 Aug 2020 17:41:59 +0800
+Subject: [PATCH] performance degradation in multi-core scenarios, here is an
+ extra libpthreadcond.so using old version of the function. you can use it by
+ adding LD_PRELOAD=./libpthreadcond.so in front of your program (eg:
+ LD_PRELOAD=./libpthreadcond.so ./test). use with-libpthreadcond to compile
+ it. warning:2.17 version does not meet the posix standard, you should pay
+ attention when using it.
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=ed19993b5b0d05d62cc883571519a67dae481a14
+
+
+diff --git a/nptl_2_17/Makefile b/nptl_2_17/Makefile
+new file mode 100644
+index 00000000..4c30c5f1
+--- /dev/null
++++ b/nptl_2_17/Makefile
+@@ -0,0 +1,52 @@
++include libpthreadcond_config
++subdir=libpthreadcond
++objdir=../$(build_dir)/
++
++
++ifdef subdir
++.. := ../
++endif
++
++objpfx := $(patsubst %//,%/,$(objdir)/$(subdir)/)
++common-objpfx = $(objdir)/
++common-objdir = $(objdir)
++
++sysdep_dir := $(..)sysdeps
++export sysdep_dir := $(sysdep_dir)
++
++include $(common-objpfx)soversions.mk
++include $(common-objpfx)config.make
++
++uses-callbacks = -fexceptions
++
++sysdirs := $(foreach D,$(config-sysdirs),$(firstword $(filter /%,$D) $(..)$D))
++
+++sysdep_dirs = $(sysdirs)
+++sysdep_dirs := $(objdir) $(+sysdep_dirs)
++
+++sysdep-includes := $(foreach dir,$(+sysdep_dirs), $(addprefix -I,$(wildcard $(dir)/include) $(dir)))
++
++compile_obj = vars_2_17.os pthread_cond_wait_2_17.os pthread_cond_timedwait_2_17.os pthread_cond_signal_2_17.os pthread_cond_broadcast_2_17.os pthread_cond_init_2_17.os pthread_cond_destroy_2_17.os cleanup_compat_2_17.os unwind_2_17.os cancellation_2_17.os pthread_mutex_cond_lock_2_17.os pthread_mutex_lock_2_17.os pthread_mutex_unlock_2_17.os pthread_condattr_getclock_2_17.os pthread_condattr_getpshared_2_17.os pthread_condattr_init_2_17.os pthread_condattr_setclock_2_17.os tpp_2_17.os
++compile_obj_dir = $(foreach n,$(compile_obj),../$(build_dir)/nptl/$(n))
++
++exist_obj = lowlevellock.os lll_timedlock_wait.os pthread_mutex_conf.os
++ifeq (x86_64, $(arch))
++exist_obj += elision-lock.os elision-unlock.os elision-timed.os elision-trylock.os
++endif
++
++exist_obj_dir = $(foreach n,$(exist_obj),../$(build_dir)/nptl/$(n))
++
++CFLAGS = -c -std=gnu11 -fgnu89-inline -g -O2 -Wall -Wwrite-strings -Wundef -Werror -fmerge-all-constants -frounding-math -fno-stack-protector -Wstrict-prototypes -Wold-style-definition -fmath-errno -fPIC -ftls-model=initial-exec -DPIC -DSHARED -DTOP_NAMESPACE=glibc
++
++Headers = -I../include -I../$(build_dir)/nptl $(+sysdep-includes) -I../nptl_2_17 -I../nptl -I../libio -I../. -D_LIBC_REENTRANT -include ../$(build_dir)/libc-modules.h -include include/libc-symbols.h
++
++all: libpthreadcond.so
++
++libpthreadcond.so : $(compile_obj) libpthreadcond_pic.a
++ gcc -shared -static-libgcc -Wl,-O1 -Wl,-z,defs -Wl,-dynamic-linker=/usr/local/lib/$(ld.so-version) -B../$(build_dir)/csu/ -Wl,--version-script=libpthreadcond-$(arch).map -Wl,-soname=libpthreadcond.so.0 -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -L../$(build_dir) -L../$(build_dir)/math -L../$(build_dir)/elf -L../$(build_dir)/dlfcn -L../$(build_dir)/nss -L../$(build_dir)/nis -L../$(build_dir)/rt -L../$(build_dir)/resolv -L../$(build_dir)/mathvec -L../$(build_dir)/support -L../$(build_dir)/crypt -L../$(build_dir)/nptl -Wl,-rpath-link=../$(build_dir):../$(build_dir)/math:../$(build_dir)/elf:../$(build_dir)/dlfcn:../$(build_dir)/nss:../$(build_dir)/nis:../$(build_dir)/rt:../$(build_dir)/resolv:../$(build_dir)/mathvec:../$(build_dir)/support:../$(build_dir)/crypt:../$(build_dir)/nptl -o ../$(build_dir)/nptl/libpthreadcond.so ../$(build_dir)/csu/abi-note.o -Wl,--whole-archive ../$(build_dir)/nptl/libpthreadcond_pic.a -Wl,--no-whole-archive -Wl,--start-group ../$(build_dir)/libc.so ../$(build_dir)/libc_nonshared.a -Wl,--as-needed ../$(build_dir)/elf/ld.so -Wl,--no-as-needed -Wl,--end-group
++
++libpthreadcond_pic.a : $(compile_obj_dir) $(exist_obj_dir)
++ ar cruv ../$(build_dir)/nptl/$@ $^
++
++$(compile_obj) : %.os : %.c
++ gcc $< $(CFLAGS) $(Headers) -o ../$(build_dir)/nptl/$@ -MD -MP -MF ../$(build_dir)/nptl/$@.dt -MT ../$(build_dir)/nptl/$@
+diff --git a/nptl_2_17/bits/pthreadtypes_2_17.h b/nptl_2_17/bits/pthreadtypes_2_17.h
+new file mode 100644
+index 00000000..f501ea4c
+--- /dev/null
++++ b/nptl_2_17/bits/pthreadtypes_2_17.h
+@@ -0,0 +1,121 @@
++/* Declaration of common pthread types for all architectures.
++ Copyright (C) 2017-2020 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
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _BITS_PTHREADTYPES_COMMON_H
++# define _BITS_PTHREADTYPES_COMMON_H 1
++
++/* For internal mutex and condition variable definitions. */
++#include <bits/thread-shared-types_2_17.h>
++
++/* Thread identifiers. The structure of the attribute type is not
++ exposed on purpose. */
++typedef unsigned long int pthread_t;
++
++
++/* Data structures for mutex handling. The structure of the attribute
++ type is not exposed on purpose. */
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
++ int __align;
++} pthread_mutexattr_t;
++
++
++/* Data structure for condition variable handling. The structure of
++ the attribute type is not exposed on purpose. */
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_CONDATTR_T];
++ int __align;
++} pthread_condattr_t;
++
++
++/* Keys for thread-specific data */
++typedef unsigned int pthread_key_t;
++
++
++/* Once-only execution */
++typedef int __ONCE_ALIGNMENT pthread_once_t;
++
++
++union pthread_attr_t
++{
++ char __size[__SIZEOF_PTHREAD_ATTR_T];
++ long int __align;
++};
++#ifndef __have_pthread_attr_t
++typedef union pthread_attr_t pthread_attr_t;
++# define __have_pthread_attr_t 1
++#endif
++
++
++typedef union
++{
++ struct __pthread_mutex_s __data;
++ char __size[__SIZEOF_PTHREAD_MUTEX_T];
++ long int __align;
++} pthread_mutex_t;
++
++
++typedef union
++{
++ struct __pthread_cond_s __data;
++ char __size[__SIZEOF_PTHREAD_COND_T];
++ __extension__ long long int __align;
++} pthread_cond_t;
++
++
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K
++/* Data structure for reader-writer lock variable handling. The
++ structure of the attribute type is deliberately not exposed. */
++typedef union
++{
++ struct __pthread_rwlock_arch_t __data;
++ char __size[__SIZEOF_PTHREAD_RWLOCK_T];
++ long int __align;
++} pthread_rwlock_t;
++
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
++ long int __align;
++} pthread_rwlockattr_t;
++#endif
++
++
++#ifdef __USE_XOPEN2K
++/* POSIX spinlock data type. */
++typedef volatile int pthread_spinlock_t;
++
++
++/* POSIX barriers data type. The structure of the type is
++ deliberately not exposed. */
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_BARRIER_T];
++ long int __align;
++} pthread_barrier_t;
++
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
++ int __align;
++} pthread_barrierattr_t;
++#endif
++
++#endif
+diff --git a/nptl_2_17/bits/thread-shared-types_2_17.h b/nptl_2_17/bits/thread-shared-types_2_17.h
+new file mode 100644
+index 00000000..50e86261
+--- /dev/null
++++ b/nptl_2_17/bits/thread-shared-types_2_17.h
+@@ -0,0 +1,104 @@
++/* Common threading primitives definitions for both POSIX and C11.
++ Copyright (C) 2017-2020 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
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _THREAD_SHARED_TYPES_H
++#define _THREAD_SHARED_TYPES_H 1
++
++/* Arch-specific definitions. Each architecture must define the following
++ macros to define the expected sizes of pthread data types:
++
++ __SIZEOF_PTHREAD_ATTR_T - size of pthread_attr_t.
++ __SIZEOF_PTHREAD_MUTEX_T - size of pthread_mutex_t.
++ __SIZEOF_PTHREAD_MUTEXATTR_T - size of pthread_mutexattr_t.
++ __SIZEOF_PTHREAD_COND_T - size of pthread_cond_t.
++ __SIZEOF_PTHREAD_CONDATTR_T - size of pthread_condattr_t.
++ __SIZEOF_PTHREAD_RWLOCK_T - size of pthread_rwlock_t.
++ __SIZEOF_PTHREAD_RWLOCKATTR_T - size of pthread_rwlockattr_t.
++ __SIZEOF_PTHREAD_BARRIER_T - size of pthread_barrier_t.
++ __SIZEOF_PTHREAD_BARRIERATTR_T - size of pthread_barrierattr_t.
++
++ The additional macro defines any constraint for the lock alignment
++ inside the thread structures:
++
++ __LOCK_ALIGNMENT - for internal lock/futex usage.
++
++ Same idea but for the once locking primitive:
++
++ __ONCE_ALIGNMENT - for pthread_once_t/once_flag definition. */
++
++#include <bits/pthreadtypes-arch.h>
++
++
++/* Common definition of pthread_mutex_t. */
++
++typedef struct __pthread_internal_list
++{
++ struct __pthread_internal_list *__prev;
++ struct __pthread_internal_list *__next;
++} __pthread_list_t;
++
++typedef struct __pthread_internal_slist
++{
++ struct __pthread_internal_slist *__next;
++} __pthread_slist_t;
++
++/* Arch-specific mutex definitions. A generic implementation is provided
++ by sysdeps/nptl/bits/struct_mutex.h. If required, an architecture
++ can override it by defining:
++
++ 1. struct __pthread_mutex_s (used on both pthread_mutex_t and mtx_t
++ definition). It should contains at least the internal members
++ defined in the generic version.
++
++ 2. __LOCK_ALIGNMENT for any extra attribute for internal lock used with
++ atomic operations.
++
++ 3. The macro __PTHREAD_MUTEX_INITIALIZER used for static initialization.
++ It should initialize the mutex internal flag. */
++
++#include <bits/struct_mutex.h>
++
++/* Arch-sepecific read-write lock definitions. A generic implementation is
++ provided by struct_rwlock.h. If required, an architecture can override it
++ by defining:
++
++ 1. struct __pthread_rwlock_arch_t (used on pthread_rwlock_t definition).
++ It should contain at least the internal members defined in the
++ generic version.
++
++ 2. The macro __PTHREAD_RWLOCK_INITIALIZER used for static initialization.
++ It should initialize the rwlock internal type. */
++
++#include <bits/struct_rwlock.h>
++
++
++/* Common definition of pthread_cond_t. */
++
++struct __pthread_cond_s
++{
++ 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;
++ void *__mutex;
++ unsigned int __nwaiters;
++ unsigned int __broadcast_seq;
++};
++
++#endif /* _THREAD_SHARED_TYPES_H */
+diff --git a/nptl_2_17/build_libpthreadcondso.sh b/nptl_2_17/build_libpthreadcondso.sh
+new file mode 100644
+index 00000000..6997277b
+--- /dev/null
++++ b/nptl_2_17/build_libpthreadcondso.sh
+@@ -0,0 +1,9 @@
++#!/bin/sh
++build_arch=$1
++build_dir=$2
++config_dir=libpthreadcond_config
++
++echo arch=${build_arch} > ${config_dir}
++echo build_dir=${build_dir} >> ${config_dir}
++make
++rm -rf ${config_dir}
+diff --git a/nptl_2_17/cancellation_2_17.c b/nptl_2_17/cancellation_2_17.c
+new file mode 100644
+index 00000000..644d83bf
+--- /dev/null
++++ b/nptl_2_17/cancellation_2_17.c
+@@ -0,0 +1,104 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <setjmp.h>
++#include <stdlib.h>
++#include <futex-internal.h>
++
++
++/* The next two functions are similar to pthread_setcanceltype() but
++ more specialized for the use in the cancelable functions like write().
++ They do not need to check parameters etc. These functions must be
++ AS-safe, with the exception of the actual cancellation, because they
++ are called by wrappers around AS-safe functions like write().*/
++int
++attribute_hidden
++__pthread_enable_asynccancel (void)
++{
++ struct pthread *self = THREAD_SELF;
++ int oldval = THREAD_GETMEM (self, cancelhandling);
++
++ while (1)
++ {
++ int newval = oldval | CANCELTYPE_BITMASK;
++
++ if (newval == oldval)
++ break;
++
++ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
++ oldval);
++ if (__glibc_likely (curval == oldval))
++ {
++ if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
++ {
++ THREAD_SETMEM (self, result, PTHREAD_CANCELED);
++ __do_cancel ();
++ }
++
++ break;
++ }
++
++ /* Prepare the next round. */
++ oldval = curval;
++ }
++
++ return oldval;
++}
++
++/* See the comment for __pthread_enable_asynccancel regarding
++ the AS-safety of this function. */
++void
++attribute_hidden
++__pthread_disable_asynccancel (int oldtype)
++{
++ /* If asynchronous cancellation was enabled before we do not have
++ anything to do. */
++ if (oldtype & CANCELTYPE_BITMASK)
++ return;
++
++ struct pthread *self = THREAD_SELF;
++ int newval;
++
++ int oldval = THREAD_GETMEM (self, cancelhandling);
++
++ while (1)
++ {
++ newval = oldval & ~CANCELTYPE_BITMASK;
++
++ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
++ oldval);
++ if (__glibc_likely (curval == oldval))
++ break;
++
++ /* Prepare the next round. */
++ oldval = curval;
++ }
++
++ /* We cannot return when we are being canceled. Upon return the
++ thread might be things which would have to be undone. The
++ following loop should loop until the cancellation signal is
++ delivered. */
++ while (__builtin_expect ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
++ == CANCELING_BITMASK, 0))
++ {
++ futex_wait_simple ((unsigned int *) &self->cancelhandling, newval,
++ FUTEX_PRIVATE);
++ newval = THREAD_GETMEM (self, cancelhandling);
++ }
++}
+diff --git a/nptl_2_17/cleanup_compat_2_17.c b/nptl_2_17/cleanup_compat_2_17.c
+new file mode 100644
+index 00000000..ccc55836
+--- /dev/null
++++ b/nptl_2_17/cleanup_compat_2_17.c
+@@ -0,0 +1,50 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdlib.h>
++#include "pthreadP_2_17.h"
++
++
++void
++_pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg)
++{
++ struct pthread *self = THREAD_SELF;
++
++ buffer->__routine = routine;
++ buffer->__arg = arg;
++ buffer->__prev = THREAD_GETMEM (self, cleanup);
++
++ THREAD_SETMEM (self, cleanup, buffer);
++}
++strong_alias (_pthread_cleanup_push, __pthread_cleanup_push)
++
++
++void
++_pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, int execute)
++{
++ struct pthread *self __attribute ((unused)) = THREAD_SELF;
++
++ THREAD_SETMEM (self, cleanup, buffer->__prev);
++
++ /* If necessary call the cleanup routine after we removed the
++ current cleanup block from the list. */
++ if (execute)
++ buffer->__routine (buffer->__arg);
++}
++strong_alias (_pthread_cleanup_pop, __pthread_cleanup_pop)
+diff --git a/nptl_2_17/libpthreadcond-aarch64.map b/nptl_2_17/libpthreadcond-aarch64.map
+new file mode 100644
+index 00000000..d970af06
+--- /dev/null
++++ b/nptl_2_17/libpthreadcond-aarch64.map
+@@ -0,0 +1,8 @@
++GLIBC_2.17 {
++ global:
++ pthread_cond_init; pthread_cond_destroy;
++ pthread_cond_signal; pthread_cond_broadcast;
++ pthread_cond_wait; pthread_cond_timedwait;
++ local:
++ *;
++};
+diff --git a/nptl_2_17/libpthreadcond-x86_64.map b/nptl_2_17/libpthreadcond-x86_64.map
+new file mode 100644
+index 00000000..d7f23322
+--- /dev/null
++++ b/nptl_2_17/libpthreadcond-x86_64.map
+@@ -0,0 +1,8 @@
++GLIBC_2.3.2 {
++ global:
++ pthread_cond_init; pthread_cond_destroy;
++ pthread_cond_signal; pthread_cond_broadcast;
++ pthread_cond_wait; pthread_cond_timedwait;
++ local:
++ *;
++};
+diff --git a/nptl_2_17/pthreadP_2_17.h b/nptl_2_17/pthreadP_2_17.h
+new file mode 100644
+index 00000000..e195221a
+--- /dev/null
++++ b/nptl_2_17/pthreadP_2_17.h
+@@ -0,0 +1,620 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _PTHREADP_H
++#define _PTHREADP_H 1
++
++#include <pthread_2_17.h>
++#include <setjmp.h>
++#include <stdbool.h>
++#include <sys/syscall.h>
++#include "descr.h"
++#include <tls.h>
++#include <lowlevellock.h>
++#include <stackinfo.h>
++#include <internaltypes.h>
++#include <pthread-functions.h>
++#include <atomic.h>
++#include <kernel-features.h>
++#include <errno.h>
++#include <internal-signals.h>
++#include "pthread_mutex_conf.h"
++
++
++/* Atomic operations on TLS memory. */
++#ifndef THREAD_ATOMIC_CMPXCHG_VAL
++# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, new, old) \
++ atomic_compare_and_exchange_val_acq (&(descr)->member, new, old)
++#endif
++
++#ifndef THREAD_ATOMIC_BIT_SET
++# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
++ atomic_bit_set (&(descr)->member, bit)
++#endif
++
++
++static inline short max_adaptive_count (void)
++{
++#if HAVE_TUNABLES
++ return __mutex_aconf.spin_count;
++#else
++ return DEFAULT_ADAPTIVE_COUNT;
++#endif
++}
++
++
++/* Magic cookie representing robust mutex with dead owner. */
++#define PTHREAD_MUTEX_INCONSISTENT INT_MAX
++/* Magic cookie representing not recoverable robust mutex. */
++#define PTHREAD_MUTEX_NOTRECOVERABLE (INT_MAX - 1)
++
++#define COND_NWAITERS_SHIFT 1
++
++/* Internal mutex type value. */
++enum
++{
++ PTHREAD_MUTEX_KIND_MASK_NP = 3,
++
++ PTHREAD_MUTEX_ELISION_NP = 256,
++ PTHREAD_MUTEX_NO_ELISION_NP = 512,
++
++ PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16,
++ PTHREAD_MUTEX_ROBUST_RECURSIVE_NP
++ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP
++ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP
++ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
++ PTHREAD_MUTEX_PRIO_INHERIT_NP = 32,
++ PTHREAD_MUTEX_PI_NORMAL_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_NORMAL,
++ PTHREAD_MUTEX_PI_RECURSIVE_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_PI_ERRORCHECK_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_PI_ADAPTIVE_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
++ PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP,
++ PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_RECURSIVE_NP,
++ PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP,
++ PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP,
++ PTHREAD_MUTEX_PRIO_PROTECT_NP = 64,
++ PTHREAD_MUTEX_PP_NORMAL_NP
++ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_NORMAL,
++ PTHREAD_MUTEX_PP_RECURSIVE_NP
++ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_PP_ERRORCHECK_NP
++ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_PP_ADAPTIVE_NP
++ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
++ PTHREAD_MUTEX_ELISION_FLAGS_NP
++ = PTHREAD_MUTEX_ELISION_NP | PTHREAD_MUTEX_NO_ELISION_NP,
++
++ PTHREAD_MUTEX_TIMED_ELISION_NP =
++ PTHREAD_MUTEX_TIMED_NP | PTHREAD_MUTEX_ELISION_NP,
++ PTHREAD_MUTEX_TIMED_NO_ELISION_NP =
++ PTHREAD_MUTEX_TIMED_NP | PTHREAD_MUTEX_NO_ELISION_NP,
++};
++#define PTHREAD_MUTEX_PSHARED_BIT 128
++
++/* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++#define PTHREAD_MUTEX_TYPE(m) \
++ (atomic_load_relaxed (&((m)->__data.__kind)) & 127)
++/* Don't include NO_ELISION, as that type is always the same
++ as the underlying lock type. */
++#define PTHREAD_MUTEX_TYPE_ELISION(m) \
++ (atomic_load_relaxed (&((m)->__data.__kind)) \
++ & (127 | PTHREAD_MUTEX_ELISION_NP))
++
++#if LLL_PRIVATE == 0 && LLL_SHARED == 128
++# define PTHREAD_MUTEX_PSHARED(m) \
++ (atomic_load_relaxed (&((m)->__data.__kind)) & 128)
++#else
++# define PTHREAD_MUTEX_PSHARED(m) \
++ ((atomic_load_relaxed (&((m)->__data.__kind)) & 128) \
++ ? LLL_SHARED : LLL_PRIVATE)
++#endif
++
++/* The kernel when waking robust mutexes on exit never uses
++ FUTEX_PRIVATE_FLAG FUTEX_WAKE. */
++#define PTHREAD_ROBUST_MUTEX_PSHARED(m) LLL_SHARED
++
++/* Ceiling in __data.__lock. __data.__lock is signed, so don't
++ use the MSB bit in there, but in the mask also include that bit,
++ so that the compiler can optimize & PTHREAD_MUTEX_PRIO_CEILING_MASK
++ masking if the value is then shifted down by
++ PTHREAD_MUTEX_PRIO_CEILING_SHIFT. */
++#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 19
++#define PTHREAD_MUTEX_PRIO_CEILING_MASK 0xfff80000
++
++
++/* Flags in mutex attr. */
++#define PTHREAD_MUTEXATTR_PROTOCOL_SHIFT 28
++#define PTHREAD_MUTEXATTR_PROTOCOL_MASK 0x30000000
++#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT 12
++#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK 0x00fff000
++#define PTHREAD_MUTEXATTR_FLAG_ROBUST 0x40000000
++#define PTHREAD_MUTEXATTR_FLAG_PSHARED 0x80000000
++#define PTHREAD_MUTEXATTR_FLAG_BITS \
++ (PTHREAD_MUTEXATTR_FLAG_ROBUST | PTHREAD_MUTEXATTR_FLAG_PSHARED \
++ | PTHREAD_MUTEXATTR_PROTOCOL_MASK | PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
++
++
++/* For the following, see pthread_rwlock_common.c. */
++#define PTHREAD_RWLOCK_WRPHASE 1
++#define PTHREAD_RWLOCK_WRLOCKED 2
++#define PTHREAD_RWLOCK_RWAITING 4
++#define PTHREAD_RWLOCK_READER_SHIFT 3
++#define PTHREAD_RWLOCK_READER_OVERFLOW ((unsigned int) 1 \
++ << (sizeof (unsigned int) * 8 - 1))
++#define PTHREAD_RWLOCK_WRHANDOVER ((unsigned int) 1 \
++ << (sizeof (unsigned int) * 8 - 1))
++#define PTHREAD_RWLOCK_FUTEX_USED 2
++
++
++/* Bits used in robust mutex implementation. */
++#define FUTEX_WAITERS 0x80000000
++#define FUTEX_OWNER_DIED 0x40000000
++#define FUTEX_TID_MASK 0x3fffffff
++
++
++/* pthread_once definitions. See __pthread_once for how these are used. */
++#define __PTHREAD_ONCE_INPROGRESS 1
++#define __PTHREAD_ONCE_DONE 2
++#define __PTHREAD_ONCE_FORK_GEN_INCR 4
++
++/* Attribute to indicate thread creation was issued from C11 thrd_create. */
++#define ATTR_C11_THREAD ((void*)(uintptr_t)-1)
++
++#if 0
++/* Condition variable definitions. See __pthread_cond_wait_common.
++ Need to be defined here so there is one place from which
++ nptl_lock_constants can grab them. */
++#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
++#define __PTHREAD_COND_SHARED_MASK 1
++#endif
++
++/* Internal variables. */
++
++
++/* Default pthread attributes. */
++extern struct pthread_attr __default_pthread_attr attribute_hidden;
++extern int __default_pthread_attr_lock attribute_hidden;
++
++/* Size and alignment of static TLS block. */
++extern size_t __static_tls_size attribute_hidden;
++extern size_t __static_tls_align_m1 attribute_hidden;
++
++/* Flag whether the machine is SMP or not. */
++extern int __is_smp attribute_hidden;
++
++/* Thread descriptor handling. */
++extern list_t __stack_user;
++hidden_proto (__stack_user)
++
++/* Attribute handling. */
++extern struct pthread_attr *__attr_list attribute_hidden;
++extern int __attr_list_lock attribute_hidden;
++
++/* Concurrency handling. */
++extern int __concurrency_level attribute_hidden;
++
++/* Thread-local data key handling. */
++extern struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX];
++hidden_proto (__pthread_keys)
++
++/* Number of threads running. */
++extern unsigned int __nptl_nthreads attribute_hidden;
++
++#ifndef __ASSUME_SET_ROBUST_LIST
++/* Negative if we do not have the system call and we can use it. */
++extern int __set_robust_list_avail attribute_hidden;
++#endif
++
++/* Thread Priority Protection. */
++extern int __sched_fifo_min_prio attribute_hidden;
++extern int __sched_fifo_max_prio attribute_hidden;
++extern void __init_sched_fifo_prio (void) attribute_hidden;
++extern int __pthread_tpp_change_priority (int prev_prio, int new_prio)
++ attribute_hidden;
++extern int __pthread_current_priority (void) attribute_hidden;
++
++/* The library can run in debugging mode where it performs a lot more
++ tests. */
++extern int __pthread_debug attribute_hidden;
++/** For now disable debugging support. */
++#if 0
++# define DEBUGGING_P __builtin_expect (__pthread_debug, 0)
++# define INVALID_TD_P(pd) (DEBUGGING_P && __find_in_stack_list (pd) == NULL)
++# define INVALID_NOT_TERMINATED_TD_P(pd) INVALID_TD_P (pd)
++#else
++# define DEBUGGING_P 0
++/* Simplified test. This will not catch all invalid descriptors but
++ is better than nothing. And if the test triggers the thread
++ descriptor is guaranteed to be invalid. */
++# define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0)
++# define INVALID_NOT_TERMINATED_TD_P(pd) __builtin_expect ((pd)->tid < 0, 0)
++#endif
++
++
++/* Cancellation test. */
++#define CANCELLATION_P(self) \
++ do { \
++ int cancelhandling = THREAD_GETMEM (self, cancelhandling); \
++ if (CANCEL_ENABLED_AND_CANCELED (cancelhandling)) \
++ { \
++ THREAD_SETMEM (self, result, PTHREAD_CANCELED); \
++ __do_cancel (); \
++ } \
++ } while (0)
++
++
++extern void __pthread_unwind (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute __attribute ((__noreturn__))
++ ;
++extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute __attribute ((__noreturn__))
++#ifndef SHARED
++ weak_function
++#endif
++ ;
++extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++hidden_proto (__pthread_unwind)
++hidden_proto (__pthread_unwind_next)
++hidden_proto (__pthread_register_cancel)
++hidden_proto (__pthread_unregister_cancel)
++# ifdef SHARED
++extern void attribute_hidden pthread_cancel_init (void);
++# endif
++extern void __nptl_unwind_freeres (void) attribute_hidden;
++
++/* Called when a thread reacts on a cancellation request. */
++static inline void
++__attribute ((noreturn, always_inline))
++__do_cancel (void)
++{
++ struct pthread *self = THREAD_SELF;
++
++ /* Make sure we get no more cancellations. */
++ THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
++
++ __pthread_unwind ((__pthread_unwind_buf_t *)
++ THREAD_GETMEM (self, cleanup_jmp_buf));
++}
++
++
++/* Internal prototypes. */
++
++/* Thread list handling. */
++extern struct pthread *__find_in_stack_list (struct pthread *pd)
++ attribute_hidden;
++
++/* Deallocate a thread's stack after optionally making sure the thread
++ descriptor is still valid. */
++extern void __free_tcb (struct pthread *pd) attribute_hidden;
++
++/* Free allocated stack. */
++extern void __deallocate_stack (struct pthread *pd) attribute_hidden;
++
++/* Mark all the stacks except for the current one as available. This
++ function also re-initializes the lock for the stack cache. */
++extern void __reclaim_stacks (void) attribute_hidden;
++
++/* Make all threads's stacks executable. */
++extern int __make_stacks_executable (void **stack_endp) attribute_hidden;
++
++/* longjmp handling. */
++extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe);
++hidden_proto (__pthread_cleanup_upto)
++
++
++/* Functions with versioned interfaces. */
++extern int __pthread_create_2_1 (pthread_t *newthread,
++ const pthread_attr_t *attr,
++ void *(*start_routine) (void *), void *arg);
++extern int __pthread_create_2_0 (pthread_t *newthread,
++ const pthread_attr_t *attr,
++ void *(*start_routine) (void *), void *arg);
++extern int __pthread_attr_init_2_1 (pthread_attr_t *attr);
++extern int __pthread_attr_init_2_0 (pthread_attr_t *attr);
++
++
++/* Event handlers for libthread_db interface. */
++extern void __nptl_create_event (void);
++extern void __nptl_death_event (void);
++hidden_proto (__nptl_create_event)
++hidden_proto (__nptl_death_event)
++
++/* Register the generation counter in the libpthread with the libc. */
++#ifdef TLS_MULTIPLE_THREADS_IN_TCB
++extern void __libc_pthread_init (unsigned long int *ptr,
++ void (*reclaim) (void),
++ const struct pthread_functions *functions);
++#else
++extern int *__libc_pthread_init (unsigned long int *ptr,
++ void (*reclaim) (void),
++ const struct pthread_functions *functions);
++
++/* Variable set to a nonzero value either if more than one thread runs or ran,
++ or if a single-threaded process is trying to cancel itself. See
++ nptl/descr.h for more context on the single-threaded process case. */
++extern int __pthread_multiple_threads attribute_hidden;
++/* Pointer to the corresponding variable in libc. */
++extern int *__libc_multiple_threads_ptr attribute_hidden;
++#endif
++
++extern void __pthread_init_static_tls (struct link_map *) attribute_hidden;
++
++extern size_t __pthread_get_minstack (const pthread_attr_t *attr);
++
++/* Namespace save aliases. */
++extern int __pthread_getschedparam (pthread_t thread_id, int *policy,
++ struct sched_param *param);
++extern int __pthread_setschedparam (pthread_t thread_id, int policy,
++ const struct sched_param *param);
++extern int __pthread_setcancelstate (int state, int *oldstate);
++extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
++ const pthread_mutexattr_t *__mutexattr);
++extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
++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_cond_lock (pthread_mutex_t *__mutex)
++ attribute_hidden;
++extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex)
++ attribute_hidden;
++extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
++extern int __pthread_mutex_unlock_usercnt (pthread_mutex_t *__mutex,
++ int __decr) attribute_hidden;
++extern int __pthread_mutexattr_init (pthread_mutexattr_t *attr);
++extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *attr);
++extern int __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind);
++extern int __pthread_attr_destroy (pthread_attr_t *attr);
++extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr,
++ int *detachstate);
++extern int __pthread_attr_setdetachstate (pthread_attr_t *attr,
++ int detachstate);
++extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr,
++ int *inherit);
++extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit);
++extern int __pthread_attr_getschedparam (const pthread_attr_t *attr,
++ struct sched_param *param);
++extern int __pthread_attr_setschedparam (pthread_attr_t *attr,
++ const struct sched_param *param);
++extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr,
++ int *policy);
++extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy);
++extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope);
++extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope);
++extern int __pthread_attr_getstackaddr (const pthread_attr_t *__restrict
++ __attr, void **__restrict __stackaddr);
++extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr,
++ void *__stackaddr);
++extern int __pthread_attr_getstacksize (const pthread_attr_t *__restrict
++ __attr,
++ size_t *__restrict __stacksize);
++extern int __pthread_attr_setstacksize (pthread_attr_t *__attr,
++ size_t __stacksize);
++extern int __pthread_attr_getstack (const pthread_attr_t *__restrict __attr,
++ void **__restrict __stackaddr,
++ size_t *__restrict __stacksize);
++extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
++ size_t __stacksize);
++extern int __pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
++ const pthread_rwlockattr_t *__restrict
++ __attr);
++extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_cond_broadcast (pthread_cond_t *cond);
++extern int __pthread_cond_destroy (pthread_cond_t *cond);
++extern int __pthread_cond_init (pthread_cond_t *cond,
++ const pthread_condattr_t *cond_attr);
++extern int __pthread_cond_signal (pthread_cond_t *cond);
++extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
++extern int __pthread_cond_timedwait (pthread_cond_t *cond,
++ pthread_mutex_t *mutex,
++ const struct timespec *abstime);
++extern int __pthread_condattr_destroy (pthread_condattr_t *attr);
++extern int __pthread_condattr_init (pthread_condattr_t *attr);
++extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *));
++extern int __pthread_key_delete (pthread_key_t key);
++extern void *__pthread_getspecific (pthread_key_t key);
++extern int __pthread_setspecific (pthread_key_t key, const void *value);
++extern int __pthread_once (pthread_once_t *once_control,
++ void (*init_routine) (void));
++extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void),
++ void (*child) (void));
++extern pthread_t __pthread_self (void);
++extern int __pthread_equal (pthread_t thread1, pthread_t thread2);
++extern int __pthread_detach (pthread_t th);
++extern int __pthread_cancel (pthread_t th);
++extern int __pthread_kill (pthread_t threadid, int signo);
++extern void __pthread_exit (void *value) __attribute__ ((__noreturn__));
++extern int __pthread_join (pthread_t threadid, void **thread_return);
++extern int __pthread_setcanceltype (int type, int *oldtype);
++extern int __pthread_enable_asynccancel (void) attribute_hidden;
++extern void __pthread_disable_asynccancel (int oldtype) attribute_hidden;
++extern void __pthread_testcancel (void);
++extern int __pthread_clockjoin_ex (pthread_t, void **, clockid_t,
++ const struct timespec *, bool)
++ attribute_hidden;
++
++
++hidden_proto (__pthread_mutex_init)
++hidden_proto (__pthread_mutex_destroy)
++hidden_proto (__pthread_mutex_lock)
++hidden_proto (__pthread_mutex_trylock)
++hidden_proto (__pthread_mutex_unlock)
++hidden_proto (__pthread_rwlock_rdlock)
++hidden_proto (__pthread_rwlock_wrlock)
++hidden_proto (__pthread_rwlock_unlock)
++hidden_proto (__pthread_key_create)
++hidden_proto (__pthread_getspecific)
++hidden_proto (__pthread_setspecific)
++hidden_proto (__pthread_once)
++hidden_proto (__pthread_setcancelstate)
++hidden_proto (__pthread_testcancel)
++hidden_proto (__pthread_mutexattr_init)
++hidden_proto (__pthread_mutexattr_settype)
++
++extern int __pthread_cond_broadcast_2_0 (pthread_cond_2_0_t *cond);
++extern int __pthread_cond_destroy_2_0 (pthread_cond_2_0_t *cond);
++extern int __pthread_cond_init_2_0 (pthread_cond_2_0_t *cond,
++ const pthread_condattr_t *cond_attr);
++extern int __pthread_cond_signal_2_0 (pthread_cond_2_0_t *cond);
++extern int __pthread_cond_timedwait_2_0 (pthread_cond_2_0_t *cond,
++ pthread_mutex_t *mutex,
++ const struct timespec *abstime);
++extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond,
++ pthread_mutex_t *mutex);
++
++extern int __pthread_getaffinity_np (pthread_t th, size_t cpusetsize,
++ cpu_set_t *cpuset);
++
++/* Special versions which use non-exported functions. */
++extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg)
++ attribute_hidden;
++
++/* Replace cleanup macros defined in <pthread.h> with internal
++ versions that don't depend on unwind info and better support
++ cancellation. */
++# undef pthread_cleanup_push
++# define pthread_cleanup_push(routine,arg) \
++ { struct _pthread_cleanup_buffer _buffer; \
++ __pthread_cleanup_push (&_buffer, (routine), (arg));
++
++extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
++ int execute) attribute_hidden;
++# undef pthread_cleanup_pop
++# define pthread_cleanup_pop(execute) \
++ __pthread_cleanup_pop (&_buffer, (execute)); }
++
++extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg);
++extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
++ int execute);
++
++/* Old cleanup interfaces, still used in libc.so. */
++extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg);
++extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
++ int execute);
++extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg);
++extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
++ int execute);
++
++extern void __nptl_deallocate_tsd (void) attribute_hidden;
++
++extern void __nptl_setxid_error (struct xid_command *cmdp, int error)
++ attribute_hidden;
++extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden;
++#ifndef SHARED
++extern void __nptl_set_robust (struct pthread *self);
++#endif
++
++extern void __nptl_stacks_freeres (void) attribute_hidden;
++extern void __shm_directory_freeres (void) attribute_hidden;
++
++extern void __wait_lookup_done (void) attribute_hidden;
++
++#ifdef SHARED
++# define PTHREAD_STATIC_FN_REQUIRE(name)
++#else
++# define PTHREAD_STATIC_FN_REQUIRE(name) __asm (".globl " #name);
++#endif
++
++/* Test if the mutex is suitable for the FUTEX_WAIT_REQUEUE_PI operation. */
++#if (defined lll_futex_wait_requeue_pi \
++ && defined __ASSUME_REQUEUE_PI)
++# define USE_REQUEUE_PI(mut) \
++ ((mut) && (mut) != (void *) ~0l \
++ && (((mut)->__data.__kind \
++ & (PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP)) \
++ == PTHREAD_MUTEX_PRIO_INHERIT_NP))
++#else
++# define USE_REQUEUE_PI(mut) 0
++#endif
++
++/* Returns 0 if POL is a valid scheduling policy. */
++static inline int
++check_sched_policy_attr (int pol)
++{
++ if (pol == SCHED_OTHER || pol == SCHED_FIFO || pol == SCHED_RR)
++ return 0;
++
++ return EINVAL;
++}
++
++/* Returns 0 if PR is within the accepted range of priority values for
++ the scheduling policy POL or EINVAL otherwise. */
++static inline int
++check_sched_priority_attr (int pr, int pol)
++{
++ int min = __sched_get_priority_min (pol);
++ int max = __sched_get_priority_max (pol);
++
++ if (min >= 0 && max >= 0 && pr >= min && pr <= max)
++ return 0;
++
++ return EINVAL;
++}
++
++/* Returns 0 if ST is a valid stack size for a thread stack and EINVAL
++ otherwise. */
++static inline int
++check_stacksize_attr (size_t st)
++{
++ if (st >= PTHREAD_STACK_MIN)
++ return 0;
++
++ return EINVAL;
++}
++
++#define ASSERT_TYPE_SIZE(type, size) \
++ _Static_assert (sizeof (type) == size, \
++ "sizeof (" #type ") != " #size)
++
++#define ASSERT_PTHREAD_INTERNAL_SIZE(type, internal) \
++ _Static_assert (sizeof ((type) { { 0 } }).__size >= sizeof (internal),\
++ "sizeof (" #type ".__size) < sizeof (" #internal ")")
++
++#define ASSERT_PTHREAD_STRING(x) __STRING (x)
++#define ASSERT_PTHREAD_INTERNAL_OFFSET(type, member, offset) \
++ _Static_assert (offsetof (type, member) == offset, \
++ "offset of " #member " field of " #type " != " \
++ ASSERT_PTHREAD_STRING (offset))
++#define ASSERT_PTHREAD_INTERNAL_MEMBER_SIZE(type, member, mtype) \
++ _Static_assert (sizeof (((type) { 0 }).member) != 8, \
++ "sizeof (" #type "." #member ") != sizeof (" #mtype "))")
++
++#endif /* pthreadP.h */
+diff --git a/nptl_2_17/pthread_2_17.h b/nptl_2_17/pthread_2_17.h
+new file mode 100644
+index 00000000..3954770a
+--- /dev/null
++++ b/nptl_2_17/pthread_2_17.h
+@@ -0,0 +1,1173 @@
++/* Copyright (C) 2002-2020 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
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _PTHREAD_H
++#define _PTHREAD_H 1
++
++#include <features.h>
++#include <sched.h>
++#include <time.h>
++
++#include <bits/endian.h>
++#include <bits/pthreadtypes_2_17.h>
++#include <bits/setjmp.h>
++#include <bits/wordsize.h>
++#include <bits/types/struct_timespec.h>
++
++
++/* Detach state. */
++enum
++{
++ PTHREAD_CREATE_JOINABLE,
++#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE
++ PTHREAD_CREATE_DETACHED
++#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED
++};
++
++
++/* Mutex types. */
++enum
++{
++ PTHREAD_MUTEX_TIMED_NP,
++ PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_ADAPTIVE_NP
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
++ ,
++ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
++ PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
++#endif
++#ifdef __USE_GNU
++ /* For compatibility. */
++ , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
++#endif
++};
++
++
++#ifdef __USE_XOPEN2K
++/* Robust mutex or not flags. */
++enum
++{
++ PTHREAD_MUTEX_STALLED,
++ PTHREAD_MUTEX_STALLED_NP = PTHREAD_MUTEX_STALLED,
++ PTHREAD_MUTEX_ROBUST,
++ PTHREAD_MUTEX_ROBUST_NP = PTHREAD_MUTEX_ROBUST
++};
++#endif
++
++
++#if defined __USE_POSIX199506 || defined __USE_UNIX98
++/* Mutex protocols. */
++enum
++{
++ PTHREAD_PRIO_NONE,
++ PTHREAD_PRIO_INHERIT,
++ PTHREAD_PRIO_PROTECT
++};
++#endif
++
++
++#define PTHREAD_MUTEX_INITIALIZER \
++ { { __PTHREAD_MUTEX_INITIALIZER (PTHREAD_MUTEX_TIMED_NP) } }
++#ifdef __USE_GNU
++# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
++ { { __PTHREAD_MUTEX_INITIALIZER (PTHREAD_MUTEX_RECURSIVE_NP) } }
++# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
++ { { __PTHREAD_MUTEX_INITIALIZER (PTHREAD_MUTEX_ERRORCHECK_NP) } }
++# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
++ { { __PTHREAD_MUTEX_INITIALIZER (PTHREAD_MUTEX_ADAPTIVE_NP) } }
++#endif
++
++
++/* Read-write lock types. */
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K
++enum
++{
++ PTHREAD_RWLOCK_PREFER_READER_NP,
++ PTHREAD_RWLOCK_PREFER_WRITER_NP,
++ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
++ PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP
++};
++
++
++/* Read-write lock initializers. */
++# define PTHREAD_RWLOCK_INITIALIZER \
++ { { __PTHREAD_RWLOCK_INITIALIZER (PTHREAD_RWLOCK_DEFAULT_NP) } }
++# ifdef __USE_GNU
++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
++ { { __PTHREAD_RWLOCK_INITIALIZER (PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP) } }
++# endif
++#endif /* Unix98 or XOpen2K */
++
++
++/* Scheduler inheritance. */
++enum
++{
++ PTHREAD_INHERIT_SCHED,
++#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED
++ PTHREAD_EXPLICIT_SCHED
++#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED
++};
++
++
++/* Scope handling. */
++enum
++{
++ PTHREAD_SCOPE_SYSTEM,
++#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM
++ PTHREAD_SCOPE_PROCESS
++#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS
++};
++
++
++/* Process shared or private flag. */
++enum
++{
++ PTHREAD_PROCESS_PRIVATE,
++#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE
++ PTHREAD_PROCESS_SHARED
++#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED
++};
++
++
++
++/* Conditional variable handling. */
++#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }
++
++
++/* Cleanup buffers */
++struct _pthread_cleanup_buffer
++{
++ void (*__routine) (void *); /* Function to call. */
++ void *__arg; /* Its argument. */
++ int __canceltype; /* Saved cancellation type. */
++ struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */
++};
++
++/* Cancellation */
++enum
++{
++ PTHREAD_CANCEL_ENABLE,
++#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE
++ PTHREAD_CANCEL_DISABLE
++#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE
++};
++enum
++{
++ PTHREAD_CANCEL_DEFERRED,
++#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED
++ PTHREAD_CANCEL_ASYNCHRONOUS
++#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS
++};
++#define PTHREAD_CANCELED ((void *) -1)
++
++
++/* Single execution handling. */
++#define PTHREAD_ONCE_INIT 0
++
++
++#ifdef __USE_XOPEN2K
++/* Value returned by 'pthread_barrier_wait' for one of the threads after
++ the required number of threads have called this function.
++ -1 is distinct from 0 and all errno constants */
++# define PTHREAD_BARRIER_SERIAL_THREAD -1
++#endif
++
++
++__BEGIN_DECLS
++
++/* Create a new thread, starting with execution of START-ROUTINE
++ getting passed ARG. Creation attributed come from ATTR. The new
++ handle is stored in *NEWTHREAD. */
++extern int pthread_create (pthread_t *__restrict __newthread,
++ const pthread_attr_t *__restrict __attr,
++ void *(*__start_routine) (void *),
++ void *__restrict __arg) __THROWNL __nonnull ((1, 3));
++
++/* Terminate calling thread.
++
++ The registered cleanup handlers are called via exception handling
++ so we cannot mark this function with __THROW.*/
++extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));
++
++/* Make calling thread wait for termination of the thread TH. The
++ exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN
++ is not NULL.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_join (pthread_t __th, void **__thread_return);
++
++#ifdef __USE_GNU
++/* Check whether thread TH has terminated. If yes return the status of
++ the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL. */
++extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW;
++
++/* Make calling thread wait for termination of the thread TH, but only
++ until TIMEOUT. The exit status of the thread is stored in
++ *THREAD_RETURN, if THREAD_RETURN is not NULL.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return,
++ const struct timespec *__abstime);
++
++/* Make calling thread wait for termination of the thread TH, but only
++ until TIMEOUT measured against the clock specified by CLOCKID. The
++ exit status of the thread is stored in *THREAD_RETURN, if
++ THREAD_RETURN is not NULL.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_clockjoin_np (pthread_t __th, void **__thread_return,
++ clockid_t __clockid,
++ const struct timespec *__abstime);
++#endif
++
++/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
++ The resources of TH will therefore be freed immediately when it
++ terminates, instead of waiting for another thread to perform PTHREAD_JOIN
++ on it. */
++extern int pthread_detach (pthread_t __th) __THROW;
++
++
++/* Obtain the identifier of the current thread. */
++extern pthread_t pthread_self (void) __THROW __attribute__ ((__const__));
++
++/* Compare two thread identifiers. */
++extern int pthread_equal (pthread_t __thread1, pthread_t __thread2)
++ __THROW __attribute__ ((__const__));
++
++
++/* Thread attribute handling. */
++
++/* Initialize thread attribute *ATTR with default attributes
++ (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER,
++ no user-provided stack). */
++extern int pthread_attr_init (pthread_attr_t *__attr) __THROW __nonnull ((1));
++
++/* Destroy thread attribute *ATTR. */
++extern int pthread_attr_destroy (pthread_attr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Get detach state attribute. */
++extern int pthread_attr_getdetachstate (const pthread_attr_t *__attr,
++ int *__detachstate)
++ __THROW __nonnull ((1, 2));
++
++/* Set detach state attribute. */
++extern int pthread_attr_setdetachstate (pthread_attr_t *__attr,
++ int __detachstate)
++ __THROW __nonnull ((1));
++
++
++/* Get the size of the guard area created for stack overflow protection. */
++extern int pthread_attr_getguardsize (const pthread_attr_t *__attr,
++ size_t *__guardsize)
++ __THROW __nonnull ((1, 2));
++
++/* Set the size of the guard area created for stack overflow protection. */
++extern int pthread_attr_setguardsize (pthread_attr_t *__attr,
++ size_t __guardsize)
++ __THROW __nonnull ((1));
++
++
++/* Return in *PARAM the scheduling parameters of *ATTR. */
++extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict __attr,
++ struct sched_param *__restrict __param)
++ __THROW __nonnull ((1, 2));
++
++/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */
++extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr,
++ const struct sched_param *__restrict
++ __param) __THROW __nonnull ((1, 2));
++
++/* Return in *POLICY the scheduling policy of *ATTR. */
++extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict
++ __attr, int *__restrict __policy)
++ __THROW __nonnull ((1, 2));
++
++/* Set scheduling policy in *ATTR according to POLICY. */
++extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy)
++ __THROW __nonnull ((1));
++
++/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */
++extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict
++ __attr, int *__restrict __inherit)
++ __THROW __nonnull ((1, 2));
++
++/* Set scheduling inheritance mode in *ATTR according to INHERIT. */
++extern int pthread_attr_setinheritsched (pthread_attr_t *__attr,
++ int __inherit)
++ __THROW __nonnull ((1));
++
++
++/* Return in *SCOPE the scheduling contention scope of *ATTR. */
++extern int pthread_attr_getscope (const pthread_attr_t *__restrict __attr,
++ int *__restrict __scope)
++ __THROW __nonnull ((1, 2));
++
++/* Set scheduling contention scope in *ATTR according to SCOPE. */
++extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope)
++ __THROW __nonnull ((1));
++
++/* Return the previously set address for the stack. */
++extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict
++ __attr, void **__restrict __stackaddr)
++ __THROW __nonnull ((1, 2)) __attribute_deprecated__;
++
++/* Set the starting address of the stack of the thread to be created.
++ Depending on whether the stack grows up or down the value must either
++ be higher or lower than all the address in the memory block. The
++ minimal size of the block must be PTHREAD_STACK_MIN. */
++extern int pthread_attr_setstackaddr (pthread_attr_t *__attr,
++ void *__stackaddr)
++ __THROW __nonnull ((1)) __attribute_deprecated__;
++
++/* Return the currently used minimal stack size. */
++extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict
++ __attr, size_t *__restrict __stacksize)
++ __THROW __nonnull ((1, 2));
++
++/* Add information about the minimum stack size needed for the thread
++ to be started. This size must never be less than PTHREAD_STACK_MIN
++ and must also not exceed the system limits. */
++extern int pthread_attr_setstacksize (pthread_attr_t *__attr,
++ size_t __stacksize)
++ __THROW __nonnull ((1));
++
++#ifdef __USE_XOPEN2K
++/* Return the previously set address for the stack. */
++extern int pthread_attr_getstack (const pthread_attr_t *__restrict __attr,
++ void **__restrict __stackaddr,
++ size_t *__restrict __stacksize)
++ __THROW __nonnull ((1, 2, 3));
++
++/* The following two interfaces are intended to replace the last two. They
++ require setting the address as well as the size since only setting the
++ address will make the implementation on some architectures impossible. */
++extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
++ size_t __stacksize) __THROW __nonnull ((1));
++#endif
++
++#ifdef __USE_GNU
++/* Thread created with attribute ATTR will be limited to run only on
++ the processors represented in CPUSET. */
++extern int pthread_attr_setaffinity_np (pthread_attr_t *__attr,
++ size_t __cpusetsize,
++ const cpu_set_t *__cpuset)
++ __THROW __nonnull ((1, 3));
++
++/* Get bit set in CPUSET representing the processors threads created with
++ ATTR can run on. */
++extern int pthread_attr_getaffinity_np (const pthread_attr_t *__attr,
++ size_t __cpusetsize,
++ cpu_set_t *__cpuset)
++ __THROW __nonnull ((1, 3));
++
++/* Get the default attributes used by pthread_create in this process. */
++extern int pthread_getattr_default_np (pthread_attr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Set the default attributes to be used by pthread_create in this
++ process. */
++extern int pthread_setattr_default_np (const pthread_attr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Initialize thread attribute *ATTR with attributes corresponding to the
++ already running thread TH. It shall be called on uninitialized ATTR
++ and destroyed with pthread_attr_destroy when no longer needed. */
++extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr)
++ __THROW __nonnull ((2));
++#endif
++
++
++/* Functions for scheduling control. */
++
++/* Set the scheduling parameters for TARGET_THREAD according to POLICY
++ and *PARAM. */
++extern int pthread_setschedparam (pthread_t __target_thread, int __policy,
++ const struct sched_param *__param)
++ __THROW __nonnull ((3));
++
++/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */
++extern int pthread_getschedparam (pthread_t __target_thread,
++ int *__restrict __policy,
++ struct sched_param *__restrict __param)
++ __THROW __nonnull ((2, 3));
++
++/* Set the scheduling priority for TARGET_THREAD. */
++extern int pthread_setschedprio (pthread_t __target_thread, int __prio)
++ __THROW;
++
++
++#ifdef __USE_GNU
++/* Get thread name visible in the kernel and its interfaces. */
++extern int pthread_getname_np (pthread_t __target_thread, char *__buf,
++ size_t __buflen)
++ __THROW __nonnull ((2));
++
++/* Set thread name visible in the kernel and its interfaces. */
++extern int pthread_setname_np (pthread_t __target_thread, const char *__name)
++ __THROW __nonnull ((2));
++#endif
++
++
++#ifdef __USE_UNIX98
++/* Determine level of concurrency. */
++extern int pthread_getconcurrency (void) __THROW;
++
++/* Set new concurrency level to LEVEL. */
++extern int pthread_setconcurrency (int __level) __THROW;
++#endif
++
++#ifdef __USE_GNU
++/* Yield the processor to another thread or process.
++ This function is similar to the POSIX `sched_yield' function but
++ might be differently implemented in the case of a m-on-n thread
++ implementation. */
++extern int pthread_yield (void) __THROW;
++
++
++/* Limit specified thread TH to run only on the processors represented
++ in CPUSET. */
++extern int pthread_setaffinity_np (pthread_t __th, size_t __cpusetsize,
++ const cpu_set_t *__cpuset)
++ __THROW __nonnull ((3));
++
++/* Get bit set in CPUSET representing the processors TH can run on. */
++extern int pthread_getaffinity_np (pthread_t __th, size_t __cpusetsize,
++ cpu_set_t *__cpuset)
++ __THROW __nonnull ((3));
++#endif
++
++
++/* Functions for handling initialization. */
++
++/* Guarantee that the initialization function INIT_ROUTINE will be called
++ only once, even if pthread_once is executed several times with the
++ same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or
++ extern variable initialized to PTHREAD_ONCE_INIT.
++
++ The initialization functions might throw exception which is why
++ this function is not marked with __THROW. */
++extern int pthread_once (pthread_once_t *__once_control,
++ void (*__init_routine) (void)) __nonnull ((1, 2));
++
++
++/* Functions for handling cancellation.
++
++ Note that these functions are explicitly not marked to not throw an
++ exception in C++ code. If cancellation is implemented by unwinding
++ this is necessary to have the compiler generate the unwind information. */
++
++/* Set cancelability state of current thread to STATE, returning old
++ state in *OLDSTATE if OLDSTATE is not NULL. */
++extern int pthread_setcancelstate (int __state, int *__oldstate);
++
++/* Set cancellation state of current thread to TYPE, returning the old
++ type in *OLDTYPE if OLDTYPE is not NULL. */
++extern int pthread_setcanceltype (int __type, int *__oldtype);
++
++/* Cancel THREAD immediately or at the next possibility. */
++extern int pthread_cancel (pthread_t __th);
++
++/* Test for pending cancellation for the current thread and terminate
++ the thread as per pthread_exit(PTHREAD_CANCELED) if it has been
++ cancelled. */
++extern void pthread_testcancel (void);
++
++
++/* Cancellation handling with integration into exception handling. */
++
++typedef struct
++{
++ struct
++ {
++ __jmp_buf __cancel_jmp_buf;
++ int __mask_was_saved;
++ } __cancel_jmp_buf[1];
++ void *__pad[4];
++} __pthread_unwind_buf_t __attribute__ ((__aligned__));
++
++/* No special attributes by default. */
++#ifndef __cleanup_fct_attribute
++# define __cleanup_fct_attribute
++#endif
++
++
++/* Structure to hold the cleanup handler information. */
++struct __pthread_cleanup_frame
++{
++ void (*__cancel_routine) (void *);
++ void *__cancel_arg;
++ int __do_it;
++ int __cancel_type;
++};
++
++#if defined __GNUC__ && defined __EXCEPTIONS
++# ifdef __cplusplus
++/* Class to handle cancellation handler invocation. */
++class __pthread_cleanup_class
++{
++ void (*__cancel_routine) (void *);
++ void *__cancel_arg;
++ int __do_it;
++ int __cancel_type;
++
++ public:
++ __pthread_cleanup_class (void (*__fct) (void *), void *__arg)
++ : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { }
++ ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); }
++ void __setdoit (int __newval) { __do_it = __newval; }
++ void __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED,
++ &__cancel_type); }
++ void __restore () const { pthread_setcanceltype (__cancel_type, 0); }
++};
++
++/* Install a cleanup handler: ROUTINE will be called with arguments ARG
++ when the thread is canceled or calls pthread_exit. ROUTINE will also
++ be called with arguments ARG when the matching pthread_cleanup_pop
++ is executed with non-zero EXECUTE argument.
++
++ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
++ be used in matching pairs at the same nesting level of braces. */
++# define pthread_cleanup_push(routine, arg) \
++ do { \
++ __pthread_cleanup_class __clframe (routine, arg)
++
++/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
++ If EXECUTE is non-zero, the handler function is called. */
++# define pthread_cleanup_pop(execute) \
++ __clframe.__setdoit (execute); \
++ } while (0)
++
++# ifdef __USE_GNU
++/* Install a cleanup handler as pthread_cleanup_push does, but also
++ saves the current cancellation type and sets it to deferred
++ cancellation. */
++# define pthread_cleanup_push_defer_np(routine, arg) \
++ do { \
++ __pthread_cleanup_class __clframe (routine, arg); \
++ __clframe.__defer ()
++
++/* Remove a cleanup handler as pthread_cleanup_pop does, but also
++ restores the cancellation type that was in effect when the matching
++ pthread_cleanup_push_defer was called. */
++# define pthread_cleanup_pop_restore_np(execute) \
++ __clframe.__restore (); \
++ __clframe.__setdoit (execute); \
++ } while (0)
++# endif
++# else
++/* Function called to call the cleanup handler. As an extern inline
++ function the compiler is free to decide inlining the change when
++ needed or fall back on the copy which must exist somewhere
++ else. */
++__extern_inline void
++__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
++{
++ if (__frame->__do_it)
++ __frame->__cancel_routine (__frame->__cancel_arg);
++}
++
++/* Install a cleanup handler: ROUTINE will be called with arguments ARG
++ when the thread is canceled or calls pthread_exit. ROUTINE will also
++ be called with arguments ARG when the matching pthread_cleanup_pop
++ is executed with non-zero EXECUTE argument.
++
++ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
++ be used in matching pairs at the same nesting level of braces. */
++# define pthread_cleanup_push(routine, arg) \
++ do { \
++ struct __pthread_cleanup_frame __clframe \
++ __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \
++ = { .__cancel_routine = (routine), .__cancel_arg = (arg), \
++ .__do_it = 1 };
++
++/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
++ If EXECUTE is non-zero, the handler function is called. */
++# define pthread_cleanup_pop(execute) \
++ __clframe.__do_it = (execute); \
++ } while (0)
++
++# ifdef __USE_GNU
++/* Install a cleanup handler as pthread_cleanup_push does, but also
++ saves the current cancellation type and sets it to deferred
++ cancellation. */
++# define pthread_cleanup_push_defer_np(routine, arg) \
++ do { \
++ struct __pthread_cleanup_frame __clframe \
++ __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \
++ = { .__cancel_routine = (routine), .__cancel_arg = (arg), \
++ .__do_it = 1 }; \
++ (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, \
++ &__clframe.__cancel_type)
++
++/* Remove a cleanup handler as pthread_cleanup_pop does, but also
++ restores the cancellation type that was in effect when the matching
++ pthread_cleanup_push_defer was called. */
++# define pthread_cleanup_pop_restore_np(execute) \
++ (void) pthread_setcanceltype (__clframe.__cancel_type, NULL); \
++ __clframe.__do_it = (execute); \
++ } while (0)
++# endif
++# endif
++#else
++/* Install a cleanup handler: ROUTINE will be called with arguments ARG
++ when the thread is canceled or calls pthread_exit. ROUTINE will also
++ be called with arguments ARG when the matching pthread_cleanup_pop
++ is executed with non-zero EXECUTE argument.
++
++ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
++ be used in matching pairs at the same nesting level of braces. */
++# define pthread_cleanup_push(routine, arg) \
++ do { \
++ __pthread_unwind_buf_t __cancel_buf; \
++ void (*__cancel_routine) (void *) = (routine); \
++ void *__cancel_arg = (arg); \
++ int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \
++ __cancel_buf.__cancel_jmp_buf, 0); \
++ if (__glibc_unlikely (__not_first_call)) \
++ { \
++ __cancel_routine (__cancel_arg); \
++ __pthread_unwind_next (&__cancel_buf); \
++ /* NOTREACHED */ \
++ } \
++ \
++ __pthread_register_cancel (&__cancel_buf); \
++ do {
++extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++
++/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
++ If EXECUTE is non-zero, the handler function is called. */
++# define pthread_cleanup_pop(execute) \
++ do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\
++ } while (0); \
++ __pthread_unregister_cancel (&__cancel_buf); \
++ if (execute) \
++ __cancel_routine (__cancel_arg); \
++ } while (0)
++extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++
++# ifdef __USE_GNU
++/* Install a cleanup handler as pthread_cleanup_push does, but also
++ saves the current cancellation type and sets it to deferred
++ cancellation. */
++# define pthread_cleanup_push_defer_np(routine, arg) \
++ do { \
++ __pthread_unwind_buf_t __cancel_buf; \
++ void (*__cancel_routine) (void *) = (routine); \
++ void *__cancel_arg = (arg); \
++ int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \
++ __cancel_buf.__cancel_jmp_buf, 0); \
++ if (__glibc_unlikely (__not_first_call)) \
++ { \
++ __cancel_routine (__cancel_arg); \
++ __pthread_unwind_next (&__cancel_buf); \
++ /* NOTREACHED */ \
++ } \
++ \
++ __pthread_register_cancel_defer (&__cancel_buf); \
++ do {
++extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++
++/* Remove a cleanup handler as pthread_cleanup_pop does, but also
++ restores the cancellation type that was in effect when the matching
++ pthread_cleanup_push_defer was called. */
++# define pthread_cleanup_pop_restore_np(execute) \
++ do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\
++ } while (0); \
++ __pthread_unregister_cancel_restore (&__cancel_buf); \
++ if (execute) \
++ __cancel_routine (__cancel_arg); \
++ } while (0)
++extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++# endif
++
++/* Internal interface to initiate cleanup. */
++extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute __attribute__ ((__noreturn__))
++# ifndef SHARED
++ __attribute__ ((__weak__))
++# endif
++ ;
++#endif
++
++/* Function used in the macros. */
++struct __jmp_buf_tag;
++extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL;
++
++
++/* Mutex handling. */
++
++/* Initialize a mutex. */
++extern int pthread_mutex_init (pthread_mutex_t *__mutex,
++ const pthread_mutexattr_t *__mutexattr)
++ __THROW __nonnull ((1));
++
++/* Destroy a mutex. */
++extern int pthread_mutex_destroy (pthread_mutex_t *__mutex)
++ __THROW __nonnull ((1));
++
++/* Try locking a mutex. */
++extern int pthread_mutex_trylock (pthread_mutex_t *__mutex)
++ __THROWNL __nonnull ((1));
++
++/* Lock a mutex. */
++extern int pthread_mutex_lock (pthread_mutex_t *__mutex)
++ __THROWNL __nonnull ((1));
++
++#ifdef __USE_XOPEN2K
++/* Wait until lock becomes available, or specified time passes. */
++extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 2));
++#endif
++
++#ifdef __USE_GNU
++extern int pthread_mutex_clocklock (pthread_mutex_t *__restrict __mutex,
++ clockid_t __clockid,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 3));
++#endif
++
++/* Unlock a mutex. */
++extern int pthread_mutex_unlock (pthread_mutex_t *__mutex)
++ __THROWNL __nonnull ((1));
++
++
++/* Get the priority ceiling of MUTEX. */
++extern int pthread_mutex_getprioceiling (const pthread_mutex_t *
++ __restrict __mutex,
++ int *__restrict __prioceiling)
++ __THROW __nonnull ((1, 2));
++
++/* Set the priority ceiling of MUTEX to PRIOCEILING, return old
++ priority ceiling value in *OLD_CEILING. */
++extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict __mutex,
++ int __prioceiling,
++ int *__restrict __old_ceiling)
++ __THROW __nonnull ((1, 3));
++
++
++#ifdef __USE_XOPEN2K8
++/* Declare the state protected by MUTEX as consistent. */
++extern int pthread_mutex_consistent (pthread_mutex_t *__mutex)
++ __THROW __nonnull ((1));
++# ifdef __USE_GNU
++extern int pthread_mutex_consistent_np (pthread_mutex_t *__mutex)
++ __THROW __nonnull ((1));
++# endif
++#endif
++
++
++/* Functions for handling mutex attributes. */
++
++/* Initialize mutex attribute object ATTR with default attributes
++ (kind is PTHREAD_MUTEX_TIMED_NP). */
++extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Destroy mutex attribute object ATTR. */
++extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Get the process-shared flag of the mutex attribute ATTR. */
++extern int pthread_mutexattr_getpshared (const pthread_mutexattr_t *
++ __restrict __attr,
++ int *__restrict __pshared)
++ __THROW __nonnull ((1, 2));
++
++/* Set the process-shared flag of the mutex attribute ATTR. */
++extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr,
++ int __pshared)
++ __THROW __nonnull ((1));
++
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
++/* Return in *KIND the mutex kind attribute in *ATTR. */
++extern int pthread_mutexattr_gettype (const pthread_mutexattr_t *__restrict
++ __attr, int *__restrict __kind)
++ __THROW __nonnull ((1, 2));
++
++/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
++ PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
++ PTHREAD_MUTEX_DEFAULT). */
++extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
++ __THROW __nonnull ((1));
++#endif
++
++/* Return in *PROTOCOL the mutex protocol attribute in *ATTR. */
++extern int pthread_mutexattr_getprotocol (const pthread_mutexattr_t *
++ __restrict __attr,
++ int *__restrict __protocol)
++ __THROW __nonnull ((1, 2));
++
++/* Set the mutex protocol attribute in *ATTR to PROTOCOL (either
++ PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, or PTHREAD_PRIO_PROTECT). */
++extern int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr,
++ int __protocol)
++ __THROW __nonnull ((1));
++
++/* Return in *PRIOCEILING the mutex prioceiling attribute in *ATTR. */
++extern int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *
++ __restrict __attr,
++ int *__restrict __prioceiling)
++ __THROW __nonnull ((1, 2));
++
++/* Set the mutex prioceiling attribute in *ATTR to PRIOCEILING. */
++extern int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *__attr,
++ int __prioceiling)
++ __THROW __nonnull ((1));
++
++#ifdef __USE_XOPEN2K
++/* Get the robustness flag of the mutex attribute ATTR. */
++extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr,
++ int *__robustness)
++ __THROW __nonnull ((1, 2));
++# ifdef __USE_GNU
++extern int pthread_mutexattr_getrobust_np (const pthread_mutexattr_t *__attr,
++ int *__robustness)
++ __THROW __nonnull ((1, 2));
++# endif
++
++/* Set the robustness flag of the mutex attribute ATTR. */
++extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr,
++ int __robustness)
++ __THROW __nonnull ((1));
++# ifdef __USE_GNU
++extern int pthread_mutexattr_setrobust_np (pthread_mutexattr_t *__attr,
++ int __robustness)
++ __THROW __nonnull ((1));
++# endif
++#endif
++
++
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K
++/* Functions for handling read-write locks. */
++
++/* Initialize read-write lock RWLOCK using attributes ATTR, or use
++ the default values if later is NULL. */
++extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
++ const pthread_rwlockattr_t *__restrict
++ __attr) __THROW __nonnull ((1));
++
++/* Destroy read-write lock RWLOCK. */
++extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock)
++ __THROW __nonnull ((1));
++
++/* Acquire read lock for RWLOCK. */
++extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++/* Try to acquire read lock for RWLOCK. */
++extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++# ifdef __USE_XOPEN2K
++/* Try to acquire read lock for RWLOCK or return after specfied time. */
++extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 2));
++# endif
++
++# ifdef __USE_GNU
++extern int pthread_rwlock_clockrdlock (pthread_rwlock_t *__restrict __rwlock,
++ clockid_t __clockid,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 3));
++# endif
++
++/* Acquire write lock for RWLOCK. */
++extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++/* Try to acquire write lock for RWLOCK. */
++extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++# ifdef __USE_XOPEN2K
++/* Try to acquire write lock for RWLOCK or return after specfied time. */
++extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 2));
++# endif
++
++# ifdef __USE_GNU
++extern int pthread_rwlock_clockwrlock (pthread_rwlock_t *__restrict __rwlock,
++ clockid_t __clockid,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 3));
++# endif
++
++/* Unlock RWLOCK. */
++extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++
++/* Functions for handling read-write lock attributes. */
++
++/* Initialize attribute object ATTR with default values. */
++extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Destroy attribute object ATTR. */
++extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Return current setting of process-shared attribute of ATTR in PSHARED. */
++extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *
++ __restrict __attr,
++ int *__restrict __pshared)
++ __THROW __nonnull ((1, 2));
++
++/* Set process-shared attribute of ATTR to PSHARED. */
++extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr,
++ int __pshared)
++ __THROW __nonnull ((1));
++
++/* Return current setting of reader/writer preference. */
++extern int pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *
++ __restrict __attr,
++ int *__restrict __pref)
++ __THROW __nonnull ((1, 2));
++
++/* Set reader/write preference. */
++extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr,
++ int __pref) __THROW __nonnull ((1));
++#endif
++
++
++/* Functions for handling conditional variables. */
++
++/* Initialize condition variable COND using attributes ATTR, or use
++ the default values if later is NULL. */
++extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
++ const pthread_condattr_t *__restrict __cond_attr)
++ __THROW __nonnull ((1));
++
++/* Destroy condition variable COND. */
++extern int pthread_cond_destroy (pthread_cond_t *__cond)
++ __THROW __nonnull ((1));
++
++/* Wake up one thread waiting for condition variable COND. */
++extern int pthread_cond_signal (pthread_cond_t *__cond)
++ __THROWNL __nonnull ((1));
++
++/* Wake up all threads waiting for condition variables COND. */
++extern int pthread_cond_broadcast (pthread_cond_t *__cond)
++ __THROWNL __nonnull ((1));
++
++/* Wait for condition variable COND to be signaled or broadcast.
++ MUTEX is assumed to be locked before.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
++ pthread_mutex_t *__restrict __mutex)
++ __nonnull ((1, 2));
++
++/* Wait for condition variable COND to be signaled or broadcast until
++ ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an
++ absolute time specification; zero is the beginning of the epoch
++ (00:00:00 GMT, January 1, 1970).
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
++ pthread_mutex_t *__restrict __mutex,
++ const struct timespec *__restrict __abstime)
++ __nonnull ((1, 2, 3));
++
++# ifdef __USE_GNU
++/* Wait for condition variable COND to be signaled or broadcast until
++ ABSTIME measured by the specified clock. MUTEX is assumed to be
++ locked before. CLOCK is the clock to use. ABSTIME is an absolute
++ time specification against CLOCK's epoch.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_cond_clockwait (pthread_cond_t *__restrict __cond,
++ pthread_mutex_t *__restrict __mutex,
++ __clockid_t __clock_id,
++ const struct timespec *__restrict __abstime)
++ __nonnull ((1, 2, 4));
++# endif
++
++/* Functions for handling condition variable attributes. */
++
++/* Initialize condition variable attribute ATTR. */
++extern int pthread_condattr_init (pthread_condattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Destroy condition variable attribute ATTR. */
++extern int pthread_condattr_destroy (pthread_condattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Get the process-shared flag of the condition variable attribute ATTR. */
++extern int pthread_condattr_getpshared (const pthread_condattr_t *
++ __restrict __attr,
++ int *__restrict __pshared)
++ __THROW __nonnull ((1, 2));
++
++/* Set the process-shared flag of the condition variable attribute ATTR. */
++extern int pthread_condattr_setpshared (pthread_condattr_t *__attr,
++ int __pshared) __THROW __nonnull ((1));
++
++#ifdef __USE_XOPEN2K
++/* Get the clock selected for the condition variable attribute ATTR. */
++extern int pthread_condattr_getclock (const pthread_condattr_t *
++ __restrict __attr,
++ __clockid_t *__restrict __clock_id)
++ __THROW __nonnull ((1, 2));
++
++/* Set the clock selected for the condition variable attribute ATTR. */
++extern int pthread_condattr_setclock (pthread_condattr_t *__attr,
++ __clockid_t __clock_id)
++ __THROW __nonnull ((1));
++#endif
++
++
++#ifdef __USE_XOPEN2K
++/* Functions to handle spinlocks. */
++
++/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can
++ be shared between different processes. */
++extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared)
++ __THROW __nonnull ((1));
++
++/* Destroy the spinlock LOCK. */
++extern int pthread_spin_destroy (pthread_spinlock_t *__lock)
++ __THROW __nonnull ((1));
++
++/* Wait until spinlock LOCK is retrieved. */
++extern int pthread_spin_lock (pthread_spinlock_t *__lock)
++ __THROWNL __nonnull ((1));
++
++/* Try to lock spinlock LOCK. */
++extern int pthread_spin_trylock (pthread_spinlock_t *__lock)
++ __THROWNL __nonnull ((1));
++
++/* Release spinlock LOCK. */
++extern int pthread_spin_unlock (pthread_spinlock_t *__lock)
++ __THROWNL __nonnull ((1));
++
++
++/* Functions to handle barriers. */
++
++/* Initialize BARRIER with the attributes in ATTR. The barrier is
++ opened when COUNT waiters arrived. */
++extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier,
++ const pthread_barrierattr_t *__restrict
++ __attr, unsigned int __count)
++ __THROW __nonnull ((1));
++
++/* Destroy a previously dynamically initialized barrier BARRIER. */
++extern int pthread_barrier_destroy (pthread_barrier_t *__barrier)
++ __THROW __nonnull ((1));
++
++/* Wait on barrier BARRIER. */
++extern int pthread_barrier_wait (pthread_barrier_t *__barrier)
++ __THROWNL __nonnull ((1));
++
++
++/* Initialize barrier attribute ATTR. */
++extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Destroy previously dynamically initialized barrier attribute ATTR. */
++extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Get the process-shared flag of the barrier attribute ATTR. */
++extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t *
++ __restrict __attr,
++ int *__restrict __pshared)
++ __THROW __nonnull ((1, 2));
++
++/* Set the process-shared flag of the barrier attribute ATTR. */
++extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr,
++ int __pshared)
++ __THROW __nonnull ((1));
++#endif
++
++
++/* Functions for handling thread-specific data. */
++
++/* Create a key value identifying a location in the thread-specific
++ data area. Each thread maintains a distinct thread-specific data
++ area. DESTR_FUNCTION, if non-NULL, is called with the value
++ associated to that key when the key is destroyed.
++ DESTR_FUNCTION is not called if the value associated is NULL when
++ the key is destroyed. */
++extern int pthread_key_create (pthread_key_t *__key,
++ void (*__destr_function) (void *))
++ __THROW __nonnull ((1));
++
++/* Destroy KEY. */
++extern int pthread_key_delete (pthread_key_t __key) __THROW;
++
++/* Return current value of the thread-specific data slot identified by KEY. */
++extern void *pthread_getspecific (pthread_key_t __key) __THROW;
++
++/* Store POINTER in the thread-specific data slot identified by KEY. */
++extern int pthread_setspecific (pthread_key_t __key,
++ const void *__pointer) __THROW ;
++
++
++#ifdef __USE_XOPEN2K
++/* Get ID of CPU-time clock for thread THREAD_ID. */
++extern int pthread_getcpuclockid (pthread_t __thread_id,
++ __clockid_t *__clock_id)
++ __THROW __nonnull ((2));
++#endif
++
++
++/* Install handlers to be called when a new process is created with FORK.
++ The PREPARE handler is called in the parent process just before performing
++ FORK. The PARENT handler is called in the parent process just after FORK.
++ The CHILD handler is called in the child process. Each of the three
++ handlers can be NULL, meaning that no handler needs to be called at that
++ point.
++ PTHREAD_ATFORK can be called several times, in which case the PREPARE
++ handlers are called in LIFO order (last added with PTHREAD_ATFORK,
++ first called before FORK), and the PARENT and CHILD handlers are called
++ in FIFO (first added, first called). */
++
++extern int pthread_atfork (void (*__prepare) (void),
++ void (*__parent) (void),
++ void (*__child) (void)) __THROW;
++
++
++#ifdef __USE_EXTERN_INLINES
++/* Optimizations. */
++__extern_inline int
++__NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2))
++{
++ return __thread1 == __thread2;
++}
++#endif
++
++__END_DECLS
++
++#endif /* pthread.h */
+diff --git a/nptl_2_17/pthread_cond_broadcast_2_17.c b/nptl_2_17/pthread_cond_broadcast_2_17.c
+new file mode 100644
+index 00000000..e1d5f332
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_broadcast_2_17.c
+@@ -0,0 +1,94 @@
++/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include <pthread_2_17.h>
++#include <pthreadP_2_17.h>
++#include <endian.h>
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++#include <stap-probe.h>
++#include <atomic.h>
++
++#include <shlib-compat.h>
++
++#include <kernel-features.h>
++
++int
++__pthread_cond_broadcast (pthread_cond_t *cond)
++{
++ LIBC_PROBE (cond_broadcast, 1, cond);
++
++ int pshared = (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;
++
++#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;
++
++wake_all:
++ lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared);
++ return 0;
++ }
++ /* We are done. */
++ lll_unlock (cond->__data.__lock, pshared);
++
++ return 0;
++}
++
++versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
++ GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_cond_destroy_2_17.c b/nptl_2_17/pthread_cond_destroy_2_17.c
+new file mode 100644
+index 00000000..62c8ae72
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_destroy_2_17.c
+@@ -0,0 +1,85 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <errno.h>
++#include <shlib-compat.h>
++#include <stap-probe.h>
++int
++__pthread_cond_destroy (pthread_cond_t *cond)
++{
++ int pshared = (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))
++
++ {
++ /* 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)
++ {
++ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
++ lll_futex_wake (&mut->__data.__lock, INT_MAX,
++ PTHREAD_MUTEX_PSHARED (mut));
++ }
++
++ 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));
++ }
++
++ return 0;
++}
++versioned_symbol (libpthread, __pthread_cond_destroy,
++ pthread_cond_destroy, GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_cond_init_2_17.c b/nptl_2_17/pthread_cond_init_2_17.c
+new file mode 100644
+index 00000000..7acaa86b
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_init_2_17.c
+@@ -0,0 +1,50 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <shlib-compat.h>
++#include <stap-probe.h>
++
++
++int
++__pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
++{
++ ASSERT_TYPE_SIZE (pthread_cond_t, __SIZEOF_PTHREAD_COND_T);
++
++ 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.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0
++ ? NULL : (void *) ~0l);
++ cond->__data.__broadcast_seq = 0;
++
++
++ LIBC_PROBE (cond_init, 2, cond, cond_attr);
++
++ return 0;
++}
++versioned_symbol (libpthread, __pthread_cond_init,
++ pthread_cond_init, GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_cond_signal_2_17.c b/nptl_2_17/pthread_cond_signal_2_17.c
+new file mode 100644
+index 00000000..a8053d33
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_signal_2_17.c
+@@ -0,0 +1,82 @@
++/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include <pthread_2_17.h>
++#include <pthreadP_2_17.h>
++#include <endian.h>
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++
++#include <shlib-compat.h>
++#include <kernel-features.h>
++#include <stap-probe.h>
++
++
++int
++__pthread_cond_signal (pthread_cond_t *cond)
++{
++ int pshared = (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)
++ {
++ /* 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);
++ }
++/* We are done. */
++ lll_unlock (cond->__data.__lock, pshared);
++
++ return 0;
++}
++
++versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
++ GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_cond_timedwait_2_17.c b/nptl_2_17/pthread_cond_timedwait_2_17.c
+new file mode 100644
+index 00000000..965d51a1
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_timedwait_2_17.c
+@@ -0,0 +1,268 @@
++/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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
++ <http://www.gnu.org/licenses/>. */
++
++#include <pthread_2_17.h>
++#include <pthreadP_2_17.h>
++#include <endian.h>
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++#include <sys/time.h>
++#include <kernel-features.h>
++
++#include <shlib-compat.h>
++
++#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
++# undef INTERNAL_VSYSCALL
++# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
++# undef INLINE_VSYSCALL
++# define INLINE_VSYSCALL INLINE_SYSCALL
++#else
++# include <libc-vdso.h>
++#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_2_17/pthread_cond_wait_2_17.c b/nptl_2_17/pthread_cond_wait_2_17.c
+new file mode 100644
+index 00000000..ecd404ad
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_wait_2_17.c
+@@ -0,0 +1,231 @@
++/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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
++ <http://www.gnu.org/licenses/>. */
++
++#include <pthread_2_17.h>
++#include <pthreadP_2_17.h>
++#include <endian.h>
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++#include <kernel-features.h>
++#include <shlib-compat.h>
++#include <stap-probe.h>
++
++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)
++{
++ 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)
++ {
++ /* 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;
++ }
++
++ cbuffer->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. */
++ destroying = 0;
++ if (cbuffer->cond->__data.__total_seq == -1ULL
++ && cbuffer->cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
++ {
++ lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1, pshared);
++ destroying = 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);
++}
++
++int
++__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
++{
++struct _pthread_cleanup_buffer buffer;
++ struct _condvar_cleanup_buffer cbuffer;
++ int err;
++ int pshared = (cond->__data.__mutex == (void *) ~0l)
++ ? LLL_SHARED : LLL_PRIVATE;
++
++#if (defined lll_futex_wait_requeue_pi \
++ && defined __ASSUME_REQUEUE_PI)
++ int pi_flag = 0;
++#endif
++
++ LIBC_PROBE (cond_wait, 2, cond, mutex);
++ /* Make sure we are alone. */
++ lll_lock (cond->__data.__lock, pshared);
++
++ /* Now we can release the mutex. */
++ err = __pthread_mutex_unlock_usercnt (mutex, 0);
++ if (__glibc_unlikely (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;
++
++ /* 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;
++
++ do
++ {
++ 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);
++ }
++ else
++#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;
++
++ /* Check whether we are eligible for wakeup. */
++ val = cond->__data.__wakeup_seq;
++ }
++ 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 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. 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);
++}
++
++versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
++ GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_condattr_getclock_2_17.c b/nptl_2_17/pthread_condattr_getclock_2_17.c
+new file mode 100644
+index 00000000..e07b349e
+--- /dev/null
++++ b/nptl_2_17/pthread_condattr_getclock_2_17.c
+@@ -0,0 +1,28 @@
++/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++
++
++int
++pthread_condattr_getclock (const pthread_condattr_t *attr, clockid_t *clock_id)
++{
++ *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1)
++ & ((1 << COND_NWAITERS_SHIFT) - 1));
++ return 0;
++}
+diff --git a/nptl_2_17/pthread_condattr_getpshared_2_17.c b/nptl_2_17/pthread_condattr_getpshared_2_17.c
+new file mode 100644
+index 00000000..8f4fe2bf
+--- /dev/null
++++ b/nptl_2_17/pthread_condattr_getpshared_2_17.c
+@@ -0,0 +1,28 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++
++
++int
++pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
++{
++ *pshared = ((const struct pthread_condattr *) attr)->value & 1;
++
++ return 0;
++}
+diff --git a/nptl_2_17/pthread_condattr_init_2_17.c b/nptl_2_17/pthread_condattr_init_2_17.c
+new file mode 100644
+index 00000000..d90ba1e8
+--- /dev/null
++++ b/nptl_2_17/pthread_condattr_init_2_17.c
+@@ -0,0 +1,34 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include <string.h>
++#include "pthreadP_2_17.h"
++
++
++int
++__pthread_condattr_init (pthread_condattr_t *attr)
++{
++ ASSERT_TYPE_SIZE (pthread_condattr_t, __SIZEOF_PTHREAD_CONDATTR_T);
++ ASSERT_PTHREAD_INTERNAL_SIZE (pthread_condattr_t,
++ struct pthread_condattr);
++
++ memset (attr, '\0', sizeof (*attr));
++
++ return 0;
++}
++strong_alias (__pthread_condattr_init, pthread_condattr_init)
+diff --git a/nptl_2_17/pthread_condattr_setclock_2_17.c b/nptl_2_17/pthread_condattr_setclock_2_17.c
+new file mode 100644
+index 00000000..5d91f17b
+--- /dev/null
++++ b/nptl_2_17/pthread_condattr_setclock_2_17.c
+@@ -0,0 +1,45 @@
++/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <time.h>
++#include <sysdep.h>
++#include "pthreadP_2_17.h"
++
++
++int
++pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id)
++{
++ /* Only a few clocks are allowed. */
++ if (clock_id != CLOCK_MONOTONIC && clock_id != CLOCK_REALTIME)
++ /* If more clocks are allowed some day the storing of the clock ID
++ in the pthread_cond_t structure needs to be adjusted. */
++ return EINVAL;
++
++ /* Make sure the value fits in the bits we reserved. */
++ assert (clock_id < (1 << COND_NWAITERS_SHIFT));
++
++ int *valuep = &((struct pthread_condattr *) attr)->value;
++
++ *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1))
++ | (clock_id << 1));
++
++ return 0;
++}
+diff --git a/nptl_2_17/pthread_mutex_cond_lock_2_17.c b/nptl_2_17/pthread_mutex_cond_lock_2_17.c
+new file mode 100644
+index 00000000..2f077130
+--- /dev/null
++++ b/nptl_2_17/pthread_mutex_cond_lock_2_17.c
+@@ -0,0 +1,21 @@
++#include <pthreadP.h>
++
++#define LLL_MUTEX_LOCK(mutex) \
++ lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex))
++
++/* Not actually elided so far. Needed? */
++#define LLL_MUTEX_LOCK_ELISION(mutex) \
++ ({ lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)); 0; })
++
++#define LLL_MUTEX_TRYLOCK(mutex) \
++ lll_cond_trylock ((mutex)->__data.__lock)
++#define LLL_MUTEX_TRYLOCK_ELISION(mutex) LLL_MUTEX_TRYLOCK(mutex)
++
++/* We need to assume that there are other threads blocked on the futex.
++ See __pthread_mutex_lock_full for further details. */
++#define LLL_ROBUST_MUTEX_LOCK_MODIFIER FUTEX_WAITERS
++#define __pthread_mutex_lock __pthread_mutex_cond_lock
++#define __pthread_mutex_lock_full __pthread_mutex_cond_lock_full
++#define NO_INCR
++
++#include <nptl/pthread_mutex_lock.c>
+diff --git a/nptl_2_17/pthread_mutex_lock_2_17.c b/nptl_2_17/pthread_mutex_lock_2_17.c
+new file mode 100644
+index 00000000..73ee0842
+--- /dev/null
++++ b/nptl_2_17/pthread_mutex_lock_2_17.c
+@@ -0,0 +1,628 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <assert.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <sys/param.h>
++#include <not-cancel.h>
++#include <atomic.h>
++#include <futex-internal.h>
++#include <stap-probe.h>
++
++#ifndef lll_lock_elision
++#define lll_lock_elision(lock, try_lock, private) ({ \
++ lll_lock (lock, private); 0; })
++#endif
++
++#ifndef lll_trylock_elision
++#define lll_trylock_elision(a,t) lll_trylock(a)
++#endif
++
++/* Some of the following definitions differ when pthread_mutex_cond_lock.c
++ includes this file. */
++#ifndef LLL_MUTEX_LOCK
++# define LLL_MUTEX_LOCK(mutex) \
++ lll_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex))
++# define LLL_MUTEX_TRYLOCK(mutex) \
++ lll_trylock ((mutex)->__data.__lock)
++# define LLL_ROBUST_MUTEX_LOCK_MODIFIER 0
++# define LLL_MUTEX_LOCK_ELISION(mutex) \
++ lll_lock_elision ((mutex)->__data.__lock, (mutex)->__data.__elision, \
++ PTHREAD_MUTEX_PSHARED (mutex))
++# define LLL_MUTEX_TRYLOCK_ELISION(mutex) \
++ lll_trylock_elision((mutex)->__data.__lock, (mutex)->__data.__elision, \
++ PTHREAD_MUTEX_PSHARED (mutex))
++#endif
++
++#ifndef FORCE_ELISION
++#define FORCE_ELISION(m, s)
++#endif
++
++static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
++ __attribute_noinline__;
++
++int
++__pthread_mutex_lock (pthread_mutex_t *mutex)
++{
++ /* See concurrency notes regarding mutex type which is loaded from __kind
++ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
++ unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
++
++ LIBC_PROBE (mutex_entry, 1, mutex);
++
++ if (__builtin_expect (type & ~(PTHREAD_MUTEX_KIND_MASK_NP
++ | PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
++ return __pthread_mutex_lock_full (mutex);
++
++ if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_NP))
++ {
++ FORCE_ELISION (mutex, goto elision);
++ simple:
++ /* Normal mutex. */
++ LLL_MUTEX_LOCK (mutex);
++ assert (mutex->__data.__owner == 0);
++ }
++#ifdef HAVE_ELISION
++ else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP))
++ {
++ elision: __attribute__((unused))
++ /* This case can never happen on a system without elision,
++ as the mutex type initialization functions will not
++ allow to set the elision flags. */
++ /* Don't record owner or users for elision case. This is a
++ tail call. */
++ return LLL_MUTEX_LOCK_ELISION (mutex);
++ }
++#endif
++ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
++ == PTHREAD_MUTEX_RECURSIVE_NP, 1))
++ {
++ /* Recursive mutex. */
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++
++ /* Check whether we already hold the mutex. */
++ if (mutex->__data.__owner == id)
++ {
++ /* Just bump the counter. */
++ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
++ /* Overflow of the counter. */
++ return EAGAIN;
++
++ ++mutex->__data.__count;
++
++ return 0;
++ }
++
++ /* We have to get the mutex. */
++ LLL_MUTEX_LOCK (mutex);
++
++ assert (mutex->__data.__owner == 0);
++ mutex->__data.__count = 1;
++ }
++ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
++ == PTHREAD_MUTEX_ADAPTIVE_NP, 1))
++ {
++ if (! __is_smp)
++ goto simple;
++
++ if (LLL_MUTEX_TRYLOCK (mutex) != 0)
++ {
++ int cnt = 0;
++ int max_cnt = MIN (DEFAULT_ADAPTIVE_COUNT,
++ mutex->__data.__spins * 2 + 10);
++ do
++ {
++ if (cnt++ >= max_cnt)
++ {
++ LLL_MUTEX_LOCK (mutex);
++ break;
++ }
++ atomic_spin_nop ();
++ }
++ while (LLL_MUTEX_TRYLOCK (mutex) != 0);
++
++ mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
++ }
++ assert (mutex->__data.__owner == 0);
++ }
++ else
++ {
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++ assert (PTHREAD_MUTEX_TYPE (mutex) == PTHREAD_MUTEX_ERRORCHECK_NP);
++ /* Check whether we already hold the mutex. */
++ if (__glibc_unlikely (mutex->__data.__owner == id))
++ return EDEADLK;
++ goto simple;
++ }
++
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++
++ /* Record the ownership. */
++ mutex->__data.__owner = id;
++#ifndef NO_INCR
++ ++mutex->__data.__nusers;
++#endif
++
++ LIBC_PROBE (mutex_acquired, 1, mutex);
++
++ return 0;
++}
++
++static int
++__pthread_mutex_lock_full (pthread_mutex_t *mutex)
++{
++ int oldval;
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++
++ switch (PTHREAD_MUTEX_TYPE (mutex))
++ {
++ case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
++ case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
++ case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ &mutex->__data.__list.__next);
++ /* We need to set op_pending before starting the operation. Also
++ see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++
++ oldval = mutex->__data.__lock;
++ /* This is set to FUTEX_WAITERS iff we might have shared the
++ FUTEX_WAITERS flag with other threads, and therefore need to keep it
++ set to avoid lost wake-ups. We have the same requirement in the
++ simple mutex algorithm.
++ We start with value zero for a normal mutex, and FUTEX_WAITERS if we
++ are building the special case mutexes for use from within condition
++ variables. */
++ unsigned int assume_other_futex_waiters = LLL_ROBUST_MUTEX_LOCK_MODIFIER;
++ while (1)
++ {
++ /* Try to acquire the lock through a CAS from 0 (not acquired) to
++ our TID | assume_other_futex_waiters. */
++ if (__glibc_likely (oldval == 0))
++ {
++ oldval
++ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ id | assume_other_futex_waiters, 0);
++ if (__glibc_likely (oldval == 0))
++ break;
++ }
++
++ if ((oldval & FUTEX_OWNER_DIED) != 0)
++ {
++ /* The previous owner died. Try locking the mutex. */
++ int newval = id;
++#ifdef NO_INCR
++ /* We are not taking assume_other_futex_waiters into accoount
++ here simply because we'll set FUTEX_WAITERS anyway. */
++ newval |= FUTEX_WAITERS;
++#else
++ newval |= (oldval & FUTEX_WAITERS) | assume_other_futex_waiters;
++#endif
++
++ newval
++ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ newval, oldval);
++
++ if (newval != oldval)
++ {
++ oldval = newval;
++ continue;
++ }
++
++ /* We got the mutex. */
++ mutex->__data.__count = 1;
++ /* But it is inconsistent unless marked otherwise. */
++ mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
++
++ /* We must not enqueue the mutex before we have acquired it.
++ Also see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ ENQUEUE_MUTEX (mutex);
++ /* We need to clear op_pending after we enqueue the mutex. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++
++ /* Note that we deliberately exit here. If we fall
++ through to the end of the function __nusers would be
++ incremented which is not correct because the old
++ owner has to be discounted. If we are not supposed
++ to increment __nusers we actually have to decrement
++ it here. */
++#ifdef NO_INCR
++ --mutex->__data.__nusers;
++#endif
++
++ return EOWNERDEAD;
++ }
++
++ /* Check whether we already hold the mutex. */
++ if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
++ {
++ int kind = PTHREAD_MUTEX_TYPE (mutex);
++ if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
++ {
++ /* We do not need to ensure ordering wrt another memory
++ access. Also see comments at ENQUEUE_MUTEX. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ NULL);
++ return EDEADLK;
++ }
++
++ if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
++ {
++ /* We do not need to ensure ordering wrt another memory
++ access. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ NULL);
++
++ /* Just bump the counter. */
++ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
++ /* Overflow of the counter. */
++ return EAGAIN;
++
++ ++mutex->__data.__count;
++
++ return 0;
++ }
++ }
++
++ /* We cannot acquire the mutex nor has its owner died. Thus, try
++ to block using futexes. Set FUTEX_WAITERS if necessary so that
++ other threads are aware that there are potentially threads
++ blocked on the futex. Restart if oldval changed in the
++ meantime. */
++ if ((oldval & FUTEX_WAITERS) == 0)
++ {
++ if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
++ oldval | FUTEX_WAITERS,
++ oldval)
++ != 0)
++ {
++ oldval = mutex->__data.__lock;
++ continue;
++ }
++ oldval |= FUTEX_WAITERS;
++ }
++
++ /* It is now possible that we share the FUTEX_WAITERS flag with
++ another thread; therefore, update assume_other_futex_waiters so
++ that we do not forget about this when handling other cases
++ above and thus do not cause lost wake-ups. */
++ assume_other_futex_waiters |= FUTEX_WAITERS;
++
++ /* Block using the futex and reload current lock value. */
++ lll_futex_wait (&mutex->__data.__lock, oldval,
++ PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
++ oldval = mutex->__data.__lock;
++ }
++
++ /* We have acquired the mutex; check if it is still consistent. */
++ if (__builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
++ {
++ /* This mutex is now not recoverable. */
++ mutex->__data.__count = 0;
++ int private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
++ lll_unlock (mutex->__data.__lock, private);
++ /* FIXME This violates the mutex destruction requirements. See
++ __pthread_mutex_unlock_full. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ return ENOTRECOVERABLE;
++ }
++
++ mutex->__data.__count = 1;
++ /* We must not enqueue the mutex before we have acquired it.
++ Also see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ ENQUEUE_MUTEX (mutex);
++ /* We need to clear op_pending after we enqueue the mutex. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ break;
++
++ /* The PI support requires the Linux futex system call. If that's not
++ available, pthread_mutex_init should never have allowed the type to
++ be set. So it will get the default case for an invalid type. */
++#ifdef __NR_futex
++ case PTHREAD_MUTEX_PI_RECURSIVE_NP:
++ case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PI_NORMAL_NP:
++ case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
++ {
++ int kind, robust;
++ {
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
++ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
++ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
++ }
++
++ if (robust)
++ {
++ /* Note: robust PI futexes are signaled by setting bit 0. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ (void *) (((uintptr_t) &mutex->__data.__list.__next)
++ | 1));
++ /* We need to set op_pending before starting the operation. Also
++ see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ }
++
++ oldval = mutex->__data.__lock;
++
++ /* Check whether we already hold the mutex. */
++ if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
++ {
++ if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
++ {
++ /* We do not need to ensure ordering wrt another memory
++ access. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ return EDEADLK;
++ }
++
++ if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
++ {
++ /* We do not need to ensure ordering wrt another memory
++ access. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++
++ /* Just bump the counter. */
++ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
++ /* Overflow of the counter. */
++ return EAGAIN;
++
++ ++mutex->__data.__count;
++
++ return 0;
++ }
++ }
++
++ int newval = id;
++# ifdef NO_INCR
++ newval |= FUTEX_WAITERS;
++# endif
++ oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ newval, 0);
++
++ if (oldval != 0)
++ {
++ /* The mutex is locked. The kernel will now take care of
++ everything. */
++ int private = (robust
++ ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
++ : PTHREAD_MUTEX_PSHARED (mutex));
++ int e = futex_lock_pi ((unsigned int *) &mutex->__data.__lock,
++ NULL, private);
++ if (e == ESRCH || e == EDEADLK)
++ {
++ assert (e != EDEADLK
++ || (kind != PTHREAD_MUTEX_ERRORCHECK_NP
++ && kind != PTHREAD_MUTEX_RECURSIVE_NP));
++ /* ESRCH can happen only for non-robust PI mutexes where
++ the owner of the lock died. */
++ assert (e != ESRCH || !robust);
++
++ /* Delay the thread indefinitely. */
++ while (1)
++ lll_timedwait (&(int){0}, 0, 0 /* ignored */, NULL,
++ private);
++ }
++
++ oldval = mutex->__data.__lock;
++
++ assert (robust || (oldval & FUTEX_OWNER_DIED) == 0);
++ }
++
++ if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
++ {
++ atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED);
++
++ /* We got the mutex. */
++ mutex->__data.__count = 1;
++ /* But it is inconsistent unless marked otherwise. */
++ mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
++
++ /* We must not enqueue the mutex before we have acquired it.
++ Also see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ ENQUEUE_MUTEX_PI (mutex);
++ /* We need to clear op_pending after we enqueue the mutex. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++
++ /* Note that we deliberately exit here. If we fall
++ through to the end of the function __nusers would be
++ incremented which is not correct because the old owner
++ has to be discounted. If we are not supposed to
++ increment __nusers we actually have to decrement it here. */
++# ifdef NO_INCR
++ --mutex->__data.__nusers;
++# endif
++
++ return EOWNERDEAD;
++ }
++
++ if (robust
++ && __builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
++ {
++ /* This mutex is now not recoverable. */
++ mutex->__data.__count = 0;
++
++ futex_unlock_pi ((unsigned int *) &mutex->__data.__lock,
++ PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
++
++ /* To the kernel, this will be visible after the kernel has
++ acquired the mutex in the syscall. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ return ENOTRECOVERABLE;
++ }
++
++ mutex->__data.__count = 1;
++ if (robust)
++ {
++ /* We must not enqueue the mutex before we have acquired it.
++ Also see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ ENQUEUE_MUTEX_PI (mutex);
++ /* We need to clear op_pending after we enqueue the mutex. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ }
++ }
++ break;
++#endif /* __NR_futex. */
++
++ case PTHREAD_MUTEX_PP_RECURSIVE_NP:
++ case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PP_NORMAL_NP:
++ case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
++ {
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
++ & PTHREAD_MUTEX_KIND_MASK_NP;
++
++ oldval = mutex->__data.__lock;
++
++ /* Check whether we already hold the mutex. */
++ if (mutex->__data.__owner == id)
++ {
++ if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
++ return EDEADLK;
++
++ if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
++ {
++ /* Just bump the counter. */
++ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
++ /* Overflow of the counter. */
++ return EAGAIN;
++
++ ++mutex->__data.__count;
++
++ return 0;
++ }
++ }
++
++ int oldprio = -1, ceilval;
++ do
++ {
++ int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
++ >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
++
++ if (__pthread_current_priority () > ceiling)
++ {
++ if (oldprio != -1)
++ __pthread_tpp_change_priority (oldprio, -1);
++ return EINVAL;
++ }
++
++ int retval = __pthread_tpp_change_priority (oldprio, ceiling);
++ if (retval)
++ return retval;
++
++ ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
++ oldprio = ceiling;
++
++ oldval
++ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++#ifdef NO_INCR
++ ceilval | 2,
++#else
++ ceilval | 1,
++#endif
++ ceilval);
++
++ if (oldval == ceilval)
++ break;
++
++ do
++ {
++ oldval
++ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ ceilval | 2,
++ ceilval | 1);
++
++ if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
++ break;
++
++ if (oldval != ceilval)
++ lll_futex_wait (&mutex->__data.__lock, ceilval | 2,
++ PTHREAD_MUTEX_PSHARED (mutex));
++ }
++ while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ ceilval | 2, ceilval)
++ != ceilval);
++ }
++ while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
++
++ assert (mutex->__data.__owner == 0);
++ mutex->__data.__count = 1;
++ }
++ break;
++
++ default:
++ /* Correct code cannot set any other type. */
++ return EINVAL;
++ }
++
++ /* Record the ownership. */
++ mutex->__data.__owner = id;
++#ifndef NO_INCR
++ ++mutex->__data.__nusers;
++#endif
++
++ LIBC_PROBE (mutex_acquired, 1, mutex);
++
++ return 0;
++}
++#ifndef __pthread_mutex_lock
++weak_alias (__pthread_mutex_lock, pthread_mutex_lock)
++hidden_def (__pthread_mutex_lock)
++#endif
++
++
++#ifdef NO_INCR
++void
++__pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex)
++{
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
++ assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
++ assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
++ assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
++
++ /* Record the ownership. */
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++ mutex->__data.__owner = id;
++
++ if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
++ ++mutex->__data.__count;
++}
++#endif
+diff --git a/nptl_2_17/pthread_mutex_unlock_2_17.c b/nptl_2_17/pthread_mutex_unlock_2_17.c
+new file mode 100644
+index 00000000..18ba158e
+--- /dev/null
++++ b/nptl_2_17/pthread_mutex_unlock_2_17.c
+@@ -0,0 +1,360 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <assert.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <lowlevellock.h>
++#include <stap-probe.h>
++#include <futex-internal.h>
++
++#ifndef lll_unlock_elision
++#define lll_unlock_elision(a,b,c) ({ lll_unlock (a,c); 0; })
++#endif
++
++static int
++__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
++ __attribute_noinline__;
++
++int
++attribute_hidden
++__pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr)
++{
++ /* See concurrency notes regarding mutex type which is loaded from __kind
++ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
++ int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
++ if (__builtin_expect (type
++ & ~(PTHREAD_MUTEX_KIND_MASK_NP
++ |PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
++ return __pthread_mutex_unlock_full (mutex, decr);
++
++ if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP)
++ == PTHREAD_MUTEX_TIMED_NP)
++ {
++ /* Always reset the owner field. */
++ normal:
++ mutex->__data.__owner = 0;
++ if (decr)
++ /* One less user. */
++ --mutex->__data.__nusers;
++
++ /* Unlock. */
++ lll_unlock (mutex->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex));
++
++ LIBC_PROBE (mutex_release, 1, mutex);
++
++ return 0;
++ }
++ else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP))
++ {
++ /* Don't reset the owner/users fields for elision. */
++ return lll_unlock_elision (mutex->__data.__lock, mutex->__data.__elision,
++ PTHREAD_MUTEX_PSHARED (mutex));
++ }
++ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
++ == PTHREAD_MUTEX_RECURSIVE_NP, 1))
++ {
++ /* Recursive mutex. */
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++ goto normal;
++ }
++ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
++ == PTHREAD_MUTEX_ADAPTIVE_NP, 1))
++ goto normal;
++ else
++ {
++ /* Error checking mutex. */
++ assert (type == PTHREAD_MUTEX_ERRORCHECK_NP);
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
++ || ! lll_islocked (mutex->__data.__lock))
++ return EPERM;
++ goto normal;
++ }
++}
++
++
++static int
++__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
++{
++ int newowner = 0;
++ int private;
++
++ switch (PTHREAD_MUTEX_TYPE (mutex))
++ {
++ case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
++ /* Recursive mutex. */
++ if ((mutex->__data.__lock & FUTEX_TID_MASK)
++ == THREAD_GETMEM (THREAD_SELF, tid)
++ && __builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_INCONSISTENT, 0))
++ {
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return ENOTRECOVERABLE;
++
++ goto notrecoverable;
++ }
++
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++
++ goto robust;
++
++ case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
++ case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
++ if ((mutex->__data.__lock & FUTEX_TID_MASK)
++ != THREAD_GETMEM (THREAD_SELF, tid)
++ || ! lll_islocked (mutex->__data.__lock))
++ return EPERM;
++
++ /* If the previous owner died and the caller did not succeed in
++ making the state consistent, mark the mutex as unrecoverable
++ and make all waiters. */
++ if (__builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_INCONSISTENT, 0))
++ notrecoverable:
++ newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
++
++ robust:
++ /* Remove mutex from the list. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ &mutex->__data.__list.__next);
++ /* We must set op_pending before we dequeue the mutex. Also see
++ comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ DEQUEUE_MUTEX (mutex);
++
++ mutex->__data.__owner = newowner;
++ if (decr)
++ /* One less user. */
++ --mutex->__data.__nusers;
++
++ /* Unlock by setting the lock to 0 (not acquired); if the lock had
++ FUTEX_WAITERS set previously, then wake any waiters.
++ The unlock operation must be the last access to the mutex to not
++ violate the mutex destruction requirements (see __lll_unlock). */
++ private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
++ if (__glibc_unlikely ((atomic_exchange_rel (&mutex->__data.__lock, 0)
++ & FUTEX_WAITERS) != 0))
++ lll_futex_wake (&mutex->__data.__lock, 1, private);
++
++ /* We must clear op_pending after we release the mutex.
++ FIXME However, this violates the mutex destruction requirements
++ because another thread could acquire the mutex, destroy it, and
++ reuse the memory for something else; then, if this thread crashes,
++ and the memory happens to have a value equal to the TID, the kernel
++ will believe it is still related to the mutex (which has been
++ destroyed already) and will modify some other random object. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ break;
++
++ /* The PI support requires the Linux futex system call. If that's not
++ available, pthread_mutex_init should never have allowed the type to
++ be set. So it will get the default case for an invalid type. */
++#ifdef __NR_futex
++ case PTHREAD_MUTEX_PI_RECURSIVE_NP:
++ /* Recursive mutex. */
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++ goto continue_pi_non_robust;
++
++ case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
++ /* Recursive mutex. */
++ if ((mutex->__data.__lock & FUTEX_TID_MASK)
++ == THREAD_GETMEM (THREAD_SELF, tid)
++ && __builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_INCONSISTENT, 0))
++ {
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return ENOTRECOVERABLE;
++
++ goto pi_notrecoverable;
++ }
++
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++
++ goto continue_pi_robust;
++
++ case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PI_NORMAL_NP:
++ case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
++ if ((mutex->__data.__lock & FUTEX_TID_MASK)
++ != THREAD_GETMEM (THREAD_SELF, tid)
++ || ! lll_islocked (mutex->__data.__lock))
++ return EPERM;
++
++ /* If the previous owner died and the caller did not succeed in
++ making the state consistent, mark the mutex as unrecoverable
++ and make all waiters. */
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ if ((atomic_load_relaxed (&(mutex->__data.__kind))
++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
++ && __builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_INCONSISTENT, 0))
++ pi_notrecoverable:
++ newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
++
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ if ((atomic_load_relaxed (&(mutex->__data.__kind))
++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
++ {
++ continue_pi_robust:
++ /* Remove mutex from the list.
++ Note: robust PI futexes are signaled by setting bit 0. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ (void *) (((uintptr_t) &mutex->__data.__list.__next)
++ | 1));
++ /* We must set op_pending before we dequeue the mutex. Also see
++ comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ DEQUEUE_MUTEX (mutex);
++ }
++
++ continue_pi_non_robust:
++ mutex->__data.__owner = newowner;
++ if (decr)
++ /* One less user. */
++ --mutex->__data.__nusers;
++
++ /* Unlock. Load all necessary mutex data before releasing the mutex
++ to not violate the mutex destruction requirements (see
++ lll_unlock). */
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ int robust = atomic_load_relaxed (&(mutex->__data.__kind))
++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
++ private = (robust
++ ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
++ : PTHREAD_MUTEX_PSHARED (mutex));
++ /* Unlock the mutex using a CAS unless there are futex waiters or our
++ TID is not the value of __lock anymore, in which case we let the
++ kernel take care of the situation. Use release MO in the CAS to
++ synchronize with acquire MO in lock acquisitions. */
++ int l = atomic_load_relaxed (&mutex->__data.__lock);
++ do
++ {
++ if (((l & FUTEX_WAITERS) != 0)
++ || (l != THREAD_GETMEM (THREAD_SELF, tid)))
++ {
++ futex_unlock_pi ((unsigned int *) &mutex->__data.__lock,
++ private);
++ break;
++ }
++ }
++ while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
++ &l, 0));
++
++ /* This happens after the kernel releases the mutex but violates the
++ mutex destruction requirements; see comments in the code handling
++ PTHREAD_MUTEX_ROBUST_NORMAL_NP. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ break;
++#endif /* __NR_futex. */
++
++ case PTHREAD_MUTEX_PP_RECURSIVE_NP:
++ /* Recursive mutex. */
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++ goto pp;
++
++ case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
++ /* Error checking mutex. */
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
++ || (mutex->__data.__lock & ~ PTHREAD_MUTEX_PRIO_CEILING_MASK) == 0)
++ return EPERM;
++ /* FALLTHROUGH */
++
++ case PTHREAD_MUTEX_PP_NORMAL_NP:
++ case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
++ /* Always reset the owner field. */
++ pp:
++ mutex->__data.__owner = 0;
++
++ if (decr)
++ /* One less user. */
++ --mutex->__data.__nusers;
++
++ /* Unlock. Use release MO in the CAS to synchronize with acquire MO in
++ lock acquisitions. */
++ int newval;
++ int oldval = atomic_load_relaxed (&mutex->__data.__lock);
++ do
++ {
++ newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK;
++ }
++ while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
++ &oldval, newval));
++
++ if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1)
++ lll_futex_wake (&mutex->__data.__lock, 1,
++ PTHREAD_MUTEX_PSHARED (mutex));
++
++ int oldprio = newval >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
++
++ LIBC_PROBE (mutex_release, 1, mutex);
++
++ return __pthread_tpp_change_priority (oldprio, -1);
++
++ default:
++ /* Correct code cannot set any other type. */
++ return EINVAL;
++ }
++
++ LIBC_PROBE (mutex_release, 1, mutex);
++ return 0;
++}
++
++
++int
++__pthread_mutex_unlock (pthread_mutex_t *mutex)
++{
++ return __pthread_mutex_unlock_usercnt (mutex, 1);
++}
++weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
++hidden_def (__pthread_mutex_unlock)
+diff --git a/nptl_2_17/pthreadtypes_2_17.h b/nptl_2_17/pthreadtypes_2_17.h
+new file mode 100644
+index 00000000..0483e44a
+--- /dev/null
++++ b/nptl_2_17/pthreadtypes_2_17.h
+@@ -0,0 +1,179 @@
++/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _INTERNALTYPES_H
++#define _INTERNALTYPES_H 1
++
++#include <stdint.h>
++#include <atomic.h>
++#include <endian.h>
++
++
++struct pthread_attr
++{
++ /* Scheduler parameters and priority. */
++ struct sched_param schedparam;
++ int schedpolicy;
++ /* Various flags like detachstate, scope, etc. */
++ int flags;
++ /* Size of guard area. */
++ size_t guardsize;
++ /* Stack handling. */
++ void *stackaddr;
++ size_t stacksize;
++ /* Affinity map. */
++ cpu_set_t *cpuset;
++ size_t cpusetsize;
++};
++
++#define ATTR_FLAG_DETACHSTATE 0x0001
++#define ATTR_FLAG_NOTINHERITSCHED 0x0002
++#define ATTR_FLAG_SCOPEPROCESS 0x0004
++#define ATTR_FLAG_STACKADDR 0x0008
++#define ATTR_FLAG_OLDATTR 0x0010
++#define ATTR_FLAG_SCHED_SET 0x0020
++#define ATTR_FLAG_POLICY_SET 0x0040
++
++
++/* Mutex attribute data structure. */
++struct pthread_mutexattr
++{
++ /* Identifier for the kind of mutex.
++
++ Bit 31 is set if the mutex is to be shared between processes.
++
++ Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify
++ the type of the mutex. */
++ int mutexkind;
++};
++
++
++/* Conditional variable attribute data structure. */
++struct pthread_condattr
++{
++ /* Combination of values:
++
++ 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;
++};
++#define COND_CLOCK_BITS 1
++#define COND_NWAITERS_SHIFT 1
++
++/* Read-write lock variable attribute data structure. */
++struct pthread_rwlockattr
++{
++ int lockkind;
++ int pshared;
++};
++
++
++/* Barrier data structure. See pthread_barrier_wait for a description
++ of how these fields are used. */
++struct pthread_barrier
++{
++ unsigned int in;
++ unsigned int current_round;
++ unsigned int count;
++ int shared;
++ unsigned int out;
++};
++/* See pthread_barrier_wait for a description. */
++#define BARRIER_IN_THRESHOLD (UINT_MAX/2)
++
++
++/* Barrier variable attribute data structure. */
++struct pthread_barrierattr
++{
++ int pshared;
++};
++
++
++/* Thread-local data handling. */
++struct pthread_key_struct
++{
++ /* Sequence numbers. Even numbers indicated vacant entries. Note
++ that zero is even. We use uintptr_t to not require padding on
++ 32- and 64-bit machines. On 64-bit machines it helps to avoid
++ wrapping, too. */
++ uintptr_t seq;
++
++ /* Destructor for the data. */
++ void (*destr) (void *);
++};
++
++/* Check whether an entry is unused. */
++#define KEY_UNUSED(p) (((p) & 1) == 0)
++/* Check whether a key is usable. We cannot reuse an allocated key if
++ the sequence counter would overflow after the next destroy call.
++ This would mean that we potentially free memory for a key with the
++ same sequence. This is *very* unlikely to happen, A program would
++ have to create and destroy a key 2^31 times (on 32-bit platforms,
++ on 64-bit platforms that would be 2^63). If it should happen we
++ simply don't use this specific key anymore. */
++#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2)))
++
++
++/* Handling of read-write lock data. */
++// XXX For now there is only one flag. Maybe more in future.
++#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0)
++
++
++/* Semaphore variable structure. */
++struct new_sem
++{
++#if __HAVE_64B_ATOMICS
++ /* The data field holds both value (in the least-significant 32 bits) and
++ nwaiters. */
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++# define SEM_VALUE_OFFSET 0
++# elif __BYTE_ORDER == __BIG_ENDIAN
++# define SEM_VALUE_OFFSET 1
++# else
++# error Unsupported byte order.
++# endif
++# define SEM_NWAITERS_SHIFT 32
++# define SEM_VALUE_MASK (~(unsigned int)0)
++ uint64_t data;
++ int private;
++ int pad;
++#else
++# define SEM_VALUE_SHIFT 1
++# define SEM_NWAITERS_MASK ((unsigned int)1)
++ unsigned int value;
++ int private;
++ int pad;
++ unsigned int nwaiters;
++#endif
++};
++
++struct old_sem
++{
++ unsigned int value;
++};
++
++
++/* Compatibility type for old conditional variable interfaces. */
++typedef struct
++{
++ pthread_cond_t *cond;
++} pthread_cond_2_0_t;
++
++#endif /* internaltypes.h */
+diff --git a/nptl_2_17/tpp_2_17.c b/nptl_2_17/tpp_2_17.c
+new file mode 100644
+index 00000000..56357ea3
+--- /dev/null
++++ b/nptl_2_17/tpp_2_17.c
+@@ -0,0 +1,195 @@
++/* Thread Priority Protect helpers.
++ Copyright (C) 2006-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
++
++ 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
++ <https://www.gnu.org/licenses/>. */
++
++#include <assert.h>
++#include <atomic.h>
++#include <errno.h>
++#include <pthreadP.h>
++#include <sched.h>
++#include <stdlib.h>
++#include <atomic.h>
++
++
++int __sched_fifo_min_prio = -1;
++int __sched_fifo_max_prio = -1;
++
++/* We only want to initialize __sched_fifo_min_prio and __sched_fifo_max_prio
++ once. The standard solution would be similar to pthread_once, but then
++ readers would need to use an acquire fence. In this specific case,
++ initialization is comprised of just idempotent writes to two variables
++ that have an initial value of -1. Therefore, we can treat each variable as
++ a separate, at-least-once initialized value. This enables using just
++ relaxed MO loads and stores, but requires that consumers check for
++ initialization of each value that is to be used; see
++ __pthread_tpp_change_priority for an example.
++ */
++void
++__init_sched_fifo_prio (void)
++{
++ atomic_store_relaxed (&__sched_fifo_max_prio,
++ __sched_get_priority_max (SCHED_FIFO));
++ atomic_store_relaxed (&__sched_fifo_min_prio,
++ __sched_get_priority_min (SCHED_FIFO));
++}
++
++int
++__pthread_tpp_change_priority (int previous_prio, int new_prio)
++{
++ struct pthread *self = THREAD_SELF;
++ struct priority_protection_data *tpp = THREAD_GETMEM (self, tpp);
++ int fifo_min_prio = atomic_load_relaxed (&__sched_fifo_min_prio);
++ int fifo_max_prio = atomic_load_relaxed (&__sched_fifo_max_prio);
++
++ if (tpp == NULL)
++ {
++ /* See __init_sched_fifo_prio. We need both the min and max prio,
++ so need to check both, and run initialization if either one is
++ not initialized. The memory model's write-read coherence rule
++ makes this work. */
++ if (fifo_min_prio == -1 || fifo_max_prio == -1)
++ {
++ __init_sched_fifo_prio ();
++ fifo_min_prio = atomic_load_relaxed (&__sched_fifo_min_prio);
++ fifo_max_prio = atomic_load_relaxed (&__sched_fifo_max_prio);
++ }
++
++ size_t size = sizeof *tpp;
++ size += (fifo_max_prio - fifo_min_prio + 1)
++ * sizeof (tpp->priomap[0]);
++ tpp = calloc (size, 1);
++ if (tpp == NULL)
++ return ENOMEM;
++ tpp->priomax = fifo_min_prio - 1;
++ THREAD_SETMEM (self, tpp, tpp);
++ }
++
++ assert (new_prio == -1
++ || (new_prio >= fifo_min_prio
++ && new_prio <= fifo_max_prio));
++ assert (previous_prio == -1
++ || (previous_prio >= fifo_min_prio
++ && previous_prio <= fifo_max_prio));
++
++ int priomax = tpp->priomax;
++ int newpriomax = priomax;
++ if (new_prio != -1)
++ {
++ if (tpp->priomap[new_prio - fifo_min_prio] + 1 == 0)
++ return EAGAIN;
++ ++tpp->priomap[new_prio - fifo_min_prio];
++ if (new_prio > priomax)
++ newpriomax = new_prio;
++ }
++
++ if (previous_prio != -1)
++ {
++ if (--tpp->priomap[previous_prio - fifo_min_prio] == 0
++ && priomax == previous_prio
++ && previous_prio > new_prio)
++ {
++ int i;
++ for (i = previous_prio - 1; i >= fifo_min_prio; --i)
++ if (tpp->priomap[i - fifo_min_prio])
++ break;
++ newpriomax = i;
++ }
++ }
++
++ if (priomax == newpriomax)
++ return 0;
++
++ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */
++ lll_lock (self->lock, LLL_PRIVATE);
++
++ tpp->priomax = newpriomax;
++
++ int result = 0;
++
++ if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
++ {
++ if (__sched_getparam (self->tid, &self->schedparam) != 0)
++ result = errno;
++ else
++ self->flags |= ATTR_FLAG_SCHED_SET;
++ }
++
++ if ((self->flags & ATTR_FLAG_POLICY_SET) == 0)
++ {
++ self->schedpolicy = __sched_getscheduler (self->tid);
++ if (self->schedpolicy == -1)
++ result = errno;
++ else
++ self->flags |= ATTR_FLAG_POLICY_SET;
++ }
++
++ if (result == 0)
++ {
++ struct sched_param sp = self->schedparam;
++ if (sp.sched_priority < newpriomax || sp.sched_priority < priomax)
++ {
++ if (sp.sched_priority < newpriomax)
++ sp.sched_priority = newpriomax;
++
++ if (__sched_setscheduler (self->tid, self->schedpolicy, &sp) < 0)
++ result = errno;
++ }
++ }
++
++ lll_unlock (self->lock, LLL_PRIVATE);
++
++ return result;
++}
++
++int
++__pthread_current_priority (void)
++{
++ struct pthread *self = THREAD_SELF;
++ if ((self->flags & (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET))
++ == (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET))
++ return self->schedparam.sched_priority;
++
++ int result = 0;
++
++ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */
++ lll_lock (self->lock, LLL_PRIVATE);
++
++ if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
++ {
++ if (__sched_getparam (self->tid, &self->schedparam) != 0)
++ result = -1;
++ else
++ self->flags |= ATTR_FLAG_SCHED_SET;
++ }
++
++ if ((self->flags & ATTR_FLAG_POLICY_SET) == 0)
++ {
++ self->schedpolicy = __sched_getscheduler (self->tid);
++ if (self->schedpolicy == -1)
++ result = -1;
++ else
++ self->flags |= ATTR_FLAG_POLICY_SET;
++ }
++
++ if (result != -1)
++ result = self->schedparam.sched_priority;
++
++ lll_unlock (self->lock, LLL_PRIVATE);
++
++ return result;
++}
+diff --git a/nptl_2_17/unwind_2_17.c b/nptl_2_17/unwind_2_17.c
+new file mode 100644
+index 00000000..1534540c
+--- /dev/null
++++ b/nptl_2_17/unwind_2_17.c
+@@ -0,0 +1,138 @@
++/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>
++ and Richard Henderson <rth@redhat.com>, 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
++ <https://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <setjmp.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <jmpbuf-unwind.h>
++
++#ifdef _STACK_GROWS_DOWN
++# define FRAME_LEFT(frame, other, adj) \
++ ((uintptr_t) frame - adj >= (uintptr_t) other - adj)
++#elif _STACK_GROWS_UP
++# define FRAME_LEFT(frame, other, adj) \
++ ((uintptr_t) frame - adj <= (uintptr_t) other - adj)
++#else
++# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
++#endif
++
++static _Unwind_Reason_Code
++unwind_stop (int version, _Unwind_Action actions,
++ _Unwind_Exception_Class exc_class,
++ struct _Unwind_Exception *exc_obj,
++ struct _Unwind_Context *context, void *stop_parameter)
++{
++ struct pthread_unwind_buf *buf = stop_parameter;
++ struct pthread *self = THREAD_SELF;
++ struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup);
++ int do_longjump = 0;
++
++ /* Adjust all pointers used in comparisons, so that top of thread's
++ stack is at the top of address space. Without that, things break
++ if stack is allocated above the main stack. */
++ uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size;
++
++ /* Do longjmp if we're at "end of stack", aka "end of unwind data".
++ We assume there are only C frame without unwind data in between
++ here and the jmp_buf target. Otherwise simply note that the CFA
++ of a function is NOT within it's stack frame; it's the SP of the
++ previous frame. */
++ if ((actions & _UA_END_OF_STACK)
++ || ! _JMPBUF_CFA_UNWINDS_ADJ (buf->cancel_jmp_buf[0].jmp_buf, context,
++ adj))
++ do_longjump = 1;
++
++ if (__glibc_unlikely (curp != NULL))
++ {
++ /* Handle the compatibility stuff. Execute all handlers
++ registered with the old method which would be unwound by this
++ step. */
++ struct _pthread_cleanup_buffer *oldp = buf->priv.data.cleanup;
++ void *cfa = (void *) (_Unwind_Ptr) _Unwind_GetCFA (context);
++
++ if (curp != oldp && (do_longjump || FRAME_LEFT (cfa, curp, adj)))
++ {
++ do
++ {
++ /* Pointer to the next element. */
++ struct _pthread_cleanup_buffer *nextp = curp->__prev;
++
++ /* Call the handler. */
++ curp->__routine (curp->__arg);
++
++ /* To the next. */
++ curp = nextp;
++ }
++ while (curp != oldp
++ && (do_longjump || FRAME_LEFT (cfa, curp, adj)));
++
++ /* Mark the current element as handled. */
++ THREAD_SETMEM (self, cleanup, curp);
++ }
++ }
++
++ if (do_longjump)
++ __libc_unwind_longjmp ((struct __jmp_buf_tag *) buf->cancel_jmp_buf, 1);
++
++ return _URC_NO_REASON;
++}
++
++
++static void
++unwind_cleanup (_Unwind_Reason_Code reason, struct _Unwind_Exception *exc)
++{
++ /* When we get here a C++ catch block didn't rethrow the object. We
++ cannot handle this case and therefore abort. */
++ __libc_fatal ("FATAL: exception not rethrown\n");
++}
++
++
++void
++__cleanup_fct_attribute __attribute ((noreturn))
++__pthread_unwind (__pthread_unwind_buf_t *buf)
++{
++ struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
++ struct pthread *self = THREAD_SELF;
++
++ /* This is not a catchable exception, so don't provide any details about
++ the exception type. We do need to initialize the field though. */
++ THREAD_SETMEM (self, exc.exception_class, 0);
++ THREAD_SETMEM (self, exc.exception_cleanup, &unwind_cleanup);
++
++ _Unwind_ForcedUnwind (&self->exc, unwind_stop, ibuf);
++ /* NOTREACHED */
++
++ /* We better do not get here. */
++ abort ();
++}
++hidden_def (__pthread_unwind)
++
++
++void
++__cleanup_fct_attribute __attribute ((noreturn))
++__pthread_unwind_next (__pthread_unwind_buf_t *buf)
++{
++ struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
++
++ __pthread_unwind ((__pthread_unwind_buf_t *) ibuf->priv.data.prev);
++}
++hidden_def (__pthread_unwind_next)
+diff --git a/nptl_2_17/vars_2_17.c b/nptl_2_17/vars_2_17.c
+new file mode 100644
+index 00000000..295d7e33
+--- /dev/null
++++ b/nptl_2_17/vars_2_17.c
+@@ -0,0 +1,43 @@
++/* Copyright (C) 2004-2020 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
++ <https://www.gnu.org/licenses/>. */
++
++#include <pthreadP_2_17.h>
++#include <stdlib.h>
++#include <tls.h>
++#include <unistd.h>
++
++/* Default thread attributes for the case when the user does not
++ provide any. */
++struct pthread_attr __default_pthread_attr attribute_hidden;
++
++/* Mutex protecting __default_pthread_attr. */
++int __default_pthread_attr_lock = LLL_LOCK_INITIALIZER;
++
++/* Flag whether the machine is SMP or not. */
++int __is_smp attribute_hidden;
++
++#ifndef TLS_MULTIPLE_THREADS_IN_TCB
++/* Variable set to a nonzero value either if more than one thread runs or ran,
++ or if a single-threaded process is trying to cancel itself. See
++ nptl/descr.h for more context on the single-threaded process case. */
++int __pthread_multiple_threads attribute_hidden;
++#endif
++
++/* Table of the key information. */
++struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX]
++ __attribute__ ((nocommon));
++hidden_data_def (__pthread_keys)
+--
+2.23.0
+
diff --git a/delete-no-hard-link-to-avoid-all_language-package-to.patch b/delete-no-hard-link-to-avoid-all_language-package-to.patch new file mode 100644 index 0000000..1ccebcc --- /dev/null +++ b/delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -0,0 +1,26 @@ +From ba6891f0633d394a59d14f0a54090fa1b6260c16 Mon Sep 17 00:00:00 2001 +From: buque <wuxu.wu@hotmail.com> +Date: Wed, 15 Jul 2020 15:09:54 +0800 +Subject: [PATCH] delete --no-hard-link to avoid all_language package too + large. + +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/localedata/Makefile b/localedata/Makefile +index b8a3b67..c78d0fe 100644 +--- a/localedata/Makefile ++++ b/localedata/Makefile +@@ -444,7 +444,7 @@ $(INSTALL-SUPPORTED-LOCALE-ARCHIVE): install-locales-dir + $(build-one-locale) + + $(INSTALL-SUPPORTED-LOCALE-FILES): install-locales-dir +- @flags="-c --no-archive --no-hard-links"; \ ++ @flags="-c --no-archive"; \ + $(build-one-locale) + + tst-setlocale-ENV = LC_ALL=ja_JP.EUC-JP +-- +2.25.1 + diff --git a/elf-Allow-dlopen-of-filter-object-to-work-BZ-16272.patch b/elf-Allow-dlopen-of-filter-object-to-work-BZ-16272.patch new file mode 100644 index 0000000..cea541d --- /dev/null +++ b/elf-Allow-dlopen-of-filter-object-to-work-BZ-16272.patch @@ -0,0 +1,537 @@ +From eb447b7b4bd6177f876ba9420ad9e048c27bae91 Mon Sep 17 00:00:00 2001 +From: David Kilroy <David.Kilroy@arm.com> +Date: Wed, 12 Feb 2020 14:28:15 -0300 +Subject: [PATCH] elf: Allow dlopen of filter object to work [BZ #16272] + +There are two fixes that are needed to be able to dlopen filter +objects. First _dl_map_object_deps cannot assume that map will be at +the beginning of l_searchlist.r_list[], as filtees are inserted before +map. Secondly dl_open_worker needs to ensure that filtees get +relocated. + +In _dl_map_object_deps: + +* avoiding removing relocation dependencies of map by setting + l_reserved to 0 and otherwise processing the rest of the search + list. + +* ensure that map remains at the beginning of l_initfini - the list + of things that need initialisation (and destruction). Do this by + splitting the copy up. This may not be required, but matches the + initialization order without dlopen. + +Modify dl_open_worker to relocate the objects in new->l_inifini. +new->l_initfini is constructed in _dl_map_object_deps, and lists the +objects that need initialization and destruction. Originally the list +of objects in new->l_next are relocated. All of these objects should +also be included in new->l_initfini (both lists are populated with +dependencies in _dl_map_object_deps). We can't use new->l_prev to pick +up filtees, as during a recursive dlopen from an interposed malloc +call, l->prev can contain objects that are not ready for relocation. + +Add tests to verify that symbols resolve to the filtee implementation +when auxiliary and filter objects are used, both as a normal link and +when dlopen'd. + +Tested by running the testsuite on x86_64. +--- + elf/Makefile | 18 ++++++++++++++++-- + elf/dl-deps.c | 39 ++++++++++++++++++++++++++++---------- + elf/dl-open.c | 11 +++++++---- + elf/tst-auxobj-dlopen.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ + elf/tst-auxobj.c | 42 +++++++++++++++++++++++++++++++++++++++++ + elf/tst-filterobj-aux.c | 33 ++++++++++++++++++++++++++++++++ + elf/tst-filterobj-dlopen.c | 39 ++++++++++++++++++++++++++++++++++++++ + elf/tst-filterobj-filtee.c | 27 ++++++++++++++++++++++++++ + elf/tst-filterobj-filtee.h | 24 +++++++++++++++++++++++ + elf/tst-filterobj-flt.c | 27 ++++++++++++++++++++++++++ + elf/tst-filterobj.c | 36 +++++++++++++++++++++++++++++++++++ + 11 files changed, 327 insertions(+), 16 deletions(-) + create mode 100644 elf/tst-auxobj-dlopen.c + create mode 100644 elf/tst-auxobj.c + create mode 100644 elf/tst-filterobj-aux.c + create mode 100644 elf/tst-filterobj-dlopen.c + create mode 100644 elf/tst-filterobj-filtee.c + create mode 100644 elf/tst-filterobj-filtee.h + create mode 100644 elf/tst-filterobj-flt.c + create mode 100644 elf/tst-filterobj.c + +diff --git a/elf/Makefile b/elf/Makefile +index f440488..2053c9d 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -202,7 +202,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-tlsmodid \ + tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \ + tst-dlopenfail-2 \ +- tst-tls-ie tst-tls-ie-dlmopen ++ tst-tls-ie tst-tls-ie-dlmopen \ ++ tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -316,7 +317,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-dlopenfailmod3 tst-ldconfig-ld-mod \ + tst-tls-ie-mod0 tst-tls-ie-mod1 tst-tls-ie-mod2 \ + tst-tls-ie-mod3 tst-tls-ie-mod4 tst-tls-ie-mod5 \ +- tst-tls-ie-mod6 ++ tst-tls-ie-mod6 \ ++ tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. + modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\ +@@ -1723,3 +1725,15 @@ $(objpfx)tst-tls-ie-dlmopen.out: \ + $(objpfx)tst-tls-ie-mod4.so \ + $(objpfx)tst-tls-ie-mod5.so \ + $(objpfx)tst-tls-ie-mod6.so ++ ++LDFLAGS-tst-filterobj-flt.so = -Wl,--filter=$(objpfx)tst-filterobj-filtee.so ++$(objpfx)tst-filterobj: $(objpfx)tst-filterobj-flt.so ++$(objpfx)tst-filterobj-dlopen: $(libdl) ++$(objpfx)tst-filterobj.out: $(objpfx)tst-filterobj-filtee.so ++$(objpfx)tst-filterobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so ++ ++LDFLAGS-tst-filterobj-aux.so = -Wl,--auxiliary=$(objpfx)tst-filterobj-filtee.so ++$(objpfx)tst-auxobj: $(objpfx)tst-filterobj-aux.so ++$(objpfx)tst-auxobj-dlopen: $(libdl) ++$(objpfx)tst-auxobj.out: $(objpfx)tst-filterobj-filtee.so ++$(objpfx)tst-auxobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so +diff --git a/elf/dl-deps.c b/elf/dl-deps.c +index 5103a8a..0730ea9 100644 +--- a/elf/dl-deps.c ++++ b/elf/dl-deps.c +@@ -485,14 +485,18 @@ _dl_map_object_deps (struct link_map *map, + + map->l_searchlist.r_list = &l_initfini[nlist + 1]; + map->l_searchlist.r_nlist = nlist; ++ unsigned int map_index = UINT_MAX; + + for (nlist = 0, runp = known; runp; runp = runp->next) + { + if (__builtin_expect (trace_mode, 0) && runp->map->l_faked) + /* This can happen when we trace the loading. */ + --map->l_searchlist.r_nlist; +- else ++ else { ++ if (runp->map == map) ++ map_index = nlist; + map->l_searchlist.r_list[nlist++] = runp->map; ++ } + + /* Now clear all the mark bits we set in the objects on the search list + to avoid duplicates, so the next call starts fresh. */ +@@ -550,13 +554,14 @@ Filters not supported with LD_TRACE_PRELINKING")); + } + + /* Maybe we can remove some relocation dependencies now. */ +- assert (map->l_searchlist.r_list[0] == map); + struct link_map_reldeps *l_reldeps = NULL; + if (map->l_reldeps != NULL) + { +- for (i = 1; i < nlist; ++i) ++ for (i = 0; i < nlist; ++i) + map->l_searchlist.r_list[i]->l_reserved = 1; + ++ /* Avoid removing relocation dependencies of the main binary. */ ++ map->l_reserved = 0; + struct link_map **list = &map->l_reldeps->list[0]; + for (i = 0; i < map->l_reldeps->act; ++i) + if (list[i]->l_reserved) +@@ -581,16 +586,30 @@ Filters not supported with LD_TRACE_PRELINKING")); + } + } + +- for (i = 1; i < nlist; ++i) ++ for (i = 0; i < nlist; ++i) + map->l_searchlist.r_list[i]->l_reserved = 0; + } + +- /* Sort the initializer list to take dependencies into account. The binary +- itself will always be initialize last. */ +- memcpy (l_initfini, map->l_searchlist.r_list, +- nlist * sizeof (struct link_map *)); +- /* We can skip looking for the binary itself which is at the front of +- the search list. */ ++ /* Sort the initializer list to take dependencies into account. Always ++ initialize the binary itself last. */ ++ assert (map_index < nlist); ++ if (map_index > 0) ++ { ++ /* Copy the binary into position 0. */ ++ l_initfini[0] = map->l_searchlist.r_list[map_index]; ++ ++ /* Copy the filtees. */ ++ for (i = 0; i < map_index; ++i) ++ l_initfini[i+1] = map->l_searchlist.r_list[i]; ++ ++ /* Copy the remainder. */ ++ for (i = map_index + 1; i < nlist; ++i) ++ l_initfini[i] = map->l_searchlist.r_list[i]; ++ } ++ else ++ memcpy (l_initfini, map->l_searchlist.r_list, ++ nlist * sizeof (struct link_map *)); ++ + _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); + + /* Terminate the list of dependencies. */ +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 623c975..ecb2ba9 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -621,22 +621,25 @@ dl_open_worker (void *a) + allows IFUNC relocations to work and it also means copy + relocation of dependencies are if necessary overwritten. */ + unsigned int nmaps = 0; +- struct link_map *l = new; ++ unsigned int j = 0; ++ struct link_map *l = new->l_initfini[0]; + do + { + if (! l->l_real->l_relocated) + ++nmaps; +- l = l->l_next; ++ l = new->l_initfini[++j]; + } + while (l != NULL); ++ /* Stack allocation is limited by the number of loaded objects. */ + struct link_map *maps[nmaps]; + nmaps = 0; +- l = new; ++ j = 0; ++ l = new->l_initfini[0]; + do + { + if (! l->l_real->l_relocated) + maps[nmaps++] = l; +- l = l->l_next; ++ l = new->l_initfini[++j]; + } + while (l != NULL); + _dl_sort_maps (maps, nmaps, NULL, false); +diff --git a/elf/tst-auxobj-dlopen.c b/elf/tst-auxobj-dlopen.c +new file mode 100644 +index 0000000..cb54aba +--- /dev/null ++++ b/elf/tst-auxobj-dlopen.c +@@ -0,0 +1,47 @@ ++/* Test for BZ#16272, dlopen'ing an auxiliary filter object. ++ Ensure that symbols from the resolve correctly. ++ ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <support/check.h> ++#include <support/xdlfcn.h> ++ ++static int do_test (void) ++{ ++ void *lib = xdlopen ("tst-filterobj-aux.so", RTLD_LAZY); ++ char *(*fn)(void) = xdlsym (lib, "get_text"); ++ const char* text = fn (); ++ ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the filtee */ ++ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)"); ++ ++ fn = xdlsym (lib, "get_text2"); ++ text = fn (); ++ ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the auxiliary object */ ++ TEST_COMPARE_STRING (text, "Hello from auxiliary filter object (PASS)"); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/elf/tst-auxobj.c b/elf/tst-auxobj.c +new file mode 100644 +index 0000000..bdc7713 +--- /dev/null ++++ b/elf/tst-auxobj.c +@@ -0,0 +1,42 @@ ++/* Test that symbols from auxiliary filter objects are resolved to the ++ filtee. ++ ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <support/check.h> ++#include "tst-filterobj-filtee.h" ++ ++static int do_test (void) ++{ ++ const char* text = get_text (); ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the filtee */ ++ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)"); ++ ++ text = get_text2 (); ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the auxiliary object */ ++ TEST_COMPARE_STRING (text, "Hello from auxiliary filter object (PASS)"); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/elf/tst-filterobj-aux.c b/elf/tst-filterobj-aux.c +new file mode 100644 +index 0000000..0b732f2 +--- /dev/null ++++ b/elf/tst-filterobj-aux.c +@@ -0,0 +1,33 @@ ++/* Auxiliary filter object. ++ Contains symbols to be resolved in filtee, and one which doesn't. ++ ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include "tst-filterobj-filtee.h" ++ ++/* We never want to see the output of the auxiliary object. */ ++const char *get_text (void) ++{ ++ return "Hello from auxiliary filter object (FAIL)"; ++} ++ ++/* The filtee doesn't implement this symbol, so this should resolve. */ ++const char *get_text2 (void) ++{ ++ return "Hello from auxiliary filter object (PASS)"; ++} +diff --git a/elf/tst-filterobj-dlopen.c b/elf/tst-filterobj-dlopen.c +new file mode 100644 +index 0000000..c5b5072 +--- /dev/null ++++ b/elf/tst-filterobj-dlopen.c +@@ -0,0 +1,39 @@ ++/* Test for BZ#16272, dlopen'ing a filter object. ++ Ensure that symbols from the filter object resolve to the filtee. ++ ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <support/check.h> ++#include <support/xdlfcn.h> ++ ++static int do_test (void) ++{ ++ void *lib = xdlopen ("tst-filterobj-flt.so", RTLD_LAZY); ++ char *(*fn)(void) = xdlsym (lib, "get_text"); ++ const char* text = fn (); ++ ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the filtee */ ++ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)"); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/elf/tst-filterobj-filtee.c b/elf/tst-filterobj-filtee.c +new file mode 100644 +index 0000000..8fa557c +--- /dev/null ++++ b/elf/tst-filterobj-filtee.c +@@ -0,0 +1,27 @@ ++/* Filtee for BZ#16272 test. ++ Contains desired symbol implementations. ++ ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include "tst-filterobj-filtee.h" ++ ++/* This is the real implementation that wants to be called */ ++const char *get_text (void) ++{ ++ return "Hello from filtee (PASS)"; ++} +diff --git a/elf/tst-filterobj-filtee.h b/elf/tst-filterobj-filtee.h +new file mode 100644 +index 0000000..46aee28 +--- /dev/null ++++ b/elf/tst-filterobj-filtee.h +@@ -0,0 +1,24 @@ ++/* Filtee header for BZ#16272 test. ++ Contains prototypes for symbols implemented in the filtee. ++ ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++const char *get_text (void); ++ ++/* For testing auxiliary filter object. */ ++const char *get_text2 (void); +diff --git a/elf/tst-filterobj-flt.c b/elf/tst-filterobj-flt.c +new file mode 100644 +index 0000000..5062654 +--- /dev/null ++++ b/elf/tst-filterobj-flt.c +@@ -0,0 +1,27 @@ ++/* Filter object for BZ#16272 test. ++ Contains symbols to be resolved in filtee. ++ ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include "tst-filterobj-filtee.h" ++ ++/* We never want to see the output of the filter object */ ++const char *get_text (void) ++{ ++ return "Hello from filter object (FAIL)"; ++} +diff --git a/elf/tst-filterobj.c b/elf/tst-filterobj.c +new file mode 100644 +index 0000000..96bfae0 +--- /dev/null ++++ b/elf/tst-filterobj.c +@@ -0,0 +1,36 @@ ++/* Test that symbols from filter objects are resolved to the filtee. ++ ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <support/check.h> ++#include "tst-filterobj-filtee.h" ++ ++static int do_test (void) ++{ ++ const char* text = get_text (); ++ ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the filtee */ ++ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)"); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +-- +1.8.3.1 + diff --git a/glibc-1070416.patch b/glibc-1070416.patch new file mode 100644 index 0000000..0975e0f --- /dev/null +++ b/glibc-1070416.patch @@ -0,0 +1,38 @@ +Short description: Add syslog.target dependency. +Author(s): Fedora glibc team <glibc@lists.fedoraproject.org> +Origin: PATCH +Bug-Fedora: #1070416 +Upstream status: not-needed + +Fedora-specific changes to the nscd.service file. +See also: glibc-nscd-sysconfig.patch. + +--- a/nscd/nscd.service ++++ b/nscd/nscd.service +@@ -2,6 +2,7 @@ + + [Unit] + Description=Name Service Cache Daemon ++After=syslog.target + + [Service] + Type=forking +@@ -17,3 +18,4 @@ + + [Install] + WantedBy=multi-user.target ++Also=nscd.socket +diff --git a/nscd/nscd.socket b/nscd/nscd.socket +new file mode 100644 +index 0000000..7e512d5 +--- /dev/null ++++ b/nscd/nscd.socket +@@ -0,0 +1,8 @@ ++[Unit] ++Description=Name Service Cache Daemon Socket ++ ++[Socket] ++ListenDatagram=/var/run/nscd/socket ++ ++[Install] ++WantedBy=sockets.target diff --git a/glibc-bench-compare b/glibc-bench-compare new file mode 100644 index 0000000..84e3aba --- /dev/null +++ b/glibc-bench-compare @@ -0,0 +1,153 @@ +#!/usr/bin/bash +# This script can be invoked as follows: +# +# glibc-bench-compare [options] <BUILD> [BUILD] +# +# Options may be one of the following: +# +# -t The BUILD arguments are task ids and not a version-release string +# -a ARCH Do comparison for ARCH architecture +# +# If any of the above options are given, both BUILD arguments must be given. +# Otherwise, if only one BUILD is specified, then it is compared against the +# installed glibc. + +# Silence the pushd/popd messages +pushd() { + command pushd "$@" > /dev/null 2>&1 +} + +popd() { + command popd "$@" > /dev/null 2>&1 +} + +# Clean up any downloaded files before we exit +trap "rm -rf /tmp/glibc-bench-compare.$BASHPID.*" EXIT + +task=0 +arch=$(uname -i) +options=0 +path=0 +installed= + +# Look for any commandline options +while getopts ":tpa:" opt; do + case $opt in + p) + path=1 + ;; + t) + task=1 + options=1 + echo "Not implemented." + exit 1 + ;; + a) + arch=$OPTARG + options=1 + ;; + *) + ;; + esac +done + +# Done, now shift all option arguments out. +shift $((OPTIND-1)) + +if [ $# -gt 2 ] || [ $# -eq 0 ] || [ $# -lt 2 -a $options -eq 1 ]; then + echo "Usage: $0 [OPTIONS] <old> [new]" + echo + echo "OPTIONS:" + echo -e "\t-t\tCompare two brew tasks" + echo -e "\t-a ARCH\tGet rpms for the ARCH architecture" + echo -e "\t-p\tCompare built rpms in two paths." + echo -e "\t\tThis minimally needs glibc, glibc-common and glibc-benchtests" + exit 1 +fi + +if [ -z $2 ]; then + new="$1" + old=$(rpm --queryformat "%{VERSION}-%{RELEASE}\n" -q glibc | head -1) + installed=$old +else + new="$2" + old="$1" +fi + +decompress_rpms() { + # We were given a path to the rpms. Figure out the version-release and + # decompress the rpms. + if [ -n $1 ]; then + vr=$(rpm --queryformat="%{VERSION}-%{RELEASE}" -qp $1/glibc-2*.rpm | head -1) + mkdir $vr && pushd $vr + fi + + for r in $1*.rpm; do + ( rpm2cpio $r | cpio -di ) > /dev/null + done + + if [ -n $1 ]; then + popd + echo $vr + fi +} + +# Get rpms for a build and decompress them +get_build() { + echo "Processing build $1" + mkdir $1 && pushd $1 + brew buildinfo "glibc-$1" | + sed -n -e "s|/mnt/koji\(.\+$arch.\+\)|http://kojipkgs.fedoraproject.org\1|p" | + while read url; do + echo "Downloading $url" + wget -q $url + done + decompress_rpms + + echo "Removing rpms" + rm -f $1/*.rpm + + popd +} + +# Run benchmarks for a build +run_bench() { + if [ -z $1 ]; then + make DETAILED=1 ver=$installed prefix= -f /usr/libexec/glibc-benchtests/bench.mk bench + else + make DETAILED=1 ver=$1 prefix=$PWD -f $1/usr/libexec/glibc-benchtests/bench.mk bench + fi +} + +# Get absolute paths if needed, since we will change into the working directory +# next. +if [ $path -eq 1 ]; then + old_path=$(realpath $old)/ + new_path=$(realpath $new)/ +fi + +tmpdir=$(mktemp -p /tmp -d glibc-bench-compare.$$.XXXX) +pushd $tmpdir + +# Get both builds. +if [ $path -eq 0 ]; then + if [ -z $installed ]; then + get_build $old + fi + get_build $new +else + old=$(decompress_rpms $old_path) + new=$(decompress_rpms $new_path) +fi + +# make bench for each of those. +if [ -z $installed ]; then + run_bench $old +else + run_bench +fi +run_bench $new + +# Now run the comparison script. +$old/usr/libexec/glibc-benchtests/compare_bench.py $old/usr/libexec/glibc-benchtests/benchout.schema.json \ + bench.$old.out bench.$new.out diff --git a/glibc-c-utf8-locale.patch b/glibc-c-utf8-locale.patch new file mode 100644 index 0000000..a4cf357 --- /dev/null +++ b/glibc-c-utf8-locale.patch @@ -0,0 +1,286 @@ +Short description: Add C.UTF-8 support. +Author(s): Fedora glibc team <glibc@lists.fedoraproject.org> +Origin: PATCH +Upstream status: not-submitted + +This patch needs to upstream as part of Carlos O'Donell +<carlos@redhat.com>'s work on enabling upstream C.UTF-8 support. This +work is currently blocked on cleaning up the test results to prove that +full code-point sorting is working as intended. + +Note that this patch does not provide full code-point sorting as +expected. + +This patch needs to upstream as soon as possible since it would be nice +to have this in F29 and fixed. + +From 2eda7b462b415105f5a05c1323372d4e39d46439 Mon Sep 17 00:00:00 2001 +From: Mike FABIAN <mfabian@redhat.com> +Date: Mon, 10 Aug 2015 15:58:12 +0200 +Subject: [PATCH] Add a C.UTF-8 locale + +--- + localedata/SUPPORTED | 1 + + localedata/locales/C | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 239 insertions(+) + create mode 100644 localedata/locales/C + +diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED +index 8ca023e..2a78391 100644 +--- a/localedata/SUPPORTED ++++ b/localedata/SUPPORTED +@@ -1,6 +1,7 @@ + # This file names the currently supported and somewhat tested locales. + # If you have any additions please file a glibc bug report. + SUPPORTED-LOCALES=\ ++C.UTF-8/UTF-8 \ + aa_DJ.UTF-8/UTF-8 \ + aa_DJ/ISO-8859-1 \ + aa_ER/UTF-8 \ +diff --git a/localedata/locales/C b/localedata/locales/C +new file mode 100644 +index 0000000..fdf460e +--- /dev/null ++++ b/localedata/locales/C +@@ -0,0 +1,238 @@ ++escape_char / ++comment_char % ++% Locale for C locale in UTF-8 ++ ++LC_IDENTIFICATION ++title "C locale" ++source "" ++address "" ++contact "" ++email "mfabian@redhat.com" ++tel "" ++fax "" ++language "C" ++territory "" ++revision "1.0" ++date "2015-08-10" ++% ++category "i18n:2012";LC_IDENTIFICATION ++category "i18n:2012";LC_CTYPE ++category "i18n:2012";LC_COLLATE ++category "i18n:2012";LC_TIME ++category "i18n:2012";LC_NUMERIC ++category "i18n:2012";LC_MONETARY ++category "i18n:2012";LC_MESSAGES ++category "i18n:2012";LC_PAPER ++category "i18n:2012";LC_NAME ++category "i18n:2012";LC_ADDRESS ++category "i18n:2012";LC_TELEPHONE ++category "i18n:2012";LC_MEASUREMENT ++END LC_IDENTIFICATION ++ ++LC_CTYPE ++copy "i18n" ++ ++translit_start ++include "translit_combining";"" ++translit_end ++ ++END LC_CTYPE ++ ++LC_COLLATE ++order_start forward ++<U0000> ++.. ++<UFFFF> ++<U00010000> ++.. ++<U0001FFFF> ++<U00020000> ++.. ++<U0002FFFF> ++<U000E0000> ++.. ++<U000EFFFF> ++<U000F0000> ++.. ++<U000FFFFF> ++<U00100000> ++.. ++<U0010FFFF> ++UNDEFINED ++order_end ++END LC_COLLATE ++ ++LC_MONETARY ++% This is the 14652 i18n fdcc-set definition for ++% the LC_MONETARY category ++% (except for the int_curr_symbol and currency_symbol, they are empty in ++% the 14652 i18n fdcc-set definition and also empty in ++% glibc/locale/C-monetary.c. But localedef complains in that case). ++% ++% Using "USD" for int_curr_symbol. But maybe "XXX" would be better? ++% XXX is "No currency" (https://en.wikipedia.org/wiki/ISO_4217) ++int_curr_symbol "<U0055><U0053><U0044><U0020>" ++% Using "$" for currency_symbol. But maybe <U00A4> would be better? ++% U+00A4 is the "generic currency symbol" ++% (https://en.wikipedia.org/wiki/Currency_sign_%28typography%29) ++currency_symbol "<U0024>" ++mon_decimal_point "<U002E>" ++mon_thousands_sep "" ++mon_grouping -1 ++positive_sign "" ++negative_sign "<U002D>" ++int_frac_digits -1 ++frac_digits -1 ++p_cs_precedes -1 ++int_p_sep_by_space -1 ++p_sep_by_space -1 ++n_cs_precedes -1 ++int_n_sep_by_space -1 ++n_sep_by_space -1 ++p_sign_posn -1 ++n_sign_posn -1 ++% ++END LC_MONETARY ++ ++LC_NUMERIC ++% This is the POSIX Locale definition for ++% the LC_NUMERIC category. ++% ++decimal_point "<U002E>" ++thousands_sep "" ++grouping -1 ++END LC_NUMERIC ++ ++LC_TIME ++% This is the POSIX Locale definition for ++% the LC_TIME category. ++% ++% Abbreviated weekday names (%a) ++abday "<U0053><U0075><U006E>";"<U004D><U006F><U006E>";/ ++ "<U0054><U0075><U0065>";"<U0057><U0065><U0064>";/ ++ "<U0054><U0068><U0075>";"<U0046><U0072><U0069>";/ ++ "<U0053><U0061><U0074>" ++ ++% Full weekday names (%A) ++day "<U0053><U0075><U006E><U0064><U0061><U0079>";/ ++ "<U004D><U006F><U006E><U0064><U0061><U0079>";/ ++ "<U0054><U0075><U0065><U0073><U0064><U0061><U0079>";/ ++ "<U0057><U0065><U0064><U006E><U0065><U0073><U0064><U0061><U0079>";/ ++ "<U0054><U0068><U0075><U0072><U0073><U0064><U0061><U0079>";/ ++ "<U0046><U0072><U0069><U0064><U0061><U0079>";/ ++ "<U0053><U0061><U0074><U0075><U0072><U0064><U0061><U0079>" ++ ++% Abbreviated month names (%b) ++abmon "<U004A><U0061><U006E>";"<U0046><U0065><U0062>";/ ++ "<U004D><U0061><U0072>";"<U0041><U0070><U0072>";/ ++ "<U004D><U0061><U0079>";"<U004A><U0075><U006E>";/ ++ "<U004A><U0075><U006C>";"<U0041><U0075><U0067>";/ ++ "<U0053><U0065><U0070>";"<U004F><U0063><U0074>";/ ++ "<U004E><U006F><U0076>";"<U0044><U0065><U0063>" ++ ++% Full month names (%B) ++mon "<U004A><U0061><U006E><U0075><U0061><U0072><U0079>";/ ++ "<U0046><U0065><U0062><U0072><U0075><U0061><U0072><U0079>";/ ++ "<U004D><U0061><U0072><U0063><U0068>";/ ++ "<U0041><U0070><U0072><U0069><U006C>";/ ++ "<U004D><U0061><U0079>";/ ++ "<U004A><U0075><U006E><U0065>";/ ++ "<U004A><U0075><U006C><U0079>";/ ++ "<U0041><U0075><U0067><U0075><U0073><U0074>";/ ++ "<U0053><U0065><U0070><U0074><U0065><U006D><U0062><U0065><U0072>";/ ++ "<U004F><U0063><U0074><U006F><U0062><U0065><U0072>";/ ++ "<U004E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/ ++ "<U0044><U0065><U0063><U0065><U006D><U0062><U0065><U0072>" ++ ++% Week description, consists of three fields: ++% 1. Number of days in a week. ++% 2. Gregorian date that is a first weekday (19971130 for Sunday, 19971201 for Monday). ++% 3. The weekday number to be contained in the first week of the year. ++% ++% ISO 8601 conforming applications should use the values 7, 19971201 (a ++% Monday), and 4 (Thursday), respectively. ++week 7;19971201;4 ++first_weekday 1 ++first_workday 1 ++ ++% Appropriate date and time representation (%c) ++% "%a %b %e %H:%M:%S %Y" ++d_t_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0059>" ++ ++% Appropriate date representation (%x) ++% "%m/%d/%y" ++d_fmt "<U0025><U006D><U002F><U0025><U0064><U002F><U0025><U0079>" ++ ++% Appropriate time representation (%X) ++% "%H:%M:%S" ++t_fmt "<U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053>" ++ ++% Appropriate AM/PM time representation (%r) ++% "%I:%M:%S %p" ++t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0070>" ++ ++% Equivalent of AM/PM (%p) "AM"/"PM" ++% ++am_pm "<U0041><U004D>";"<U0050><U004D>" ++ ++% Appropriate date representation (date(1)) "%a %b %e %H:%M:%S %Z %Y" ++date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U0020><U0025><U0059>" ++END LC_TIME ++ ++LC_MESSAGES ++% This is the POSIX Locale definition for ++% the LC_NUMERIC category. ++% ++yesexpr "<U005E><U005B><U0079><U0059><U005D>" ++noexpr "<U005E><U005B><U006E><U004E><U005D>" ++yesstr "<U0059><U0065><U0073>" ++nostr "<U004E><U006F>" ++END LC_MESSAGES ++ ++LC_PAPER ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_PAPER category. ++% (A4 paper, this is also used in the built in C/POSIX ++% locale in glibc/locale/C-paper.c) ++height 297 ++width 210 ++END LC_PAPER ++ ++LC_NAME ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_NAME category. ++% "%p%t%g%t%m%t%f" ++% (also used in the built in C/POSIX locale in glibc/locale/C-name.c) ++name_fmt "<U0025><U0070><U0025><U0074><U0025><U0067><U0025><U0074>/ ++<U0025><U006D><U0025><U0074><U0025><U0066>" ++END LC_NAME ++ ++LC_ADDRESS ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_ADDRESS category. ++% "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N" ++% (also used in the built in C/POSIX locale in glibc/locale/C-address.c) ++postal_fmt "<U0025><U0061><U0025><U004E><U0025><U0066><U0025><U004E>/ ++<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0073>/ ++<U0020><U0025><U0068><U0020><U0025><U0065><U0020><U0025><U0072><U0025>/ ++<U004E><U0025><U0043><U002D><U0025><U007A><U0020><U0025><U0054><U0025>/ ++<U004E><U0025><U0063><U0025><U004E>" ++END LC_ADDRESS ++ ++LC_TELEPHONE ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_TELEPHONE category. ++% "+%c %a %l" ++tel_int_fmt "<U002B><U0025><U0063><U0020><U0025><U0061><U0020><U0025>/ ++<U006C>" ++% (also used in the built in C/POSIX locale in glibc/locale/C-telephone.c) ++END LC_TELEPHONE ++ ++LC_MEASUREMENT ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_MEASUREMENT category. ++% (same as in the built in C/POSIX locale in glibc/locale/C-measurement.c) ++%metric ++measurement 1 ++END LC_MEASUREMENT ++ +-- +2.4.3 + diff --git a/glibc.spec b/glibc.spec new file mode 100644 index 0000000..83d20b0 --- /dev/null +++ b/glibc.spec @@ -0,0 +1,1329 @@ +%global __filter_GLIBC_PRIVATE 1 + +%define rpm_ver_major %(eval "echo `rpm -q rpm |cut -d '-' -f2 |cut -d. -f1`") +%define rpm_ver_minor %(eval "echo `rpm -q rpm |cut -d '-' -f2 |cut -d. -f2`") +%define rpm_version_ge_412 %(eval "if [ %{rpm_ver_major} -gt 4 -o %{rpm_ver_major} -eq 4 -a %{rpm_ver_minor} -ge 12 ]; then echo 1; else echo 0; fi") +%define gcc_version %(eval "echo `gcc --version |head -1 |awk '{print $3}' |awk -F '.' '{print $1}'`") +############################################################################## +# We support the following options: +# --with/--without, +# * testsuite +# - Running the testsuite. It must run for production builds. +# - Default: Always run the testsuite. +# * benchtests +# - Running and building benchmark subpackage. +# - Default: Always build the benchtests. +# * bootstrap +# - Bootstrapping the package. +# - Default: Not bootstrapping. +# * werror +# - Build with -Werror +# - Default: Enable using -Werror +# * docs +# - Build with documentation and the required dependencies. +# - Default: Always build documentation. +# * valgrind +# - Run smoke tests with valgrind to verify dynamic loader. +# - Default: Always run valgrind tests if there is architecture support. +############################################################################## +%bcond_without testsuite +%bcond_without benchtests +%bcond_with bootstrap +%bcond_without werror +%bcond_without docs +%bcond_with libpthreadcond + +%ifarch %{valgrind_arches} +%bcond_without valgrind +%else +%bcond_with valgrind +%endif + +%if %{with bootstrap} +%undefine with_benchtests +%undefine with_werror +%undefine with_docs +%undefine with_valgrind +%endif + +%define enablekernel 3.2 +%define target %{_target_cpu}-%{_vendor}-linux +%ifarch %{arm} +%define target %{_target_cpu}-%{_vendor}-linuxeabi +%endif +%define x86_arches %{ix86} x86_64 +%define all_license LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ and GPLv2+ with exceptions and BSD and Inner-Net and ISC and Public Domain and GFDL +%define GCC gcc +%define GXX g++ +############################################################################## +# glibc - The GNU C Library (glibc) core package. +############################################################################## +Name: glibc +Version: 2.31 +Release: 10 +Summary: The GNU libc libraries +License: %{all_license} +URL: http://www.gnu.org/software/glibc/ + +Source0: https://ftp.gnu.org/gnu/glibc/%{name}-%{version}.tar.xz +Source1: nscd.conf +Source2: nsswitch.conf +Source3: bench.mk +Source4: glibc-bench-compare +Source5: LanguageList +Source6: LicenseList + +Patch0: glibc-1070416.patch +Patch1: glibc-c-utf8-locale.patch + +Patch6000: Fix-use-after-free-in-glob-when-expanding-user-bug-2.patch +Patch6001: Avoid-ldbl-96-stack-corruption-from-range-reduction-.patch +Patch6002: Reset-converter-state-after-second-wchar_t-output-Bu.patch +Patch6003: Fix-avx2-strncmp-offset-compare-condition-check-BZ-2.patch +Patch6004: nptl-wait-for-pending-setxid-request-also-in-detache.patch +Patch6005: x86-64-Use-RDX_LP-on-__x86_shared_non_temporal_thres.patch +Patch6006: x86_64-Use-xmmN-with-vpxor-to-clear-a-vector-registe.patch +Patch6007: nptl-Don-t-madvise-user-provided-stack.patch +Patch6008: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch +Patch6009: Fix-strtod-multiple-precision-division-bug-bug-26137.patch +Patch6010: Fix-double-free-in-__printf_fp_l-bug-26214.patch +Patch6011: Fix-memory-leak-in-__printf_fp_l-bug-26215.patch +Patch6012: Fix-CVE-2020-6096-001.patch +Patch6013: Fix-CVE-2020-6096-002.patch +Patch6014: Disable-warnings-due-to-deprecated-libselinux-symbol.patch +Patch6015: rtld-Avoid-using-up-static-TLS-surplus-for-optimizat.patch +Patch6016: Fix-CVE-2020-27618-iconv-Accept-redundant-shift-sequences.patch +Patch6017: elf-Allow-dlopen-of-filter-object-to-work-BZ-16272.patch +Patch6018: Handle-SEM_STAT_ANY-the-same-way-as-SEM_STAT-so-that.patch + +Patch9000: delete-no-hard-link-to-avoid-all_language-package-to.patch +Patch9001: build-extra-libpthreadcond-so.patch +Patch9002: remove-country-selection-from-tzselect.patch + +Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) + +BuildRequires: audit-libs-devel >= 1.1.3, sed >= 3.95, libcap-devel, gettext +BuildRequires: procps-ng, util-linux, gawk, systemtap-sdt-devel, systemd, python3 +BuildRequires: make >= 4.0, bison >= 2.7, binutils >= 2.30-17, gcc >= 7.2.1-6 +BuildRequires: m4 gcc_secure gdb + +%if %{without bootstrap} +BuildRequires: gd-devel libpng-devel zlib-devel +%endif + +%if %{with docs} +BuildRequires: texinfo >= 5.0 +%endif + +%if %{without bootstrap} +BuildRequires: libselinux-devel >= 1.33.4-3 +%endif + +%if %{with valgrind} +BuildRequires: valgrind +%endif + +%if 0%{?_enable_debug_packages} +BuildRequires: elfutils >= 0.72 rpm >= 4.2-0.56 +%endif + +%if %{without bootstrap} +%if %{with testsuite} +BuildRequires: gcc-c++ libstdc++-static glibc-devel libidn2 +%endif +%endif + +Requires: glibc-common = %{version}-%{release} +Requires: glibc-langpack = %{version}-%{release} +Requires: basesystem + +%description +The GNU C Library project provides the core libraries for the GNU system and +GNU/Linux systems, as well as many other systems that use Linux as the kernel. +These libraries provide critical APIs including ISO C11, POSIX.1-2008, BSD, +OS-specific APIs and more. These APIs include such foundational facilities as +open, read, write, malloc, printf, getaddrinfo, dlopen, pthread_create, crypt, + login, exit and more. + +############################################################################## +# glibc "common" sub-package +############################################################################## +%package common +Summary: Common binaries and locale data for glibc +Provides: glibc-langpack = %{version}-%{release} + +Provides: glibc-langpack-en = %{version}-%{release} +Provides: glibc-langpack-en%{?_isa} = %{version}-%{release} +Provides: glibc-langpack-zh = %{version}-%{release} +Provides: glibc-langpack-zh%{?_isa} = %{version}-%{release} + +Requires: %{name} = %{version}-%{release} +Requires: tzdata >= 2003a + +%description common +The glibc-common package includes common binaries for the GNU libc +libraries and national language (locale) support. Besides, zh_CN and +en_US are included. + +%transfiletriggerin common -P 2000000 -- /lib /usr/lib /lib64 /usr/lib64 +/sbin/ldconfig +%end + +%transfiletriggerpostun common -P 2000000 -- /lib /usr/lib /lib64 /usr/lib64 +/sbin/ldconfig +%end + +%undefine __brp_ldconfig + +############################################################################## +# glibc "all-langpacks" sub-package +############################################################################## +%package all-langpacks +Summary: All language packs for %{name}. +Requires: %{name} = %{version}-%{release} +Requires: %{name}-common = %{version}-%{release} +Provides: %{name}-langpack = %{version}-%{release} +Obsoletes: %{name}-minimal-langpack = 2.28 + +%{lua: +-- List the Symbol provided by all-langpacks +lang_provides = {} +for line in io.lines(rpm.expand("%{SOURCE5}")) do + print(rpm.expand([[ +Provides:]]..line..[[ = %{version}-%{release} +Obsoletes:]]..line..[[ = 2.28 +]])) +end +} + +%description all-langpacks +The glibc-all-langpacks provides all the glibc-langpacks. Every entry +includes the basic information required to support the corresponding +language in your applications. + +############################################################################## +# glibc "locale-source" sub-package +############################################################################## +%package locale-source +Summary: The sources package of locales +Requires: %{name} = %{version}-%{release} +Requires: %{name}-common = %{version}-%{release} + +%description locale-source +The locale-source package contains all language packs which are built custom +locales + +############################################################################## +# glibc "devel" sub-package +############################################################################## +%package devel +Summary: The devel for %{name} +Requires: %{name} = %{version}-%{release} +Requires: libgcc%{_isa} +Requires(pre): info +Requires(pre): kernel-headers +Requires(pre): coreutils +Requires: kernel-headers >= 3.2 +%if 0%{rpm_version_ge_412} +Requires: libxcrypt-devel%{_isa} >= 4.0.0 +Requires: libxcrypt-static%{?_isa} >= 4.0.0 +%endif +BuildRequires: kernel-headers >= 3.2 + +Provides: %{name}-static = %{version}-%{release} +Provides: %{name}-static%{_isa} = %{version}-%{release} +Provides: %{name}-headers = %{version}-%{release} +Provides: %{name}-headers(%{_target_cpu}) +Provides: %{name}-headers%{_isa} = %{version}-%{release} + +Obsoletes: %{name}-static = 2.28 +Obsoletes: %{name}-headers = 2.28 + +%description devel +The glibc-devel package contains the object files necessary for developing +programs which use the standard C libraries. Besides, it contains the +headers. Thus, it is necessory to install glibc-devel if you ned develop programs. + +############################################################################## +# glibc "nscd" sub-package +############################################################################## +%package -n nscd +Summary: Name caching service daemon. +Requires: %{name} = %{version}-%{release} +%if %{without bootstrap} +Requires: libselinux >= 1.17.10-1 +%endif +Requires: audit-libs >= 1.1.3 +Requires(pre): shadow-utils, coreutils +Requires: systemd +Requires(postun): shadow-utils + +%description -n nscd +The nscd package is able to daemon caches name service lookups and improve +the performance with LDAP. + +############################################################################## +# nss modules sub-package +############################################################################## +%package -n nss_modules +Summary: Name Service Switch module using hash-indexed files and Hesiod +Requires: %{name}%{_isa} = %{version}-%{release} +Provides: nss_db = %{version}-%{release} +Provides: nss_db%{_isa} = %{version}-%{release} +Provides: nss_hesiod = %{version}-%{release} +Provides: nss_hesiod%{_isa} = %{version}-%{release} +Obsoletes: nss_db = 2.28, nss_hesiod = 2.28 + +%description -n nss_modules +This package contains nss_db and nss_hesiod. The former uses hash-indexed files +to speed up user, group, service, host name, and other NSS-based lookups.The +latter uses the Domain Name System (DNS) as a source for user, group, and service +information to follow the Hesiod convention of Project Athena. + +############################################################################## +# nss-devel sub-package +############################################################################## +%package nss-devel +Summary: The devel for directly linking NSS service modules +Requires: nss_db%{_isa} = %{version}-%{release} +Requires: nss_hesiod%{_isa} = %{version}-%{release} + +%description nss-devel +This package contains the necessary devel files to compile applications and +libraries which directly link against NSS modules supplied by glibc. This +package is rarely used, and in most cases use the glibc-devel package instead. + +############################################################################## +# libnsl subpackage +############################################################################## +%package -n libnsl +Summary: Public client interface for NIS(YP) and NIS+ +Requires: %{name}%{_isa} = %{version}-%{release} + +%description -n libnsl +The libnsl package contains the public client interface for NIS(YP) and NIS+. +It replaces the NIS library that used to be in glibc. + +############################################################################## +# glibc benchtests sub-package +############################################################################## +%if %{with benchtests} + +%package benchtests +Summary: Build benchmarking binaries and scripts for %{name} + +%description benchtests +This package provides built benchmark binaries and scripts which will be used +to run microbenchmark tests on the system. +%endif + +############################################################################## +# glibc debugutils sub-package +############################################################################## +%package debugutils +Summary: debug files for %{name} +Requires: %{name} = %{version}-%{release} +Provides: %{name}-utils = %{version}-%{release} +Provides: %{name}-utils%{_isa} = %{version}-%{release} + +Obsoletes: %{name}-utils = 2.28 + +%description debugutils +This package provides memusage, a memory usage profiler, mtrace, a memory leak +tracer and xtrace, a function call tracer, all of which is not necessory for you. + +############################################################################## +# glibc debuginfo sub-package +############################################################################## +%if 0%{?_enable_debug_packages} +%define debug_package %{nil} +%define __debug_install_post %{nil} +%global __debug_package 1 + +%undefine _debugsource_packages +%undefine _debuginfo_subpackages +%undefine _unique_debug_names +%undefine _unique_debug_srcs + +%package debuginfo +Summary: Debug information for %{name} +AutoReqProv: no + +%description debuginfo +This package provides debug information for package %{name}. +Debug information is useful when developing applications that use this +package or when debugging this package. + +%package debugsource +Summary: Debug source for %{name} +AutoReqProv: no + +%description debugsource +This package provides debug sources for package %{name}. +Debug sources are useful when developing applications that use this +package or when debugging this package. + +%endif # 0%{?_enable_debug_packages} + +############################################################################## +# glibc help sub-package +############################################################################## +%package help +Summary: The doc and man for %{name} +Buildarch: noarch +Requires: man info + +%description help +This package provides al doc and man files of %{name} + +############################################################################## +# Prepare for the build. +############################################################################## +%prep +%autosetup -n %{name}-%{version} -p1 + +chmod +x benchtests/scripts/*.py scripts/pylint + +find . -type f -size 0 -o -name "*.orig" -exec rm -f {} \; + +touch `find . -name configure` + +touch locale/programs/*-kw.h + +############################################################################## +# Build glibc... +############################################################################## +%build + +BuildFlags="-O2 -g" +BuildFlags="$BuildFlags -DNDEBUG" +reference=" \ + "-Wp,-D_GLIBCXX_ASSERTIONS" \ + "-fasynchronous-unwind-tables" \ + "-fstack-clash-protection" \ + "-funwind-tables" \ + "-m31" \ + "-m32" \ + "-m64" \ + "-march=haswell" \ + "-march=i686" \ + "-march=x86-64" \ + "-march=z13" \ + "-march=z14" \ + "-march=zEC12" \ + "-mfpmath=sse" \ + "-msse2" \ + "-mstackrealign" \ + "-mtune=generic" \ + "-mtune=z13" \ + "-mtune=z14" \ + "-mtune=zEC12" \ + "-specs=/usr/lib/rpm/%{_vendor}/%{_vendor}-annobin-cc1" " + +for flag in $RPM_OPT_FLAGS $RPM_LD_FLAGS ; do + if echo "$reference" | grep -q -F " $flag " ; then + BuildFlags="$BuildFlags $flag" + fi +done + +%define glibc_make_flags_as ASFLAGS="-g -Wa,--generate-missing-build-notes=yes" +%define glibc_make_flags %{glibc_make_flags_as} + +EnableKernel="--enable-kernel=%{enablekernel}" + +builddir=build-%{target} +rm -rf $builddir +mkdir $builddir +pushd $builddir +../configure CC="%GCC" CXX="%GXX" CFLAGS="$BuildFlags" \ + --prefix=%{_prefix} \ + --with-headers=%{_prefix}/include $EnableKernel \ + --with-nonshared-cflags=-Wp,-D_FORTIFY_SOURCE=2 \ + --enable-bind-now \ + --build=%{target} \ + --enable-stack-protector=strong \ +%ifarch %{x86_arches} +%if 0%{?gcc_version} >= 8 + --enable-static-pie \ + --enable-cet \ +%endif +%endif + --enable-tunables \ + --enable-systemtap \ +%ifarch %{ix86} + --disable-multi-arch \ +%endif +%if %{without werror} + --disable-werror \ +%endif + --disable-profile \ +%if %{with bootstrap} + --without-selinux \ +%endif +%if 0%{rpm_version_ge_412} + --disable-crypt \ +%endif + || + { cat config.log; false; } + +make %{?_smp_mflags} -O -r %{glibc_make_flags} +popd + +############################################################################## +# Build libpthreadcond +############################################################################## +%if %{with libpthreadcond} + cd nptl_2_17 + sh build_libpthreadcondso.sh %{_target_cpu} $builddir + cd .. +%endif + +############################################################################## +# Install glibc... +############################################################################## +%install +chmod 644 sysdeps/gnu/errlist.c + +%ifarch riscv64 +for d in $RPM_BUILD_ROOT%{_libdir} $RPM_BUILD_ROOT/%{_lib}; do + mkdir -p $d + (cd $d && ln -sf . lp64d) +done +%endif + +make -j1 install_root=$RPM_BUILD_ROOT install -C build-%{target} + +%if %{with libpthreadcond} + cp build-%{target}/nptl/libpthreadcond.so $RPM_BUILD_ROOT%{_libdir} +%endif + +pushd build-%{target} + +# notice: we can't use parallel compilation because the localedata will use "localedef" command +# to create locales such as LC_CTYPE, LC_TIME etc, and this command will create a file, +# or create a hard link if there already has a output file who's input is the same, +# so when we use parallel compilation, it will lead to different results, and this will cause BEP inconsistence. +make -j1 install_root=$RPM_BUILD_ROOT \ + install-locale-files -C ../localedata objdir=`pwd` +popd + +rm -f $RPM_BUILD_ROOT/%{_libdir}/libNoVersion* +rm -f $RPM_BUILD_ROOT/%{_lib}/libNoVersion* +rm -f $RPM_BUILD_ROOT/%{_lib}/libnss1-* +rm -f $RPM_BUILD_ROOT/%{_lib}/libnss-*.so.1 +rm -f $RPM_BUILD_ROOT/{usr/,}sbin/sln + +mkdir -p $RPM_BUILD_ROOT/var/cache/ldconfig +truncate -s 0 $RPM_BUILD_ROOT/var/cache/ldconfig/aux-cache + +$RPM_BUILD_ROOT/sbin/ldconfig -N -r $RPM_BUILD_ROOT + +# Install info files +%if %{with docs} +# Move the info files if glibc installed them into the wrong location. +if [ -d $RPM_BUILD_ROOT%{_prefix}/info -a "%{_infodir}" != "%{_prefix}/info" ]; then + mkdir -p $RPM_BUILD_ROOT%{_infodir} + mv -f $RPM_BUILD_ROOT%{_prefix}/info/* $RPM_BUILD_ROOT%{_infodir} + rm -rf $RPM_BUILD_ROOT%{_prefix}/info +fi + +# Compress all of the info files. +gzip -9nvf $RPM_BUILD_ROOT%{_infodir}/libc* + +%else +rm -f $RPM_BUILD_ROOT%{_infodir}/dir +rm -f $RPM_BUILD_ROOT%{_infodir}/libc.info* +%endif + +# Create all-packages libc.lang +olddir=`pwd` +pushd $RPM_BUILD_ROOT%{_prefix}/lib/locale +rm -f locale-archive +$olddir/build-%{target}/elf/ld.so \ + --library-path $olddir/build-%{target}/ \ + $olddir/build-%{target}/locale/localedef \ + --alias-file=$olddir/intl/locale.alias \ + --prefix $RPM_BUILD_ROOT --add-to-archive \ + eo *_* +%{find_lang} libc +popd +mv $RPM_BUILD_ROOT%{_prefix}/lib/locale/libc.lang . + +# Install configuration files for services +install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/etc/nsswitch.conf + +mkdir -p $RPM_BUILD_ROOT/etc/default +install -p -m 644 nis/nss $RPM_BUILD_ROOT/etc/default/nss + +# This is for ncsd - in glibc 2.2 +install -m 644 nscd/nscd.conf $RPM_BUILD_ROOT/etc +mkdir -p $RPM_BUILD_ROOT%{_tmpfilesdir} +install -m 644 %{SOURCE1} %{buildroot}%{_tmpfilesdir} +mkdir -p $RPM_BUILD_ROOT/lib/systemd/system +install -m 644 nscd/nscd.service nscd/nscd.socket $RPM_BUILD_ROOT/lib/systemd/system + +# Include ld.so.conf +echo 'include ld.so.conf.d/*.conf' > $RPM_BUILD_ROOT/etc/ld.so.conf +truncate -s 0 $RPM_BUILD_ROOT/etc/ld.so.cache +chmod 644 $RPM_BUILD_ROOT/etc/ld.so.conf +mkdir -p $RPM_BUILD_ROOT/etc/ld.so.conf.d +mkdir -p $RPM_BUILD_ROOT/etc/sysconfig +truncate -s 0 $RPM_BUILD_ROOT/etc/sysconfig/nscd +truncate -s 0 $RPM_BUILD_ROOT/etc/gai.conf + +# Include %{_libdir}/gconv/gconv-modules.cache +truncate -s 0 $RPM_BUILD_ROOT%{_libdir}/gconv/gconv-modules.cache +chmod 644 $RPM_BUILD_ROOT%{_libdir}/gconv/gconv-modules.cache + +# Install debug copies of unstripped static libraries +%if 0%{?_enable_debug_packages} +mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_libdir} +cp -a $RPM_BUILD_ROOT%{_libdir}/*.a \ + $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_libdir}/ +rm -f $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_libdir}/*_p.a +%endif + +# Remove any zoneinfo files; they are maintained by tzdata. +rm -rf $RPM_BUILD_ROOT%{_prefix}/share/zoneinfo + +touch -r %{SOURCE0} $RPM_BUILD_ROOT/etc/ld.so.conf +touch -r sunrpc/etc.rpc $RPM_BUILD_ROOT/etc/rpc + +# Lastly copy some additional documentation for the packages. +rm -rf documentation +mkdir documentation +cp timezone/README documentation/README.timezone +cp posix/gai.conf documentation/ + +%if %{with benchtests} +# Build benchmark binaries. Ignore the output of the benchmark runs. +pushd build-%{target} +make BENCH_DURATION=1 bench-build +popd + +# Copy over benchmark binaries. +mkdir -p $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests +cp $(find build-%{target}/benchtests -type f -executable) $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/ + +#makefile. +for b in %{SOURCE3} %{SOURCE4}; do + cp $b $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/ +done + +#comparison scripts. +for i in benchout.schema.json compare_bench.py import_bench.py validate_benchout.py; do + cp benchtests/scripts/$i $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/ +done + +%if 0%{?_enable_debug_packages} +pushd locale +ln -s programs/*.gperf . +popd + +pushd iconv +ln -s ../locale/programs/charmap-kw.gperf . +popd + +%if %{with docs} +rm -f $RPM_BUILD_ROOT%{_infodir}/dir +%endif + +mkdir -p $RPM_BUILD_ROOT/var/{db,run}/nscd +touch $RPM_BUILD_ROOT/var/{db,run}/nscd/{passwd,group,hosts,services} +touch $RPM_BUILD_ROOT/var/run/nscd/{socket,nscd.pid} + +mkdir -p $RPM_BUILD_ROOT%{_libdir} +mv -f $RPM_BUILD_ROOT/%{_lib}/lib{pcprofile,memusage}.so \ + $RPM_BUILD_ROOT%{_libdir} + +# Strip all of the installed object files. +strip -g $RPM_BUILD_ROOT%{_libdir}/*.o + +# Rebuild libpthread.a using --whole-archive to ensure all of libpthread +# is included in a static link. +pushd $RPM_BUILD_ROOT%{_prefix}/%{_lib}/ +%GCC -r -nostdlib -o libpthread.o -Wl,--whole-archive ./libpthread.a +rm libpthread.a +ar rcs libpthread.a libpthread.o +rm libpthread.o +popd + +for i in $RPM_BUILD_ROOT%{_prefix}/bin/{xtrace,memusage}; do +%if %{with bootstrap} + test -w $i || continue +%endif + sed -e 's~=/%{_lib}/libpcprofile.so~=%{_libdir}/libpcprofile.so~' \ + -e 's~=/%{_lib}/libmemusage.so~=%{_libdir}/libmemusage.so~' \ + -e 's~='\''/\\\$LIB/libpcprofile.so~='\''%{_prefix}/\\$LIB/libpcprofile.so~' \ + -e 's~='\''/\\\$LIB/libmemusage.so~='\''%{_prefix}/\\$LIB/libmemusage.so~' \ + -i $i +done + +touch master.filelist +touch glibc.filelist +touch common.filelist +touch devel.filelist +touch nscd.filelist +touch nss_modules.filelist +touch nss-devel.filelist +touch libnsl.filelist +touch debugutils.filelist +touch benchtests.filelist +touch debuginfo.filelist + +{ + find $RPM_BUILD_ROOT \( -type f -o -type l \) \ + \( \ + -name etc -printf "%%%%config " -o \ + -name gconv-modules \ + -printf "%%%%verify(not md5 size mtime) %%%%config(noreplace) " -o \ + -name gconv-modules.cache \ + -printf "%%%%verify(not md5 size mtime) " \ + , \ + ! -path "*/lib/debug/*" -printf "/%%P\n" \) + + find $RPM_BUILD_ROOT -type d \ + \( -path '*%{_prefix}/share/locale' -prune -o \ + \( -path '*%{_prefix}/share/*' \ +%if %{with docs} + ! -path '*%{_infodir}' -o \ +%endif + -path "*%{_prefix}/include/*" \ + \) -printf "%%%%dir /%%P\n" \) +} | { + sed -e '\,.*/share/locale/\([^/_]\+\).*/LC_MESSAGES/.*\.mo,d' \ + -e '\,.*/share/i18n/locales/.*,d' \ + -e '\,.*/share/i18n/charmaps/.*,d' \ + -e '\,.*/etc/\(localtime\|nsswitch.conf\|ld\.so\.conf\|ld\.so\.cache\|default\|rpc\|gai\.conf\),d' \ + -e '\,.*/%{_libdir}/lib\(pcprofile\|memusage\)\.so,d' \ + -e '\,.*/bin/\(memusage\|mtrace\|xtrace\|pcprofiledump\),d' +} | sort > master.filelist + +chmod 0444 master.filelist + +############################################################################## +# glibc - The GNU C Library (glibc) core package. +############################################################################## +cat master.filelist \ + | grep -v \ + -e '%{_infodir}' \ + -e '%{_libdir}/lib.*_p.a' \ + -e '%{_prefix}/include' \ + -e '%{_libdir}/lib.*\.a' \ + -e '%{_libdir}/.*\.o' \ + -e '%{_libdir}/lib.*\.so' \ + -e 'nscd' \ + -e '%{_prefix}/bin' \ + -e '%{_prefix}/lib/locale' \ + -e '%{_prefix}/sbin/[^i]' \ + -e '%{_prefix}/share' \ + -e '/var/db/Makefile' \ + -e '/libnss_.*\.so[0-9.]*$' \ + -e '/libnsl' \ + -e 'glibc-benchtests' \ + -e 'aux-cache' \ + > glibc.filelist + +for module in compat files dns; do + cat master.filelist \ + | grep -E \ + -e "/libnss_$module(\.so\.[0-9.]+|-[0-9.]+\.so)$" \ + >> glibc.filelist +done +grep -e "libmemusage.so" -e "libpcprofile.so" master.filelist >> glibc.filelist + +%if %{with libpthreadcond} + echo "%{_libdir}/libpthreadcond.so" >> glibc.filelist +%endif + +############################################################################## +# glibc "common" sub-package +############################################################################## +grep '%{_prefix}/bin' master.filelist > common.filelist +grep '%{_prefix}/sbin' master.filelist \ + | grep -v '%{_prefix}/sbin/iconvconfig' \ + | grep -v 'nscd' >> common.filelist + +grep '%{_prefix}/share' master.filelist \ + | grep -v \ + -e '%{_prefix}/share/info/libc.info.*' \ + -e '%%dir %{prefix}/share/info' \ + -e '%%dir %{prefix}/share' \ + >> common.filelist + +############################################################################### +# glibc "devel" sub-package +############################################################################### +%if %{with docs} +grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > devel.filelist +%endif + +grep '%{_libdir}/lib.*\.a' master.filelist \ + | grep '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \ + >> devel.filelist + +grep '%{_libdir}/.*\.o' < master.filelist >> devel.filelist +grep '%{_libdir}/lib.*\.so' < master.filelist >> devel.filelist + +sed -i -e '\,libmemusage.so,d' \ + -e '\,libpcprofile.so,d' \ + -e '\,/libnss_[a-z]*\.so$,d' \ + devel.filelist + +grep '%{_prefix}/include' < master.filelist >> devel.filelist + +grep '%{_libdir}/lib.*\.a' < master.filelist \ + | grep -v '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \ + >> devel.filelist + + +############################################################################## +# glibc "nscd" sub-package +############################################################################## +echo '%{_prefix}/sbin/nscd' > nscd.filelist + +############################################################################## +# nss modules sub-package +############################################################################## +grep -E "/libnss_(db|hesiod)(\.so\.[0-9.]+|-[0-9.]+\.so)$" \ +master.filelist > nss_modules.filelist + +############################################################################## +# nss-devel sub-package +############################################################################## +grep '/libnss_[a-z]*\.so$' master.filelist > nss-devel.filelist + +############################################################################## +# libnsl subpackage +############################################################################## +grep '/libnsl-[0-9.]*.so$' master.filelist > libnsl.filelist +test $(wc -l < libnsl.filelist) -eq 1 + +############################################################################## +# glibc debugutils sub-package +############################################################################## +cat > debugutils.filelist <<EOF +%if %{without bootstrap} +%{_prefix}/bin/memusage +%{_prefix}/bin/memusagestat +%endif +%{_prefix}/bin/mtrace +%{_prefix}/bin/pcprofiledump +%{_prefix}/bin/xtrace +EOF + +############################################################################## +# glibc benchtests sub-package +############################################################################## +find build-%{target}/benchtests -type f -executable | while read b; do + echo "%{_prefix}/libexec/glibc-benchtests/$(basename $b)" +done > benchtests.filelist +# ... and the makefile. +for b in %{SOURCE3} %{SOURCE4}; do + echo "%{_prefix}/libexec/glibc-benchtests/$(basename $b)" >> benchtests.filelist +done +# ... and finally, the comparison scripts. +echo "%{_prefix}/libexec/glibc-benchtests/benchout.schema.json" >> benchtests.filelist +echo "%{_prefix}/libexec/glibc-benchtests/compare_bench.py*" >> benchtests.filelist +echo "%{_prefix}/libexec/glibc-benchtests/import_bench.py*" >> benchtests.filelist +echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.filelist +%endif # 0%{?_enable_debug_packages} + +############################################################################## +# glibc debuginfo sub-package +############################################################################## +touch debuginfo_additional.filelist +find_debuginfo_args='--strict-build-id -i' +%ifarch %{x86_arches} +find_debuginfo_args="$find_debuginfo_args \ + -l common.filelist \ + -l debugutils.filelist \ + -l nscd.filelist \ + -p '.*/(sbin|libexec)/.*' \ + -o debuginfo_additional.filelist \ + -l nss_modules.filelist \ + -l libnsl.filelist \ + -l glibc.filelist \ +%if %{with benchtests} + -l benchtests.filelist +%endif + " +%endif + +/usr/lib/rpm/find-debuginfo.sh $find_debuginfo_args -o debuginfo.filelist + +%ifarch %{x86_arches} +sed -i '\#^$RPM_BUILD_ROOT%{_prefix}/src/debug/#d' debuginfo_additional.filelist +cat debuginfo_additional.filelist >> debuginfo.filelist +find $RPM_BUILD_ROOT%{_prefix}/src/debug \ + \( -type d -printf '%%%%dir ' \) , \ + -printf '%{_prefix}/src/debug/%%P\n' >> debuginfo.filelist + +add_dir=%{_prefix}/lib/debug%{_libdir} +find $RPM_BUILD_ROOT$add_dir -name "*.a" -printf "$add_dir/%%P\n" >> debuginfo.filelist +%endif # %{x86_arches} + +remove_dir="%{_prefix}/src/debug" +remove_dir="$remove_dir $(echo %{_prefix}/lib/debug{,/%{_lib},/bin,/sbin})" +remove_dir="$remove_dir $(echo %{_prefix}/lib/debug%{_prefix}{,/%{_lib},/libexec,/bin,/sbin})" + +for d in $(echo $remove_dir | sed 's/ /\n/g'); do + sed -i "\|^%%dir $d/\?$|d" debuginfo.filelist +done + +%endif # %{with benchtests} +############################################################################## +# Run the glibc testsuite +############################################################################## +%check +%if %{with testsuite} +# Increase timeouts +export TIMEOUTFACTOR=16 +parent=$$ +echo ====================TESTING========================= + +# Default libraries. +pushd build-%{target} +make %{?_smp_mflags} -O check |& tee rpmbuild.check.log >&2 +test -n tests.sum +if ! grep -q '^Summary of test results:$' rpmbuild.check.log ; then + echo "FAIL: test suite build of target: $(basename "$(pwd)")" >& 2 + exit 1 +fi +set +x +grep -v ^PASS: tests.sum > rpmbuild.tests.sum.not-passing || true +if test -n rpmbuild.tests.sum.not-passing ; then + echo ===================FAILED TESTS===================== >&2 + echo "Target: $(basename "$(pwd)")" >& 2 + cat rpmbuild.tests.sum.not-passing >&2 + while read failed_code failed_test ; do + for suffix in out test-result ; do + if test -e "$failed_test.$suffix"; then + echo >&2 + echo "=====$failed_code $failed_test.$suffix=====" >&2 + cat -- "$failed_test.$suffix" >&2 + echo >&2 + fi + done + done <rpmbuild.tests.sum.not-passing +fi + +# Unconditonally dump differences in the system call list. +echo "* System call consistency checks:" >&2 +cat misc/tst-syscall-list.out >&2 +set -x +popd + +echo ====================TESTING END===================== +PLTCMD='/^Relocation section .*\(\.rela\?\.plt\|\.rela\.IA_64\.pltoff\)/,/^$/p' +echo ====================PLT RELOCS LD.SO================ +readelf -Wr $RPM_BUILD_ROOT/%{_lib}/ld-*.so | sed -n -e "$PLTCMD" +echo ====================PLT RELOCS LIBC.SO============== +readelf -Wr $RPM_BUILD_ROOT/%{_lib}/libc-*.so | sed -n -e "$PLTCMD" +echo ====================PLT RELOCS END================== + +pushd build-%{target} +LD_SHOW_AUXV=1 elf/ld.so --library-path .:elf:nptl:dlfcn /bin/true + +%if %{with valgrind} +elf/ld.so --library-path .:elf:nptl:dlfcn \ + /usr/bin/valgrind --error-exitcode=1 \ + elf/ld.so --library-path .:elf:nptl:dlfcn /usr/bin/true +%endif +popd + +%endif # %{run_glibc_tests} + +############################################################################## +# Install and uninstall scripts +############################################################################## +%pre -p <lua> +-- Check that the running kernel is new enough +required = '%{enablekernel}' +rel = posix.uname("%r") +if rpm.vercmp(rel, required) < 0 then + error("FATAL: kernel too old", 0) +end + +%post -p <lua> +-- 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" } + +-- 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 ("%{_prefix}/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 ("%{_prefix}/sbin/iconvconfig", + "-o", iconv_cache, + "--nostdlib", + iconv_dir) +else + io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n") +end + +%pre devel +# this used to be a link and it is causing nightmares now +if [ -L %{_prefix}/include/scsi ] ; then + rm -f %{_prefix}/include/scsi +fi + +%pre -n nscd +getent group nscd >/dev/null || /usr/sbin/groupadd -g 28 -r nscd +getent passwd nscd >/dev/null || + /usr/sbin/useradd -M -o -r -d / -s /sbin/nologin \ + -c "NSCD Daemon" -u 28 -g nscd nscd + +%post -n nscd +%systemd_post nscd.service + +%preun -n nscd +%systemd_preun nscd.service + +%postun -n nscd +if test $1 = 0; then + /usr/sbin/userdel nscd > /dev/null 2>&1 || : +fi +%systemd_postun_with_restart nscd.service + +############################################################################## +# Files list +############################################################################## +%files -f glibc.filelist +%dir %{_prefix}/%{_lib}/audit +%verify(not md5 size mtime) %config(noreplace) /etc/nsswitch.conf +%verify(not md5 size mtime) %config(noreplace) /etc/ld.so.conf +%verify(not md5 size mtime) %config(noreplace) /etc/rpc +%dir /etc/ld.so.conf.d +%dir %{_prefix}/libexec/getconf +%dir %{_libdir}/gconv +%dir %attr(0700,root,root) /var/cache/ldconfig +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/cache/ldconfig/aux-cache +%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/ld.so.cache +%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/gai.conf +%{!?_licensedir:%global license %%doc} +%license COPYING COPYING.LIB LICENSES + +%files -f common.filelist common +%attr(0644,root,root) %verify(not md5 size mtime mode) %ghost %config(missingok,noreplace) %{_prefix}/lib/locale/locale-archive +%dir %{_prefix}/lib/locale +%dir %{_prefix}/lib/locale/C.utf8 +%{_prefix}/lib/locale/C.utf8/* +%{_prefix}/lib/locale/zh_CN.utf8 +%{_prefix}/lib/locale/en_US.utf8 +%{_prefix}/share/locale/zh_CN +%{_prefix}/share/locale/en_GB +%dir %attr(755,root,root) /etc/default +%verify(not md5 size mtime) %config(noreplace) /etc/default/nss + +%files -f libc.lang all-langpacks +%{_prefix}/lib/locale +%exclude %{_prefix}/lib/locale/locale-archive +%exclude %{_prefix}/lib/locale/C.utf8 +%exclude %{_prefix}/lib/locale/zh_CN.utf8 +%exclude %{_prefix}/lib/locale/en_US.utf8 +%exclude %{_prefix}/share/locale/zh_CN +%exclude %{_prefix}/share/locale/en_GB + +%files locale-source +%dir %{_prefix}/share/i18n/locales +%{_prefix}/share/i18n/locales/* +%dir %{_prefix}/share/i18n/charmaps +%{_prefix}/share/i18n/charmaps/* + +%files -f devel.filelist devel + +%files -f nscd.filelist -n nscd +%config(noreplace) /etc/nscd.conf +%dir %attr(0755,root,root) /var/run/nscd +%dir %attr(0755,root,root) /var/db/nscd +/lib/systemd/system/nscd.service +/lib/systemd/system/nscd.socket +%{_tmpfilesdir}/nscd.conf +%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/nscd.pid +%attr(0666,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/socket +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/passwd +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/group +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/hosts +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/services +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/passwd +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/group +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/hosts +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/services +%ghost %config(missingok,noreplace) /etc/sysconfig/nscd + +%files -f nss_modules.filelist -n nss_modules +/var/db/Makefile + +%files -f nss-devel.filelist nss-devel + +%files -f libnsl.filelist -n libnsl +/%{_lib}/libnsl.so.1 + +%files -f debugutils.filelist debugutils + +%if %{with benchtests} +%files -f benchtests.filelist benchtests +%endif + +%if 0%{?_enable_debug_packages} +%files -f debuginfo.filelist debuginfo + +%files debugsource +%endif + + +%files help +#Doc of glibc package +%doc README NEWS INSTALL elf/rtld-debugger-interface.txt +#Doc of common sub-package +%doc documentation/README.timezone +%doc documentation/gai.conf +#Doc of nss_modules sub-package +%doc hesiod/README.hesiod + +%changelog +* Sat Mar 20 2021 xuhuijie <xuhuijie@huawei.com> - 2.31-10 +- semctl: SEM_STAT_ANY fails to pass the buffer specified by + the caller to the kernel [BZ #26637] + https://sourceware.org/bugzilla/show_bug.cgi?id=26637 + +* Tue Jan 26 2021 shanzhikun <shanzhikun@huawei.com> - 2.31-9 +- elf: Allow dlopen of filter object to work [BZ #16272] + https://sourceware.org/bugzilla/show_bug.cgi?id=16272 + +* Fri Jan 8 2021 Wang Shuo<wangshuo_1994@foxmail.com> - 2.31-8 +- Replace "openEuler" by %{_vendor} for versatility + +* Tue Nov 10 2020 liusirui <liusirui@huawei.com> - 2.31-7 +- Fix CVE-2020-27618, iconv accept redundant shift sequences in IBM1364 [BZ #26224] + https://sourceware.org/bugzilla/show_bug.cgi?id=26224 + +* Tue Sep 15 2020 shanzhikun<shanzhikun@huawei.com> - 2.31-6 +- rtld: Avoid using up static TLS surplus for optimizations [BZ #25051]. + https://sourceware.org/git/?p=glibc.git;a=commit;h=ffb17e7ba3a5ba9632cee97330b325072fbe41dd + +* Fri Sep 4 2020 MarsChan<chenmingmin@huawei.com> - 2.31-5 +- For political reasons, remove country selection from tzselect.ksh + +* Fri Aug 14 2020 Xu Huijie<546391727@qq.com> - 2.31-4 +- since the new version of the pthread_cond_wait() + function has performance degradation in multi-core + scenarios, here is an extra libpthreadcond.so using + old version of the function. you can use it by adding + LD_PRELOAD=./libpthreadcond.so in front of your program + (eg: LD_PRELOAD=./libpthreadcond.so ./test). + use with-libpthreadcond to compile it. + warning:2.17 version pthread_cond_wait() does not meet + the posix standard, you should pay attention when using + it. + +* Fri Jul 24 2020 Wang Shuo<wangshuo_1994@foxmail.com> - 2.31-3 +- backport patch to disable warnings due to deprecated libselinux +- symbols used by nss and nscd + +* Fri Jul 24 2020 Wang Shuo<wangshuo_1994@foxmail.com> - 2.31-2 +- fix CVE-2020-6096 +- fix bugzilla 26137, 26214 and 26215 + +* Thu Jul 9 2020 wuxu<wuxu.wu@hotmail.com> - 2.31-1 +- upgrade glibc to 2.31-1 +- delete build-locale-archive command +- delete nsswitch.conf file +- replace glibc_post_upgrade function with lua +- remove sys/sysctl.h header file +- delete stime, ftime function + +* Tue Jul 7 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-45 +- disable rpc, it has been splited to libnss and libtirpc +- disable parallel compilation + +* Tue Jul 7 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-44 +- backup to version 40 + +* Mon Jul 6 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-43 +- disable rpc, it has been splited to libnss and libtirpc +- disable parallel compilation + +* Mon Jul 6 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-42 +- add zh and en to LanguageList + +* Thu Jul 2 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-41 +- add filelist to improve the scalability +- backport many patch for bugfix + +* Sat May 30 2020 liqingqing<liqignqing3@huawei.com> - 2.28-40 +- Fix array overflow in backtrace on PowerPC (bug 25423) + +* Thu May 28 2020 jdkboy<guoge1@huawei.com> - 2.28-39 +- Disable compilation warnings temporarily + +* Tue Apr 28 2020 liqingqing<liqignqing3@huawei.com> - 2.28-38 +- Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487) + +* Thu Apr 16 2020 wangbin<wangbin224@huawei.com> - 2.28-37 +- backport Kunpeng patches + +* Thu Mar 19 2020 yuxiangyang<yuxiangyang4@huawei.com> - 2.28-36 +- fix build src.rpm error + +* Fri Mar 13 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-35 +- exclude conflict files about rpc + +* Fri Mar 13 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-34 +- enable obsolete rpc + +* Tue Mar 10 2020 liqingqing<liqingqing3@huawei.com> - 2.28-33 +- fix use after free in glob when expanding user bug + +* Wed Feb 26 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-32 +- remove aditional require for debugutils package + +* Tue Jan 7 2020 Wang Shuo <wangshuo47@huawei.com> - 2.28-31 +- Fix compile macro + +* Mon Jan 6 2020 Wang Shuo <wangshuo47@huawei.com> - 2.28-30 +- add obsoletes symbol for language + +* Fri Dec 20 2019 liqingqing <liqingqing3@huawei.com> - 2.28-29 +- remove country selection from tzselect +- fix some bugs https://sourceware.org/git/?p=glibc.git;a=commit;h=1df872fd74f730bcae3df201a229195445d2e18a + https://sourceware.org/git/?p=glibc.git;a=commit;h=823624bdc47f1f80109c9c52dee7939b9386d708 + https://sourceware.org/git/?p=glibc.git;a=commit;h=bc10e22c90e42613bd5dafb77b80a9ea1759dd1b + https://sourceware.org/git/?p=glibc.git;a=commit;h=6c29942cbf059aca47fd4bbd852ea42c9d46b71f + https://sourceware.org/git/?p=glibc.git;a=commit;h=31effacee2fc1b327bedc9a5fcb4b83f227c6539 + https://sourceware.org/git/?p=glibc.git;a=commit;h=5b06f538c5aee0389ed034f60d90a8884d6d54de + https://sourceware.org/git/?p=glibc.git;a=commit;h=57ada43c905eec7ba28fe60a08b93a52d88e26c1 + https://sourceware.org/git/?p=glibc.git;a=commit;h=e0e4c321c3145b6ac0e8f6e894f87790cf9437ce + https://sourceware.org/git/?p=glibc.git;a=commit;h=182a3746b8cc28784718c8ea27346e97d1423945 + https://sourceware.org/git/?p=glibc.git;a=commit;h=02d8b5ab1c89bcef2627d2b621bfb35b573852c2 + https://sourceware.org/git/?p=glibc.git;a=commit;h=f59a54ab0c2dcaf9ee946df2bfee9d4be81f09b8 + https://sourceware.org/git/?p=glibc.git;a=commit;h=fefa21790b5081e5d04662a240e2efd18603ef86 + https://sourceware.org/git/?p=glibc.git;a=commit;h=2bd81b60d6ffdf7e0d22006d69f4b812b1c80513 + https://sourceware.org/git/?p=glibc.git;a=commit;h=a55541fd1c4774d483c2d2b4bd17bcb9faac62e7 + https://sourceware.org/git/?p=glibc.git;a=commit;h=b6d2c4475d5abc05dd009575b90556bdd3c78ad0 + https://sourceware.org/git/?p=glibc.git;a=commit;h=8a80ee5e2bab17a1f8e1e78fab5c33ac7efa8b29 + https://sourceware.org/git/?p=glibc.git;a=commit;h=c0fd3244e71db39cef1e2d1d8ba12bb8b7375ce4 +- fix CVE-2016-10739 CVE-2019-19126 CVE-2019-6488 +- add pie compile option for debug/Makefile and remove -static for build-locale-archive + +* Fri Dec 20 2019 liusirui <liusirui@huawei.com> - 2.28-28 +- Fix null pointer in mtrace + +* Thu Nov 21 2019 mengxian <mengxian@huawei.com> - 2.28-27 +- In x86, configure static pie and cet only with gcc 8 or above + +* Wed Nov 13 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.28-26 +- Optimized instructions for Kunpeng processor + +* Fri Jan 18 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.28-25 +- Package init diff --git a/nptl-Don-t-madvise-user-provided-stack.patch b/nptl-Don-t-madvise-user-provided-stack.patch new file mode 100644 index 0000000..41937de --- /dev/null +++ b/nptl-Don-t-madvise-user-provided-stack.patch @@ -0,0 +1,41 @@ +From 087942251f26d5fd5802b8d14e47d460263a0c4d Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 24 Jun 2020 07:47:15 +0100 +Subject: [PATCH] nptl: Don't madvise user provided stack + +User provided stack should not be released nor madvised at +thread exit because it's owned by the user. + +If the memory is shared or file based then MADV_DONTNEED +can have unwanted effects. With memory tagging on aarch64 +linux the tags are dropped and thus it may invalidate +pointers. + +Tested on aarch64-linux-gnu with MTE, it fixes + +FAIL: nptl/tst-stack3 +FAIL: nptl/tst-stack3-mem + +--- + nptl/pthread_create.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index 179f07a1..00931c19 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -564,8 +564,9 @@ START_THREAD_DEFN + } + #endif + +- advise_stack_range (pd->stackblock, pd->stackblock_size, (uintptr_t) pd, +- pd->guardsize); ++ if (!pd->user_stack) ++ advise_stack_range (pd->stackblock, pd->stackblock_size, (uintptr_t) pd, ++ pd->guardsize); + + if (__glibc_unlikely (pd->cancelhandling & SETXID_BITMASK)) + { +-- +2.19.1 + diff --git a/nptl-wait-for-pending-setxid-request-also-in-detache.patch b/nptl-wait-for-pending-setxid-request-also-in-detache.patch new file mode 100644 index 0000000..604e0b7 --- /dev/null +++ b/nptl-wait-for-pending-setxid-request-also-in-detache.patch @@ -0,0 +1,52 @@ +From 4cab20fa49b3ea3e3454fdc4f13bf3828d8efd19 Mon Sep 17 00:00:00 2001 +From: Andreas Schwab <schwab@suse.de> +Date: Thu, 7 May 2020 15:50:09 +0200 +Subject: [PATCH] nptl: wait for pending setxid request also in detached thread + (bug 25942) + +There is a race between __nptl_setxid and exiting detached thread, which +causes a deadlock on stack_cache_lock. The deadlock happens in this +state: + +T1: setgroups -> __nptl_setxid (holding stack_cache_lock, waiting on cmdp->cntr == 0) +T2 (detached, exiting): start_thread -> __deallocate_stack (waiting on stack_cache_lock) +more threads waiting on stack_cache_lock in pthread_create + +For non-detached threads, start_thread waits for its own setxid handler to +finish before exiting. Do this for detached threads as well. +--- + nptl/pthread_create.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index afd379e89a..a43089065c 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -567,11 +567,7 @@ START_THREAD_DEFN + advise_stack_range (pd->stackblock, pd->stackblock_size, (uintptr_t) pd, + pd->guardsize); + +- /* If the thread is detached free the TCB. */ +- if (IS_DETACHED (pd)) +- /* Free the TCB. */ +- __free_tcb (pd); +- else if (__glibc_unlikely (pd->cancelhandling & SETXID_BITMASK)) ++ if (__glibc_unlikely (pd->cancelhandling & SETXID_BITMASK)) + { + /* Some other thread might call any of the setXid functions and expect + us to reply. In this case wait until we did that. */ +@@ -587,6 +583,11 @@ START_THREAD_DEFN + pd->setxid_futex = 0; + } + ++ /* If the thread is detached free the TCB. */ ++ if (IS_DETACHED (pd)) ++ /* Free the TCB. */ ++ __free_tcb (pd); ++ + /* We cannot call '_exit' here. '_exit' will terminate the process. + + The 'exit' implementation in the kernel will signal when the +-- +2.19.1 + diff --git a/nscd.conf b/nscd.conf new file mode 100644 index 0000000..8a24a78 --- /dev/null +++ b/nscd.conf @@ -0,0 +1 @@ +d /run/nscd 0755 root root diff --git a/nsswitch.conf b/nsswitch.conf new file mode 100644 index 0000000..b49a3b2 --- /dev/null +++ b/nsswitch.conf @@ -0,0 +1,56 @@ +# +# /etc/nsswitch.conf +# +# An example Name Service Switch config file. This file should be +# sorted with the most-used services at the beginning. +# +# The entry '[NOTFOUND=return]' means that the search for an +# entry should stop if the search in the previous entry turned +# up nothing. Note that if the search failed due to some other reason +# (like no NIS server responding) then the search continues with the +# next entry. +# +# Valid entries include: +# +# nisplus Use NIS+ (NIS version 3) +# nis Use NIS (NIS version 2), also called YP +# dns Use DNS (Domain Name Service) +# files Use the local files in /etc +# db Use the pre-processed /var/db files +# compat Use /etc files plus *_compat pseudo-databases +# hesiod Use Hesiod (DNS) for user lookups +# sss Use sssd (System Security Services Daemon) +# [NOTFOUND=return] Stop searching if not found so far +# +# 'sssd' performs its own 'files'-based caching, so it should +# generally come before 'files'. + +# To use 'db', install the nss_db package, and put the 'db' in front +# of 'files' for entries you want to be looked up first in the +# databases, like this: +# +# passwd: db files +# shadow: db files +# group: db files + +passwd: sss files +shadow: files sss +group: sss files + +hosts: files dns myhostname + +bootparams: files + +ethers: files +netmasks: files +networks: files +protocols: files +rpc: files +services: files sss + +netgroup: sss + +publickey: files + +automount: files sss +aliases: files diff --git a/remove-country-selection-from-tzselect.patch b/remove-country-selection-from-tzselect.patch new file mode 100644 index 0000000..5b00087 --- /dev/null +++ b/remove-country-selection-from-tzselect.patch @@ -0,0 +1,151 @@ +From dff0000cc458d6d4993b821f2badcf31ea28062e Mon Sep 17 00:00:00 2001 +From: MarsChan <cmm8293@163.com> +Date: Sun, 6 Sep 2020 09:42:44 +0800 +Subject: [PATCH] remove country selection from tzselect.ksh + +--- + timezone/tzselect.ksh | 98 +++++++++---------------------------------- + 1 file changed, 20 insertions(+), 78 deletions(-) + +diff --git a/timezone/tzselect.ksh b/timezone/tzselect.ksh +index 18fce27e..7e31798c 100755 +--- a/timezone/tzselect.ksh ++++ b/timezone/tzselect.ksh +@@ -51,7 +51,7 @@ say() { + + coord= + location_limit=10 +-zonetabtype=zone1970 ++zonetabtype=zone + + usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT] + Select a timezone interactively. +@@ -398,94 +398,37 @@ while + '` + ;; + *) +- # Get list of names of countries in the continent or ocean. +- countries=`$AWK \ ++ # Get list of regions in the continent or ocean. ++ timezones=`$AWK \ + -v continent="$continent" \ + -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ + ' + BEGIN { FS = "\t" } + /^#/ { next } + $3 ~ ("^" continent "/") { +- ncc = split($1, cc, /,/) ++ ncc = split($3, cc, /,/) + for (i = 1; i <= ncc; i++) + if (!cc_seen[cc[i]]++) cc_list[++ccs] = cc[i] + } + END { +- while (getline <TZ_COUNTRY_TABLE) { +- if ($0 !~ /^#/) cc_name[$1] = $2 +- } + for (i = 1; i <= ccs; i++) { +- country = cc_list[i] +- if (cc_name[country]) { +- country = cc_name[country] +- } +- print country ++ print cc_list[i] + } + } + ' <"$TZ_ZONE_TABLE" | sort -f` +- +- +- # If there's more than one country, ask the user which one. +- case $countries in +- *"$newline"*) +- echo >&2 'Please select a country' \ +- 'whose clocks agree with yours.' +- doselect $countries +- country=$select_result;; +- *) +- country=$countries +- esac +- +- +- # Get list of timezones in the country. +- regions=`$AWK \ +- -v country="$country" \ +- -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ +- ' +- BEGIN { +- FS = "\t" +- cc = country +- while (getline <TZ_COUNTRY_TABLE) { +- if ($0 !~ /^#/ && country == $2) { +- cc = $1 +- break +- } +- } +- } +- /^#/ { next } +- $1 ~ cc { print $4 } +- ' <"$TZ_ZONE_TABLE"` +- +- +- # If there's more than one region, ask the user which one. +- case $regions in +- *"$newline"*) +- echo >&2 'Please select one of the following timezones.' +- doselect $regions +- region=$select_result;; +- *) +- region=$regions +- esac ++ regions=[] ++ index=0 ++ for item in $timezones; do ++ regions[$index]=`echo $item | awk -F '/' '{print $2}'` ++ index=$(($index+1)) ++ done ++ echo >&2 'Please select a timezone' \ ++ 'whose clocks agree with yours.' ++ doselect ${regions[@]} ++ region=$select_result + + # Determine TZ from country and region. +- TZ=`$AWK \ +- -v country="$country" \ +- -v region="$region" \ +- -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ +- ' +- BEGIN { +- FS = "\t" +- cc = country +- while (getline <TZ_COUNTRY_TABLE) { +- if ($0 !~ /^#/ && country == $2) { +- cc = $1 +- break +- } +- } +- } +- /^#/ { next } +- $1 ~ cc && $4 == region { print $3 } +- ' <"$TZ_ZONE_TABLE"` ++ TZ=$continent/$region + esac + + # Make sure the corresponding zoneinfo file exists. +@@ -523,11 +466,10 @@ Universal Time is now: $UTdate." + echo >&2 "" + echo >&2 "The following information has been given:" + echo >&2 "" +- case $country%$region%$coord in +- ?*%?*%) say >&2 " $country$newline $region";; +- ?*%%) say >&2 " $country";; +- %?*%?*) say >&2 " coord $coord$newline $region";; +- %%?*) say >&2 " coord $coord";; ++ case $region%$coord in ++ ?*%) say >&2 " $region";; ++ ?*%?*) say >&2 " coord $coord$newline $region";; ++ %?*) say >&2 " coord $coord";; + *) say >&2 " TZ='$TZ'" + esac + say >&2 "" +-- +2.24.3 (Apple Git-128) + diff --git a/rtld-Avoid-using-up-static-TLS-surplus-for-optimizat.patch b/rtld-Avoid-using-up-static-TLS-surplus-for-optimizat.patch new file mode 100644 index 0000000..d70be0b --- /dev/null +++ b/rtld-Avoid-using-up-static-TLS-surplus-for-optimizat.patch @@ -0,0 +1,586 @@ +From ffb17e7ba3a5ba9632cee97330b325072fbe41dd Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 10 Jun 2020 13:40:40 +0100 +Subject: [PATCH] rtld: Avoid using up static TLS surplus for optimizations [BZ + #25051] + +On some targets static TLS surplus area can be used opportunistically +for dynamically loaded modules such that the TLS access then becomes +faster (TLSDESC and powerpc TLS optimization). However we don't want +all surplus TLS to be used for this optimization because dynamically +loaded modules with initial-exec model TLS can only use surplus TLS. + +The new contract for surplus static TLS use is: + +- libc.so can have up to 192 bytes of IE TLS, +- other system libraries together can have up to 144 bytes of IE TLS. +- Some "optional" static TLS is available for opportunistic use. + +The optional TLS is now tunable: rtld.optional_static_tls, so users +can directly affect the allocated static TLS size. (Note that module +unloading with dlclose does not reclaim static TLS. After the optional +TLS runs out, TLS access is no longer optimized to use static TLS.) + +The default setting of rtld.optional_static_tls is 512 so the surplus +TLS is 3*192 + 4*144 + 512 = 1664 by default, the same as before. + +Fixes BZ #25051. + +Tested on aarch64-linux-gnu and x86_64-linux-gnu. + +Reviewed-by: Carlos O'Donell <carlos@redhat.com> +--- + csu/libc-tls.c | 3 ++ + elf/Makefile | 29 +++++++++++- + elf/dl-reloc.c | 37 +++++++++++---- + elf/dl-tls.c | 9 ++-- + elf/dl-tunables.list | 5 ++ + elf/dynamic-link.h | 5 +- + elf/tst-tls-ie-dlmopen.c | 112 +++++++++++++++++++++++++++++++++++++++++++++ + elf/tst-tls-ie-mod.h | 40 ++++++++++++++++ + elf/tst-tls-ie-mod0.c | 4 ++ + elf/tst-tls-ie-mod1.c | 4 ++ + elf/tst-tls-ie-mod2.c | 4 ++ + elf/tst-tls-ie-mod3.c | 4 ++ + elf/tst-tls-ie-mod4.c | 4 ++ + elf/tst-tls-ie-mod5.c | 4 ++ + elf/tst-tls-ie-mod6.c | 4 ++ + elf/tst-tls-ie.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ + manual/tunables.texi | 17 +++++++ + sysdeps/generic/ldsodefs.h | 3 ++ + 18 files changed, 382 insertions(+), 17 deletions(-) + create mode 100644 elf/tst-tls-ie-dlmopen.c + create mode 100644 elf/tst-tls-ie-mod.h + create mode 100644 elf/tst-tls-ie-mod0.c + create mode 100644 elf/tst-tls-ie-mod1.c + create mode 100644 elf/tst-tls-ie-mod2.c + create mode 100644 elf/tst-tls-ie-mod3.c + create mode 100644 elf/tst-tls-ie-mod4.c + create mode 100644 elf/tst-tls-ie-mod5.c + create mode 100644 elf/tst-tls-ie-mod6.c + create mode 100644 elf/tst-tls-ie.c + +diff --git a/csu/libc-tls.c b/csu/libc-tls.c +index 28a7944..1b68d71 100644 +--- a/csu/libc-tls.c ++++ b/csu/libc-tls.c +@@ -59,6 +59,9 @@ size_t _dl_tls_static_size = 2048; + size_t _dl_tls_static_used; + /* Alignment requirement of the static TLS block. */ + size_t _dl_tls_static_align; ++/* Remaining amount of static TLS that may be used for optimizing ++ dynamic TLS access (e.g. with TLSDESC). */ ++size_t _dl_tls_static_optional = 512; + + /* Generation counter for the dtv. */ + size_t _dl_tls_generation; +diff --git a/elf/Makefile b/elf/Makefile +index 632a4d8..f440488 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -201,7 +201,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-unwind-ctor tst-unwind-main tst-audit13 \ + tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-tlsmodid \ + tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \ +- tst-dlopenfail-2 ++ tst-dlopenfail-2 \ ++ tst-tls-ie tst-tls-ie-dlmopen + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -312,7 +313,10 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \ + tst-initlazyfailmod tst-finilazyfailmod \ + tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ +- tst-dlopenfailmod3 tst-ldconfig-ld-mod ++ tst-dlopenfailmod3 tst-ldconfig-ld-mod \ ++ tst-tls-ie-mod0 tst-tls-ie-mod1 tst-tls-ie-mod2 \ ++ tst-tls-ie-mod3 tst-tls-ie-mod4 tst-tls-ie-mod5 \ ++ tst-tls-ie-mod6 + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. + modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\ +@@ -1699,3 +1703,23 @@ LDFLAGS-tst-dlopen-nodelete-reloc-mod17.so = -Wl,--no-as-needed + + $(objpfx)tst-ldconfig-ld_so_conf-update.out: $(objpfx)tst-ldconfig-ld-mod.so + $(objpfx)tst-ldconfig-ld_so_conf-update: $(libdl) ++ ++$(objpfx)tst-tls-ie: $(libdl) $(shared-thread-library) ++$(objpfx)tst-tls-ie.out: \ ++ $(objpfx)tst-tls-ie-mod0.so \ ++ $(objpfx)tst-tls-ie-mod1.so \ ++ $(objpfx)tst-tls-ie-mod2.so \ ++ $(objpfx)tst-tls-ie-mod3.so \ ++ $(objpfx)tst-tls-ie-mod4.so \ ++ $(objpfx)tst-tls-ie-mod5.so \ ++ $(objpfx)tst-tls-ie-mod6.so ++ ++$(objpfx)tst-tls-ie-dlmopen: $(libdl) $(shared-thread-library) ++$(objpfx)tst-tls-ie-dlmopen.out: \ ++ $(objpfx)tst-tls-ie-mod0.so \ ++ $(objpfx)tst-tls-ie-mod1.so \ ++ $(objpfx)tst-tls-ie-mod2.so \ ++ $(objpfx)tst-tls-ie-mod3.so \ ++ $(objpfx)tst-tls-ie-mod4.so \ ++ $(objpfx)tst-tls-ie-mod5.so \ ++ $(objpfx)tst-tls-ie-mod6.so +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index ffcc84d..6d32e49 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -39,13 +39,16 @@ + /* We are trying to perform a static TLS relocation in MAP, but it was + dynamically loaded. This can only work if there is enough surplus in + the static TLS area already allocated for each running thread. If this +- object's TLS segment is too big to fit, we fail. If it fits, +- we set MAP->l_tls_offset and return. +- This function intentionally does not return any value but signals error +- directly, as static TLS should be rare and code handling it should +- not be inlined as much as possible. */ ++ object's TLS segment is too big to fit, we fail with -1. If it fits, ++ we set MAP->l_tls_offset and return 0. ++ A portion of the surplus static TLS can be optionally used to optimize ++ dynamic TLS access (with TLSDESC or powerpc TLS optimizations). ++ If OPTIONAL is true then TLS is allocated for such optimization and ++ the caller must have a fallback in case the optional portion of surplus ++ TLS runs out. If OPTIONAL is false then the entire surplus TLS area is ++ considered and the allocation only fails if that runs out. */ + int +-_dl_try_allocate_static_tls (struct link_map *map) ++_dl_try_allocate_static_tls (struct link_map *map, bool optional) + { + /* If we've already used the variable with dynamic access, or if the + alignment requirements are too high, fail. */ +@@ -68,8 +71,14 @@ _dl_try_allocate_static_tls (struct link_map *map) + + size_t n = (freebytes - blsize) / map->l_tls_align; + +- size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align +- - map->l_tls_firstbyte_offset); ++ /* Account optional static TLS surplus usage. */ ++ size_t use = freebytes - n * map->l_tls_align - map->l_tls_firstbyte_offset; ++ if (optional && use > GL(dl_tls_static_optional)) ++ goto fail; ++ else if (optional) ++ GL(dl_tls_static_optional) -= use; ++ ++ size_t offset = GL(dl_tls_static_used) + use; + + map->l_tls_offset = GL(dl_tls_static_used) = offset; + #elif TLS_DTV_AT_TP +@@ -83,6 +92,13 @@ _dl_try_allocate_static_tls (struct link_map *map) + if (used > GL(dl_tls_static_size)) + goto fail; + ++ /* Account optional static TLS surplus usage. */ ++ size_t use = used - GL(dl_tls_static_used); ++ if (optional && use > GL(dl_tls_static_optional)) ++ goto fail; ++ else if (optional) ++ GL(dl_tls_static_optional) -= use; ++ + map->l_tls_offset = offset; + map->l_tls_firstbyte_offset = GL(dl_tls_static_used); + GL(dl_tls_static_used) = used; +@@ -110,12 +126,15 @@ _dl_try_allocate_static_tls (struct link_map *map) + return 0; + } + ++/* This function intentionally does not return any value but signals error ++ directly, as static TLS should be rare and code handling it should ++ not be inlined as much as possible. */ + void + __attribute_noinline__ + _dl_allocate_static_tls (struct link_map *map) + { + if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET +- || _dl_try_allocate_static_tls (map)) ++ || _dl_try_allocate_static_tls (map, false)) + { + _dl_signal_error (0, map->l_name, NULL, N_("\ + cannot allocate memory in static TLS block")); +diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h +index bb7a66f..6727233 100644 +--- a/elf/dynamic-link.h ++++ b/elf/dynamic-link.h +@@ -40,9 +40,10 @@ + (__builtin_expect ((sym_map)->l_tls_offset \ + != FORCED_DYNAMIC_TLS_OFFSET, 1) \ + && (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \ +- || _dl_try_allocate_static_tls (sym_map) == 0)) ++ || _dl_try_allocate_static_tls (sym_map, true) == 0)) + +-int _dl_try_allocate_static_tls (struct link_map *map) attribute_hidden; ++int _dl_try_allocate_static_tls (struct link_map *map, bool optional) ++ attribute_hidden; + + #include <elf.h> + +diff --git a/elf/tst-tls-ie-dlmopen.c b/elf/tst-tls-ie-dlmopen.c +new file mode 100644 +index 0000000..c7b5c68 +--- /dev/null ++++ b/elf/tst-tls-ie-dlmopen.c +@@ -0,0 +1,112 @@ ++/* Test dlopen of modules with initial-exec TLS after dlmopen. ++ Copyright (C) 2016-2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++/* This test tries to check that surplus static TLS is not used up for ++ dynamic TLS optimizations and 4*144 = 576 bytes of static TLS is ++ still available for dlopening modules with initial-exec TLS after 3 ++ new dlmopen namespaces are created. It depends on rtld.nns=4 and ++ rtld.optional_static_tls=512 tunable settings. */ ++ ++#include <errno.h> ++#include <pthread.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++static int do_test (void); ++#include <support/xthread.h> ++#include <support/xdlfcn.h> ++#include <support/check.h> ++#include <support/test-driver.c> ++ ++/* Have some big TLS in the main exe: should not use surplus TLS. */ ++__thread char maintls[1000]; ++ ++static pthread_barrier_t barrier; ++ ++/* Forces multi-threaded behaviour. */ ++static void * ++blocked_thread_func (void *closure) ++{ ++ xpthread_barrier_wait (&barrier); ++ /* TLS load and access tests run here in the main thread. */ ++ xpthread_barrier_wait (&barrier); ++ return NULL; ++} ++ ++static void * ++load_and_access (Lmid_t lmid, const char *mod, const char *func) ++{ ++ /* Load module with TLS. */ ++ void *p = xdlmopen (lmid, mod, RTLD_NOW); ++ /* Access the TLS variable to ensure it is allocated. */ ++ void (*f) (void) = (void (*) (void))xdlsym (p, func); ++ f (); ++ return p; ++} ++ ++static int ++do_test (void) ++{ ++ void *mods[5]; ++ ++ { ++ int ret = pthread_barrier_init (&barrier, NULL, 2); ++ if (ret != 0) ++ { ++ errno = ret; ++ printf ("error: pthread_barrier_init: %m\n"); ++ exit (1); ++ } ++ } ++ ++ pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL); ++ xpthread_barrier_wait (&barrier); ++ ++ printf ("maintls[%zu]:\t %p .. %p\n", ++ sizeof maintls, maintls, maintls + sizeof maintls); ++ memset (maintls, 1, sizeof maintls); ++ ++ /* Load modules with dynamic TLS (use surplus static TLS for libc ++ in new namespaces and may be for TLS optimizations too). */ ++ mods[0] = load_and_access (LM_ID_BASE, "tst-tls-ie-mod0.so", "access0"); ++ mods[1] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod1.so", "access1"); ++ mods[2] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod2.so", "access2"); ++ mods[3] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod3.so", "access3"); ++ /* Load modules with initial-exec TLS (can only use surplus static TLS). */ ++ mods[4] = load_and_access (LM_ID_BASE, "tst-tls-ie-mod6.so", "access6"); ++ ++ /* Here 576 bytes + 3 * libc use of surplus static TLS is in use so less ++ than 1024 bytes are available (exact number depends on TLS optimizations ++ and the libc TLS use). */ ++ printf ("The next dlmopen should fail...\n"); ++ void *p = dlmopen (LM_ID_BASE, "tst-tls-ie-mod4.so", RTLD_NOW); ++ if (p != NULL) ++ FAIL_EXIT1 ("error: expected dlmopen to fail because there is " ++ "not enough surplus static TLS.\n"); ++ printf ("...OK failed with: %s.\n", dlerror ()); ++ ++ xpthread_barrier_wait (&barrier); ++ xpthread_join (blocked_thread); ++ ++ /* Close the modules. */ ++ for (int i = 0; i < 5; ++i) ++ xdlclose (mods[i]); ++ ++ return 0; ++} +diff --git a/elf/tst-tls-ie-mod.h b/elf/tst-tls-ie-mod.h +new file mode 100644 +index 0000000..46b362a +--- /dev/null ++++ b/elf/tst-tls-ie-mod.h +@@ -0,0 +1,40 @@ ++/* Module with specified TLS size and model. ++ Copyright (C) 2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++/* This file is parameterized by macros N, SIZE and MODEL. */ ++ ++#include <stdio.h> ++#include <string.h> ++ ++#define CONCATX(x, y) x ## y ++#define CONCAT(x, y) CONCATX (x, y) ++#define STRX(x) #x ++#define STR(x) STRX (x) ++ ++#define VAR CONCAT (var, N) ++ ++__attribute__ ((aligned (8), tls_model (MODEL))) ++__thread char VAR[SIZE]; ++ ++void ++CONCAT (access, N) (void) ++{ ++ printf (STR (VAR) "[%d]:\t %p .. %p " MODEL "\n", SIZE, VAR, VAR + SIZE); ++ fflush (stdout); ++ memset (VAR, 1, SIZE); ++} +diff --git a/elf/tst-tls-ie-mod0.c b/elf/tst-tls-ie-mod0.c +new file mode 100644 +index 0000000..2450686 +--- /dev/null ++++ b/elf/tst-tls-ie-mod0.c +@@ -0,0 +1,4 @@ ++#define N 0 ++#define SIZE 480 ++#define MODEL "global-dynamic" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod1.c b/elf/tst-tls-ie-mod1.c +new file mode 100644 +index 0000000..849ff91 +--- /dev/null ++++ b/elf/tst-tls-ie-mod1.c +@@ -0,0 +1,4 @@ ++#define N 1 ++#define SIZE 120 ++#define MODEL "global-dynamic" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod2.c b/elf/tst-tls-ie-mod2.c +new file mode 100644 +index 0000000..23915ab +--- /dev/null ++++ b/elf/tst-tls-ie-mod2.c +@@ -0,0 +1,4 @@ ++#define N 2 ++#define SIZE 24 ++#define MODEL "global-dynamic" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod3.c b/elf/tst-tls-ie-mod3.c +new file mode 100644 +index 0000000..5395f84 +--- /dev/null ++++ b/elf/tst-tls-ie-mod3.c +@@ -0,0 +1,4 @@ ++#define N 3 ++#define SIZE 16 ++#define MODEL "global-dynamic" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod4.c b/elf/tst-tls-ie-mod4.c +new file mode 100644 +index 0000000..93ac2ea +--- /dev/null ++++ b/elf/tst-tls-ie-mod4.c +@@ -0,0 +1,4 @@ ++#define N 4 ++#define SIZE 1024 ++#define MODEL "initial-exec" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod5.c b/elf/tst-tls-ie-mod5.c +new file mode 100644 +index 0000000..84b3fd2 +--- /dev/null ++++ b/elf/tst-tls-ie-mod5.c +@@ -0,0 +1,4 @@ ++#define N 5 ++#define SIZE 128 ++#define MODEL "initial-exec" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod6.c b/elf/tst-tls-ie-mod6.c +new file mode 100644 +index 0000000..c736bf0 +--- /dev/null ++++ b/elf/tst-tls-ie-mod6.c +@@ -0,0 +1,4 @@ ++#define N 6 ++#define SIZE 576 ++#define MODEL "initial-exec" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie.c b/elf/tst-tls-ie.c +new file mode 100644 +index 0000000..2dc0894 +--- /dev/null ++++ b/elf/tst-tls-ie.c +@@ -0,0 +1,111 @@ ++/* Test dlopen of modules with initial-exec TLS. ++ Copyright (C) 2016-2020 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 ++ <https://www.gnu.org/licenses/>. */ ++ ++/* This test tries to check that surplus static TLS is not used up for ++ dynamic TLS optimizations and 3*192 + 4*144 = 1152 bytes of static ++ TLS is available for dlopening modules with initial-exec TLS. It ++ depends on rtld.nns=4 and rtld.optional_static_tls=512 tunable setting. */ ++ ++#include <errno.h> ++#include <pthread.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++static int do_test (void); ++#include <support/xthread.h> ++#include <support/xdlfcn.h> ++#include <support/check.h> ++#include <support/test-driver.c> ++ ++/* Have some big TLS in the main exe: should not use surplus TLS. */ ++__thread char maintls[1000]; ++ ++static pthread_barrier_t barrier; ++ ++/* Forces multi-threaded behaviour. */ ++static void * ++blocked_thread_func (void *closure) ++{ ++ xpthread_barrier_wait (&barrier); ++ /* TLS load and access tests run here in the main thread. */ ++ xpthread_barrier_wait (&barrier); ++ return NULL; ++} ++ ++static void * ++load_and_access (const char *mod, const char *func) ++{ ++ /* Load module with TLS. */ ++ void *p = xdlopen (mod, RTLD_NOW); ++ /* Access the TLS variable to ensure it is allocated. */ ++ void (*f) (void) = (void (*) (void))xdlsym (p, func); ++ f (); ++ return p; ++} ++ ++static int ++do_test (void) ++{ ++ void *mods[6]; ++ ++ { ++ int ret = pthread_barrier_init (&barrier, NULL, 2); ++ if (ret != 0) ++ { ++ errno = ret; ++ printf ("error: pthread_barrier_init: %m\n"); ++ exit (1); ++ } ++ } ++ ++ pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL); ++ xpthread_barrier_wait (&barrier); ++ ++ printf ("maintls[%zu]:\t %p .. %p\n", ++ sizeof maintls, maintls, maintls + sizeof maintls); ++ memset (maintls, 1, sizeof maintls); ++ ++ /* Load modules with dynamic TLS (may use surplus static TLS ++ opportunistically). */ ++ mods[0] = load_and_access ("tst-tls-ie-mod0.so", "access0"); ++ mods[1] = load_and_access ("tst-tls-ie-mod1.so", "access1"); ++ mods[2] = load_and_access ("tst-tls-ie-mod2.so", "access2"); ++ mods[3] = load_and_access ("tst-tls-ie-mod3.so", "access3"); ++ /* Load modules with initial-exec TLS (can only use surplus static TLS). */ ++ mods[4] = load_and_access ("tst-tls-ie-mod4.so", "access4"); ++ mods[5] = load_and_access ("tst-tls-ie-mod5.so", "access5"); ++ ++ /* Here 1152 bytes of surplus static TLS is in use and at most 512 bytes ++ are available (depending on TLS optimizations). */ ++ printf ("The next dlopen should fail...\n"); ++ void *p = dlopen ("tst-tls-ie-mod6.so", RTLD_NOW); ++ if (p != NULL) ++ FAIL_EXIT1 ("error: expected dlopen to fail because there is " ++ "not enough surplus static TLS.\n"); ++ printf ("...OK failed with: %s.\n", dlerror ()); ++ ++ xpthread_barrier_wait (&barrier); ++ xpthread_join (blocked_thread); ++ ++ /* Close the modules. */ ++ for (int i = 0; i < 6; ++i) ++ xdlclose (mods[i]); ++ ++ return 0; ++} +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index eb3ef5b..ba114ab 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -442,6 +442,9 @@ struct rtld_global + EXTERN size_t _dl_tls_static_used; + /* Alignment requirement of the static TLS block. */ + EXTERN size_t _dl_tls_static_align; ++ /* Remaining amount of static TLS that may be used for optimizing ++ dynamic TLS access (e.g. with TLSDESC). */ ++ EXTERN size_t _dl_tls_static_optional; + + /* Number of additional entries in the slotinfo array of each slotinfo + list element. A large number makes it almost certain take we never +-- +1.8.3.1 + @@ -0,0 +1 @@ +78a720f17412f3c3282be5a6f3363ec6 glibc-2.31.tar.xz diff --git a/turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch b/turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch new file mode 100644 index 0000000..5b766cf --- /dev/null +++ b/turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch @@ -0,0 +1,25 @@ +From 44314a556239a7524b5a6451025737c1bdbb1cd0 Mon Sep 17 00:00:00 2001 +From: Wang Shuo <wangshuo47@huawei.com> +Date: Thu, 21 May 2020 11:23:06 +0800 +Subject: [PATCH] turn REP_STOSB_THRESHOLD from 2k to 1M + +--- + sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S +index dcd63c92..92c08eed 100644 +--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S +@@ -65,7 +65,7 @@ + Enhanced REP STOSB. Since the stored value is fixed, larger register + size has minimal impact on threshold. */ + #ifndef REP_STOSB_THRESHOLD +-# define REP_STOSB_THRESHOLD 2048 ++# define REP_STOSB_THRESHOLD 1048576 + #endif + + #ifndef SECTION +-- +2.19.1 + diff --git a/x86-64-Use-RDX_LP-on-__x86_shared_non_temporal_thres.patch b/x86-64-Use-RDX_LP-on-__x86_shared_non_temporal_thres.patch new file mode 100644 index 0000000..82f8476 --- /dev/null +++ b/x86-64-Use-RDX_LP-on-__x86_shared_non_temporal_thres.patch @@ -0,0 +1,50 @@ +From 55c7bcc71b84123d5d4bd2814366a6b05fcf8ebd Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" <hjl.tools@gmail.com> +Date: Sat, 9 May 2020 12:04:23 -0700 +Subject: [PATCH] x86-64: Use RDX_LP on __x86_shared_non_temporal_threshold [BZ + #25966] + +Since __x86_shared_non_temporal_threshold is defined as + +long int __x86_shared_non_temporal_threshold; + +and long int is 4 bytes for x32, use RDX_LP to compare against +__x86_shared_non_temporal_threshold in assembly code. +--- + sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +index c763b7d871..74953245aa 100644 +--- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +@@ -244,7 +244,7 @@ L(return): + ret + + L(movsb): +- cmpq __x86_shared_non_temporal_threshold(%rip), %rdx ++ cmp __x86_shared_non_temporal_threshold(%rip), %RDX_LP + jae L(more_8x_vec) + cmpq %rsi, %rdi + jb 1f +@@ -402,7 +402,7 @@ L(more_8x_vec): + addq %r8, %rdx + #if (defined USE_MULTIARCH || VEC_SIZE == 16) && IS_IN (libc) + /* Check non-temporal store threshold. */ +- cmpq __x86_shared_non_temporal_threshold(%rip), %rdx ++ cmp __x86_shared_non_temporal_threshold(%rip), %RDX_LP + ja L(large_forward) + #endif + L(loop_4x_vec_forward): +@@ -454,7 +454,7 @@ L(more_8x_vec_backward): + subq %r8, %rdx + #if (defined USE_MULTIARCH || VEC_SIZE == 16) && IS_IN (libc) + /* Check non-temporal store threshold. */ +- cmpq __x86_shared_non_temporal_threshold(%rip), %rdx ++ cmp __x86_shared_non_temporal_threshold(%rip), %RDX_LP + ja L(large_backward) + #endif + L(loop_4x_vec_backward): +-- +2.19.1 + diff --git a/x86_64-Use-xmmN-with-vpxor-to-clear-a-vector-registe.patch b/x86_64-Use-xmmN-with-vpxor-to-clear-a-vector-registe.patch new file mode 100644 index 0000000..a308561 --- /dev/null +++ b/x86_64-Use-xmmN-with-vpxor-to-clear-a-vector-registe.patch @@ -0,0 +1,43 @@ +From a35a59036ebae3efcdf5e8167610e0656fca9770 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" <hjl.tools@gmail.com> +Date: Thu, 11 Jun 2020 12:41:18 -0700 +Subject: [PATCH] x86_64: Use %xmmN with vpxor to clear a vector register + +Since "vpxor %xmmN, %xmmN, %xmmN" clears the whole vector register, use +%xmmN, instead of %ymmN, with vpxor to clear a vector register. +--- + sysdeps/x86_64/multiarch/strcmp-avx2.S | 4 ++-- + sysdeps/x86_64/multiarch/strrchr-avx2.S | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S +index 48d03a9f46..5f88a68262 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S +@@ -91,8 +91,8 @@ ENTRY (STRCMP) + # endif + movl %edi, %eax + xorl %edx, %edx +- /* Make %ymm7 all zeros in this function. */ +- vpxor %ymm7, %ymm7, %ymm7 ++ /* Make %xmm7 (%ymm7) all zeros in this function. */ ++ vpxor %xmm7, %xmm7, %xmm7 + orl %esi, %eax + andl $(PAGE_SIZE - 1), %eax + cmpl $(PAGE_SIZE - (VEC_SIZE * 4)), %eax +diff --git a/sysdeps/x86_64/multiarch/strrchr-avx2.S b/sysdeps/x86_64/multiarch/strrchr-avx2.S +index 23077b4c45..146bdd51d0 100644 +--- a/sysdeps/x86_64/multiarch/strrchr-avx2.S ++++ b/sysdeps/x86_64/multiarch/strrchr-avx2.S +@@ -44,7 +44,7 @@ ENTRY (STRRCHR) + movl %edi, %ecx + /* Broadcast CHAR to YMM4. */ + VPBROADCAST %xmm4, %ymm4 +- vpxor %ymm0, %ymm0, %ymm0 ++ vpxor %xmm0, %xmm0, %xmm0 + + /* Check if we may cross page boundary with one vector load. */ + andl $(2 * VEC_SIZE - 1), %ecx +-- +2.19.1 + |
