diff --git a/.openeuler/patch/upsteam-patch-config.yaml b/.openeuler/patch/upsteam-patch-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1f824ed7fa80f8fd716cde68dcac46d771d2686f --- /dev/null +++ b/.openeuler/patch/upsteam-patch-config.yaml @@ -0,0 +1,20 @@ +# .openeuler/patch/upsteam-patch-config.yaml +# 上游社区git地址, 已经有yaml描述, 这里不重复 +# openeuler社区的master分支的维护策略就是定期升级到社区最新版本, 因此不需要配置抓补丁工具; +# openeuler社区的LTS分支需要实时抓取补丁, 从上游社区的stable分支和mainline分支; + +# glibc的LTS分支看护不是很及时, 社区问题还是主要在master分支修复, 因此仅跟踪master分支; +# liqingqing最近一次跟踪补丁是在2020-10-27; 因此start_commit_id开始值选了更早的1个补丁; + +- branch: 'openEuler-20.03-LTS' # 本地需要回合补丁的分支 + period: 1 # 自动抓取周期(天) + enabled: true # 是否开启跟踪 + tracking_list: + - scm_branch: master # 上游社区跟踪的分支 + start_commit_id: dac8713629c8736a60aebec2f01657e46baa4c73 # 上游社区跟踪分支开始的commit id +- branch: 'openEuler-20.03-LTS-Next' + period: 1 + enabled: false + tracking_list: + - scm_branch: master + start_commit_id: dac8713629c8736a60aebec2f01657e46baa4c73 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 0000000000000000000000000000000000000000..09522fa248daaec9f3d5b85a7696ddbb01e67d76 --- /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 +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 @@ + # . + + 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 ++ . */ ++ ++#include ++#include ++#include ++ ++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 +-- +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 0000000000000000000000000000000000000000..25e6d57da47fb86885a4fd208a0facf4a7ac14ba --- /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 +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 +Tested-by: Carlos O'Donell +--- + 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 + #endif ++#include + + #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 + #include + #include "nss_db/nss_db.h" ++#include + + /* 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 0000000000000000000000000000000000000000..c26139f12fc95d99bf9bec65bd55ab237449124c --- /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 +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 +--- + 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 0000000000000000000000000000000000000000..d3a3d67904e8e150b7d8fc2db0f889be765b8324 --- /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 +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 0000000000000000000000000000000000000000..3d65faecc4ffe41266d1b3e44cd5bbeeba084e1c --- /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 +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 0000000000000000000000000000000000000000..a613744c23c669a40bd2f72f32c4234a1a0cf3b3 --- /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 +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 0000000000000000000000000000000000000000..996179ea2c1963260045d266d1b7781e67a9f32a --- /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 +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 0000000000000000000000000000000000000000..d88874631b8a0b3f3fdc6dbda8700482d5869034 --- /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 +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 0000000000000000000000000000000000000000..43bcf34938c16c61dd6b33884a0a52c07d88e365 --- /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 +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/LanguageList b/LanguageList index 62f1facd33b91a6d30a0599435cc3a494b6a891b..7ae63910daa934729f4218f1d525e24e70397009 100644 --- a/LanguageList +++ b/LanguageList @@ -39,6 +39,7 @@ glibc-langpack-dsb glibc-langpack-dv glibc-langpack-dz glibc-langpack-el +glibc-langpack-en glibc-langpack-eo glibc-langpack-es glibc-langpack-et @@ -191,4 +192,5 @@ glibc-langpack-yi glibc-langpack-yo glibc-langpack-yue glibc-langpack-yuw +glibc-langpack-zh glibc-langpack-zu 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 0000000000000000000000000000000000000000..b616737f44fb7fdb012dba9a945e155ee5128c0b --- /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 +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 +--- + 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* A few BIG5-HKSCS characters map in two unicode code points. ++ They are: ++ /x88/x62 => ++ /x88/x64 => ++ /x88/xa3 => ++ /x88/xa5 => ++ 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] = { ++ /* X => X */ ++ { "", "\x88\x62\x58", { 0x00CA, 0x0304, 0x0058 } }, ++ /* X => X */ ++ { "", "\x88\x64\x58", { 0x00CA, 0x030C, 0x0058 } }, ++ /* X => X */ ++ { "", "\x88\xa3\x58", { 0x00EA, 0x0304, 0x0058 } }, ++ /* X => X */ ++ { "", "\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 +-- +2.19.1 + diff --git a/build-extra-libpthreadcond-so.patch b/build-extra-libpthreadcond-so.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d80f07423b7e8d9f445e64ac1007b375c3a6c86 --- /dev/null +++ b/build-extra-libpthreadcond-so.patch @@ -0,0 +1,4935 @@ +From 808cf7c45e187c1889867ac83d047abfdf81c7a3 Mon Sep 17 00:00:00 2001 +From: root +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 ++ . */ ++ ++#ifndef _BITS_PTHREADTYPES_COMMON_H ++# define _BITS_PTHREADTYPES_COMMON_H 1 ++ ++/* For internal mutex and condition variable definitions. */ ++#include ++ ++/* 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 ++ . */ ++ ++#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 ++ ++ ++/* 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 ++ ++/* 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 ++ ++ ++/* 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 , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include "pthreadP_2_17.h" ++#include ++#include ++#include ++ ++ ++/* 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 , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include "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 , 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 ++ . */ ++ ++#ifndef _PTHREADP_H ++#define _PTHREADP_H 1 ++ ++#include ++#include ++#include ++#include ++#include "descr.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 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 ++ . */ ++ ++#ifndef _PTHREAD_H ++#define _PTHREAD_H 1 ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* 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 , 2003. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++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 , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include "pthreadP_2_17.h" ++#include ++#include ++#include ++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 , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include "pthreadP_2_17.h" ++#include ++#include ++ ++ ++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 , 2003. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++ ++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 , 2003. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifndef HAVE_CLOCK_GETTIME_VSYSCALL ++# undef INTERNAL_VSYSCALL ++# define INTERNAL_VSYSCALL INTERNAL_SYSCALL ++# undef INLINE_VSYSCALL ++# define INLINE_VSYSCALL INLINE_SYSCALL ++#else ++# include ++#endif ++ ++/* Cleanup handler, defined in pthread_cond_wait.c. */ ++extern void __condvar_cleanup (void *arg) ++ __attribute__ ((visibility ("hidden"))); ++ ++struct _condvar_cleanup_buffer ++{ ++ int oldtype; ++ pthread_cond_t *cond; ++ pthread_mutex_t *mutex; ++ unsigned int bc_seq; ++}; ++ ++int ++__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, ++ const struct timespec *abstime) ++{ ++ struct _pthread_cleanup_buffer buffer; ++ struct _condvar_cleanup_buffer cbuffer; ++ int result = 0; ++ ++ /* Catch invalid parameters. */ ++ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) ++ return EINVAL; ++ ++ int pshared = (cond->__data.__mutex == (void *) ~0l) ++ ? LLL_SHARED : LLL_PRIVATE; ++ ++#if (defined lll_futex_timed_wait_requeue_pi \ ++ && defined __ASSUME_REQUEUE_PI) ++ int pi_flag = 0; ++#endif ++ ++ /* Make sure we are alone. */ ++ lll_lock (cond->__data.__lock, pshared); ++ ++ /* Now we can release the mutex. */ ++ int err = __pthread_mutex_unlock_usercnt (mutex, 0); ++ if (err) ++ { ++ lll_unlock (cond->__data.__lock, pshared); ++ return err; ++ } ++ ++ /* We have one new user of the condvar. */ ++ ++cond->__data.__total_seq; ++ ++cond->__data.__futex; ++ cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT; ++ ++ /* Work around the fact that the kernel rejects negative timeout values ++ despite them being valid. */ ++ if (__glibc_unlikely (abstime->tv_sec < 0)) ++ goto timeout; ++ ++ /* Remember the mutex we are using here. If there is already a ++ different address store this is a bad user bug. Do not store ++ anything for pshared condvars. */ ++ if (cond->__data.__mutex != (void *) ~0l) ++ cond->__data.__mutex = mutex; ++ ++ /* Prepare structure passed to cancellation handler. */ ++ cbuffer.cond = cond; ++ cbuffer.mutex = mutex; ++ ++ /* Before we block we enable cancellation. Therefore we have to ++ install a cancellation handler. */ ++ __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); ++ ++ /* The current values of the wakeup counter. The "woken" counter ++ must exceed this value. */ ++ unsigned long long int val; ++ unsigned long long int seq; ++ val = seq = cond->__data.__wakeup_seq; ++ /* Remember the broadcast counter. */ ++ cbuffer.bc_seq = cond->__data.__broadcast_seq; ++ ++ while (1) ++ { ++#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ ++ || !defined lll_futex_timed_wait_bitset) ++ struct timespec rt; ++ { ++# ifdef __NR_clock_gettime ++ INTERNAL_SYSCALL_DECL (err); ++ (void) INTERNAL_VSYSCALL (clock_gettime, err, 2, ++ (cond->__data.__nwaiters ++ & ((1 << COND_NWAITERS_SHIFT) - 1)), ++ &rt); ++ /* Convert the absolute timeout value to a relative timeout. */ ++ rt.tv_sec = abstime->tv_sec - rt.tv_sec; ++ rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec; ++# else ++ /* Get the current time. So far we support only one clock. */ ++ struct timeval tv; ++ (void) __gettimeofday (&tv, NULL); ++ ++ /* Convert the absolute timeout value to a relative timeout. */ ++ rt.tv_sec = abstime->tv_sec - tv.tv_sec; ++ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; ++# endif ++ } ++ if (rt.tv_nsec < 0) ++ { ++ rt.tv_nsec += 1000000000; ++ --rt.tv_sec; ++ } ++ /* Did we already time out? */ ++ if (__glibc_unlikely (rt.tv_sec < 0)) ++ { ++ if (cbuffer.bc_seq != cond->__data.__broadcast_seq) ++ goto bc_out; ++ ++ goto timeout; ++ } ++#endif ++ ++ unsigned int futex_val = cond->__data.__futex; ++ ++ /* Prepare to wait. Release the condvar futex. */ ++ lll_unlock (cond->__data.__lock, pshared); ++ ++ /* Enable asynchronous cancellation. Required by the standard. */ ++ cbuffer.oldtype = __pthread_enable_asynccancel (); ++ ++/* REQUEUE_PI was implemented after FUTEX_CLOCK_REALTIME, so it is sufficient ++ to check just the former. */ ++#if (defined lll_futex_timed_wait_requeue_pi \ ++ && defined __ASSUME_REQUEUE_PI) ++ /* If pi_flag remained 1 then it means that we had the lock and the mutex ++ but a spurious waker raced ahead of us. Give back the mutex before ++ going into wait again. */ ++ if (pi_flag) ++ { ++ __pthread_mutex_cond_lock_adjust (mutex); ++ __pthread_mutex_unlock_usercnt (mutex, 0); ++ } ++ pi_flag = USE_REQUEUE_PI (mutex); ++ ++ if (pi_flag) ++ { ++ unsigned int clockbit = (cond->__data.__nwaiters & 1 ++ ? 0 : FUTEX_CLOCK_REALTIME); ++ err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex, ++ futex_val, abstime, clockbit, ++ &mutex->__data.__lock, ++ pshared); ++ pi_flag = (err == 0); ++ } ++ else ++#endif ++ ++ { ++#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ ++ || !defined lll_futex_timed_wait_bitset) ++ /* Wait until woken by signal or broadcast. */ ++ err = lll_futex_timed_wait (&cond->__data.__futex, ++ futex_val, &rt, pshared); ++#else ++ unsigned int clockbit = (cond->__data.__nwaiters & 1 ++ ? 0 : FUTEX_CLOCK_REALTIME); ++ err = lll_futex_timed_wait_bitset (&cond->__data.__futex, futex_val, ++ abstime, clockbit, pshared); ++#endif ++ } ++ ++ /* Disable asynchronous cancellation. */ ++ __pthread_disable_asynccancel (cbuffer.oldtype); ++ ++ /* We are going to look at shared data again, so get the lock. */ ++ lll_lock (cond->__data.__lock, pshared); ++ ++ /* If a broadcast happened, we are done. */ ++ if (cbuffer.bc_seq != cond->__data.__broadcast_seq) ++ goto bc_out; ++ ++ /* Check whether we are eligible for wakeup. */ ++ val = cond->__data.__wakeup_seq; ++ if (val != seq && cond->__data.__woken_seq != val) ++ break; ++ ++ /* Not woken yet. Maybe the time expired? */ ++ if (__glibc_unlikely (err == -ETIMEDOUT)) ++ { ++ timeout: ++ /* Yep. Adjust the counters. */ ++ ++cond->__data.__wakeup_seq; ++ ++cond->__data.__futex; ++ ++ /* The error value. */ ++ result = ETIMEDOUT; ++ break; ++ } ++ } ++ ++ /* Another thread woken up. */ ++ ++cond->__data.__woken_seq; ++ ++ bc_out: ++ ++ cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT; ++ ++ /* If pthread_cond_destroy was called on this variable already, ++ notify the pthread_cond_destroy caller all waiters have left ++ and it can be successfully destroyed. */ ++ if (cond->__data.__total_seq == -1ULL ++ && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT)) ++ lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); ++ ++ /* We are done with the condvar. */ ++ lll_unlock (cond->__data.__lock, pshared); ++ ++ /* The cancellation handling is back to normal, remove the handler. */ ++ __pthread_cleanup_pop (&buffer, 0); ++ ++ /* Get the mutex before returning. */ ++#if (defined lll_futex_timed_wait_requeue_pi \ ++ && defined __ASSUME_REQUEUE_PI) ++ if (pi_flag) ++ { ++ __pthread_mutex_cond_lock_adjust (mutex); ++ err = 0; ++ } ++ else ++#endif ++ err = __pthread_mutex_cond_lock (mutex); ++ ++ return err ?: result; ++} ++ ++versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, ++ GLIBC_2_3_2); +diff --git a/nptl_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 , 2003. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 , 2003. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include "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 , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include "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 , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include "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 , 2003. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "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 ++ ++#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 +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 , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include "pthreadP_2_17.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include "pthreadP_2_17.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 , 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 ++ . */ ++ ++#ifndef _INTERNALTYPES_H ++#define _INTERNALTYPES_H 1 ++ ++#include ++#include ++#include ++ ++ ++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 , 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++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 ++ and Richard Henderson , 2003. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include "pthreadP_2_17.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++/* 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/build-locale-archive.c b/build-locale-archive.c deleted file mode 100644 index 9183972375dbd1e4239fc52c955d1c210de60d42..0000000000000000000000000000000000000000 --- a/build-locale-archive.c +++ /dev/null @@ -1,862 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../locale/hashval.h" -#define __LC_LAST 13 -#include "../locale/locarchive.h" -#include "../crypt/md5.h" - -const char *alias_file = DATADIR "/locale/locale.alias"; -const char *locar_file = PREFIX "/lib/locale/locale-archive"; -const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl"; -const char *loc_path = PREFIX "/lib/locale/"; -/* Flags set by `--verbose` option. */ -int be_quiet = 1; -int verbose = 0; -int max_locarchive_open_retry = 10; -const char *output_prefix; - -/* Endianness should have been taken care of by localedef. We don't need to do - additional swapping. We need this variable exported however, since - locarchive.c uses it to determine if it needs to swap endianness of a value - before writing to or reading from the archive. */ -bool swap_endianness_p = false; - -static const char *locnames[] = - { -#define DEFINE_CATEGORY(category, category_name, items, a) \ - [category] = category_name, -#include "../locale/categories.def" -#undef DEFINE_CATEGORY - }; - -static int -is_prime (unsigned long candidate) -{ - /* No even number and none less than 10 will be passed here. */ - unsigned long int divn = 3; - unsigned long int sq = divn * divn; - - while (sq < candidate && candidate % divn != 0) - { - ++divn; - sq += 4 * divn; - ++divn; - } - - return candidate % divn != 0; -} - -unsigned long -next_prime (unsigned long seed) -{ - /* Make it definitely odd. */ - seed |= 1; - - while (!is_prime (seed)) - seed += 2; - - return seed; -} - -void -error (int status, int errnum, const char *message, ...) -{ - va_list args; - - va_start (args, message); - fflush (stdout); - fprintf (stderr, "%s: ", program_invocation_name); - vfprintf (stderr, message, args); - va_end (args); - if (errnum) - fprintf (stderr, ": %s", strerror (errnum)); - putc ('\n', stderr); - fflush (stderr); - if (status) - exit (errnum == EROFS ? 0 : status); -} - -void * -xmalloc (size_t size) -{ - void *p = malloc (size); - if (p == NULL) - error (EXIT_FAILURE, errno, "could not allocate %zd bytes of memory", size); - return p; -} - -static void -open_tmpl_archive (struct locarhandle *ah) -{ - struct stat64 st; - int fd; - struct locarhead head; - const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname; - - /* Open the archive. We must have exclusive write access. */ - fd = open64 (archivefname, O_RDONLY); - if (fd == -1) - error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"", - archivefname); - - if (fstat64 (fd, &st) < 0) - error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"", - archivefname); - - /* Read the header. */ - if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head)) - error (EXIT_FAILURE, errno, "cannot read archive header"); - - ah->fd = fd; - ah->mmaped = (head.sumhash_offset - + head.sumhash_size * sizeof (struct sumhashent)); - if (ah->mmaped > (unsigned long) st.st_size) - error (EXIT_FAILURE, 0, "locale archive template file truncated"); - ah->mmaped = st.st_size; - ah->reserved = st.st_size; - - /* Now we know how large the administrative information part is. - Map all of it. */ - ah->addr = mmap64 (NULL, ah->mmaped, PROT_READ, MAP_SHARED, fd, 0); - if (ah->addr == MAP_FAILED) - error (EXIT_FAILURE, errno, "cannot map archive header"); -} - -/* Open the locale archive. */ -extern void open_archive (struct locarhandle *ah, bool readonly); - -/* Close the locale archive. */ -extern void close_archive (struct locarhandle *ah); - -/* Add given locale data to the archive. */ -extern int add_locale_to_archive (struct locarhandle *ah, const char *name, - locale_data_t data, bool replace); - -extern void add_alias (struct locarhandle *ah, const char *alias, - bool replace, const char *oldname, - uint32_t *locrec_offset_p); - -extern struct namehashent * -insert_name (struct locarhandle *ah, - const char *name, size_t name_len, bool replace); - -struct nameent -{ - char *name; - struct locrecent *locrec; -}; - -struct dataent -{ - const unsigned char *sum; - uint32_t file_offset; -}; - -static int -nameentcmp (const void *a, const void *b) -{ - struct locrecent *la = ((const struct nameent *) a)->locrec; - struct locrecent *lb = ((const struct nameent *) b)->locrec; - uint32_t start_a = -1, end_a = 0; - uint32_t start_b = -1, end_b = 0; - int cnt; - - for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) - { - if (la->record[cnt].offset < start_a) - start_a = la->record[cnt].offset; - if (la->record[cnt].offset + la->record[cnt].len > end_a) - end_a = la->record[cnt].offset + la->record[cnt].len; - } - assert (start_a != (uint32_t)-1); - assert (end_a != 0); - - for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) - { - if (lb->record[cnt].offset < start_b) - start_b = lb->record[cnt].offset; - if (lb->record[cnt].offset + lb->record[cnt].len > end_b) - end_b = lb->record[cnt].offset + lb->record[cnt].len; - } - assert (start_b != (uint32_t)-1); - assert (end_b != 0); - - if (start_a != start_b) - return (int)start_a - (int)start_b; - return (int)end_a - (int)end_b; -} - -static int -dataentcmp (const void *a, const void *b) -{ - if (((const struct dataent *) a)->file_offset - < ((const struct dataent *) b)->file_offset) - return -1; - - if (((const struct dataent *) a)->file_offset - > ((const struct dataent *) b)->file_offset) - return 1; - - return 0; -} - -static int -sumsearchfn (const void *key, const void *ent) -{ - uint32_t keyn = *(uint32_t *)key; - uint32_t entn = ((struct dataent *)ent)->file_offset; - - if (keyn < entn) - return -1; - if (keyn > entn) - return 1; - return 0; -} - -static void -compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused, - struct dataent *files, locale_data_t data) -{ - int cnt; - struct locrecent *locrec = name->locrec; - struct dataent *file; - data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset; - data[LC_ALL].size = locrec->record[LC_ALL].len; - for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) - { - data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset; - data[cnt].size = locrec->record[cnt].len; - if (data[cnt].addr >= data[LC_ALL].addr - && data[cnt].addr + data[cnt].size - <= data[LC_ALL].addr + data[LC_ALL].size) - __md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum); - else - { - file = bsearch (&locrec->record[cnt].offset, files, sumused, - sizeof (*files), sumsearchfn); - if (file == NULL) - error (EXIT_FAILURE, 0, "inconsistent template file"); - memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum)); - } - } -} - -static int -fill_archive (struct locarhandle *tmpl_ah, - const char *fname, - size_t install_langs_count, char *install_langs_list[], - size_t nlist, char *list[], - const char *primary) -{ - struct locarhandle ah; - struct locarhead *head; - int result = 0; - struct nameent *names; - struct namehashent *namehashtab; - size_t cnt, used; - struct dataent *files; - struct sumhashent *sumhashtab; - size_t sumused; - struct locrecent *primary_locrec = NULL; - struct nameent *primary_nameent = NULL; - - head = tmpl_ah->addr; - names = (struct nameent *) malloc (head->namehash_used - * sizeof (struct nameent)); - files = (struct dataent *) malloc (head->sumhash_used - * sizeof (struct dataent)); - if (names == NULL || files == NULL) - error (EXIT_FAILURE, errno, "could not allocate tables"); - - namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr - + head->namehash_offset); - sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr - + head->sumhash_offset); - - for (cnt = used = 0; cnt < head->namehash_size; ++cnt) - if (namehashtab[cnt].locrec_offset != 0) - { - char * name; - int i; - assert (used < head->namehash_used); - name = tmpl_ah->addr + namehashtab[cnt].name_offset; - if (install_langs_count == 0) - { - /* Always intstall the entry. */ - names[used].name = name; - names[used++].locrec - = (struct locrecent *) ((char *) tmpl_ah->addr + - namehashtab[cnt].locrec_offset); - } - else - { - /* Only install the entry if the user asked for it via - --install-langs. */ - for (i = 0; i < install_langs_count; i++) - { - /* Add one for "_" and one for the null terminator. */ - size_t len = strlen (install_langs_list[i]) + 2; - char *install_lang = (char *)xmalloc (len); - strcpy (install_lang, install_langs_list[i]); - if (strchr (install_lang, '_') == NULL) - strcat (install_lang, "_"); - if (strncmp (name, install_lang, strlen (install_lang)) == 0) - { - names[used].name = name; - names[used++].locrec - = (struct locrecent *) ((char *)tmpl_ah->addr - + namehashtab[cnt].locrec_offset); - } - free (install_lang); - } - } - } - - /* Sort the names. */ - qsort (names, used, sizeof (struct nameent), nameentcmp); - - for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt) - if (sumhashtab[cnt].file_offset != 0) - { - assert (sumused < head->sumhash_used); - files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum; - files[sumused++].file_offset = sumhashtab[cnt].file_offset; - } - - /* Sort by file locations. */ - qsort (files, sumused, sizeof (struct dataent), dataentcmp); - - /* Open the archive. This call never returns if we cannot - successfully open the archive. */ - ah.fname = NULL; - if (fname != NULL) - ah.fname = fname; - open_archive (&ah, false); - - if (primary != NULL) - { - for (cnt = 0; cnt < used; ++cnt) - if (strcmp (names[cnt].name, primary) == 0) - break; - if (cnt < used) - { - locale_data_t data; - - compute_data (tmpl_ah, &names[cnt], sumused, files, data); - result |= add_locale_to_archive (&ah, primary, data, 0); - primary_locrec = names[cnt].locrec; - primary_nameent = &names[cnt]; - } - } - - for (cnt = 0; cnt < used; ++cnt) - if (&names[cnt] == primary_nameent) - continue; - else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec) - || names[cnt].locrec == primary_locrec) - { - const char *oldname; - struct namehashent *namehashent; - uint32_t locrec_offset; - - if (names[cnt].locrec == primary_locrec) - oldname = primary; - else - oldname = names[cnt - 1].name; - namehashent = insert_name (&ah, oldname, strlen (oldname), true); - assert (namehashent->name_offset != 0); - assert (namehashent->locrec_offset != 0); - locrec_offset = namehashent->locrec_offset; - add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset); - } - else - { - locale_data_t data; - - compute_data (tmpl_ah, &names[cnt], sumused, files, data); - result |= add_locale_to_archive (&ah, names[cnt].name, data, 0); - } - - while (nlist-- > 0) - { - const char *fname = *list++; - size_t fnamelen = strlen (fname); - struct stat64 st; - DIR *dirp; - struct dirent64 *d; - int seen; - locale_data_t data; - int cnt; - - /* First see whether this really is a directory and whether it - contains all the require locale category files. */ - if (stat64 (fname, &st) < 0) - { - error (0, 0, "stat of \"%s\" failed: %s: ignored", fname, - strerror (errno)); - continue; - } - if (!S_ISDIR (st.st_mode)) - { - error (0, 0, "\"%s\" is no directory; ignored", fname); - continue; - } - - dirp = opendir (fname); - if (dirp == NULL) - { - error (0, 0, "cannot open directory \"%s\": %s: ignored", - fname, strerror (errno)); - continue; - } - - seen = 0; - while ((d = readdir64 (dirp)) != NULL) - { - for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) - if (strcmp (d->d_name, locnames[cnt]) == 0) - { - unsigned char d_type; - - /* We have an object of the required name. If it's - a directory we have to look at a file with the - prefix "SYS_". Otherwise we have found what we - are looking for. */ -#ifdef _DIRENT_HAVE_D_TYPE - d_type = d->d_type; - - if (d_type != DT_REG) -#endif - { - char fullname[fnamelen + 2 * strlen (d->d_name) + 7]; - -#ifdef _DIRENT_HAVE_D_TYPE - if (d_type == DT_UNKNOWN) -#endif - { - strcpy (stpcpy (stpcpy (fullname, fname), "/"), - d->d_name); - - if (stat64 (fullname, &st) == -1) - /* We cannot stat the file, ignore it. */ - break; - - d_type = IFTODT (st.st_mode); - } - - if (d_type == DT_DIR) - { - /* We have to do more tests. The file is a - directory and it therefore must contain a - regular file with the same name except a - "SYS_" prefix. */ - char *t = stpcpy (stpcpy (fullname, fname), "/"); - strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"), - d->d_name); - - if (stat64 (fullname, &st) == -1) - /* There is no SYS_* file or we cannot - access it. */ - break; - - d_type = IFTODT (st.st_mode); - } - } - - /* If we found a regular file (eventually after - following a symlink) we are successful. */ - if (d_type == DT_REG) - ++seen; - break; - } - } - - closedir (dirp); - - if (seen != __LC_LAST - 1) - { - /* We don't have all locale category files. Ignore the name. */ - error (0, 0, "incomplete set of locale files in \"%s\"", - fname); - continue; - } - - /* Add the files to the archive. To do this we first compute - sizes and the MD5 sums of all the files. */ - for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) - { - char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7]; - int fd; - - strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]); - fd = open64 (fullname, O_RDONLY); - if (fd == -1 || fstat64 (fd, &st) == -1) - { - /* Cannot read the file. */ - if (fd != -1) - close (fd); - break; - } - - if (S_ISDIR (st.st_mode)) - { - char *t; - close (fd); - t = stpcpy (stpcpy (fullname, fname), "/"); - strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"), - locnames[cnt]); - - fd = open64 (fullname, O_RDONLY); - if (fd == -1 || fstat64 (fd, &st) == -1 - || !S_ISREG (st.st_mode)) - { - if (fd != -1) - close (fd); - break; - } - } - - /* Map the file. */ - data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED, - fd, 0); - if (data[cnt].addr == MAP_FAILED) - { - /* Cannot map it. */ - close (fd); - break; - } - - data[cnt].size = st.st_size; - __md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum); - - /* We don't need the file descriptor anymore. */ - close (fd); - } - - if (cnt != __LC_LAST) - { - while (cnt-- > 0) - if (cnt != LC_ALL) - munmap (data[cnt].addr, data[cnt].size); - - error (0, 0, "cannot read all files in \"%s\": ignored", fname); - - continue; - } - - result |= add_locale_to_archive (&ah, basename (fname), data, 0); - - for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) - munmap (data[cnt].addr, data[cnt].size); - } - - /* We are done. */ - close_archive (&ah); - - return result; -} - -void usage() -{ - printf ("\ -Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\ - Builds a locale archive from a template file.\n\ - Options:\n\ - -h, --help Print this usage message.\n\ - -v, --verbose Verbose execution.\n\ - -l, --install-langs=LIST Only include locales given in LIST into the \n\ - locale archive. LIST is a colon separated list\n\ - of locale prefixes, for example \"de:en:ja\".\n\ - The special argument \"all\" means to install\n\ - all languages and it must be present by itself.\n\ - If \"all\" is present with any other language it\n\ - will be treated as the name of a locale.\n\ - If the --install-langs option is missing, all\n\ - locales are installed. The colon separated list\n\ - can contain any strings matching the beginning of\n\ - locale names.\n\ - If a string does not contain a \"_\", it is added.\n\ - Examples:\n\ - --install-langs=\"en\"\n\ - installs en_US, en_US.iso88591,\n\ - en_US.iso885915, en_US.utf8,\n\ - en_GB ...\n\ - --install-langs=\"en_US.utf8\"\n\ - installs only en_US.utf8.\n\ - --install-langs=\"ko\"\n\ - installs ko_KR, ko_KR.euckr,\n\ - ko_KR.utf8 but *not* kok_IN\n\ - because \"ko\" does not contain\n\ - \"_\" and it is silently added\n\ - --install-langs\"ko:kok\"\n\ - installs ko_KR, ko_KR.euckr,\n\ - ko_KR.utf8, kok_IN, and\n\ - kok_IN.utf8.\n\ - --install-langs=\"POSIX\" will\n\ - installs *no* locales at all\n\ - because POSIX matches none of\n\ - the locales. Actually, any string\n\ - matching nothing will do that.\n\ - POSIX and C will always be\n\ - available because they are\n\ - builtin.\n\ - Aliases are installed as well,\n\ - i.e. --install-langs=\"de\"\n\ - will install not only every locale starting with\n\ - \"de\" but also the aliases \"deutsch\"\n\ - and and \"german\" although the latter does not\n\ - start with \"de\".\n\ -\n\ - If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\ - where the glibc used expects these files are used by default.\n\ -"); -} - -int main (int argc, char *argv[]) -{ - char path[4096]; - DIR *dirp; - struct dirent64 *d; - struct stat64 st; - char *list[16384], *primary; - char *lang; - int install_langs_count = 0; - int i; - char *install_langs_arg, *ila_start; - char **install_langs_list = NULL; - unsigned int cnt = 0; - struct locarhandle tmpl_ah; - char *new_locar_fname = NULL; - size_t loc_path_len = strlen (loc_path); - - while (1) - { - int c; - - static struct option long_options[] = - { - {"help", no_argument, 0, 'h'}, - {"verbose", no_argument, 0, 'v'}, - {"install-langs", required_argument, 0, 'l'}, - {0, 0, 0, 0} - }; - /* getopt_long stores the option index here. */ - int option_index = 0; - - c = getopt_long (argc, argv, "vhl:", - long_options, &option_index); - - /* Detect the end of the options. */ - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("unknown option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - usage (); - exit (1); - - case 'v': - verbose = 1; - be_quiet = 0; - break; - - case 'h': - usage (); - exit (0); - - case 'l': - install_langs_arg = ila_start = strdup (optarg); - /* If the argument to --install-lang is "all", do - not limit the list of languages to install and install - them all. We do not support installing a single locale - called "all". */ -#define MAGIC_INSTALL_ALL "all" - if (install_langs_arg != NULL - && install_langs_arg[0] != '\0' - && !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL, - strlen(MAGIC_INSTALL_ALL)) == 0 - && strlen (install_langs_arg) == 3)) - { - /* Count the number of languages we will install. */ - while (true) - { - lang = strtok(install_langs_arg, ":;,"); - if (lang == NULL) - break; - install_langs_count++; - install_langs_arg = NULL; - } - free (ila_start); - - /* Reject an entire string made up of delimiters. */ - if (install_langs_count == 0) - break; - - /* Copy the list. */ - install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count); - install_langs_arg = ila_start = strdup (optarg); - install_langs_count = 0; - while (true) - { - lang = strtok(install_langs_arg, ":;,"); - if (lang == NULL) - break; - install_langs_list[install_langs_count] = lang; - install_langs_count++; - install_langs_arg = NULL; - } - } - break; - - case '?': - /* getopt_long already printed an error message. */ - usage (); - exit (0); - - default: - abort (); - } - } - tmpl_ah.fname = NULL; - if (optind < argc) - tmpl_ah.fname = argv[optind]; - if (optind + 1 < argc) - new_locar_fname = argv[optind + 1]; - if (verbose) - { - if (tmpl_ah.fname) - printf("input archive file specified on command line: %s\n", - tmpl_ah.fname); - else - printf("using default input archive file.\n"); - if (new_locar_fname) - printf("output archive file specified on command line: %s\n", - new_locar_fname); - else - printf("using default output archive file.\n"); - } - - dirp = opendir (loc_path); - if (dirp == NULL) - error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path); - - open_tmpl_archive (&tmpl_ah); - - if (new_locar_fname) - unlink (new_locar_fname); - else - unlink (locar_file); - primary = getenv ("LC_ALL"); - if (primary == NULL) - primary = getenv ("LANG"); - if (primary != NULL) - { - if (strncmp (primary, "ja", 2) != 0 - && strncmp (primary, "ko", 2) != 0 - && strncmp (primary, "zh", 2) != 0) - { - char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q; - /* This leads to invalid locales sometimes: - de_DE.iso885915@euro -> de_DE.utf8@euro */ - if (ptr != NULL) - { - p = ptr; - q = primary; - while (*q && *q != '.' && *q != '@') - *p++ = *q++; - if (*q == '.') - while (*q && *q != '@') - q++; - p = stpcpy (p, ".utf8"); - strcpy (p, q); - primary = ptr; - } - else - primary = NULL; - } - } - - memcpy (path, loc_path, loc_path_len); - - while ((d = readdir64 (dirp)) != NULL) - { - if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0) - continue; - if (strchr (d->d_name, '_') == NULL) - continue; - - size_t d_name_len = strlen (d->d_name); - if (loc_path_len + d_name_len + 1 > sizeof (path)) - { - error (0, 0, "too long filename \"%s\"", d->d_name); - continue; - } - - memcpy (path + loc_path_len, d->d_name, d_name_len + 1); - if (stat64 (path, &st) < 0) - { - error (0, errno, "cannot stat \"%s\"", path); - continue; - } - if (! S_ISDIR (st.st_mode)) - continue; - if (cnt == 16384) - { - error (0, 0, "too many directories in \"%s\"", loc_path); - break; - } - list[cnt] = strdup (path); - if (list[cnt] == NULL) - { - error (0, errno, "cannot add file to list \"%s\"", path); - continue; - } - if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0) - { - char *p = list[0]; - list[0] = list[cnt]; - list[cnt] = p; - } - cnt++; - } - closedir (dirp); - /* Store the archive to the file specified as the second argument on the - command line or the default locale archive. */ - fill_archive (&tmpl_ah, new_locar_fname, - install_langs_count, install_langs_list, - cnt, list, primary); - close_archive (&tmpl_ah); - truncate (tmpl_file, 0); - if (install_langs_count > 0) - { - free (ila_start); - free (install_langs_list); - } - char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL }; - execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]); - exit (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 0000000000000000000000000000000000000000..1ccebcc7acf5de1724e075e2c12c47ce74523869 --- /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 +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/glibc-1070416.patch b/glibc-1070416.patch new file mode 100644 index 0000000000000000000000000000000000000000..0975e0fa98e39c499f61f933d5c2040c54d5835c --- /dev/null +++ b/glibc-1070416.patch @@ -0,0 +1,38 @@ +Short description: Add syslog.target dependency. +Author(s): Fedora glibc team +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-2.28.tar.xz b/glibc-2.31.tar.xz similarity index 63% rename from glibc-2.28.tar.xz rename to glibc-2.31.tar.xz index ab67c77a436727f53dd5ff5e0c2b7d3a73eccd4a..366e70ca3f7be20a3ac4142c853a890d9eb296a8 100644 Binary files a/glibc-2.28.tar.xz and b/glibc-2.31.tar.xz differ diff --git a/glibc-c-utf8-locale.patch b/glibc-c-utf8-locale.patch new file mode 100644 index 0000000000000000000000000000000000000000..a4cf357a24cf0d111cb6ab2a812d1b4da9eb7878 --- /dev/null +++ b/glibc-c-utf8-locale.patch @@ -0,0 +1,286 @@ +Short description: Add C.UTF-8 support. +Author(s): Fedora glibc team +Origin: PATCH +Upstream status: not-submitted + +This patch needs to upstream as part of Carlos O'Donell +'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 +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 ++ ++.. ++ ++ ++.. ++ ++ ++.. ++ ++ ++.. ++ ++ ++.. ++ ++ ++.. ++ ++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 "" ++% Using "$" for currency_symbol. But maybe would be better? ++% U+00A4 is the "generic currency symbol" ++% (https://en.wikipedia.org/wiki/Currency_sign_%28typography%29) ++currency_symbol "" ++mon_decimal_point "" ++mon_thousands_sep "" ++mon_grouping -1 ++positive_sign "" ++negative_sign "" ++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 "" ++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 "";"";/ ++ "";"";/ ++ "";"";/ ++ "" ++ ++% Full weekday names (%A) ++day "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "" ++ ++% Abbreviated month names (%b) ++abmon "";"";/ ++ "";"";/ ++ "";"";/ ++ "";"";/ ++ "";"";/ ++ "";"" ++ ++% Full month names (%B) ++mon "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "" ++ ++% 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 "" ++ ++% Appropriate date representation (%x) ++% "%m/%d/%y" ++d_fmt "" ++ ++% Appropriate time representation (%X) ++% "%H:%M:%S" ++t_fmt "" ++ ++% Appropriate AM/PM time representation (%r) ++% "%I:%M:%S %p" ++t_fmt_ampm "" ++ ++% Equivalent of AM/PM (%p) "AM"/"PM" ++% ++am_pm "";"" ++ ++% Appropriate date representation (date(1)) "%a %b %e %H:%M:%S %Z %Y" ++date_fmt "" ++END LC_TIME ++ ++LC_MESSAGES ++% This is the POSIX Locale definition for ++% the LC_NUMERIC category. ++% ++yesexpr "" ++noexpr "" ++yesstr "" ++nostr "" ++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 "/ ++" ++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 "/ ++/ ++/ ++/ ++" ++END LC_ADDRESS ++ ++LC_TELEPHONE ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_TELEPHONE category. ++% "+%c %a %l" ++tel_int_fmt "/ ++" ++% (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 index 1dc2725b7b569d2578c2c6939def64bf827d7796..0fa0e027e3a4b102528b064d3acc411adf676ca8 100644 --- a/glibc.spec +++ b/glibc.spec @@ -26,11 +26,12 @@ # - Run smoke tests with valgrind to verify dynamic loader. # - Default: Always run valgrind tests if there is architecture support. ############################################################################## -%bcond_with testsuite +%bcond_without testsuite %bcond_without benchtests %bcond_with bootstrap %bcond_without werror %bcond_without docs +%bcond_with libpthreadcond %ifarch %{valgrind_arches} %bcond_without valgrind @@ -58,22 +59,44 @@ # glibc - The GNU C Library (glibc) core package. ############################################################################## Name: glibc -Version: 2.28 -Release: 36 +Version: 2.31 +Release: 7 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: build-locale-archive.c -Source2: nscd.conf -Source3: nsswitch.conf -Source4: bench.mk -Source5: glibc-bench-compare +Source1: nscd.conf +Source2: nsswitch.conf +Source3: bench.mk +Source4: glibc-bench-compare +Source5: LanguageList Source6: LicenseList -Source7: LanguageList -Patch0: Fix-use-after-free-in-glob-when-expanding-user-bug-2.patch +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 + +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) @@ -110,7 +133,7 @@ BuildRequires: gcc-c++ libstdc++-static glibc-devel libidn2 Requires: glibc-common = %{version}-%{release} Requires: glibc-langpack = %{version}-%{release} -Requires(pre): basesystem +Requires: basesystem %description The GNU C Library project provides the core libraries for the GNU system and @@ -158,14 +181,15 @@ 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("%{SOURCE7}")) do +for line in io.lines(rpm.expand("%{SOURCE5}")) do print(rpm.expand([[ Provides:]]..line..[[ = %{version}-%{release} -Obsoletes:]]..line..[[ +Obsoletes:]]..line..[[ = 2.28 ]])) end } @@ -196,7 +220,8 @@ Requires: %{name} = %{version}-%{release} Requires: libgcc%{_isa} Requires(pre): info Requires(pre): kernel-headers -Requires: kernel-headers >= 2.2.1 +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 @@ -209,8 +234,8 @@ Provides: %{name}-headers = %{version}-%{release} Provides: %{name}-headers(%{_target_cpu}) Provides: %{name}-headers%{_isa} = %{version}-%{release} -Obsoletes: %{name}-static -Obsoletes: %{name}-headers +Obsoletes: %{name}-static = 2.28 +Obsoletes: %{name}-headers = 2.28 %description devel The glibc-devel package contains the object files necessary for developing @@ -245,7 +270,7 @@ 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 nss_hesiod +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 @@ -296,19 +321,47 @@ to run microbenchmark tests on the system. %package debugutils Summary: debug files for %{name} Requires: %{name} = %{version}-%{release} -Requires: %{name}-debuginfo = %{version}-%{release} - -Provides: %{name}-debuginfo = %{version}-%{release} -Provides: %{name}-debuginfo%{_isa} = %{version}-%{release} Provides: %{name}-utils = %{version}-%{release} Provides: %{name}-utils%{_isa} = %{version}-%{release} -Obsoletes: %{name}-utils +Obsoletes: %{name}-utils = 2.28 %description debugutils -This package provides many static files for debug. Besides, It contain memusage, -a memory usage profiler, mtrace, a memory leak tracer and xtrace, a function -call tracer, all of which is not necessory for you. +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 @@ -341,6 +394,7 @@ touch locale/programs/*-kw.h %build BuildFlags="-O2 -g" +BuildFlags="$BuildFlags -DNDEBUG" reference=" \ "-Wp,-D_GLIBCXX_ASSERTIONS" \ "-fasynchronous-unwind-tables" \ @@ -349,6 +403,7 @@ reference=" \ "-m31" \ "-m32" \ "-m64" \ + "-march=haswell" \ "-march=i686" \ "-march=x86-64" \ "-march=z13" \ @@ -391,7 +446,6 @@ pushd $builddir --enable-cet \ %endif %endif - --enable-obsolete-rpc \ --enable-tunables \ --enable-systemtap \ %ifarch %{ix86} @@ -413,6 +467,15 @@ pushd $builddir 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... ############################################################################## @@ -428,9 +491,18 @@ done 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} -make %{?_smp_mflags} -O install_root=$RPM_BUILD_ROOT \ - install-locales -C ../localedata objdir=`pwd` + +# 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* @@ -468,16 +540,15 @@ 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 \ - *_* -# Setup the locale-archive template for use by glibc-all-langpacks. -mv locale-archive{,.tmpl} + eo *_* %{find_lang} libc popd mv $RPM_BUILD_ROOT%{_prefix}/lib/locale/libc.lang . # Install configuration files for services -install -p -m 644 %{SOURCE3} $RPM_BUILD_ROOT/etc/nsswitch.conf +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 @@ -485,7 +556,7 @@ 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 %{SOURCE2} %{buildroot}%{_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 @@ -502,10 +573,6 @@ truncate -s 0 $RPM_BUILD_ROOT/etc/gai.conf truncate -s 0 $RPM_BUILD_ROOT%{_libdir}/gconv/gconv-modules.cache chmod 644 $RPM_BUILD_ROOT%{_libdir}/gconv/gconv-modules.cache -# Install the upgrade program -install -m 700 build-%{target}/elf/glibc_post_upgrade \ - $RPM_BUILD_ROOT%{_prefix}/sbin/glibc_post_upgrade.%{_target_cpu} - # Install debug copies of unstripped static libraries %if 0%{?_enable_debug_packages} mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_libdir} @@ -520,20 +587,6 @@ 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 -pushd build-%{target} -%GCC -Os -g -o build-locale-archive %{SOURCE1} \ - ../build-%{target}/locale/locarchive.o \ - ../build-%{target}/locale/md5.o \ - ../build-%{target}/locale/record-status.o \ - -I. -DDATADIR=\"%{_datadir}\" -DPREFIX=\"%{_prefix}\" \ - -L../build-%{target} \ - -B../build-%{target}/csu/ -lc -lc_nonshared \ - -Wl,-dynamic-linker=/lib64/ld-%{version}.so \ - -Wl,-rpath-link=.:./math:./elf:./dlfcn:./nss:./rt:./resolv:./mathvec:./support:./nptl libc.so.6 libc_nonshared.a \ - -Wl,--as-needed $olddir/build-%{target}/elf/ld.so -install -m 700 build-locale-archive $RPM_BUILD_ROOT%{_prefix}/sbin/build-locale-archive -popd - # Lastly copy some additional documentation for the packages. rm -rf documentation mkdir documentation @@ -551,7 +604,7 @@ 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 %{SOURCE4} %{SOURCE5}; do +for b in %{SOURCE3} %{SOURCE4}; do cp $b $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/ done @@ -573,7 +626,6 @@ popd rm -f $RPM_BUILD_ROOT%{_infodir}/dir %endif -truncate -s 0 $RPM_BUILD_ROOT/%{_prefix}/lib/locale/locale-archive 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} @@ -604,7 +656,219 @@ for i in $RPM_BUILD_ROOT%{_prefix}/bin/{xtrace,memusage}; do -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 < 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 @@ -679,20 +943,131 @@ if rpm.vercmp(rel, required) < 0 then error("FATAL: kernel too old", 0) end -%post -p %{_prefix}/sbin/glibc_post_upgrade.%{_target_cpu} - -%posttrans common -e -p -if posix.stat("%{_prefix}/lib/locale/locale-archive.tmpl", "size") > 0 then - pid = posix.fork() +%post -p +-- 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 - posix.exec("%{_prefix}/sbin/build-locale-archive", "--install-langs", "%%{_install_langs}") + assert (posix.exec (program, ...)) elseif pid > 0 then - posix.wait(pid) + 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 -%postun common -p -os.remove("%{_prefix}/lib/locale/locale-archive") +-- (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 @@ -700,16 +1075,6 @@ if [ -L %{_prefix}/include/scsi ] ; then rm -f %{_prefix}/include/scsi fi -%if %{with docs} -%post devel -/sbin/install-info %{_infodir}/libc.info.gz %{_infodir}/dir > /dev/null 2>&1 || : - -%preun devel -if [ "$1" = 0 ]; then - /sbin/install-info --delete %{_infodir}/libc.info.gz %{_infodir}/dir > /dev/null 2>&1 || : -fi -%endif - %pre -n nscd getent group nscd >/dev/null || /usr/sbin/groupadd -g 28 -r nscd getent passwd nscd >/dev/null || @@ -731,71 +1096,36 @@ fi ############################################################################## # Files list ############################################################################## -%files +%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 -%verify(not md5 size mtime) %config(noreplace) /usr/lib64/gconv/gconv-modules -%verify(not md5 size mtime) /usr/lib64/gconv/gconv-modules.cache %dir /etc/ld.so.conf.d %dir %{_prefix}/libexec/getconf -%{_prefix}/libexec/getconf/* %dir %{_libdir}/gconv -%{_libdir}/gconv/*.so -%dir %{_libdir}/audit -%{_libdir}/audit/* %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 -%{_sbindir}/glibc* -%{_sbindir}/iconvconfig -/lib/* -%{_libdir}/libmemusage.so -%{_libdir}/libpcprofile.so -/sbin/ldconfig -/%{_lib}/*.* -%exclude /%{_lib}/libnss_db* -%exclude /%{_lib}/libnss_hesiod* -%exclude /%{_lib}/libnsl* -%exclude /lib/systemd +%{!?_licensedir:%global license %%doc} %license COPYING COPYING.LIB LICENSES -%files common -%dir %{_prefix}/share/i18n -%dir %{_prefix}/share/i18n/charmaps -%dir %{_prefix}/share/i18n/locales -%attr(0644,root,root) %verify(not md5 size mtime) %{_prefix}/lib/locale/locale-archive.tmpl +%files -f common.filelist common %attr(0644,root,root) %verify(not md5 size mtime mode) %ghost %config(missingok,noreplace) %{_prefix}/lib/locale/locale-archive -%{_prefix}/lib/locale/C.utf8 +%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 -%{_prefix}/bin/catchsegv -%{_prefix}/bin/gencat -%{_prefix}/bin/getconf -%{_prefix}/bin/getent -%{_prefix}/bin/iconv -%{_prefix}/bin/ldd -%{_prefix}/bin/locale -%{_prefix}/bin/localedef -%{_prefix}/bin/makedb -%{_prefix}/bin/pldd -%{_prefix}/bin/sotruss -%{_prefix}/bin/sprof -%{_prefix}/bin/tzselect %dir %attr(755,root,root) /etc/default %verify(not md5 size mtime) %config(noreplace) /etc/default/nss -%{_prefix}/share/locale/locale.alias -%{_sbindir}/build-locale-archive -%{_sbindir}/zdump -%{_sbindir}/zic -%files all-langpacks -f libc.lang +%files -f libc.lang all-langpacks %{_prefix}/lib/locale %exclude %{_prefix}/lib/locale/locale-archive -%exclude %{_prefix}/lib/locale/locale-archive.tmpl %exclude %{_prefix}/lib/locale/C.utf8 %exclude %{_prefix}/lib/locale/zh_CN.utf8 %exclude %{_prefix}/lib/locale/en_US.utf8 @@ -803,61 +1133,14 @@ fi %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 devel -%{_infodir}/* -%{_libdir}/*.a -%{_libdir}/*.o -%{_libdir}/*.so -%{_prefix}/include/*.h -%dir %{_prefix}/include/arpa -%dir %{_prefix}/include/bits -%dir %{_prefix}/include/bits/types -%dir %{_prefix}/include/gnu -%dir %{_prefix}/include/net -%dir %{_prefix}/include/netash -%dir %{_prefix}/include/netatalk -%dir %{_prefix}/include/netax25 -%dir %{_prefix}/include/neteconet -%dir %{_prefix}/include/netinet -%dir %{_prefix}/include/netipx -%dir %{_prefix}/include/netiucv -%dir %{_prefix}/include/netpacket -%dir %{_prefix}/include/netrom -%dir %{_prefix}/include/netrose -%dir %{_prefix}/include/nfs -%dir %{_prefix}/include/protocols -%dir %{_prefix}/include/rpc -%dir %{_prefix}/include/scsi -%dir %{_prefix}/include/sys -%{_prefix}/include/arpa/* -%{_prefix}/include/bits/* -%{_prefix}/include/gnu/* -%{_prefix}/include/net/* -%{_prefix}/include/netash/* -%{_prefix}/include/netatalk/* -%{_prefix}/include/netax25/* -%{_prefix}/include/neteconet/* -%{_prefix}/include/netinet/* -%{_prefix}/include/netipx/* -%{_prefix}/include/netiucv/* -%{_prefix}/include/netpacket/* -%{_prefix}/include/netrom/* -%{_prefix}/include/netrose/* -%{_prefix}/include/nfs/* -%{_prefix}/include/protocols/* -%{_prefix}/include/rpc/* -%{_prefix}/include/scsi/* -%{_prefix}/include/sys/* -%exclude %{_libdir}/libmemusage.so -%exclude %{_libdir}/libpcprofile.so -%exclude %{_libdir}/libnss* -%exclude %{_prefix}/bin/rpcgen -%exclude %{_prefix}/include/rpcsvc/* - -%files -n nscd +%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 @@ -875,49 +1158,107 @@ fi %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 -%{_sbindir}/nscd -%files -n nss_modules +%files -f nss_modules.filelist -n nss_modules /var/db/Makefile -/%{_lib}/libnss_db* -/%{_lib}/libnss_hesiod* -%files nss-devel -%{_libdir}/libnss* +%files -f nss-devel.filelist nss-devel -%files -n libnsl -/%{_lib}/libnsl* +%files -f libnsl.filelist -n libnsl +/%{_lib}/libnsl.so.1 + +%files -f debugutils.filelist debugutils %if %{with benchtests} -%files benchtests -%{_prefix}/libexec/glibc-benchtests/* +%files -f benchtests.filelist benchtests %endif -%files debugutils -%if %{without bootstrap} -%{_prefix}/bin/memusage -%{_prefix}/bin/memusagestat +%if 0%{?_enable_debug_packages} +%files -f debuginfo.filelist debuginfo + +%files debugsource %endif -%{_prefix}/bin/mtrace -%{_prefix}/bin/pcprofiledump -%{_prefix}/bin/xtrace -%{_prefix}/lib/debug/usr/bin/*.debug -%{_prefix}/lib/debug/usr/lib64/*.a %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 +* Tue Nov 10 2020 liusirui - 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 - 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 - 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 - 2.31-3 +- backport patch to disable warnings due to deprecated libselinux +- symbols used by nss and nscd + +* Fri Jul 24 2020 Wang Shuo - 2.31-2 +- fix CVE-2020-6096 +- fix bugzilla 26137, 26214 and 26215 + +* Thu Jul 9 2020 wuxu - 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 - 2.28-45 +- disable rpc, it has been splited to libnss and libtirpc +- disable parallel compilation + +* Tue Jul 7 2020 Wang Shuo - 2.28-44 +- backup to version 40 + +* Mon Jul 6 2020 Wang Shuo - 2.28-43 +- disable rpc, it has been splited to libnss and libtirpc +- disable parallel compilation + +* Mon Jul 6 2020 Wang Shuo - 2.28-42 +- add zh and en to LanguageList + +* Thu Jul 2 2020 Wang Shuo - 2.28-41 +- add filelist to improve the scalability +- backport many patch for bugfix + +* Sat May 30 2020 liqingqing - 2.28-40 +- Fix array overflow in backtrace on PowerPC (bug 25423) + +* Thu May 28 2020 jdkboy - 2.28-39 +- Disable compilation warnings temporarily + +* Tue Apr 28 2020 liqingqing - 2.28-38 +- Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487) + +* Thu Apr 16 2020 wangbin - 2.28-37 +- backport Kunpeng patches + * Thu Mar 19 2020 yuxiangyang - 2.28-36 - fix build src.rpm error diff --git a/glibc.yaml b/glibc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4927cb3ddefef6701fae25f10ef86c04ed698a2b --- /dev/null +++ b/glibc.yaml @@ -0,0 +1,4 @@ +version_control: git +src_repo: https://sourceware.org/git/glibc.git +tag_prefix: glibc- +seperator: "." 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 0000000000000000000000000000000000000000..41937de79ab7ad15cb30f6c6de0bfbc91a91fb28 --- /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 +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 0000000000000000000000000000000000000000..604e0b7d1eacb7aefcf304d717e36f2ad08f9fd8 --- /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 +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/remove-country-selection-from-tzselect.patch b/remove-country-selection-from-tzselect.patch new file mode 100644 index 0000000000000000000000000000000000000000..5b00087180d51d1edf88c8b310b40e6c2d97e5e2 --- /dev/null +++ b/remove-country-selection-from-tzselect.patch @@ -0,0 +1,151 @@ +From dff0000cc458d6d4993b821f2badcf31ea28062e Mon Sep 17 00:00:00 2001 +From: MarsChan +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 &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 &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 &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 0000000000000000000000000000000000000000..d70be0beed3df7bfb68b9d56b97b1f5bd252a97f --- /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 +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 +--- + 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 + +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 ++ . */ ++ ++/* 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 ++#include ++#include ++#include ++#include ++ ++static int do_test (void); ++#include ++#include ++#include ++#include ++ ++/* 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 ++ . */ ++ ++/* This file is parameterized by macros N, SIZE and MODEL. */ ++ ++#include ++#include ++ ++#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 ++ . */ ++ ++/* 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 ++#include ++#include ++#include ++#include ++ ++static int do_test (void); ++#include ++#include ++#include ++#include ++ ++/* 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 + 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 0000000000000000000000000000000000000000..5b766cf3b3cf5869de61bf1243359a0457fcc63f --- /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 +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 0000000000000000000000000000000000000000..82f84764f502ded222bd3ec439b911012154059c --- /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" +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 0000000000000000000000000000000000000000..a308561bf10135dfa95db1efae74807ce97f00eb --- /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" +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 +