From ccb58cf702596222c8965a50bb483f4eff055c3e Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Wed, 25 Aug 2021 08:57:49 +0800 Subject: [PATCH 01/70] fix CVE-2021-38604 (cherry picked from commit 2418652d62c193b291ca04e0fa0fd149c88e4ab1) --- ...-38604-0001-librt-add-test-bug-28213.patch | 146 ++++++++++++++++++ ...x-NULL-pointer-dereference-bug-28213.patch | 39 +++++ glibc.spec | 8 +- 3 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch create mode 100644 backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch diff --git a/backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch b/backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch new file mode 100644 index 0000000..c511b66 --- /dev/null +++ b/backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch @@ -0,0 +1,146 @@ +From 4cc79c217744743077bf7a0ec5e0a4318f1e6641 Mon Sep 17 00:00:00 2001 +From: Nikita Popov +Date: Thu, 12 Aug 2021 16:09:50 +0530 +Subject: [PATCH] librt: add test (bug 28213) + +This test implements following logic: +1) Create POSIX message queue. + Register a notification with mq_notify (using NULL attributes). + Then immediately unregister the notification with mq_notify. + Helper thread in a vulnerable version of glibc + should cause NULL pointer dereference after these steps. +2) Once again, register the same notification. + Try to send a dummy message. + Test is considered successfulif the dummy message + is successfully received by the callback function. + +Signed-off-by: Nikita Popov +Reviewed-by: Siddhesh Poyarekar +--- + rt/Makefile | 1 + + rt/tst-bz28213.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 102 insertions(+) + create mode 100644 rt/tst-bz28213.c + +diff --git a/rt/Makefile b/rt/Makefile +index 113cea03a5..910e775995 100644 +--- a/rt/Makefile ++++ b/rt/Makefile +@@ -74,6 +74,7 @@ tests := tst-shm tst-timer tst-timer2 \ + tst-aio7 tst-aio8 tst-aio9 tst-aio10 \ + tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \ + tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \ ++ tst-bz28213 \ + tst-timer3 tst-timer4 tst-timer5 \ + tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \ + tst-shm-cancel \ +diff --git a/rt/tst-bz28213.c b/rt/tst-bz28213.c +new file mode 100644 +index 0000000000..0c096b5a0a +--- /dev/null ++++ b/rt/tst-bz28213.c +@@ -0,0 +1,101 @@ ++/* Bug 28213: test for NULL pointer dereference in mq_notify. ++ Copyright (C) The GNU Toolchain Authors. ++ 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 ++#include ++#include ++#include ++#include ++ ++static mqd_t m = -1; ++static const char msg[] = "hello"; ++ ++static void ++check_bz28213_cb (union sigval sv) ++{ ++ char buf[sizeof (msg)]; ++ ++ (void) sv; ++ ++ TEST_VERIFY_EXIT ((size_t) mq_receive (m, buf, sizeof (buf), NULL) ++ == sizeof (buf)); ++ TEST_VERIFY_EXIT (memcmp (buf, msg, sizeof (buf)) == 0); ++ ++ exit (0); ++} ++ ++static void ++check_bz28213 (void) ++{ ++ struct sigevent sev; ++ ++ memset (&sev, '\0', sizeof (sev)); ++ sev.sigev_notify = SIGEV_THREAD; ++ sev.sigev_notify_function = check_bz28213_cb; ++ ++ /* Step 1: Register & unregister notifier. ++ Helper thread should receive NOTIFY_REMOVED notification. ++ In a vulnerable version of glibc, NULL pointer dereference follows. */ ++ TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0); ++ TEST_VERIFY_EXIT (mq_notify (m, NULL) == 0); ++ ++ /* Step 2: Once again, register notification. ++ Try to send one message. ++ Test is considered successful, if the callback does exit (0). */ ++ TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0); ++ TEST_VERIFY_EXIT (mq_send (m, msg, sizeof (msg), 1) == 0); ++ ++ /* Wait... */ ++ pause (); ++} ++ ++static int ++do_test (void) ++{ ++ static const char m_name[] = "/bz28213_queue"; ++ struct mq_attr m_attr; ++ ++ memset (&m_attr, '\0', sizeof (m_attr)); ++ m_attr.mq_maxmsg = 1; ++ m_attr.mq_msgsize = sizeof (msg); ++ ++ m = mq_open (m_name, ++ O_RDWR | O_CREAT | O_EXCL, ++ 0600, ++ &m_attr); ++ ++ if (m < 0) ++ { ++ if (errno == ENOSYS) ++ FAIL_UNSUPPORTED ("POSIX message queues are not implemented\n"); ++ FAIL_EXIT1 ("Failed to create POSIX message queue: %m\n"); ++ } ++ ++ TEST_VERIFY_EXIT (mq_unlink (m_name) == 0); ++ ++ check_bz28213 (); ++ ++ return 0; ++} ++ ++#include +-- +2.27.0 + diff --git a/backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch b/backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch new file mode 100644 index 0000000..3dca8cc --- /dev/null +++ b/backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch @@ -0,0 +1,39 @@ +From b805aebd42364fe696e417808a700fdb9800c9e8 Mon Sep 17 00:00:00 2001 +From: Nikita Popov +Date: Mon, 9 Aug 2021 20:17:34 +0530 +Subject: [PATCH] librt: fix NULL pointer dereference (bug 28213) + +Helper thread frees copied attribute on NOTIFY_REMOVED message +received from the OS kernel. Unfortunately, it fails to check whether +copied attribute actually exists (data.attr != NULL). This worked +earlier because free() checks passed pointer before actually +attempting to release corresponding memory. But +__pthread_attr_destroy assumes pointer is not NULL. + +So passing NULL pointer to __pthread_attr_destroy will result in +segmentation fault. This scenario is possible if +notification->sigev_notify_attributes == NULL (which means default +thread attributes should be used). + +Signed-off-by: Nikita Popov +Reviewed-by: Siddhesh Poyarekar +--- + sysdeps/unix/sysv/linux/mq_notify.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index 9799dcdaa4..eccae2e4c6 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -131,7 +131,7 @@ helper_thread (void *arg) + to wait until it is done with it. */ + (void) __pthread_barrier_wait (¬ify_barrier); + } +- else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) ++ else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL) + { + /* The only state we keep is the copy of the thread attributes. */ + __pthread_attr_destroy (data.attr); +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 6f0b863..3169c40 100644 --- a/glibc.spec +++ b/glibc.spec @@ -60,7 +60,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 1 +Release: 2 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -76,6 +76,8 @@ Source7: replace_same_file_to_hard_link.py Patch0: glibc-1070416.patch Patch1: glibc-c-utf8-locale.patch +Patch2: backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch +Patch3: backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1163,6 +1165,10 @@ fi %doc hesiod/README.hesiod %changelog +* Wed Aug 25 2021 Qingqing Li - 2.34-2 +- fix CVE-2021-38604 + https://sourceware.org/bugzilla/show_bug.cgi?id=28213 + * Thu Aug 5 2021 Qingqing Li - 2.34-1 - upgrade to 2.34. -- Gitee From ac4412e50216db660fe787e06e4707623067ba07 Mon Sep 17 00:00:00 2001 From: yangyanchao Date: Tue, 14 Sep 2021 15:45:08 +0800 Subject: [PATCH 02/70] add --enable-static-pie in aarch64 Signed-off-by: yangyanchao (cherry picked from commit 40f3e7ca8a7299a8e53d2056a1dbf76c1c7487f2) --- glibc.spec | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/glibc.spec b/glibc.spec index 3169c40..61dc941 100644 --- a/glibc.spec +++ b/glibc.spec @@ -46,6 +46,9 @@ %undefine with_valgrind %endif +# Only some architectures have static PIE support +%define pie_arches %{ix86} x86_64 aarch64 + %define enablekernel 3.2 %define target %{_target_cpu}-%{_vendor}-linux %ifarch %{arm} @@ -60,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 2 +Release: 3 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -425,9 +428,13 @@ pushd $builddir --enable-bind-now \ --build=%{target} \ --enable-stack-protector=strong \ -%ifarch %{x86_arches} +%ifarch %{pie_arches} %if 0%{?gcc_version} >= 8 --enable-static-pie \ +%endif +%endif +%ifarch %{x86_arches} +%if 0%{?gcc_version} >= 8 --enable-cet \ %endif %endif @@ -1165,6 +1172,9 @@ fi %doc hesiod/README.hesiod %changelog +* Tue Sep 14 2021 Yang Yanchao - 2.34-3 +- add --enable-static-pie in aarch64 + * Wed Aug 25 2021 Qingqing Li - 2.34-2 - fix CVE-2021-38604 https://sourceware.org/bugzilla/show_bug.cgi?id=28213 -- Gitee From b9bf92ef1cf13ff625e732480cbf181cd14f3173 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Fri, 17 Sep 2021 09:29:06 +0800 Subject: [PATCH 03/70] fix some patches to fix some memory leak and double free bugs. (cherry picked from commit 524981388ed240aa2c6728cadcf26d255e401e77) --- ...ioctl-prctl-redirects-for-_TIME_BITS.patch | 72 +++++++++++++++++++ ...awn_sgid-Avoid-double-calls-to-close.patch | 28 ++++++++ ...id-double-free-in-label-and-preceden.patch | 36 ++++++++++ gconv_parseconfdir-Fix-memory-leak.patch | 37 ++++++++++ gethosts-Remove-unused-argument-_type.patch | 44 ++++++++++++ glibc.spec | 14 +++- ..._charmap-Close-output-file-when-done.patch | 26 +++++++ ...d-leak-on-empty-paths-in-config-file.patch | 30 ++++++++ ...realloc-failure-in-nis_getnames-BZ-2.patch | 46 ++++++++++++ ...rrect-message-queue-for-tst-mqueue10.patch | 35 +++++++++ 10 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch create mode 100644 copy_and_spawn_sgid-Avoid-double-calls-to-close.patch create mode 100644 gaiconf_init-Avoid-double-free-in-label-and-preceden.patch create mode 100644 gconv_parseconfdir-Fix-memory-leak.patch create mode 100644 gethosts-Remove-unused-argument-_type.patch create mode 100644 iconv_charmap-Close-output-file-when-done.patch create mode 100644 ldconfig-avoid-leak-on-empty-paths-in-config-file.patch create mode 100644 nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch create mode 100644 rt-Set-the-correct-message-queue-for-tst-mqueue10.patch diff --git a/Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch b/Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch new file mode 100644 index 0000000..b33981d --- /dev/null +++ b/Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch @@ -0,0 +1,72 @@ +From c87fcacc50505d550f1bb038382bcc7ea73a5926 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 6 Aug 2021 09:51:38 +0200 +Subject: [PATCH] Linux: Fix fcntl, ioctl, prctl redirects for _TIME_BITS=64 + (bug 28182) + +__REDIRECT and __THROW are not compatible with C++ due to the ordering of the +__asm__ alias and the throw specifier. __REDIRECT_NTH has to be used +instead. + +Fixes commit 8a40aff86ba5f64a3a84883e539cb67b ("io: Add time64 alias +for fcntl"), commit 82c395d91ea4f69120d453aeec398e30 ("misc: Add +time64 alias for ioctl"), commit b39ffab860cd743a82c91946619f1b8158 +("Linux: Add time64 alias for prctl"). + +Reviewed-by: Carlos O'Donell +--- + io/fcntl.h | 8 ++++---- + misc/sys/ioctl.h | 4 ++-- + sysdeps/unix/sysv/linux/sys/prctl.h | 2 +- + 3 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/io/fcntl.h b/io/fcntl.h +index 8917a73..1c96f98 100644 +--- a/io/fcntl.h ++++ b/io/fcntl.h +@@ -187,10 +187,10 @@ extern int fcntl64 (int __fd, int __cmd, ...); + # endif + #else /* __USE_TIME_BITS64 */ + # ifdef __REDIRECT +-extern int __REDIRECT (fcntl, (int __fd, int __request, ...), +- __fcntl_time64) __THROW; +-extern int __REDIRECT (fcntl64, (int __fd, int __request, ...), +- __fcntl_time64) __THROW; ++extern int __REDIRECT_NTH (fcntl, (int __fd, int __request, ...), ++ __fcntl_time64); ++extern int __REDIRECT_NTH (fcntl64, (int __fd, int __request, ...), ++ __fcntl_time64); + # else + extern int __fcntl_time64 (int __fd, int __request, ...) __THROW; + # define fcntl64 __fcntl_time64 +diff --git a/misc/sys/ioctl.h b/misc/sys/ioctl.h +index 6884d99..9945c1e 100644 +--- a/misc/sys/ioctl.h ++++ b/misc/sys/ioctl.h +@@ -42,8 +42,8 @@ __BEGIN_DECLS + extern int ioctl (int __fd, unsigned long int __request, ...) __THROW; + #else + # ifdef __REDIRECT +-extern int __REDIRECT (ioctl, (int __fd, unsigned long int __request, ...), +- __ioctl_time64) __THROW; ++extern int __REDIRECT_NTH (ioctl, (int __fd, unsigned long int __request, ...), ++ __ioctl_time64); + # else + extern int __ioctl_time64 (int __fd, unsigned long int __request, ...) __THROW; + # define ioctl __ioctl_time64 +diff --git a/sysdeps/unix/sysv/linux/sys/prctl.h b/sysdeps/unix/sysv/linux/sys/prctl.h +index db88938..f0e0d2f 100644 +--- a/sysdeps/unix/sysv/linux/sys/prctl.h ++++ b/sysdeps/unix/sysv/linux/sys/prctl.h +@@ -42,7 +42,7 @@ __BEGIN_DECLS + extern int prctl (int __option, ...) __THROW; + #else + # ifdef __REDIRECT +-extern int __REDIRECT (prctl, (int __option, ...), __prctl_time64) __THROW; ++extern int __REDIRECT_NTH (prctl, (int __option, ...), __prctl_time64); + # else + extern int __prctl_time64 (int __option,d ...) __THROW; + # define ioctl __prctl_time64 +-- +1.8.3.1 + diff --git a/copy_and_spawn_sgid-Avoid-double-calls-to-close.patch b/copy_and_spawn_sgid-Avoid-double-calls-to-close.patch new file mode 100644 index 0000000..0f47990 --- /dev/null +++ b/copy_and_spawn_sgid-Avoid-double-calls-to-close.patch @@ -0,0 +1,28 @@ +From 45caed9d67a00af917d8b5b88d4b5eb1225b7aef Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Tue, 3 Aug 2021 21:10:53 +0530 +Subject: [PATCH] copy_and_spawn_sgid: Avoid double calls to close() + +If close() on infd and outfd succeeded, reset the fd numbers so that +we don't attempt to close them again. + +Reviewed-by: Arjun Shankar +--- + support/support_capture_subprocess.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +index 27bfd19..0bacf6d 100644 +--- a/support/support_capture_subprocess.c ++++ b/support/support_capture_subprocess.c +@@ -170,6 +170,7 @@ copy_and_spawn_sgid (char *child_id, gid_t gid) + support_subprogram because we only want the program exit status, not the + contents. */ + ret = 0; ++ infd = outfd = -1; + + char * const args[] = {execname, child_id, NULL}; + +-- +1.8.3.1 + diff --git a/gaiconf_init-Avoid-double-free-in-label-and-preceden.patch b/gaiconf_init-Avoid-double-free-in-label-and-preceden.patch new file mode 100644 index 0000000..7ebc183 --- /dev/null +++ b/gaiconf_init-Avoid-double-free-in-label-and-preceden.patch @@ -0,0 +1,36 @@ +From 77a34079d8f3d63b61543bf3af93043f8674e4c4 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Tue, 3 Aug 2021 21:11:03 +0530 +Subject: [PATCH] gaiconf_init: Avoid double-free in label and precedence lists + +labellist and precedencelist could get freed a second time if there +are allocation failures, so set them to NULL to avoid a double-free. + +Reviewed-by: Arjun Shankar +--- + sysdeps/posix/getaddrinfo.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 838a68f..43dfc67 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -2008,6 +2008,7 @@ gaiconf_init (void) + l = l->next; + } + free_prefixlist (labellist); ++ labellist = NULL; + + /* Sort the entries so that the most specific ones are at + the beginning. */ +@@ -2046,6 +2047,7 @@ gaiconf_init (void) + l = l->next; + } + free_prefixlist (precedencelist); ++ precedencelist = NULL; + + /* Sort the entries so that the most specific ones are at + the beginning. */ +-- +1.8.3.1 + diff --git a/gconv_parseconfdir-Fix-memory-leak.patch b/gconv_parseconfdir-Fix-memory-leak.patch new file mode 100644 index 0000000..de306cc --- /dev/null +++ b/gconv_parseconfdir-Fix-memory-leak.patch @@ -0,0 +1,37 @@ +From 5f9b78fe35d08739b6da1e5b356786d41116c108 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Tue, 3 Aug 2021 21:10:20 +0530 +Subject: [PATCH] gconv_parseconfdir: Fix memory leak + +The allocated `conf` would leak if we have to skip over the file due +to the underlying filesystem not supporting dt_type. + +Reviewed-by: Arjun Shankar +--- + iconv/gconv_parseconfdir.h | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h +index a4153e5..2f06268 100644 +--- a/iconv/gconv_parseconfdir.h ++++ b/iconv/gconv_parseconfdir.h +@@ -153,12 +153,11 @@ gconv_parseconfdir (const char *dir, size_t dir_len) + struct stat64 st; + if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0) + continue; +- if (ent->d_type == DT_UNKNOWN +- && (lstat64 (conf, &st) == -1 +- || !S_ISREG (st.st_mode))) +- continue; + +- found |= read_conf_file (conf, dir, dir_len); ++ if (ent->d_type != DT_UNKNOWN ++ || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode))) ++ found |= read_conf_file (conf, dir, dir_len); ++ + free (conf); + } + } +-- +1.8.3.1 + diff --git a/gethosts-Remove-unused-argument-_type.patch b/gethosts-Remove-unused-argument-_type.patch new file mode 100644 index 0000000..1fb60e7 --- /dev/null +++ b/gethosts-Remove-unused-argument-_type.patch @@ -0,0 +1,44 @@ +From b17e842a60819098d2a203ecc8b8371b7e1d6c65 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Wed, 4 Aug 2021 02:21:01 +0530 +Subject: [PATCH] gethosts: Remove unused argument _type + +The generated code is unchanged. +--- + sysdeps/posix/getaddrinfo.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 43dfc67..9f1cde2 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -239,7 +239,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, + return true; + } + +-#define gethosts(_family, _type) \ ++#define gethosts(_family) \ + { \ + struct hostent th; \ + char *localcanon = NULL; \ +@@ -829,7 +829,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + if (req->ai_family == AF_INET6 + || req->ai_family == AF_UNSPEC) + { +- gethosts (AF_INET6, struct in6_addr); ++ gethosts (AF_INET6); + no_inet6_data = no_data; + inet6_status = status; + } +@@ -841,7 +841,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + know we are not going to need them. */ + && ((req->ai_flags & AI_ALL) || !got_ipv6))) + { +- gethosts (AF_INET, struct in_addr); ++ gethosts (AF_INET); + + if (req->ai_family == AF_INET) + { +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index 61dc941..a4158e5 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 3 +Release: 4 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -81,6 +81,15 @@ Patch0: glibc-1070416.patch Patch1: glibc-c-utf8-locale.patch Patch2: backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch Patch3: backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch +Patch4: copy_and_spawn_sgid-Avoid-double-calls-to-close.patch +Patch5: gaiconf_init-Avoid-double-free-in-label-and-preceden.patch +Patch6: gconv_parseconfdir-Fix-memory-leak.patch +Patch7: gethosts-Remove-unused-argument-_type.patch +Patch8: iconv_charmap-Close-output-file-when-done.patch +Patch9: ldconfig-avoid-leak-on-empty-paths-in-config-file.patch +Patch10: Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch +Patch11: nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch +Patch12: rt-Set-the-correct-message-queue-for-tst-mqueue10.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1172,6 +1181,9 @@ fi %doc hesiod/README.hesiod %changelog +* Fri Sep 17 2021 Qingqing Li - 2.34-4 +- backport upstream patches to fix some memory leak and double free bugs + * Tue Sep 14 2021 Yang Yanchao - 2.34-3 - add --enable-static-pie in aarch64 diff --git a/iconv_charmap-Close-output-file-when-done.patch b/iconv_charmap-Close-output-file-when-done.patch new file mode 100644 index 0000000..a966922 --- /dev/null +++ b/iconv_charmap-Close-output-file-when-done.patch @@ -0,0 +1,26 @@ +From 1e0e6d656db9dfa12ef7eb67976385d3deb0d4ff Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Tue, 3 Aug 2021 21:10:29 +0530 +Subject: [PATCH] iconv_charmap: Close output file when done + +Reviewed-by: Arjun Shankar +--- + iconv/iconv_charmap.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/iconv/iconv_charmap.c b/iconv/iconv_charmap.c +index e2d53fe..a8b6b56 100644 +--- a/iconv/iconv_charmap.c ++++ b/iconv/iconv_charmap.c +@@ -234,6 +234,8 @@ charmap_conversion (const char *from_code, struct charmap_t *from_charmap, + while (++remaining < argc); + + /* All done. */ ++ if (output != stdout) ++ fclose (output); + free_table (cvtbl); + return status; + } +-- +1.8.3.1 + diff --git a/ldconfig-avoid-leak-on-empty-paths-in-config-file.patch b/ldconfig-avoid-leak-on-empty-paths-in-config-file.patch new file mode 100644 index 0000000..c415a47 --- /dev/null +++ b/ldconfig-avoid-leak-on-empty-paths-in-config-file.patch @@ -0,0 +1,30 @@ +From b0234d79e7d82475d1666f25326ec045c045b3ed Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Tue, 3 Aug 2021 21:10:10 +0530 +Subject: [PATCH] ldconfig: avoid leak on empty paths in config file + +Reviewed-by: Arjun Shankar +--- + elf/ldconfig.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index 1037e8d..b889363 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -503,7 +503,11 @@ add_dir_1 (const char *line, const char *from_file, int from_line) + entry->path[--i] = '\0'; + + if (i == 0) +- return; ++ { ++ free (entry->path); ++ free (entry); ++ return; ++ } + + char *path = entry->path; + if (opt_chroot != NULL) +-- +1.8.3.1 + diff --git a/nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch b/nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch new file mode 100644 index 0000000..b72b474 --- /dev/null +++ b/nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch @@ -0,0 +1,46 @@ +From 60698263122b7c54ded3f70a466176e17a529480 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 28 Jul 2021 14:23:32 -0400 +Subject: [PATCH] nis: Fix leak on realloc failure in nis_getnames [BZ #28150] + +If pos >= count but realloc fails, tmp will not have been placed in +getnames[pos] yet, and so will not be freed in free_null. Detected +by Coverity. + +Also remove misleading comment from nis_getnames(), since it actually +did properly release getnames when out of memory. + +Tested-by: Carlos O'Donell +--- + nis/nis_subr.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/nis/nis_subr.c b/nis/nis_subr.c +index dd0e300..6784fc3 100644 +--- a/nis/nis_subr.c ++++ b/nis/nis_subr.c +@@ -103,9 +103,6 @@ count_dots (const_nis_name str) + return count; + } + +-/* If we run out of memory, we don't give already allocated memory +- free. The overhead for bringing getnames back in a safe state to +- free it is to big. */ + nis_name * + nis_getnames (const_nis_name name) + { +@@ -271,7 +268,10 @@ nis_getnames (const_nis_name name) + nis_name *newp = realloc (getnames, + (count + 1) * sizeof (char *)); + if (__glibc_unlikely (newp == NULL)) +- goto free_null; ++ { ++ free (tmp); ++ goto free_null; ++ } + getnames = newp; + } + getnames[pos] = tmp; +-- +1.8.3.1 + diff --git a/rt-Set-the-correct-message-queue-for-tst-mqueue10.patch b/rt-Set-the-correct-message-queue-for-tst-mqueue10.patch new file mode 100644 index 0000000..700045a --- /dev/null +++ b/rt-Set-the-correct-message-queue-for-tst-mqueue10.patch @@ -0,0 +1,35 @@ +From 3d9a539ee66165148b2b9e08b46e03a5f58f65d2 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Wed, 4 Aug 2021 17:14:46 -0300 +Subject: [PATCH] rt: Set the correct message queue for tst-mqueue10 + +Checked on x86_64-linux-gnu. +--- + rt/tst-mqueue10.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/rt/tst-mqueue10.c b/rt/tst-mqueue10.c +index 1879580..0bf64d7 100644 +--- a/rt/tst-mqueue10.c ++++ b/rt/tst-mqueue10.c +@@ -25,7 +25,7 @@ + #include + #include + +-static char name[sizeof "/tst-mqueue2-" + INT_BUFSIZE_BOUND (pid_t)]; ++static char name[sizeof "/tst-mqueue10-" + INT_BUFSIZE_BOUND (pid_t)]; + + static void + do_cleanup (void) +@@ -37,7 +37,7 @@ do_cleanup (void) + static int + do_test (void) + { +- snprintf (name, sizeof (name), "/tst-mqueue2-%u", getpid ()); ++ snprintf (name, sizeof (name), "/tst-mqueue10-%u", getpid ()); + + char msg[8] = { 0x55 }; + +-- +1.8.3.1 + -- Gitee From 1e9651012c1c279733448de72b55fac116f2e88d Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Fri, 17 Sep 2021 16:02:18 +0800 Subject: [PATCH 04/70] aarch64: optimize memset performance (cherry picked from commit 8d6576b56f864d1a1fd03f1035fcd9a0b835e10a) --- ...Improve-A64FX-memset-for-small-sizes.patch | 136 ++++++++++++++++++ ...Improve-A64FX-memset-for-large-sizes.patch | 131 +++++++++++++++++ ...ove-A64FX-memset-for-remaining-bytes.patch | 80 +++++++++++ ...ove-A64FX-memset-by-removing-unroll3.patch | 51 +++++++ ...64-Improve-A64FX-memset-medium-loops.patch | 96 +++++++++++++ glibc.spec | 10 +- 6 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch create mode 100644 2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch create mode 100644 3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch create mode 100644 4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch create mode 100644 5-5-AArch64-Improve-A64FX-memset-medium-loops.patch diff --git a/1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch b/1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch new file mode 100644 index 0000000..2db0045 --- /dev/null +++ b/1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch @@ -0,0 +1,136 @@ +From 07b427296b8d59f439144029d9a948f6c1ce0a31 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:30:27 +0100 +Subject: [PATCH] [1/5] AArch64: Improve A64FX memset for small sizes + +Improve performance of small memsets by reducing instruction counts and +improving code alignment. Bench-memset shows 35-45% performance gain for +small sizes. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 96 ++++++++++++-------------------- + 1 file changed, 36 insertions(+), 60 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index ce54e54..cf3d402 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -51,78 +51,54 @@ + .endm + + .macro st1b_unroll first=0, last=7 +- st1b z0.b, p0, [dst, #\first, mul vl] ++ st1b z0.b, p0, [dst, \first, mul vl] + .if \last-\first + st1b_unroll "(\first+1)", \last + .endif + .endm + +- .macro shortcut_for_small_size exit +- // if rest <= vector_length * 2 +- whilelo p0.b, xzr, count +- whilelo p1.b, vector_length, count +- b.last 1f +- st1b z0.b, p0, [dstin, #0, mul vl] +- st1b z0.b, p1, [dstin, #1, mul vl] +- ret +-1: // if rest > vector_length * 8 +- cmp count, vector_length, lsl 3 // vector_length * 8 +- b.hi \exit +- // if rest <= vector_length * 4 +- lsl tmp1, vector_length, 1 // vector_length * 2 +- whilelo p2.b, tmp1, count +- incb tmp1 +- whilelo p3.b, tmp1, count +- b.last 1f +- st1b z0.b, p0, [dstin, #0, mul vl] +- st1b z0.b, p1, [dstin, #1, mul vl] +- st1b z0.b, p2, [dstin, #2, mul vl] +- st1b z0.b, p3, [dstin, #3, mul vl] +- ret +-1: // if rest <= vector_length * 8 +- lsl tmp1, vector_length, 2 // vector_length * 4 +- whilelo p4.b, tmp1, count +- incb tmp1 +- whilelo p5.b, tmp1, count +- b.last 1f +- st1b z0.b, p0, [dstin, #0, mul vl] +- st1b z0.b, p1, [dstin, #1, mul vl] +- st1b z0.b, p2, [dstin, #2, mul vl] +- st1b z0.b, p3, [dstin, #3, mul vl] +- st1b z0.b, p4, [dstin, #4, mul vl] +- st1b z0.b, p5, [dstin, #5, mul vl] +- ret +-1: lsl tmp1, vector_length, 2 // vector_length * 4 +- incb tmp1 // vector_length * 5 +- incb tmp1 // vector_length * 6 +- whilelo p6.b, tmp1, count +- incb tmp1 +- whilelo p7.b, tmp1, count +- st1b z0.b, p0, [dstin, #0, mul vl] +- st1b z0.b, p1, [dstin, #1, mul vl] +- st1b z0.b, p2, [dstin, #2, mul vl] +- st1b z0.b, p3, [dstin, #3, mul vl] +- st1b z0.b, p4, [dstin, #4, mul vl] +- st1b z0.b, p5, [dstin, #5, mul vl] +- st1b z0.b, p6, [dstin, #6, mul vl] +- st1b z0.b, p7, [dstin, #7, mul vl] +- ret +- .endm + +-ENTRY (MEMSET) ++#undef BTI_C ++#define BTI_C + ++ENTRY (MEMSET) + PTR_ARG (0) + SIZE_ARG (2) + +- cbnz count, 1f +- ret +-1: dup z0.b, valw + cntb vector_length +- // shortcut for less than vector_length * 8 +- // gives a free ptrue to p0.b for n >= vector_length +- shortcut_for_small_size L(vl_agnostic) +- // end of shortcut ++ dup z0.b, valw ++ whilelo p0.b, vector_length, count ++ b.last 1f ++ whilelo p1.b, xzr, count ++ st1b z0.b, p1, [dstin, 0, mul vl] ++ st1b z0.b, p0, [dstin, 1, mul vl] ++ ret ++ ++ // count >= vector_length * 2 ++1: cmp count, vector_length, lsl 2 ++ add dstend, dstin, count ++ b.hi 1f ++ st1b z0.b, p0, [dstin, 0, mul vl] ++ st1b z0.b, p0, [dstin, 1, mul vl] ++ st1b z0.b, p0, [dstend, -2, mul vl] ++ st1b z0.b, p0, [dstend, -1, mul vl] ++ ret ++ ++ // count > vector_length * 4 ++1: lsl tmp1, vector_length, 3 ++ cmp count, tmp1 ++ b.hi L(vl_agnostic) ++ st1b z0.b, p0, [dstin, 0, mul vl] ++ st1b z0.b, p0, [dstin, 1, mul vl] ++ st1b z0.b, p0, [dstin, 2, mul vl] ++ st1b z0.b, p0, [dstin, 3, mul vl] ++ st1b z0.b, p0, [dstend, -4, mul vl] ++ st1b z0.b, p0, [dstend, -3, mul vl] ++ st1b z0.b, p0, [dstend, -2, mul vl] ++ st1b z0.b, p0, [dstend, -1, mul vl] ++ ret + ++ .p2align 4 + L(vl_agnostic): // VL Agnostic + mov rest, count + mov dst, dstin +-- +1.8.3.1 + diff --git a/2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch b/2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch new file mode 100644 index 0000000..81cdbe0 --- /dev/null +++ b/2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch @@ -0,0 +1,131 @@ +From 9bc2ed8f46d80859a5596789cc9e8cc2de84b0e7 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:39:37 +0100 +Subject: [PATCH] [2/5] AArch64: Improve A64FX memset for large sizes + +Improve performance of large memsets. Simplify alignment code. For zero memset +use DC ZVA, which almost doubles performance. For non-zero memsets use the +unroll8 loop which is about 10% faster. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 85 ++++++++++---------------------- + 1 file changed, 25 insertions(+), 60 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index cf3d402..75cf43a 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -27,14 +27,11 @@ + */ + + #define L1_SIZE (64*1024) // L1 64KB +-#define L2_SIZE (8*1024*1024) // L2 8MB - 1MB ++#define L2_SIZE (8*1024*1024) // L2 8MB + #define CACHE_LINE_SIZE 256 + #define PF_DIST_L1 (CACHE_LINE_SIZE * 16) // Prefetch distance L1 +-#define ZF_DIST (CACHE_LINE_SIZE * 21) // Zerofill distance +-#define rest x8 ++#define rest x2 + #define vector_length x9 +-#define vl_remainder x10 // vector_length remainder +-#define cl_remainder x11 // CACHE_LINE_SIZE remainder + + #if HAVE_AARCH64_SVE_ASM + # if IS_IN (libc) +@@ -42,14 +39,6 @@ + + .arch armv8.2-a+sve + +- .macro dc_zva times +- dc zva, tmp1 +- add tmp1, tmp1, CACHE_LINE_SIZE +- .if \times-1 +- dc_zva "(\times-1)" +- .endif +- .endm +- + .macro st1b_unroll first=0, last=7 + st1b z0.b, p0, [dst, \first, mul vl] + .if \last-\first +@@ -188,54 +177,30 @@ L(L1_prefetch): // if rest >= L1_SIZE + cbnz rest, L(unroll32) + ret + +-L(L2): +- // align dst address at vector_length byte boundary +- sub tmp1, vector_length, 1 +- ands tmp2, dst, tmp1 +- // if vl_remainder == 0 +- b.eq 1f +- sub vl_remainder, vector_length, tmp2 +- // process remainder until the first vector_length boundary +- whilelt p2.b, xzr, vl_remainder +- st1b z0.b, p2, [dst] +- add dst, dst, vl_remainder +- sub rest, rest, vl_remainder +- // align dstin address at CACHE_LINE_SIZE byte boundary +-1: mov tmp1, CACHE_LINE_SIZE +- ands tmp2, dst, CACHE_LINE_SIZE - 1 +- // if cl_remainder == 0 +- b.eq L(L2_dc_zva) +- sub cl_remainder, tmp1, tmp2 +- // process remainder until the first CACHE_LINE_SIZE boundary +- mov tmp1, xzr // index +-2: whilelt p2.b, tmp1, cl_remainder +- st1b z0.b, p2, [dst, tmp1] +- incb tmp1 +- cmp tmp1, cl_remainder +- b.lo 2b +- add dst, dst, cl_remainder +- sub rest, rest, cl_remainder +- +-L(L2_dc_zva): +- // zero fill +- mov tmp1, dst +- dc_zva (ZF_DIST / CACHE_LINE_SIZE) - 1 +- mov zva_len, ZF_DIST +- add tmp1, zva_len, CACHE_LINE_SIZE * 2 +- // unroll ++ // count >= L2_SIZE + .p2align 3 +-1: st1b_unroll 0, 3 +- add tmp2, dst, zva_len +- dc zva, tmp2 +- st1b_unroll 4, 7 +- add tmp2, tmp2, CACHE_LINE_SIZE +- dc zva, tmp2 +- add dst, dst, CACHE_LINE_SIZE * 2 +- sub rest, rest, CACHE_LINE_SIZE * 2 +- cmp rest, tmp1 // ZF_DIST + CACHE_LINE_SIZE * 2 +- b.ge 1b +- cbnz rest, L(unroll8) +- ret ++L(L2): ++ tst valw, 255 ++ b.ne L(unroll8) ++ // align dst to CACHE_LINE_SIZE byte boundary ++ and tmp2, dst, CACHE_LINE_SIZE - 1 ++ st1b z0.b, p0, [dst, 0, mul vl] ++ st1b z0.b, p0, [dst, 1, mul vl] ++ st1b z0.b, p0, [dst, 2, mul vl] ++ st1b z0.b, p0, [dst, 3, mul vl] ++ sub dst, dst, tmp2 ++ add count, count, tmp2 ++ ++ // clear cachelines using DC ZVA ++ sub count, count, CACHE_LINE_SIZE * 2 ++ .p2align 4 ++1: add dst, dst, CACHE_LINE_SIZE ++ dc zva, dst ++ subs count, count, CACHE_LINE_SIZE ++ b.hi 1b ++ add count, count, CACHE_LINE_SIZE ++ add dst, dst, CACHE_LINE_SIZE ++ b L(last) + + END (MEMSET) + libc_hidden_builtin_def (MEMSET) +-- +1.8.3.1 + diff --git a/3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch b/3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch new file mode 100644 index 0000000..7ba3516 --- /dev/null +++ b/3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch @@ -0,0 +1,80 @@ +From 186092c6ba8825598ffdbf15dbf0823c771f560d Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:42:07 +0100 +Subject: [PATCH] [3/5] AArch64: Improve A64FX memset for remaining bytes + +Simplify handling of remaining bytes. Avoid lots of taken branches and complex +whilelo computations, instead unconditionally write vectors from the end. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 46 +++++++++----------------------- + 1 file changed, 13 insertions(+), 33 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index 75cf43a..337c86b 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -130,38 +130,19 @@ L(unroll8): + b 1b + + L(last): +- whilelo p0.b, xzr, rest +- whilelo p1.b, vector_length, rest +- b.last 1f +- st1b z0.b, p0, [dst, #0, mul vl] +- st1b z0.b, p1, [dst, #1, mul vl] +- ret +-1: lsl tmp1, vector_length, 1 // vector_length * 2 +- whilelo p2.b, tmp1, rest +- incb tmp1 +- whilelo p3.b, tmp1, rest +- b.last 1f +- st1b z0.b, p0, [dst, #0, mul vl] +- st1b z0.b, p1, [dst, #1, mul vl] +- st1b z0.b, p2, [dst, #2, mul vl] +- st1b z0.b, p3, [dst, #3, mul vl] +- ret +-1: lsl tmp1, vector_length, 2 // vector_length * 4 +- whilelo p4.b, tmp1, rest +- incb tmp1 +- whilelo p5.b, tmp1, rest +- incb tmp1 +- whilelo p6.b, tmp1, rest +- incb tmp1 +- whilelo p7.b, tmp1, rest +- st1b z0.b, p0, [dst, #0, mul vl] +- st1b z0.b, p1, [dst, #1, mul vl] +- st1b z0.b, p2, [dst, #2, mul vl] +- st1b z0.b, p3, [dst, #3, mul vl] +- st1b z0.b, p4, [dst, #4, mul vl] +- st1b z0.b, p5, [dst, #5, mul vl] +- st1b z0.b, p6, [dst, #6, mul vl] +- st1b z0.b, p7, [dst, #7, mul vl] ++ cmp count, vector_length, lsl 1 ++ b.ls 2f ++ add tmp2, vector_length, vector_length, lsl 2 ++ cmp count, tmp2 ++ b.ls 5f ++ st1b z0.b, p0, [dstend, -8, mul vl] ++ st1b z0.b, p0, [dstend, -7, mul vl] ++ st1b z0.b, p0, [dstend, -6, mul vl] ++5: st1b z0.b, p0, [dstend, -5, mul vl] ++ st1b z0.b, p0, [dstend, -4, mul vl] ++ st1b z0.b, p0, [dstend, -3, mul vl] ++2: st1b z0.b, p0, [dstend, -2, mul vl] ++ st1b z0.b, p0, [dstend, -1, mul vl] + ret + + L(L1_prefetch): // if rest >= L1_SIZE +@@ -199,7 +180,6 @@ L(L2): + subs count, count, CACHE_LINE_SIZE + b.hi 1b + add count, count, CACHE_LINE_SIZE +- add dst, dst, CACHE_LINE_SIZE + b L(last) + + END (MEMSET) +-- +1.8.3.1 + diff --git a/4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch b/4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch new file mode 100644 index 0000000..fd17671 --- /dev/null +++ b/4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch @@ -0,0 +1,51 @@ +From e69d9981f858a38e19304e6ff5ebdf89f2cb0ba0 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:44:27 +0100 +Subject: [PATCH] [4/5] AArch64: Improve A64FX memset by removing unroll32 + +Remove unroll32 code since it doesn't improve performance. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index 337c86b..ef03156 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -102,22 +102,6 @@ L(vl_agnostic): // VL Agnostic + ccmp vector_length, tmp1, 0, cs + b.eq L(L1_prefetch) + +-L(unroll32): +- lsl tmp1, vector_length, 3 // vector_length * 8 +- lsl tmp2, vector_length, 5 // vector_length * 32 +- .p2align 3 +-1: cmp rest, tmp2 +- b.cc L(unroll8) +- st1b_unroll +- add dst, dst, tmp1 +- st1b_unroll +- add dst, dst, tmp1 +- st1b_unroll +- add dst, dst, tmp1 +- st1b_unroll +- add dst, dst, tmp1 +- sub rest, rest, tmp2 +- b 1b + + L(unroll8): + lsl tmp1, vector_length, 3 +@@ -155,7 +139,7 @@ L(L1_prefetch): // if rest >= L1_SIZE + sub rest, rest, CACHE_LINE_SIZE * 2 + cmp rest, L1_SIZE + b.ge 1b +- cbnz rest, L(unroll32) ++ cbnz rest, L(unroll8) + ret + + // count >= L2_SIZE +-- +1.8.3.1 + diff --git a/5-5-AArch64-Improve-A64FX-memset-medium-loops.patch b/5-5-AArch64-Improve-A64FX-memset-medium-loops.patch new file mode 100644 index 0000000..f8bc03e --- /dev/null +++ b/5-5-AArch64-Improve-A64FX-memset-medium-loops.patch @@ -0,0 +1,96 @@ +From a5db6a5cae6a92d1675c013e5c8d972768721576 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:46:20 +0100 +Subject: [PATCH] [5/5] AArch64: Improve A64FX memset medium loops + +Simplify the code for memsets smaller than L1. Improve the unroll8 and +L1_prefetch loops. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 45 ++++++++++++++------------------ + 1 file changed, 19 insertions(+), 26 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index ef03156..7bf759b 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -30,7 +30,6 @@ + #define L2_SIZE (8*1024*1024) // L2 8MB + #define CACHE_LINE_SIZE 256 + #define PF_DIST_L1 (CACHE_LINE_SIZE * 16) // Prefetch distance L1 +-#define rest x2 + #define vector_length x9 + + #if HAVE_AARCH64_SVE_ASM +@@ -89,29 +88,19 @@ ENTRY (MEMSET) + + .p2align 4 + L(vl_agnostic): // VL Agnostic +- mov rest, count + mov dst, dstin +- add dstend, dstin, count +- // if rest >= L2_SIZE && vector_length == 64 then L(L2) +- mov tmp1, 64 +- cmp rest, L2_SIZE +- ccmp vector_length, tmp1, 0, cs +- b.eq L(L2) +- // if rest >= L1_SIZE && vector_length == 64 then L(L1_prefetch) +- cmp rest, L1_SIZE +- ccmp vector_length, tmp1, 0, cs +- b.eq L(L1_prefetch) +- ++ cmp count, L1_SIZE ++ b.hi L(L1_prefetch) + ++ // count >= 8 * vector_length + L(unroll8): +- lsl tmp1, vector_length, 3 +- .p2align 3 +-1: cmp rest, tmp1 +- b.cc L(last) +- st1b_unroll ++ sub count, count, tmp1 ++ .p2align 4 ++1: st1b_unroll 0, 7 + add dst, dst, tmp1 +- sub rest, rest, tmp1 +- b 1b ++ subs count, count, tmp1 ++ b.hi 1b ++ add count, count, tmp1 + + L(last): + cmp count, vector_length, lsl 1 +@@ -129,18 +118,22 @@ L(last): + st1b z0.b, p0, [dstend, -1, mul vl] + ret + +-L(L1_prefetch): // if rest >= L1_SIZE ++ // count >= L1_SIZE + .p2align 3 ++L(L1_prefetch): ++ cmp count, L2_SIZE ++ b.hs L(L2) ++ cmp vector_length, 64 ++ b.ne L(unroll8) + 1: st1b_unroll 0, 3 + prfm pstl1keep, [dst, PF_DIST_L1] + st1b_unroll 4, 7 + prfm pstl1keep, [dst, PF_DIST_L1 + CACHE_LINE_SIZE] + add dst, dst, CACHE_LINE_SIZE * 2 +- sub rest, rest, CACHE_LINE_SIZE * 2 +- cmp rest, L1_SIZE +- b.ge 1b +- cbnz rest, L(unroll8) +- ret ++ sub count, count, CACHE_LINE_SIZE * 2 ++ cmp count, PF_DIST_L1 ++ b.hs 1b ++ b L(unroll8) + + // count >= L2_SIZE + .p2align 3 +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index a4158e5..2e68546 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 4 +Release: 5 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -90,6 +90,11 @@ Patch9: ldconfig-avoid-leak-on-empty-paths-in-config-file.patch Patch10: Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch Patch11: nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch Patch12: rt-Set-the-correct-message-queue-for-tst-mqueue10.patch +Patch13: 1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch +Patch14: 2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch +Patch15: 3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch +Patch16: 4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch +Patch17: 5-5-AArch64-Improve-A64FX-memset-medium-loops.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1181,6 +1186,9 @@ fi %doc hesiod/README.hesiod %changelog +* Fri Sep 17 2021 Qingqing Li - 2.34-5 +- aarch64: optimize memset performance. + * Fri Sep 17 2021 Qingqing Li - 2.34-4 - backport upstream patches to fix some memory leak and double free bugs -- Gitee From c91dfbc17b4e95d6b34847b148874c45365b147b Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Sun, 26 Sep 2021 09:49:22 +0800 Subject: [PATCH 05/70] aarch64: Make elf_machine_{load_addr,dynamic} robust [BZ #28203] (cherry picked from commit e4fd5bf689c258409e10311fc1500998b8c9f3ad) --- ..._machine_-load_address-dynamic-robus.patch | 72 +++++++ elf-Unconditionally-use-__ehdr_start.patch | 177 ++++++++++++++++++ glibc.spec | 9 +- 3 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 aarch64-Make-elf_machine_-load_address-dynamic-robus.patch create mode 100644 elf-Unconditionally-use-__ehdr_start.patch diff --git a/aarch64-Make-elf_machine_-load_address-dynamic-robus.patch b/aarch64-Make-elf_machine_-load_address-dynamic-robus.patch new file mode 100644 index 0000000..b178499 --- /dev/null +++ b/aarch64-Make-elf_machine_-load_address-dynamic-robus.patch @@ -0,0 +1,72 @@ +From 43d06ed218fc8be58987bdfd00e21e5720f0b862 Mon Sep 17 00:00:00 2001 +From: Fangrui Song +Date: Wed, 11 Aug 2021 09:00:37 -0700 +Subject: [PATCH] aarch64: Make elf_machine_{load_address,dynamic} robust [BZ + #28203] + +The AArch64 ABI is largely platform agnostic and does not specify +_GLOBAL_OFFSET_TABLE_[0] ([1]). glibc ld.so turns out to be probably the +only user of _GLOBAL_OFFSET_TABLE_[0] and GNU ld defines the value +to the link-time address _DYNAMIC. [2] + +In 2012, __ehdr_start was implemented in GNU ld and gold in binutils +2.23. Using adrp+add / (-mcmodel=tiny) adr to access +__ehdr_start/_DYNAMIC gives us a robust way to get the load address and +the link-time address of _DYNAMIC. + +[1]: From a psABI maintainer, https://bugs.llvm.org/show_bug.cgi?id=49672#c2 +[2]: LLD's aarch64 port does not set _GLOBAL_OFFSET_TABLE_[0] to the +link-time address _DYNAMIC. +LLD is widely used on aarch64 Android and ChromeOS devices. Software +just works without the need for _GLOBAL_OFFSET_TABLE_[0]. + +Reviewed-by: Szabolcs Nagy +--- + sysdeps/aarch64/dl-machine.h | 24 +++++++++--------------- + 1 file changed, 9 insertions(+), 15 deletions(-) + +diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +index d29d827..3e10cb4 100644 +--- a/sysdeps/aarch64/dl-machine.h ++++ b/sysdeps/aarch64/dl-machine.h +@@ -37,28 +37,22 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr) + return ehdr->e_machine == EM_AARCH64; + } + +-/* Return the link-time address of _DYNAMIC. Conveniently, this is the +- first element of the GOT. */ +-static inline ElfW(Addr) __attribute__ ((unused)) +-elf_machine_dynamic (void) +-{ +- extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden; +- return _GLOBAL_OFFSET_TABLE_[0]; +-} +- + /* Return the run-time load address of the shared object. */ + + static inline ElfW(Addr) __attribute__ ((unused)) + elf_machine_load_address (void) + { +- /* To figure out the load address we use the definition that for any symbol: +- dynamic_addr(symbol) = static_addr(symbol) + load_addr ++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden; ++ return (ElfW(Addr)) &__ehdr_start; ++} + +- _DYNAMIC sysmbol is used here as its link-time address stored in +- the special unrelocated first GOT entry. */ ++/* Return the link-time address of _DYNAMIC. */ + +- extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; +- return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic (); ++static inline ElfW(Addr) __attribute__ ((unused)) ++elf_machine_dynamic (void) ++{ ++ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; ++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address (); + } + + /* Set up the loaded object described by L so its unrelocated PLT +-- +1.8.3.1 + diff --git a/elf-Unconditionally-use-__ehdr_start.patch b/elf-Unconditionally-use-__ehdr_start.patch new file mode 100644 index 0000000..b30438d --- /dev/null +++ b/elf-Unconditionally-use-__ehdr_start.patch @@ -0,0 +1,177 @@ +From 302247c89121e8d4c7629e589edbb4974fff6edb Mon Sep 17 00:00:00 2001 +From: Fangrui Song +Date: Tue, 10 Aug 2021 11:04:56 -0700 +Subject: [PATCH] elf: Unconditionally use __ehdr_start + +We can consider __ehdr_start (from binutils 2.23 onwards) +unconditionally supported, since configure.ac requires binutils>=2.25. + +The configure.ac check is related to an ia64 bug fixed by binutils 2.24. +See https://sourceware.org/pipermail/libc-alpha/2014-August/053503.html + +Tested on x86_64-linux-gnu. Tested build-many-glibcs.py with +aarch64-linux-gnu and s390x-linux-gnu. + +Reviewed-by: Szabolcs Nagy +--- + config.h.in | 3 --- + configure | 52 ---------------------------------------------------- + configure.ac | 34 ---------------------------------- + elf/rtld.c | 13 ++++--------- + 4 files changed, 4 insertions(+), 98 deletions(-) + +diff --git a/config.h.in b/config.h.in +index 8b45a3a..0d92504 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -198,9 +198,6 @@ + /* Define if CC supports attribute retain. */ + #undef HAVE_GNU_RETAIN + +-/* Define if the linker defines __ehdr_start. */ +-#undef HAVE_EHDR_START +- + /* Define to 1 if the assembler needs intermediate aliases to define + multiple symbol versions for one symbol. */ + #define SYMVER_NEEDS_ALIAS 0 +diff --git a/configure b/configure +index 9619c10..7272fbf 100755 +--- a/configure ++++ b/configure +@@ -6636,58 +6636,6 @@ if test $libc_cv_predef_fortify_source = yes; then + fi + + +-# Some linkers on some architectures support __ehdr_start but with +-# bugs. Make sure usage of it does not create relocations in the +-# output (as the linker should resolve them all for us). +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker provides working __ehdr_start" >&5 +-$as_echo_n "checking whether the linker provides working __ehdr_start... " >&6; } +-if ${libc_cv_ehdr_start+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +-old_CFLAGS="$CFLAGS" +-old_LDFLAGS="$LDFLAGS" +-old_LIBS="$LIBS" +-CFLAGS="$CFLAGS -fPIC" +-LDFLAGS="$LDFLAGS -nostdlib -nostartfiles -shared $no_ssp" +-LIBS= +-cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-typedef struct { +- char foo; +- long val; +-} Ehdr; +-extern const Ehdr __ehdr_start __attribute__ ((visibility ("hidden"))); +-long ehdr (void) { return __ehdr_start.val; } +- +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- if $READELF -r conftest | grep -F __ehdr_start >/dev/null; then +- libc_cv_ehdr_start=broken +- else +- libc_cv_ehdr_start=yes +- fi +-else +- libc_cv_ehdr_start=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +-CFLAGS="$old_CFLAGS" +-LDFLAGS="$old_LDFLAGS" +-LIBS="$old_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ehdr_start" >&5 +-$as_echo "$libc_cv_ehdr_start" >&6; } +-if test "$libc_cv_ehdr_start" = yes; then +- $as_echo "#define HAVE_EHDR_START 1" >>confdefs.h +- +-elif test "$libc_cv_ehdr_start" = broken; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: linker is broken -- you should upgrade" >&5 +-$as_echo "$as_me: WARNING: linker is broken -- you should upgrade" >&2;} +-fi +- + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the assembler requires one version per symbol" >&5 + $as_echo_n "checking whether the assembler requires one version per symbol... " >&6; } + if ${libc_cv_symver_needs_alias+:} false; then : +diff --git a/configure.ac b/configure.ac +index 34ecbba..af47cd5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1662,40 +1662,6 @@ if test $libc_cv_predef_fortify_source = yes; then + fi + AC_SUBST(CPPUNDEFS) + +-# Some linkers on some architectures support __ehdr_start but with +-# bugs. Make sure usage of it does not create relocations in the +-# output (as the linker should resolve them all for us). +-AC_CACHE_CHECK([whether the linker provides working __ehdr_start], +- libc_cv_ehdr_start, [ +-old_CFLAGS="$CFLAGS" +-old_LDFLAGS="$LDFLAGS" +-old_LIBS="$LIBS" +-CFLAGS="$CFLAGS -fPIC" +-LDFLAGS="$LDFLAGS -nostdlib -nostartfiles -shared $no_ssp" +-LIBS= +-AC_LINK_IFELSE([AC_LANG_SOURCE([ +-typedef struct { +- char foo; +- long val; +-} Ehdr; +-extern const Ehdr __ehdr_start __attribute__ ((visibility ("hidden"))); +-long ehdr (void) { return __ehdr_start.val; } +-])], +- [if $READELF -r conftest | grep -F __ehdr_start >/dev/null; then +- libc_cv_ehdr_start=broken +- else +- libc_cv_ehdr_start=yes +- fi], [libc_cv_ehdr_start=no]) +-CFLAGS="$old_CFLAGS" +-LDFLAGS="$old_LDFLAGS" +-LIBS="$old_LIBS" +-]) +-if test "$libc_cv_ehdr_start" = yes; then +- AC_DEFINE([HAVE_EHDR_START]) +-elif test "$libc_cv_ehdr_start" = broken; then +- AC_MSG_WARN([linker is broken -- you should upgrade]) +-fi +- + dnl Starting with binutils 2.35, GAS can attach multiple symbol versions + dnl to one symbol (PR 23840). + AC_CACHE_CHECK(whether the assembler requires one version per symbol, +diff --git a/elf/rtld.c b/elf/rtld.c +index d733359..878e648 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1684,21 +1684,16 @@ dl_main (const ElfW(Phdr) *phdr, + if (GLRO(dl_use_load_bias) == (ElfW(Addr)) -2) + GLRO(dl_use_load_bias) = main_map->l_addr == 0 ? -1 : 0; + +- /* Set up the program header information for the dynamic linker +- itself. It is needed in the dl_iterate_phdr callbacks. */ +- const ElfW(Ehdr) *rtld_ehdr; +- + /* Starting from binutils-2.23, the linker will define the magic symbol + __ehdr_start to point to our own ELF header if it is visible in a + segment that also includes the phdrs. If that's not available, we use + the old method that assumes the beginning of the file is part of the + lowest-addressed PT_LOAD segment. */ +-#ifdef HAVE_EHDR_START + extern const ElfW(Ehdr) __ehdr_start __attribute__ ((visibility ("hidden"))); +- rtld_ehdr = &__ehdr_start; +-#else +- rtld_ehdr = (void *) GL(dl_rtld_map).l_map_start; +-#endif ++ ++ /* Set up the program header information for the dynamic linker ++ itself. It is needed in the dl_iterate_phdr callbacks. */ ++ const ElfW(Ehdr) *rtld_ehdr = &__ehdr_start; + assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr); + assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr))); + +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index 2e68546..a4c1625 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 5 +Release: 6 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -95,6 +95,8 @@ Patch14: 2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch Patch15: 3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch Patch16: 4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch Patch17: 5-5-AArch64-Improve-A64FX-memset-medium-loops.patch +Patch18: elf-Unconditionally-use-__ehdr_start.patch +Patch19: aarch64-Make-elf_machine_-load_address-dynamic-robus.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1186,6 +1188,11 @@ fi %doc hesiod/README.hesiod %changelog +* Sun Sep 26 2021 Qingqing Li - 2.34-6 +- elf: Unconditionally use __ehdr_start. +- aarch64: Make elf_machine_{load_addr,dynamic} robust [BZ #28203]. + upstream link: https://sourceware.org/bugzilla/show_bug.cgi?id=28203 + * Fri Sep 17 2021 Qingqing Li - 2.34-5 - aarch64: optimize memset performance. -- Gitee From 270c700e660d92b99526205fdeaeab87acf19cf4 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 27 Sep 2021 19:17:12 +0800 Subject: [PATCH 06/70] mtrace: use a static buffer for printing, fix upstream bug BZ #25947 (cherry picked from commit 8b0605e3bfb2c5f594f8d16b2ff802e59df24c18) --- glibc.spec | 7 ++- ...-static-buffer-for-printing-BZ-25947.patch | 61 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch diff --git a/glibc.spec b/glibc.spec index a4c1625..b6f43de 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 6 +Release: 7 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -97,6 +97,7 @@ Patch16: 4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch Patch17: 5-5-AArch64-Improve-A64FX-memset-medium-loops.patch Patch18: elf-Unconditionally-use-__ehdr_start.patch Patch19: aarch64-Make-elf_machine_-load_address-dynamic-robus.patch +Patch20: mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1188,6 +1189,10 @@ fi %doc hesiod/README.hesiod %changelog +* Mon Sep 27 2021 Qingqing Li - 2.34-7 +- mtrace: use a static buffer for printing, fix memory leak. + upstream link: https://sourceware.org/bugzilla/show_bug.cgi?id=25947 + * Sun Sep 26 2021 Qingqing Li - 2.34-6 - elf: Unconditionally use __ehdr_start. - aarch64: Make elf_machine_{load_addr,dynamic} robust [BZ #28203]. diff --git a/mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch b/mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch new file mode 100644 index 0000000..9c25d43 --- /dev/null +++ b/mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch @@ -0,0 +1,61 @@ +From dc906e94f7033892dadbd91718349f19e1376391 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Thu, 12 Aug 2021 06:38:15 +0530 +Subject: [PATCH] mtrace: Use a static buffer for printing [BZ #25947] + +Use a static buffer for mtrace printing now that it no longer adds to +default libc footprint. + +Reviewed-by: DJ Delorie +--- + malloc/mtrace-impl.c | 14 +++----------- + 1 file changed, 3 insertions(+), 11 deletions(-) + +diff --git a/malloc/mtrace-impl.c b/malloc/mtrace-impl.c +index 0e10ab7..83008ca 100644 +--- a/malloc/mtrace-impl.c ++++ b/malloc/mtrace-impl.c +@@ -34,11 +34,8 @@ + + #include + +-#define TRACE_BUFFER_SIZE 512 +- + static FILE *mallstream; + static const char mallenv[] = "MALLOC_TRACE"; +-static char *malloc_trace_buffer; + + static void + tr_where (const void *caller, Dl_info *info) +@@ -184,16 +181,13 @@ do_mtrace (void) + mallfile = secure_getenv (mallenv); + if (mallfile != NULL) + { +- char *mtb = malloc (TRACE_BUFFER_SIZE); +- if (mtb == NULL) +- return; +- + mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce"); + if (mallstream != NULL) + { + /* Be sure it doesn't malloc its buffer! */ +- malloc_trace_buffer = mtb; +- setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE); ++ static char tracebuf [512]; ++ ++ setvbuf (mallstream, tracebuf, _IOFBF, sizeof (tracebuf)); + fprintf (mallstream, "= Start\n"); + if (!added_atexit_handler) + { +@@ -203,8 +197,6 @@ do_mtrace (void) + } + __malloc_debug_enable (MALLOC_MTRACE_HOOK); + } +- else +- free (mtb); + } + } + +-- +1.8.3.1 + -- Gitee From cf356da366456c69e5b2578bd42ec0db34f96dc4 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Wed, 29 Sep 2021 10:36:09 +0800 Subject: [PATCH 07/70] time fix overflow itimer tests on 32 bit system (cherry picked from commit 60314ef12d246e73f1ac04308ff9bda01d3c8ab6) --- glibc.spec | 6 +- ...rflow-itimer-tests-on-32-bit-systems.patch | 90 +++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 time-Fix-overflow-itimer-tests-on-32-bit-systems.patch diff --git a/glibc.spec b/glibc.spec index b6f43de..8489901 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 7 +Release: 8 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -98,6 +98,7 @@ Patch17: 5-5-AArch64-Improve-A64FX-memset-medium-loops.patch Patch18: elf-Unconditionally-use-__ehdr_start.patch Patch19: aarch64-Make-elf_machine_-load_address-dynamic-robus.patch Patch20: mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch +Patch21: time-Fix-overflow-itimer-tests-on-32-bit-systems.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1189,6 +1190,9 @@ fi %doc hesiod/README.hesiod %changelog +* Wed Sep 29 2021 Qingqing Li - 2.34-8 +- fix overflow ittimer tests on 32 bit system + * Mon Sep 27 2021 Qingqing Li - 2.34-7 - mtrace: use a static buffer for printing, fix memory leak. upstream link: https://sourceware.org/bugzilla/show_bug.cgi?id=25947 diff --git a/time-Fix-overflow-itimer-tests-on-32-bit-systems.patch b/time-Fix-overflow-itimer-tests-on-32-bit-systems.patch new file mode 100644 index 0000000..939e816 --- /dev/null +++ b/time-Fix-overflow-itimer-tests-on-32-bit-systems.patch @@ -0,0 +1,90 @@ +From 6e8a0aac2f883a23efb1683b120499138f9e6021 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Mon, 7 Jun 2021 22:10:19 +0900 +Subject: [PATCH] time: Fix overflow itimer tests on 32-bit systems + +On the port of OpenRISC I am working on and it appears the rv32 port +we have sets __TIMESIZE == 64 && __WORDSIZE == 32. This causes the +size of time_t to be 8 bytes, but the tv_sec in the kernel is still 32-bit +causing truncation. + +The truncations are unavoidable on these systems so skip the +testing/failures by guarding with __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64. + +Also, futher in the tests and in other parts of code checking for time_t +overflow does not work on 32-bit systems when time_t is 64-bit. As +suggested by Adhemerval, update the in_time_t_range function to assume +32-bits by using int32_t. + +This also brings in the header for stdint.h so we can update other +usages of __int32_t to int32_t as suggested by Adhemerval. + +Reviewed-by: Adhemerval Zanella +--- + include/time.h | 10 ++++++---- + time/tst-itimer.c | 4 ++-- + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/include/time.h b/include/time.h +index 22b29ca..127347e 100644 +--- a/include/time.h ++++ b/include/time.h +@@ -11,6 +11,7 @@ + # include + # include + # include ++# include + + extern __typeof (strftime_l) __strftime_l; + libc_hidden_proto (__strftime_l) +@@ -342,11 +343,12 @@ libc_hidden_proto (__time64) + actual clock ID. */ + #define CLOCK_IDFIELD_SIZE 3 + +-/* Check whether T fits in time_t. */ ++/* Check whether T fits in int32_t, assume all usages are for ++ sizeof(time_t) == 32. */ + static inline bool + in_time_t_range (__time64_t t) + { +- time_t s = t; ++ int32_t s = t; + return s == t; + } + +@@ -453,8 +455,8 @@ timespec64_to_timeval64 (const struct __timespec64 ts64) + and suseconds_t. */ + struct __timeval32 + { +- __int32_t tv_sec; /* Seconds. */ +- __int32_t tv_usec; /* Microseconds. */ ++ int32_t tv_sec; /* Seconds. */ ++ int32_t tv_usec; /* Microseconds. */ + }; + + /* Conversion functions for converting to/from __timeval32 */ +diff --git a/time/tst-itimer.c b/time/tst-itimer.c +index 929c2b7..bd7d7af 100644 +--- a/time/tst-itimer.c ++++ b/time/tst-itimer.c +@@ -100,7 +100,7 @@ do_test (void) + + /* Linux does not provide 64 bit time_t support for getitimer and + setitimer on architectures with 32 bit time_t support. */ +- if (sizeof (__time_t) == 8) ++ if (__KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64) + { + TEST_COMPARE (setitimer (timers[i], &it, NULL), 0); + TEST_COMPARE (setitimer (timers[i], &(struct itimerval) { 0 }, +@@ -131,7 +131,7 @@ do_test (void) + it.it_interval.tv_usec = 20; + it.it_value.tv_sec = 30; + it.it_value.tv_usec = 40; +- if (sizeof (__time_t) == 8) ++ if (__KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64) + { + TEST_COMPARE (setitimer (timers[i], &it, NULL), 0); + +-- +1.8.3.1 + -- Gitee From 353770b818eb4042be24ee79b7a81c896ebf9c22 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Wed, 29 Sep 2021 11:52:32 +0800 Subject: [PATCH 08/70] elf: drop elf/tls-macros.h in favor of thread tls_mode attribute. use __ehdr_start for __GLOBAL_OFFSET_TABLE[0] (cherry picked from commit 39ba9372151901720447a246c3293e862e7c0d39) --- Remove-sysdeps-tls-macros.h.patch | 1810 +++++++++++++++++ ...fy-elf_machine_-load_address-dynamic.patch | 82 + ...-macros.h-in-favor-of-__thread-and-t.patch | 543 +++++ ...colon-in-LD_SHOW_AUXV-output-BZ-2825.patch | 27 + glibc.spec | 13 +- ...-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch | 60 + ...-caching-of-instruction-support-chec.patch | 178 ++ ...fy-elf_machine_-load_address-dynamic.patch | 55 + 8 files changed, 2767 insertions(+), 1 deletion(-) create mode 100644 Remove-sysdeps-tls-macros.h.patch create mode 100644 arm-Simplify-elf_machine_-load_address-dynamic.patch create mode 100644 elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch create mode 100644 elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch create mode 100644 riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch create mode 100644 x86-fix-Autoconf-caching-of-instruction-support-chec.patch create mode 100644 x86_64-Simplify-elf_machine_-load_address-dynamic.patch diff --git a/Remove-sysdeps-tls-macros.h.patch b/Remove-sysdeps-tls-macros.h.patch new file mode 100644 index 0000000..82561b7 --- /dev/null +++ b/Remove-sysdeps-tls-macros.h.patch @@ -0,0 +1,1810 @@ +From 710ba420fd417a4a82e0ad2e998e5f3b972cb503 Mon Sep 17 00:00:00 2001 +From: Fangrui Song +Date: Wed, 18 Aug 2021 09:15:20 -0700 +Subject: [PATCH] Remove sysdeps/*/tls-macros.h + +They provide TLS_GD/TLS_LD/TLS_IE/TLS_IE macros for TLS testing. Now +that we have migrated to __thread and tls_model attributes, these macros +are unused and the tls-macros.h files can retire. + +Reviewed-by: Szabolcs Nagy +--- + benchtests/strcoll-inputs/filelist#en_US.UTF-8 | 22 ---- + sysdeps/aarch64/tls-macros.h | 51 --------- + sysdeps/alpha/tls-macros.h | 25 ----- + sysdeps/arc/tls-macros.h | 47 -------- + sysdeps/arm/tls-macros.h | 72 ------------- + sysdeps/csky/abiv2/tls-macros.h | 55 ---------- + sysdeps/generic/tls-macros.h | 12 --- + sysdeps/hppa/tls-macros.h | 114 -------------------- + sysdeps/i386/tls-macros.h | 47 -------- + sysdeps/ia64/tls-macros.h | 66 ------------ + sysdeps/m68k/tls-macros.h | 68 ------------ + sysdeps/microblaze/tls-macros.h | 46 -------- + sysdeps/mips/tls-macros.h | 130 ---------------------- + sysdeps/nios2/tls-macros.h | 46 -------- + sysdeps/powerpc/powerpc32/tls-macros.h | 49 --------- + sysdeps/powerpc/powerpc64/tls-macros.h | 42 -------- + sysdeps/powerpc/tls-macros.h | 3 - + sysdeps/riscv/tls-macros.h | 47 -------- + sysdeps/s390/s390-32/tls-macros.h | 106 ------------------ + sysdeps/s390/s390-64/tls-macros.h | 90 ---------------- + sysdeps/sh/tls-macros.h | 143 ------------------------- + sysdeps/sparc/sparc32/tls-macros.h | 66 ------------ + sysdeps/sparc/sparc64/tls-macros.h | 65 ----------- + sysdeps/x86_64/tls-macros.h | 39 ------- + 24 files changed, 1451 deletions(-) + delete mode 100644 sysdeps/aarch64/tls-macros.h + delete mode 100644 sysdeps/alpha/tls-macros.h + delete mode 100644 sysdeps/arc/tls-macros.h + delete mode 100644 sysdeps/arm/tls-macros.h + delete mode 100644 sysdeps/csky/abiv2/tls-macros.h + delete mode 100644 sysdeps/generic/tls-macros.h + delete mode 100644 sysdeps/hppa/tls-macros.h + delete mode 100644 sysdeps/i386/tls-macros.h + delete mode 100644 sysdeps/ia64/tls-macros.h + delete mode 100644 sysdeps/m68k/tls-macros.h + delete mode 100644 sysdeps/microblaze/tls-macros.h + delete mode 100644 sysdeps/mips/tls-macros.h + delete mode 100644 sysdeps/nios2/tls-macros.h + delete mode 100644 sysdeps/powerpc/powerpc32/tls-macros.h + delete mode 100644 sysdeps/powerpc/powerpc64/tls-macros.h + delete mode 100644 sysdeps/powerpc/tls-macros.h + delete mode 100644 sysdeps/riscv/tls-macros.h + delete mode 100644 sysdeps/s390/s390-32/tls-macros.h + delete mode 100644 sysdeps/s390/s390-64/tls-macros.h + delete mode 100644 sysdeps/sh/tls-macros.h + delete mode 100644 sysdeps/sparc/sparc32/tls-macros.h + delete mode 100644 sysdeps/sparc/sparc64/tls-macros.h + delete mode 100644 sysdeps/x86_64/tls-macros.h + +diff --git a/benchtests/strcoll-inputs/filelist#en_US.UTF-8 b/benchtests/strcoll-inputs/filelist#en_US.UTF-8 +index 43eb9ef..197700e 100644 +--- a/benchtests/strcoll-inputs/filelist#en_US.UTF-8 ++++ b/benchtests/strcoll-inputs/filelist#en_US.UTF-8 +@@ -3195,7 +3195,6 @@ Implies + submul_1.S + sysdep.h + add_n.S +-tls-macros.h + libc-tls.c + sub_n.S + libgcc-compat.c +@@ -3443,7 +3442,6 @@ libresolv.abilist + thread_state.h + pty-private.h + ldconfig.h +-tls-macros.h + fd_to_filename.h + not-cancel.h + safe-fatal.h +@@ -3605,7 +3603,6 @@ start.S + tst-mode-switch-3.c + addmul_1.S + add_n.S +-tls-macros.h + libc-tls.c + sub_n.S + strcmp.S +@@ -3921,7 +3918,6 @@ addmul_1.S + pthread_spin_trylock.S + add_n.S + e_sqrt.c +-tls-macros.h + sub_n.S + strcmp.S + strlen.S +@@ -4138,7 +4134,6 @@ addmul_1.S + pthread_spin_trylock.S + add_n.S + rtld-memset.c +-tls-macros.h + sub_n.S + strcmp.S + strlen.S +@@ -4651,7 +4646,6 @@ addmul_1.S + sysdep.h + strlen.c + add_n.S +-tls-macros.h + sub_n.S + i786 + Implies +@@ -4712,7 +4706,6 @@ Makefile + start.S + libm-test-ulps + sysdep.h +-tls-macros.h + libc-tls.c + tst-audit.h + dl-machine.h +@@ -5071,7 +5064,6 @@ addmul_1.S + sysdep.h + add_n.S + wcschr.S +-tls-macros.h + sub_n.S + tst-quad2.c + strcmp.S +@@ -6337,7 +6329,6 @@ Makefile + start.S + libm-test-ulps + sysdep.h +-tls-macros.h + libc-tls.c + strlen.S + tst-audit.h +@@ -6447,7 +6438,6 @@ strstr.c + string-endian.h + memcmp.c + sysdep.h +-tls-macros.h + tst-audit.h + dl-machine.h + dl-tls.h +@@ -6581,7 +6571,6 @@ Makefile + start.S + libm-test-ulps + sysdep.h +-tls-macros.h + libc-tls.c + strcmp.S + strrchr.S +@@ -7004,7 +6993,6 @@ addmul_1.S + Implies + sysdep.h + rtld-memset.c +-tls-macros.h + strcmp.S + strlen.S + tst-audit.h +@@ -7124,7 +7112,6 @@ wcschr.c + Makefile + ffs.c + sysdep.h +-tls-macros.h + test-arithf.c + nofpu + atomic-feupdateenv.c +@@ -7386,7 +7373,6 @@ gprrest0.S + sysdep.h + add_n.S + rtld-memset.c +-tls-macros.h + sub_n.S + strcmp.S + strlen.S +@@ -7969,7 +7955,6 @@ memcmp.S + Makefile + start.S + sysdep.h +-tls-macros.h + libc-tls.c + strcmp.S + sched_cpucount.c +@@ -8197,7 +8182,6 @@ start.S + addmul_1.S + nscd-types.h + add_n.S +-tls-macros.h + libc-tls.c + sub_n.S + divqu.S +@@ -8318,7 +8302,6 @@ Makefile + ffs.c + start.S + sysdep.h +-tls-macros.h + libc-tls.c + tst-audit.h + wcpcpy.c +@@ -8628,7 +8611,6 @@ Makefile + start.S + sysdep.h + add_n.S +-tls-macros.h + sub_n.S + strcmp.S + tst-audit.h +@@ -8690,7 +8672,6 @@ start.S + addmul_1.S + sysdep.h + add_n.S +-tls-macros.h + sub_n.S + strcmp.S + tst-audit.h +@@ -8796,7 +8777,6 @@ ftestexcept.c + rt-aeabi_unwind_cpp_pr1.c + sysdep.h + add_n.S +-tls-macros.h + libc-tls.c + sub_n.S + strlen.S +@@ -8879,7 +8859,6 @@ Makefile + start.S + libm-test-ulps + sysdep.h +-tls-macros.h + libc-tls.c + tst-audit.h + dl-machine.h +@@ -12064,7 +12043,6 @@ nodelmod4.c + dl-fini.c + unload2dep.c + unload8.c +-tls-macros.h + unload4.c + tst-array5.exp + unload4mod2.c +diff --git a/sysdeps/aarch64/tls-macros.h b/sysdeps/aarch64/tls-macros.h +deleted file mode 100644 +index 33883dc..0000000 +--- a/sysdeps/aarch64/tls-macros.h ++++ /dev/null +@@ -1,51 +0,0 @@ +-/* Copyright (C) 2009-2021 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 +- . */ +- +-#define TLS_LD(x) TLS_GD(x) +- +-#define TLS_GD(x) \ +- ({ register unsigned long __result asm ("x0"); \ +- asm ("adrp %0, :tlsgd:" #x "; " \ +- "add %0, %0, #:tlsgd_lo12:" #x "; " \ +- "bl __tls_get_addr;" \ +- "nop" \ +- : "=r" (__result) \ +- : \ +- : "x1", "x2", "x3", "x4", "x5", "x6", \ +- "x7", "x8", "x9", "x10", "x11", "x12", \ +- "x13", "x14", "x15", "x16", "x17", "x18", \ +- "x30", "memory", "cc"); \ +- (int *) (__result); }) +- +-#define TLS_IE(x) \ +- ({ register unsigned long __result asm ("x0"); \ +- register unsigned long __t; \ +- asm ("mrs %1, tpidr_el0; " \ +- "adrp %0, :gottprel:" #x "; " \ +- "ldr %0, [%0, #:gottprel_lo12:" #x "]; " \ +- "add %0, %0, %1" \ +- : "=r" (__result), "=r" (__t)); \ +- (int *) (__result); }) +- +-#define TLS_LE(x) \ +- ({ register unsigned long __result asm ("x0"); \ +- asm ("mrs %0, tpidr_el0; " \ +- "add %0, %0, :tprel_hi12:" #x "; " \ +- "add %0, %0, :tprel_lo12_nc:" #x \ +- : "=r" (__result)); \ +- (int *) (__result); }) +diff --git a/sysdeps/alpha/tls-macros.h b/sysdeps/alpha/tls-macros.h +deleted file mode 100644 +index 00489c2..0000000 +--- a/sysdeps/alpha/tls-macros.h ++++ /dev/null +@@ -1,25 +0,0 @@ +-/* Macros to support TLS testing in times of missing compiler support. */ +- +-extern void *__tls_get_addr (void *); +- +-# define TLS_GD(x) \ +- ({ register void *__gp asm ("$29"); void *__result; \ +- asm ("lda %0, " #x "($gp) !tlsgd" : "=r" (__result) : "r"(__gp)); \ +- __tls_get_addr (__result); }) +- +-# define TLS_LD(x) \ +- ({ register void *__gp asm ("$29"); void *__result; \ +- asm ("lda %0, " #x "($gp) !tlsldm" : "=r" (__result) : "r"(__gp)); \ +- __result = __tls_get_addr (__result); \ +- asm ("lda %0, " #x "(%0) !dtprel" : "+r" (__result)); \ +- __result; }) +- +-# define TLS_IE(x) \ +- ({ register void *__gp asm ("$29"); long ofs; \ +- asm ("ldq %0, " #x "($gp) !gottprel" : "=r"(ofs) : "r"(__gp)); \ +- __builtin_thread_pointer () + ofs; }) +- +-# define TLS_LE(x) \ +- ({ void *__result = __builtin_thread_pointer (); \ +- asm ("lda %0, " #x "(%0) !tprel" : "+r" (__result)); \ +- __result; }) +diff --git a/sysdeps/arc/tls-macros.h b/sysdeps/arc/tls-macros.h +deleted file mode 100644 +index b0003d8..0000000 +--- a/sysdeps/arc/tls-macros.h ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* Macros to support TLS testing in times of missing compiler support. ARC version. +- Copyright (C) 2020-2021 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 +- . */ +- +- +-/* For now. */ +-#define TLS_LD(x) TLS_IE(x) +- +-#define TLS_GD(x) \ +- ({ void *__result; \ +- __asm__ ("add r0, pcl, @" #x "@tlsgd \n" \ +- ".tls_gd_ld " #x "`bl __tls_get_addr@plt \n" \ +- "mov %0, r0 \n" \ +- : "=&r" (__result) \ +- ::"r0","r1","r2","r3","r4","r5","r6","r7", \ +- "r8","r9","r10","r11","r12"); \ +- __result; }) +- +-#define TLS_LE(x) \ +- ({ void *__result; \ +- void *tp = __builtin_thread_pointer (); \ +- __asm__ ("add %0, %1, @" #x "@tpoff \n" \ +- : "=r" (__result) : "r"(tp)); \ +- __result; }) +- +-#define TLS_IE(x) \ +- ({ void *__result; \ +- void *tp = __builtin_thread_pointer (); \ +- __asm__ ("ld %0, [pcl, @" #x "@tlsie] \n" \ +- "add %0, %1, %0 \n" \ +- : "=&r" (__result) : "r" (tp)); \ +- __result; }) +diff --git a/sysdeps/arm/tls-macros.h b/sysdeps/arm/tls-macros.h +deleted file mode 100644 +index 25cd849..0000000 +--- a/sysdeps/arm/tls-macros.h ++++ /dev/null +@@ -1,72 +0,0 @@ +-#include /* For ARCH_HAS_T2. */ +- +-#ifdef __thumb2__ +-# define ARM_PC_OFFSET "4" +-#else +-# define ARM_PC_OFFSET "8" +-#endif +- +-/* Returns the address of data containing ".word SYMBOL(RELOC)". */ +-#if defined (ARCH_HAS_T2) && !defined (PIC) +-# define GET_SPECIAL_RELOC(symbol, reloc) \ +- ({ \ +- int *__##symbol##_rodata; \ +- asm ("movw %0, #:lower16:1f\n" \ +- "movt %0, #:upper16:1f\n" \ +- ".pushsection .rodata.cst4, \"aM\", %%progbits, 4\n" \ +- ".balign 4\n" \ +- "1: .word " #symbol "(" #reloc ")\n" \ +- ".popsection" \ +- : "=r" (__##symbol##_rodata)); \ +- __##symbol##_rodata; \ +- }) +-#elif defined (ARCH_HAS_T2) && defined (PIC) && ARM_PCREL_MOVW_OK +-# define GET_SPECIAL_RELOC(symbol, reloc) \ +- ({ \ +- int *__##symbol##_rodata; \ +- asm ("movw %0, #:lower16:1f - 2f - " ARM_PC_OFFSET "\n" \ +- "movt %0, #:upper16:1f - 2f - " ARM_PC_OFFSET "\n" \ +- ".pushsection .rodata.cst4, \"aM\", %%progbits, 4\n" \ +- ".balign 4\n" \ +- "1: .word " #symbol "(" #reloc ")\n" \ +- ".popsection\n" \ +- "2: add %0, %0, pc" \ +- : "=r" (__##symbol##_rodata)); \ +- __##symbol##_rodata; \ +- }) +-#else +-# define GET_SPECIAL_RELOC(symbol, reloc) \ +- ({ \ +- int *__##symbol##_rodata; \ +- asm ("adr %0, 1f\n" \ +- "b 2f\n" \ +- ".balign 4\n" \ +- "1: .word " #symbol "(" #reloc ")\n" \ +- "2:" \ +- : "=r" (__##symbol##_rodata)); \ +- __##symbol##_rodata; \ +- }) +-#endif +- +-/* Returns the pointer value (SYMBOL(RELOC) + pc - PC_OFS). */ +-#define GET_SPECIAL_PCREL(symbol, reloc) \ +- ({ \ +- int *__##symbol##_rodata = GET_SPECIAL_RELOC (symbol, reloc); \ +- (void *) ((int) __##symbol##_rodata + *__##symbol##_rodata); \ +- }) +- +-#define TLS_LE(x) \ +- (__builtin_thread_pointer () + *GET_SPECIAL_RELOC (x, tpoff)) +- +-#define TLS_IE(x) \ +- ((int *) (__builtin_thread_pointer () \ +- + *(int *) GET_SPECIAL_PCREL (x, gottpoff))) +- +-extern void *__tls_get_addr (void *); +- +-#define TLS_LD(x) \ +- ((int *) (__tls_get_addr (GET_SPECIAL_PCREL (x, tlsldm)) \ +- + *GET_SPECIAL_RELOC (x, tlsldo))) +- +-#define TLS_GD(x) \ +- ((int *) __tls_get_addr (GET_SPECIAL_PCREL (x, tlsgd))) +diff --git a/sysdeps/csky/abiv2/tls-macros.h b/sysdeps/csky/abiv2/tls-macros.h +deleted file mode 100644 +index 57ed1e7..0000000 +--- a/sysdeps/csky/abiv2/tls-macros.h ++++ /dev/null +@@ -1,55 +0,0 @@ +-/* Macros for accessing thread-local storage. C-SKY ABIV2 version. +- Copyright (C) 2018-2021 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 +- . */ +- +-# define TLS_LE(x) \ +- ({ int *__result; \ +- __asm__ ("lrw %0, " #x "@TPOFF\n\t" \ +- "add %0, tls, %0" \ +- : "=&r" (__result)); \ +- __result; }) +- +-# define TLS_IE(x) \ +- ({ int *__result; \ +- __asm__ ("grs a1, 1f\n" \ +- "1:\tlrw %0, " #x "@GOTTPOFF\n\t" \ +- "ldr.w %0, (a1, %0 << 0)\n\t" \ +- "add %0, tls, %0" \ +- : "=&r" (__result): : "a1"); \ +- __result; }) +- +-# define TLS_LD(x) \ +- ({ char *__result; \ +- int __offset; \ +- extern void *__tls_get_addr (void *); \ +- __asm__ ("grs a1, 1f\n" \ +- "1:\tlrw %0, " #x "@TLSLDM32;\n\t" \ +- "add %0, a1, %0" \ +- : "=r" (__result) : : "a1"); \ +- __result = (char *)__tls_get_addr (__result); \ +- __asm__ ("lrw %0, " #x "@TLSLDO32" \ +- : "=r" (__offset)); \ +- (int *) (__result + __offset); }) +- +-# define TLS_GD(x) \ +- ({ int *__result; \ +- extern void *__tls_get_addr (void *); \ +- __asm__ ("grs a1, 1f\n" \ +- "1:\tlrw %0, " #x "@TLSGD32\n\t" \ +- "add %0, a1, %0" \ +- : "=r" (__result) : : "a1"); \ +- (int *)__tls_get_addr (__result); }) +diff --git a/sysdeps/generic/tls-macros.h b/sysdeps/generic/tls-macros.h +deleted file mode 100644 +index 0a08f7c..0000000 +--- a/sysdeps/generic/tls-macros.h ++++ /dev/null +@@ -1,12 +0,0 @@ +-/* Macros to support TLS testing in times of missing compiler support. +- Stub version. +- +- These macros should yield int * expressions for the TLS symbol X +- accessed using the various TLS access models. Macros for some machines +- are defined in elf/tls-macros.h, but ports can instead provide this file. +- +-#define TLS_LE(x) +-#define TLS_IE(x) +-#define TLS_LD(x) +-#define TLS_GD(x) +-*/ +diff --git a/sysdeps/hppa/tls-macros.h b/sysdeps/hppa/tls-macros.h +deleted file mode 100644 +index 38edb1b..0000000 +--- a/sysdeps/hppa/tls-macros.h ++++ /dev/null +@@ -1,114 +0,0 @@ +-/* TLS Access Macros for HP PARISC Linux */ +- +-/* HPPA Local Exec TLS access. */ +-#define TLS_LE(x) \ +- ({ int * __result; \ +- unsigned long __tmp; \ +- asm ( \ +- " mfctl %%cr27, %1\n" \ +- " addil LR'" #x "-$tls_leoff$, %1\n" \ +- " ldo RR'" #x "-$tls_leoff$(%%r1), %0\n" \ +- : "=r" (__result), "=r" (__tmp) \ +- : \ +- : "r1" ); \ +- __result; \ +- }) +- +-/* HPPA Initial Exec TLS access. */ +-#ifdef PIC +-# define TLS_IE(x) \ +- ({ int * __result; \ +- unsigned long __tmp, __tmp2; \ +- asm ( \ +- " mfctl %%cr27, %1\n" \ +- " addil LT'" #x "-$tls_ieoff$, %%r19\n" \ +- " ldw RT'" #x "-$tls_ieoff$(%%r1), %2\n" \ +- " add %1, %2, %0\n" \ +- : "=r" (__result), "=r" (__tmp), "=r" (__tmp2) \ +- : \ +- : "r1" ); \ +- __result; \ +- }) +-#else +-# define TLS_IE(x) \ +- ({ int * __result; \ +- unsigned long __tmp, __tmp2; \ +- asm ( \ +- " mfctl %%cr27, %1\n" \ +- " addil LR'" #x "-$tls_ieoff$, %%r27\n" \ +- " ldw RR'" #x "-$tls_ieoff$(%%r1), %2\n" \ +- " add %1, %2, %0\n" \ +- : "=r" (__result), "=r" (__tmp), "=r" (__tmp2) \ +- : \ +- : "r1" ); \ +- __result; \ +- }) +-#endif +- +-#ifdef PIC +-/* HPPA Local Dynamic TLS access. */ +-# define TLS_LD(x) \ +- ({ int * __result; \ +- asm ( \ +- " copy %%r19, %%r4\n" \ +- " addil LT'" #x "-$tls_ldidx$, %%r19\n" \ +- " bl __tls_get_addr, %%r2\n" \ +- " ldo RT'" #x "-$tls_ldidx$(%%r1), %%r26\n" \ +- " addil LR'" #x "-$tls_dtpoff$, %%r28\n" \ +- " ldo RR'" #x "-$tls_dtpoff$(%%r1), %0\n" \ +- " copy %%r4, %%r19\n" \ +- : "=r" (__result) \ +- : \ +- : "r1", "r2", "r4", "r20", "r21", "r22", "r23", "r24", \ +- "r25", "r26", "r28", "r29", "r31" ); \ +- __result; \ +- }) +-#else +-# define TLS_LD(x) \ +- ({ int * __result; \ +- asm ( \ +- " addil LR'" #x "-$tls_ldidx$, %%r27\n" \ +- " bl __tls_get_addr, %%r2\n" \ +- " ldo RR'" #x "-$tls_ldidx$(%%r1), %%r26\n" \ +- " addil LR'" #x "-$tls_dtpoff$, %%r28\n" \ +- " ldo RR'" #x "-$tls_dtpoff$(%%r1), %0\n" \ +- : "=r" (__result) \ +- : \ +- : "r1", "r2", "r20", "r21", "r22", "r23", "r24", \ +- "r25", "r26", "r28", "r29", "r31" ); \ +- __result; \ +- }) +-#endif +- +-/* HPPA General Dynamic TLS access. */ +-#ifdef PIC +-# define TLS_GD(x) \ +- ({ int * __result; \ +- asm ( \ +- " copy %%r19, %%r4\n" \ +- " addil LT'" #x "-$tls_gdidx$, %%r19\n" \ +- " bl __tls_get_addr, %%r2\n" \ +- " ldo RT'" #x "-$tls_gdidx$(%%r1), %%r26\n" \ +- " copy %%r28, %0\n" \ +- " copy %%r4, %%r19\n" \ +- : "=r" (__result) \ +- : \ +- : "r1", "r2", "r4", "r20", "r21", "r22", "r23", "r24", \ +- "r25", "r26", "r28", "r29", "r31" ); \ +- __result; \ +- }) +-#else +-# define TLS_GD(x) \ +- ({ int * __result; \ +- asm ( \ +- " addil LR'" #x "-$tls_gdidx$, %%r27\n" \ +- " bl __tls_get_addr, %%r2\n" \ +- " ldo RR'" #x "-$tls_gdidx$(%%r1), %%r26\n" \ +- " copy %%r28, %0\n" \ +- : "=r" (__result) \ +- : \ +- : "r1", "r2", "r20", "r21", "r22", "r23", "r24", \ +- "r25", "r26", "r28", "r29", "r31" ); \ +- __result; \ +- }) +-#endif +diff --git a/sysdeps/i386/tls-macros.h b/sysdeps/i386/tls-macros.h +deleted file mode 100644 +index 9c1303d..0000000 +--- a/sysdeps/i386/tls-macros.h ++++ /dev/null +@@ -1,47 +0,0 @@ +-#define TLS_LE(x) \ +- ({ int *__l; \ +- asm ("movl %%gs:0,%0\n\t" \ +- "subl $" #x "@tpoff,%0" \ +- : "=r" (__l)); \ +- __l; }) +- +-#define TLS_IE(x) \ +- ({ int *__l, __b; \ +- asm ("call 1f\n\t" \ +- ".subsection 1\n" \ +- "1:\tmovl (%%esp), %%ebx\n\t" \ +- "ret\n\t" \ +- ".previous\n\t" \ +- "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ +- "movl %%gs:0,%0\n\t" \ +- "subl " #x "@gottpoff(%%ebx),%0" \ +- : "=r" (__l), "=&b" (__b)); \ +- __l; }) +- +-#define TLS_LD(x) \ +- ({ int *__l, __b, __c, __d; \ +- asm ("call 1f\n\t" \ +- ".subsection 1\n" \ +- "1:\tmovl (%%esp), %%ebx\n\t" \ +- "ret\n\t" \ +- ".previous\n\t" \ +- "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ +- "leal " #x "@tlsldm(%%ebx),%%eax\n\t" \ +- "call ___tls_get_addr@plt\n\t" \ +- "leal " #x "@dtpoff(%%eax), %%eax" \ +- : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d)); \ +- __l; }) +- +-#define TLS_GD(x) \ +- ({ int *__l, __b, __c, __d; \ +- asm ("call 1f\n\t" \ +- ".subsection 1\n" \ +- "1:\tmovl (%%esp), %%ebx\n\t" \ +- "ret\n\t" \ +- ".previous\n\t" \ +- "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ +- "leal " #x "@tlsgd(%%ebx),%%eax\n\t" \ +- "call ___tls_get_addr@plt\n\t" \ +- "nop" \ +- : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d)); \ +- __l; }) +diff --git a/sysdeps/ia64/tls-macros.h b/sysdeps/ia64/tls-macros.h +deleted file mode 100644 +index 13b216d..0000000 +--- a/sysdeps/ia64/tls-macros.h ++++ /dev/null +@@ -1,66 +0,0 @@ +-/* Macros to support TLS testing in times of missing compiler support. */ +- +-extern void *__tls_get_addr (void *); +- +-# define TLS_LE(x) \ +- ({ void *__l; \ +- asm ("mov r2=r13\n\t" \ +- ";;\n\t" \ +- "addl %0=@tprel(" #x "),r2\n\t" \ +- : "=r" (__l) : : "r2" ); __l; }) +- +-# define TLS_IE(x) \ +- ({ void *__l; \ +- register long __gp asm ("gp"); \ +- asm (";;\n\t" \ +- "addl r16=@ltoff(@tprel(" #x ")),gp\n\t" \ +- ";;\n\t" \ +- "ld8 r17=[r16]\n\t" \ +- ";;\n\t" \ +- "add %0=r13,r17\n\t" \ +- ";;\n\t" \ +- : "=r" (__l) : "r" (__gp) : "r16", "r17" ); __l; }) +- +-# define __TLS_CALL_CLOBBERS \ +- "r2", "r3", "r8", "r9", "r10", "r11", "r14", "r15", "r16", "r17", \ +- "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", \ +- "r27", "r28", "r29", "r30", "r31", \ +- "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ +- "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ +- "b6", "b7", \ +- "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" +- +-# define TLS_LD(x) \ +- ({ void *__l; \ +- register long __gp asm ("gp"); \ +- asm (";;\n\t" \ +- "mov loc0=gp\n\t" \ +- "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \ +- "addl out1=@dtprel(" #x "),r0\n\t" \ +- ";;\n\t" \ +- "ld8 out0=[r16]\n\t" \ +- "br.call.sptk.many b0=__tls_get_addr" \ +- ";;\n\t" \ +- "mov gp=loc0\n\t" \ +- "mov %0=r8\n\t" \ +- ";;\n\t" \ +- : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS); \ +- __l; }) +- +-# define TLS_GD(x) \ +- ({ void *__l; \ +- register long __gp asm ("gp"); \ +- asm (";;\n\t" \ +- "mov loc0=gp\n\t" \ +- "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \ +- "addl r17=@ltoff(@dtprel(" #x ")),gp\n\t" \ +- ";;\n\t" \ +- "ld8 out0=[r16]\n\t" \ +- "ld8 out1=[r17]\n\t" \ +- "br.call.sptk.many b0=__tls_get_addr" \ +- ";;\n\t" \ +- "mov gp=loc0\n\t" \ +- "mov %0=r8\n\t" \ +- ";;\n\t" \ +- : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS); \ +- __l; }) +diff --git a/sysdeps/m68k/tls-macros.h b/sysdeps/m68k/tls-macros.h +deleted file mode 100644 +index 5fe1735..0000000 +--- a/sysdeps/m68k/tls-macros.h ++++ /dev/null +@@ -1,68 +0,0 @@ +-/* Macros for accessing thread-local storage. m68k version. +- Copyright (C) 2010-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Maxim Kuvyrkov , 2010. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library. If not, see +- . */ +- +-#define TLS_GD(x) \ +- ({ \ +- void *__result; \ +- extern void *__tls_get_addr (void *); \ +- \ +- asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \ +- "lea (-6, %%pc, %0), %0\n\t" \ +- "lea " #x "@TLSGD(%0), %0" \ +- : "=&a" (__result)); \ +- (int *) __tls_get_addr (__result); }) +- +-#define TLS_LD(x) \ +- ({ \ +- char *__tp; \ +- int __offset; \ +- extern void *__tls_get_addr (void *); \ +- \ +- asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \ +- "lea (-6, %%pc, %0), %0\n\t" \ +- "lea " #x "@TLSLDM(%0), %0" \ +- : "=&a" (__tp)); \ +- __tp = (char *) __tls_get_addr (__tp); \ +- asm ("movel #" #x "@TLSLDO, %0" \ +- : "=a" (__offset)); \ +- (int *) (__tp + __offset); }) +- +-#define TLS_IE(x) \ +- ({ \ +- char *__tp; \ +- int __offset; \ +- extern void * __m68k_read_tp (void); \ +- \ +- __tp = (char *) __m68k_read_tp (); \ +- asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \ +- "lea (-6, %%pc, %0), %0\n\t" \ +- "movel " #x "@TLSIE(%0), %0" \ +- : "=&a" (__offset)); \ +- (int *) (__tp + __offset); }) +- +-#define TLS_LE(x) \ +- ({ \ +- char *__tp; \ +- int __offset; \ +- extern void * __m68k_read_tp (void); \ +- \ +- __tp = (char *) __m68k_read_tp (); \ +- asm ("movel #" #x "@TLSLE, %0" \ +- : "=a" (__offset)); \ +- (int *) (__tp + __offset); }) +diff --git a/sysdeps/microblaze/tls-macros.h b/sysdeps/microblaze/tls-macros.h +deleted file mode 100644 +index f7cd59d..0000000 +--- a/sysdeps/microblaze/tls-macros.h ++++ /dev/null +@@ -1,46 +0,0 @@ +-/* Copyright (C) 2009-2021 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 +- . */ +- +-#define TLS_LD(x) \ +- ({ \ +- char *__result; \ +- int __offset; \ +- extern void *__tls_get_addr (void *); \ +- asm ("mfs r20,rpc \n" \ +- "addik r20,r20,_GLOBAL_OFFSET_TABLE_+8\n" \ +- "addik %0,r20," #x "@TLSLDM" \ +- : "=r" (__result)); \ +- __result = (char *) __tls_get_addr (__result); \ +- asm ("addik %0,r0,"#x"@TLSDTPREL" \ +- : "=r" (__offset)); \ +- (int *) (__result + __offset); }) +- +- +-#define TLS_GD(x) \ +- ({ \ +- int *__result; \ +- extern void *__tls_get_addr (void *); \ +- asm ("mfs r20,rpc\n" \ +- "addik r20,r20,_GLOBAL_OFFSET_TABLE_+8\n" \ +- "addik %0,r20," #x "@TLSGD" \ +- : "=r" (__result)); \ +- (int *) __tls_get_addr (__result); }) +- +-#define TLS_LE(x) TLS_LD(x) +- +-#define TLS_IE(x) TLS_GD(x) +diff --git a/sysdeps/mips/tls-macros.h b/sysdeps/mips/tls-macros.h +deleted file mode 100644 +index a6fdfbc..0000000 +--- a/sysdeps/mips/tls-macros.h ++++ /dev/null +@@ -1,130 +0,0 @@ +-/* Macros to support TLS testing in times of missing compiler support. */ +- +-#include +-#include +-#include +- +-#define __STRING2(X) __STRING(X) +-#define ADDU __STRING2(PTR_ADDU) +-#define ADDIU __STRING2(PTR_ADDIU) +-#define LW __STRING2(PTR_L) +- +-/* Load the GOT pointer, which may not be in $28 in a non-PIC +- (abicalls pic0) function. */ +-#ifndef __PIC__ +-# if _MIPS_SIM != _ABI64 +-# ifndef __mips16 +-# define LOAD_GP "move %[tmp], $28\n\tla $28, __gnu_local_gp\n\t" +-# else +-# define LOAD_GP \ +- "li %[tmp], %%hi(__gnu_local_gp)\n\t" \ +- "sll %[tmp], 16\n\t" \ +- "addiu %[tmp], %%lo(__gnu_local_gp)\n\t" +-# endif +-# else +-# define LOAD_GP "move %[tmp], $28\n\tdla $28, __gnu_local_gp\n\t" +-# endif +-# define UNLOAD_GP "\n\tmove $28, %[tmp]" +-#else +-/* MIPS16 (re)creates the GP value using PC-relative instructions. */ +-# ifdef __mips16 +-# define LOAD_GP \ +- "li %[tmp], %%hi(_gp_disp)\n\t" \ +- "addiu %0, $pc, %%lo(_gp_disp)\n\t" \ +- "sll %[tmp], 16\n\t" \ +- "addu %[tmp], %0\n\t" +-# else +-# define LOAD_GP +-# endif +-# define UNLOAD_GP +-#endif +- +-# if __mips_isa_rev >= 2 +-# define TLS_RDHWR "rdhwr\t%0,$29" +-# else +-# define TLS_RDHWR \ +- ".set push\n\t.set mips32r2\n\t" \ +- "rdhwr\t%0,$29\n\t.set pop" +-#endif +- +-#ifndef __mips16 +-# define TLS_GD(x) \ +- ({ void *__result, *__tmp; \ +- extern void *__tls_get_addr (void *); \ +- asm (LOAD_GP ADDIU " %0, $28, %%tlsgd(" #x ")" \ +- UNLOAD_GP \ +- : "=r" (__result), [tmp] "=&r" (__tmp)); \ +- (int *)__tls_get_addr (__result); }) +-# define TLS_LD(x) \ +- ({ void *__result, *__tmp; \ +- extern void *__tls_get_addr (void *); \ +- asm (LOAD_GP ADDIU " %0, $28, %%tlsldm(" #x ")" \ +- UNLOAD_GP \ +- : "=r" (__result), [tmp] "=&r" (__tmp)); \ +- __result = __tls_get_addr (__result); \ +- asm ("lui $3,%%dtprel_hi(" #x ")\n\t" \ +- "addiu $3,$3,%%dtprel_lo(" #x ")\n\t" \ +- ADDU " %0,%0,$3" \ +- : "+r" (__result) : : "$3"); \ +- __result; }) +-# define TLS_IE(x) \ +- ({ void *__result, *__tmp; \ +- asm (TLS_RDHWR \ +- : "=v" (__result)); \ +- asm (LOAD_GP LW " $3,%%gottprel(" #x ")($28)\n\t" \ +- ADDU " %0,%0,$3" \ +- UNLOAD_GP \ +- : "+r" (__result), [tmp] "=&r" (__tmp) \ +- : : "$3"); \ +- __result; }) +-# define TLS_LE(x) \ +- ({ void *__result; \ +- asm (TLS_RDHWR \ +- : "=v" (__result)); \ +- asm ("lui $3,%%tprel_hi(" #x ")\n\t" \ +- "addiu $3,$3,%%tprel_lo(" #x ")\n\t" \ +- ADDU " %0,%0,$3" \ +- : "+r" (__result) : : "$3"); \ +- __result; }) +- +-#else /* __mips16 */ +-/* MIPS16 version. */ +-# define TLS_GD(x) \ +- ({ void *__result, *__tmp; \ +- extern void *__tls_get_addr (void *); \ +- asm (LOAD_GP ADDIU " %1, %%tlsgd(" #x ")" \ +- "\n\tmove %0, %1" \ +- : "=d" (__result), [tmp] "=&d" (__tmp)); \ +- (int *) __tls_get_addr (__result); }) +-# define TLS_LD(x) \ +- ({ void *__result, *__tmp; \ +- extern void *__tls_get_addr (void *); \ +- asm (LOAD_GP ADDIU " %1, %%tlsldm(" #x ")" \ +- "\n\tmove %0, %1" \ +- : "=d" (__result), [tmp] "=&d" (__tmp)); \ +- __result = __tls_get_addr (__result); \ +- asm ("li $3,%%dtprel_hi(" #x ")\n\t" \ +- "sll $3,16\n\t" \ +- "addiu $3,%%dtprel_lo(" #x ")\n\t" \ +- ADDU " %0,%0,$3" \ +- : "+d" (__result) : : "$3"); \ +- __result; }) +-# define TLS_IE(x) \ +- ({ void *__result, *__tmp, *__tp; \ +- __tp = __builtin_thread_pointer (); \ +- asm (LOAD_GP LW " $3,%%gottprel(" #x ")(%1)\n\t" \ +- ADDU " %0,%[tp],$3" \ +- : "=&d" (__result), [tmp] "=&d" (__tmp) \ +- : [tp] "d" (__tp) : "$3"); \ +- __result; }) +-# define TLS_LE(x) \ +- ({ void *__result, *__tp; \ +- __tp = __builtin_thread_pointer (); \ +- asm ("li $3,%%tprel_hi(" #x ")\n\t" \ +- "sll $3,16\n\t" \ +- "addiu $3,%%tprel_lo(" #x ")\n\t" \ +- ADDU " %0,%[tp],$3" \ +- : "=d" (__result) : [tp] "d" (__tp) : "$3"); \ +- __result; }) +- +-#endif /* __mips16 */ +diff --git a/sysdeps/nios2/tls-macros.h b/sysdeps/nios2/tls-macros.h +deleted file mode 100644 +index 7029530..0000000 +--- a/sysdeps/nios2/tls-macros.h ++++ /dev/null +@@ -1,46 +0,0 @@ +-#define TLS_LE(x) \ +- ({ int *__result; \ +- asm ("addi %0, r23, %%tls_le(" #x ")" \ +- : "=r" (__result)); \ +- __result; }) +- +-#define TLS_IE(x) \ +- ({ int *__result; \ +- int __tmp; \ +- asm ("nextpc %0 ; " \ +- "1: movhi %1, %%hiadj(_gp_got - 1b) ; " \ +- "addi %1, %1, %%lo(_gp_got - 1b) ; " \ +- "add %0, %0, %1 ; " \ +- "ldw %1, %%tls_ie(" #x ")(%0) ; " \ +- "add %1, r23, %1" \ +- : "=&r" (__tmp), "=&r" (__result)); \ +- __result; }) +- +-#define TLS_LD(x) \ +- ({ char *__result; \ +- char *__result2; \ +- int *__result3; \ +- int __tmp; \ +- extern void *__tls_get_addr (void *); \ +- asm ("nextpc %0 ; " \ +- "1: movhi %1, %%hiadj(_gp_got - 1b) ; " \ +- "addi %1, %1, %%lo(_gp_got - 1b) ; " \ +- "add %0, %0, %1 ; " \ +- "addi %0, %0, %%tls_ldm(" #x ")" \ +- : "=r" (__result), "=r" (__tmp)); \ +- __result2 = (char *)__tls_get_addr (__result); \ +- asm ("addi %0, %1, %%tls_ldo(" #x ")" \ +- : "=r" (__result3) : "r" (__result2)); \ +- __result3; }) +- +-#define TLS_GD(x) \ +- ({ int *__result; \ +- int __tmp; \ +- extern void *__tls_get_addr (void *); \ +- asm ("nextpc %0 ; " \ +- "1: movhi %1, %%hiadj(_gp_got - 1b) ; " \ +- "addi %1, %1, %%lo(_gp_got - 1b) ; " \ +- "add %0, %0, %1 ; " \ +- "addi %0, %0, %%tls_gd(" #x ")" \ +- : "=r" (__result), "=r" (__tmp)); \ +- (int *)__tls_get_addr (__result); }) +diff --git a/sysdeps/powerpc/powerpc32/tls-macros.h b/sysdeps/powerpc/powerpc32/tls-macros.h +deleted file mode 100644 +index ee0eac4..0000000 +--- a/sysdeps/powerpc/powerpc32/tls-macros.h ++++ /dev/null +@@ -1,49 +0,0 @@ +-/* Include sysdeps/powerpc/tls-macros.h for __TLS_CALL_CLOBBERS */ +-#include_next "tls-macros.h" +- +-/* PowerPC32 Local Exec TLS access. */ +-#define TLS_LE(x) \ +- ({ int *__result; \ +- asm ("addi %0,2," #x "@tprel" \ +- : "=r" (__result)); \ +- __result; }) +- +-/* PowerPC32 Initial Exec TLS access. */ +-#define TLS_IE(x) \ +- ({ int *__result; \ +- asm ("bcl 20,31,1f\n1:\t" \ +- "mflr %0\n\t" \ +- "addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ +- "addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ +- "lwz %0," #x "@got@tprel(%0)\n\t" \ +- "add %0,%0," #x "@tls" \ +- : "=b" (__result) : \ +- : "lr"); \ +- __result; }) +- +-/* PowerPC32 Local Dynamic TLS access. */ +-#define TLS_LD(x) \ +- ({ int *__result; \ +- asm ("bcl 20,31,1f\n1:\t" \ +- "mflr 3\n\t" \ +- "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ +- "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ +- "addi 3,3," #x "@got@tlsld\n\t" \ +- "bl __tls_get_addr@plt\n\t" \ +- "addi %0,3," #x "@dtprel" \ +- : "=r" (__result) : \ +- : "3", __TLS_CALL_CLOBBERS); \ +- __result; }) +- +-/* PowerPC32 General Dynamic TLS access. */ +-#define TLS_GD(x) \ +- ({ register int *__result __asm__ ("r3"); \ +- asm ("bcl 20,31,1f\n1:\t" \ +- "mflr 3\n\t" \ +- "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ +- "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ +- "addi 3,3," #x "@got@tlsgd\n\t" \ +- "bl __tls_get_addr@plt" \ +- : "=r" (__result) : \ +- : __TLS_CALL_CLOBBERS); \ +- __result; }) +diff --git a/sysdeps/powerpc/powerpc64/tls-macros.h b/sysdeps/powerpc/powerpc64/tls-macros.h +deleted file mode 100644 +index 79a0b25..0000000 +--- a/sysdeps/powerpc/powerpc64/tls-macros.h ++++ /dev/null +@@ -1,42 +0,0 @@ +-/* Include sysdeps/powerpc/tls-macros.h for __TLS_CALL_CLOBBERS */ +-#include_next "tls-macros.h" +- +-/* PowerPC64 Local Exec TLS access. */ +-#define TLS_LE(x) \ +- ({ int * __result; \ +- asm ("addis %0,13," #x "@tprel@ha\n\t" \ +- "addi %0,%0," #x "@tprel@l" \ +- : "=b" (__result) ); \ +- __result; \ +- }) +-/* PowerPC64 Initial Exec TLS access. */ +-#define TLS_IE(x) \ +- ({ int * __result; \ +- asm ("ld %0," #x "@got@tprel(2)\n\t" \ +- "add %0,%0," #x "@tls" \ +- : "=r" (__result) ); \ +- __result; \ +- }) +- +-/* PowerPC64 Local Dynamic TLS access. */ +-#define TLS_LD(x) \ +- ({ int * __result; \ +- asm ("addi 3,2," #x "@got@tlsld\n\t" \ +- "bl __tls_get_addr\n\t" \ +- "nop \n\t" \ +- "addis %0,3," #x "@dtprel@ha\n\t" \ +- "addi %0,%0," #x "@dtprel@l" \ +- : "=b" (__result) : \ +- : "3", __TLS_CALL_CLOBBERS); \ +- __result; \ +- }) +-/* PowerPC64 General Dynamic TLS access. */ +-#define TLS_GD(x) \ +- ({ register int *__result __asm__ ("r3"); \ +- asm ("addi 3,2," #x "@got@tlsgd\n\t" \ +- "bl __tls_get_addr\n\t" \ +- "nop " \ +- : "=r" (__result) : \ +- : __TLS_CALL_CLOBBERS); \ +- __result; \ +- }) +diff --git a/sysdeps/powerpc/tls-macros.h b/sysdeps/powerpc/tls-macros.h +deleted file mode 100644 +index 809ef5c..0000000 +--- a/sysdeps/powerpc/tls-macros.h ++++ /dev/null +@@ -1,3 +0,0 @@ +-#define __TLS_CALL_CLOBBERS \ +- "0", "4", "5", "6", "7", "8", "9", "10", "11", "12", \ +- "lr", "ctr", "cr0", "cr1", "cr5", "cr6", "cr7" +diff --git a/sysdeps/riscv/tls-macros.h b/sysdeps/riscv/tls-macros.h +deleted file mode 100644 +index 90c496c..0000000 +--- a/sysdeps/riscv/tls-macros.h ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* Macros to support TLS testing in times of missing compiler support. +- Copyright (C) 2017-2021 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 "dl-tls.h" +- +-#define TLS_GD(x) \ +- ({ void *__result; \ +- asm ("la.tls.gd %0, " #x "\n\t" \ +- : "=r" (__result)); \ +- __tls_get_addr (__result); }) +- +-#define TLS_LD(x) TLS_GD(x) +- +-#define TLS_IE(x) \ +- ({ void *__result; \ +- asm ("la.tls.ie %0, " #x "\n\t" \ +- "add %0, %0, tp\n\t" \ +- : "=r" (__result)); \ +- __result; }) +- +-#define TLS_LE(x) \ +- ({ void *__result; \ +- asm ("lui %0, %%tprel_hi(" #x ")\n\t" \ +- "add %0, %0, tp, %%tprel_add(" #x ")\n\t" \ +- "addi %0, %0, %%tprel_lo(" #x ")\n\t" \ +- : "=r" (__result)); \ +- __result; }) +diff --git a/sysdeps/s390/s390-32/tls-macros.h b/sysdeps/s390/s390-32/tls-macros.h +deleted file mode 100644 +index 153523a..0000000 +--- a/sysdeps/s390/s390-32/tls-macros.h ++++ /dev/null +@@ -1,106 +0,0 @@ +-#define TLS_LE(x) \ +- ({ unsigned long __offset; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.long " #x "@ntpoff\n" \ +- "1:\tl %0,0(%0)" \ +- : "=a" (__offset) : : "cc" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +- +-#ifdef PIC +-# define TLS_IE(x) \ +- ({ unsigned long __offset, __save12; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ +- ".long " #x "@gotntpoff\n" \ +- "1:\tlr %1,%%r12\n\t" \ +- "l %%r12,0(%0)\n\t" \ +- "la %%r12,0(%0,%%r12)\n\t" \ +- "l %0,4(%0)\n\t" \ +- "l %0,0(%0,%%r12):tls_load:" #x "\n\t" \ +- "lr %%r12,%1\n" \ +- : "=&a" (__offset), "=&a" (__save12) : : "cc" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#else +-# define TLS_IE(x) \ +- ({ unsigned long __offset; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.long " #x "@indntpoff\n" \ +- "1:\t l %0,0(%0)\n\t" \ +- "l %0,0(%0):tls_load:" #x \ +- : "=&a" (__offset) : : "cc" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#endif +- +-#ifdef PIC +-# define TLS_LD(x) \ +- ({ unsigned long __offset, __save12; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ +- ".long __tls_get_offset@plt-0b\n\t" \ +- ".long " #x "@tlsldm\n\t" \ +- ".long " #x "@dtpoff\n" \ +- "1:\tlr %1,%%r12\n\t" \ +- "l %%r12,0(%0)\n\t" \ +- "la %%r12,0(%%r12,%0)\n\t" \ +- "l %%r1,4(%0)\n\t" \ +- "l %%r2,8(%0)\n\t" \ +- "bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t" \ +- "l %0,12(%0)\n\t" \ +- "alr %0,%%r2\n\t" \ +- "lr %%r12,%1" \ +- : "=&a" (__offset), "=&a" (__save12) \ +- : : "cc", "0", "1", "2", "3", "4", "5", "14"); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#else +-# define TLS_LD(x) \ +- ({ unsigned long __offset; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \ +- ".long __tls_get_offset@plt\n\t" \ +- ".long " #x "@tlsldm\n\t" \ +- ".long " #x "@dtpoff\n" \ +- "1:\tl %%r12,0(%0)\n\t" \ +- "l %%r1,4(%0)\n\t" \ +- "l %%r2,8(%0)\n\t" \ +- "bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t" \ +- "l %0,12(%0)\n\t" \ +- "alr %0,%%r2" \ +- : "=&a" (__offset) \ +- : : "cc", "0", "1", "2", "3", "4", "5", "12", "14"); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#endif +- +-#ifdef PIC +-# define TLS_GD(x) \ +- ({ unsigned long __offset, __save12; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ +- ".long __tls_get_offset@plt-0b\n\t" \ +- ".long " #x "@tlsgd\n" \ +- "1:\tlr %1,%%r12\n\t" \ +- "l %%r12,0(%0)\n\t" \ +- "la %%r12,0(%%r12,%0)\n\t" \ +- "l %%r1,4(%0)\n\t" \ +- "l %%r2,8(%0)\n\t" \ +- "bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t" \ +- "lr %0,%%r2\n\t" \ +- "lr %%r12,%1" \ +- : "=&a" (__offset), "=&a" (__save12) \ +- : : "cc", "0", "1", "2", "3", "4", "5", "14"); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#else +-# define TLS_GD(x) \ +- ({ unsigned long __offset; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \ +- ".long __tls_get_offset@plt\n\t" \ +- ".long " #x "@tlsgd\n" \ +- "1:\tl %%r12,0(%0)\n\t" \ +- "l %%r1,4(%0)\n\t" \ +- "l %%r2,8(%0)\n\t" \ +- "bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t" \ +- "lr %0,%%r2" \ +- : "=&a" (__offset) \ +- : : "cc", "0", "1", "2", "3", "4", "5", "12", "14"); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#endif +diff --git a/sysdeps/s390/s390-64/tls-macros.h b/sysdeps/s390/s390-64/tls-macros.h +deleted file mode 100644 +index 449a843..0000000 +--- a/sysdeps/s390/s390-64/tls-macros.h ++++ /dev/null +@@ -1,90 +0,0 @@ +-#define TLS_LE(x) \ +- ({ unsigned long __offset; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.quad " #x "@ntpoff\n" \ +- "1:\tlg %0,0(%0)" \ +- : "=a" (__offset) : : "cc" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +- +-#ifdef PIC +-# define TLS_IE(x) \ +- ({ unsigned long __offset, __save12; \ +- __asm__ ("bras %0,0f\n\t" \ +- ".quad " #x "@gotntpoff\n" \ +- "0:\tlgr %1,%%r12\n\t" \ +- "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ +- "lg %0,0(%0)\n\t" \ +- "lg %0,0(%0,%%r12):tls_load:" #x "\n\t" \ +- "lgr %%r12,%1\n" \ +- : "=&a" (__offset), "=&a" (__save12) : : "cc" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#else +-# define TLS_IE(x) \ +- ({ unsigned long __offset; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.quad " #x "@indntpoff\n" \ +- "1:\t lg %0,0(%0)\n\t" \ +- "lg %0,0(%0):tls_load:" #x \ +- : "=&a" (__offset) : : "cc" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#endif +- +-#ifdef PIC +-# define TLS_LD(x) \ +- ({ unsigned long __offset, __save12; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.quad " #x "@tlsldm\n\t" \ +- ".quad " #x "@dtpoff\n" \ +- "1:\tlgr %1,%%r12\n\t" \ +- "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ +- "lg %%r2,0(%0)\n\t" \ +- "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \ +- "lg %0,8(%0)\n\t" \ +- "algr %0,%%r2\n\t" \ +- "lgr %%r12,%1" \ +- : "=&a" (__offset), "=&a" (__save12) \ +- : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#else +-# define TLS_LD(x) \ +- ({ unsigned long __offset; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.quad " #x "@tlsldm\n\t" \ +- ".quad " #x "@dtpoff\n" \ +- "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ +- "lg %%r2,0(%0)\n\t" \ +- "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \ +- "lg %0,8(%0)\n\t" \ +- "algr %0,%%r2" \ +- : "=&a" (__offset) \ +- : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#endif +- +-#ifdef PIC +-# define TLS_GD(x) \ +- ({ unsigned long __offset, __save12; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.quad " #x "@tlsgd\n" \ +- "1:\tlgr %1,%%r12\n\t" \ +- "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ +- "lg %%r2,0(%0)\n\t" \ +- "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \ +- "lgr %0,%%r2\n\t" \ +- "lgr %%r12,%1" \ +- : "=&a" (__offset), "=&a" (__save12) \ +- : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#else +-# define TLS_GD(x) \ +- ({ unsigned long __offset; \ +- __asm__ ("bras %0,1f\n" \ +- "0:\t.quad " #x "@tlsgd\n" \ +- "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ +- "lg %%r2,0(%0)\n\t" \ +- "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \ +- "lgr %0,%%r2" \ +- : "=&a" (__offset) \ +- : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \ +- (int *) (__builtin_thread_pointer() + __offset); }) +-#endif +diff --git a/sysdeps/sh/tls-macros.h b/sysdeps/sh/tls-macros.h +deleted file mode 100644 +index aa56b0a..0000000 +--- a/sysdeps/sh/tls-macros.h ++++ /dev/null +@@ -1,143 +0,0 @@ +-#define TLS_LE(x) \ +- ({ int *__l; void *__tp; \ +- asm ("stc gbr,%1\n\t" \ +- "mov.l 1f,%0\n\t" \ +- "bra 2f\n\t" \ +- " add %1,%0\n\t" \ +- ".align 2\n\t" \ +- "1: .long " #x "@tpoff\n\t" \ +- "2:" \ +- : "=r" (__l), "=r" (__tp)); \ +- __l; }) +- +-#ifdef PIC +-# define TLS_IE(x) \ +- ({ int *__l; void *__tp; \ +- register void *__gp __asm__("r12"); \ +- asm ("mov.l 1f,r0\n\t" \ +- "stc gbr,%1\n\t" \ +- "mov.l @(r0,r12),%0\n\t" \ +- "bra 2f\n\t" \ +- " add %1,%0\n\t" \ +- ".align 2\n\t" \ +- "1: .long " #x "@gottpoff\n\t" \ +- "2:" \ +- : "=r" (__l), "=r" (__tp) : "r" (__gp) : "r0"); \ +- __l; }) +-#else +-# define TLS_IE(x) \ +- ({ int *__l; void *__tp; \ +- asm ("mov.l r12,@-r15\n\t" \ +- "mova 0f,r0\n\t" \ +- "mov.l 0f,r12\n\t" \ +- "add r0,r12\n\t" \ +- "mov.l 1f,r0\n\t" \ +- "stc gbr,%1\n\t" \ +- "mov.l @(r0,r12),%0\n\t" \ +- "bra 2f\n\t" \ +- " add %1,%0\n\t" \ +- ".align 2\n\t" \ +- "1: .long " #x "@gottpoff\n\t" \ +- "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ +- "2: mov.l @r15+,r12" \ +- : "=r" (__l), "=r" (__tp) : : "r0"); \ +- __l; }) +-#endif +- +-#ifdef PIC +-# define TLS_LD(x) \ +- ({ int *__l; \ +- register void *__gp __asm__("r12"); \ +- asm ("mov.l 1f,r4\n\t" \ +- "mova 2f,r0\n\t" \ +- "mov.l 2f,r1\n\t" \ +- "add r0,r1\n\t" \ +- "jsr @r1\n\t" \ +- " add r12,r4\n\t" \ +- "bra 4f\n\t" \ +- " nop\n\t" \ +- ".align 2\n\t" \ +- "1: .long " #x "@tlsldm\n\t" \ +- "2: .long __tls_get_addr@plt\n\t" \ +- "4: mov.l 3f,%0\n\t" \ +- "bra 5f\n\t" \ +- " add r0,%0\n\t" \ +- ".align 2\n\t" \ +- "3: .long " #x "@dtpoff\n\t" \ +- "5:" \ +- : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5", \ +- "r6", "r7", "pr", "t"); \ +- __l; }) +-#else +-# define TLS_LD(x) \ +- ({ int *__l; \ +- asm ("mov.l r12,@-r15\n\t" \ +- "mova 0f,r0\n\t" \ +- "mov.l 0f,r12\n\t" \ +- "add r0,r12\n\t" \ +- "mov.l 1f,r4\n\t" \ +- "mova 2f,r0\n\t" \ +- "mov.l 2f,r1\n\t" \ +- "add r0,r1\n\t" \ +- "jsr @r1\n\t" \ +- " add r12,r4\n\t" \ +- "bra 4f\n\t" \ +- " nop\n\t" \ +- ".align 2\n\t" \ +- "1: .long " #x "@tlsldm\n\t" \ +- "2: .long __tls_get_addr@plt\n\t" \ +- "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ +- "4: mov.l 3f,%0\n\t" \ +- "bra 5f\n\t" \ +- " add r0,%0\n\t" \ +- ".align 2\n\t" \ +- "3: .long " #x "@dtpoff\n\t" \ +- "5: mov.l @r15+,r12" \ +- : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ +- "pr", "t"); \ +- __l; }) +-#endif +- +-#ifdef PIC +-# define TLS_GD(x) \ +- ({ int *__l; \ +- register void *__gp __asm__("r12"); \ +- asm ("mov.l 1f,r4\n\t" \ +- "mova 2f,r0\n\t" \ +- "mov.l 2f,r1\n\t" \ +- "add r0,r1\n\t" \ +- "jsr @r1\n\t" \ +- " add r12,r4\n\t" \ +- "bra 3f\n\t" \ +- " mov r0,%0\n\t" \ +- ".align 2\n\t" \ +- "1: .long " #x "@tlsgd\n\t" \ +- "2: .long __tls_get_addr@plt\n\t" \ +- "3:" \ +- : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5", \ +- "r6", "r7", "pr", "t"); \ +- __l; }) +-#else +-# define TLS_GD(x) \ +- ({ int *__l; \ +- asm ("mov.l r12,@-r15\n\t" \ +- "mova 0f,r0\n\t" \ +- "mov.l 0f,r12\n\t" \ +- "add r0,r12\n\t" \ +- "mov.l 1f,r4\n\t" \ +- "mova 2f,r0\n\t" \ +- "mov.l 2f,r1\n\t" \ +- "add r0,r1\n\t" \ +- "jsr @r1\n\t" \ +- " add r12,r4\n\t" \ +- "bra 3f\n\t" \ +- " mov r0,%0\n\t" \ +- ".align 2\n\t" \ +- "1: .long " #x "@tlsgd\n\t" \ +- "2: .long __tls_get_addr@plt\n\t" \ +- "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ +- "3: mov.l @r15+,r12" \ +- : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ +- "pr", "t"); \ +- __l; }) +-#endif +diff --git a/sysdeps/sparc/sparc32/tls-macros.h b/sysdeps/sparc/sparc32/tls-macros.h +deleted file mode 100644 +index 152216e..0000000 +--- a/sysdeps/sparc/sparc32/tls-macros.h ++++ /dev/null +@@ -1,66 +0,0 @@ +-#define TLS_LE(x) \ +- ({ int *__l; \ +- asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l)); \ +- asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ +- asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l)); \ +- __l; }) +- +-#ifdef __PIC__ +-# define TLS_LOAD_PIC \ +- ({ register long pc __asm__ ("%o7"); \ +- long got; \ +- asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ +- "call .+8\n\t" \ +- "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \ +- "add %1, %0, %1\n\t" \ +- : "=r" (pc), "=r" (got)); \ +- got; }) +-#else +-# define TLS_LOAD_PIC \ +- ({ long got; \ +- asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t" \ +- "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t" \ +- "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0" \ +- : "=r" (got)); \ +- got; }) +-#endif +- +-#define TLS_IE(x) \ +- ({ int *__l; \ +- asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l)); \ +- asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ +- asm ("ld [%1 + %2], %0, %%tie_ld(" #x ")" \ +- : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l)); \ +- asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l)); \ +- __l; }) +- +-#define TLS_LD(x) \ +- ({ int *__l; register void *__o0 asm ("%o0"); \ +- long __o; \ +- asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l)); \ +- asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ +- asm ("add %1, %2, %0, %%tldm_add(" #x ")" \ +- : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ +- asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ +- " nop" \ +- : "=r" (__o0) : "0" (__o0) \ +- : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ +- "o5", "o7", "cc"); \ +- asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o)); \ +- asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o)); \ +- asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l) \ +- : "r" (__o0), "r" (__o)); \ +- __l; }) +- +-#define TLS_GD(x) \ +- ({ int *__l; register void *__o0 asm ("%o0"); \ +- asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l)); \ +- asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ +- asm ("add %1, %2, %0, %%tgd_add(" #x ")" \ +- : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ +- asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ +- " nop" \ +- : "=r" (__o0) : "0" (__o0) \ +- : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ +- "o5", "o7", "cc"); \ +- __o0; }) +diff --git a/sysdeps/sparc/sparc64/tls-macros.h b/sysdeps/sparc/sparc64/tls-macros.h +deleted file mode 100644 +index bb0d803..0000000 +--- a/sysdeps/sparc/sparc64/tls-macros.h ++++ /dev/null +@@ -1,65 +0,0 @@ +-#define TLS_LE(x) \ +- ({ int *__l; \ +- asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l)); \ +- asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ +- asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l)); \ +- __l; }) +- +-#ifdef __PIC__ +-# define TLS_LOAD_PIC \ +- ({ long pc, got; \ +- asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ +- "rd %%pc, %0\n\t" \ +- "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \ +- "add %1, %0, %1\n\t" \ +- : "=r" (pc), "=r" (got)); \ +- got; }) +-#else +-# define TLS_LOAD_PIC \ +- ({ long got; \ +- asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t" \ +- "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t" \ +- "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0" \ +- : "=r" (got)); \ +- got; }) +-#endif +- +-#define TLS_IE(x) \ +- ({ int *__l; \ +- asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l)); \ +- asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ +- asm ("ldx [%1 + %2], %0, %%tie_ldx(" #x ")" \ +- : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l)); \ +- asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l)); \ +- __l; }) +- +-#define TLS_LD(x) \ +- ({ int *__l; register void *__o0 asm ("%o0"); \ +- long __o; \ +- asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l)); \ +- asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ +- asm ("add %1, %2, %0, %%tldm_add(" #x ")" \ +- : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ +- asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ +- " nop" \ +- : "=r" (__o0) : "0" (__o0) \ +- : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ +- "o5", "o7", "cc"); \ +- asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o)); \ +- asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o)); \ +- asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l) \ +- : "r" (__o0), "r" (__o)); \ +- __l; }) +- +-#define TLS_GD(x) \ +- ({ int *__l; register void *__o0 asm ("%o0"); \ +- asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l)); \ +- asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ +- asm ("add %1, %2, %0, %%tgd_add(" #x ")" \ +- : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ +- asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ +- " nop" \ +- : "=r" (__o0) : "0" (__o0) \ +- : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ +- "o5", "o7", "cc"); \ +- __o0; }) +diff --git a/sysdeps/x86_64/tls-macros.h b/sysdeps/x86_64/tls-macros.h +deleted file mode 100644 +index 22d2a4b..0000000 +--- a/sysdeps/x86_64/tls-macros.h ++++ /dev/null +@@ -1,39 +0,0 @@ +-#define TLS_LE(x) \ +- ({ int *__l; \ +- asm ("mov %%fs:0,%0\n\t" \ +- "lea " #x "@tpoff(%0), %0" \ +- : "=r" (__l)); \ +- __l; }) +- +-#define TLS_IE(x) \ +- ({ int *__l; \ +- asm ("mov %%fs:0,%0\n\t" \ +- "add " #x "@gottpoff(%%rip),%0" \ +- : "=r" (__l)); \ +- __l; }) +- +-#define TLS_LD(x) \ +- ({ int *__l, __c, __d; \ +- asm ("leaq " #x "@tlsld(%%rip),%%rdi\n\t" \ +- "call __tls_get_addr@plt\n\t" \ +- "leaq " #x "@dtpoff(%%rax), %%rax" \ +- : "=a" (__l), "=&c" (__c), "=&d" (__d) \ +- : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \ +- __l; }) +- +-#ifdef __ILP32__ +-# define TLS_GD_PREFIX +-#else +-# define TLS_GD_PREFIX ".byte 0x66\n\t" +-#endif +- +-#define TLS_GD(x) \ +- ({ int *__l, __c, __d; \ +- asm (TLS_GD_PREFIX \ +- "leaq " #x "@tlsgd(%%rip),%%rdi\n\t" \ +- ".word 0x6666\n\t" \ +- "rex64\n\t" \ +- "call __tls_get_addr@plt" \ +- : "=a" (__l), "=&c" (__c), "=&d" (__d) \ +- : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \ +- __l; }) +-- +1.8.3.1 + diff --git a/arm-Simplify-elf_machine_-load_address-dynamic.patch b/arm-Simplify-elf_machine_-load_address-dynamic.patch new file mode 100644 index 0000000..42987ce --- /dev/null +++ b/arm-Simplify-elf_machine_-load_address-dynamic.patch @@ -0,0 +1,82 @@ +From bca0f5cbc9257c13322b99e55235c4f21ba0bd82 Mon Sep 17 00:00:00 2001 +From: Fangrui Song +Date: Wed, 18 Aug 2021 11:13:03 -0700 +Subject: [PATCH] arm: Simplify elf_machine_{load_address,dynamic} + +and drop reliance on _GLOBAL_OFFSET_TABLE_[0] being the link-time +address of _DYNAMIC. &__ehdr_start is a better way to get the load address. + +This is similar to commits b37b75d269883a2c553bb7019a813094eb4e2dd1 +(x86-64) and 43d06ed218fc8be58987bdfd00e21e5720f0b862 (aarch64). + +Reviewed-by: Joseph Myers +--- + sysdeps/arm/dl-machine.h | 47 ++++++++++------------------------------------- + 1 file changed, 10 insertions(+), 37 deletions(-) + +diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h +index ff5e09e..eb13cb8 100644 +--- a/sysdeps/arm/dl-machine.h ++++ b/sysdeps/arm/dl-machine.h +@@ -37,48 +37,21 @@ elf_machine_matches_host (const Elf32_Ehdr *ehdr) + return ehdr->e_machine == EM_ARM; + } + +- +-/* Return the link-time address of _DYNAMIC. Conveniently, this is the +- first element of the GOT. */ +-static inline Elf32_Addr __attribute__ ((unused)) +-elf_machine_dynamic (void) +-{ +- /* Declaring this hidden ensures that a PC-relative reference is used. */ +- extern const Elf32_Addr _GLOBAL_OFFSET_TABLE_[] attribute_hidden; +- return _GLOBAL_OFFSET_TABLE_[0]; +-} +- +- + /* Return the run-time load address of the shared object. */ +-static inline Elf32_Addr __attribute__ ((unused)) ++static inline ElfW(Addr) __attribute__ ((unused)) + elf_machine_load_address (void) + { +- Elf32_Addr pcrel_addr; +-#ifdef SHARED +- extern Elf32_Addr __dl_start (void *) asm ("_dl_start"); +- Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; +- asm ("adr %0, _dl_start" : "=r" (pcrel_addr)); +-#else +- extern Elf32_Addr __dl_relocate_static_pie (void *) +- asm ("_dl_relocate_static_pie") attribute_hidden; +- Elf32_Addr got_addr = (Elf32_Addr) &__dl_relocate_static_pie; +- asm ("adr %0, _dl_relocate_static_pie" : "=r" (pcrel_addr)); +-#endif +-#ifdef __thumb__ +- /* Clear the low bit of the function address. +- +- NOTE: got_addr is from GOT table whose lsb is always set by linker if it's +- Thumb function address. PCREL_ADDR comes from PC-relative calculation +- which will finish during assembling. GAS assembler before the fix for +- PR gas/21458 was not setting the lsb but does after that. Always do the +- strip for both, so the code works with various combinations of glibc and +- Binutils. */ +- got_addr &= ~(Elf32_Addr) 1; +- pcrel_addr &= ~(Elf32_Addr) 1; +-#endif +- return pcrel_addr - got_addr; ++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden; ++ return (ElfW(Addr)) &__ehdr_start; + } + ++/* Return the link-time address of _DYNAMIC. */ ++static inline ElfW(Addr) __attribute__ ((unused)) ++elf_machine_dynamic (void) ++{ ++ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; ++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address (); ++} + + /* Set up the loaded object described by L so its unrelocated PLT + entries will jump to the on-demand fixup code in dl-runtime.c. */ +-- +1.8.3.1 + diff --git a/elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch b/elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch new file mode 100644 index 0000000..1cd2fc2 --- /dev/null +++ b/elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch @@ -0,0 +1,543 @@ +From 33c50ef42878b07ee6ead8b3f1a81d8c2c74697c Mon Sep 17 00:00:00 2001 +From: Fangrui Song +Date: Mon, 16 Aug 2021 09:59:30 -0700 +Subject: [PATCH] elf: Drop elf/tls-macros.h in favor of __thread and tls_model + attributes [BZ #28152] [BZ #28205] + +elf/tls-macros.h was added for TLS testing when GCC did not support +__thread. __thread and tls_model attributes are mature now and have been +used by many newer tests. + +Also delete tst-tls2.c which tests .tls_common (unused by modern GCC and +unsupported by Clang/LLD). .tls_common and .tbss definition are almost +identical after linking, so the runtime test doesn't add additional +coverage. Assembler and linker tests should be on the binutils side. + +When LLD 13.0.0 is allowed in configure.ac +(https://sourceware.org/pipermail/libc-alpha/2021-August/129866.html), +`make check` result is on par with glibc built with GNU ld on aarch64 +and x86_64. + +As a future clean-up, TLS_GD/TLS_LD/TLS_IE/TLS_IE macros can be removed from +sysdeps/*/tls-macros.h. We can add optional -mtls-dialect={gnu2,trad} +tests to ensure coverage. + +Tested on aarch64-linux-gnu, powerpc64le-linux-gnu, and x86_64-linux-gnu. + +Reviewed-by: Szabolcs Nagy +--- + elf/Makefile | 4 +- + elf/tls-macros.h | 25 ----------- + elf/tst-tls1.c | 64 +++++++++++----------------- + elf/tst-tls2.c | 82 ------------------------------------ + elf/tst-tls3.c | 26 +++++------- + elf/tst-tlsmod1.c | 24 +++++------ + elf/tst-tlsmod2.c | 6 +-- + elf/tst-tlsmod3.c | 8 ++-- + elf/tst-tlsmod4.c | 6 +-- + elf/tst-tlsmod5.c | 4 +- + elf/tst-tlsmod6.c | 4 +- + sysdeps/powerpc/mod-tlsopt-powerpc.c | 6 +-- + sysdeps/powerpc/tst-tlsifunc.c | 4 +- + 13 files changed, 64 insertions(+), 199 deletions(-) + delete mode 100644 elf/tls-macros.h + delete mode 100644 elf/tst-tls2.c + +diff --git a/elf/Makefile b/elf/Makefile +index d05f410..725537c 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -163,7 +163,7 @@ tests-static-normal := tst-array1-static tst-array5-static \ + tst-single_threaded-static tst-single_threaded-pthread-static \ + tst-dst-static tst-getauxval-static + +-tests-static-internal := tst-tls1-static tst-tls2-static \ ++tests-static-internal := tst-tls1-static \ + tst-ptrguard1-static tst-stackguard1-static \ + tst-tls1-static-non-pie + +@@ -183,7 +183,7 @@ endif + tests := tst-tls9 tst-leaks1 \ + tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ + tst-auxv tst-stringtable +-tests-internal := tst-tls1 tst-tls2 $(tests-static-internal) ++tests-internal := tst-tls1 $(tests-static-internal) + tests-static := $(tests-static-normal) $(tests-static-internal) + + ifeq (yes,$(build-shared)) +diff --git a/elf/tls-macros.h b/elf/tls-macros.h +deleted file mode 100644 +index e25e33b..0000000 +--- a/elf/tls-macros.h ++++ /dev/null +@@ -1,25 +0,0 @@ +-/* Macros to support TLS testing in times of missing compiler support. */ +- +-#define COMMON_INT_DEF(x) \ +- asm (".tls_common " #x ",4,4") +-/* XXX Until we get compiler support we don't need declarations. */ +-#define COMMON_INT_DECL(x) +- +-/* XXX This definition will probably be machine specific, too. */ +-#define VAR_INT_DEF(x) \ +- asm (".section .tdata\n\t" \ +- ".globl " #x "\n" \ +- ".balign 4\n" \ +- #x ":\t.long 0\n\t" \ +- ".size " #x ",4\n\t" \ +- ".previous") +-/* XXX Until we get compiler support we don't need declarations. */ +-#define VAR_INT_DECL(x) +- +-#include_next +- +- /* XXX Each architecture must have its own asm for now. */ +-#if !defined TLS_LE || !defined TLS_IE \ +- || !defined TLS_LD || !defined TLS_GD +-# error "No support for this architecture so far." +-#endif +diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c +index c31da56..b341221 100644 +--- a/elf/tst-tls1.c ++++ b/elf/tst-tls1.c +@@ -1,13 +1,14 @@ + /* glibc test for TLS in ld.so. */ + #include + +-#include "tls-macros.h" +- +- +-/* Two common 'int' variables in TLS. */ +-COMMON_INT_DEF(foo); +-COMMON_INT_DEF(bar); + ++__thread int foo, bar __attribute__ ((tls_model("local-exec"))); ++extern __thread int foo_gd asm ("foo") __attribute__ ((tls_model("global-dynamic"))); ++extern __thread int foo_ld asm ("foo") __attribute__ ((tls_model("local-dynamic"))); ++extern __thread int foo_ie asm ("foo") __attribute__ ((tls_model("initial-exec"))); ++extern __thread int bar_gd asm ("bar") __attribute__ ((tls_model("global-dynamic"))); ++extern __thread int bar_ld asm ("bar") __attribute__ ((tls_model("local-dynamic"))); ++extern __thread int bar_ie asm ("bar") __attribute__ ((tls_model("initial-exec"))); + + static int + do_test (void) +@@ -18,63 +19,48 @@ do_test (void) + + /* Set the variable using the local exec model. */ + puts ("set bar to 1 (LE)"); +- ap = TLS_LE (bar); +- *ap = 1; ++ bar = 1; + + + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); +- ap = TLS_IE (foo); +- bp = TLS_IE (bar); ++ ap = &foo_ie; ++ bp = &bar_ie; + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) ++ if (*ap != 0 || *bp != 1) + { +- printf ("bar = %d\n", *bp); ++ printf ("foo = %d\nbar = %d\n", *ap, *bp); + result = 1; + } + + +- /* Get variables using local dynamic model. */ +- fputs ("get sum of foo and bar (LD)", stdout); +- ap = TLS_LD (foo); +- bp = TLS_LD (bar); ++ /* Get variables using local dynamic model or TLSDESC. */ ++ fputs ("get sum of foo and bar (LD or TLSDESC)", stdout); ++ ap = &foo_ld; ++ bp = &bar_ld; + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) ++ if (*ap != 0 || *bp != 1) + { +- printf ("bar = %d\n", *bp); ++ printf ("foo = %d\nbar = %d\n", *ap, *bp); + result = 1; + } + + +- /* Get variables using generic dynamic model. */ +- fputs ("get sum of foo and bar (GD)", stdout); +- ap = TLS_GD (foo); +- bp = TLS_GD (bar); ++ /* Get variables using general dynamic model or TLSDESC. */ ++ fputs ("get sum of foo and bar (GD or TLSDESC)", stdout); ++ ap = &foo_gd; ++ bp = &bar_gd; + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) ++ if (*ap != 0 || *bp != 1) + { +- printf ("bar = %d\n", *bp); ++ printf ("foo = %d\nbar = %d\n", *ap, *bp); + result = 1; + } + ++ + return result; + } + +diff --git a/elf/tst-tls2.c b/elf/tst-tls2.c +deleted file mode 100644 +index 963b8d6..0000000 +--- a/elf/tst-tls2.c ++++ /dev/null +@@ -1,82 +0,0 @@ +-/* glibc test for TLS in ld.so. */ +-#include +- +-#include "tls-macros.h" +- +- +-/* Two 'int' variables in TLS. */ +-VAR_INT_DEF(foo); +-VAR_INT_DEF(bar); +- +- +-static int +-do_test (void) +-{ +- int result = 0; +- int *ap, *bp; +- +- +- /* Set the variable using the local exec model. */ +- puts ("set bar to 1 (LE)"); +- ap = TLS_LE (bar); +- *ap = 1; +- +- +- /* Get variables using initial exec model. */ +- fputs ("get sum of foo and bar (IE)", stdout); +- ap = TLS_IE (foo); +- bp = TLS_IE (bar); +- printf (" = %d\n", *ap + *bp); +- result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) +- { +- printf ("bar = %d\n", *bp); +- result = 1; +- } +- +- +- /* Get variables using local dynamic model. */ +- fputs ("get sum of foo and bar (LD)", stdout); +- ap = TLS_LD (foo); +- bp = TLS_LD (bar); +- printf (" = %d\n", *ap + *bp); +- result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) +- { +- printf ("bar = %d\n", *bp); +- result = 1; +- } +- +- +- /* Get variables using generic dynamic model. */ +- fputs ("get sum of foo and bar (GD)", stdout); +- ap = TLS_GD (foo); +- bp = TLS_GD (bar); +- printf (" = %d\n", *ap + *bp); +- result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) +- { +- printf ("bar = %d\n", *bp); +- result = 1; +- } +- +- return result; +-} +- +- +-#include +diff --git a/elf/tst-tls3.c b/elf/tst-tls3.c +index 7e0abb4..222b179 100644 +--- a/elf/tst-tls3.c ++++ b/elf/tst-tls3.c +@@ -1,13 +1,12 @@ + /* glibc test for TLS in ld.so. */ + #include + +-#include "tls-macros.h" + +- +-/* One define int variable, two externs. */ +-COMMON_INT_DECL(foo); +-VAR_INT_DECL(bar); +-VAR_INT_DEF(baz); ++__thread int foo, bar __attribute__ ((tls_model("initial-exec"))); ++__thread int baz __attribute__ ((tls_model("local-exec"))); ++extern __thread int foo_gd __attribute__ ((alias("foo"), tls_model("global-dynamic"))); ++extern __thread int bar_gd __attribute__ ((alias("bar"), tls_model("global-dynamic"))); ++extern __thread int baz_ld __attribute__ ((alias("baz"), tls_model("local-dynamic"))); + + + extern int in_dso (void); +@@ -22,23 +21,20 @@ do_test (void) + + /* Set the variable using the local exec model. */ + puts ("set baz to 3 (LE)"); +- ap = TLS_LE (baz); +- *ap = 3; ++ baz = 3; + + + /* Get variables using initial exec model. */ + puts ("set variables foo and bar (IE)"); +- ap = TLS_IE (foo); +- *ap = 1; +- bp = TLS_IE (bar); +- *bp = 2; ++ foo = 1; ++ bar = 2; + + + /* Get variables using local dynamic model. */ + fputs ("get sum of foo, bar (GD) and baz (LD)", stdout); +- ap = TLS_GD (foo); +- bp = TLS_GD (bar); +- cp = TLS_LD (baz); ++ ap = &foo_gd; ++ bp = &bar_gd; ++ cp = &baz_ld; + printf (" = %d\n", *ap + *bp + *cp); + result |= *ap + *bp + *cp != 6; + if (*ap != 1) +diff --git a/elf/tst-tlsmod1.c b/elf/tst-tlsmod1.c +index 8d91567..a448c4d 100644 +--- a/elf/tst-tlsmod1.c ++++ b/elf/tst-tlsmod1.c +@@ -1,12 +1,12 @@ + #include + +-#include "tls-macros.h" + ++__thread int foo, bar __attribute__ ((tls_model("global-dynamic"))); ++extern __thread int baz __attribute__ ((tls_model("global-dynamic"))); ++extern __thread int foo_ie asm ("foo") __attribute__ ((tls_model("initial-exec"))); ++extern __thread int bar_ie asm ("bar") __attribute__ ((tls_model("initial-exec"))); ++extern __thread int baz_ie asm ("baz") __attribute__ ((tls_model("initial-exec"))); + +-/* One define int variable, two externs. */ +-COMMON_INT_DEF(foo); +-VAR_INT_DEF(bar); +-VAR_INT_DECL(baz); + + extern int in_dso (void); + +@@ -19,8 +19,8 @@ in_dso (void) + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); + asm ("" ::: "memory"); +- ap = TLS_IE (foo); +- bp = TLS_IE (bar); ++ ap = &foo_ie; ++ bp = &bar_ie; + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 3; + if (*ap != 1) +@@ -35,11 +35,11 @@ in_dso (void) + } + + +- /* Get variables using generic dynamic model. */ +- fputs ("get sum of foo and bar and baz (GD)", stdout); +- ap = TLS_GD (foo); +- bp = TLS_GD (bar); +- cp = TLS_GD (baz); ++ /* Get variables using generic dynamic model or TLSDESC. */ ++ fputs ("get sum of foo and bar and baz (GD or TLSDESC)", stdout); ++ ap = &foo; ++ bp = &bar; ++ cp = &baz; + printf (" = %d\n", *ap + *bp + *cp); + result |= *ap + *bp + *cp != 6; + if (*ap != 1) +diff --git a/elf/tst-tlsmod2.c b/elf/tst-tlsmod2.c +index 40eb140..3223fe4 100644 +--- a/elf/tst-tlsmod2.c ++++ b/elf/tst-tlsmod2.c +@@ -1,9 +1,7 @@ + #include + +-#include "tls-macros.h" + +- +-COMMON_INT_DEF(foo); ++__thread int foo; + + + int +@@ -15,7 +13,7 @@ in_dso (int n, int *caller_foop) + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + +- foop = TLS_GD (foo); ++ foop = &foo; + + if (caller_foop != NULL && foop != caller_foop) + { +diff --git a/elf/tst-tlsmod3.c b/elf/tst-tlsmod3.c +index 6d186c4..d6e7498 100644 +--- a/elf/tst-tlsmod3.c ++++ b/elf/tst-tlsmod3.c +@@ -1,10 +1,10 @@ + #include + +-#include "tls-macros.h" + + extern int in_dso (int n, int *caller_foop); + +-COMMON_INT_DEF(comm_n); ++extern __thread int foo; ++__thread int comm_n; + + + +@@ -20,8 +20,8 @@ in_dso2 (void) + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + +- foop = TLS_GD (foo); +- np = TLS_GD (comm_n); ++ foop = &foo; ++ np = &comm_n; + + if (n != *np) + { +diff --git a/elf/tst-tlsmod4.c b/elf/tst-tlsmod4.c +index 86889aa..f38919a 100644 +--- a/elf/tst-tlsmod4.c ++++ b/elf/tst-tlsmod4.c +@@ -1,9 +1,7 @@ + #include + +-#include "tls-macros.h" + +- +-COMMON_INT_DEF(baz); ++__thread int baz; + + + int +@@ -15,7 +13,7 @@ in_dso (int n, int *caller_bazp) + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + +- bazp = TLS_GD (baz); ++ bazp = &baz; + + if (caller_bazp != NULL && bazp != caller_bazp) + { +diff --git a/elf/tst-tlsmod5.c b/elf/tst-tlsmod5.c +index a97c7e5..3f39c5b 100644 +--- a/elf/tst-tlsmod5.c ++++ b/elf/tst-tlsmod5.c +@@ -1,3 +1 @@ +-#include "tls-macros.h" +- +-COMMON_INT_DEF(foo); ++__thread int foo; +diff --git a/elf/tst-tlsmod6.c b/elf/tst-tlsmod6.c +index e968596..7b3571f 100644 +--- a/elf/tst-tlsmod6.c ++++ b/elf/tst-tlsmod6.c +@@ -1,3 +1 @@ +-#include "tls-macros.h" +- +-COMMON_INT_DEF(bar); ++__thread int bar; +diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c +index ee0db12..2a82e53 100644 +--- a/sysdeps/powerpc/mod-tlsopt-powerpc.c ++++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c +@@ -1,11 +1,9 @@ + /* shared library to test for __tls_get_addr optimization. */ + #include + +-#include "../../elf/tls-macros.h" + #include "dl-tls.h" + +-/* common 'int' variable in TLS. */ +-COMMON_INT_DEF(foo); ++__thread int foo __attribute__ ((tls_model("global-dynamic"))); + + + int +@@ -14,7 +12,7 @@ tls_get_addr_opt_test (void) + int result = 0; + + /* Get variable using general dynamic model. */ +- int *ap = TLS_GD (foo); ++ int *ap = &foo; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); +diff --git a/sysdeps/powerpc/tst-tlsifunc.c b/sysdeps/powerpc/tst-tlsifunc.c +index 3095d41..c8c0bad 100644 +--- a/sysdeps/powerpc/tst-tlsifunc.c ++++ b/sysdeps/powerpc/tst-tlsifunc.c +@@ -21,9 +21,9 @@ + #include + #include + #include +-#include + + __thread int bar; ++extern __thread int bar_gd asm ("bar") __attribute__ ((tls_model("global-dynamic"))); + static int *bar_ptr = NULL; + + static uint32_t resolver_platform = 0; +@@ -57,7 +57,7 @@ get_platform (void) + void + init_foo (void) + { +- bar_ptr = TLS_GD (bar); ++ bar_ptr = &bar_gd; + } + + int +-- +1.8.3.1 + diff --git a/elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch b/elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch new file mode 100644 index 0000000..ffd1cb1 --- /dev/null +++ b/elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch @@ -0,0 +1,27 @@ +From 82fbcd7118d760492e2ecc9fa291e358b9ba0361 Mon Sep 17 00:00:00 2001 +From: Arjun Shankar +Date: Fri, 20 Aug 2021 16:24:05 +0200 +Subject: [PATCH] elf: Fix missing colon in LD_SHOW_AUXV output [BZ #28253] + +This commit adds a missing colon in the AT_MINSIGSTKSZ entry in +the _dl_show_auxv function. +--- + elf/dl-sysdep.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c +index d47bef1..2c684c2 100644 +--- a/elf/dl-sysdep.c ++++ b/elf/dl-sysdep.c +@@ -317,7 +317,7 @@ _dl_show_auxv (void) + [AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex }, + [AT_RANDOM - 2] = { "RANDOM: 0x", hex }, + [AT_HWCAP2 - 2] = { "HWCAP2: 0x", hex }, +- [AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ ", dec }, ++ [AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ: ", dec }, + [AT_L1I_CACHESIZE - 2] = { "L1I_CACHESIZE: ", dec }, + [AT_L1I_CACHEGEOMETRY - 2] = { "L1I_CACHEGEOMETRY: 0x", hex }, + [AT_L1D_CACHESIZE - 2] = { "L1D_CACHESIZE: ", dec }, +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index 8489901..9cf62fd 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 8 +Release: 9 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -99,6 +99,13 @@ Patch18: elf-Unconditionally-use-__ehdr_start.patch Patch19: aarch64-Make-elf_machine_-load_address-dynamic-robus.patch Patch20: mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch Patch21: time-Fix-overflow-itimer-tests-on-32-bit-systems.patch +Patch22: arm-Simplify-elf_machine_-load_address-dynamic.patch +Patch23: elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch +Patch24: elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch +Patch25: Remove-sysdeps-tls-macros.h.patch +Patch26: riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch +Patch27: x86_64-Simplify-elf_machine_-load_address-dynamic.patch +Patch28: x86-fix-Autoconf-caching-of-instruction-support-chec.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1190,6 +1197,10 @@ fi %doc hesiod/README.hesiod %changelog +* Wed Sep 29 2021 Qingqing Li - 2.34-9 +- elf: drop elf/tls-macros.h in favor of thread tls_mode attribute. +- use __ehdr_start for __GLOBAL_OFFSET_TABLE[0] + * Wed Sep 29 2021 Qingqing Li - 2.34-8 - fix overflow ittimer tests on 32 bit system diff --git a/riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch b/riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch new file mode 100644 index 0000000..a45f186 --- /dev/null +++ b/riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch @@ -0,0 +1,60 @@ +From 34b4624b04fc8f038b2c329ca7560197320615b4 Mon Sep 17 00:00:00 2001 +From: Fangrui Song +Date: Wed, 18 Aug 2021 10:01:31 -0700 +Subject: [PATCH] riscv: Drop reliance on _GLOBAL_OFFSET_TABLE_[0] + +&__ehdr_start is a better way to get the load address. + +This is similar to commits b37b75d269883a2c553bb7019a813094eb4e2dd1 +(x86-64) and 43d06ed218fc8be58987bdfd00e21e5720f0b862 (aarch64). + +Reviewed-by: Palmer Dabbelt +--- + sysdeps/riscv/dl-machine.h | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h +index aedf69f..5b07461 100644 +--- a/sysdeps/riscv/dl-machine.h ++++ b/sysdeps/riscv/dl-machine.h +@@ -76,27 +76,26 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr) + return 1; + } + ++/* Return the run-time load address of the shared object. */ ++static inline ElfW(Addr) ++elf_machine_load_address (void) ++{ ++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden; ++ return (ElfW(Addr)) &__ehdr_start; ++} ++ + /* Return the link-time address of _DYNAMIC. */ + static inline ElfW(Addr) + elf_machine_dynamic (void) + { +- extern ElfW(Addr) _GLOBAL_OFFSET_TABLE_ __attribute__ ((visibility ("hidden"))); +- return _GLOBAL_OFFSET_TABLE_; ++ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; ++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address (); + } + + #define STRINGXP(X) __STRING (X) + #define STRINGXV(X) STRINGV_ (X) + #define STRINGV_(...) # __VA_ARGS__ + +-/* Return the run-time load address of the shared object. */ +-static inline ElfW(Addr) +-elf_machine_load_address (void) +-{ +- ElfW(Addr) load_addr; +- asm ("lla %0, _DYNAMIC" : "=r" (load_addr)); +- return load_addr - elf_machine_dynamic (); +-} +- + /* Initial entry point code for the dynamic linker. + The C function `_dl_start' is the real entry point; + its return value is the user program's entry point. */ +-- +1.8.3.1 + diff --git a/x86-fix-Autoconf-caching-of-instruction-support-chec.patch b/x86-fix-Autoconf-caching-of-instruction-support-chec.patch new file mode 100644 index 0000000..d4117fa --- /dev/null +++ b/x86-fix-Autoconf-caching-of-instruction-support-chec.patch @@ -0,0 +1,178 @@ +From 0835c0f0bad351117154b815f34f8af19ea7e325 Mon Sep 17 00:00:00 2001 +From: Matt Whitlock +Date: Wed, 16 Jun 2021 23:40:47 -0400 +Subject: [PATCH] x86: fix Autoconf caching of instruction support checks [BZ + #27991] + +The Autoconf documentation for the AC_CACHE_CHECK macro states: + + The commands-to-set-it must have no side effects except for setting + the variable cache-id, see below. + +However, the tests for support of -msahf and -mmovbe were embedded in +the commands-to-set-it for lib_cv_include_x86_isa_level. This had the +consequence that libc_cv_have_x86_lahf_sahf and libc_cv_have_x86_movbe +were not defined whenever lib_cv_include_x86_isa_level was read from +cache. These variables' being undefined meant that their unquoted use +in later test expressions led to the 'test' built-in's misparsing its +arguments and emitting errors like "test: =: unexpected operator" or +"test: =: unary operator expected", depending on the particular shell. + +This commit refactors the tests for LAHF/SAHF and MOVBE instruction +support into their own AC_CACHE_CHECK macro invocations to obey the +rule that the commands-to-set-it must have no side effects other than +setting the variable named by cache-id. + +Signed-off-by: Matt Whitlock +Reviewed-by: Adhemerval Zanella +--- + sysdeps/x86/configure | 56 ++++++++++++++++++++++++++++++------------------ + sysdeps/x86/configure.ac | 34 +++++++++++++++-------------- + 2 files changed, 53 insertions(+), 37 deletions(-) + +diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure +index ead1295..62676bb 100644 +--- a/sysdeps/x86/configure ++++ b/sysdeps/x86/configure +@@ -126,8 +126,6 @@ cat > conftest2.S <&5 + (eval $ac_try) 2>&5 +@@ -137,9 +135,22 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest c + count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l` + if test "$count" = 1; then + libc_cv_include_x86_isa_level=yes +- cat > conftest.c <&5 ++$as_echo "$libc_cv_include_x86_isa_level" >&6; } ++if test $libc_cv_include_x86_isa_level = yes; then ++ $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LAHF/SAHF instruction support" >&5 ++$as_echo_n "checking for LAHF/SAHF instruction support... " >&6; } ++if ${libc_cv_have_x86_lahf_sahf+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ libc_cv_have_x86_lahf_sahf=no ++ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? +@@ -147,7 +158,20 @@ EOF + test $ac_status = 0; }; } | grep -q "\-msahf"; then + libc_cv_have_x86_lahf_sahf=yes + fi +- if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c' ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_have_x86_lahf_sahf" >&5 ++$as_echo "$libc_cv_have_x86_lahf_sahf" >&6; } ++ if test $libc_cv_have_x86_lahf_sahf = yes; then ++ $as_echo "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h ++ ++ fi ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MOVBE instruction support" >&5 ++$as_echo_n "checking for MOVBE instruction support... " >&6; } ++if ${libc_cv_have_x86_movbe+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ libc_cv_have_x86_movbe=no ++ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? +@@ -155,23 +179,13 @@ EOF + test $ac_status = 0; }; } | grep -q "\-mmovbe"; then + libc_cv_have_x86_movbe=yes + fi +- fi +-fi +-rm -f conftest* +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_include_x86_isa_level" >&5 +-$as_echo "$libc_cv_include_x86_isa_level" >&6; } +-if test $libc_cv_include_x86_isa_level = yes; then +- $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h +- + fi +-if test $libc_cv_have_x86_lahf_sahf = yes; then +- $as_echo "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h +- +-fi +-if test $libc_cv_have_x86_movbe = yes; then +- $as_echo "#define HAVE_X86_MOVBE 1" >>confdefs.h ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_have_x86_movbe" >&5 ++$as_echo "$libc_cv_have_x86_movbe" >&6; } ++ if test $libc_cv_have_x86_movbe = yes; then ++ $as_echo "#define HAVE_X86_MOVBE 1" >>confdefs.h + ++ fi + fi + config_vars="$config_vars + enable-x86-isa-level = $libc_cv_include_x86_isa_level" +diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac +index bca97fd..04a12ab 100644 +--- a/sysdeps/x86/configure.ac ++++ b/sysdeps/x86/configure.ac +@@ -98,30 +98,32 @@ cat > conftest2.S < conftest.c < +Date: Tue, 17 Aug 2021 10:45:57 -0700 +Subject: [PATCH] x86_64: Simplify elf_machine_{load_address,dynamic} + +and drop reliance on _GLOBAL_OFFSET_TABLE_[0] being the link-time +address of _DYNAMIC. &__ehdr_start is a better way to get the load address. + +Reviewed-by: H.J. Lu +--- + sysdeps/x86_64/dl-machine.h | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h +index a8596aa..ceee507 100644 +--- a/sysdeps/x86_64/dl-machine.h ++++ b/sysdeps/x86_64/dl-machine.h +@@ -35,27 +35,20 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr) + } + + +-/* Return the link-time address of _DYNAMIC. Conveniently, this is the +- first element of the GOT. This must be inlined in a function which +- uses global data. */ ++/* Return the run-time load address of the shared object. */ + static inline ElfW(Addr) __attribute__ ((unused)) +-elf_machine_dynamic (void) ++elf_machine_load_address (void) + { +- /* This produces an IP-relative reloc which is resolved at link time. */ +- extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden; +- return _GLOBAL_OFFSET_TABLE_[0]; ++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden; ++ return (ElfW(Addr)) &__ehdr_start; + } + +- +-/* Return the run-time load address of the shared object. */ ++/* Return the link-time address of _DYNAMIC. */ + static inline ElfW(Addr) __attribute__ ((unused)) +-elf_machine_load_address (void) ++elf_machine_dynamic (void) + { +- /* Compute the difference between the runtime address of _DYNAMIC as seen +- by an IP-relative reference, and the link-time address found in the +- special unrelocated first GOT entry. */ + extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; +- return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic (); ++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address (); + } + + /* Set up the loaded object described by L so its unrelocated PLT +-- +1.8.3.1 + -- Gitee From b0f357c5e8d455ed4a8969a5f778f672a3c18974 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 11 Oct 2021 09:01:17 +0800 Subject: [PATCH 09/70] update test memmove.c to cover 16KB (cherry picked from commit 09e73f980a2082976132db18fec9247b7d01891b) --- ...ng-test-memmove.c-to-cover-16KB-copy.patch | 78 +++++++++++++++++++ glibc.spec | 6 +- 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 Update-string-test-memmove.c-to-cover-16KB-copy.patch diff --git a/Update-string-test-memmove.c-to-cover-16KB-copy.patch b/Update-string-test-memmove.c-to-cover-16KB-copy.patch new file mode 100644 index 0000000..894833e --- /dev/null +++ b/Update-string-test-memmove.c-to-cover-16KB-copy.patch @@ -0,0 +1,78 @@ +From c333dcf8d8f9e6e46475d9eff24bd5394b5d3d9e Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Mon, 1 Feb 2021 17:23:12 -0800 +Subject: [PATCH] Update string/test-memmove.c to cover 16KB copy + +--- + string/test-memmove.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +diff --git a/string/test-memmove.c b/string/test-memmove.c +index b271248..670094c 100644 +--- a/string/test-memmove.c ++++ b/string/test-memmove.c +@@ -312,6 +312,50 @@ do_test2 (size_t offset) + munmap ((void *) large_buf, size); + } + ++static void ++do_test3 (size_t bytes_move, size_t offset) ++{ ++ size_t size = bytes_move * 3; ++ uint32_t *buf; ++ ++ buf = mmap (NULL, size, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANON, -1, 0); ++ ++ if (buf == MAP_FAILED) ++ error (EXIT_UNSUPPORTED, errno, "mmap failed"); ++ ++ size_t arr_size = bytes_move / sizeof (uint32_t); ++ size_t i; ++ ++ FOR_EACH_IMPL (impl, 0) ++ { ++ for (i = 0; i < arr_size; i++) ++ buf[i] = (uint32_t) i; ++ ++ uint32_t *dst = &buf[arr_size + offset]; ++ ++#ifdef TEST_BCOPY ++ CALL (impl, (char *) buf, (char *) dst, bytes_move); ++#else ++ CALL (impl, (char *) dst, (char *) buf, bytes_move); ++#endif ++ ++ for (i = 0; i < arr_size; i++) ++ { ++ if (dst[i] != (uint32_t) i) ++ { ++ error (0, 0, ++ "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"", ++ impl->name, dst, buf, i); ++ ret = 1; ++ break; ++ } ++ } ++ } ++ ++ munmap ((void *) buf, size); ++} ++ + int + test_main (void) + { +@@ -356,6 +400,10 @@ test_main (void) + do_test2 (0x200000); + do_test2 (0x4000000 - 1); + do_test2 (0x4000000); ++ ++ /* Copy 16KB data. */ ++ do_test3 (16384, 3); ++ + return ret; + } + +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index 9cf62fd..b359571 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 9 +Release: 10 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -106,6 +106,7 @@ Patch25: Remove-sysdeps-tls-macros.h.patch Patch26: riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch Patch27: x86_64-Simplify-elf_machine_-load_address-dynamic.patch Patch28: x86-fix-Autoconf-caching-of-instruction-support-chec.patch +Patch29: Update-string-test-memmove.c-to-cover-16KB-copy.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1197,6 +1198,9 @@ fi %doc hesiod/README.hesiod %changelog +* Mon Oct 11 2021 Qingqing Li - 2.34-10 +- update test memmove.c to cover 16KB. + * Wed Sep 29 2021 Qingqing Li - 2.34-9 - elf: drop elf/tls-macros.h in favor of thread tls_mode attribute. - use __ehdr_start for __GLOBAL_OFFSET_TABLE[0] -- Gitee From edaae3468991c27ae6c7ba39cebd956d87ec6404 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 12 Oct 2021 16:28:32 +0800 Subject: [PATCH 10/70] Add the testsuite whitelist. If a test case out of the trustlist fails, the compilation is interrupted. Signed-off-by: Yang Yanchao (cherry picked from commit 99e0df34584506161b2e1b34dfa5d4cbd6100562) --- glibc.spec | 39 +++++++++++-- testsuite_whitelist.aarch64 | 111 +++++++++++++++++++++++++++++++++++ testsuite_whitelist.x86_64 | 112 ++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+), 4 deletions(-) create mode 100644 testsuite_whitelist.aarch64 create mode 100644 testsuite_whitelist.x86_64 diff --git a/glibc.spec b/glibc.spec index b359571..28cc18b 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 10 +Release: 11 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -77,6 +77,10 @@ Source5: LanguageList Source6: LicenseList Source7: replace_same_file_to_hard_link.py +%if %{with testsuite} +Source8: testsuite_whitelist.%{_target_cpu} +%endif + Patch0: glibc-1070416.patch Patch1: glibc-c-utf8-locale.patch Patch2: backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch @@ -885,6 +889,18 @@ done ############################################################################## %check %if %{with testsuite} + +omit_testsuite() { + whitelist=$1 + sed -i '/^#/d' $whitelist + sed -i '/^[\s]*$/d' $whitelist + while read testsuite; do + testsuite_escape=$(echo "$testsuite" | \ + sed 's/\([.+?^$\/\\|()\[]\|\]\)/\\\0/g') + sed -i "/${testsuite_escape}/d" rpmbuild.tests.sum.not-passing + done < "$whitelist" +} + # Increase timeouts export TIMEOUTFACTOR=16 parent=$$ @@ -893,14 +909,24 @@ echo ====================TESTING========================= # Default libraries. pushd build-%{target} make %{?_smp_mflags} -O check |& tee rpmbuild.check.log >&2 -test -n tests.sum +test -s tests.sum + +# This hides a test suite build failure, which should be fatal. We +# check "Summary of test results:" below to verify that all tests +# were built and run. if ! grep -q '^Summary of test results:$' rpmbuild.check.log ; then echo "FAIL: test suite build of target: $(basename "$(pwd)")" >& 2 exit 1 fi set +x -grep -v ^PASS: tests.sum > rpmbuild.tests.sum.not-passing || true -if test -n rpmbuild.tests.sum.not-passing ; then +grep -v ^PASS: tests.sum | grep -v ^UNSUPPORTED > rpmbuild.tests.sum.not-passing || true + +# Delete the testsuite from the whitelist +cp %{SOURCE8} testsuite_whitelist +omit_testsuite testsuite_whitelist +rm -rf testsuite_whitelist + +if test -s rpmbuild.tests.sum.not-passing ; then echo ===================FAILED TESTS===================== >&2 echo "Target: $(basename "$(pwd)")" >& 2 cat rpmbuild.tests.sum.not-passing >&2 @@ -914,6 +940,7 @@ if test -n rpmbuild.tests.sum.not-passing ; then fi done done - 2.34-11 +- Add the testsuite whitelist. + If a test case out of the trustlist fails, the compilation is interrupted. + * Mon Oct 11 2021 Qingqing Li - 2.34-10 - update test memmove.c to cover 16KB. diff --git a/testsuite_whitelist.aarch64 b/testsuite_whitelist.aarch64 new file mode 100644 index 0000000..3e99a3d --- /dev/null +++ b/testsuite_whitelist.aarch64 @@ -0,0 +1,111 @@ +# These test cases failed due to gcc_secure +conform/ISO/setjmp.h/conform +conform/ISO/stdlib.h/conform +conform/ISO/stdlib.h/linknamespace +conform/ISO/string.h/conform +conform/ISO11/setjmp.h/conform +conform/ISO11/stdio.h/conform +conform/ISO11/stdlib.h/conform +conform/ISO11/stdlib.h/linknamespace +conform/ISO11/string.h/conform +conform/ISO11/wchar.h/conform +conform/ISO99/setjmp.h/conform +conform/ISO99/stdio.h/conform +conform/ISO99/stdlib.h/conform +conform/ISO99/stdlib.h/linknamespace +conform/ISO99/string.h/conform +conform/ISO99/wchar.h/conform +conform/POSIX/stdlib.h/conform +conform/POSIX/stdlib.h/linknamespace +conform/POSIX/string.h/conform +conform/POSIX2008/fcntl.h/conform +conform/POSIX2008/mqueue.h/conform +conform/POSIX2008/stdio.h/conform +conform/POSIX2008/stdlib.h/conform +conform/POSIX2008/stdlib.h/linknamespace +conform/POSIX2008/wchar.h/conform +conform/UNIX98/stdlib.h/conform +conform/UNIX98/string.h/conform +conform/UNIX98/unistd.h/conform +conform/UNIX98/unistd.h/linknamespace +conform/UNIX98/wchar.h/conform +conform/XOPEN2K/fcntl.h/conform +conform/XOPEN2K/mqueue.h/conform +conform/XOPEN2K/stdio.h/conform +conform/XOPEN2K/stdlib.h/conform +conform/XOPEN2K/string.h/conform +conform/XOPEN2K/syslog.h/conform +conform/XOPEN2K/unistd.h/conform +conform/XOPEN2K/unistd.h/linknamespace +conform/XOPEN2K/wchar.h/conform +conform/XOPEN2K8/fcntl.h/conform +conform/XOPEN2K8/mqueue.h/conform +conform/XOPEN2K8/stdio.h/conform +conform/XOPEN2K8/stdlib.h/conform +conform/XOPEN2K8/syslog.h/conform +conform/XOPEN2K8/unistd.h/conform +conform/XOPEN2K8/unistd.h/linknamespace +conform/XOPEN2K8/wchar.h/conform +conform/XPG4/stdlib.h/conform +conform/XPG4/stdlib.h/linknamespace +conform/XPG4/string.h/conform +conform/XPG4/unistd.h/conform +conform/XPG42/stdlib.h/conform +conform/XPG42/string.h/conform +conform/XPG42/unistd.h/conform +elf/circleload1 +elf/constload1 +elf/dblload +elf/dblunload +elf/lateglobal +elf/reldep6 +elf/resolvfail +elf/tst-global1 +elf/tst-tls20 +nptl/tst-execstack + +# GCC no longer implements +conform/UNIX98/varargs.h/conform +conform/UNIX98/varargs.h/linknamespace +conform/XPG4/varargs.h/conform +conform/XPG4/varargs.h/linknamespace +conform/XPG42/varargs.h/conform +conform/XPG42/varargs.h/linknamespace + +# These cases depend on gdbm-devel +conform/UNIX98/ndbm.h/conform +conform/UNIX98/ndbm.h/linknamespace +conform/XOPEN2K/ndbm.h/conform +conform/XOPEN2K/ndbm.h/linknamespace +conform/XOPEN2K8/ndbm.h/conform +conform/XOPEN2K8/ndbm.h/linknamespace +conform/XPG42/ndbm.h/conform +conform/XPG42/ndbm.h/linknamespace + +# Test whether the date/time is correct under different +# language libraries, use case problems, and see that +# the compiled language library itself has no errors +# https://sourceware.org/bugzilla/show_bug.cgi?id=23164 +localedata/tst-langinfo-newlocale-static + +# The use case itself passed but because +# test-xfail-tst-protected1a/test-xfail-tst-protected1b was added +elf/tst-protected1a +elf/tst-protected1b + +# the test case is due to check whether a macro is defined +# in the header files. As GLIBC evolves, the position of the +# macro changes, causing the use case to fail +posix/annexc + +# Check whether sys/mman.h is consistent with linux/mman.h. +# kernel has a self-developed macro that does not require glibc adaptation +# https://gitee.com/src-openeuler/kernel/issues/I4BZ9T?from=project-issue +misc/tst-mman-consts + +# Add the tst-nss-files-hosts-long.root/etc/hosts of glibc to +# the /etc/hosts directory of the system, and then run sucess +nss/tst-nss-files-hosts-long + +# The test case fails due to OBS machine restrictions which can be passed locally. +elf/tst-debug1 diff --git a/testsuite_whitelist.x86_64 b/testsuite_whitelist.x86_64 new file mode 100644 index 0000000..342591b --- /dev/null +++ b/testsuite_whitelist.x86_64 @@ -0,0 +1,112 @@ +# These test cases failed due to gcc_secure +conform/ISO/setjmp.h/conform +conform/ISO/stdlib.h/conform +conform/ISO/stdlib.h/linknamespace +conform/ISO/string.h/conform +conform/ISO11/setjmp.h/conform +conform/ISO11/stdio.h/conform +conform/ISO11/stdlib.h/conform +conform/ISO11/stdlib.h/linknamespace +conform/ISO11/string.h/conform +conform/ISO11/wchar.h/conform +conform/ISO99/setjmp.h/conform +conform/ISO99/stdio.h/conform +conform/ISO99/stdlib.h/conform +conform/ISO99/stdlib.h/linknamespace +conform/ISO99/string.h/conform +conform/ISO99/wchar.h/conform +conform/POSIX/stdlib.h/conform +conform/POSIX/stdlib.h/linknamespace +conform/POSIX/string.h/conform +conform/POSIX2008/fcntl.h/conform +conform/POSIX2008/mqueue.h/conform +conform/POSIX2008/stdio.h/conform +conform/POSIX2008/stdlib.h/conform +conform/POSIX2008/stdlib.h/linknamespace +conform/POSIX2008/wchar.h/conform +conform/UNIX98/stdlib.h/conform +conform/UNIX98/string.h/conform +conform/UNIX98/unistd.h/conform +conform/UNIX98/unistd.h/linknamespace +conform/UNIX98/wchar.h/conform +conform/XOPEN2K/fcntl.h/conform +conform/XOPEN2K/mqueue.h/conform +conform/XOPEN2K/stdio.h/conform +conform/XOPEN2K/stdlib.h/conform +conform/XOPEN2K/string.h/conform +conform/XOPEN2K/syslog.h/conform +conform/XOPEN2K/unistd.h/conform +conform/XOPEN2K/unistd.h/linknamespace +conform/XOPEN2K/wchar.h/conform +conform/XOPEN2K8/fcntl.h/conform +conform/XOPEN2K8/mqueue.h/conform +conform/XOPEN2K8/stdio.h/conform +conform/XOPEN2K8/stdlib.h/conform +conform/XOPEN2K8/syslog.h/conform +conform/XOPEN2K8/unistd.h/conform +conform/XOPEN2K8/unistd.h/linknamespace +conform/XOPEN2K8/wchar.h/conform +conform/XPG4/stdlib.h/conform +conform/XPG4/stdlib.h/linknamespace +conform/XPG4/string.h/conform +conform/XPG4/unistd.h/conform +conform/XPG42/stdlib.h/conform +conform/XPG42/string.h/conform +conform/XPG42/unistd.h/conform +elf/circleload1 +elf/constload1 +elf/dblload +elf/dblunload +elf/ifuncmain6pie +elf/lateglobal +elf/reldep6 +elf/resolvfail +elf/tst-global1 +elf/tst-tls20 +nptl/tst-execstack + +# GCC no longer implements +conform/UNIX98/varargs.h/conform +conform/UNIX98/varargs.h/linknamespace +conform/XPG4/varargs.h/conform +conform/XPG4/varargs.h/linknamespace +conform/XPG42/varargs.h/conform +conform/XPG42/varargs.h/linknamespace + +# These cases depend on gdbm-devel +conform/UNIX98/ndbm.h/conform +conform/UNIX98/ndbm.h/linknamespace +conform/XOPEN2K/ndbm.h/conform +conform/XOPEN2K/ndbm.h/linknamespace +conform/XOPEN2K8/ndbm.h/conform +conform/XOPEN2K8/ndbm.h/linknamespace +conform/XPG42/ndbm.h/conform +conform/XPG42/ndbm.h/linknamespace + +# Test whether the date/time is correct under different +# language libraries, use case problems, and see that +# the compiled language library itself has no errors +# https://sourceware.org/bugzilla/show_bug.cgi?id=23164 +localedata/tst-langinfo-newlocale-static + +# The use case itself passed but because +# test-xfail-tst-protected1a/test-xfail-tst-protected1b was added +elf/tst-protected1a +elf/tst-protected1b + +# the test case is due to check whether a macro is defined +# in the header files. As GLIBC evolves, the position of the +# macro changes, causing the use case to fail +posix/annexc + +# Check whether sys/mman.h is consistent with linux/mman.h. +# kernel has a self-developed macro that does not require glibc adaptation +# https://gitee.com/src-openeuler/kernel/issues/I4BZ9T?from=project-issue +misc/tst-mman-consts + +# It need to build GliBC on a platform that supports CET +elf/check-cet + +# Add the tst-nss-files-hosts-long.root/etc/hosts of glibc to +# the /etc/hosts directory of the system, and then run sucess +nss/tst-nss-files-hosts-long -- Gitee From eceb2aabf5422ebd2db2f5f7ead1fc7e8806ae78 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 19 Oct 2021 12:06:41 +0800 Subject: [PATCH 11/70] Add locale-archive sub packages to support more languages and reduce memory usage. Signed-off-by: Yang Yanchao (cherry picked from commit 14364fe566c40364998b24184700e87ec69f593b) --- glibc.spec | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/glibc.spec b/glibc.spec index 28cc18b..1596a34 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 11 +Release: 12 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -229,6 +229,20 @@ Requires: %{name}-common = %{version}-%{release} The locale-source package contains all language packs which are built custom locales +############################################################################## +# glibc "locale-archive" sub-package +############################################################################## +%package locale-archive +Summary: The locale-archive of glibc +Requires: %{name} = %{version}-%{release} +Requires: %{name}-common = %{version}-%{release} + +%description locale-archive +The locale-archive sub package contains the locale-archive. In the past, +this file is provided in "glibc-common".Now, we provide basic language support +in "glibc-common", but if you need a customized language, you can extract +it from the "local-archive". + ############################################################################## # glibc "devel" sub-package ############################################################################## @@ -562,6 +576,12 @@ $olddir/build-%{target}/elf/ld.so \ --prefix $RPM_BUILD_ROOT --add-to-archive \ eo *_* %{find_lang} libc +# In the past, locale-archive is provided by common. +# In the current version, locale-archive is provided by locale-archive. +# Due to the change of the packing mode, the locale-archive fails to be +# replaced during the upgrade. Therefore, a backup file is required to +# replace the locale-archive. +ln locale-archive locale-archive.update popd mv $RPM_BUILD_ROOT%{_prefix}/lib/locale/libc.lang . @@ -1106,6 +1126,28 @@ else io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n") end +%posttrans locale-archive +archive_path="%{_prefix}/lib/locale/locale-archive" +update_path="%{_prefix}/lib/locale/locale-archive.update" +save_path="%{_prefix}/lib/locale/locale-archive.rpmsave" +archive_stat=`stat --format="%D %i" "$archive_path" 2>/dev/null || echo "null"` +update_stat=`stat --format="%D %i" "$update_path" || echo "null"` +# When the hard link does not match, use locale-archive.update +if [ "$archive_stat" != "null" ] && + [ "$update_stat" != "null" ] && + [ "$archive_stat" != "$update_stat" ];then + unlink $archive_path + archive_stat="null" +fi +# Regenerate a file if it does not exist +if [ "$archive_stat" == "null" ];then + ln "$update_path" "$archive_path" +fi +# Delete the .rpmsave +if [ -f "$save_path" ];then + unlink $save_path +fi + %pre devel # this used to be a link and it is causing nightmares now if [ -L %{_prefix}/include/scsi ] ; then @@ -1149,7 +1191,6 @@ fi %license COPYING COPYING.LIB LICENSES %files -f common.filelist common -%attr(0644,root,root) %verify(not md5 size mtime mode) %ghost %config(missingok,noreplace) %{_prefix}/lib/locale/locale-archive %dir %{_prefix}/lib/locale %dir %{_prefix}/lib/locale/C.utf8 %{_prefix}/lib/locale/C.utf8/* @@ -1161,6 +1202,7 @@ fi %files -f libc.lang all-langpacks %{_prefix}/lib/locale %exclude %{_prefix}/lib/locale/locale-archive +%exclude %{_prefix}/lib/locale/locale-archive.update %exclude %{_prefix}/lib/locale/C.utf8 %exclude %{_prefix}/lib/locale/zh_CN.utf8 %exclude %{_prefix}/lib/locale/en_US.utf8 @@ -1173,6 +1215,10 @@ fi %dir %{_prefix}/share/i18n/charmaps %{_prefix}/share/i18n/charmaps/* +%files locale-archive +%attr(0644,root,root) %{_prefix}/lib/locale/locale-archive +%attr(0644,root,root) %{_prefix}/lib/locale/locale-archive.update + %files -f devel.filelist devel %files -f nscd.filelist -n nscd @@ -1225,6 +1271,10 @@ fi %doc hesiod/README.hesiod %changelog +* Tue Oct 19 2021 Yang Yanchao - 2.34-12 +- Add locale-archive sub packages to support more languages + and reduce memory usage. + * Tue Oct 12 2021 Yang Yanchao - 2.34-11 - Add the testsuite whitelist. If a test case out of the trustlist fails, the compilation is interrupted. -- Gitee From 89ddec60f76e841518531cec4c6bffbeed652848 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 25 Oct 2021 15:09:40 +0800 Subject: [PATCH 12/70] fpu: x86-64 optimize load of all bits set into ZMM register. (cherry picked from commit 018de895cabd2b028eba48efcba0d9f5bbaf71b1) --- glibc.spec | 6 +- ...load-of-all-bits-set-into-ZMM-regist.patch | 267 ++++++++++++++++++ 2 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch diff --git a/glibc.spec b/glibc.spec index 1596a34..7919f7f 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 12 +Release: 13 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -111,6 +111,7 @@ Patch26: riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch Patch27: x86_64-Simplify-elf_machine_-load_address-dynamic.patch Patch28: x86-fix-Autoconf-caching-of-instruction-support-chec.patch Patch29: Update-string-test-memmove.c-to-cover-16KB-copy.patch +Patch30: x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1271,6 +1272,9 @@ fi %doc hesiod/README.hesiod %changelog +* Mon Oct 25 2021 Qingqing Li - 2.34-13 +- fpu: x86-64 optimize load of all bits set into ZMM register. + * Tue Oct 19 2021 Yang Yanchao - 2.34-12 - Add locale-archive sub packages to support more languages and reduce memory usage. diff --git a/x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch b/x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch new file mode 100644 index 0000000..924e63c --- /dev/null +++ b/x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch @@ -0,0 +1,267 @@ +From 78c9ec9000f873abe7a15a91b87080a2e4308260 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Fri, 20 Aug 2021 06:42:24 -0700 +Subject: [PATCH] x86-64: Optimize load of all bits set into ZMM register [BZ + #28252] + +Optimize loads of all bits set into ZMM register in AVX512 SVML codes +by replacing + + vpbroadcastq .L_2il0floatpacket.16(%rip), %zmmX + +and + + vmovups .L_2il0floatpacket.13(%rip), %zmmX + +with + vpternlogd $0xff, %zmmX, %zmmX, %zmmX + +This fixes BZ #28252. +--- + sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S | 7 +------ + sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S | 7 +------ + sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S | 7 +------ + sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S | 7 +------ + sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S | 7 +------ + sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S | 7 +------ + sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S | 7 +------ + sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S | 12 ++---------- + sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S | 7 +------ + sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S | 7 +------ + 10 files changed, 11 insertions(+), 64 deletions(-) + +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S +index e68fcdb..58e588a 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S +@@ -265,7 +265,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_cos + vmovaps %zmm0, %zmm8 + + /* Check for large arguments path */ +- vpbroadcastq .L_2il0floatpacket.16(%rip), %zmm2 ++ vpternlogd $0xff, %zmm2, %zmm2, %zmm2 + + /* + ARGUMENT RANGE REDUCTION: +@@ -456,8 +456,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_cos + jmp .LBL_2_7 + #endif + END (_ZGVeN8v_cos_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.16: +- .long 0xffffffff,0xffffffff +- .type .L_2il0floatpacket.16,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S +index dfa2aca..f5f117d 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S +@@ -274,7 +274,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_log + + /* preserve mantissa, set input exponent to 2^(-10) */ + vpternlogq $248, _ExpMask(%rax), %zmm3, %zmm2 +- vpbroadcastq .L_2il0floatpacket.12(%rip), %zmm1 ++ vpternlogd $0xff, %zmm1, %zmm1, %zmm1 + vpsrlq $32, %zmm4, %zmm6 + + /* reciprocal approximation good to at least 11 bits */ +@@ -461,8 +461,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_log + jmp .LBL_2_7 + #endif + END (_ZGVeN8v_log_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.12: +- .long 0xffffffff,0xffffffff +- .type .L_2il0floatpacket.12,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S +index be8ab7c..48d251d 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S +@@ -261,7 +261,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_sin + andq $-64, %rsp + subq $1280, %rsp + movq __svml_d_trig_data@GOTPCREL(%rip), %rax +- vpbroadcastq .L_2il0floatpacket.14(%rip), %zmm14 ++ vpternlogd $0xff, %zmm1, %zmm1, %zmm14 + vmovups __dAbsMask(%rax), %zmm7 + vmovups __dInvPI(%rax), %zmm2 + vmovups __dRShifter(%rax), %zmm1 +@@ -458,8 +458,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_sin + jmp .LBL_2_7 + #endif + END (_ZGVeN8v_sin_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.14: +- .long 0xffffffff,0xffffffff +- .type .L_2il0floatpacket.14,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S +index 6118870..a4944a4 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S +@@ -430,7 +430,7 @@ WRAPPER_IMPL_AVX512_fFF _ZGVdN4vl8l8_sincos + + /* SinPoly = SinR*SinPoly */ + vfmadd213pd %zmm5, %zmm5, %zmm4 +- vpbroadcastq .L_2il0floatpacket.15(%rip), %zmm3 ++ vpternlogd $0xff, %zmm3, %zmm3, %zmm3 + + /* Update Cos result's sign */ + vxorpd %zmm2, %zmm1, %zmm1 +@@ -741,8 +741,3 @@ END (_ZGVeN8vvv_sincos_knl) + ENTRY (_ZGVeN8vvv_sincos_skx) + WRAPPER_AVX512_vvv_vl8l8 _ZGVeN8vl8l8_sincos_skx + END (_ZGVeN8vvv_sincos_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.15: +- .long 0xffffffff,0xffffffff +- .type .L_2il0floatpacket.15,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S +index f671d60..fe8474f 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S +@@ -278,7 +278,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_cosf + X = X - Y*PI1 - Y*PI2 - Y*PI3 + */ + vmovaps %zmm0, %zmm6 +- vmovups .L_2il0floatpacket.13(%rip), %zmm12 ++ vpternlogd $0xff, %zmm12, %zmm12, %zmm12 + vmovups __sRShifter(%rax), %zmm3 + vmovups __sPI1_FMA(%rax), %zmm5 + vmovups __sA9_FMA(%rax), %zmm9 +@@ -453,8 +453,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_cosf + jmp .LBL_2_7 + #endif + END (_ZGVeN16v_cosf_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.13: +- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +- .type .L_2il0floatpacket.13,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S +index 637bfe3..229b782 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S +@@ -264,7 +264,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_expf + vmovaps %zmm0, %zmm7 + + /* compare against threshold */ +- vmovups .L_2il0floatpacket.13(%rip), %zmm3 ++ vpternlogd $0xff, %zmm3, %zmm3, %zmm3 + vmovups __sInvLn2(%rax), %zmm4 + vmovups __sShifter(%rax), %zmm1 + vmovups __sLn2hi(%rax), %zmm6 +@@ -440,8 +440,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_expf + + #endif + END (_ZGVeN16v_expf_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.13: +- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +- .type .L_2il0floatpacket.13,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S +index 9d790fb..fa2aae9 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S +@@ -235,7 +235,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_logf + andq $-64, %rsp + subq $1280, %rsp + movq __svml_slog_data@GOTPCREL(%rip), %rax +- vmovups .L_2il0floatpacket.7(%rip), %zmm6 ++ vpternlogd $0xff, %zmm6, %zmm6, %zmm6 + vmovups _iBrkValue(%rax), %zmm4 + vmovups _sPoly_7(%rax), %zmm8 + +@@ -409,8 +409,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_logf + + #endif + END (_ZGVeN16v_logf_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.7: +- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +- .type .L_2il0floatpacket.7,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S +index c5c43c4..6aea2a4 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S +@@ -385,7 +385,7 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf + vpsrlq $32, %zmm3, %zmm2 + vpmovqd %zmm2, %ymm11 + vcvtps2pd %ymm14, %zmm13 +- vmovups .L_2il0floatpacket.23(%rip), %zmm14 ++ vpternlogd $0xff, %zmm14, %zmm14, %zmm14 + vmovaps %zmm14, %zmm26 + vpandd _ABSMASK(%rax), %zmm1, %zmm8 + vpcmpd $1, _INF(%rax), %zmm8, %k2 +@@ -427,7 +427,7 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf + vpmovqd %zmm11, %ymm5 + vpxord %zmm10, %zmm10, %zmm10 + vgatherdpd _Log2Rcp_lookup(%rax,%ymm4), %zmm10{%k3} +- vpbroadcastq .L_2il0floatpacket.24(%rip), %zmm4 ++ vpternlogd $0xff, %zmm4, %zmm4, %zmm4 + vpxord %zmm11, %zmm11, %zmm11 + vcvtdq2pd %ymm7, %zmm7 + vgatherdpd _Log2Rcp_lookup(%rax,%ymm5), %zmm11{%k1} +@@ -643,11 +643,3 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf + jmp .LBL_2_7 + #endif + END (_ZGVeN16vv_powf_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.23: +- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +- .type .L_2il0floatpacket.23,@object +-.L_2il0floatpacket.24: +- .long 0xffffffff,0xffffffff +- .type .L_2il0floatpacket.24,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S +index 9cf359c..a446c50 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S +@@ -317,7 +317,7 @@ WRAPPER_IMPL_AVX512_fFF _ZGVdN8vvv_sincosf + + /* Result sign calculations */ + vpternlogd $150, %zmm0, %zmm14, %zmm1 +- vmovups .L_2il0floatpacket.13(%rip), %zmm14 ++ vpternlogd $0xff, %zmm14, %zmm14, %zmm14 + + /* Add correction term 0.5 for cos() part */ + vaddps %zmm8, %zmm5, %zmm15 +@@ -748,8 +748,3 @@ END (_ZGVeN16vvv_sincosf_knl) + ENTRY (_ZGVeN16vvv_sincosf_skx) + WRAPPER_AVX512_vvv_vl4l4 _ZGVeN16vl4l4_sincosf_skx + END (_ZGVeN16vvv_sincosf_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.13: +- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +- .type .L_2il0floatpacket.13,@object +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S +index bd05109..c1b352d 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S +@@ -280,7 +280,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_sinf + movq __svml_s_trig_data@GOTPCREL(%rip), %rax + + /* Check for large and special values */ +- vmovups .L_2il0floatpacket.11(%rip), %zmm14 ++ vpternlogd $0xff, %zmm14, %zmm14, %zmm14 + vmovups __sAbsMask(%rax), %zmm5 + vmovups __sInvPI(%rax), %zmm1 + vmovups __sRShifter(%rax), %zmm2 +@@ -472,8 +472,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_sinf + jmp .LBL_2_7 + #endif + END (_ZGVeN16v_sinf_skx) +- +- .section .rodata, "a" +-.L_2il0floatpacket.11: +- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +- .type .L_2il0floatpacket.11,@object +-- +1.8.3.1 + -- Gitee From af382177a323f1f4a8703d5567a67e7b4a7cdcf6 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 25 Oct 2021 16:54:09 +0800 Subject: [PATCH 13/70] fix mtrace output and valgrind check failed for tunables_strdup. -mtrace fix output with PIE and ASLR. -elf: rtld copy terminating null in tunables strdup. (cherry picked from commit 88a66f7a0c88f2b58ab82a670ff1d671c5cbfb68) --- glibc.spec | 8 +- ...ix-output-with-PIE-and-ASLR-BZ-22716.patch | 77 +++++++++++++++++++ ...ating-null-in-tunables_strdup-bug-28.patch | 28 +++++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch create mode 100644 rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch diff --git a/glibc.spec b/glibc.spec index 7919f7f..edc7cc4 100644 --- a/glibc.spec +++ b/glibc.spec @@ -63,7 +63,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 13 +Release: 14 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -112,6 +112,8 @@ Patch27: x86_64-Simplify-elf_machine_-load_address-dynamic.patch Patch28: x86-fix-Autoconf-caching-of-instruction-support-chec.patch Patch29: Update-string-test-memmove.c-to-cover-16KB-copy.patch Patch30: x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch +Patch31: mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch +Patch32: rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1272,6 +1274,10 @@ fi %doc hesiod/README.hesiod %changelog +* Mon Oct 25 2021 Qingqing Li - 2.34-14 +- mtrace fix output with PIE and ASLR. +- elf: rtld copy terminating null in tunables strdup. + * Mon Oct 25 2021 Qingqing Li - 2.34-13 - fpu: x86-64 optimize load of all bits set into ZMM register. diff --git a/mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch b/mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch new file mode 100644 index 0000000..10622da --- /dev/null +++ b/mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch @@ -0,0 +1,77 @@ +From f2e33c3268db9adf8e57e991676ed0d5ac74e8a8 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Mon, 23 Aug 2021 08:11:54 +0530 +Subject: [PATCH] mtrace: Fix output with PIE and ASLR [BZ #22716] + +Record only the relative address of the caller in mtrace file. Use +LD_TRACE_PRELINKING to get the executable as well as binary vs +executable load offsets so that we may compute a base to add to the +relative address in the mtrace file. This allows us to get a valid +address to pass to addr2line in all cases. + +Fixes BZ #22716. + +Co-authored-by: John Ogness +Reviewed-by: Andreas Schwab +Reviewed-by: DJ Delorie +--- + malloc/mtrace-impl.c | 6 +++--- + malloc/mtrace.pl | 15 +++++++-------- + 2 files changed, 10 insertions(+), 11 deletions(-) + +diff --git a/malloc/mtrace-impl.c b/malloc/mtrace-impl.c +index 83008ca..f5f19c2 100644 +--- a/malloc/mtrace-impl.c ++++ b/malloc/mtrace-impl.c +@@ -65,9 +65,9 @@ tr_where (const void *caller, Dl_info *info) + offset); + } + +- fprintf (mallstream, "@ %s%s%s[%p] ", info->dli_fname ? : "", +- info->dli_fname ? ":" : "", +- buf, caller); ++ fprintf (mallstream, "@ %s%s%s[0x%" PRIxPTR "] ", ++ info->dli_fname ? : "", info->dli_fname ? ":" : "", buf, ++ caller - info->dli_fbase); + } + else + fprintf (mallstream, "@ [%p] ", caller); +diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl +index 6f49c83..b1073a1 100644 +--- a/malloc/mtrace.pl ++++ b/malloc/mtrace.pl +@@ -75,11 +75,15 @@ if ($#ARGV == 0) { + } else { + $prog = "./$binary"; + } +- if (open (LOCS, "env LD_TRACE_LOADED_OBJECTS=1 $prog |")) { ++ # Set the environment variable LD_TRACE_PRELINKING to an empty string so ++ # that we trigger tracing but do not match with the executable or any of ++ # its dependencies. ++ if (open (LOCS, "env LD_TRACE_PRELINKING= $prog |")) { + while () { + chop; +- if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) { ++ if (/^.*=> (.*) \((0x[0123456789abcdef]*), (0x[0123456789abcdef]*).*/) { + $locs{$1} = $2; ++ $rel{$1} = hex($2) - hex($3); + } + } + close (LOCS); +@@ -110,12 +114,7 @@ sub location { + my $addr = $2; + my $searchaddr; + return $cache{$addr} if (exists $cache{$addr}); +- if ($locs{$prog} ne "") { +- $searchaddr = sprintf "%#x", $addr - $locs{$prog}; +- } else { +- $searchaddr = $addr; +- $prog = $binary; +- } ++ $searchaddr = sprintf "%#x", hex($addr) + $rel{$prog}; + if ($binary ne "" && open (ADDR, "addr2line -e $prog $searchaddr|")) { + my $line = ; + chomp $line; +-- +1.8.3.1 + diff --git a/rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch b/rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch new file mode 100644 index 0000000..6f73106 --- /dev/null +++ b/rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch @@ -0,0 +1,28 @@ +From a4f5a3103fc3e7974dbe35b411cba9f670807cde Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Mon, 23 Aug 2021 10:19:52 +0200 +Subject: [PATCH] rtld: copy terminating null in tunables_strdup (bug 28256) + +Avoid triggering a false positive from valgrind by copying the terminating +null in tunables_strdup. At this point the heap is still clean, but +valgrind is stricter here. +--- + elf/dl-tunables.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c +index 8009e54..1666736 100644 +--- a/elf/dl-tunables.c ++++ b/elf/dl-tunables.c +@@ -56,8 +56,6 @@ tunables_strdup (const char *in) + if (out == (void *)-1) + _dl_fatal_printf ("sbrk() failure while processing tunables\n"); + +- i--; +- + while (i-- > 0) + out[i] = in[i]; + +-- +1.8.3.1 + -- Gitee From 6a6b8fb597df0ee977cb3e1f3b5f2efdf684f12b Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 26 Oct 2021 09:31:27 +0800 Subject: [PATCH 14/70] glibc:add glibc-compat-2.17 subpackage to provide the function of the glibc-2.17 pthread library. Currently, provide pthread_condition function. Signed-off-by: Yang Yanchao (cherry picked from commit 0efa08b12d929199d6355cfbffe03d86c2c798cc) --- ...tch => compat-2.17-libpthreadcond-so.patch | 14501 ++++++++++------ glibc.spec | 64 +- 2 files changed, 9583 insertions(+), 4982 deletions(-) rename build-extra-libpthreadcond-so.patch => compat-2.17-libpthreadcond-so.patch (45%) diff --git a/build-extra-libpthreadcond-so.patch b/compat-2.17-libpthreadcond-so.patch similarity index 45% rename from build-extra-libpthreadcond-so.patch rename to compat-2.17-libpthreadcond-so.patch index f3c8e7d..b7c62fe 100644 --- a/build-extra-libpthreadcond-so.patch +++ b/compat-2.17-libpthreadcond-so.patch @@ -1,52 +1,103 @@ -From 808cf7c45e187c1889867ac83d047abfdf81c7a3 Mon Sep 17 00:00:00 2001 -From: xuhuijie -Date: Fri, 14 Aug 2020 17:41:59 +0800 +commit a88c9263686012ca2a336379b7d66e59dea2b43b +Author: Ulrich Drepper +Date: Wed Feb 5 09:54:24 2003 +0000 Subject: [PATCH] build extra lipthreadcond so -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 + +since https://sourceware.org/git/?p=glibc.git;a=commit;h=ed19993b5b0d05d62cc883571519a67dae481a14 +delete pthread_condtion function.However, using these interfaces has better performance. +Therefore, we add a subpacket to use these interfaces. +you can use it by adding LD_PRELOAD=./libpthreadcond.so in front of your program (eg: +LD_PRELOAD=./libpthreadcond.so ./test). use with-compat_2_17 to compile it. +WARNING:2.17 version does not meet the posix standard, you should pay attention when using it. + +This patch contains, but is not limited to, the following submissions: +a88c9263686,59ba27a63ad,9bc6103d046,5acf7263d52,7ce5c1640cb,3e976b962a8,5bd8a24966d + +During the evolution of glibc, many header files are changed. To ensure the stability +of libpthread-2.17, header files of earlier versions are used, such as lowlevellock.h, sysdep.h, +descr.h, and futex-internal.h,pthread-function.h,pthreadtypes-arch.h,no-cancel.h.etc. Of course, +there are some interface modifications, such as __pause_nocancel. --- - nptl_2_17/Makefile | 52 + - nptl_2_17/bits/pthreadtypes_2_17.h | 121 ++ - nptl_2_17/bits/thread-shared-types_2_17.h | 104 ++ - nptl_2_17/build_libpthreadcondso.sh | 9 + - nptl_2_17/cancellation_2_17.c | 104 ++ - nptl_2_17/cleanup_compat_2_17.c | 50 + - nptl_2_17/libpthreadcond-aarch64.map | 8 + - nptl_2_17/libpthreadcond-x86_64.map | 8 + - nptl_2_17/pthreadP_2_17.h | 620 +++++++++ - nptl_2_17/pthread_2_17.h | 1173 ++++++++++++++++++ - nptl_2_17/pthread_cond_broadcast_2_17.c | 94 ++ - nptl_2_17/pthread_cond_destroy_2_17.c | 85 ++ - nptl_2_17/pthread_cond_init_2_17.c | 50 + - nptl_2_17/pthread_cond_signal_2_17.c | 82 ++ - nptl_2_17/pthread_cond_timedwait_2_17.c | 268 ++++ - nptl_2_17/pthread_cond_wait_2_17.c | 231 ++++ - nptl_2_17/pthread_condattr_getclock_2_17.c | 28 + - nptl_2_17/pthread_condattr_getpshared_2_17.c | 28 + - nptl_2_17/pthread_condattr_init_2_17.c | 34 + - nptl_2_17/pthread_condattr_setclock_2_17.c | 45 + - nptl_2_17/pthread_mutex_cond_lock_2_17.c | 21 + - nptl_2_17/pthread_mutex_lock_2_17.c | 628 ++++++++++ - nptl_2_17/pthread_mutex_unlock_2_17.c | 360 ++++++ - nptl_2_17/pthreadtypes_2_17.h | 179 +++ - nptl_2_17/tpp_2_17.c | 195 +++ - nptl_2_17/unwind_2_17.c | 138 +++ - nptl_2_17/vars_2_17.c | 43 + - 27 files changed, 4758 insertions(+) + nptl_2_17/Makefile | 50 + + nptl_2_17/bits/pthreadtypes_2_17.h | 127 ++ + nptl_2_17/bits/thread-shared-types_2_17.h | 185 +++ + nptl_2_17/build_libpthread-2.17.so.sh | 10 + + nptl_2_17/cancellation_2_17.c | 102 ++ + nptl_2_17/cleanup_compat_2_17.c | 50 + + nptl_2_17/descr_2_17.h | 412 ++++++ + nptl_2_17/elision-conf_2_17.c | 137 ++ + nptl_2_17/elision-conf_2_17.h | 41 + + nptl_2_17/elision-lock_2_17.c | 107 ++ + nptl_2_17/elision-timed_2_17.c | 26 + + nptl_2_17/elision-trylock_2_17.c | 75 ++ + nptl_2_17/elision-unlock_2_17.c | 33 + + nptl_2_17/futex-internal_2_17.h | 263 ++++ + nptl_2_17/hle_2_17.h | 75 ++ + nptl_2_17/internaltypes_2_17.h | 179 +++ + nptl_2_17/kernel-features_2_17.h | 162 +++ + nptl_2_17/libpthread-2.17-aarch64.map | 8 + + nptl_2_17/libpthread-2.17-x86_64.map | 8 + + nptl_2_17/lll_timedlock_wait_2_17.c | 59 + + nptl_2_17/lowlevellock_2_17.c | 46 + + nptl_2_17/pthread-functions_2_17.h | 116 ++ + nptl_2_17/pthreadP_2_17.h | 714 ++++++++++ + nptl_2_17/pthread_2_17.h | 1162 +++++++++++++++++ + nptl_2_17/pthread_cond_broadcast_2_17.c | 98 ++ + nptl_2_17/pthread_cond_destroy_2_17.c | 85 ++ + nptl_2_17/pthread_cond_init_2_17.c | 50 + + nptl_2_17/pthread_cond_signal_2_17.c | 82 ++ + nptl_2_17/pthread_cond_timedwait_2_17.c | 266 ++++ + nptl_2_17/pthread_cond_wait_2_17.c | 234 ++++ + nptl_2_17/pthread_condattr_getclock_2_17.c | 28 + + nptl_2_17/pthread_condattr_getpshared_2_17.c | 28 + + nptl_2_17/pthread_condattr_init_2_17.c | 33 + + nptl_2_17/pthread_condattr_setclock_2_17.c | 45 + + nptl_2_17/pthread_mutex_cond_lock_2_17.c | 21 + + nptl_2_17/pthread_mutex_lock_2_17.c | 635 +++++++++ + nptl_2_17/pthread_mutex_unlock_2_17.c | 359 +++++ + .../nptl/bits/pthreadtypes-arch_2_17.h | 71 + + nptl_2_17/sysdeps/generic/sysdep_2_17.h | 97 ++ + nptl_2_17/sysdeps/nptl/futex-internal_2_17.h | 210 +++ + nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h | 208 +++ + nptl_2_17/sysdeps/unix/sysdep_2_17.h | 148 +++ + .../unix/sysv/linux/aarch64/sysdep_2_17.h | 301 +++++ + .../unix/sysv/linux/generic/sysdep_2_17.h | 35 + + .../unix/sysv/linux/internal-signals_2_17.h | 91 ++ + .../unix/sysv/linux/lowlevellock-futex_2_17.h | 150 +++ + .../sysdeps/unix/sysv/linux/not-cancel_2_17.h | 93 ++ + .../sysdeps/unix/sysv/linux/sysdep_2_17.h | 68 + + .../unix/sysv/linux/x86_64/sysdep_2_17.h | 432 ++++++ + nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h | 34 + + nptl_2_17/sysdeps/x86/sysdep_2_17.h | 104 ++ + .../x86_64/nptl/bits/pthreadtypes-arch_2_17.h | 106 ++ + nptl_2_17/sysdeps/x86_64/sysdep_2_17.h | 129 ++ + nptl_2_17/thread_db_2_17.h | 458 +++++++ + nptl_2_17/tpp_2_17.c | 195 +++ + nptl_2_17/vars_2_17.c | 43 + + 56 files changed, 9084 insertions(+) create mode 100644 nptl_2_17/Makefile create mode 100644 nptl_2_17/bits/pthreadtypes_2_17.h create mode 100644 nptl_2_17/bits/thread-shared-types_2_17.h - create mode 100644 nptl_2_17/build_libpthreadcondso.sh + create mode 100644 nptl_2_17/build_libpthread-2.17.so.sh create mode 100644 nptl_2_17/cancellation_2_17.c create mode 100644 nptl_2_17/cleanup_compat_2_17.c - create mode 100644 nptl_2_17/libpthreadcond-aarch64.map - create mode 100644 nptl_2_17/libpthreadcond-x86_64.map + create mode 100644 nptl_2_17/descr_2_17.h + create mode 100644 nptl_2_17/elision-conf_2_17.c + create mode 100644 nptl_2_17/elision-conf_2_17.h + create mode 100644 nptl_2_17/elision-lock_2_17.c + create mode 100644 nptl_2_17/elision-timed_2_17.c + create mode 100644 nptl_2_17/elision-trylock_2_17.c + create mode 100644 nptl_2_17/elision-unlock_2_17.c + create mode 100644 nptl_2_17/futex-internal_2_17.h + create mode 100644 nptl_2_17/hle_2_17.h + create mode 100644 nptl_2_17/internaltypes_2_17.h + create mode 100644 nptl_2_17/kernel-features_2_17.h + create mode 100644 nptl_2_17/libpthread-2.17-aarch64.map + create mode 100644 nptl_2_17/libpthread-2.17-x86_64.map + create mode 100644 nptl_2_17/lll_timedlock_wait_2_17.c + create mode 100644 nptl_2_17/lowlevellock_2_17.c + create mode 100644 nptl_2_17/pthread-functions_2_17.h create mode 100644 nptl_2_17/pthreadP_2_17.h create mode 100644 nptl_2_17/pthread_2_17.h create mode 100644 nptl_2_17/pthread_cond_broadcast_2_17.c @@ -62,4932 +113,9446 @@ https://sourceware.org/git/?p=glibc.git;a=commit;h=ed19993b5b0d05d62cc883571519a create mode 100644 nptl_2_17/pthread_mutex_cond_lock_2_17.c create mode 100644 nptl_2_17/pthread_mutex_lock_2_17.c create mode 100644 nptl_2_17/pthread_mutex_unlock_2_17.c - create mode 100644 nptl_2_17/pthreadtypes_2_17.h + create mode 100644 nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h + create mode 100644 nptl_2_17/sysdeps/generic/sysdep_2_17.h + create mode 100644 nptl_2_17/sysdeps/nptl/futex-internal_2_17.h + create mode 100644 nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/sysdep_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h + create mode 100644 nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h + create mode 100644 nptl_2_17/sysdeps/x86/sysdep_2_17.h + create mode 100644 nptl_2_17/sysdeps/x86_64/nptl/bits/pthreadtypes-arch_2_17.h + create mode 100644 nptl_2_17/sysdeps/x86_64/sysdep_2_17.h + create mode 100644 nptl_2_17/thread_db_2_17.h create mode 100644 nptl_2_17/tpp_2_17.c - create mode 100644 nptl_2_17/unwind_2_17.c create mode 100644 nptl_2_17/vars_2_17.c - - -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/nptl_2_17/Makefile b/nptl_2_17/Makefile +new file mode 100644 +index 00000000..4c66b2b6 +--- /dev/null ++++ b/nptl_2_17/Makefile +@@ -0,0 +1,50 @@ ++include libpthread-2.17_config ++subdir=libpthread-2.17 ++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 = 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 pthread_condattr_getclock_2_17.os pthread_condattr_getpshared_2_17.os pthread_condattr_init_2_17.os pthread_condattr_setclock_2_17.os cleanup_compat_2_17.os cancellation_2_17.os pthread_mutex_lock_2_17.os pthread_mutex_unlock_2_17.os tpp_2_17.os vars_2_17.os pthread_mutex_cond_lock_2_17.os lll_timedlock_wait_2_17.os lowlevellock_2_17.os ++ ++ifeq (x86_64, $(arch)) ++compile_obj += elision-lock_2_17.os elision-unlock_2_17.os elision-timed_2_17.os elision-trylock_2_17.os ++endif ++ ++compile_obj_dir = $(foreach n,$(compile_obj),../$(build_dir)/nptl/$(n)) ++ ++CFLAGS = -c -std=gnu11 -fgnu89-inline -fPIE -DNDEBUG -O2 -Wall -Werror -Wp,-D_GLIBCXX_ASSERTIONS -Wundef -Wwrite-strings -fasynchronous-unwind-tables -fmerge-all-constants -frounding-math -fstack-clash-protection -fstack-protector-strong -g -mtune=generic -Wstrict-prototypes -Wold-style-definition -fno-math-errno -fPIC -fexceptions -fasynchronous-unwind-tables -ftls-model=initial-exec -D_FORTIFY_SOURCE=2 -DSHARED -DTOP_NAMESPACE=glibc ++ ++Headers = -I../include -I../$(build_dir)/nptl $(+sysdep-includes) -I../nptl_2_17 -I../nptl -I../libio -I../. -I../nptl_2_17/sysdeps/$(arch)/nptl -I../nptl_2_17/sysdeps/nptl -I../nptl_2_17/sysdeps/unix/sysv/linux/$(arch) -I../nptl_2_17/sysdeps/unix/sysv/linux -D_LIBC_REENTRANT -include ../$(build_dir)/libc-modules.h -include include/libc-symbols.h ++ ++all: libpthread-2.17.so ++ ++libpthread-2.17.so : $(compile_obj) libpthread-2.17_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=libpthread-2.17-$(arch).map -Wl,-soname=libpthread-2.17.so.0 -Wl,-z,noexecstack -Wtrampolines -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -Wl,-z,now -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst -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/libpthread-2.17.so ../$(build_dir)/csu/abi-note.o -Wl,--whole-archive ../$(build_dir)/nptl/libpthread-2.17_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 ++ ++libpthread-2.17_pic.a : $(compile_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..da5521c1 +--- /dev/null ++++ b/nptl_2_17/bits/pthreadtypes_2_17.h +@@ -0,0 +1,127 @@ ++/* Declaration of common pthread types for all architectures. ++ Copyright (C) 2017-2018 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-shared-types_2_17.h" ++ ++/* Thread identifiers. The structure of the attribute type is not ++ exposed on purpose. */ ++typedef unsigned long int pthread_t; ++ ++ ++/* Data structures for mutex handling. The structure of the attribute ++ type is not exposed on purpose. */ ++typedef union ++{ ++ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; ++ int __align; ++} pthread_mutexattr_t; ++ ++ ++/* Data structure for condition variable handling. The structure of ++ the attribute type is not exposed on purpose. */ ++typedef union ++{ ++ char __size[__SIZEOF_PTHREAD_CONDATTR_T]; ++ int __align; ++} pthread_condattr_t; ++ ++ ++/* Keys for thread-specific data */ ++typedef unsigned int pthread_key_t; ++ ++ ++/* Once-only execution */ ++typedef int __ONCE_ALIGNMENT pthread_once_t; ++ ++ ++union pthread_attr_t ++{ ++ char __size[__SIZEOF_PTHREAD_ATTR_T]; ++ long int __align; ++}; ++#ifndef __have_pthread_attr_t ++typedef union pthread_attr_t pthread_attr_t; ++# define __have_pthread_attr_t 1 ++#endif ++ ++ ++typedef union ++{ ++ struct __pthread_mutex_s __data; ++ char __size[__SIZEOF_PTHREAD_MUTEX_T]; ++ long int __align; ++} pthread_mutex_t; ++ ++ ++typedef union ++{ ++struct ++{ ++ 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; ++}__data; ++ char __size[__SIZEOF_PTHREAD_COND_T]; ++ long int __align; ++} pthread_cond_t; ++ ++ ++/* 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; ++ ++ ++/* 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 +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..497e6903 +--- /dev/null ++++ b/nptl_2_17/bits/thread-shared-types_2_17.h +@@ -0,0 +1,185 @@ ++/* Common threading primitives definitions for both POSIX and C11. ++ Copyright (C) 2017-2018 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. ++ ++ Also, the following macros must be define for internal pthread_mutex_t ++ struct definitions (struct __pthread_mutex_s): ++ ++ __PTHREAD_COMPAT_PADDING_MID - any additional members after 'kind' ++ and before '__spin' (for 64 bits) or ++ '__nusers' (for 32 bits). ++ __PTHREAD_COMPAT_PADDING_END - any additional members at the end of ++ the internal structure. ++ __PTHREAD_MUTEX_LOCK_ELISION - 1 if the architecture supports lock ++ elision or 0 otherwise. ++ __PTHREAD_MUTEX_NUSERS_AFTER_KIND - control where to put __nusers. The ++ preferred value for new architectures ++ is 0. ++ __PTHREAD_MUTEX_USE_UNION - control whether internal __spins and ++ __list will be place inside a union for ++ linuxthreads compatibility. ++ The preferred value for new architectures ++ is 0. ++ ++ For a new port the preferred values for the required defines are: ++ ++ #define __PTHREAD_COMPAT_PADDING_MID ++ #define __PTHREAD_COMPAT_PADDING_END ++ #define __PTHREAD_MUTEX_LOCK_ELISION 0 ++ #define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 ++ #define __PTHREAD_MUTEX_USE_UNION 0 ++ ++ __PTHREAD_MUTEX_LOCK_ELISION can be set to 1 if the hardware plans to ++ eventually support lock elision using transactional memory. ++ ++ 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. ++ ++ And finally the internal pthread_rwlock_t (struct __pthread_rwlock_arch_t) ++ must be defined. ++ */ ++#include ++ ++/* Common definition of pthread_mutex_t. */ ++ ++#if !__PTHREAD_MUTEX_USE_UNION ++typedef struct __pthread_internal_list ++{ ++ struct __pthread_internal_list *__prev; ++ struct __pthread_internal_list *__next; ++} __pthread_list_t; ++#else ++typedef struct __pthread_internal_slist ++{ ++ struct __pthread_internal_slist *__next; ++} __pthread_slist_t; ++#endif ++ ++/* Lock elision support. */ ++#if __PTHREAD_MUTEX_LOCK_ELISION ++# if !__PTHREAD_MUTEX_USE_UNION ++# define __PTHREAD_SPINS_DATA \ ++ short __spins; \ ++ short __elision ++# define __PTHREAD_SPINS 0, 0 ++# else ++# define __PTHREAD_SPINS_DATA \ ++ struct \ ++ { \ ++ short __espins; \ ++ short __eelision; \ ++ } __elision_data ++# define __PTHREAD_SPINS { 0, 0 } ++# define __spins __elision_data.__espins ++# define __elision __elision_data.__eelision ++# endif ++#else ++# define __PTHREAD_SPINS_DATA int __spins ++/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */ ++# define __PTHREAD_SPINS 0 ++#endif ++ ++struct __pthread_mutex_s ++{ ++ int __lock __LOCK_ALIGNMENT; ++ unsigned int __count; ++ int __owner; ++#if !__PTHREAD_MUTEX_NUSERS_AFTER_KIND ++ unsigned int __nusers; ++#endif ++ /* KIND must stay at this position in the structure to maintain ++ binary compatibility with static initializers. ++ ++ Concurrency notes: ++ The __kind of a mutex is initialized either by the static ++ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init. ++ ++ After a mutex has been initialized, the __kind of a mutex is usually not ++ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can ++ be enabled. This is done concurrently in the pthread_mutex_*lock functions ++ by using the macro FORCE_ELISION. This macro is only defined for ++ architectures which supports lock elision. ++ ++ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and ++ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set ++ type of a mutex. ++ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set ++ with pthread_mutexattr_settype. ++ After a mutex has been initialized, the functions pthread_mutex_*lock can ++ enable elision - if the mutex-type and the machine supports it - by setting ++ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards ++ the lock / unlock functions are using specific elision code-paths. */ ++ int __kind; ++ __PTHREAD_COMPAT_PADDING_MID ++#if __PTHREAD_MUTEX_NUSERS_AFTER_KIND ++ unsigned int __nusers; ++#endif ++#if !__PTHREAD_MUTEX_USE_UNION ++ __PTHREAD_SPINS_DATA; ++ __pthread_list_t __list; ++# define __PTHREAD_MUTEX_HAVE_PREV 1 ++#else ++ __extension__ union ++ { ++ __PTHREAD_SPINS_DATA; ++ __pthread_slist_t __list; ++ }; ++# define __PTHREAD_MUTEX_HAVE_PREV 0 ++#endif ++ __PTHREAD_COMPAT_PADDING_END ++}; ++ ++ ++/* 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; ++ ++long int __align; ++}; ++ ++#endif /* _THREAD_SHARED_TYPES_H */ +diff --git a/nptl_2_17/build_libpthread-2.17.so.sh b/nptl_2_17/build_libpthread-2.17.so.sh +new file mode 100644 +index 00000000..bdb97d0f +--- /dev/null ++++ b/nptl_2_17/build_libpthread-2.17.so.sh +@@ -0,0 +1,10 @@ ++#!/bin/sh ++set -e ++build_arch=$1 ++build_dir=$2 ++config_dir=libpthread-2.17_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..db299fec +--- /dev/null ++++ b/nptl_2_17/cancellation_2_17.c +@@ -0,0 +1,102 @@ ++/* Copyright (C) 2002-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include "pthreadP_2_17.h" ++#include ++#include ++#include "futex-internal_2_17.h" ++ ++/* The next two functions are similar to pthread_setcanceltype() but ++ more specialized for the use in the cancelable functions like write(). ++ They do not need to check parameters etc. */ ++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; ++} ++ ++ ++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..53cf903d +--- /dev/null ++++ b/nptl_2_17/cleanup_compat_2_17.c +@@ -0,0 +1,50 @@ ++/* Copyright (C) 2002-2018 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 ++ ++ ++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/descr_2_17.h b/nptl_2_17/descr_2_17.h +new file mode 100644 +index 00000000..5148c852 +--- /dev/null ++++ b/nptl_2_17/descr_2_17.h +@@ -0,0 +1,412 @@ ++/* Copyright (C) 2002-2018 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 _DESCR_H ++#define _DESCR_H 1 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "thread_db_2_17.h" ++#include ++#include ++#include ++#include ++ ++#ifndef TCB_ALIGNMENT ++# define TCB_ALIGNMENT sizeof (double) ++#endif ++ ++ ++/* We keep thread specific data in a special data structure, a two-level ++ array. The top-level array contains pointers to dynamically allocated ++ arrays of a certain number of data pointers. So we can implement a ++ sparse array. Each dynamic second-level array has ++ PTHREAD_KEY_2NDLEVEL_SIZE ++ entries. This value shouldn't be too large. */ ++#define PTHREAD_KEY_2NDLEVEL_SIZE 32 ++ ++/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE ++ keys in each subarray. */ ++#define PTHREAD_KEY_1STLEVEL_SIZE \ ++ ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ ++ / PTHREAD_KEY_2NDLEVEL_SIZE) ++ ++ ++ ++ ++/* Internal version of the buffer to store cancellation handler ++ information. */ ++struct pthread_unwind_buf ++{ ++ struct ++ { ++ __jmp_buf jmp_buf; ++ int mask_was_saved; ++ } cancel_jmp_buf[1]; ++ ++ union ++ { ++ /* This is the placeholder of the public version. */ ++ void *pad[4]; ++ ++ struct ++ { ++ /* Pointer to the previous cleanup buffer. */ ++ struct pthread_unwind_buf *prev; ++ ++ /* Backward compatibility: state of the old-style cleanup ++ handler at the time of the previous new-style cleanup handler ++ installment. */ ++ struct _pthread_cleanup_buffer *cleanup; ++ ++ /* Cancellation type before the push call. */ ++ int canceltype; ++ } data; ++ } priv; ++}; ++ ++ ++/* Opcodes and data types for communication with the signal handler to ++ change user/group IDs. */ ++struct xid_command ++{ ++ int syscall_no; ++ /* Enforce zero-extension for the pointer argument in ++ ++ int setgroups (size_t size, const gid_t *list); ++ ++ The kernel XID arguments are unsigned and do not require sign ++ extension. */ ++ unsigned long int id[3]; ++ volatile int cntr; ++ volatile int error; /* -1: no call yet, 0: success seen, >0: error seen. */ ++}; ++ ++ ++/* Data structure used by the kernel to find robust futexes. */ ++struct robust_list_head ++{ ++ void *list; ++ long int futex_offset; ++ void *list_op_pending; ++}; ++ ++ ++/* Data strcture used to handle thread priority protection. */ ++struct priority_protection_data ++{ ++ int priomax; ++ unsigned int priomap[]; ++}; ++ ++ ++/* Thread descriptor data structure. */ ++struct pthread ++{ ++ union ++ { ++#if !TLS_DTV_AT_TP ++ /* This overlaps the TCB as used for TLS without threads (see tls.h). */ ++ tcbhead_t header; ++#else ++ struct ++ { ++ /* multiple_threads is enabled either when the process has spawned at ++ least one thread or when a single-threaded process cancels itself. ++ This enables additional code to introduce locking before doing some ++ compare_and_exchange operations and also enable cancellation points. ++ The concepts of multiple threads and cancellation points ideally ++ should be separate, since it is not necessary for multiple threads to ++ have been created for cancellation points to be enabled, as is the ++ case is when single-threaded process cancels itself. ++ ++ Since enabling multiple_threads enables additional code in ++ cancellation points and compare_and_exchange operations, there is a ++ potential for an unneeded performance hit when it is enabled in a ++ single-threaded, self-canceling process. This is OK though, since a ++ single-threaded process will enable async cancellation only when it ++ looks to cancel itself and is hence going to end anyway. */ ++ int multiple_threads; ++ int gscope_flag; ++ } header; ++#endif ++ ++ /* This extra padding has no special purpose, and this structure layout ++ is private and subject to change without affecting the official ABI. ++ We just have it here in case it might be convenient for some ++ implementation-specific instrumentation hack or suchlike. */ ++ void *__padding[24]; ++ }; ++ ++ /* This descriptor's link on the `stack_used' or `__stack_user' list. */ ++ list_t list; ++ ++ /* Thread ID - which is also a 'is this thread descriptor (and ++ therefore stack) used' flag. */ ++ pid_t tid; ++ ++ /* Ununsed. */ ++ pid_t pid_ununsed; ++ ++ /* List of robust mutexes the thread is holding. */ ++#if __PTHREAD_MUTEX_HAVE_PREV ++ void *robust_prev; ++ struct robust_list_head robust_head; ++ ++ /* The list above is strange. It is basically a double linked list ++ but the pointer to the next/previous element of the list points ++ in the middle of the object, the __next element. Whenever ++ casting to __pthread_list_t we need to adjust the pointer ++ first. ++ These operations are effectively concurrent code in that the thread ++ can get killed at any point in time and the kernel takes over. Thus, ++ the __next elements are a kind of concurrent list and we need to ++ enforce using compiler barriers that the individual operations happen ++ in such a way that the kernel always sees a consistent list. The ++ backward links (ie, the __prev elements) are not used by the kernel. ++ FIXME We should use relaxed MO atomic operations here and signal fences ++ because this kind of concurrency is similar to synchronizing with a ++ signal handler. */ ++# define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next)) ++ ++# define ENQUEUE_MUTEX_BOTH(mutex, val) \ ++ do { \ ++ __pthread_list_t *next = (__pthread_list_t *) \ ++ ((((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_head.list)) & ~1ul) \ ++ - QUEUE_PTR_ADJUST); \ ++ next->__prev = (void *) &mutex->__data.__list.__next; \ ++ mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF, \ ++ robust_head.list); \ ++ mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head; \ ++ /* Ensure that the new list entry is ready before we insert it. */ \ ++ __asm ("" ::: "memory"); \ ++ THREAD_SETMEM (THREAD_SELF, robust_head.list, \ ++ (void *) (((uintptr_t) &mutex->__data.__list.__next) \ ++ | val)); \ ++ } while (0) ++# define DEQUEUE_MUTEX(mutex) \ ++ do { \ ++ __pthread_list_t *next = (__pthread_list_t *) \ ++ ((char *) (((uintptr_t) mutex->__data.__list.__next) & ~1ul) \ ++ - QUEUE_PTR_ADJUST); \ ++ next->__prev = mutex->__data.__list.__prev; \ ++ __pthread_list_t *prev = (__pthread_list_t *) \ ++ ((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul) \ ++ - QUEUE_PTR_ADJUST); \ ++ prev->__next = mutex->__data.__list.__next; \ ++ /* Ensure that we remove the entry from the list before we change the \ ++ __next pointer of the entry, which is read by the kernel. */ \ ++ __asm ("" ::: "memory"); \ ++ mutex->__data.__list.__prev = NULL; \ ++ mutex->__data.__list.__next = NULL; \ ++ } while (0) ++#else ++ union ++ { ++ __pthread_slist_t robust_list; ++ struct robust_list_head robust_head; ++ }; ++ ++# define ENQUEUE_MUTEX_BOTH(mutex, val) \ ++ do { \ ++ mutex->__data.__list.__next \ ++ = THREAD_GETMEM (THREAD_SELF, robust_list.__next); \ ++ /* Ensure that the new list entry is ready before we insert it. */ \ ++ __asm ("" ::: "memory"); \ ++ THREAD_SETMEM (THREAD_SELF, robust_list.__next, \ ++ (void *) (((uintptr_t) &mutex->__data.__list) | val)); \ ++ } while (0) ++# define DEQUEUE_MUTEX(mutex) \ ++ do { \ ++ __pthread_slist_t *runp = (__pthread_slist_t *) \ ++ (((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_list.__next)) & ~1ul); \ ++ if (runp == &mutex->__data.__list) \ ++ THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next); \ ++ else \ ++ { \ ++ __pthread_slist_t *next = (__pthread_slist_t *) \ ++ (((uintptr_t) runp->__next) & ~1ul); \ ++ while (next != &mutex->__data.__list) \ ++ { \ ++ runp = next; \ ++ next = (__pthread_slist_t *) (((uintptr_t) runp->__next) & ~1ul); \ ++ } \ ++ \ ++ runp->__next = next->__next; \ ++ /* Ensure that we remove the entry from the list before we change the \ ++ __next pointer of the entry, which is read by the kernel. */ \ ++ __asm ("" ::: "memory"); \ ++ mutex->__data.__list.__next = NULL; \ ++ } \ ++ } while (0) ++#endif ++#define ENQUEUE_MUTEX(mutex) ENQUEUE_MUTEX_BOTH (mutex, 0) ++#define ENQUEUE_MUTEX_PI(mutex) ENQUEUE_MUTEX_BOTH (mutex, 1) ++ ++ /* List of cleanup buffers. */ ++ struct _pthread_cleanup_buffer *cleanup; ++ ++ /* Unwind information. */ ++ struct pthread_unwind_buf *cleanup_jmp_buf; ++#define HAVE_CLEANUP_JMP_BUF ++ ++ /* Flags determining processing of cancellation. */ ++ int cancelhandling; ++ /* Bit set if cancellation is disabled. */ ++#define CANCELSTATE_BIT 0 ++#define CANCELSTATE_BITMASK (0x01 << CANCELSTATE_BIT) ++ /* Bit set if asynchronous cancellation mode is selected. */ ++#define CANCELTYPE_BIT 1 ++#define CANCELTYPE_BITMASK (0x01 << CANCELTYPE_BIT) ++ /* Bit set if canceling has been initiated. */ ++#define CANCELING_BIT 2 ++#define CANCELING_BITMASK (0x01 << CANCELING_BIT) ++ /* Bit set if canceled. */ ++#define CANCELED_BIT 3 ++#define CANCELED_BITMASK (0x01 << CANCELED_BIT) ++ /* Bit set if thread is exiting. */ ++#define EXITING_BIT 4 ++#define EXITING_BITMASK (0x01 << EXITING_BIT) ++ /* Bit set if thread terminated and TCB is freed. */ ++#define TERMINATED_BIT 5 ++#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT) ++ /* Bit set if thread is supposed to change XID. */ ++#define SETXID_BIT 6 ++#define SETXID_BITMASK (0x01 << SETXID_BIT) ++ /* Mask for the rest. Helps the compiler to optimize. */ ++#define CANCEL_RESTMASK 0xffffff80 ++ ++#define CANCEL_ENABLED_AND_CANCELED(value) \ ++ (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK \ ++ | CANCEL_RESTMASK | TERMINATED_BITMASK)) == CANCELED_BITMASK) ++#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \ ++ (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK \ ++ | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK)) \ ++ == (CANCELTYPE_BITMASK | CANCELED_BITMASK)) ++ ++ /* Flags. Including those copied from the thread attribute. */ ++ int flags; ++ ++ /* We allocate one block of references here. This should be enough ++ to avoid allocating any memory dynamically for most applications. */ ++ struct pthread_key_data ++ { ++ /* Sequence number. 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; ++ ++ /* Data pointer. */ ++ void *data; ++ } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE]; ++ ++ /* Two-level array for the thread-specific data. */ ++ struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE]; ++ ++ /* Flag which is set when specific data is set. */ ++ bool specific_used; ++ ++ /* True if events must be reported. */ ++ bool report_events; ++ ++ /* True if the user provided the stack. */ ++ bool user_stack; ++ ++ /* True if thread must stop at startup time. */ ++ bool stopped_start; ++ ++ /* The parent's cancel handling at the time of the pthread_create ++ call. This might be needed to undo the effects of a cancellation. */ ++ int parent_cancelhandling; ++ ++ /* Lock to synchronize access to the descriptor. */ ++ int lock; ++ ++ /* Lock for synchronizing setxid calls. */ ++ unsigned int setxid_futex; ++ ++#ifdef __x86_64__ ++ /* Offset of the CPU clock at start thread start time. */ ++ hp_timing_t cpuclock_offset; ++#endif ++ ++ /* If the thread waits to join another one the ID of the latter is ++ stored here. ++ ++ In case a thread is detached this field contains a pointer of the ++ TCB if the thread itself. This is something which cannot happen ++ in normal operation. */ ++ struct pthread *joinid; ++ /* Check whether a thread is detached. */ ++#define IS_DETACHED(pd) ((pd)->joinid == (pd)) ++ ++ /* The result of the thread function. */ ++ void *result; ++ ++ /* Scheduling parameters for the new thread. */ ++ struct sched_param schedparam; ++ int schedpolicy; ++ ++ /* Start position of the code to be executed and the argument passed ++ to the function. */ ++ void *(*start_routine) (void *); ++ void *arg; ++ ++ /* Debug state. */ ++ td_eventbuf_t eventbuf; ++ /* Next descriptor with a pending event. */ ++ struct pthread *nextevent; ++ ++ /* Machine-specific unwind info. */ ++ struct _Unwind_Exception exc; ++ ++ /* If nonzero, pointer to the area allocated for the stack and guard. */ ++ void *stackblock; ++ /* Size of the stackblock area including the guard. */ ++ size_t stackblock_size; ++ /* Size of the included guard area. */ ++ size_t guardsize; ++ /* This is what the user specified and what we will report. */ ++ size_t reported_guardsize; ++ ++ /* Thread Priority Protection data. */ ++ struct priority_protection_data *tpp; ++ ++ /* Resolver state. */ ++ struct __res_state res; ++ ++ /* Indicates whether is a C11 thread created by thrd_creat. */ ++ bool c11; ++ ++ /* This member must be last. */ ++ char end_padding[]; ++ ++#define PTHREAD_STRUCT_END_PADDING \ ++ (sizeof (struct pthread) - offsetof (struct pthread, end_padding)) ++} __attribute ((aligned (TCB_ALIGNMENT))); ++ ++ ++#endif /* descr.h */ +diff --git a/nptl_2_17/elision-conf_2_17.c b/nptl_2_17/elision-conf_2_17.c +new file mode 100644 +index 00000000..13dd985e +--- /dev/null ++++ b/nptl_2_17/elision-conf_2_17.c +@@ -0,0 +1,137 @@ ++/* elision-conf.c: Lock elision tunable parameters. ++ Copyright (C) 2013-2018 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 "config.h" ++#include ++#include ++#include ++#include ++ ++# define TUNABLE_NAMESPACE elision ++# define TOP_NAMESPACE glibc ++#include ++ ++/* Reasonable initial tuning values, may be revised in the future. ++ This is a conservative initial value. */ ++ ++struct elision_config __elision_aconf = ++ { ++ /* How often to not attempt to use elision if a transaction aborted ++ because the lock is already acquired. Expressed in number of lock ++ acquisition attempts. */ ++ .skip_lock_busy = 3, ++ /* How often to not attempt to use elision if a transaction aborted due ++ to reasons other than other threads' memory accesses. Expressed in ++ number of lock acquisition attempts. */ ++ .skip_lock_internal_abort = 3, ++ /* How often we retry using elision if there is chance for the transaction ++ to finish execution (e.g., it wasn't aborted due to the lock being ++ already acquired. */ ++ .retry_try_xbegin = 3, ++ /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock. */ ++ .skip_trylock_internal_abort = 3, ++ }; ++ ++/* Force elision for all new locks. This is used to decide whether existing ++ DEFAULT locks should be automatically upgraded to elision in ++ pthread_mutex_lock(). Disabled for suid programs. Only used when elision ++ is available. */ ++ ++int __pthread_force_elision attribute_hidden = 0; ++ ++#if HAVE_TUNABLES ++static inline void ++__always_inline ++do_set_elision_enable (int32_t elision_enable) ++{ ++ /* Enable elision if it's avaliable in hardware. It's not necessary to check ++ if __libc_enable_secure isn't enabled since elision_enable will be set ++ according to the default, which is disabled. */ ++ if (elision_enable == 1) ++ __pthread_force_elision = HAS_CPU_FEATURE (RTM) ? 1 : 0; ++} ++ ++/* The pthread->elision_enable tunable is 0 or 1 indicating that elision ++ should be disabled or enabled respectively. The feature will only be used ++ if it's supported by the hardware. */ ++ ++void ++TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *valp) ++{ ++ int32_t elision_enable = (int32_t) valp->numval; ++ do_set_elision_enable (elision_enable); ++} ++ ++#define TUNABLE_CALLBACK_FNDECL(__name, __type) \ ++static inline void \ ++__always_inline \ ++do_set_elision_ ## __name (__type value) \ ++{ \ ++ __elision_aconf.__name = value; \ ++} \ ++void \ ++TUNABLE_CALLBACK (set_elision_ ## __name) (tunable_val_t *valp) \ ++{ \ ++ __type value = (__type) (valp)->numval; \ ++ do_set_elision_ ## __name (value); \ ++} ++ ++TUNABLE_CALLBACK_FNDECL (skip_lock_busy, int32_t); ++TUNABLE_CALLBACK_FNDECL (skip_lock_internal_abort, int32_t); ++TUNABLE_CALLBACK_FNDECL (retry_try_xbegin, int32_t); ++TUNABLE_CALLBACK_FNDECL (skip_trylock_internal_abort, int32_t); ++#endif ++ ++/* Initialize elision. */ ++ ++static void ++elision_init (int argc __attribute__ ((unused)), ++ char **argv __attribute__ ((unused)), ++ char **environ) ++{ ++#if HAVE_TUNABLES ++ /* Elision depends on tunables and must be explicitly turned on by setting ++ the appropriate tunable on a supported platform. */ ++ ++ TUNABLE_GET (enable, int32_t, ++ TUNABLE_CALLBACK (set_elision_enable)); ++ TUNABLE_GET (skip_lock_busy, int32_t, ++ TUNABLE_CALLBACK (set_elision_skip_lock_busy)); ++ TUNABLE_GET (skip_lock_internal_abort, int32_t, ++ TUNABLE_CALLBACK (set_elision_skip_lock_internal_abort)); ++ TUNABLE_GET (tries, int32_t, ++ TUNABLE_CALLBACK (set_elision_retry_try_xbegin)); ++ TUNABLE_GET (skip_trylock_internal_abort, int32_t, ++ TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort)); ++#endif ++ ++ if (!__pthread_force_elision) ++ __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks. */ ++} ++ ++#ifdef SHARED ++# define INIT_SECTION ".init_array" ++#else ++# define INIT_SECTION ".preinit_array" ++#endif ++ ++void (*const __pthread_init_array []) (int, char **, char **) ++ __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) = ++{ ++ &elision_init ++}; +diff --git a/nptl_2_17/elision-conf_2_17.h b/nptl_2_17/elision-conf_2_17.h +new file mode 100644 +index 00000000..9cd38962 +--- /dev/null ++++ b/nptl_2_17/elision-conf_2_17.h +@@ -0,0 +1,41 @@ ++/* elision-conf.h: Lock elision tunable parameters. ++ Copyright (C) 2013-2018 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 _ELISION_CONF_H ++#define _ELISION_CONF_H 1 ++ ++#include ++#include ++ ++/* Should make sure there is no false sharing on this. */ ++ ++struct elision_config ++{ ++ int skip_lock_busy; ++ int skip_lock_internal_abort; ++ int retry_try_xbegin; ++ int skip_trylock_internal_abort; ++}; ++ ++extern struct elision_config __elision_aconf attribute_hidden; ++ ++extern int __pthread_force_elision attribute_hidden; ++ ++/* Tell the test suite to test elision for this architecture. */ ++#define HAVE_ELISION 1 ++ ++#endif +diff --git a/nptl_2_17/elision-lock_2_17.c b/nptl_2_17/elision-lock_2_17.c +new file mode 100644 +index 00000000..6eebde8a +--- /dev/null ++++ b/nptl_2_17/elision-lock_2_17.c +@@ -0,0 +1,107 @@ ++/* elision-lock.c: Elided pthread mutex lock. ++ Copyright (C) 2011-2018 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 "pthreadP_2_17.h" ++#include "lowlevellock_2_17.h" ++#include "hle_2_17.h" ++#include ++ ++#if !defined(LLL_LOCK) && !defined(EXTRAARG) ++/* Make sure the configuration code is always linked in for static ++ libraries. */ ++#include "elision-conf_2_17.c" ++#endif ++ ++#ifndef EXTRAARG ++#define EXTRAARG ++#endif ++#ifndef LLL_LOCK ++#define LLL_LOCK(a,b) lll_lock(a,b), 0 ++#endif ++ ++#define aconf __elision_aconf ++ ++/* Adaptive lock using transactions. ++ By default the lock region is run as a transaction, and when it ++ aborts or the lock is busy the lock adapts itself. */ ++ ++int ++__lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int private) ++{ ++ /* adapt_count can be accessed concurrently; these accesses can be both ++ inside of transactions (if critical sections are nested and the outer ++ critical section uses lock elision) and outside of transactions. Thus, ++ we need to use atomic accesses to avoid data races. However, the ++ value of adapt_count is just a hint, so relaxed MO accesses are ++ sufficient. */ ++ if (atomic_load_relaxed (adapt_count) <= 0) ++ { ++ unsigned status; ++ int try_xbegin; ++ ++ for (try_xbegin = aconf.retry_try_xbegin; ++ try_xbegin > 0; ++ try_xbegin--) ++ { ++ if ((status = _xbegin()) == _XBEGIN_STARTED) ++ { ++ if (*futex == 0) ++ return 0; ++ ++ /* Lock was busy. Fall back to normal locking. ++ Could also _xend here but xabort with 0xff code ++ is more visible in the profiler. */ ++ _xabort (_ABORT_LOCK_BUSY); ++ } ++ ++ if (!(status & _XABORT_RETRY)) ++ { ++ if ((status & _XABORT_EXPLICIT) ++ && _XABORT_CODE (status) == _ABORT_LOCK_BUSY) ++ { ++ /* Right now we skip here. Better would be to wait a bit ++ and retry. This likely needs some spinning. See ++ above for why relaxed MO is sufficient. */ ++ if (atomic_load_relaxed (adapt_count) ++ != aconf.skip_lock_busy) ++ atomic_store_relaxed (adapt_count, aconf.skip_lock_busy); ++ } ++ /* Internal abort. There is no chance for retry. ++ Use the normal locking and next time use lock. ++ Be careful to avoid writing to the lock. See above for why ++ relaxed MO is sufficient. */ ++ else if (atomic_load_relaxed (adapt_count) ++ != aconf.skip_lock_internal_abort) ++ atomic_store_relaxed (adapt_count, ++ aconf.skip_lock_internal_abort); ++ break; ++ } ++ } ++ } ++ else ++ { ++ /* Use a normal lock until the threshold counter runs out. ++ Lost updates possible. */ ++ atomic_store_relaxed (adapt_count, ++ atomic_load_relaxed (adapt_count) - 1); ++ } ++ ++ /* Use a normal lock here. */ ++ return LLL_LOCK ((*futex), private); ++} +diff --git a/nptl_2_17/elision-timed_2_17.c b/nptl_2_17/elision-timed_2_17.c +new file mode 100644 +index 00000000..b103f9aa +--- /dev/null ++++ b/nptl_2_17/elision-timed_2_17.c +@@ -0,0 +1,26 @@ ++/* elision-timed.c: Lock elision timed lock. ++ Copyright (C) 2013-2018 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 "lowlevellock_2_17.h" ++#define __lll_lock_elision __lll_timedlock_elision ++#define EXTRAARG const struct timespec *t, ++#undef LLL_LOCK ++#define LLL_LOCK(a, b) lll_timedlock(a, t, b) ++#include "elision-lock_2_17.c" +diff --git a/nptl_2_17/elision-trylock_2_17.c b/nptl_2_17/elision-trylock_2_17.c +new file mode 100644 +index 00000000..8ed92198 +--- /dev/null ++++ b/nptl_2_17/elision-trylock_2_17.c +@@ -0,0 +1,75 @@ ++/* elision-trylock.c: Lock eliding trylock for pthreads. ++ Copyright (C) 2013-2018 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 "hle_2_17.h" ++#include ++ ++#define aconf __elision_aconf ++ ++/* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is ++ the adaptation counter in the mutex. */ ++ ++int ++__lll_trylock_elision (int *futex, short *adapt_count) ++{ ++ /* Implement POSIX semantics by forbiding nesting ++ trylock. Sorry. After the abort the code is re-executed ++ non transactional and if the lock was already locked ++ return an error. */ ++ _xabort (_ABORT_NESTED_TRYLOCK); ++ ++ /* Only try a transaction if it's worth it. See __lll_lock_elision for ++ why we need atomic accesses. Relaxed MO is sufficient because this is ++ just a hint. */ ++ if (atomic_load_relaxed (adapt_count) <= 0) ++ { ++ unsigned status; ++ ++ if ((status = _xbegin()) == _XBEGIN_STARTED) ++ { ++ if (*futex == 0) ++ return 0; ++ ++ /* Lock was busy. Fall back to normal locking. ++ Could also _xend here but xabort with 0xff code ++ is more visible in the profiler. */ ++ _xabort (_ABORT_LOCK_BUSY); ++ } ++ ++ if (!(status & _XABORT_RETRY)) ++ { ++ /* Internal abort. No chance for retry. For future ++ locks don't try speculation for some time. See above for MO. */ ++ if (atomic_load_relaxed (adapt_count) ++ != aconf.skip_lock_internal_abort) ++ atomic_store_relaxed (adapt_count, aconf.skip_lock_internal_abort); ++ } ++ /* Could do some retries here. */ ++ } ++ else ++ { ++ /* Lost updates are possible but harmless (see above). */ ++ atomic_store_relaxed (adapt_count, ++ atomic_load_relaxed (adapt_count) - 1); ++ } ++ ++ return lll_trylock (*futex); ++} +diff --git a/nptl_2_17/elision-unlock_2_17.c b/nptl_2_17/elision-unlock_2_17.c +new file mode 100644 +index 00000000..20b658a8 +--- /dev/null ++++ b/nptl_2_17/elision-unlock_2_17.c +@@ -0,0 +1,33 @@ ++/* elision-unlock.c: Commit an elided pthread lock. ++ Copyright (C) 2013-2018 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 "pthreadP_2_17.h" ++#include "lowlevellock_2_17.h" ++#include "hle_2_17.h" ++ ++int ++__lll_unlock_elision(int *lock, int private) ++{ ++ /* When the lock was free we're in a transaction. ++ When you crash here you unlocked a free lock. */ ++ if (*lock == 0) ++ _xend(); ++ else ++ lll_unlock ((*lock), private); ++ return 0; ++} +diff --git a/nptl_2_17/futex-internal_2_17.h b/nptl_2_17/futex-internal_2_17.h +new file mode 100644 +index 00000000..b0512da0 +--- /dev/null ++++ b/nptl_2_17/futex-internal_2_17.h +@@ -0,0 +1,263 @@ ++/* futex operations for glibc-internal use. Linux version. ++ Copyright (C) 2014-2018 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 FUTEX_INTERNAL_H ++#define FUTEX_INTERNAL_H ++ ++#include ++#include ++#include ++#include ++ ++/* See sysdeps/nptl/futex-internal.h for documentation; this file only ++ contains Linux-specific comments. ++ ++ The Linux kernel treats provides absolute timeouts based on the ++ CLOCK_REALTIME clock and relative timeouts measured against the ++ CLOCK_MONOTONIC clock. ++ ++ We expect a Linux kernel version of 2.6.22 or more recent (since this ++ version, EINTR is not returned on spurious wake-ups anymore). */ ++ ++/* FUTEX_SHARED is always supported by the Linux kernel. */ ++static __always_inline int ++futex_supports_pshared (int pshared) ++{ ++ if (__glibc_likely (pshared == PTHREAD_PROCESS_PRIVATE)) ++ return 0; ++ else if (pshared == PTHREAD_PROCESS_SHARED) ++ return 0; ++ else ++ return EINVAL; ++} ++ ++/* The Linux kernel supports relative timeouts measured against the ++ CLOCK_MONOTONIC clock. */ ++static __always_inline bool ++futex_supports_exact_relative_timeouts (void) ++{ ++ return true; ++} ++ ++/* See sysdeps/nptl/futex-internal.h for details. */ ++static __always_inline int ++futex_wait (unsigned int *futex_word, unsigned int expected, int private) ++{ ++ int err = lll_futex_timed_wait (futex_word, expected, NULL, private); ++ switch (err) ++ { ++ case 0: ++ case -EAGAIN: ++ case -EINTR: ++ return -err; ++ ++ case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */ ++ case -EFAULT: /* Must have been caused by a glibc or application bug. */ ++ case -EINVAL: /* Either due to wrong alignment or due to the timeout not ++ being normalized. Must have been caused by a glibc or ++ application bug. */ ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ futex_fatal_error (); ++ } ++} ++ ++/* See sysdeps/nptl/futex-internal.h for details. */ ++static __always_inline int ++futex_wait_cancelable (unsigned int *futex_word, unsigned int expected, ++ int private) ++{ ++ int oldtype; ++ oldtype = __pthread_enable_asynccancel (); ++ int err = lll_futex_timed_wait (futex_word, expected, NULL, private); ++ __pthread_disable_asynccancel (oldtype); ++ switch (err) ++ { ++ case 0: ++ case -EAGAIN: ++ case -EINTR: ++ return -err; ++ ++ case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */ ++ case -EFAULT: /* Must have been caused by a glibc or application bug. */ ++ case -EINVAL: /* Either due to wrong alignment or due to the timeout not ++ being normalized. Must have been caused by a glibc or ++ application bug. */ ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ futex_fatal_error (); ++ } ++} ++ ++/* See sysdeps/nptl/futex-internal.h for details. */ ++static __always_inline int ++futex_reltimed_wait (unsigned int *futex_word, unsigned int expected, ++ const struct timespec *reltime, int private) ++{ ++ int err = lll_futex_timed_wait (futex_word, expected, reltime, private); ++ switch (err) ++ { ++ case 0: ++ case -EAGAIN: ++ case -EINTR: ++ case -ETIMEDOUT: ++ return -err; ++ ++ case -EFAULT: /* Must have been caused by a glibc or application bug. */ ++ case -EINVAL: /* Either due to wrong alignment or due to the timeout not ++ being normalized. Must have been caused by a glibc or ++ application bug. */ ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ futex_fatal_error (); ++ } ++} ++ ++/* See sysdeps/nptl/futex-internal.h for details. */ ++static __always_inline int ++futex_reltimed_wait_cancelable (unsigned int *futex_word, ++ unsigned int expected, ++ const struct timespec *reltime, int private) ++{ ++ int oldtype; ++ oldtype = __pthread_enable_asynccancel (); ++ int err = lll_futex_timed_wait (futex_word, expected, reltime, private); ++ __pthread_disable_asynccancel (oldtype); ++ switch (err) ++ { ++ case 0: ++ case -EAGAIN: ++ case -EINTR: ++ case -ETIMEDOUT: ++ return -err; ++ ++ case -EFAULT: /* Must have been caused by a glibc or application bug. */ ++ case -EINVAL: /* Either due to wrong alignment or due to the timeout not ++ being normalized. Must have been caused by a glibc or ++ application bug. */ ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ futex_fatal_error (); ++ } ++} ++ ++/* See sysdeps/nptl/futex-internal.h for details. */ ++static __always_inline int ++futex_abstimed_supported_clockid (clockid_t clockid) ++{ ++ return lll_futex_supported_clockid (clockid); ++} ++ ++/* See sysdeps/nptl/futex-internal.h for details. */ ++static __always_inline int ++futex_abstimed_wait (unsigned int *futex_word, unsigned int expected, ++ clockid_t clockid, ++ const struct timespec *abstime, int private) ++{ ++ /* Work around the fact that the kernel rejects negative timeout values ++ despite them being valid. */ ++ if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0))) ++ return ETIMEDOUT; ++ int err = lll_futex_clock_wait_bitset (futex_word, expected, ++ clockid, abstime, ++ private); ++ switch (err) ++ { ++ case 0: ++ case -EAGAIN: ++ case -EINTR: ++ case -ETIMEDOUT: ++ return -err; ++ ++ case -EFAULT: /* Must have been caused by a glibc or application bug. */ ++ case -EINVAL: /* Either due to wrong alignment, unsupported ++ clockid or due to the timeout not being ++ normalized. Must have been caused by a glibc or ++ application bug. */ ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ futex_fatal_error (); ++ } ++} ++ ++/* See sysdeps/nptl/futex-internal.h for details. */ ++static __always_inline int ++futex_abstimed_wait_cancelable (unsigned int *futex_word, ++ unsigned int expected, ++ clockid_t clockid, ++ const struct timespec *abstime, int private) ++{ ++ /* Work around the fact that the kernel rejects negative timeout values ++ despite them being valid. */ ++ if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0))) ++ return ETIMEDOUT; ++ int oldtype; ++ oldtype = __pthread_enable_asynccancel (); ++ int err = lll_futex_clock_wait_bitset (futex_word, expected, ++ clockid, abstime, ++ private); ++ __pthread_disable_asynccancel (oldtype); ++ switch (err) ++ { ++ case 0: ++ case -EAGAIN: ++ case -EINTR: ++ case -ETIMEDOUT: ++ return -err; ++ ++ case -EFAULT: /* Must have been caused by a glibc or application bug. */ ++ case -EINVAL: /* Either due to wrong alignment or due to the timeout not ++ being normalized. Must have been caused by a glibc or ++ application bug. */ ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ futex_fatal_error (); ++ } ++} ++ ++/* See sysdeps/nptl/futex-internal.h for details. */ ++static __always_inline void ++futex_wake (unsigned int *futex_word, int processes_to_wake, int private) ++{ ++ int res = lll_futex_wake (futex_word, processes_to_wake, private); ++ /* No error. Ignore the number of woken processes. */ ++ if (res >= 0) ++ return; ++ switch (res) ++ { ++ case -EFAULT: /* Could have happened due to memory reuse. */ ++ case -EINVAL: /* Could be either due to incorrect alignment (a bug in ++ glibc or in the application) or due to memory being ++ reused for a PI futex. We cannot distinguish between the ++ two causes, and one of them is correct use, so we do not ++ act in this case. */ ++ return; ++ case -ENOSYS: /* Must have been caused by a glibc bug. */ ++ /* No other errors are documented at this time. */ ++ default: ++ futex_fatal_error (); ++ } ++} ++ ++#endif /* futex-internal.h */ +diff --git a/nptl_2_17/hle_2_17.h b/nptl_2_17/hle_2_17.h +new file mode 100644 +index 00000000..4a7b9e3b +--- /dev/null ++++ b/nptl_2_17/hle_2_17.h +@@ -0,0 +1,75 @@ ++/* Shared RTM header. Emulate TSX intrinsics for compilers and assemblers ++ that do not support the intrinsics and instructions yet. */ ++#ifndef _HLE_H ++#define _HLE_H 1 ++ ++#ifdef __ASSEMBLER__ ++ ++.macro XBEGIN target ++ .byte 0xc7,0xf8 ++ .long \target-1f ++1: ++.endm ++ ++.macro XEND ++ .byte 0x0f,0x01,0xd5 ++.endm ++ ++.macro XABORT code ++ .byte 0xc6,0xf8,\code ++.endm ++ ++.macro XTEST ++ .byte 0x0f,0x01,0xd6 ++.endm ++ ++#endif ++ ++/* Official RTM intrinsics interface matching gcc/icc, but works ++ on older gcc compatible compilers and binutils. ++ We should somehow detect if the compiler supports it, because ++ it may be able to generate slightly better code. */ ++ ++#define _XBEGIN_STARTED (~0u) ++#define _XABORT_EXPLICIT (1 << 0) ++#define _XABORT_RETRY (1 << 1) ++#define _XABORT_CONFLICT (1 << 2) ++#define _XABORT_CAPACITY (1 << 3) ++#define _XABORT_DEBUG (1 << 4) ++#define _XABORT_NESTED (1 << 5) ++#define _XABORT_CODE(x) (((x) >> 24) & 0xff) ++ ++#define _ABORT_LOCK_BUSY 0xff ++#define _ABORT_LOCK_IS_LOCKED 0xfe ++#define _ABORT_NESTED_TRYLOCK 0xfd ++ ++#ifndef __ASSEMBLER__ ++ ++#define __force_inline __attribute__((__always_inline__)) inline ++ ++static __force_inline int _xbegin(void) ++{ ++ int ret = _XBEGIN_STARTED; ++ asm volatile (".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory"); ++ return ret; ++} ++ ++static __force_inline void _xend(void) ++{ ++ asm volatile (".byte 0x0f,0x01,0xd5" ::: "memory"); ++} ++ ++static __force_inline void _xabort(const unsigned int status) ++{ ++ asm volatile (".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); ++} ++ ++static __force_inline int _xtest(void) ++{ ++ unsigned char out; ++ asm volatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : "=r" (out) :: "memory"); ++ return out; ++} ++ ++#endif ++#endif +diff --git a/nptl_2_17/internaltypes_2_17.h b/nptl_2_17/internaltypes_2_17.h +new file mode 100644 +index 00000000..603dc01c +--- /dev/null ++++ b/nptl_2_17/internaltypes_2_17.h +@@ -0,0 +1,179 @@ ++/* Copyright (C) 2002-2018 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/kernel-features_2_17.h b/nptl_2_17/kernel-features_2_17.h +new file mode 100644 +index 00000000..299ae0a1 +--- /dev/null ++++ b/nptl_2_17/kernel-features_2_17.h +@@ -0,0 +1,162 @@ ++/* Set flags signalling availability of kernel features based on given ++ kernel version number. ++ Copyright (C) 1999-2018 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 must not contain any C code. At least it must be protected ++ to allow using the file also in assembler files. */ ++ ++#ifndef __LINUX_KERNEL_VERSION_2_17 ++/* We assume the worst; all kernels should be supported. */ ++# define __LINUX_KERNEL_VERSION_2_17 0 ++#endif ++ ++/* We assume for __LINUX_KERNEL_VERSION the same encoding used in ++ linux/version.h. I.e., the major, minor, and subminor all get a ++ byte with the major number being in the highest byte. This means ++ we can do numeric comparisons. ++ ++ In the following we will define certain symbols depending on ++ whether the describes kernel feature is available in the kernel ++ version given by __LINUX_KERNEL_VERSION. We are not always exactly ++ recording the correct versions in which the features were ++ introduced. If somebody cares these values can afterwards be ++ corrected. */ ++ ++/* Some architectures use the socketcall multiplexer for some or all ++ socket-related operations instead of separate syscalls. ++ __ASSUME_SOCKETCALL is defined for such architectures. */ ++ ++/* The changed st_ino field appeared in 2.4.0-test6. However, SH is lame, ++ and still does not have a 64-bit inode field. */ ++#define __ASSUME_ST_INO_64_BIT 1 ++ ++/* The statfs64 syscalls are available in 2.5.74 (but not for alpha). */ ++#define __ASSUME_STATFS64 1 ++ ++/* pselect/ppoll were introduced just after 2.6.16-rc1. On x86_64 and ++ SH this appeared first in 2.6.19-rc1, on ia64 in 2.6.22-rc1. */ ++#define __ASSUME_PSELECT 1 ++ ++/* The *at syscalls were introduced just after 2.6.16-rc1. On PPC ++ they were introduced in 2.6.17-rc1, on SH in 2.6.19-rc1. */ ++#define __ASSUME_ATFCTS 1 ++ ++/* Support for inter-process robust mutexes was added in 2.6.17 (but ++ some architectures lack futex_atomic_cmpxchg_inatomic in some ++ configurations). */ ++#define __ASSUME_SET_ROBUST_LIST 1 ++ ++/* Support for various CLOEXEC and NONBLOCK flags was added in ++ 2.6.27. */ ++#define __ASSUME_IN_NONBLOCK 1 ++ ++/* Support for the FUTEX_CLOCK_REALTIME flag was added in 2.6.29. */ ++#define __ASSUME_FUTEX_CLOCK_REALTIME 1 ++ ++/* Support for preadv and pwritev was added in 2.6.30. */ ++#define __ASSUME_PREADV 1 ++#define __ASSUME_PWRITEV 1 ++ ++ ++/* Support for FUTEX_*_REQUEUE_PI was added in 2.6.31 (but some ++ * architectures lack futex_atomic_cmpxchg_inatomic in some ++ * configurations). */ ++#define __ASSUME_REQUEUE_PI 1 ++ ++/* Support for sendmmsg functionality was added in 3.0. */ ++#define __ASSUME_SENDMMSG 1 ++ ++/* On most architectures, most socket syscalls are supported for all ++ supported kernel versions, but on some socketcall architectures ++ separate syscalls were only added later. */ ++#define __ASSUME_SENDMSG_SYSCALL 1 ++#define __ASSUME_RECVMSG_SYSCALL 1 ++#define __ASSUME_ACCEPT_SYSCALL 1 ++#define __ASSUME_CONNECT_SYSCALL 1 ++#define __ASSUME_RECVFROM_SYSCALL 1 ++#define __ASSUME_SENDTO_SYSCALL 1 ++#define __ASSUME_ACCEPT4_SYSCALL 1 ++#define __ASSUME_RECVMMSG_SYSCALL 1 ++#define __ASSUME_SENDMMSG_SYSCALL 1 ++ ++/* Support for SysV IPC through wired syscalls. All supported architectures ++ either support ipc syscall and/or all the ipc correspondent syscalls. */ ++#define __ASSUME_DIRECT_SYSVIPC_SYSCALLS 1 ++ ++/* Support for p{read,write}v2 was added in 4.6. However Linux default ++ implementation does not assume the __ASSUME_* and instead use a fallback ++ implementation based on p{read,write}v and returning an error for ++ non supported flags. */ ++ ++/* Support for the renameat2 system call was added in kernel 3.15. */ ++#if __LINUX_KERNEL_VERSION >= 0x030F00 ++# define __ASSUME_RENAMEAT2 ++#endif ++ ++/* Support for the execveat syscall was added in 3.19. */ ++#if __LINUX_KERNEL_VERSION >= 0x031300 ++# define __ASSUME_EXECVEAT 1 ++#endif ++ ++#if __LINUX_KERNEL_VERSION >= 0x040400 ++# define __ASSUME_MLOCK2 1 ++#endif ++ ++#if __LINUX_KERNEL_VERSION >= 0x040500 ++# define __ASSUME_COPY_FILE_RANGE 1 ++#endif ++ ++/* Support for statx was added in kernel 4.11. */ ++#if __LINUX_KERNEL_VERSION >= 0x040B00 ++# define __ASSUME_STATX 1 ++#endif ++ ++/* Support for clone call used on fork. The signature varies across the ++ architectures with current 4 different variants: ++ ++ 1. long int clone (unsigned long flags, unsigned long newsp, ++ int *parent_tidptr, unsigned long tls, ++ int *child_tidptr) ++ ++ 2. long int clone (unsigned long newsp, unsigned long clone_flags, ++ int *parent_tidptr, int * child_tidptr, ++ unsigned long tls) ++ ++ 3. long int clone (unsigned long flags, unsigned long newsp, ++ int stack_size, int *parent_tidptr, ++ int *child_tidptr, unsigned long tls) ++ ++ 4. long int clone (unsigned long flags, unsigned long newsp, ++ int *parent_tidptr, int *child_tidptr, ++ unsigned long tls) ++ ++ The fourth variant is intended to be used as the default for newer ports, ++ Also IA64 uses the third variant but with __NR_clone2 instead of ++ __NR_clone. ++ ++ The macros names to define the variant used for the architecture is ++ similar to kernel: ++ ++ - __ASSUME_CLONE_BACKWARDS: for variant 1. ++ - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390). ++ - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze). ++ - __ASSUME_CLONE_DEFAULT: for variant 4. ++ - __ASSUME_CLONE2: for clone2 with variant 3 (ia64). ++ */ ++ ++#define __ASSUME_CLONE_DEFAULT 1 +diff --git a/nptl_2_17/libpthread-2.17-aarch64.map b/nptl_2_17/libpthread-2.17-aarch64.map +new file mode 100644 +index 00000000..d970af06 +--- /dev/null ++++ b/nptl_2_17/libpthread-2.17-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/libpthread-2.17-x86_64.map b/nptl_2_17/libpthread-2.17-x86_64.map +new file mode 100644 +index 00000000..d7f23322 +--- /dev/null ++++ b/nptl_2_17/libpthread-2.17-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/lll_timedlock_wait_2_17.c b/nptl_2_17/lll_timedlock_wait_2_17.c +new file mode 100644 +index 00000000..45ca994e +--- /dev/null ++++ b/nptl_2_17/lll_timedlock_wait_2_17.c +@@ -0,0 +1,59 @@ ++/* Timed low level locking for pthread library. Generic futex-using version. ++ Copyright (C) 2003-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Paul Mackerras , 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 ++ ++ ++int ++__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) ++{ ++ /* Reject invalid timeouts. */ ++ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) ++ return EINVAL; ++ ++ /* Try locking. */ ++ while (atomic_exchange_acq (futex, 2) != 0) ++ { ++ struct timeval tv; ++ ++ /* Get the current time. */ ++ (void) __gettimeofday (&tv, NULL); ++ ++ /* Compute relative timeout. */ ++ struct timespec rt; ++ rt.tv_sec = abstime->tv_sec - tv.tv_sec; ++ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; ++ if (rt.tv_nsec < 0) ++ { ++ rt.tv_nsec += 1000000000; ++ --rt.tv_sec; ++ } ++ ++ if (rt.tv_sec < 0) ++ return ETIMEDOUT; ++ ++ /* If *futex == 2, wait until woken or timeout. */ ++ lll_futex_timed_wait (futex, 2, &rt, private); ++ } ++ ++ return 0; ++} +diff --git a/nptl_2_17/lowlevellock_2_17.c b/nptl_2_17/lowlevellock_2_17.c +new file mode 100644 +index 00000000..9bbcc924 +--- /dev/null ++++ b/nptl_2_17/lowlevellock_2_17.c +@@ -0,0 +1,46 @@ ++/* low level locking for pthread library. Generic futex-using version. ++ Copyright (C) 2003-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Paul Mackerras , 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 ++ ++void ++__lll_lock_wait_private (int *futex) ++{ ++ if (*futex == 2) ++ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */ ++ ++ while (atomic_exchange_acq (futex, 2) != 0) ++ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */ ++} ++ ++ ++/* This function doesn't get included in libc. */ ++void ++__lll_lock_wait (int *futex, int private) ++{ ++ if (*futex == 2) ++ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */ ++ ++ while (atomic_exchange_acq (futex, 2) != 0) ++ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */ ++} +diff --git a/nptl_2_17/pthread-functions_2_17.h b/nptl_2_17/pthread-functions_2_17.h +new file mode 100644 +index 00000000..9e2a79f5 +--- /dev/null ++++ b/nptl_2_17/pthread-functions_2_17.h +@@ -0,0 +1,116 @@ ++/* Copyright (C) 2003-2018 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 ++ . */ ++ ++#ifndef _PTHREAD_FUNCTIONS_H ++#define _PTHREAD_FUNCTIONS_H 1 ++ ++#include ++#include ++#include ++#include ++ ++struct xid_command; ++ ++/* Data type shared with libc. The libc uses it to pass on calls to ++ the thread functions. */ ++struct pthread_functions ++{ ++ int (*ptr_pthread_attr_destroy) (pthread_attr_t *); ++ int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *); ++ int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *); ++ int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); ++ int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); ++ int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); ++ int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); ++ int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, ++ struct sched_param *); ++ int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, ++ const struct sched_param *); ++ int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); ++ int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); ++ int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); ++ int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); ++ int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); ++ int (*ptr_pthread_condattr_init) (pthread_condattr_t *); ++ int (*ptr___pthread_cond_broadcast) (pthread_cond_t *); ++ int (*ptr___pthread_cond_destroy) (pthread_cond_t *); ++ int (*ptr___pthread_cond_init) (pthread_cond_t *, ++ const pthread_condattr_t *); ++ ++ int (*ptr___pthread_cond_signal) (pthread_cond_t *); ++ int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); ++ int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, ++ const struct timespec *); ++ int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *); ++ int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *); ++ int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *, ++ const pthread_condattr_t *); ++ int (*ptr___pthread_cond_signal_2_0) (pthread_cond_2_0_t *); ++ int (*ptr___pthread_cond_wait_2_0) (pthread_cond_2_0_t *, pthread_mutex_t *); ++ int (*ptr___pthread_cond_timedwait_2_0) (pthread_cond_2_0_t *, ++ pthread_mutex_t *, ++ const struct timespec *); ++ int (*ptr_pthread_equal) (pthread_t, pthread_t); ++ void (*ptr___pthread_exit) (void *) __attribute__ ((__noreturn__)); ++ int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); ++ int (*ptr_pthread_setschedparam) (pthread_t, int, ++ const struct sched_param *); ++ int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); ++ int (*ptr_pthread_mutex_init) (pthread_mutex_t *, ++ const pthread_mutexattr_t *); ++ int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); ++ int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); ++ int (*ptr___pthread_setcancelstate) (int, int *); ++ int (*ptr_pthread_setcanceltype) (int, int *); ++ void (*ptr___pthread_cleanup_upto) (__jmp_buf, char *); ++ int (*ptr___pthread_once) (pthread_once_t *, void (*) (void)); ++ int (*ptr___pthread_rwlock_rdlock) (pthread_rwlock_t *); ++ int (*ptr___pthread_rwlock_wrlock) (pthread_rwlock_t *); ++ int (*ptr___pthread_rwlock_unlock) (pthread_rwlock_t *); ++ int (*ptr___pthread_key_create) (pthread_key_t *, void (*) (void *)); ++ void *(*ptr___pthread_getspecific) (pthread_key_t); ++ int (*ptr___pthread_setspecific) (pthread_key_t, const void *); ++ void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer *, ++ void (*) (void *), void *); ++ void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer *, ++ int); ++#define HAVE_PTR_NTHREADS ++ unsigned int *ptr_nthreads; ++ void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *) ++ __attribute ((noreturn)) __cleanup_fct_attribute; ++ void (*ptr__nptl_deallocate_tsd) (void); ++ int (*ptr__nptl_setxid) (struct xid_command *); ++ void (*ptr_set_robust) (struct pthread *); ++}; ++ ++/* Variable in libc.so. */ ++extern struct pthread_functions __libc_pthread_functions attribute_hidden; ++extern int __libc_pthread_functions_init attribute_hidden; ++ ++#ifdef PTR_DEMANGLE ++# define PTHFCT_CALL(fct, params) \ ++ ({ __typeof (__libc_pthread_functions.fct) __p; \ ++ __p = __libc_pthread_functions.fct; \ ++ PTR_DEMANGLE (__p); \ ++ __p params; }) ++#else ++# define PTHFCT_CALL(fct, params) \ ++ __libc_pthread_functions.fct params ++#endif ++ ++#endif /* pthread-functions.h */ +diff --git a/nptl_2_17/pthreadP_2_17.h b/nptl_2_17/pthreadP_2_17.h +new file mode 100644 +index 00000000..ee1488c0 +--- /dev/null ++++ b/nptl_2_17/pthreadP_2_17.h +@@ -0,0 +1,714 @@ ++/* Copyright (C) 2002-2018 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 "kernel-features_2_17.h" ++#include "pthread_2_17.h" ++#include ++#include "internaltypes_2_17.h" ++#include ++#include "descr_2_17.h" ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* 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 ++ ++ ++/* Adaptive mutex definitions. */ ++#ifndef MAX_ADAPTIVE_COUNT ++# define MAX_ADAPTIVE_COUNT 100 ++#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) ++ ++ ++/* 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__)) ++ weak_function ++ ; ++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)); ++} ++ ++ ++/* Set cancellation mode to asynchronous. */ ++#define CANCEL_ASYNC() \ ++ __pthread_enable_asynccancel () ++/* Reset to previous cancellation mode. */ ++#define CANCEL_RESET(oldtype) \ ++ __pthread_disable_asynccancel (oldtype) ++ ++# ifdef LIBC_CANCEL_ASYNC ++# undef LIBC_CANCEL_ASYNC ++# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC () ++# endif ++# ifdef LIBC_CANCEL_RESET ++# undef LIBC_CANCEL_RESET ++# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val) ++# endif ++# define LIBC_CANCEL_HANDLED() \ ++ __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \ ++ __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel") ++ ++ ++/* 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 ++ ++/* Find a thread given its TID. */ ++extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden ++#ifdef SHARED ++; ++#else ++weak_function; ++#define __find_thread_by_id(tid) \ ++ (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL) ++#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_timedjoin_ex (pthread_t, void **, const struct timespec *, ++ bool); ++ ++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) ++hidden_proto (__pthread_timedjoin_ex) ++ ++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); ++ ++/* The two functions are in libc.so and not exported. */ ++extern int __libc_enable_asynccancel (void) attribute_hidden; ++extern void __libc_disable_asynccancel (int oldtype) attribute_hidden; ++ ++ ++/* The two functions are in librt.so and not exported. */ ++extern int __librt_enable_asynccancel (void) attribute_hidden; ++extern void __librt_disable_asynccancel (int oldtype) attribute_hidden; ++ ++/* 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)); } ++ ++# if defined __EXCEPTIONS && !defined __cplusplus ++/* Structure to hold the cleanup handler information. */ ++struct __pthread_cleanup_combined_frame ++{ ++ void (*__cancel_routine) (void *); ++ void *__cancel_arg; ++ int __do_it; ++ struct _pthread_cleanup_buffer __buffer; ++}; ++ ++/* Special cleanup macros which register cleanup both using ++ __pthread_cleanup_{push,pop} and using cleanup attribute. This is needed ++ for pthread_once, so that it supports both throwing exceptions from the ++ pthread_once callback (only cleanup attribute works there) and cancellation ++ of the thread running the callback if the callback or some routines it ++ calls don't have unwind information. */ ++ ++static __always_inline void ++__pthread_cleanup_combined_routine (struct __pthread_cleanup_combined_frame ++ *__frame) ++{ ++ if (__frame->__do_it) ++ { ++ __frame->__cancel_routine (__frame->__cancel_arg); ++ __frame->__do_it = 0; ++ __pthread_cleanup_pop (&__frame->__buffer, 0); ++ } ++} ++ ++static inline void ++__pthread_cleanup_combined_routine_voidptr (void *__arg) ++{ ++ struct __pthread_cleanup_combined_frame *__frame ++ = (struct __pthread_cleanup_combined_frame *) __arg; ++ if (__frame->__do_it) ++ { ++ __frame->__cancel_routine (__frame->__cancel_arg); ++ __frame->__do_it = 0; ++ } ++} ++ ++# define pthread_cleanup_combined_push(routine, arg) \ ++ do { \ ++ void (*__cancel_routine) (void *) = (routine); \ ++ struct __pthread_cleanup_combined_frame __clframe \ ++ __attribute__ ((__cleanup__ (__pthread_cleanup_combined_routine))) \ ++ = { .__cancel_routine = __cancel_routine, .__cancel_arg = (arg), \ ++ .__do_it = 1 }; \ ++ __pthread_cleanup_push (&__clframe.__buffer, \ ++ __pthread_cleanup_combined_routine_voidptr, \ ++ &__clframe); ++ ++# define pthread_cleanup_combined_pop(execute) \ ++ __pthread_cleanup_pop (&__clframe.__buffer, 0); \ ++ __clframe.__do_it = 0; \ ++ if (execute) \ ++ __cancel_routine (__clframe.__cancel_arg); \ ++ } while (0) ++ ++# endif ++ ++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)) ++ ++#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..f2d9c226 +--- /dev/null ++++ b/nptl_2_17/pthread_2_17.h +@@ -0,0 +1,1162 @@ ++/* Copyright (C) 2002-2018 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 "bits/pthreadtypes_2_17.h" ++ ++#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 ++ ++ ++#if __PTHREAD_MUTEX_HAVE_PREV ++# define PTHREAD_MUTEX_INITIALIZER \ ++ { { 0, 0, 0, 0, 0, __PTHREAD_SPINS, { 0, 0 } } } ++# ifdef __USE_GNU ++# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } ++# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __PTHREAD_SPINS, { 0, 0 } } } ++# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } ++ ++# endif ++#else ++# define PTHREAD_MUTEX_INITIALIZER \ ++ { { 0, 0, 0, 0, 0, { __PTHREAD_SPINS } } } ++# ifdef __USE_GNU ++# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { __PTHREAD_SPINS } } } ++# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { __PTHREAD_SPINS } } } ++# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { __PTHREAD_SPINS } } } ++ ++# endif ++#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 ++}; ++ ++/* Define __PTHREAD_RWLOCK_INT_FLAGS_SHARED to 1 if pthread_rwlock_t ++ has the shared field. All 64-bit architectures have the shared field ++ in pthread_rwlock_t. */ ++#ifndef __PTHREAD_RWLOCK_INT_FLAGS_SHARED ++# if __WORDSIZE == 64 ++# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1 ++# endif ++#endif ++ ++/* Read-write lock initializers. */ ++# define PTHREAD_RWLOCK_INITIALIZER \ ++ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } } ++# ifdef __USE_GNU ++# ifdef __PTHREAD_RWLOCK_INT_FLAGS_SHARED ++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, \ ++ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } ++# else ++# if __BYTE_ORDER == __LITTLE_ENDIAN ++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \ ++ 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } } ++# else ++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\ ++ 0 } } ++# endif ++# endif ++# 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); ++#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 ++ ++/* 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 ++ ++/* 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 ++ ++/* 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)); ++ ++/* 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..d9b68f79 +--- /dev/null ++++ b/nptl_2_17/pthread_cond_broadcast_2_17.c +@@ -0,0 +1,98 @@ ++/* 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 "kernel-features_2_17.h" ++#include "pthread_2_17.h" ++#include "pthreadP_2_17.h" ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* We do the following steps from __pthread_cond_signal in one critical ++ section: (1) signal all waiters in G1, (2) close G1 so that it can become ++ the new G2 and make G2 the new G1, and (3) signal all waiters in the new ++ G1. We don't need to do all these steps if there are no waiters in G1 ++ and/or G2. See __pthread_cond_signal for further details. */ ++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..f5bd7ade +--- /dev/null ++++ b/nptl_2_17/pthread_cond_destroy_2_17.c +@@ -0,0 +1,85 @@ ++/* Copyright (C) 2002-2018 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..f4eff6ab +--- /dev/null ++++ b/nptl_2_17/pthread_cond_init_2_17.c +@@ -0,0 +1,50 @@ ++/* Copyright (C) 2002-2018 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..5d79b894 +--- /dev/null ++++ b/nptl_2_17/pthread_cond_signal_2_17.c +@@ -0,0 +1,82 @@ ++/* 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 "kernel-features_2_17.h" ++#include "pthread_2_17.h" ++#include "pthreadP_2_17.h" ++#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..ab497195 +--- /dev/null ++++ b/nptl_2_17/pthread_cond_timedwait_2_17.c +@@ -0,0 +1,266 @@ ++/* 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 "kernel-features_2_17.h" ++#include "bits/thread-shared-types_2_17.h" ++#include ++#include "pthread_2_17.h" ++#include "pthreadP_2_17.h" ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++# undef INTERNAL_VSYSCALL ++# define INTERNAL_VSYSCALL INTERNAL_SYSCALL ++# undef INLINE_VSYSCALL ++# define INLINE_VSYSCALL INLINE_SYSCALL ++ ++/* 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..966ecab1 +--- /dev/null ++++ b/nptl_2_17/pthread_cond_wait_2_17.c +@@ -0,0 +1,234 @@ ++/* 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 "bits/thread-shared-types_2_17.h" ++#include ++#include ++#include "kernel-features_2_17.h" ++#include "pthread_2_17.h" ++#include "pthreadP_2_17.h" ++ ++#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..414a6856 +--- /dev/null ++++ b/nptl_2_17/pthread_condattr_getclock_2_17.c +@@ -0,0 +1,28 @@ ++/* Copyright (C) 2003-2018 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..2b85506f +--- /dev/null ++++ b/nptl_2_17/pthread_condattr_getpshared_2_17.c +@@ -0,0 +1,28 @@ ++/* Copyright (C) 2002-2018 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..427a349c +--- /dev/null ++++ b/nptl_2_17/pthread_condattr_init_2_17.c +@@ -0,0 +1,33 @@ ++/* Copyright (C) 2002-2018 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 ++ ++ ++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..69c64dcb +--- /dev/null ++++ b/nptl_2_17/pthread_condattr_setclock_2_17.c +@@ -0,0 +1,45 @@ ++/* Copyright (C) 2003-2018 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" ++#include ++#include ++#include ++#include ++#include ++ ++ ++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..674ae77b +--- /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..787f37b0 +--- /dev/null ++++ b/nptl_2_17/pthread_mutex_lock_2_17.c +@@ -0,0 +1,635 @@ ++/* Copyright (C) 2002-2018 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 (MAX_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)); ++ INTERNAL_SYSCALL_DECL (__err); ++ int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, ++ __lll_private_flag (FUTEX_LOCK_PI, ++ private), 1, 0); ++ ++ if (INTERNAL_SYSCALL_ERROR_P (e, __err) ++ && (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH ++ || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)) ++ { ++ assert (INTERNAL_SYSCALL_ERRNO (e, __err) != 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 (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust); ++ ++ /* Delay the thread indefinitely. */ ++ while (1) ++ pause (); ++ } ++ ++ 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; ++ ++ INTERNAL_SYSCALL_DECL (__err); ++ INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, ++ __lll_private_flag (FUTEX_UNLOCK_PI, ++ PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), ++ 0, 0); ++ ++ /* 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..cca86029 +--- /dev/null ++++ b/nptl_2_17/pthread_mutex_unlock_2_17.c +@@ -0,0 +1,359 @@ ++/* Copyright (C) 2002-2018 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 ++ ++#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))) ++ { ++ INTERNAL_SYSCALL_DECL (__err); ++ INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock, ++ __lll_private_flag (FUTEX_UNLOCK_PI, 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/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h b/nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h +new file mode 100644 +index 00000000..008aa7e0 +--- /dev/null ++++ b/nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h +@@ -0,0 +1,71 @@ ++/* Copyright (C) 2002-2018 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_ARCH_H ++#define _BITS_PTHREADTYPES_ARCH_H 1 ++ ++#include ++ ++#ifdef __ILP32__ ++# define __SIZEOF_PTHREAD_ATTR_T 32 ++# define __SIZEOF_PTHREAD_MUTEX_T 32 ++# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 ++# define __SIZEOF_PTHREAD_CONDATTR_T 4 ++# define __SIZEOF_PTHREAD_RWLOCK_T 48 ++# define __SIZEOF_PTHREAD_BARRIER_T 20 ++# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 ++#else ++# define __SIZEOF_PTHREAD_ATTR_T 64 ++# define __SIZEOF_PTHREAD_MUTEX_T 48 ++# define __SIZEOF_PTHREAD_MUTEXATTR_T 8 ++# define __SIZEOF_PTHREAD_CONDATTR_T 8 ++# define __SIZEOF_PTHREAD_RWLOCK_T 56 ++# define __SIZEOF_PTHREAD_BARRIER_T 32 ++# define __SIZEOF_PTHREAD_BARRIERATTR_T 8 ++#endif ++#define __SIZEOF_PTHREAD_COND_T 48 ++#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 ++ ++/* Definitions for internal mutex struct. */ ++#define __PTHREAD_COMPAT_PADDING_MID ++#define __PTHREAD_COMPAT_PADDING_END ++#define __PTHREAD_MUTEX_LOCK_ELISION 0 ++#define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 ++#define __PTHREAD_MUTEX_USE_UNION 0 ++ ++#define __LOCK_ALIGNMENT ++#define __ONCE_ALIGNMENT ++ ++struct __pthread_rwlock_arch_t ++{ ++ unsigned int __readers; ++ unsigned int __writers; ++ unsigned int __wrphase_futex; ++ unsigned int __writers_futex; ++ unsigned int __pad3; ++ unsigned int __pad4; ++ int __cur_writer; ++ int __shared; ++ unsigned long int __pad1; ++ unsigned long int __pad2; ++ unsigned int __flags; ++}; ++ ++#define __PTHREAD_RWLOCK_ELISION_EXTRA 0 ++ ++#endif /* bits/pthreadtypes.h */ +diff --git a/nptl_2_17/sysdeps/generic/sysdep_2_17.h b/nptl_2_17/sysdeps/generic/sysdep_2_17.h +new file mode 100644 +index 00000000..934d4da8 +--- /dev/null ++++ b/nptl_2_17/sysdeps/generic/sysdep_2_17.h +@@ -0,0 +1,97 @@ ++/* Generic asm macros used on many machines. ++ Copyright (C) 1991-2018 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 C_LABEL ++ ++/* Define a macro we can use to construct the asm name for a C symbol. */ ++# define C_LABEL(name) name##: ++ ++#endif ++ ++#ifdef __ASSEMBLER__ ++/* Mark the end of function named SYM. This is used on some platforms ++ to generate correct debugging information. */ ++# ifndef END ++# define END(sym) ++# endif ++ ++# ifndef JUMPTARGET ++# define JUMPTARGET(sym) sym ++# endif ++#endif ++ ++/* Makros to generate eh_frame unwind information. */ ++#ifdef __ASSEMBLER__ ++# define cfi_startproc .cfi_startproc ++# define cfi_endproc .cfi_endproc ++# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off ++# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg ++# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off ++# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off ++# define cfi_offset(reg, off) .cfi_offset reg, off ++# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off ++# define cfi_register(r1, r2) .cfi_register r1, r2 ++# define cfi_return_column(reg) .cfi_return_column reg ++# define cfi_restore(reg) .cfi_restore reg ++# define cfi_same_value(reg) .cfi_same_value reg ++# define cfi_undefined(reg) .cfi_undefined reg ++# define cfi_remember_state .cfi_remember_state ++# define cfi_restore_state .cfi_restore_state ++# define cfi_window_save .cfi_window_save ++# define cfi_personality(enc, exp) .cfi_personality enc, exp ++# define cfi_lsda(enc, exp) .cfi_lsda enc, exp ++ ++#else /* ! ASSEMBLER */ ++ ++# define CFI_STRINGIFY(Name) CFI_STRINGIFY2 (Name) ++# define CFI_STRINGIFY2(Name) #Name ++# define CFI_STARTPROC ".cfi_startproc" ++# define CFI_ENDPROC ".cfi_endproc" ++# define CFI_DEF_CFA(reg, off) \ ++ ".cfi_def_cfa " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) ++# define CFI_DEF_CFA_REGISTER(reg) \ ++ ".cfi_def_cfa_register " CFI_STRINGIFY(reg) ++# define CFI_DEF_CFA_OFFSET(off) \ ++ ".cfi_def_cfa_offset " CFI_STRINGIFY(off) ++# define CFI_ADJUST_CFA_OFFSET(off) \ ++ ".cfi_adjust_cfa_offset " CFI_STRINGIFY(off) ++# define CFI_OFFSET(reg, off) \ ++ ".cfi_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) ++# define CFI_REL_OFFSET(reg, off) \ ++ ".cfi_rel_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) ++# define CFI_REGISTER(r1, r2) \ ++ ".cfi_register " CFI_STRINGIFY(r1) "," CFI_STRINGIFY(r2) ++# define CFI_RETURN_COLUMN(reg) \ ++ ".cfi_return_column " CFI_STRINGIFY(reg) ++# define CFI_RESTORE(reg) \ ++ ".cfi_restore " CFI_STRINGIFY(reg) ++# define CFI_UNDEFINED(reg) \ ++ ".cfi_undefined " CFI_STRINGIFY(reg) ++# define CFI_REMEMBER_STATE \ ++ ".cfi_remember_state" ++# define CFI_RESTORE_STATE \ ++ ".cfi_restore_state" ++# define CFI_WINDOW_SAVE \ ++ ".cfi_window_save" ++# define CFI_PERSONALITY(enc, exp) \ ++ ".cfi_personality " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp) ++# define CFI_LSDA(enc, exp) \ ++ ".cfi_lsda " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp) ++#endif ++ ++#include "dwarf2.h" +diff --git a/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h b/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h +new file mode 100644 +index 00000000..353fdfb9 +--- /dev/null ++++ b/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h +@@ -0,0 +1,210 @@ ++/* futex operations for glibc-internal use. Stub version; do not include ++ this file directly. ++ Copyright (C) 2014-2018 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 STUB_FUTEX_INTERNAL_H ++#define STUB_FUTEX_INTERNAL_H ++ ++#include ++#include ++#include ++#include ++ ++/* This file defines futex operations used internally in glibc. A futex ++ consists of the so-called futex word in userspace, which is of type ++ unsigned int and represents an application-specific condition, and kernel ++ state associated with this particular futex word (e.g., wait queues). The ++ futex operations we provide are wrappers for the futex syscalls and add ++ glibc-specific error checking of the syscall return value. We abort on ++ error codes that are caused by bugs in glibc or in the calling application, ++ or when an error code is not known. We return error codes that can arise ++ in correct executions to the caller. Each operation calls out exactly the ++ return values that callers need to handle. ++ ++ The private flag must be either FUTEX_PRIVATE or FUTEX_SHARED. ++ FUTEX_PRIVATE is always supported, and the implementation can internally ++ use FUTEX_SHARED when FUTEX_PRIVATE is requested. FUTEX_SHARED is not ++ necessarily supported (use futex_supports_pshared to detect this). ++ ++ We expect callers to only use these operations if futexes and the ++ specific futex operations being used are supported (e.g., FUTEX_SHARED). ++ ++ Given that waking other threads waiting on a futex involves concurrent ++ accesses to the futex word, you must use atomic operations to access the ++ futex word. ++ ++ Both absolute and relative timeouts can be used. An absolute timeout ++ expires when the given specific point in time on the specified clock ++ passes, or when it already has passed. A relative timeout expires when ++ the given duration of time on the CLOCK_MONOTONIC clock passes. Relative ++ timeouts may be imprecise (see futex_supports_exact_relative_timeouts). ++ ++ Due to POSIX requirements on when synchronization data structures such ++ as mutexes or semaphores can be destroyed and due to the futex design ++ having separate fast/slow paths for wake-ups, we need to consider that ++ futex_wake calls might effectively target a data structure that has been ++ destroyed and reused for another object, or unmapped; thus, some ++ errors or spurious wake-ups can happen in correct executions that would ++ not be possible in a program using just a single futex whose lifetime ++ does not end before the program terminates. For background, see: ++ https://sourceware.org/ml/libc-alpha/2014-04/msg00075.html ++ https://lkml.org/lkml/2014/11/27/472 */ ++ ++/* Defined this way for interoperability with lowlevellock. ++ FUTEX_PRIVATE must be zero because the initializers for pthread_mutex_t, ++ pthread_rwlock_t, and pthread_cond_t initialize the respective field of ++ those structures to zero, and we want FUTEX_PRIVATE to be the default. */ ++#define FUTEX_PRIVATE LLL_PRIVATE ++#define FUTEX_SHARED LLL_SHARED ++#if FUTEX_PRIVATE != 0 ++# error FUTEX_PRIVATE must be equal to 0 ++#endif ++ ++/* Returns EINVAL if PSHARED is neither PTHREAD_PROCESS_PRIVATE nor ++ PTHREAD_PROCESS_SHARED; otherwise, returns 0 if PSHARED is supported, and ++ ENOTSUP if not. */ ++static __always_inline int ++futex_supports_pshared (int pshared); ++ ++/* Returns true if relative timeouts are robust to concurrent changes to the ++ system clock. If this returns false, relative timeouts can still be used ++ but might be effectively longer or shorter than requested. */ ++static __always_inline bool ++futex_supports_exact_relative_timeouts (void); ++ ++/* Atomically wrt other futex operations on the same futex, this blocks iff ++ the value *FUTEX_WORD matches the expected value. This is ++ semantically equivalent to: ++ l = (FUTEX_WORD); ++ wait_flag = (FUTEX_WORD); ++ lock (l); ++ val = atomic_load_relaxed (FUTEX_WORD); ++ if (val != expected) { unlock (l); return EAGAIN; } ++ atomic_store_relaxed (wait_flag, true); ++ unlock (l); ++ // Now block; can time out in futex_time_wait (see below) ++ while (atomic_load_relaxed(wait_flag) && !); ++ ++ Note that no guarantee of a happens-before relation between a woken ++ futex_wait and a futex_wake is documented; however, this does not matter ++ in practice because we have to consider spurious wake-ups (see below), ++ and thus would not be able to reliably reason about which futex_wake woke ++ us. ++ ++ Returns 0 if woken by a futex operation or spuriously. (Note that due to ++ the POSIX requirements mentioned above, we need to conservatively assume ++ that unrelated futex_wake operations could wake this futex; it is easiest ++ to just be prepared for spurious wake-ups.) ++ Returns EAGAIN if the futex word did not match the expected value. ++ Returns EINTR if waiting was interrupted by a signal. ++ ++ Note that some previous code in glibc assumed the underlying futex ++ operation (e.g., syscall) to start with or include the equivalent of a ++ seq_cst fence; this allows one to avoid an explicit seq_cst fence before ++ a futex_wait call when synchronizing similar to Dekker synchronization. ++ However, we make no such guarantee here. */ ++static __always_inline int ++futex_wait (unsigned int *futex_word, unsigned int expected, int private); ++ ++/* Like futex_wait but does not provide any indication why we stopped waiting. ++ Thus, when this function returns, you have to always check FUTEX_WORD to ++ determine whether you need to continue waiting, and you cannot detect ++ whether the waiting was interrupted by a signal. Example use: ++ while (atomic_load_relaxed (&futex_word) == 23) ++ futex_wait_simple (&futex_word, 23, FUTEX_PRIVATE); ++ This is common enough to make providing this wrapper worthwhile. */ ++static __always_inline void ++futex_wait_simple (unsigned int *futex_word, unsigned int expected, ++ int private) ++{ ++ ignore_value (futex_wait (futex_word, expected, private)); ++} ++ ++ ++/* Like futex_wait but is a POSIX cancellation point. */ ++static __always_inline int ++futex_wait_cancelable (unsigned int *futex_word, unsigned int expected, ++ int private); ++ ++/* Like futex_wait, but will eventually time out (i.e., stop being ++ blocked) after the duration of time provided (i.e., RELTIME) has ++ passed. The caller must provide a normalized RELTIME. RELTIME can also ++ equal NULL, in which case this function behaves equivalent to futex_wait. ++ ++ Returns the same values as futex_wait under those same conditions; ++ additionally, returns ETIMEDOUT if the timeout expired. ++ */ ++static __always_inline int ++futex_reltimed_wait (unsigned int* futex_word, unsigned int expected, ++ const struct timespec* reltime, int private); ++ ++/* Like futex_reltimed_wait but is a POSIX cancellation point. */ ++static __always_inline int ++futex_reltimed_wait_cancelable (unsigned int* futex_word, ++ unsigned int expected, ++ const struct timespec* reltime, int private); ++ ++/* Check whether the specified clockid is supported by ++ futex_abstimed_wait and futex_abstimed_wait_cancelable. */ ++static __always_inline int ++futex_abstimed_supported_clockid (clockid_t clockid); ++ ++/* Like futex_reltimed_wait, but the provided timeout (ABSTIME) is an ++ absolute point in time; a call will time out after this point in time. */ ++static __always_inline int ++futex_abstimed_wait (unsigned int* futex_word, unsigned int expected, ++ clockid_t clockid, ++ const struct timespec* abstime, int private); ++ ++/* Like futex_reltimed_wait but is a POSIX cancellation point. */ ++static __always_inline int ++futex_abstimed_wait_cancelable (unsigned int* futex_word, ++ unsigned int expected, ++ clockid_t clockid, ++ const struct timespec* abstime, int private); ++ ++/* Atomically wrt other futex operations on the same futex, this unblocks the ++ specified number of processes, or all processes blocked on this futex if ++ there are fewer than the specified number. Semantically, this is ++ equivalent to: ++ l = (FUTEX_WORD); ++ lock (l); ++ for (res = 0; PROCESSES_TO_WAKE > 0; PROCESSES_TO_WAKE--, res++) { ++ if () break; ++ wf = (FUTEX_WORD); ++ // No happens-before guarantee with woken futex_wait (see above) ++ atomic_store_relaxed (wf, 0); ++ } ++ return res; ++ ++ Note that we need to support futex_wake calls to past futexes whose memory ++ has potentially been reused due to POSIX' requirements on synchronization ++ object destruction (see above); therefore, we must not report or abort ++ on most errors. */ ++static __always_inline void ++futex_wake (unsigned int* futex_word, int processes_to_wake, int private); ++ ++/* Calls __libc_fatal with an error message. Convenience function for ++ concrete implementations of the futex interface. */ ++static __always_inline __attribute__ ((__noreturn__)) void ++futex_fatal_error (void) ++{ ++ __libc_fatal ("The futex facility returned an unexpected error code."); ++} ++ ++#endif /* futex-internal.h */ +diff --git a/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h b/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h +new file mode 100644 +index 00000000..1247949a +--- /dev/null ++++ b/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h +@@ -0,0 +1,208 @@ ++/* Low-level lock implementation. Generic futex-based version. ++ Copyright (C) 2005-2018 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 _LOWLEVELLOCK_H ++#define _LOWLEVELLOCK_H 1 ++ ++#include ++#include ++ ++/* Low-level locks use a combination of atomic operations (to acquire and ++ release lock ownership) and futex operations (to block until the state ++ of a lock changes). A lock can be in one of three states: ++ 0: not acquired, ++ 1: acquired with no waiters; no other threads are blocked or about to block ++ for changes to the lock state, ++ >1: acquired, possibly with waiters; there may be other threads blocked or ++ about to block for changes to the lock state. ++ ++ We expect that the common case is an uncontended lock, so we just need ++ to transition the lock between states 0 and 1; releasing the lock does ++ not need to wake any other blocked threads. If the lock is contended ++ and a thread decides to block using a futex operation, then this thread ++ needs to first change the state to >1; if this state is observed during ++ lock release, the releasing thread will wake one of the potentially ++ blocked threads. ++ ++ Much of this code takes a 'private' parameter. This may be: ++ LLL_PRIVATE: lock only shared within a process ++ LLL_SHARED: lock may be shared across processes. ++ ++ Condition variables contain an optimization for broadcasts that requeues ++ waiting threads on a lock's futex. Therefore, there is a special ++ variant of the locks (whose name contains "cond") that makes sure to ++ always set the lock state to >1 and not just 1. ++ ++ Robust locks set the lock to the id of the owner. This allows detection ++ of the case where the owner exits without releasing the lock. Flags are ++ OR'd with the owner id to record additional information about lock state. ++ Therefore the states of robust locks are: ++ 0: not acquired ++ id: acquired (by user identified by id & FUTEX_TID_MASK) ++ ++ The following flags may be set in the robust lock value: ++ FUTEX_WAITERS - possibly has waiters ++ FUTEX_OWNER_DIED - owning user has exited without releasing the futex. */ ++ ++ ++/* If LOCK is 0 (not acquired), set to 1 (acquired with no waiters) and return ++ 0. Otherwise leave lock unchanged and return non-zero to indicate that the ++ lock was not acquired. */ ++#define lll_trylock(lock) \ ++ __glibc_unlikely (atomic_compare_and_exchange_bool_acq (&(lock), 1, 0)) ++ ++/* If LOCK is 0 (not acquired), set to 2 (acquired, possibly with waiters) and ++ return 0. Otherwise leave lock unchanged and return non-zero to indicate ++ that the lock was not acquired. */ ++#define lll_cond_trylock(lock) \ ++ __glibc_unlikely (atomic_compare_and_exchange_bool_acq (&(lock), 2, 0)) ++ ++extern void __lll_lock_wait_private (int *futex) attribute_hidden; ++extern void __lll_lock_wait (int *futex, int private) attribute_hidden; ++ ++/* This is an expression rather than a statement even though its value is ++ void, so that it can be used in a comma expression or as an expression ++ that's cast to void. */ ++/* The inner conditional compiles to a call to __lll_lock_wait_private if ++ private is known at compile time to be LLL_PRIVATE, and to a call to ++ __lll_lock_wait otherwise. */ ++/* If FUTEX is 0 (not acquired), set to 1 (acquired with no waiters) and ++ return. Otherwise, ensure that it is >1 (acquired, possibly with waiters) ++ and then block until we acquire the lock, at which point FUTEX will still be ++ >1. The lock is always acquired on return. */ ++#define __lll_lock(futex, private) \ ++ ((void) \ ++ ({ \ ++ int *__futex = (futex); \ ++ if (__glibc_unlikely \ ++ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \ ++ { \ ++ if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ ++ __lll_lock_wait_private (__futex); \ ++ else \ ++ __lll_lock_wait (__futex, private); \ ++ } \ ++ })) ++#define lll_lock(futex, private) \ ++ __lll_lock (&(futex), private) ++ ++ ++/* This is an expression rather than a statement even though its value is ++ void, so that it can be used in a comma expression or as an expression ++ that's cast to void. */ ++/* Unconditionally set FUTEX to 2 (acquired, possibly with waiters). If FUTEX ++ was 0 (not acquired) then return. Otherwise, block until the lock is ++ acquired, at which point FUTEX is 2 (acquired, possibly with waiters). The ++ lock is always acquired on return. */ ++#define __lll_cond_lock(futex, private) \ ++ ((void) \ ++ ({ \ ++ int *__futex = (futex); \ ++ if (__glibc_unlikely (atomic_exchange_acq (__futex, 2) != 0)) \ ++ __lll_lock_wait (__futex, private); \ ++ })) ++#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) ++ ++ ++extern int __lll_timedlock_wait (int *futex, const struct timespec *, ++ int private) attribute_hidden; ++ ++ ++/* As __lll_lock, but with a timeout. If the timeout occurs then return ++ ETIMEDOUT. If ABSTIME is invalid, return EINVAL. */ ++#define __lll_timedlock(futex, abstime, private) \ ++ ({ \ ++ int *__futex = (futex); \ ++ int __val = 0; \ ++ \ ++ if (__glibc_unlikely \ ++ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \ ++ __val = __lll_timedlock_wait (__futex, abstime, private); \ ++ __val; \ ++ }) ++#define lll_timedlock(futex, abstime, private) \ ++ __lll_timedlock (&(futex), abstime, private) ++ ++ ++/* This is an expression rather than a statement even though its value is ++ void, so that it can be used in a comma expression or as an expression ++ that's cast to void. */ ++/* Unconditionally set FUTEX to 0 (not acquired), releasing the lock. If FUTEX ++ was >1 (acquired, possibly with waiters), then wake any waiters. The waiter ++ that acquires the lock will set FUTEX to >1. ++ Evaluate PRIVATE before releasing the lock so that we do not violate the ++ mutex destruction requirements. Specifically, we need to ensure that ++ another thread can destroy the mutex (and reuse its memory) once it ++ acquires the lock and when there will be no further lock acquisitions; ++ thus, we must not access the lock after releasing it, or those accesses ++ could be concurrent with mutex destruction or reuse of the memory. */ ++#define __lll_unlock(futex, private) \ ++ ((void) \ ++ ({ \ ++ int *__futex = (futex); \ ++ int __private = (private); \ ++ int __oldval = atomic_exchange_rel (__futex, 0); \ ++ if (__glibc_unlikely (__oldval > 1)) \ ++ lll_futex_wake (__futex, 1, __private); \ ++ })) ++#define lll_unlock(futex, private) \ ++ __lll_unlock (&(futex), private) ++ ++ ++#define lll_islocked(futex) \ ++ ((futex) != LLL_LOCK_INITIALIZER) ++ ++ ++/* Our internal lock implementation is identical to the binary-compatible ++ mutex implementation. */ ++ ++/* Initializers for lock. */ ++#define LLL_LOCK_INITIALIZER (0) ++#define LLL_LOCK_INITIALIZER_LOCKED (1) ++ ++ ++/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex ++ wake-up when the clone terminates. The memory location contains the ++ thread ID while the clone is running and is reset to zero by the kernel ++ afterwards. The kernel up to version 3.16.3 does not use the private futex ++ operations for futex wake-up when the clone terminates. */ ++#define lll_wait_tid(tid) \ ++ do { \ ++ __typeof (tid) __tid; \ ++ /* We need acquire MO here so that we synchronize \ ++ with the kernel's store to 0 when the clone \ ++ terminates. (see above) */ \ ++ while ((__tid = atomic_load_acquire (&(tid))) != 0) \ ++ lll_futex_wait (&(tid), __tid, LLL_SHARED); \ ++ } while (0) ++ ++extern int __lll_timedwait_tid (int *, const struct timespec *) ++ attribute_hidden; ++ ++/* As lll_wait_tid, but with a timeout. If the timeout occurs then return ++ ETIMEDOUT. If ABSTIME is invalid, return EINVAL. */ ++#define lll_timedwait_tid(tid, abstime) \ ++ ({ \ ++ int __res = 0; \ ++ if ((tid) != 0) \ ++ __res = __lll_timedwait_tid (&(tid), (abstime)); \ ++ __res; \ ++ }) ++ ++ ++#endif /* lowlevellock.h */ +diff --git a/nptl_2_17/sysdeps/unix/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysdep_2_17.h +new file mode 100644 +index 00000000..a9905ff9 +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/sysdep_2_17.h +@@ -0,0 +1,148 @@ ++/* Copyright (C) 1991-2018 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 ++#define HAVE_SYSCALLS ++ ++/* Note that using a `PASTE' macro loses. */ ++#define SYSCALL__(name, args) PSEUDO (__##name, name, args) ++#define SYSCALL(name, args) PSEUDO (name, name, args) ++ ++#define __SYSCALL_CONCAT_X(a,b) a##b ++#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X (a, b) ++ ++ ++#define __INTERNAL_SYSCALL0(name, err) \ ++ INTERNAL_SYSCALL (name, err, 0) ++#define __INTERNAL_SYSCALL1(name, err, a1) \ ++ INTERNAL_SYSCALL (name, err, 1, a1) ++#define __INTERNAL_SYSCALL2(name, err, a1, a2) \ ++ INTERNAL_SYSCALL (name, err, 2, a1, a2) ++#define __INTERNAL_SYSCALL3(name, err, a1, a2, a3) \ ++ INTERNAL_SYSCALL (name, err, 3, a1, a2, a3) ++#define __INTERNAL_SYSCALL4(name, err, a1, a2, a3, a4) \ ++ INTERNAL_SYSCALL (name, err, 4, a1, a2, a3, a4) ++#define __INTERNAL_SYSCALL5(name, err, a1, a2, a3, a4, a5) \ ++ INTERNAL_SYSCALL (name, err, 5, a1, a2, a3, a4, a5) ++#define __INTERNAL_SYSCALL6(name, err, a1, a2, a3, a4, a5, a6) \ ++ INTERNAL_SYSCALL (name, err, 6, a1, a2, a3, a4, a5, a6) ++#define __INTERNAL_SYSCALL7(name, err, a1, a2, a3, a4, a5, a6, a7) \ ++ INTERNAL_SYSCALL (name, err, 7, a1, a2, a3, a4, a5, a6, a7) ++ ++#define __INTERNAL_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,o,...) o ++#define __INTERNAL_SYSCALL_NARGS(...) \ ++ __INTERNAL_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,) ++#define __INTERNAL_SYSCALL_DISP(b,...) \ ++ __SYSCALL_CONCAT (b,__INTERNAL_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) ++ ++/* Issue a syscall defined by syscall number plus any other argument required. ++ It is similar to INTERNAL_SYSCALL macro, but without the need to pass the ++ expected argument number as second parameter. */ ++#define INTERNAL_SYSCALL_CALL(...) \ ++ __INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL, __VA_ARGS__) ++ ++#define __INLINE_SYSCALL0(name) \ ++ INLINE_SYSCALL (name, 0) ++#define __INLINE_SYSCALL1(name, a1) \ ++ INLINE_SYSCALL (name, 1, a1) ++#define __INLINE_SYSCALL2(name, a1, a2) \ ++ INLINE_SYSCALL (name, 2, a1, a2) ++#define __INLINE_SYSCALL3(name, a1, a2, a3) \ ++ INLINE_SYSCALL (name, 3, a1, a2, a3) ++#define __INLINE_SYSCALL4(name, a1, a2, a3, a4) \ ++ INLINE_SYSCALL (name, 4, a1, a2, a3, a4) ++#define __INLINE_SYSCALL5(name, a1, a2, a3, a4, a5) \ ++ INLINE_SYSCALL (name, 5, a1, a2, a3, a4, a5) ++#define __INLINE_SYSCALL6(name, a1, a2, a3, a4, a5, a6) \ ++ INLINE_SYSCALL (name, 6, a1, a2, a3, a4, a5, a6) ++#define __INLINE_SYSCALL7(name, a1, a2, a3, a4, a5, a6, a7) \ ++ INLINE_SYSCALL (name, 7, a1, a2, a3, a4, a5, a6, a7) ++ ++#define __INLINE_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n ++#define __INLINE_SYSCALL_NARGS(...) \ ++ __INLINE_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,) ++#define __INLINE_SYSCALL_DISP(b,...) \ ++ __SYSCALL_CONCAT (b,__INLINE_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) ++ ++/* Issue a syscall defined by syscall number plus any other argument ++ required. Any error will be handled using arch defined macros and errno ++ will be set accordingly. ++ It is similar to INLINE_SYSCALL macro, but without the need to pass the ++ expected argument number as second parameter. */ ++#define INLINE_SYSCALL_CALL(...) \ ++ __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__) ++ ++#define SYSCALL_CANCEL(...) \ ++ ({ \ ++ long int sc_ret; \ ++ if (SINGLE_THREAD_P) \ ++ sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \ ++ else \ ++ { \ ++ int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \ ++ sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \ ++ LIBC_CANCEL_RESET (sc_cancel_oldtype); \ ++ } \ ++ sc_ret; \ ++ }) ++ ++/* Issue a syscall defined by syscall number plus any other argument ++ required. Any error will be returned unmodified (including errno). */ ++#define INTERNAL_SYSCALL_CANCEL(...) \ ++ ({ \ ++ long int sc_ret; \ ++ if (SINGLE_THREAD_P) \ ++ sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); \ ++ else \ ++ { \ ++ int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \ ++ sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); \ ++ LIBC_CANCEL_RESET (sc_cancel_oldtype); \ ++ } \ ++ sc_ret; \ ++ }) ++ ++/* Machine-dependent sysdep.h files are expected to define the macro ++ PSEUDO (function_name, syscall_name) to emit assembly code to define the ++ C-callable function FUNCTION_NAME to do system call SYSCALL_NAME. ++ r0 and r1 are the system call outputs. MOVE(x, y) should be defined as ++ an instruction such that "MOVE(r1, r0)" works. ret should be defined ++ as the return instruction. */ ++ ++#ifndef SYS_ify ++#define SYS_ify(syscall_name) SYS_##syscall_name ++#endif ++ ++/* Terminate a system call named SYM. This is used on some platforms ++ to generate correct debugging information. */ ++#ifndef PSEUDO_END ++#define PSEUDO_END(sym) ++#endif ++#ifndef PSEUDO_END_NOERRNO ++#define PSEUDO_END_NOERRNO(sym) PSEUDO_END(sym) ++#endif ++#ifndef PSEUDO_END_ERRVAL ++#define PSEUDO_END_ERRVAL(sym) PSEUDO_END(sym) ++#endif ++ ++/* Wrappers around system calls should normally inline the system call code. ++ But sometimes it is not possible or implemented and we use this code. */ ++#ifndef INLINE_SYSCALL ++#define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args) ++#endif +diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h +new file mode 100644 +index 00000000..76f41900 +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h +@@ -0,0 +1,301 @@ ++/* Copyright (C) 2005-2018 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 _LINUX_AARCH64_SYSDEP_H ++#define _LINUX_AARCH64_SYSDEP_H 1 ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */ ++#include ++ ++#include ++ ++/* In order to get __set_errno() definition in INLINE_SYSCALL. */ ++#ifndef __ASSEMBLER__ ++#include ++#endif ++ ++/* For Linux we can use the system call table in the header file ++ /usr/include/asm/unistd.h ++ of the kernel. But these symbols do not follow the SYS_* syntax ++ so we have to redefine the `SYS_ify' macro here. */ ++#undef SYS_ify ++#define SYS_ify(syscall_name) (__NR_##syscall_name) ++ ++#ifdef __ASSEMBLER__ ++ ++/* Linux uses a negative return value to indicate syscall errors, ++ unlike most Unices, which use the condition codes' carry flag. ++ ++ Since version 2.1 the return value of a system call might be ++ negative even if the call succeeded. E.g., the `lseek' system call ++ might return a large offset. Therefore we must not anymore test ++ for < 0, but test for a real error by making sure the value in R0 ++ is a real error number. Linus said he will make sure the no syscall ++ returns a value in -1 .. -4095 as a valid result so we can safely ++ test with -4095. */ ++ ++# undef PSEUDO ++# define PSEUDO(name, syscall_name, args) \ ++ .text; \ ++ ENTRY (name); \ ++ DO_CALL (syscall_name, args); \ ++ cmn x0, #4095; \ ++ b.cs .Lsyscall_error; ++ ++# undef PSEUDO_END ++# define PSEUDO_END(name) \ ++ SYSCALL_ERROR_HANDLER \ ++ END (name) ++ ++# undef PSEUDO_NOERRNO ++# define PSEUDO_NOERRNO(name, syscall_name, args) \ ++ .text; \ ++ ENTRY (name); \ ++ DO_CALL (syscall_name, args); ++ ++# undef PSEUDO_END_NOERRNO ++# define PSEUDO_END_NOERRNO(name) \ ++ END (name) ++ ++# define ret_NOERRNO ret ++ ++/* The function has to return the error code. */ ++# undef PSEUDO_ERRVAL ++# define PSEUDO_ERRVAL(name, syscall_name, args) \ ++ .text; \ ++ ENTRY (name) \ ++ DO_CALL (syscall_name, args); \ ++ neg x0, x0 ++ ++# undef PSEUDO_END_ERRVAL ++# define PSEUDO_END_ERRVAL(name) \ ++ END (name) ++ ++# define ret_ERRVAL ret ++ ++# if !IS_IN (libc) ++# define SYSCALL_ERROR .Lsyscall_error ++# if RTLD_PRIVATE_ERRNO ++# define SYSCALL_ERROR_HANDLER \ ++.Lsyscall_error: \ ++ adrp x1, C_SYMBOL_NAME(rtld_errno); \ ++ neg w0, w0; \ ++ str w0, [x1, :lo12:C_SYMBOL_NAME(rtld_errno)]; \ ++ mov x0, -1; \ ++ RET; ++# else ++ ++# define SYSCALL_ERROR_HANDLER \ ++.Lsyscall_error: \ ++ adrp x1, :gottprel:errno; \ ++ neg w2, w0; \ ++ ldr PTR_REG(1), [x1, :gottprel_lo12:errno]; \ ++ mrs x3, tpidr_el0; \ ++ mov x0, -1; \ ++ str w2, [x1, x3]; \ ++ RET; ++# endif ++# else ++# define SYSCALL_ERROR __syscall_error ++# define SYSCALL_ERROR_HANDLER \ ++.Lsyscall_error: \ ++ b __syscall_error; ++# endif ++ ++/* Linux takes system call args in registers: ++ syscall number x8 ++ arg 1 x0 ++ arg 2 x1 ++ arg 3 x2 ++ arg 4 x3 ++ arg 5 x4 ++ arg 6 x5 ++ arg 7 x6 ++ ++ The compiler is going to form a call by coming here, through PSEUDO, with ++ arguments ++ syscall number in the DO_CALL macro ++ arg 1 x0 ++ arg 2 x1 ++ arg 3 x2 ++ arg 4 x3 ++ arg 5 x4 ++ arg 6 x5 ++ arg 7 x6 ++ ++*/ ++ ++# undef DO_CALL ++# define DO_CALL(syscall_name, args) \ ++ mov x8, SYS_ify (syscall_name); \ ++ svc 0 ++ ++#else /* not __ASSEMBLER__ */ ++ ++ ++/* List of system calls which are supported as vsyscalls. */ ++# define HAVE_CLOCK_GETRES_VSYSCALL 1 ++# define HAVE_CLOCK_GETTIME_VSYSCALL 1 ++# define HAVE_GETTIMEOFDAY_VSYSCALL 1 ++ ++/* Previously AArch64 used the generic version without the libc_hidden_def ++ which lead in a non existent __send symbol in libc.so. */ ++# undef HAVE_INTERNAL_SEND_SYMBOL ++ ++# define SINGLE_THREAD_BY_GLOBAL 1 ++ ++/* Define a macro which expands into the inline wrapper code for a system ++ call. */ ++# undef INLINE_SYSCALL ++# define INLINE_SYSCALL(name, nr, args...) \ ++ ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); \ ++ if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))\ ++ { \ ++ __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \ ++ _sys_result = (unsigned long) -1; \ ++ } \ ++ (long) _sys_result; }) ++ ++# undef INTERNAL_SYSCALL_DECL ++# define INTERNAL_SYSCALL_DECL(err) do { } while (0) ++ ++# undef INTERNAL_SYSCALL_RAW ++# define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ ++ ({ long _sys_result; \ ++ { \ ++ LOAD_ARGS_##nr (args) \ ++ register long _x8 asm ("x8") = (name); \ ++ asm volatile ("svc 0 // syscall " # name \ ++ : "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr : "memory"); \ ++ _sys_result = _x0; \ ++ } \ ++ _sys_result; }) ++ ++# undef INTERNAL_SYSCALL ++# define INTERNAL_SYSCALL(name, err, nr, args...) \ ++ INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args) ++ ++# undef INTERNAL_SYSCALL_AARCH64 ++# define INTERNAL_SYSCALL_AARCH64(name, err, nr, args...) \ ++ INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args) ++ ++# undef INTERNAL_SYSCALL_ERROR_P ++# define INTERNAL_SYSCALL_ERROR_P(val, err) \ ++ ((unsigned long) (val) >= (unsigned long) -4095) ++ ++# undef INTERNAL_SYSCALL_ERRNO ++# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) ++ ++# define LOAD_ARGS_0() \ ++ register long _x0 asm ("x0"); ++# define LOAD_ARGS_1(x0) \ ++ long _x0tmp = (long) (x0); \ ++ LOAD_ARGS_0 () \ ++ _x0 = _x0tmp; ++# define LOAD_ARGS_2(x0, x1) \ ++ long _x1tmp = (long) (x1); \ ++ LOAD_ARGS_1 (x0) \ ++ register long _x1 asm ("x1") = _x1tmp; ++# define LOAD_ARGS_3(x0, x1, x2) \ ++ long _x2tmp = (long) (x2); \ ++ LOAD_ARGS_2 (x0, x1) \ ++ register long _x2 asm ("x2") = _x2tmp; ++# define LOAD_ARGS_4(x0, x1, x2, x3) \ ++ long _x3tmp = (long) (x3); \ ++ LOAD_ARGS_3 (x0, x1, x2) \ ++ register long _x3 asm ("x3") = _x3tmp; ++# define LOAD_ARGS_5(x0, x1, x2, x3, x4) \ ++ long _x4tmp = (long) (x4); \ ++ LOAD_ARGS_4 (x0, x1, x2, x3) \ ++ register long _x4 asm ("x4") = _x4tmp; ++# define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5) \ ++ long _x5tmp = (long) (x5); \ ++ LOAD_ARGS_5 (x0, x1, x2, x3, x4) \ ++ register long _x5 asm ("x5") = _x5tmp; ++# define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\ ++ long _x6tmp = (long) (x6); \ ++ LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5) \ ++ register long _x6 asm ("x6") = _x6tmp; ++ ++# define ASM_ARGS_0 ++# define ASM_ARGS_1 , "r" (_x0) ++# define ASM_ARGS_2 ASM_ARGS_1, "r" (_x1) ++# define ASM_ARGS_3 ASM_ARGS_2, "r" (_x2) ++# define ASM_ARGS_4 ASM_ARGS_3, "r" (_x3) ++# define ASM_ARGS_5 ASM_ARGS_4, "r" (_x4) ++# define ASM_ARGS_6 ASM_ARGS_5, "r" (_x5) ++# define ASM_ARGS_7 ASM_ARGS_6, "r" (_x6) ++ ++# undef INTERNAL_SYSCALL_NCS ++# define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ ++ INTERNAL_SYSCALL_RAW (number, err, nr, args) ++ ++#endif /* __ASSEMBLER__ */ ++ ++/* Pointer mangling is supported for AArch64. */ ++#if (IS_IN (rtld) || \ ++ (!defined SHARED && (IS_IN (libc) \ ++ || IS_IN (libpthread)))) ++# ifdef __ASSEMBLER__ ++/* Note, dst, src, guard, and tmp are all register numbers rather than ++ register names so they will work with both ILP32 and LP64. */ ++# define PTR_MANGLE(dst, src, guard, tmp) \ ++ LDST_PCREL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); \ ++ PTR_MANGLE2 (dst, src, guard) ++/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ ++# define PTR_MANGLE2(dst, src, guard)\ ++ eor x##dst, x##src, x##guard ++# define PTR_DEMANGLE(dst, src, guard, tmp)\ ++ PTR_MANGLE (dst, src, guard, tmp) ++# define PTR_DEMANGLE2(dst, src, guard)\ ++ PTR_MANGLE2 (dst, src, guard) ++# else ++extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; ++# define PTR_MANGLE(var) \ ++ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local) ++# define PTR_DEMANGLE(var) PTR_MANGLE (var) ++# endif ++#else ++# ifdef __ASSEMBLER__ ++/* Note, dst, src, guard, and tmp are all register numbers rather than ++ register names so they will work with both ILP32 and LP64. */ ++# define PTR_MANGLE(dst, src, guard, tmp) \ ++ LDST_GLOBAL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard)); \ ++ PTR_MANGLE2 (dst, src, guard) ++/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ ++# define PTR_MANGLE2(dst, src, guard)\ ++ eor x##dst, x##src, x##guard ++# define PTR_DEMANGLE(dst, src, guard, tmp)\ ++ PTR_MANGLE (dst, src, guard, tmp) ++# define PTR_DEMANGLE2(dst, src, guard)\ ++ PTR_MANGLE2 (dst, src, guard) ++# else ++extern uintptr_t __pointer_chk_guard attribute_relro; ++# define PTR_MANGLE(var) \ ++ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard) ++# define PTR_DEMANGLE(var) PTR_MANGLE (var) ++# endif ++#endif ++ ++#endif /* linux/aarch64/sysdep.h */ +diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h +new file mode 100644 +index 00000000..1898464d +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h +@@ -0,0 +1,35 @@ ++/* Copyright (C) 2011-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Chris Metcalf , 2011. ++ ++ 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 ++ ++/* Provide the common name to allow more code reuse. */ ++#ifdef __NR_llseek ++# define __NR__llseek __NR_llseek ++#endif ++ ++#if __WORDSIZE == 64 ++/* By defining the older names, glibc will build syscall wrappers for ++ both pread and pread64; sysdeps/unix/sysv/linux/wordsize-64/pread64.c ++ will suppress generating any separate code for pread64.c. */ ++#define __NR_pread __NR_pread64 ++#define __NR_pwrite __NR_pwrite64 ++#endif +diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h +new file mode 100644 +index 00000000..8f2b45c3 +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h +@@ -0,0 +1,91 @@ ++/* Special use of signals internally. Linux version. ++ Copyright (C) 2014-2018 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 __INTERNAL_SIGNALS_H ++# define __INTERNAL_SIGNALS_H ++ ++#include ++#include ++#include ++#include ++ ++/* The signal used for asynchronous cancelation. */ ++#define SIGCANCEL __SIGRTMIN ++ ++ ++/* Signal needed for the kernel-supported POSIX timer implementation. ++ We can reuse the cancellation signal since we can distinguish ++ cancellation from timer expirations. */ ++#define SIGTIMER SIGCANCEL ++ ++ ++/* Signal used to implement the setuid et.al. functions. */ ++#define SIGSETXID (__SIGRTMIN + 1) ++ ++ ++/* Return is sig is used internally. */ ++static inline bool ++__is_internal_signal (int sig) ++{ ++ return (sig == SIGCANCEL) || (sig == SIGSETXID); ++} ++ ++/* Remove internal glibc signal from the mask. */ ++static inline void ++__clear_internal_signals (sigset_t *set) ++{ ++ __sigdelset (set, SIGCANCEL); ++ __sigdelset (set, SIGSETXID); ++} ++ ++#define SIGALL_SET \ ++ ((__sigset_t) { .__val = {[0 ... _SIGSET_NWORDS-1 ] = -1 } }) ++ ++/* Block all signals, including internal glibc ones. */ ++static inline int ++__libc_signal_block_all (sigset_t *set) ++{ ++ INTERNAL_SYSCALL_DECL (err); ++ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &SIGALL_SET, ++ set, _NSIG / 8); ++} ++ ++/* Block all application signals (excluding internal glibc ones). */ ++static inline int ++__libc_signal_block_app (sigset_t *set) ++{ ++ sigset_t allset = SIGALL_SET; ++ __clear_internal_signals (&allset); ++ INTERNAL_SYSCALL_DECL (err); ++ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &allset, set, ++ _NSIG / 8); ++} ++ ++/* Restore current process signal mask. */ ++static inline int ++__libc_signal_restore_set (const sigset_t *set) ++{ ++ INTERNAL_SYSCALL_DECL (err); ++ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, set, NULL, ++ _NSIG / 8); ++} ++ ++/* Used to communicate with signal handler. */ ++extern struct xid_command *__xidcmd attribute_hidden; ++ ++#endif +diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h +new file mode 100644 +index 00000000..399de2e5 +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h +@@ -0,0 +1,150 @@ ++/* Low-level locking access to futex facilities. Linux version. ++ Copyright (C) 2005-2018 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 _LOWLEVELLOCK_FUTEX_H ++#define _LOWLEVELLOCK_FUTEX_H 1 ++ ++#ifndef __ASSEMBLER__ ++#include ++#include ++#include ++#endif ++ ++#define FUTEX_WAIT 0 ++#define FUTEX_WAKE 1 ++#define FUTEX_REQUEUE 3 ++#define FUTEX_CMP_REQUEUE 4 ++#define FUTEX_WAKE_OP 5 ++#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) ++#define FUTEX_LOCK_PI 6 ++#define FUTEX_UNLOCK_PI 7 ++#define FUTEX_TRYLOCK_PI 8 ++#define FUTEX_WAIT_BITSET 9 ++#define FUTEX_WAKE_BITSET 10 ++#define FUTEX_WAIT_REQUEUE_PI 11 ++#define FUTEX_CMP_REQUEUE_PI 12 ++#define FUTEX_PRIVATE_FLAG 128 ++#define FUTEX_CLOCK_REALTIME 256 ++ ++#define FUTEX_BITSET_MATCH_ANY 0xffffffff ++ ++/* Values for 'private' parameter of locking macros. Yes, the ++ definition seems to be backwards. But it is not. The bit will be ++ reversed before passing to the system call. */ ++#define LLL_PRIVATE 0 ++#define LLL_SHARED FUTEX_PRIVATE_FLAG ++ ++#ifndef __ASSEMBLER__ ++ ++#if IS_IN (libc) || IS_IN (rtld) ++/* In libc.so or ld.so all futexes are private. */ ++# define __lll_private_flag(fl, private) \ ++ ({ \ ++ /* Prevent warnings in callers of this macro. */ \ ++ int __lll_private_flag_priv __attribute__ ((unused)); \ ++ __lll_private_flag_priv = (private); \ ++ ((fl) | FUTEX_PRIVATE_FLAG); \ ++ }) ++#else ++# define __lll_private_flag(fl, private) \ ++ (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) ++#endif ++ ++#define lll_futex_syscall(nargs, futexp, op, ...) \ ++ ({ \ ++ INTERNAL_SYSCALL_DECL (__err); \ ++ long int __ret = INTERNAL_SYSCALL (futex, __err, nargs, futexp, op, \ ++ __VA_ARGS__); \ ++ (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__ret, __err)) \ ++ ? -INTERNAL_SYSCALL_ERRNO (__ret, __err) : 0); \ ++ }) ++ ++#define lll_futex_wait(futexp, val, private) \ ++ lll_futex_timed_wait (futexp, val, NULL, private) ++ ++#define lll_futex_timed_wait(futexp, val, timeout, private) \ ++ lll_futex_syscall (4, futexp, \ ++ __lll_private_flag (FUTEX_WAIT, private), \ ++ val, timeout) ++ ++/* Verify whether the supplied clockid is supported by ++ lll_futex_clock_wait_bitset. */ ++#define lll_futex_supported_clockid(clockid) \ ++ ((clockid) == CLOCK_REALTIME || (clockid) == CLOCK_MONOTONIC) ++ ++/* The kernel currently only supports CLOCK_MONOTONIC or ++ CLOCK_REALTIME timeouts for FUTEX_WAIT_BITSET. We could attempt to ++ convert others here but currently do not. */ ++#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \ ++ ({ \ ++ long int __ret; \ ++ if (lll_futex_supported_clockid (clockid)) \ ++ { \ ++ const unsigned int clockbit = \ ++ (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0; \ ++ const int op = \ ++ __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private); \ ++ \ ++ __ret = lll_futex_syscall (6, futexp, op, val, \ ++ timeout, NULL /* Unused. */, \ ++ FUTEX_BITSET_MATCH_ANY); \ ++ } \ ++ else \ ++ __ret = -EINVAL; \ ++ __ret; \ ++ }) ++ ++#define lll_futex_wake(futexp, nr, private) \ ++ lll_futex_syscall (4, futexp, \ ++ __lll_private_flag (FUTEX_WAKE, private), nr, 0) ++ ++/* Returns non-zero if error happened, zero if success. */ ++#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ ++ lll_futex_syscall (6, futexp, \ ++ __lll_private_flag (FUTEX_CMP_REQUEUE, private), \ ++ nr_wake, nr_move, mutex, val) ++ ++/* Returns non-zero if error happened, zero if success. */ ++#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ ++ lll_futex_syscall (6, futexp, \ ++ __lll_private_flag (FUTEX_WAKE_OP, private), \ ++ nr_wake, nr_wake2, futexp2, \ ++ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE) ++ ++/* Priority Inheritance support. */ ++#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \ ++ lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private) ++ ++#define lll_futex_timed_wait_requeue_pi(futexp, val, timeout, clockbit, \ ++ mutex, private) \ ++ lll_futex_syscall (5, futexp, \ ++ __lll_private_flag (FUTEX_WAIT_REQUEUE_PI \ ++ | (clockbit), private), \ ++ val, timeout, mutex) ++ ++ ++#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, \ ++ val, private) \ ++ lll_futex_syscall (6, futexp, \ ++ __lll_private_flag (FUTEX_CMP_REQUEUE_PI, \ ++ private), \ ++ nr_wake, nr_move, mutex, val) ++ ++#endif /* !__ASSEMBLER__ */ ++ ++#endif /* lowlevellock-futex.h */ +diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h +new file mode 100644 +index 00000000..602307db +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h +@@ -0,0 +1,93 @@ ++/* Uncancelable versions of cancelable interfaces. Linux/NPTL version. ++ Copyright (C) 2003-2018 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 ++ . */ ++ ++#ifndef NOT_CANCEL_H ++# define NOT_CANCEL_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Non cancellable open syscall. */ ++__typeof (open) __open_nocancel; ++ ++/* Non cancellable open syscall (LFS version). */ ++__typeof (open64) __open64_nocancel; ++ ++/* Non cancellable openat syscall. */ ++__typeof (openat) __openat_nocancel; ++ ++/* Non cacellable openat syscall (LFS version). */ ++__typeof (openat64) __openat64_nocancel; ++ ++/* Non cancellable read syscall. */ ++__typeof (__read) __read_nocancel; ++ ++/* Uncancelable write. */ ++__typeof (__write) __write_nocancel; ++ ++/* Uncancelable close. */ ++__typeof (__close) __close_nocancel; ++ ++/* Non cancellable close syscall that does not also set errno in case of ++ failure. */ ++static inline void ++__close_nocancel_nostatus (int fd) ++{ ++ __close_nocancel (fd); ++} ++ ++/* Non cancellable writev syscall that does not also set errno in case of ++ failure. */ ++static inline void ++__writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt) ++{ ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL_CALL (writev, err, fd, iov, iovcnt); ++} ++ ++/* Uncancelable waitpid. */ ++__typeof (waitpid) __waitpid_nocancel; ++ ++/* Uncancelable pause. */ ++__typeof (pause) __pause_nocancel; ++ ++/* Uncancelable nanosleep. */ ++__typeof (__nanosleep) __nanosleep_nocancel; ++ ++/* Uncancelable fcntl. */ ++__typeof (__fcntl) __fcntl64_nocancel; ++ ++hidden_proto (__open_nocancel) ++hidden_proto (__open64_nocancel) ++hidden_proto (__openat_nocancel) ++hidden_proto (__openat64_nocancel) ++hidden_proto (__read_nocancel) ++hidden_proto (__write_nocancel) ++hidden_proto (__close_nocancel) ++hidden_proto (__waitpid_nocancel) ++hidden_proto (__pause_nocancel) ++hidden_proto (__nanosleep_nocancel) ++hidden_proto (__fcntl64_nocancel) ++ ++#endif /* NOT_CANCEL_H */ +diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h +new file mode 100644 +index 00000000..4fd0a9ba +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h +@@ -0,0 +1,68 @@ ++/* Copyright (C) 2015-2018 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 ++ ++/* Set error number and return -1. A target may choose to return the ++ internal function, __syscall_error, which sets errno and returns -1. ++ We use -1l, instead of -1, so that it can be casted to (void *). */ ++#define INLINE_SYSCALL_ERROR_RETURN_VALUE(err) \ ++ ({ \ ++ __set_errno (err); \ ++ -1l; \ ++ }) ++ ++/* Provide a dummy argument that can be used to force register ++ alignment for register pairs if required by the syscall ABI. */ ++#ifdef __ASSUME_ALIGNED_REGISTER_PAIRS ++#define __ALIGNMENT_ARG 0, ++#define __ALIGNMENT_COUNT(a,b) b ++#else ++#define __ALIGNMENT_ARG ++#define __ALIGNMENT_COUNT(a,b) a ++#endif ++ ++/* Provide a common macro to pass 64-bit value on syscalls. */ ++#if __WORDSIZE == 64 || defined __ASSUME_WORDSIZE64_ILP32 ++# define SYSCALL_LL(val) (val) ++# define SYSCALL_LL64(val) (val) ++#else ++#define SYSCALL_LL(val) \ ++ __LONG_LONG_PAIR ((val) >> 31, (val)) ++#define SYSCALL_LL64(val) \ ++ __LONG_LONG_PAIR ((long) ((val) >> 32), (long) ((val) & 0xffffffff)) ++#endif ++ ++/* Provide a common macro to pass 64-bit value on pread and pwrite ++ syscalls. */ ++#ifdef __ASSUME_PRW_DUMMY_ARG ++# define SYSCALL_LL_PRW(val) 0, SYSCALL_LL (val) ++# define SYSCALL_LL64_PRW(val) 0, SYSCALL_LL64 (val) ++#else ++# define SYSCALL_LL_PRW(val) __ALIGNMENT_ARG SYSCALL_LL (val) ++# define SYSCALL_LL64_PRW(val) __ALIGNMENT_ARG SYSCALL_LL64 (val) ++#endif ++ ++/* Provide a macro to pass the off{64}_t argument on p{readv,writev}{64}. */ ++#define LO_HI_LONG(val) \ ++ (long) (val), \ ++ (long) (((uint64_t) (val)) >> 32) ++ ++/* Exports the __send symbol on send.c linux implementation (some ABI have ++ it missing due the usage of a old generic version without it). */ ++#define HAVE_INTERNAL_SEND_SYMBOL 1 +diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h +new file mode 100644 +index 00000000..8cf61c21 +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h +@@ -0,0 +1,432 @@ ++/* Copyright (C) 2001-2018 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 _LINUX_X86_64_SYSDEP_H ++#define _LINUX_X86_64_SYSDEP_H 1 ++ ++/* There is some commonality. */ ++#include ++#include ++#include "descr_2_17.h" ++#include ++ ++/* Defines RTLD_PRIVATE_ERRNO. */ ++#include ++ ++/* For Linux we can use the system call table in the header file ++ /usr/include/asm/unistd.h ++ of the kernel. But these symbols do not follow the SYS_* syntax ++ so we have to redefine the `SYS_ify' macro here. */ ++#undef SYS_ify ++#define SYS_ify(syscall_name) __NR_##syscall_name ++ ++/* This is a kludge to make syscalls.list find these under the names ++ pread and pwrite, since some kernel headers define those names ++ and some define the *64 names for the same system calls. */ ++#if !defined __NR_pread && defined __NR_pread64 ++# define __NR_pread __NR_pread64 ++#endif ++#if !defined __NR_pwrite && defined __NR_pwrite64 ++# define __NR_pwrite __NR_pwrite64 ++#endif ++ ++/* This is to help the old kernel headers where __NR_semtimedop is not ++ available. */ ++#ifndef __NR_semtimedop ++# define __NR_semtimedop 220 ++#endif ++ ++ ++#ifdef __ASSEMBLER__ ++ ++/* Linux uses a negative return value to indicate syscall errors, ++ unlike most Unices, which use the condition codes' carry flag. ++ ++ Since version 2.1 the return value of a system call might be ++ negative even if the call succeeded. E.g., the `lseek' system call ++ might return a large offset. Therefore we must not anymore test ++ for < 0, but test for a real error by making sure the value in %eax ++ is a real error number. Linus said he will make sure the no syscall ++ returns a value in -1 .. -4095 as a valid result so we can savely ++ test with -4095. */ ++ ++/* We don't want the label for the error handle to be global when we define ++ it here. */ ++# ifdef PIC ++# define SYSCALL_ERROR_LABEL 0f ++# else ++# define SYSCALL_ERROR_LABEL syscall_error ++# endif ++ ++# undef PSEUDO ++# define PSEUDO(name, syscall_name, args) \ ++ .text; \ ++ ENTRY (name) \ ++ DO_CALL (syscall_name, args); \ ++ cmpq $-4095, %rax; \ ++ jae SYSCALL_ERROR_LABEL ++ ++# undef PSEUDO_END ++# define PSEUDO_END(name) \ ++ SYSCALL_ERROR_HANDLER \ ++ END (name) ++ ++# undef PSEUDO_NOERRNO ++# define PSEUDO_NOERRNO(name, syscall_name, args) \ ++ .text; \ ++ ENTRY (name) \ ++ DO_CALL (syscall_name, args) ++ ++# undef PSEUDO_END_NOERRNO ++# define PSEUDO_END_NOERRNO(name) \ ++ END (name) ++ ++# define ret_NOERRNO ret ++ ++# undef PSEUDO_ERRVAL ++# define PSEUDO_ERRVAL(name, syscall_name, args) \ ++ .text; \ ++ ENTRY (name) \ ++ DO_CALL (syscall_name, args); \ ++ negq %rax ++ ++# undef PSEUDO_END_ERRVAL ++# define PSEUDO_END_ERRVAL(name) \ ++ END (name) ++ ++# define ret_ERRVAL ret ++ ++# if defined PIC && RTLD_PRIVATE_ERRNO ++# define SYSCALL_SET_ERRNO \ ++ lea rtld_errno(%rip), %RCX_LP; \ ++ neg %eax; \ ++ movl %eax, (%rcx) ++# else ++# if IS_IN (libc) ++# define SYSCALL_ERROR_ERRNO __libc_errno ++# else ++# define SYSCALL_ERROR_ERRNO errno ++# endif ++# define SYSCALL_SET_ERRNO \ ++ movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\ ++ neg %eax; \ ++ movl %eax, %fs:(%rcx); ++# endif ++ ++# ifndef PIC ++# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ ++# else ++# define SYSCALL_ERROR_HANDLER \ ++0: \ ++ SYSCALL_SET_ERRNO; \ ++ or $-1, %RAX_LP; \ ++ ret; ++# endif /* PIC */ ++ ++/* The Linux/x86-64 kernel expects the system call parameters in ++ registers according to the following table: ++ ++ syscall number rax ++ arg 1 rdi ++ arg 2 rsi ++ arg 3 rdx ++ arg 4 r10 ++ arg 5 r8 ++ arg 6 r9 ++ ++ The Linux kernel uses and destroys internally these registers: ++ return address from ++ syscall rcx ++ eflags from syscall r11 ++ ++ Normal function call, including calls to the system call stub ++ functions in the libc, get the first six parameters passed in ++ registers and the seventh parameter and later on the stack. The ++ register use is as follows: ++ ++ system call number in the DO_CALL macro ++ arg 1 rdi ++ arg 2 rsi ++ arg 3 rdx ++ arg 4 rcx ++ arg 5 r8 ++ arg 6 r9 ++ ++ We have to take care that the stack is aligned to 16 bytes. When ++ called the stack is not aligned since the return address has just ++ been pushed. ++ ++ ++ Syscalls of more than 6 arguments are not supported. */ ++ ++# undef DO_CALL ++# define DO_CALL(syscall_name, args) \ ++ DOARGS_##args \ ++ movl $SYS_ify (syscall_name), %eax; \ ++ syscall; ++ ++# define DOARGS_0 /* nothing */ ++# define DOARGS_1 /* nothing */ ++# define DOARGS_2 /* nothing */ ++# define DOARGS_3 /* nothing */ ++# define DOARGS_4 movq %rcx, %r10; ++# define DOARGS_5 DOARGS_4 ++# define DOARGS_6 DOARGS_5 ++ ++#else /* !__ASSEMBLER__ */ ++/* Define a macro which expands inline into the wrapper code for a system ++ call. */ ++# undef INLINE_SYSCALL ++# define INLINE_SYSCALL(name, nr, args...) \ ++ ({ \ ++ unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args); \ ++ if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \ ++ { \ ++ __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ ++ resultvar = (unsigned long int) -1; \ ++ } \ ++ (long int) resultvar; }) ++ ++/* Define a macro with explicit types for arguments, which expands inline ++ into the wrapper code for a system call. It should be used when size ++ of any argument > size of long int. */ ++# undef INLINE_SYSCALL_TYPES ++# define INLINE_SYSCALL_TYPES(name, nr, args...) \ ++ ({ \ ++ unsigned long int resultvar = INTERNAL_SYSCALL_TYPES (name, , nr, args); \ ++ if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \ ++ { \ ++ __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ ++ resultvar = (unsigned long int) -1; \ ++ } \ ++ (long int) resultvar; }) ++ ++# undef INTERNAL_SYSCALL_DECL ++# define INTERNAL_SYSCALL_DECL(err) do { } while (0) ++ ++/* Registers clobbered by syscall. */ ++# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx" ++ ++/* Create a variable 'name' based on type 'X' to avoid explicit types. ++ This is mainly used set use 64-bits arguments in x32. */ ++#define TYPEFY(X, name) __typeof__ ((X) - (X)) name ++/* Explicit cast the argument to avoid integer from pointer warning on ++ x32. */ ++#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) ++ ++#undef INTERNAL_SYSCALL ++#define INTERNAL_SYSCALL(name, err, nr, args...) \ ++ internal_syscall##nr (SYS_ify (name), err, args) ++ ++#undef INTERNAL_SYSCALL_NCS ++#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ ++ internal_syscall##nr (number, err, args) ++ ++#undef internal_syscall0 ++#define internal_syscall0(number, err, dummy...) \ ++({ \ ++ unsigned long int resultvar; \ ++ asm volatile ( \ ++ "syscall\n\t" \ ++ : "=a" (resultvar) \ ++ : "0" (number) \ ++ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ ++ (long int) resultvar; \ ++}) ++ ++#undef internal_syscall1 ++#define internal_syscall1(number, err, arg1) \ ++({ \ ++ unsigned long int resultvar; \ ++ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ ++ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ ++ asm volatile ( \ ++ "syscall\n\t" \ ++ : "=a" (resultvar) \ ++ : "0" (number), "r" (_a1) \ ++ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ ++ (long int) resultvar; \ ++}) ++ ++#undef internal_syscall2 ++#define internal_syscall2(number, err, arg1, arg2) \ ++({ \ ++ unsigned long int resultvar; \ ++ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ ++ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ ++ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ ++ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ ++ asm volatile ( \ ++ "syscall\n\t" \ ++ : "=a" (resultvar) \ ++ : "0" (number), "r" (_a1), "r" (_a2) \ ++ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ ++ (long int) resultvar; \ ++}) ++ ++#undef internal_syscall3 ++#define internal_syscall3(number, err, arg1, arg2, arg3) \ ++({ \ ++ unsigned long int resultvar; \ ++ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ ++ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ ++ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ ++ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \ ++ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ ++ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ ++ asm volatile ( \ ++ "syscall\n\t" \ ++ : "=a" (resultvar) \ ++ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3) \ ++ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ ++ (long int) resultvar; \ ++}) ++ ++#undef internal_syscall4 ++#define internal_syscall4(number, err, arg1, arg2, arg3, arg4) \ ++({ \ ++ unsigned long int resultvar; \ ++ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \ ++ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ ++ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ ++ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ ++ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \ ++ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \ ++ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ ++ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ ++ asm volatile ( \ ++ "syscall\n\t" \ ++ : "=a" (resultvar) \ ++ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4) \ ++ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ ++ (long int) resultvar; \ ++}) ++ ++#undef internal_syscall5 ++#define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5) \ ++({ \ ++ unsigned long int resultvar; \ ++ TYPEFY (arg5, __arg5) = ARGIFY (arg5); \ ++ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \ ++ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ ++ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ ++ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ ++ register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \ ++ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \ ++ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \ ++ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ ++ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ ++ asm volatile ( \ ++ "syscall\n\t" \ ++ : "=a" (resultvar) \ ++ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \ ++ "r" (_a5) \ ++ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ ++ (long int) resultvar; \ ++}) ++ ++#undef internal_syscall6 ++#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \ ++({ \ ++ unsigned long int resultvar; \ ++ TYPEFY (arg6, __arg6) = ARGIFY (arg6); \ ++ TYPEFY (arg5, __arg5) = ARGIFY (arg5); \ ++ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \ ++ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ ++ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ ++ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ ++ register TYPEFY (arg6, _a6) asm ("r9") = __arg6; \ ++ register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \ ++ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \ ++ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \ ++ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ ++ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ ++ asm volatile ( \ ++ "syscall\n\t" \ ++ : "=a" (resultvar) \ ++ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \ ++ "r" (_a5), "r" (_a6) \ ++ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ ++ (long int) resultvar; \ ++}) ++ ++# undef INTERNAL_SYSCALL_ERROR_P ++# define INTERNAL_SYSCALL_ERROR_P(val, err) \ ++ ((unsigned long int) (long int) (val) >= -4095L) ++ ++# undef INTERNAL_SYSCALL_ERRNO ++# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) ++ ++/* List of system calls which are supported as vsyscalls. */ ++# define HAVE_CLOCK_GETTIME_VSYSCALL 1 ++# define HAVE_GETTIMEOFDAY_VSYSCALL 1 ++# define HAVE_GETCPU_VSYSCALL 1 ++ ++# define SINGLE_THREAD_BY_GLOBAL 1 ++ ++#endif /* __ASSEMBLER__ */ ++ ++ ++/* Pointer mangling support. */ ++#if IS_IN (rtld) ++/* We cannot use the thread descriptor because in ld.so we use setjmp ++ earlier than the descriptor is initialized. */ ++# ifdef __ASSEMBLER__ ++# define PTR_MANGLE(reg) xor __pointer_chk_guard_local(%rip), reg; \ ++ rol $2*LP_SIZE+1, reg ++# define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \ ++ xor __pointer_chk_guard_local(%rip), reg ++# else ++# define PTR_MANGLE(reg) asm ("xor __pointer_chk_guard_local(%%rip), %0\n" \ ++ "rol $2*" LP_SIZE "+1, %0" \ ++ : "=r" (reg) : "0" (reg)) ++# define PTR_DEMANGLE(reg) asm ("ror $2*" LP_SIZE "+1, %0\n" \ ++ "xor __pointer_chk_guard_local(%%rip), %0" \ ++ : "=r" (reg) : "0" (reg)) ++# endif ++#else ++# ifdef __ASSEMBLER__ ++# define PTR_MANGLE(reg) xor %fs:POINTER_GUARD, reg; \ ++ rol $2*LP_SIZE+1, reg ++# define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \ ++ xor %fs:POINTER_GUARD, reg ++# else ++# define PTR_MANGLE(var) asm ("xor %%fs:%c2, %0\n" \ ++ "rol $2*" LP_SIZE "+1, %0" \ ++ : "=r" (var) \ ++ : "0" (var), \ ++ "i" (offsetof (tcbhead_t, \ ++ pointer_guard))) ++# define PTR_DEMANGLE(var) asm ("ror $2*" LP_SIZE "+1, %0\n" \ ++ "xor %%fs:%c2, %0" \ ++ : "=r" (var) \ ++ : "0" (var), \ ++ "i" (offsetof (tcbhead_t, \ ++ pointer_guard))) ++# endif ++#endif ++ ++/* How to pass the off{64}_t argument on p{readv,writev}{64}. */ ++#undef LO_HI_LONG ++#define LO_HI_LONG(val) (val), 0 ++ ++/* Each shadow stack slot takes 8 bytes. Assuming that each stack ++ frame takes 256 bytes, this is used to compute shadow stack size ++ from stack size. */ ++#define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5 ++ ++#endif /* linux/x86_64/sysdep.h */ +diff --git a/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h +new file mode 100644 +index 00000000..5d61be20 +--- /dev/null ++++ b/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h +@@ -0,0 +1,34 @@ ++/* Copyright (C) 1991-2018 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 ++ ++#ifdef __ASSEMBLER__ ++ ++/* This is defined as a separate macro so that other sysdep.h files ++ can include this one and then redefine DO_CALL. */ ++ ++#define DO_CALL(syscall_name, args) \ ++ lea SYS_ify (syscall_name), %rax; \ ++ syscall ++ ++#define r0 %rax /* Normal return-value register. */ ++#define r1 %rbx /* Secondary return-value register. */ ++#define MOVE(x,y) movq x, y ++ ++#endif /* __ASSEMBLER__ */ +diff --git a/nptl_2_17/sysdeps/x86/sysdep_2_17.h b/nptl_2_17/sysdeps/x86/sysdep_2_17.h +new file mode 100644 +index 00000000..9f319ea4 +--- /dev/null ++++ b/nptl_2_17/sysdeps/x86/sysdep_2_17.h +@@ -0,0 +1,104 @@ ++/* Assembler macros for x86. ++ Copyright (C) 2017-2018 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 _X86_SYSDEP_H ++#define _X86_SYSDEP_H 1 ++ ++#include ++ ++/* __CET__ is defined by GCC with Control-Flow Protection values: ++ ++enum cf_protection_level ++{ ++ CF_NONE = 0, ++ CF_BRANCH = 1 << 0, ++ CF_RETURN = 1 << 1, ++ CF_FULL = CF_BRANCH | CF_RETURN, ++ CF_SET = 1 << 2 ++}; ++*/ ++ ++/* Set if CF_BRANCH (IBT) is enabled. */ ++#define X86_FEATURE_1_IBT (1U << 0) ++/* Set if CF_RETURN (SHSTK) is enabled. */ ++#define X86_FEATURE_1_SHSTK (1U << 1) ++ ++#ifdef __CET__ ++# define CET_ENABLED 1 ++# define IBT_ENABLED (__CET__ & X86_FEATURE_1_IBT) ++# define SHSTK_ENABLED (__CET__ & X86_FEATURE_1_SHSTK) ++#else ++# define CET_ENABLED 0 ++# define IBT_ENABLED 0 ++# define SHSTK_ENABLED 0 ++#endif ++ ++#ifdef __ASSEMBLER__ ++ ++/* Syntactic details of assembler. */ ++ ++#ifdef _CET_ENDBR ++# define _CET_NOTRACK notrack ++#else ++# define _CET_ENDBR ++# define _CET_NOTRACK ++#endif ++ ++/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ ++#define ALIGNARG(log2) 1<. */ ++ ++#ifndef _BITS_PTHREADTYPES_ARCH_H ++#define _BITS_PTHREADTYPES_ARCH_H 1 ++ ++#include ++ ++#ifdef __x86_64__ ++# if __WORDSIZE == 64 ++# define __SIZEOF_PTHREAD_MUTEX_T 40 ++# define __SIZEOF_PTHREAD_ATTR_T 56 ++# define __SIZEOF_PTHREAD_MUTEX_T 40 ++# define __SIZEOF_PTHREAD_RWLOCK_T 56 ++# define __SIZEOF_PTHREAD_BARRIER_T 32 ++# else ++# define __SIZEOF_PTHREAD_MUTEX_T 32 ++# define __SIZEOF_PTHREAD_ATTR_T 32 ++# define __SIZEOF_PTHREAD_MUTEX_T 32 ++# define __SIZEOF_PTHREAD_RWLOCK_T 44 ++# define __SIZEOF_PTHREAD_BARRIER_T 20 ++# endif ++#else ++# define __SIZEOF_PTHREAD_MUTEX_T 24 ++# define __SIZEOF_PTHREAD_ATTR_T 36 ++# define __SIZEOF_PTHREAD_MUTEX_T 24 ++# define __SIZEOF_PTHREAD_RWLOCK_T 32 ++# define __SIZEOF_PTHREAD_BARRIER_T 20 ++#endif ++#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 ++#define __SIZEOF_PTHREAD_COND_T 48 ++#define __SIZEOF_PTHREAD_CONDATTR_T 4 ++#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 ++#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 ++ ++/* Definitions for internal mutex struct. */ ++#define __PTHREAD_COMPAT_PADDING_MID ++#define __PTHREAD_COMPAT_PADDING_END ++#define __PTHREAD_MUTEX_LOCK_ELISION 1 ++#ifdef __x86_64__ ++# define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 ++# define __PTHREAD_MUTEX_USE_UNION 0 ++#else ++# define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 1 ++# define __PTHREAD_MUTEX_USE_UNION 1 ++#endif ++ ++#define __LOCK_ALIGNMENT ++#define __ONCE_ALIGNMENT ++ ++struct __pthread_rwlock_arch_t ++{ ++ unsigned int __readers; ++ unsigned int __writers; ++ unsigned int __wrphase_futex; ++ unsigned int __writers_futex; ++ unsigned int __pad3; ++ unsigned int __pad4; ++#ifdef __x86_64__ ++ int __cur_writer; ++ int __shared; ++ signed char __rwelision; ++# ifdef __ILP32__ ++ unsigned char __pad1[3]; ++# define __PTHREAD_RWLOCK_ELISION_EXTRA 0, { 0, 0, 0 } ++# else ++ unsigned char __pad1[7]; ++# define __PTHREAD_RWLOCK_ELISION_EXTRA 0, { 0, 0, 0, 0, 0, 0, 0 } ++# endif ++ unsigned long int __pad2; ++ /* FLAGS must stay at this position in the structure to maintain ++ binary compatibility. */ ++ unsigned int __flags; ++# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1 ++#else ++ /* FLAGS must stay at this position in the structure to maintain ++ binary compatibility. */ ++ unsigned char __flags; ++ unsigned char __shared; ++ signed char __rwelision; ++# define __PTHREAD_RWLOCK_ELISION_EXTRA 0 ++ unsigned char __pad2; ++ int __cur_writer; ++#endif ++}; ++ ++#ifndef __x86_64__ ++/* Extra attributes for the cleanup functions. */ ++# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1))) ++#endif ++ ++#endif /* bits/pthreadtypes.h */ +diff --git a/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h +new file mode 100644 +index 00000000..ab1b6bea +--- /dev/null ++++ b/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h +@@ -0,0 +1,129 @@ ++/* Assembler macros for x86-64. ++ Copyright (C) 2001-2018 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 _X86_64_SYSDEP_H ++#define _X86_64_SYSDEP_H 1 ++ ++#include ++ ++#ifdef __ASSEMBLER__ ++ ++/* Syntactic details of assembler. */ ++ ++/* This macro is for setting proper CFI with DW_CFA_expression describing ++ the register as saved relative to %rsp instead of relative to the CFA. ++ Expression is DW_OP_drop, DW_OP_breg7 (%rsp is register 7), sleb128 offset ++ from %rsp. */ ++#define cfi_offset_rel_rsp(regn, off) .cfi_escape 0x10, regn, 0x4, 0x13, \ ++ 0x77, off & 0x7F | 0x80, off >> 7 ++ ++/* If compiled for profiling, call `mcount' at the start of each function. */ ++#ifdef PROF ++/* The mcount code relies on a normal frame pointer being on the stack ++ to locate our caller, so push one just for its benefit. */ ++#define CALL_MCOUNT \ ++ pushq %rbp; \ ++ cfi_adjust_cfa_offset(8); \ ++ movq %rsp, %rbp; \ ++ cfi_def_cfa_register(%rbp); \ ++ call JUMPTARGET(mcount); \ ++ popq %rbp; \ ++ cfi_def_cfa(rsp,8); ++#else ++#define CALL_MCOUNT /* Do nothing. */ ++#endif ++ ++#define PSEUDO(name, syscall_name, args) \ ++lose: \ ++ jmp JUMPTARGET(syscall_error) \ ++ .globl syscall_error; \ ++ ENTRY (name) \ ++ DO_CALL (syscall_name, args); \ ++ jb lose ++ ++#undef JUMPTARGET ++#ifdef SHARED ++# ifdef BIND_NOW ++# define JUMPTARGET(name) *name##@GOTPCREL(%rip) ++# else ++# define JUMPTARGET(name) name##@PLT ++# endif ++#else ++/* For static archives, branch to target directly. */ ++# define JUMPTARGET(name) name ++#endif ++ ++/* Long and pointer size in bytes. */ ++#define LP_SIZE 8 ++ ++/* Instruction to operate on long and pointer. */ ++#define LP_OP(insn) insn##q ++ ++/* Assembler address directive. */ ++#define ASM_ADDR .quad ++ ++/* Registers to hold long and pointer. */ ++#define RAX_LP rax ++#define RBP_LP rbp ++#define RBX_LP rbx ++#define RCX_LP rcx ++#define RDI_LP rdi ++#define RDX_LP rdx ++#define RSI_LP rsi ++#define RSP_LP rsp ++#define R8_LP r8 ++#define R9_LP r9 ++#define R10_LP r10 ++#define R11_LP r11 ++#define R12_LP r12 ++#define R13_LP r13 ++#define R14_LP r14 ++#define R15_LP r15 ++ ++#else /* __ASSEMBLER__ */ ++ ++/* Long and pointer size in bytes. */ ++#define LP_SIZE "8" ++ ++/* Instruction to operate on long and pointer. */ ++#define LP_OP(insn) #insn "q" ++ ++/* Assembler address directive. */ ++#define ASM_ADDR ".quad" ++ ++/* Registers to hold long and pointer. */ ++#define RAX_LP "rax" ++#define RBP_LP "rbp" ++#define RBX_LP "rbx" ++#define RCX_LP "rcx" ++#define RDI_LP "rdi" ++#define RDX_LP "rdx" ++#define RSI_LP "rsi" ++#define RSP_LP "rsp" ++#define R8_LP "r8" ++#define R9_LP "r9" ++#define R10_LP "r10" ++#define R11_LP "r11" ++#define R12_LP "r12" ++#define R13_LP "r13" ++#define R14_LP "r14" ++#define R15_LP "r15" ++ ++#endif /* __ASSEMBLER__ */ ++ ++#endif /* _X86_64_SYSDEP_H */ +diff --git a/nptl_2_17/thread_db_2_17.h b/nptl_2_17/thread_db_2_17.h +new file mode 100644 +index 00000000..4206aed0 +--- /dev/null ++++ b/nptl_2_17/thread_db_2_17.h +@@ -0,0 +1,458 @@ ++/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread ++ Copyright (C) 1999-2018 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_DB_H ++#define _THREAD_DB_H 1 ++ ++/* This is the debugger interface for the NPTL library. It is ++ modelled closely after the interface with same names in Solaris ++ with the goal to share the same code in the debugger. */ ++#include ++#include ++#include ++#include ++ ++ ++/* Error codes of the library. */ ++typedef enum ++{ ++ TD_OK, /* No error. */ ++ TD_ERR, /* No further specified error. */ ++ TD_NOTHR, /* No matching thread found. */ ++ TD_NOSV, /* No matching synchronization handle found. */ ++ TD_NOLWP, /* No matching light-weighted process found. */ ++ TD_BADPH, /* Invalid process handle. */ ++ TD_BADTH, /* Invalid thread handle. */ ++ TD_BADSH, /* Invalid synchronization handle. */ ++ TD_BADTA, /* Invalid thread agent. */ ++ TD_BADKEY, /* Invalid key. */ ++ TD_NOMSG, /* No event available. */ ++ TD_NOFPREGS, /* No floating-point register content available. */ ++ TD_NOLIBTHREAD, /* Application not linked with thread library. */ ++ TD_NOEVENT, /* Requested event is not supported. */ ++ TD_NOCAPAB, /* Capability not available. */ ++ TD_DBERR, /* Internal debug library error. */ ++ TD_NOAPLIC, /* Operation is not applicable. */ ++ TD_NOTSD, /* No thread-specific data available. */ ++ TD_MALLOC, /* Out of memory. */ ++ TD_PARTIALREG, /* Not entire register set was read or written. */ ++ TD_NOXREGS, /* X register set not available for given thread. */ ++ TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */ ++ TD_NOTALLOC = TD_TLSDEFER, ++ TD_VERSION, /* Version if libpthread and libthread_db do not match. */ ++ TD_NOTLS /* There is no TLS segment in the given module. */ ++} td_err_e; ++ ++ ++/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to ++ select threads regardless of state in td_ta_thr_iter(). */ ++typedef enum ++{ ++ TD_THR_ANY_STATE, ++ TD_THR_UNKNOWN, ++ TD_THR_STOPPED, ++ TD_THR_RUN, ++ TD_THR_ACTIVE, ++ TD_THR_ZOMBIE, ++ TD_THR_SLEEP, ++ TD_THR_STOPPED_ASLEEP ++} td_thr_state_e; ++ ++/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used ++ to select threads regardless of type in td_ta_thr_iter(). */ ++typedef enum ++{ ++ TD_THR_ANY_TYPE, ++ TD_THR_USER, ++ TD_THR_SYSTEM ++} td_thr_type_e; ++ ++ ++/* Types of the debugging library. */ ++ ++/* Handle for a process. This type is opaque. */ ++typedef struct td_thragent td_thragent_t; ++ ++/* The actual thread handle type. This is also opaque. */ ++typedef struct td_thrhandle ++{ ++ td_thragent_t *th_ta_p; ++ psaddr_t th_unique; ++} td_thrhandle_t; ++ ++ ++/* Forward declaration of a type defined by and for the dynamic linker. */ ++struct link_map; ++ ++ ++/* Flags for `td_ta_thr_iter'. */ ++#define TD_THR_ANY_USER_FLAGS 0xffffffff ++#define TD_THR_LOWEST_PRIORITY -20 ++#define TD_SIGNO_MASK NULL ++ ++ ++#define TD_EVENTSIZE 2 ++#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */ ++#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per unsigned int */ ++#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */ ++ ++/* Bitmask of enabled events. */ ++typedef struct td_thr_events ++{ ++ uint32_t event_bits[TD_EVENTSIZE]; ++} td_thr_events_t; ++ ++/* Event set manipulation macros. */ ++#define __td_eventmask(n) \ ++ (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) ++#define __td_eventword(n) \ ++ ((UINT32_C ((n) - 1)) >> BT_UISHIFT) ++ ++#define td_event_emptyset(setp) \ ++ do { \ ++ int __i; \ ++ for (__i = TD_EVENTSIZE; __i > 0; --__i) \ ++ (setp)->event_bits[__i - 1] = 0; \ ++ } while (0) ++ ++#define td_event_fillset(setp) \ ++ do { \ ++ int __i; \ ++ for (__i = TD_EVENTSIZE; __i > 0; --__i) \ ++ (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \ ++ } while (0) ++ ++#define td_event_addset(setp, n) \ ++ (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) ++#define td_event_delset(setp, n) \ ++ (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) ++#define td_eventismember(setp, n) \ ++ (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) ++#if TD_EVENTSIZE == 2 ++# define td_eventisempty(setp) \ ++ (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) ++#else ++# error "td_eventisempty must be changed to match TD_EVENTSIZE" ++#endif ++ ++/* Events reportable by the thread implementation. */ ++typedef enum ++{ ++ TD_ALL_EVENTS, /* Pseudo-event number. */ ++ TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */ ++ TD_READY, /* Is executable now. */ ++ TD_SLEEP, /* Blocked in a synchronization obj. */ ++ TD_SWITCHTO, /* Now assigned to a process. */ ++ TD_SWITCHFROM, /* Not anymore assigned to a process. */ ++ TD_LOCK_TRY, /* Trying to get an unavailable lock. */ ++ TD_CATCHSIG, /* Signal posted to the thread. */ ++ TD_IDLE, /* Process getting idle. */ ++ TD_CREATE, /* New thread created. */ ++ TD_DEATH, /* Thread terminated. */ ++ TD_PREEMPT, /* Preempted. */ ++ TD_PRI_INHERIT, /* Inherited elevated priority. */ ++ TD_REAP, /* Reaped. */ ++ TD_CONCURRENCY, /* Number of processes changing. */ ++ TD_TIMEOUT, /* Conditional variable wait timed out. */ ++ TD_MIN_EVENT_NUM = TD_READY, ++ TD_MAX_EVENT_NUM = TD_TIMEOUT, ++ TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */ ++} td_event_e; ++ ++/* Values representing the different ways events are reported. */ ++typedef enum ++{ ++ NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */ ++ NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically ++ inserted. */ ++ NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */ ++} td_notify_e; ++ ++/* Description how event type is reported. */ ++typedef struct td_notify ++{ ++ td_notify_e type; /* Way the event is reported. */ ++ union ++ { ++ psaddr_t bptaddr; /* Address of breakpoint. */ ++ int syscallno; /* Number of system call used. */ ++ } u; ++} td_notify_t; ++ ++/* Structure used to report event. */ ++typedef struct td_event_msg ++{ ++ td_event_e event; /* Event type being reported. */ ++ const td_thrhandle_t *th_p; /* Thread reporting the event. */ ++ union ++ { ++# if 0 ++ td_synchandle_t *sh; /* Handle of synchronization object. */ ++#endif ++ uintptr_t data; /* Event specific data. */ ++ } msg; ++} td_event_msg_t; ++ ++/* Structure containing event data available in each thread structure. */ ++typedef struct ++{ ++ td_thr_events_t eventmask; /* Mask of enabled events. */ ++ td_event_e eventnum; /* Number of last event. */ ++ void *eventdata; /* Data associated with event. */ ++} td_eventbuf_t; ++ ++ ++/* Gathered statistics about the process. */ ++typedef struct td_ta_stats ++{ ++ int nthreads; /* Total number of threads in use. */ ++ int r_concurrency; /* Concurrency level requested by user. */ ++ int nrunnable_num; /* Average runnable threads, numerator. */ ++ int nrunnable_den; /* Average runnable threads, denominator. */ ++ int a_concurrency_num; /* Achieved concurrency level, numerator. */ ++ int a_concurrency_den; /* Achieved concurrency level, denominator. */ ++ int nlwps_num; /* Average number of processes in use, ++ numerator. */ ++ int nlwps_den; /* Average number of processes in use, ++ denominator. */ ++ int nidle_num; /* Average number of idling processes, ++ numerator. */ ++ int nidle_den; /* Average number of idling processes, ++ denominator. */ ++} td_ta_stats_t; ++ ++ ++/* Since Sun's library is based on Solaris threads we have to define a few ++ types to map them to POSIX threads. */ ++typedef pthread_t thread_t; ++typedef pthread_key_t thread_key_t; ++ ++ ++/* Callback for iteration over threads. */ ++typedef int td_thr_iter_f (const td_thrhandle_t *, void *); ++ ++/* Callback for iteration over thread local data. */ ++typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); ++ ++ ++ ++/* Forward declaration. This has to be defined by the user. */ ++struct ps_prochandle; ++ ++ ++/* Information about the thread. */ ++typedef struct td_thrinfo ++{ ++ td_thragent_t *ti_ta_p; /* Process handle. */ ++ unsigned int ti_user_flags; /* Unused. */ ++ thread_t ti_tid; /* Thread ID returned by ++ pthread_create(). */ ++ char *ti_tls; /* Pointer to thread-local data. */ ++ psaddr_t ti_startfunc; /* Start function passed to ++ pthread_create(). */ ++ psaddr_t ti_stkbase; /* Base of thread's stack. */ ++ long int ti_stksize; /* Size of thread's stack. */ ++ psaddr_t ti_ro_area; /* Unused. */ ++ int ti_ro_size; /* Unused. */ ++ td_thr_state_e ti_state; /* Thread state. */ ++ unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */ ++ td_thr_type_e ti_type; /* Type of the thread (system vs ++ user thread). */ ++ intptr_t ti_pc; /* Unused. */ ++ intptr_t ti_sp; /* Unused. */ ++ short int ti_flags; /* Unused. */ ++ int ti_pri; /* Thread priority. */ ++ lwpid_t ti_lid; /* Kernel PID for this thread. */ ++ sigset_t ti_sigmask; /* Signal mask. */ ++ unsigned char ti_traceme; /* Nonzero if event reporting ++ enabled. */ ++ unsigned char ti_preemptflag; /* Unused. */ ++ unsigned char ti_pirecflag; /* Unused. */ ++ sigset_t ti_pending; /* Set of pending signals. */ ++ td_thr_events_t ti_events; /* Set of enabled events. */ ++} td_thrinfo_t; ++ ++ ++ ++/* Prototypes for exported library functions. */ ++ ++/* Initialize the thread debug support library. */ ++extern td_err_e td_init (void); ++ ++/* Historical relict. Should not be used anymore. */ ++extern td_err_e td_log (void); ++ ++/* Return list of symbols the library can request. */ ++extern const char **td_symbol_list (void); ++ ++/* Generate new thread debug library handle for process PS. */ ++extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); ++ ++/* Free resources allocated for TA. */ ++extern td_err_e td_ta_delete (td_thragent_t *__ta); ++ ++/* Get number of currently running threads in process associated with TA. */ ++extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); ++ ++/* Return process handle passed in `td_ta_new' for process associated with ++ TA. */ ++extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, ++ struct ps_prochandle **__ph); ++ ++/* Map thread library handle PT to thread debug library handle for process ++ associated with TA and store result in *TH. */ ++extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, ++ td_thrhandle_t *__th); ++ ++/* Map process ID LWPID to thread debug library handle for process ++ associated with TA and store result in *TH. */ ++extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, ++ td_thrhandle_t *__th); ++ ++ ++/* Call for each thread in a process associated with TA the callback function ++ CALLBACK. */ ++extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, ++ td_thr_iter_f *__callback, void *__cbdata_p, ++ td_thr_state_e __state, int __ti_pri, ++ sigset_t *__ti_sigmask_p, ++ unsigned int __ti_user_flags); ++ ++/* Call for each defined thread local data entry the callback function KI. */ ++extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, ++ void *__p); ++ ++ ++/* Get event address for EVENT. */ ++extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, ++ td_event_e __event, td_notify_t *__ptr); ++ ++/* Enable EVENT in global mask. */ ++extern td_err_e td_ta_set_event (const td_thragent_t *__ta, ++ td_thr_events_t *__event); ++ ++/* Disable EVENT in global mask. */ ++extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, ++ td_thr_events_t *__event); ++ ++/* Return information about last event. */ ++extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, ++ td_event_msg_t *__msg); ++ ++ ++/* Set suggested concurrency level for process associated with TA. */ ++extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); ++ ++ ++/* Enable collecting statistics for process associated with TA. */ ++extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); ++ ++/* Reset statistics. */ ++extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); ++ ++/* Retrieve statistics from process associated with TA. */ ++extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, ++ td_ta_stats_t *__statsp); ++ ++ ++/* Validate that TH is a thread handle. */ ++extern td_err_e td_thr_validate (const td_thrhandle_t *__th); ++ ++/* Return information about thread TH. */ ++extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, ++ td_thrinfo_t *__infop); ++ ++/* Retrieve floating-point register contents of process running thread TH. */ ++extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, ++ prfpregset_t *__regset); ++ ++/* Retrieve general register contents of process running thread TH. */ ++extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, ++ prgregset_t __gregs); ++ ++/* Retrieve extended register contents of process running thread TH. */ ++extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); ++ ++/* Get size of extended register set of process running thread TH. */ ++extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); ++ ++/* Set floating-point register contents of process running thread TH. */ ++extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, ++ const prfpregset_t *__fpregs); ++ ++/* Set general register contents of process running thread TH. */ ++extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, ++ prgregset_t __gregs); ++ ++/* Set extended register contents of process running thread TH. */ ++extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, ++ const void *__addr); ++ ++ ++/* Get address of the given module's TLS storage area for the given thread. */ ++extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, ++ unsigned long int __modid, ++ psaddr_t *__base); ++ ++/* Get address of thread local variable. */ ++extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, ++ psaddr_t __map_address, size_t __offset, ++ psaddr_t *__address); ++ ++ ++/* Enable reporting for EVENT for thread TH. */ ++extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); ++ ++/* Enable EVENT for thread TH. */ ++extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, ++ td_thr_events_t *__event); ++ ++/* Disable EVENT for thread TH. */ ++extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, ++ td_thr_events_t *__event); ++ ++/* Get event message for thread TH. */ ++extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, ++ td_event_msg_t *__msg); ++ ++ ++/* Set priority of thread TH. */ ++extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); ++ ++ ++/* Set pending signals for thread TH. */ ++extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, ++ unsigned char __n, const sigset_t *__ss); ++ ++/* Set signal mask for thread TH. */ ++extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, ++ const sigset_t *__ss); ++ ++ ++/* Return thread local data associated with key TK in thread TH. */ ++extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, ++ const thread_key_t __tk, void **__data); ++ ++ ++/* Suspend execution of thread TH. */ ++extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); ++ ++/* Resume execution of thread TH. */ ++extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); ++ ++#endif /* thread_db.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..45fff81a +--- /dev/null ++++ b/nptl_2_17/tpp_2_17.c +@@ -0,0 +1,195 @@ ++/* Thread Priority Protect helpers. ++ Copyright (C) 2006-2018 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 "pthreadP_2_17.h" ++#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/vars_2_17.c b/nptl_2_17/vars_2_17.c +new file mode 100644 +index 00000000..ae60c0f8 +--- /dev/null ++++ b/nptl_2_17/vars_2_17.c +@@ -0,0 +1,43 @@ ++/* Copyright (C) 2004-2018 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 "pthreadP_2_17.h" ++#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.30.0 + diff --git a/glibc.spec b/glibc.spec index edc7cc4..e824ab5 100644 --- a/glibc.spec +++ b/glibc.spec @@ -31,7 +31,9 @@ %bcond_with bootstrap %bcond_with werror %bcond_without docs -%bcond_with libpthreadcond +%ifarch x86_64 aarch64 +%bcond_without compat_2_17 +%endif %ifarch %{valgrind_arches} %bcond_without valgrind @@ -63,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 14 +Release: 15 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -117,7 +119,7 @@ Patch32: rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch -#Patch9002: build-extra-libpthreadcond-so.patch +Patch9002: compat-2.17-libpthreadcond-so.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -409,6 +411,18 @@ Requires: man info %description help This package provides al doc and man files of %{name} +############################################################################## +# glibc compat-2.17 sub-package +############################################################################## +%if %{with compat_2_17} +%package compat-2.17 +Summary: provides pthread library with glibc-2.17 + +%description compat-2.17 +This subpackage to provide the function of the glibc-2.17 pthread library. +Currently, provide pthread_condition function.. +%endif + ############################################################################## # Prepare for the build. ############################################################################## @@ -507,11 +521,11 @@ make %{?_smp_mflags} -O -r %{glibc_make_flags} popd ############################################################################## -# Build libpthreadcond +# Build libpthread-2.17.so ############################################################################## -%if %{with libpthreadcond} +%if %{with compat_2_17} cd nptl_2_17 - sh build_libpthreadcondso.sh %{_target_cpu} $builddir + sh build_libpthread-2.17.so.sh %{_target_cpu} $builddir cd .. %endif @@ -528,10 +542,6 @@ done make %{?_smp_mflags} 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} install_root=$RPM_BUILD_ROOT \ @@ -591,6 +601,11 @@ mv $RPM_BUILD_ROOT%{_prefix}/lib/locale/libc.lang . # Install configuration files for services install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/etc/nsswitch.conf +# This is for compat-2.17 +%if %{with compat_2_17} +install -p -m 755 build-%{target}/nptl/libpthread-2.17.so $RPM_BUILD_ROOT%{_libdir} +%endif + # This is for ncsd - in glibc 2.2 install -m 644 nscd/nscd.conf $RPM_BUILD_ROOT/etc mkdir -p $RPM_BUILD_ROOT%{_tmpfilesdir} @@ -703,6 +718,9 @@ touch libnsl.filelist touch debugutils.filelist touch benchtests.filelist touch debuginfo.filelist +%if %{with compat_2_17} +touch compat-2.17.filelist +%endif { find $RPM_BUILD_ROOT \( -type f -o -type l \) \ @@ -729,6 +747,9 @@ touch debuginfo.filelist -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' \ +%if %{with compat_2_17} + -e '\,.*/%{_libdir}/libpthread-2.17.so,d' \ +%endif -e '\,.*/bin/\(memusage\|mtrace\|xtrace\|pcprofiledump\),d' } | sort > master.filelist @@ -765,10 +786,6 @@ for module in compat files dns; do 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 ############################################################################## @@ -863,6 +880,13 @@ echo "%{_prefix}/libexec/glibc-benchtests/import_bench.py*" >> benchtests.fileli echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.filelist %endif +%if %{with compat_2_17} +############################################################################## +# glibc compat-2.17 sub-package +############################################################################## + echo "%{_libdir}/libpthread-2.17.so" >> compat-2.17.filelist +%endif + %if 0%{?_enable_debug_packages} ############################################################################## # glibc debuginfo sub-package @@ -881,6 +905,9 @@ find_debuginfo_args="$find_debuginfo_args \ -l glibc.filelist \ %if %{with benchtests} -l benchtests.filelist +%endif +%if %{with compat_2_17} + -l compat-2.17.filelist \ %endif " %endif @@ -1273,7 +1300,16 @@ fi #Doc of nss_modules sub-package %doc hesiod/README.hesiod +%if %{with compat_2_17} +%files -f compat-2.17.filelist compat-2.17 +%endif + %changelog +* Tue Oct 26 2021 Yang Yanchao - 2.34-15 +- add glibc-compat-2.17 subpackage to provide the function of + the glibc-2.17 pthread library. + Currently, provide pthread_condition function. + * Mon Oct 25 2021 Qingqing Li - 2.34-14 - mtrace fix output with PIE and ASLR. - elf: rtld copy terminating null in tunables strdup. -- Gitee From 6dc52338111241fee9e13c64916e1cff3962c66d Mon Sep 17 00:00:00 2001 From: Fcc Date: Tue, 26 Oct 2021 20:29:37 +0800 Subject: [PATCH 15/70] Use __executable_start as the lowest address for profiling (cherry picked from commit 14d36df964740fcf1236710de9e79b4380c2dae4) --- ..._start-as-the-lowest-address-for-pro.patch | 106 ++++++++++++++++++ glibc.spec | 6 +- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 Use-__executable_start-as-the-lowest-address-for-pro.patch diff --git a/Use-__executable_start-as-the-lowest-address-for-pro.patch b/Use-__executable_start-as-the-lowest-address-for-pro.patch new file mode 100644 index 0000000..06ddfb1 --- /dev/null +++ b/Use-__executable_start-as-the-lowest-address-for-pro.patch @@ -0,0 +1,106 @@ +From 84a7eb1f87c1d01b58ad887a0ab5d87abbc1c772 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Fri, 30 Jul 2021 19:07:30 -0700 +Subject: [PATCH] Use __executable_start as the lowest address for profiling + [BZ #28153] + +Glibc assumes that ENTRY_POINT is the lowest address for which we need +to keep profiling records and BFD linker uses a linker script to place +the input sections. + +Starting from GCC 4.6, the main function is placed in .text.startup +section and starting from binutils 2.22, BFD linker with + +commit add44f8d5c5c05e08b11e033127a744d61c26aee +Author: Alan Modra +Date: Thu Nov 25 03:03:02 2010 +0000 + + * scripttempl/elf.sc: Group .text.exit, text.startup and .text.hot + sections. + +places .text.startup section before .text section, which leave the main +function out of profiling records. + +Starting from binutils 2.15, linker provides __executable_start to mark +the lowest address of the executable. Use __executable_start as the +lowest address to keep the main function in profiling records. This fixes +[BZ #28153]. + +Tested on Linux/x86-64, Linux/x32 and Linux/i686 as well as with +build-many-glibcs.py. +--- + csu/gmon-start.c | 10 +++++++++- + gmon/tst-gmon-gprof.sh | 2 ++ + gmon/tst-gmon-static-gprof.sh | 2 ++ + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/csu/gmon-start.c b/csu/gmon-start.c +index b343288..344606a 100644 +--- a/csu/gmon-start.c ++++ b/csu/gmon-start.c +@@ -52,6 +52,11 @@ extern char ENTRY_POINT[]; + #endif + extern char etext[]; + ++/* Use __executable_start as the lowest address to keep profiling records ++ if it provided by the linker. */ ++extern const char executable_start[] asm ("__executable_start") ++ __attribute__ ((weak, visibility ("hidden"))); ++ + #ifndef TEXT_START + # ifdef ENTRY_POINT_DECL + # define TEXT_START ENTRY_POINT +@@ -92,7 +97,10 @@ __gmon_start__ (void) + called = 1; + + /* Start keeping profiling records. */ +- __monstartup ((u_long) TEXT_START, (u_long) &etext); ++ if (&executable_start != NULL) ++ __monstartup ((u_long) &executable_start, (u_long) &etext); ++ else ++ __monstartup ((u_long) TEXT_START, (u_long) &etext); + + /* Call _mcleanup before exiting; it will write out gmon.out from the + collected data. */ +diff --git a/gmon/tst-gmon-gprof.sh b/gmon/tst-gmon-gprof.sh +index 9d37158..dc0be02 100644 +--- a/gmon/tst-gmon-gprof.sh ++++ b/gmon/tst-gmon-gprof.sh +@@ -39,12 +39,14 @@ trap cleanup 0 + cat > "$expected" < "$expected_dot" < "$expected" < "$expected_dot" < - 2.34-16 +- Use __executable_start as the lowest address for profiling + * Tue Oct 26 2021 Yang Yanchao - 2.34-15 - add glibc-compat-2.17 subpackage to provide the function of the glibc-2.17 pthread library. -- Gitee From 25bfe0fc5c08944aea45b7608e43c3de8bb6cd6d Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 26 Oct 2021 21:17:15 +0800 Subject: [PATCH 16/70] Show more debugging information during testsuite Signed-off-by: Yang Yanchao (cherry picked from commit e6a721beed80460b73fa2bc1f39130336922914a) --- glibc.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/glibc.spec b/glibc.spec index 9cbc0db..73a93b6 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 16 +Release: 17 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -969,7 +969,6 @@ if ! grep -q '^Summary of test results:$' rpmbuild.check.log ; then echo "FAIL: test suite build of target: $(basename "$(pwd)")" >& 2 exit 1 fi -set +x grep -v ^PASS: tests.sum | grep -v ^UNSUPPORTED > rpmbuild.tests.sum.not-passing || true # Delete the testsuite from the whitelist @@ -977,6 +976,7 @@ cp %{SOURCE8} testsuite_whitelist omit_testsuite testsuite_whitelist rm -rf testsuite_whitelist +set +x if test -s rpmbuild.tests.sum.not-passing ; then echo ===================FAILED TESTS===================== >&2 echo "Target: $(basename "$(pwd)")" >& 2 @@ -1306,6 +1306,9 @@ fi %endif %changelog +* Tue Oct 26 2021 Yang Yanchao - 2.34-17 +- Show more debugging information during testsuite + * Tue Oct 26 2021 Chuangchuang Fang - 2.34-16 - Use __executable_start as the lowest address for profiling -- Gitee From 60ab5dcac128fba75755c2ec0142b57719779278 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Thu, 28 Oct 2021 20:59:51 +0800 Subject: [PATCH 17/70] use testl, instead of andl, to check __x86_string_control to avoid updating __x86_string_control (cherry picked from commit a085006b9ecdc4685067692c4d50832a28e274af) --- glibc.spec | 7 +++- ...-testl-to-check-__x86_string_control.patch | 38 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 x86-64-Use-testl-to-check-__x86_string_control.patch diff --git a/glibc.spec b/glibc.spec index 73a93b6..275f792 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 17 +Release: 18 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -117,6 +117,7 @@ Patch30: x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch Patch31: mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch Patch32: rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch Patch33: Use-__executable_start-as-the-lowest-address-for-pro.patch +Patch34: x86-64-Use-testl-to-check-__x86_string_control.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1306,6 +1307,10 @@ fi %endif %changelog +* Thu Oct 28 2021 Qingqing Li - 2.34-18 +- use testl instead of andl to check __x86_string_control to + avoid updating __x86_string_control + * Tue Oct 26 2021 Yang Yanchao - 2.34-17 - Show more debugging information during testsuite diff --git a/x86-64-Use-testl-to-check-__x86_string_control.patch b/x86-64-Use-testl-to-check-__x86_string_control.patch new file mode 100644 index 0000000..363930e --- /dev/null +++ b/x86-64-Use-testl-to-check-__x86_string_control.patch @@ -0,0 +1,38 @@ +From 3c8b9879cab6d41787bc5b14c1748f62fd6d0e5f Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Sat, 28 Aug 2021 06:10:38 -0700 +Subject: [PATCH] x86-64: Use testl to check __x86_string_control + +Use testl, instead of andl, to check __x86_string_control to avoid +updating __x86_string_control. + +Reviewed-by: Carlos O'Donell +--- + sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +index 9f02624..abde843 100644 +--- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +@@ -325,7 +325,7 @@ L(movsb): + /* Avoid slow backward REP MOVSB. */ + jb L(more_8x_vec_backward) + # if AVOID_SHORT_DISTANCE_REP_MOVSB +- andl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) ++ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) + jz 3f + movq %rdi, %rcx + subq %rsi, %rcx +@@ -333,7 +333,7 @@ L(movsb): + # endif + 1: + # if AVOID_SHORT_DISTANCE_REP_MOVSB +- andl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) ++ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) + jz 3f + movq %rsi, %rcx + subq %rdi, %rcx +-- +1.8.3.1 + -- Gitee From d20be8b766c9566381e59a113dbab83a1de67000 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Fri, 29 Oct 2021 11:07:01 +0800 Subject: [PATCH 18/70] aarch64: update a64fx memset not to degrade at 16KB (cherry picked from commit 653f3153b97d952c1e05772dbad0e9c6af4d6692) --- ...-A64FX-memset-not-to-degrade-at-16KB.patch | 39 +++++++++++++++++++ glibc.spec | 6 ++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch diff --git a/AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch b/AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch new file mode 100644 index 0000000..f7ce84d --- /dev/null +++ b/AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch @@ -0,0 +1,39 @@ +From 23777232c23f80809613bdfa329f63aadf992922 Mon Sep 17 00:00:00 2001 +From: Naohiro Tamura via Libc-alpha +Date: Fri, 27 Aug 2021 05:03:04 +0000 +Subject: [PATCH] AArch64: Update A64FX memset not to degrade at 16KB + +This patch updates unroll8 code so as not to degrade at the peak +performance 16KB for both FX1000 and FX700. + +Inserted 2 instructions at the beginning of the unroll8 loop, +cmp and branch, are a workaround that is found heuristically. + +Reviewed-by: Wilco Dijkstra +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index 7bf759b..f7dfdaa 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -96,7 +96,14 @@ L(vl_agnostic): // VL Agnostic + L(unroll8): + sub count, count, tmp1 + .p2align 4 +-1: st1b_unroll 0, 7 ++ // The 2 instructions at the beginning of the following loop, ++ // cmp and branch, are a workaround so as not to degrade at ++ // the peak performance 16KB. ++ // It is found heuristically and the branch condition, b.ne, ++ // is chosen intentionally never to jump. ++1: cmp xzr, xzr ++ b.ne 1b ++ st1b_unroll 0, 7 + add dst, dst, tmp1 + subs count, count, tmp1 + b.hi 1b +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index 275f792..80db7b8 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 18 +Release: 19 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -118,6 +118,7 @@ Patch31: mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch Patch32: rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch Patch33: Use-__executable_start-as-the-lowest-address-for-pro.patch Patch34: x86-64-Use-testl-to-check-__x86_string_control.patch +Patch35: AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1307,6 +1308,9 @@ fi %endif %changelog +* Fri Oct 29 2021 Qingqing Li - 2.34-19 +- aarch64: update a64fx memset not to degrade at 16KB + * Thu Oct 28 2021 Qingqing Li - 2.34-18 - use testl instead of andl to check __x86_string_control to avoid updating __x86_string_control -- Gitee From 2431e249b57c4edf04adb17a80efd9a893bb0635 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Thu, 4 Nov 2021 19:59:03 +0800 Subject: [PATCH 19/70] pthread_kill and pthread_cancel return success for satisfy posix standard. (cherry picked from commit 5d781b4a0c02a823e7dae98e86775c3516ca3d91) --- glibc.spec | 9 +- ...l-pthread_cancel-should-not-fail-aft.patch | 292 ++++++++++++++++++ ...ort-Add-support_wait_for_thread_exit.patch | 124 ++++++++ 3 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch create mode 100644 support-Add-support_wait_for_thread_exit.patch diff --git a/glibc.spec b/glibc.spec index 80db7b8..9361a89 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 19 +Release: 20 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -119,6 +119,8 @@ Patch32: rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch Patch33: Use-__executable_start-as-the-lowest-address-for-pro.patch Patch34: x86-64-Use-testl-to-check-__x86_string_control.patch Patch35: AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch +Patch36: support-Add-support_wait_for_thread_exit.patch +Patch37: nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1308,6 +1310,11 @@ fi %endif %changelog +* Thu Nov 4 2021 Qingqing Li - 2.34-20 +- nptl: pthread_kill and pthread_cancel return success + for satisfy posix standard. + uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=19193 + * Fri Oct 29 2021 Qingqing Li - 2.34-19 - aarch64: update a64fx memset not to degrade at 16KB diff --git a/nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch b/nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch new file mode 100644 index 0000000..7d1bc81 --- /dev/null +++ b/nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch @@ -0,0 +1,292 @@ +From 8af8456004edbab71f8903a60a3cae442cf6fe69 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 13 Sep 2021 11:06:08 +0200 +Subject: [PATCH] nptl: pthread_kill, pthread_cancel should not fail after exit + (bug 19193) + +This closes one remaining race condition related to bug 12889: if +the thread already exited on the kernel side, returning ESRCH +is not correct because that error is reserved for the thread IDs +(pthread_t values) whose lifetime has ended. In case of a +kernel-side exit and a valid thread ID, no signal needs to be sent +and cancellation does not have an effect, so just return 0. + +sysdeps/pthread/tst-kill4.c triggers undefined behavior and is +removed with this commit. + +Reviewed-by: Adhemerval Zanella +--- + nptl/pthread_cancel.c | 9 +-- + nptl/pthread_kill.c | 7 ++- + sysdeps/pthread/Makefile | 5 +- + sysdeps/pthread/tst-kill4.c | 90 ----------------------------- + sysdeps/pthread/tst-pthread_cancel-exited.c | 45 +++++++++++++++ + sysdeps/pthread/tst-pthread_kill-exited.c | 46 +++++++++++++++ + 6 files changed, 106 insertions(+), 96 deletions(-) + delete mode 100644 sysdeps/pthread/tst-kill4.c + create mode 100644 sysdeps/pthread/tst-pthread_cancel-exited.c + create mode 100644 sysdeps/pthread/tst-pthread_kill-exited.c + +diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c +index 2bb523c..a8aa3b3 100644 +--- a/nptl/pthread_cancel.c ++++ b/nptl/pthread_cancel.c +@@ -61,10 +61,11 @@ __pthread_cancel (pthread_t th) + { + volatile struct pthread *pd = (volatile struct pthread *) th; + +- /* Make sure the descriptor is valid. */ +- if (INVALID_TD_P (pd)) +- /* Not a valid thread handle. */ +- return ESRCH; ++ if (pd->tid == 0) ++ /* The thread has already exited on the kernel side. Its outcome ++ (regular exit, other cancelation) has already been ++ determined. */ ++ return 0; + + static int init_sigcancel = 0; + if (atomic_load_relaxed (&init_sigcancel) == 0) +diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c +index f79a2b2..5d4c86f 100644 +--- a/nptl/pthread_kill.c ++++ b/nptl/pthread_kill.c +@@ -46,7 +46,12 @@ __pthread_kill_internal (pthread_t threadid, int signo) + ? INTERNAL_SYSCALL_ERRNO (val) : 0); + } + else +- val = ESRCH; ++ /* The kernel reports that the thread has exited. POSIX specifies ++ the ESRCH error only for the case when the lifetime of a thread ++ ID has ended, but calling pthread_kill on such a thread ID is ++ undefined in glibc. Therefore, do not treat kernel thread exit ++ as an error. */ ++ val = 0; + + return val; + } +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index 42f9fc5..dedfa0d 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -89,7 +89,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \ + tst-join14 tst-join15 \ + tst-key1 tst-key2 tst-key3 tst-key4 \ +- tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \ ++ tst-kill1 tst-kill2 tst-kill3 tst-kill5 tst-kill6 \ + tst-locale1 tst-locale2 \ + tst-memstream \ + tst-mutex-errorcheck tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 \ +@@ -118,6 +118,9 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-unload \ + tst-unwind-thread \ + tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \ ++ tst-pthread_cancel-exited \ ++ tst-pthread_kill-exited \ ++ # tests + + tests-time64 := \ + tst-abstime-time64 \ +diff --git a/sysdeps/pthread/tst-kill4.c b/sysdeps/pthread/tst-kill4.c +deleted file mode 100644 +index 222ceb7..0000000 +--- a/sysdeps/pthread/tst-kill4.c ++++ /dev/null +@@ -1,90 +0,0 @@ +-/* Copyright (C) 2003-2021 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 +- +- +-static void * +-tf (void *a) +-{ +- return NULL; +-} +- +- +-int +-do_test (void) +-{ +- pthread_attr_t at; +- if (pthread_attr_init (&at) != 0) +- { +- puts ("attr_create failed"); +- exit (1); +- } +- +- /* Limit thread stack size, because if it is too large, pthread_join +- will free it immediately rather than put it into stack cache. */ +- if (pthread_attr_setstacksize (&at, 2 * 1024 * 1024) != 0) +- { +- puts ("setstacksize failed"); +- exit (1); +- } +- +- pthread_t th; +- if (pthread_create (&th, &at, tf, NULL) != 0) +- { +- puts ("create failed"); +- exit (1); +- } +- +- pthread_attr_destroy (&at); +- +- if (pthread_join (th, NULL) != 0) +- { +- puts ("join failed"); +- exit (1); +- } +- +- /* The following only works because we assume here something about +- the implementation. Namely, that the memory allocated for the +- thread descriptor is not going away, that the TID field is +- cleared and therefore the signal is sent to process 0, and that +- we can savely assume there is no other process with this ID at +- that time. */ +- int e = pthread_kill (th, 0); +- if (e == 0) +- { +- puts ("pthread_kill succeeded"); +- exit (1); +- } +- if (e != ESRCH) +- { +- puts ("pthread_kill didn't return ESRCH"); +- exit (1); +- } +- +- return 0; +-} +- +- +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" +diff --git a/sysdeps/pthread/tst-pthread_cancel-exited.c b/sysdeps/pthread/tst-pthread_cancel-exited.c +new file mode 100644 +index 0000000..811c9be +--- /dev/null ++++ b/sysdeps/pthread/tst-pthread_cancel-exited.c +@@ -0,0 +1,45 @@ ++/* Test that pthread_kill succeeds for an exited thread. ++ Copyright (C) 2021 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 verifies that pthread_kill returns 0 (and not ESRCH) for ++ a thread that has exited on the kernel side. */ ++ ++#include ++#include ++#include ++ ++static void * ++noop_thread (void *closure) ++{ ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ pthread_t thr = xpthread_create (NULL, noop_thread, NULL); ++ ++ support_wait_for_thread_exit (); ++ ++ xpthread_cancel (thr); ++ xpthread_join (thr); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/pthread/tst-pthread_kill-exited.c b/sysdeps/pthread/tst-pthread_kill-exited.c +new file mode 100644 +index 0000000..7575fb6 +--- /dev/null ++++ b/sysdeps/pthread/tst-pthread_kill-exited.c +@@ -0,0 +1,46 @@ ++/* Test that pthread_kill succeeds for an exited thread. ++ Copyright (C) 2021 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 verifies that pthread_kill returns 0 (and not ESRCH) for ++ a thread that has exited on the kernel side. */ ++ ++#include ++#include ++#include ++#include ++ ++static void * ++noop_thread (void *closure) ++{ ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ pthread_t thr = xpthread_create (NULL, noop_thread, NULL); ++ ++ support_wait_for_thread_exit (); ++ ++ xpthread_kill (thr, SIGUSR1); ++ xpthread_join (thr); ++ ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + diff --git a/support-Add-support_wait_for_thread_exit.patch b/support-Add-support_wait_for_thread_exit.patch new file mode 100644 index 0000000..97ca806 --- /dev/null +++ b/support-Add-support_wait_for_thread_exit.patch @@ -0,0 +1,124 @@ +From 032d74eaf6179100048a5bf0ce942e97dc8b9a60 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 30 Aug 2021 13:43:56 +0200 +Subject: [PATCH] support: Add support_wait_for_thread_exit + +--- + support/Makefile | 3 +- + support/support.h | 4 ++ + support/support_wait_for_thread_exit.c | 72 ++++++++++++++++++++++++++++++++++ + 3 files changed, 78 insertions(+), 1 deletion(-) + create mode 100644 support/support_wait_for_thread_exit.c + +diff --git a/support/Makefile b/support/Makefile +index 6332e7b..2a07317 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -83,9 +83,10 @@ libsupport-routines = \ + support_test_compare_blob \ + support_test_compare_failure \ + support_test_compare_string \ +- support_write_file_string \ + support_test_main \ + support_test_verify_impl \ ++ support_wait_for_thread_exit \ ++ support_write_file_string \ + temp_file \ + timespec \ + timespec-time64 \ +diff --git a/support/support.h b/support/support.h +index e6911e1..c219e0d 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -174,6 +174,10 @@ timer_t support_create_timer (uint64_t sec, long int nsec, bool repeat, + /* Disable the timer TIMER. */ + void support_delete_timer (timer_t timer); + ++/* Wait until all threads except the current thread have exited (as ++ far as the kernel is concerned). */ ++void support_wait_for_thread_exit (void); ++ + struct support_stack + { + void *stack; +diff --git a/support/support_wait_for_thread_exit.c b/support/support_wait_for_thread_exit.c +new file mode 100644 +index 0000000..658a813 +--- /dev/null ++++ b/support/support_wait_for_thread_exit.c +@@ -0,0 +1,72 @@ ++/* Wait until all threads except the current thread has exited. ++ Copyright (C) 2021 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 ++ ++void ++support_wait_for_thread_exit (void) ++{ ++#ifdef __linux__ ++ DIR *proc_self_task = opendir ("/proc/self/task"); ++ TEST_VERIFY_EXIT (proc_self_task != NULL); ++ ++ while (true) ++ { ++ errno = 0; ++ struct dirent *e = readdir (proc_self_task); ++ if (e == NULL && errno != 0) ++ FAIL_EXIT1 ("readdir: %m"); ++ if (e == NULL) ++ { ++ /* Only the main thread remains. Testing may continue. */ ++ closedir (proc_self_task); ++ return; ++ } ++ ++ if (strcmp (e->d_name, ".") == 0 || strcmp (e->d_name, "..") == 0) ++ continue; ++ ++ int task_tid = atoi (e->d_name); ++ if (task_tid <= 0) ++ FAIL_EXIT1 ("Invalid /proc/self/task entry: %s", e->d_name); ++ ++ if (task_tid == gettid ()) ++ /* The current thread. Keep scanning for other ++ threads. */ ++ continue; ++ ++ /* task_tid does not refer to this thread here, i.e., there is ++ another running thread. */ ++ ++ /* Small timeout to give the thread a chance to exit. */ ++ usleep (50 * 1000); ++ ++ /* Start scanning the directory from the start. */ ++ rewinddir (proc_self_task); ++ } ++#else ++ /* Use a large timeout because we cannot verify that the thread has ++ exited. */ ++ usleep (5 * 1000 * 1000); ++#endif ++} +-- +1.8.3.1 + -- Gitee From 0703419f2447b473c184088649beb171f9eebe98 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 8 Nov 2021 21:07:42 +0800 Subject: [PATCH 20/70] nptl: pthread_kill race condition issues fixed. uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=19193 https://sourceware.org/bugzilla/show_bug.cgi?id=12889 https://sourceware.org/bugzilla/show_bug.cgi?id=28036 https://sourceware.org/bugzilla/show_bug.cgi?id=28363 https://sourceware.org/bugzilla/show_bug.cgi?id=28407 (cherry picked from commit 83aeb85874abee17a312eab44d75484c097ed8a8) --- glibc.spec | 15 +- ...d-deadlock-with-blocked-signals-in-t.patch | 137 ++++++ ...tween-pthread_kill-and-thread-exit-b.patch | 424 ++++++++++++++++++ ...-pthread_mutexattr_getrobust_np-pthr.patch | 37 ++ ...l-must-send-signals-to-a-specific-th.patch | 162 +++++++ ...l-needs-to-return-ESRCH-for-old-prog.patch | 142 ++++++ 6 files changed, 916 insertions(+), 1 deletion(-) create mode 100644 nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch create mode 100644 nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch create mode 100644 nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch create mode 100644 nptl-pthread_kill-must-send-signals-to-a-specific-th.patch create mode 100644 nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch diff --git a/glibc.spec b/glibc.spec index 9361a89..9cc5fc3 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 20 +Release: 21 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -121,6 +121,11 @@ Patch34: x86-64-Use-testl-to-check-__x86_string_control.patch Patch35: AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch Patch36: support-Add-support_wait_for_thread_exit.patch Patch37: nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch +Patch38: nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch +Patch39: nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch +Patch40: nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch +Patch41: nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch +Patch42: nptl-pthread_kill-must-send-signals-to-a-specific-th.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1310,6 +1315,14 @@ fi %endif %changelog +* Mon Nov 8 2021 Qingqing Li - 2.34-21 +- nptl: pthread_kill race condition issues fixed. + uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=19193 + https://sourceware.org/bugzilla/show_bug.cgi?id=12889 + https://sourceware.org/bugzilla/show_bug.cgi?id=28036 + https://sourceware.org/bugzilla/show_bug.cgi?id=28363 + https://sourceware.org/bugzilla/show_bug.cgi?id=28407 + * Thu Nov 4 2021 Qingqing Li - 2.34-20 - nptl: pthread_kill and pthread_cancel return success for satisfy posix standard. diff --git a/nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch b/nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch new file mode 100644 index 0000000..e582b70 --- /dev/null +++ b/nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch @@ -0,0 +1,137 @@ +From 2849e2f53311b66853cb5159b64cba2bddbfb854 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 23 Sep 2021 09:55:54 +0200 +Subject: [PATCH] nptl: Avoid setxid deadlock with blocked signals in thread + exit [BZ #28361] + +As part of the fix for bug 12889, signals are blocked during +thread exit, so that application code cannot run on the thread that +is about to exit. This would cause problems if the application +expected signals to be delivered after the signal handler revealed +the thread to still exist, despite pthread_kill can no longer be used +to send signals to it. However, glibc internally uses the SIGSETXID +signal in a way that is incompatible with signal blocking, due to the +way the setxid handshake delays thread exit until the setxid operation +has completed. With a blocked SIGSETXID, the handshake can never +complete, causing a deadlock. + +As a band-aid, restore the previous handshake protocol by not blocking +SIGSETXID during thread exit. + +The new test sysdeps/pthread/tst-pthread-setuid-loop.c is based on +a downstream test by Martin Osvald. + +Reviewed-by: Carlos O'Donell +Tested-by: Carlos O'Donell +--- + nptl/pthread_create.c | 12 +++++- + sysdeps/pthread/Makefile | 1 + + sysdeps/pthread/tst-pthread-setuid-loop.c | 61 +++++++++++++++++++++++++++++++ + 3 files changed, 72 insertions(+), 2 deletions(-) + create mode 100644 sysdeps/pthread/tst-pthread-setuid-loop.c + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index a559f86..d6ea43a 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -487,8 +487,16 @@ start_thread (void *arg) + + /* This prevents sending a signal from this thread to itself during + its final stages. This must come after the exit call above +- because atexit handlers must not run with signals blocked. */ +- __libc_signal_block_all (NULL); ++ because atexit handlers must not run with signals blocked. ++ ++ Do not block SIGSETXID. The setxid handshake below expects the ++ signal to be delivered. (SIGSETXID cannot run application code, ++ nor does it use pthread_kill.) Reuse the pd->sigmask space for ++ computing the signal mask, to save stack space. */ ++ __sigfillset (&pd->sigmask); ++ __sigdelset (&pd->sigmask, SIGSETXID); ++ INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &pd->sigmask, NULL, ++ __NSIG_BYTES); + + /* Tell __pthread_kill_internal that this thread is about to exit. + If there is a __pthread_kill_internal in progress, this delays +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index 48dba71..d4bd2d4 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -118,6 +118,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-unload \ + tst-unwind-thread \ + tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \ ++ tst-pthread-setuid-loop \ + tst-pthread_cancel-exited \ + tst-pthread_cancel-select-loop \ + tst-pthread_kill-exited \ +diff --git a/sysdeps/pthread/tst-pthread-setuid-loop.c b/sysdeps/pthread/tst-pthread-setuid-loop.c +new file mode 100644 +index 0000000..fda2a49 +--- /dev/null ++++ b/sysdeps/pthread/tst-pthread-setuid-loop.c +@@ -0,0 +1,61 @@ ++/* Test that setuid, pthread_create, thread exit do not deadlock (bug 28361). ++ Copyright (C) 2021 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 ++ ++/* How many threads to launch during each iteration. */ ++enum { threads = 4 }; ++ ++/* How many iterations to perform. This value seems to reproduce ++ bug 28361 in a bout one in three runs. */ ++enum { iterations = 5000 }; ++ ++/* Cache of the real user ID used by setuid_thread. */ ++static uid_t uid; ++ ++/* Start routine for the threads. */ ++static void * ++setuid_thread (void *closure) ++{ ++ TEST_COMPARE (setuid (uid), 0); ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ /* The setxid machinery is still invoked even if the UID is ++ unchanged. (The kernel might reset other credentials as part of ++ the system call.) */ ++ uid = getuid (); ++ ++ for (int i = 0; i < iterations; ++i) ++ { ++ pthread_t thread_ids[threads]; ++ for (int j = 0; j < threads; ++j) ++ thread_ids[j] = xpthread_create (NULL, setuid_thread, NULL); ++ for (int j = 0; j < threads; ++j) ++ xpthread_join (thread_ids[j]); ++ } ++ ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + diff --git a/nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch b/nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch new file mode 100644 index 0000000..3acbe23 --- /dev/null +++ b/nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch @@ -0,0 +1,424 @@ +From 526c3cf11ee9367344b6b15d669e4c3cb461a2be Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 13 Sep 2021 11:06:08 +0200 +Subject: [PATCH] nptl: Fix race between pthread_kill and thread exit (bug + 12889) + +A new thread exit lock and flag are introduced. They are used to +detect that the thread is about to exit or has exited in +__pthread_kill_internal, and the signal is not sent in this case. + +The test sysdeps/pthread/tst-pthread_cancel-select-loop.c is derived +from a downstream test originally written by Marek Polacek. + +Reviewed-by: Adhemerval Zanella +--- + nptl/allocatestack.c | 3 + + nptl/descr.h | 6 ++ + nptl/pthread_create.c | 14 +++ + nptl/pthread_kill.c | 65 +++++++----- + sysdeps/pthread/Makefile | 2 + + sysdeps/pthread/tst-pthread_cancel-select-loop.c | 87 ++++++++++++++++ + sysdeps/pthread/tst-pthread_kill-exiting.c | 123 +++++++++++++++++++++++ + 7 files changed, 275 insertions(+), 25 deletions(-) + create mode 100644 sysdeps/pthread/tst-pthread_cancel-select-loop.c + create mode 100644 sysdeps/pthread/tst-pthread_kill-exiting.c + +diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c +index 0356993..fa81007 100644 +--- a/nptl/allocatestack.c ++++ b/nptl/allocatestack.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + /* Default alignment of stack. */ + #ifndef STACK_ALIGN +@@ -126,6 +127,8 @@ get_cached_stack (size_t *sizep, void **memp) + /* No pending event. */ + result->nextevent = NULL; + ++ result->exiting = false; ++ __libc_lock_init (result->exit_lock); + result->tls_state = (struct tls_internal_t) { 0 }; + + /* Clear the DTV. */ +diff --git a/nptl/descr.h b/nptl/descr.h +index e1c8831..41ee56f 100644 +--- a/nptl/descr.h ++++ b/nptl/descr.h +@@ -395,6 +395,12 @@ struct pthread + PTHREAD_CANCEL_ASYNCHRONOUS). */ + unsigned char canceltype; + ++ /* Used in __pthread_kill_internal to detected a thread that has ++ exited or is about to exit. exit_lock must only be acquired ++ after blocking signals. */ ++ bool exiting; ++ int exit_lock; /* A low-level lock (for use with __libc_lock_init etc). */ ++ + /* Used on strsignal. */ + struct tls_internal_t tls_state; + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index 7607f36..a559f86 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include + +@@ -484,6 +485,19 @@ start_thread (void *arg) + /* This was the last thread. */ + exit (0); + ++ /* This prevents sending a signal from this thread to itself during ++ its final stages. This must come after the exit call above ++ because atexit handlers must not run with signals blocked. */ ++ __libc_signal_block_all (NULL); ++ ++ /* Tell __pthread_kill_internal that this thread is about to exit. ++ If there is a __pthread_kill_internal in progress, this delays ++ the thread exit until the signal has been queued by the kernel ++ (so that the TID used to send it remains valid). */ ++ __libc_lock_lock (pd->exit_lock); ++ pd->exiting = true; ++ __libc_lock_unlock (pd->exit_lock); ++ + #ifndef __ASSUME_SET_ROBUST_LIST + /* If this thread has any robust mutexes locked, handle them now. */ + # if __PTHREAD_MUTEX_HAVE_PREV +diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c +index 5d4c86f..fb7862e 100644 +--- a/nptl/pthread_kill.c ++++ b/nptl/pthread_kill.c +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + #include + #include +@@ -23,37 +24,51 @@ + int + __pthread_kill_internal (pthread_t threadid, int signo) + { +- pid_t tid; + struct pthread *pd = (struct pthread *) threadid; +- + if (pd == THREAD_SELF) +- /* It is a special case to handle raise() implementation after a vfork +- call (which does not update the PD tid field). */ +- tid = INLINE_SYSCALL_CALL (gettid); +- else +- /* Force load of pd->tid into local variable or register. Otherwise +- if a thread exits between ESRCH test and tgkill, we might return +- EINVAL, because pd->tid would be cleared by the kernel. */ +- tid = atomic_forced_read (pd->tid); +- +- int val; +- if (__glibc_likely (tid > 0)) + { +- pid_t pid = __getpid (); +- +- val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo); +- val = (INTERNAL_SYSCALL_ERROR_P (val) +- ? INTERNAL_SYSCALL_ERRNO (val) : 0); ++ /* Use the actual TID from the kernel, so that it refers to the ++ current thread even if called after vfork. There is no ++ signal blocking in this case, so that the signal is delivered ++ immediately, before __pthread_kill_internal returns: a signal ++ sent to the thread itself needs to be delivered ++ synchronously. (It is unclear if Linux guarantees the ++ delivery of all pending signals after unblocking in the code ++ below. POSIX only guarantees delivery of a single signal, ++ which may not be the right one.) */ ++ pid_t tid = INTERNAL_SYSCALL_CALL (gettid); ++ int ret = INTERNAL_SYSCALL_CALL (kill, tid, signo); ++ return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0; + } ++ ++ /* Block all signals, as required by pd->exit_lock. */ ++ sigset_t old_mask; ++ __libc_signal_block_all (&old_mask); ++ __libc_lock_lock (pd->exit_lock); ++ ++ int ret; ++ if (pd->exiting) ++ /* The thread is about to exit (or has exited). Sending the ++ signal is either not observable (the target thread has already ++ blocked signals at this point), or it will fail, or it might be ++ delivered to a new, unrelated thread that has reused the TID. ++ So do not actually send the signal. Do not report an error ++ because the threadid argument is still valid (the thread ID ++ lifetime has not ended), and ESRCH (for example) would be ++ misleading. */ ++ ret = 0; + else +- /* The kernel reports that the thread has exited. POSIX specifies +- the ESRCH error only for the case when the lifetime of a thread +- ID has ended, but calling pthread_kill on such a thread ID is +- undefined in glibc. Therefore, do not treat kernel thread exit +- as an error. */ +- val = 0; ++ { ++ /* Using tgkill is a safety measure. pd->exit_lock ensures that ++ the target thread cannot exit. */ ++ ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), pd->tid, signo); ++ ret = INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0; ++ } ++ ++ __libc_lock_unlock (pd->exit_lock); ++ __libc_signal_restore_set (&old_mask); + +- return val; ++ return ret; + } + + int +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index dedfa0d..48dba71 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -119,7 +119,9 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-unwind-thread \ + tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \ + tst-pthread_cancel-exited \ ++ tst-pthread_cancel-select-loop \ + tst-pthread_kill-exited \ ++ tst-pthread_kill-exiting \ + # tests + + tests-time64 := \ +diff --git a/sysdeps/pthread/tst-pthread_cancel-select-loop.c b/sysdeps/pthread/tst-pthread_cancel-select-loop.c +new file mode 100644 +index 0000000..a620875 +--- /dev/null ++++ b/sysdeps/pthread/tst-pthread_cancel-select-loop.c +@@ -0,0 +1,87 @@ ++/* Test that pthread_cancel succeeds during thread exit. ++ Copyright (C) 2021 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 trigger an internal race condition in ++ pthread_cancel, where the cancellation signal is sent after the ++ thread has begun the cancellation process. This can result in a ++ spurious ESRCH error. For the original bug 12889, the window is ++ quite small, so the bug was not reproduced in every run. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Set to true by timeout_thread_function when the test should ++ terminate. */ ++static bool timeout; ++ ++static void * ++timeout_thread_function (void *unused) ++{ ++ usleep (5 * 1000 * 1000); ++ __atomic_store_n (&timeout, true, __ATOMIC_RELAXED); ++ return NULL; ++} ++ ++/* Used for blocking the select function below. */ ++static int pipe_fds[2]; ++ ++static void * ++canceled_thread_function (void *unused) ++{ ++ while (true) ++ { ++ fd_set rfs; ++ fd_set wfs; ++ fd_set efs; ++ FD_ZERO (&rfs); ++ FD_ZERO (&wfs); ++ FD_ZERO (&efs); ++ FD_SET (pipe_fds[0], &rfs); ++ ++ /* If the cancellation request is recognized early, the thread ++ begins exiting while the cancellation signal arrives. */ ++ select (FD_SETSIZE, &rfs, &wfs, &efs, NULL); ++ } ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ xpipe (pipe_fds); ++ pthread_t thr_timeout = xpthread_create (NULL, timeout_thread_function, NULL); ++ ++ while (!__atomic_load_n (&timeout, __ATOMIC_RELAXED)) ++ { ++ pthread_t thr = xpthread_create (NULL, canceled_thread_function, NULL); ++ xpthread_cancel (thr); ++ TEST_VERIFY (xpthread_join (thr) == PTHREAD_CANCELED); ++ } ++ ++ xpthread_join (thr_timeout); ++ xclose (pipe_fds[0]); ++ xclose (pipe_fds[1]); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/pthread/tst-pthread_kill-exiting.c b/sysdeps/pthread/tst-pthread_kill-exiting.c +new file mode 100644 +index 0000000..f803e94 +--- /dev/null ++++ b/sysdeps/pthread/tst-pthread_kill-exiting.c +@@ -0,0 +1,123 @@ ++/* Test that pthread_kill succeeds during thread exit. ++ Copyright (C) 2021 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 verifies that pthread_kill for a thread that is exiting ++ succeeds (with or without actually delivering the signal). */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Set to true by timeout_thread_function when the test should ++ terminate. */ ++static bool timeout; ++ ++static void * ++timeout_thread_function (void *unused) ++{ ++ usleep (1000 * 1000); ++ __atomic_store_n (&timeout, true, __ATOMIC_RELAXED); ++ return NULL; ++} ++ ++/* Used to synchronize the sending threads with the target thread and ++ main thread. */ ++static pthread_barrier_t barrier_1; ++static pthread_barrier_t barrier_2; ++ ++/* The target thread to which signals are to be sent. */ ++static pthread_t target_thread; ++ ++/* Set by the main thread to true after timeout has been set to ++ true. */ ++static bool exiting; ++ ++static void * ++sender_thread_function (void *unused) ++{ ++ while (true) ++ { ++ /* Wait until target_thread has been initialized. The target ++ thread and main thread participate in this barrier. */ ++ xpthread_barrier_wait (&barrier_1); ++ ++ if (exiting) ++ break; ++ ++ xpthread_kill (target_thread, SIGUSR1); ++ ++ /* Communicate that the signal has been sent. The main thread ++ participates in this barrier. */ ++ xpthread_barrier_wait (&barrier_2); ++ } ++ return NULL; ++} ++ ++static void * ++target_thread_function (void *unused) ++{ ++ target_thread = pthread_self (); ++ xpthread_barrier_wait (&barrier_1); ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ xsignal (SIGUSR1, SIG_IGN); ++ ++ pthread_t thr_timeout = xpthread_create (NULL, timeout_thread_function, NULL); ++ ++ pthread_t threads[4]; ++ xpthread_barrier_init (&barrier_1, NULL, array_length (threads) + 2); ++ xpthread_barrier_init (&barrier_2, NULL, array_length (threads) + 1); ++ ++ for (int i = 0; i < array_length (threads); ++i) ++ threads[i] = xpthread_create (NULL, sender_thread_function, NULL); ++ ++ while (!__atomic_load_n (&timeout, __ATOMIC_RELAXED)) ++ { ++ xpthread_create (NULL, target_thread_function, NULL); ++ ++ /* Wait for the target thread to be set up and signal sending to ++ start. */ ++ xpthread_barrier_wait (&barrier_1); ++ ++ /* Wait for signal sending to complete. */ ++ xpthread_barrier_wait (&barrier_2); ++ ++ xpthread_join (target_thread); ++ } ++ ++ exiting = true; ++ ++ /* Signal the sending threads to exit. */ ++ xpthread_create (NULL, target_thread_function, NULL); ++ xpthread_barrier_wait (&barrier_1); ++ ++ for (int i = 0; i < array_length (threads); ++i) ++ xpthread_join (threads[i]); ++ xpthread_join (thr_timeout); ++ ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + diff --git a/nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch b/nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch new file mode 100644 index 0000000..b92e3c5 --- /dev/null +++ b/nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch @@ -0,0 +1,37 @@ +From f3e664563361dc17530113b3205998d1f19dc4d9 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Tue, 21 Sep 2021 07:12:56 +0200 +Subject: [PATCH] nptl: Fix type of pthread_mutexattr_getrobust_np, + pthread_mutexattr_setrobust_np (bug 28036) + +Reviewed-by: Carlos O'Donell +Tested-by: Carlos O'Donell +--- + sysdeps/nptl/pthread.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h +index f1b7f2b..43146e9 100644 +--- a/sysdeps/nptl/pthread.h ++++ b/sysdeps/nptl/pthread.h +@@ -933,7 +933,7 @@ extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr, + # ifdef __USE_GNU + # ifdef __REDIRECT_NTH + extern int __REDIRECT_NTH (pthread_mutexattr_getrobust_np, +- (pthread_mutex_t *, int *), ++ (pthread_mutexattr_t *, int *), + pthread_mutexattr_getrobust) __nonnull ((1)) + __attribute_deprecated_msg__ ("\ + pthread_mutexattr_getrobust_np is deprecated, use pthread_mutexattr_getrobust"); +@@ -949,7 +949,7 @@ extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr, + # ifdef __USE_GNU + # ifdef __REDIRECT_NTH + extern int __REDIRECT_NTH (pthread_mutexattr_setrobust_np, +- (pthread_mutex_t *, int), ++ (pthread_mutexattr_t *, int), + pthread_mutexattr_setrobust) __nonnull ((1)) + __attribute_deprecated_msg__ ("\ + pthread_mutexattr_setrobust_np is deprecated, use pthread_mutexattr_setrobust"); +-- +1.8.3.1 + diff --git a/nptl-pthread_kill-must-send-signals-to-a-specific-th.patch b/nptl-pthread_kill-must-send-signals-to-a-specific-th.patch new file mode 100644 index 0000000..87683c3 --- /dev/null +++ b/nptl-pthread_kill-must-send-signals-to-a-specific-th.patch @@ -0,0 +1,162 @@ +From eae81d70574e923ce3c59078b8df857ae192efa6 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 1 Oct 2021 18:16:41 +0200 +Subject: [PATCH] nptl: pthread_kill must send signals to a specific thread [BZ + #28407] + +The choice between the kill vs tgkill system calls is not just about +the TID reuse race, but also about whether the signal is sent to the +whole process (and any thread in it) or to a specific thread. + +This was caught by the openposix test suite: + + LTP: openposix test suite - FAIL: SIGUSR1 is member of new thread pendingset. + + +Fixes commit 526c3cf11ee9367344b6b15d669e4c3cb461a2be ("nptl: Fix race +between pthread_kill and thread exit (bug 12889)"). + +Reviewed-by: Carlos O'Donell +Tested-by: Carlos O'Donell +--- + nptl/pthread_kill.c | 4 +- + sysdeps/pthread/Makefile | 1 + + sysdeps/pthread/tst-pthread-raise-blocked-self.c | 92 ++++++++++++++++++++++++ + 3 files changed, 94 insertions(+), 3 deletions(-) + create mode 100644 sysdeps/pthread/tst-pthread-raise-blocked-self.c + +diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c +index a44dc8f..35bf1f9 100644 +--- a/nptl/pthread_kill.c ++++ b/nptl/pthread_kill.c +@@ -40,7 +40,7 @@ __pthread_kill_implementation (pthread_t threadid, int signo, int no_tid) + below. POSIX only guarantees delivery of a single signal, + which may not be the right one.) */ + pid_t tid = INTERNAL_SYSCALL_CALL (gettid); +- int ret = INTERNAL_SYSCALL_CALL (kill, tid, signo); ++ int ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), tid, signo); + return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0; + } + +@@ -59,8 +59,6 @@ __pthread_kill_implementation (pthread_t threadid, int signo, int no_tid) + ret = no_tid; + else + { +- /* Using tgkill is a safety measure. pd->exit_lock ensures that +- the target thread cannot exit. */ + ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), pd->tid, signo); + ret = INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0; + } +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index d4bd2d4..0af9c59 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -121,6 +121,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-pthread-setuid-loop \ + tst-pthread_cancel-exited \ + tst-pthread_cancel-select-loop \ ++ tst-pthread-raise-blocked-self \ + tst-pthread_kill-exited \ + tst-pthread_kill-exiting \ + # tests +diff --git a/sysdeps/pthread/tst-pthread-raise-blocked-self.c b/sysdeps/pthread/tst-pthread-raise-blocked-self.c +new file mode 100644 +index 0000000..128e1a6 +--- /dev/null ++++ b/sysdeps/pthread/tst-pthread-raise-blocked-self.c +@@ -0,0 +1,92 @@ ++/* Test that raise sends signal to current thread even if blocked. ++ Copyright (C) 2021 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 ++ ++/* Used to create a dummy thread ID distinct from all other thread ++ IDs. */ ++static void * ++noop (void *ignored) ++{ ++ return NULL; ++} ++ ++static volatile pthread_t signal_thread; ++ ++static void ++signal_handler (int signo) ++{ ++ signal_thread = pthread_self (); ++} ++ ++/* Used to ensure that waiting_thread has launched and can accept ++ signals. */ ++static pthread_barrier_t barrier; ++ ++static void * ++waiting_thread (void *ignored) ++{ ++ xpthread_barrier_wait (&barrier); ++ pause (); ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ xsignal (SIGUSR1, signal_handler); ++ xpthread_barrier_init (&barrier, NULL, 2); ++ ++ /* Distinct thread ID value to */ ++ pthread_t dummy = xpthread_create (NULL, noop, NULL); ++ signal_thread = dummy; ++ ++ pthread_t helper = xpthread_create (NULL, waiting_thread, NULL); ++ ++ /* Make sure that the thread is running. */ ++ xpthread_barrier_wait (&barrier); ++ ++ /* Block signals on this thread. */ ++ sigset_t set; ++ sigfillset (&set); ++ xpthread_sigmask (SIG_BLOCK, &set, NULL); ++ ++ /* Send the signal to this thread. It must not be delivered. */ ++ raise (SIGUSR1); ++ TEST_VERIFY (signal_thread == dummy); ++ ++ /* Wait a bit to give a chance for signal delivery (increases ++ chances of failure with bug 28407). */ ++ usleep (50 * 1000); ++ ++ /* Unblocking should cause synchronous delivery of the signal. */ ++ xpthread_sigmask (SIG_UNBLOCK, &set, NULL); ++ TEST_VERIFY (signal_thread == pthread_self ()); ++ ++ xpthread_cancel (helper); ++ xpthread_join (helper); ++ xpthread_join (dummy); ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + diff --git a/nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch b/nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch new file mode 100644 index 0000000..d52abb8 --- /dev/null +++ b/nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch @@ -0,0 +1,142 @@ +From 95dba35bf05e4a5d69dfae5e9c9d4df3646a7f93 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 20 Sep 2021 14:56:08 +0200 +Subject: [PATCH] nptl: pthread_kill needs to return ESRCH for old programs + (bug 19193) + +The fix for bug 19193 breaks some old applications which appear +to use pthread_kill to probe if a thread is still running, something +that is not supported by POSIX. +--- + nptl/pthread_kill.c | 37 ++++++++++++++++++++++++------- + sysdeps/pthread/tst-pthread_kill-exited.c | 21 ++++++++++++++++-- + 2 files changed, 48 insertions(+), 10 deletions(-) + +diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c +index fb7862e..a44dc8f 100644 +--- a/nptl/pthread_kill.c ++++ b/nptl/pthread_kill.c +@@ -21,8 +21,11 @@ + #include + #include + +-int +-__pthread_kill_internal (pthread_t threadid, int signo) ++/* Sends SIGNO to THREADID. If the thread is about to exit or has ++ already exited on the kernel side, return NO_TID. Otherwise return ++ 0 or an error code. */ ++static int ++__pthread_kill_implementation (pthread_t threadid, int signo, int no_tid) + { + struct pthread *pd = (struct pthread *) threadid; + if (pd == THREAD_SELF) +@@ -52,11 +55,8 @@ __pthread_kill_internal (pthread_t threadid, int signo) + signal is either not observable (the target thread has already + blocked signals at this point), or it will fail, or it might be + delivered to a new, unrelated thread that has reused the TID. +- So do not actually send the signal. Do not report an error +- because the threadid argument is still valid (the thread ID +- lifetime has not ended), and ESRCH (for example) would be +- misleading. */ +- ret = 0; ++ So do not actually send the signal. */ ++ ret = no_tid; + else + { + /* Using tgkill is a safety measure. pd->exit_lock ensures that +@@ -72,6 +72,15 @@ __pthread_kill_internal (pthread_t threadid, int signo) + } + + int ++__pthread_kill_internal (pthread_t threadid, int signo) ++{ ++ /* Do not report an error in the no-tid case because the threadid ++ argument is still valid (the thread ID lifetime has not ended), ++ and ESRCH (for example) would be misleading. */ ++ return __pthread_kill_implementation (threadid, signo, 0); ++} ++ ++int + __pthread_kill (pthread_t threadid, int signo) + { + /* Disallow sending the signal we use for cancellation, timers, +@@ -81,6 +90,7 @@ __pthread_kill (pthread_t threadid, int signo) + + return __pthread_kill_internal (threadid, signo); + } ++ + /* Some architectures (for instance arm) might pull raise through libgcc, so + avoid the symbol version if it ends up being used on ld.so. */ + #if !IS_IN(rtld) +@@ -88,6 +98,17 @@ libc_hidden_def (__pthread_kill) + versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34); + + # if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) +-compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0); ++/* Variant which returns ESRCH in the no-TID case, for backwards ++ compatibility. */ ++int ++attribute_compat_text_section ++__pthread_kill_esrch (pthread_t threadid, int signo) ++{ ++ if (__is_internal_signal (signo)) ++ return EINVAL; ++ ++ return __pthread_kill_implementation (threadid, signo, ESRCH); ++} ++compat_symbol (libc, __pthread_kill_esrch, pthread_kill, GLIBC_2_0); + # endif + #endif +diff --git a/sysdeps/pthread/tst-pthread_kill-exited.c b/sysdeps/pthread/tst-pthread_kill-exited.c +index 7575fb6..a2fddad 100644 +--- a/sysdeps/pthread/tst-pthread_kill-exited.c ++++ b/sysdeps/pthread/tst-pthread_kill-exited.c +@@ -16,11 +16,15 @@ + License along with the GNU C Library; if not, see + . */ + +-/* This test verifies that pthread_kill returns 0 (and not ESRCH) for +- a thread that has exited on the kernel side. */ ++/* This test verifies that the default pthread_kill returns 0 (and not ++ ESRCH) for a thread that has exited on the kernel side. */ + ++#include ++#include ++#include + #include + #include ++#include + #include + #include + +@@ -30,6 +34,12 @@ noop_thread (void *closure) + return NULL; + } + ++#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC ++extern __typeof (pthread_kill) compat_pthread_kill; ++compat_symbol_reference (libpthread, compat_pthread_kill, pthread_kill, ++ GLIBC_2_0); ++#endif ++ + static int + do_test (void) + { +@@ -37,7 +47,14 @@ do_test (void) + + support_wait_for_thread_exit (); + ++ /* NB: Always uses the default symbol due to separate compilation. */ + xpthread_kill (thr, SIGUSR1); ++ ++#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC ++ /* Old binaries need the non-conforming ESRCH error code. */ ++ TEST_COMPARE (compat_pthread_kill (thr, SIGUSR1), ESRCH); ++#endif ++ + xpthread_join (thr); + + return 0; +-- +1.8.3.1 + -- Gitee From 224e3c77ad445225fe179078e98666351bcf9fe1 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Tue, 9 Nov 2021 15:28:35 +0800 Subject: [PATCH 21/70] iconvconfig: Fix behaviour with --prefix (cherry picked from commit 2b77a61d3e0765d9b5545e35002b1b23eb7b4b83) --- glibc.spec | 7 +- ...g-Fix-behaviour-with-prefix-BZ-28199.patch | 123 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch diff --git a/glibc.spec b/glibc.spec index 9cc5fc3..a9687e0 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 21 +Release: 22 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -126,6 +126,7 @@ Patch39: nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch Patch40: nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch Patch41: nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch Patch42: nptl-pthread_kill-must-send-signals-to-a-specific-th.patch +Patch43: iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1315,6 +1316,10 @@ fi %endif %changelog +* Tue Nov 9 2021 Qingqing Li - 2.34-22 +- iconvconfig: Fix behaviour with --prefix + uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=28199 + * Mon Nov 8 2021 Qingqing Li - 2.34-21 - nptl: pthread_kill race condition issues fixed. uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=19193 diff --git a/iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch b/iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch new file mode 100644 index 0000000..6df7a82 --- /dev/null +++ b/iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch @@ -0,0 +1,123 @@ +From 43cea6d5652b6b9e61ac6ecc69419c909b504f47 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Mon, 13 Sep 2021 20:48:35 +0530 +Subject: [PATCH] iconvconfig: Fix behaviour with --prefix [BZ #28199] + +The consolidation of configuration parsing broke behaviour with +--prefix, where the prefix bled into the modules cache. Accept a +prefix which, when non-NULL, is prepended to the path when looking for +configuration files but only the original directory is added to the +modules cache. + +This has no effect on the codegen of gconv_conf since it passes NULL. + +Reported-by: Patrick McCarty +Reported-by: Michael Hudson-Doyle +Reviewed-by: Andreas Schwab +--- + iconv/gconv_conf.c | 2 +- + iconv/gconv_parseconfdir.h | 22 +++++++++++++++------- + iconv/iconvconfig.c | 16 ++++++++++++---- + 3 files changed, 28 insertions(+), 12 deletions(-) + +diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c +index 09ffe02..077082a 100644 +--- a/iconv/gconv_conf.c ++++ b/iconv/gconv_conf.c +@@ -477,7 +477,7 @@ __gconv_read_conf (void) + __gconv_get_path (); + + for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt) +- gconv_parseconfdir (__gconv_path_elem[cnt].name, ++ gconv_parseconfdir (NULL, __gconv_path_elem[cnt].name, + __gconv_path_elem[cnt].len); + #endif + +diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h +index 2f06268..a586268 100644 +--- a/iconv/gconv_parseconfdir.h ++++ b/iconv/gconv_parseconfdir.h +@@ -39,7 +39,6 @@ + /* Name of the file containing the module information in the directories + along the path. */ + static const char gconv_conf_filename[] = "gconv-modules"; +-static const char gconv_conf_dirname[] = "gconv-modules.d"; + + static void add_alias (char *); + static void add_module (char *, const char *, size_t, int); +@@ -110,19 +109,28 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len) + return true; + } + ++/* Prefix DIR (with length DIR_LEN) with PREFIX if the latter is non-NULL and ++ parse configuration in it. */ ++ + static __always_inline bool +-gconv_parseconfdir (const char *dir, size_t dir_len) ++gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len) + { +- /* No slash needs to be inserted between dir and gconv_conf_filename; +- dir already ends in a slash. */ +- char *buf = malloc (dir_len + sizeof (gconv_conf_dirname)); ++ /* No slash needs to be inserted between dir and gconv_conf_filename; dir ++ already ends in a slash. The additional 2 is to accommodate the ".d" ++ when looking for configuration files in gconv-modules.d. */ ++ size_t buflen = dir_len + sizeof (gconv_conf_filename) + 2; ++ char *buf = malloc (buflen + (prefix != NULL ? strlen (prefix) : 0)); ++ char *cp = buf; + bool found = false; + + if (buf == NULL) + return false; + +- char *cp = mempcpy (mempcpy (buf, dir, dir_len), gconv_conf_filename, +- sizeof (gconv_conf_filename)); ++ if (prefix != NULL) ++ cp = stpcpy (cp, prefix); ++ ++ cp = mempcpy (mempcpy (cp, dir, dir_len), gconv_conf_filename, ++ sizeof (gconv_conf_filename)); + + /* Read the gconv-modules configuration file first. */ + found = read_conf_file (buf, dir, dir_len); +diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c +index fd61cf2..a89b62e 100644 +--- a/iconv/iconvconfig.c ++++ b/iconv/iconvconfig.c +@@ -652,13 +652,21 @@ add_module (char *rp, const char *directory, + static int + handle_dir (const char *dir) + { ++ char *newp = NULL; + size_t dirlen = strlen (dir); + bool found = false; + +- char *fulldir = xasprintf ("%s%s%s", dir[0] == '/' ? prefix : "", +- dir, dir[dirlen - 1] != '/' ? "/" : ""); ++ /* End directory path with a '/' if it doesn't already. */ ++ if (dir[dirlen - 1] != '/') ++ { ++ newp = xmalloc (dirlen + 2); ++ memcpy (newp, dir, dirlen); ++ newp[dirlen++] = '/'; ++ newp[dirlen] = '\0'; ++ dir = newp; ++ } + +- found = gconv_parseconfdir (fulldir, strlen (fulldir)); ++ found = gconv_parseconfdir (dir[0] == '/' ? prefix : NULL, dir, dirlen); + + if (!found) + { +@@ -670,7 +678,7 @@ handle_dir (const char *dir) + "configuration files with names ending in .conf."); + } + +- free (fulldir); ++ free (newp); + + return found ? 0 : 1; + } +-- +1.8.3.1 + -- Gitee From ef9fb4112e60ccd03e7bb2735160fc8ddb904371 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Wed, 10 Nov 2021 11:51:41 +0800 Subject: [PATCH 22/70] gconv: Do not emit spurious NUL character in ISO-2022-JP-3, this also fix CVE-2021-43396. (cherry picked from commit 3ab2b7b71b179a0de5b079c0c24b85172b847805) --- ...t-spurious-NUL-character-in-ISO-2022.patch | 185 ++++++++++++++++++ glibc.spec | 8 +- 2 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch diff --git a/gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch b/gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch new file mode 100644 index 0000000..2c546ea --- /dev/null +++ b/gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch @@ -0,0 +1,185 @@ +From ff012870b2c02a62598c04daa1e54632e020fd7d Mon Sep 17 00:00:00 2001 +From: Nikita Popov +Date: Tue, 2 Nov 2021 13:21:42 +0500 +Subject: [PATCH] gconv: Do not emit spurious NUL character in ISO-2022-JP-3 + (bug 28524) + +Bugfix 27256 has introduced another issue: +In conversion from ISO-2022-JP-3 encoding, it is possible +to force iconv to emit extra NUL character on internal state reset. +To do this, it is sufficient to feed iconv with escape sequence +which switches active character set. +The simplified check 'data->__statep->__count != ASCII_set' +introduced by the aforementioned bugfix picks that case and +behaves as if '\0' character has been queued thus emitting it. + +To eliminate this issue, these steps are taken: +* Restore original condition +'(data->__statep->__count & ~7) != ASCII_set'. +It is necessary since bits 0-2 may contain +number of buffered input characters. +* Check that queued character is not NUL. +Similar step is taken for main conversion loop. + +Bundled test case follows following logic: +* Try to convert ISO-2022-JP-3 escape sequence +switching active character set +* Reset internal state by providing NULL as input buffer +* Ensure that nothing has been converted. + +Signed-off-by: Nikita Popov +--- + iconvdata/Makefile | 5 +++- + iconvdata/bug-iconv15.c | 60 +++++++++++++++++++++++++++++++++++++++ + iconvdata/iso-2022-jp-3.c | 28 ++++++++++++------ + 3 files changed, 84 insertions(+), 9 deletions(-) + create mode 100644 iconvdata/bug-iconv15.c + +diff --git a/iconvdata/Makefile b/iconvdata/Makefile +index c216f959..d5507a04 100644 +--- a/iconvdata/Makefile ++++ b/iconvdata/Makefile +@@ -1,4 +1,5 @@ + # Copyright (C) 1997-2021 Free Software Foundation, Inc. ++# Copyright (C) The GNU Toolchain Authors. + # This file is part of the GNU C Library. + + # The GNU C Library is free software; you can redistribute it and/or +@@ -74,7 +75,7 @@ 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 tst-iconv-big5-hkscs-to-2ucs4 \ +- bug-iconv13 bug-iconv14 ++ bug-iconv13 bug-iconv14 bug-iconv15 + ifeq ($(have-thread-library),yes) + tests += bug-iconv3 + endif +@@ -327,6 +328,8 @@ $(objpfx)bug-iconv12.out: $(addprefix $(objpfx), $(gconv-modules)) \ + $(addprefix $(objpfx),$(modules.so)) + $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \ + $(addprefix $(objpfx),$(modules.so)) ++$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \ ++ $(addprefix $(objpfx),$(modules.so)) + + $(objpfx)iconv-test.out: run-iconv-test.sh \ + $(addprefix $(objpfx), $(gconv-modules)) \ +diff --git a/iconvdata/bug-iconv15.c b/iconvdata/bug-iconv15.c +new file mode 100644 +index 00000000..cc04bd03 +--- /dev/null ++++ b/iconvdata/bug-iconv15.c +@@ -0,0 +1,60 @@ ++/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv ++ may emit spurious NUL character on state reset. ++ Copyright (C) The GNU Toolchain Authors. ++ 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) ++{ ++ char in[] = "\x1b(I"; ++ char *inbuf = in; ++ size_t inleft = sizeof (in) - 1; ++ char out[1]; ++ char *outbuf = out; ++ size_t outleft = sizeof (out); ++ iconv_t cd; ++ ++ cd = iconv_open ("UTF8", "ISO-2022-JP-3"); ++ TEST_VERIFY_EXIT (cd != (iconv_t) -1); ++ ++ /* First call to iconv should alter internal state. ++ Now, JISX0201_Kana_set is selected and ++ state value != ASCII_set. */ ++ TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1); ++ ++ /* No bytes should have been added to ++ the output buffer at this point. */ ++ TEST_VERIFY (outbuf == out); ++ TEST_VERIFY (outleft == sizeof (out)); ++ ++ /* Second call shall emit spurious NUL character in unpatched glibc. */ ++ TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1); ++ ++ /* No characters are expected to be produced. */ ++ TEST_VERIFY (outbuf == out); ++ TEST_VERIFY (outleft == sizeof (out)); ++ ++ TEST_VERIFY_EXIT (iconv_close (cd) != -1); ++ ++ return 0; ++} ++ ++#include +diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c +index c8ba88cd..5fc0c0f7 100644 +--- a/iconvdata/iso-2022-jp-3.c ++++ b/iconvdata/iso-2022-jp-3.c +@@ -1,5 +1,6 @@ + /* Conversion module for ISO-2022-JP-3. + Copyright (C) 1998-2021 Free Software Foundation, Inc. ++ Copyright (C) The GNU Toolchain Authors. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998, + and Bruno Haible , 2002. +@@ -81,20 +82,31 @@ enum + the output state to the initial state. This has to be done during the + flushing. */ + #define EMIT_SHIFT_TO_INIT \ +- if (data->__statep->__count != ASCII_set) \ ++ if ((data->__statep->__count & ~7) != ASCII_set) \ + { \ + if (FROM_DIRECTION) \ + { \ +- if (__glibc_likely (outbuf + 4 <= outend)) \ ++ uint32_t ch = data->__statep->__count >> 6; \ ++ \ ++ if (__glibc_unlikely (ch != 0)) \ + { \ +- /* Write out the last character. */ \ +- *((uint32_t *) outbuf) = data->__statep->__count >> 6; \ +- outbuf += sizeof (uint32_t); \ +- data->__statep->__count = ASCII_set; \ ++ if (__glibc_likely (outbuf + 4 <= outend)) \ ++ { \ ++ /* Write out the last character. */ \ ++ put32u (outbuf, ch); \ ++ outbuf += 4; \ ++ data->__statep->__count &= 7; \ ++ data->__statep->__count |= ASCII_set; \ ++ } \ ++ else \ ++ /* We don't have enough room in the output buffer. */ \ ++ status = __GCONV_FULL_OUTPUT; \ + } \ + else \ +- /* We don't have enough room in the output buffer. */ \ +- status = __GCONV_FULL_OUTPUT; \ ++ { \ ++ data->__statep->__count &= 7; \ ++ data->__statep->__count |= ASCII_set; \ ++ } \ + } \ + else \ + { \ +-- +2.23.0 + diff --git a/glibc.spec b/glibc.spec index a9687e0..a8b1ad5 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 22 +Release: 23 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -127,6 +127,7 @@ Patch40: nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch Patch41: nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch Patch42: nptl-pthread_kill-must-send-signals-to-a-specific-th.patch Patch43: iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch +Patch44: gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1316,6 +1317,11 @@ fi %endif %changelog +* Wed Nov 10 2021 Qingqing Li - 2.34-23 +- gconv: Do not emit spurious NUL character in ISO-2022-JP-3, + this also fix CVE-2021-43396. + uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=28524 + * Tue Nov 9 2021 Qingqing Li - 2.34-22 - iconvconfig: Fix behaviour with --prefix uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=28199 -- Gitee From 753f2695f1227e80c987dc5806c43a125f378609 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 15 Nov 2021 15:38:31 +0800 Subject: [PATCH 23/70] elf: fix ld.so crash while loading a DSO with a read-only dynamic section (cherry picked from commit 35e1891d7115354b362c1c6c122c085bb880d6fb) --- ...erriding-recipe-for-.-tst-ro-dynamic.patch | 34 ++ ...ck-between-pthread_create-and-ctors-.patch | 482 ++++++++++++++++ glibc.spec | 10 +- ...-bootstrap_map.l_ld_readonly-BZ-2834.patch | 124 +++++ ..._RO_DYN_SECTION-with-dl_relocate_ld-.patch | 515 ++++++++++++++++++ 5 files changed, 1164 insertions(+), 1 deletion(-) create mode 100644 Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch create mode 100644 elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch create mode 100644 ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch create mode 100644 ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch diff --git a/Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch b/Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch new file mode 100644 index 0000000..60576f4 --- /dev/null +++ b/Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch @@ -0,0 +1,34 @@ +From 15e6d6785ac2935bb963506b47a37b3d1f728952 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Fri, 24 Sep 2021 08:56:42 -0700 +Subject: [PATCH] Avoid warning: overriding recipe for + .../tst-ro-dynamic-mod.so + +Add tst-ro-dynamic-mod to modules-names-nobuild to avoid + +../Makerules:767: warning: ignoring old recipe for target '.../elf/tst-ro-dynamic-mod.so' + +This updates BZ #28340 fix. +--- + elf/Makefile | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/elf/Makefile b/elf/Makefile +index 0cdccaa..26986c0 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -402,8 +402,9 @@ endif + modules-execstack-yes = tst-execstack-mod + extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) + +-# filtmod1.so, tst-big-note-lib.so have special rules. +-modules-names-nobuild := filtmod1 tst-big-note-lib ++# filtmod1.so, tst-big-note-lib.so, tst-ro-dynamic-mod.so have special ++# rules. ++modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod + + tests += $(tests-static) + +-- +1.8.3.1 + diff --git a/elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch b/elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch new file mode 100644 index 0000000..da70902 --- /dev/null +++ b/elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch @@ -0,0 +1,482 @@ +From 83b5323261bb72313bffcf37476c1b8f0847c736 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy +Date: Wed, 15 Sep 2021 15:16:19 +0100 +Subject: [PATCH] elf: Avoid deadlock between pthread_create and ctors [BZ + #28357] + +The fix for bug 19329 caused a regression such that pthread_create can +deadlock when concurrent ctors from dlopen are waiting for it to finish. +Use a new GL(dl_load_tls_lock) in pthread_create that is not taken +around ctors in dlopen. + +The new lock is also used in __tls_get_addr instead of GL(dl_load_lock). + +The new lock is held in _dl_open_worker and _dl_close_worker around +most of the logic before/after the init/fini routines. When init/fini +routines are running then TLS is in a consistent, usable state. +In _dl_open_worker the new lock requires catching and reraising dlopen +failures that happen in the critical section. + +The new lock is reinitialized in a fork child, to keep the existing +behaviour and it is kept recursive in case malloc interposition or TLS +access from signal handlers can retake it. It is not obvious if this +is necessary or helps, but avoids changing the preexisting behaviour. + +The new lock may be more appropriate for dl_iterate_phdr too than +GL(dl_load_write_lock), since TLS state of an incompletely loaded +module may be accessed. If the new lock can replace the old one, +that can be a separate change. + +Fixes bug 28357. + +Reviewed-by: Adhemerval Zanella +--- + elf/dl-close.c | 6 ++ + elf/dl-open.c | 35 +++++++++++- + elf/dl-support.c | 7 +++ + elf/dl-tls.c | 16 +++--- + elf/rtld.c | 1 + + posix/fork.c | 3 + + sysdeps/generic/ldsodefs.h | 9 ++- + sysdeps/pthread/Makefile | 10 +++- + sysdeps/pthread/tst-create1.c | 119 +++++++++++++++++++++++++++++++++++++++ + sysdeps/pthread/tst-create1mod.c | 41 ++++++++++++++ + 10 files changed, 235 insertions(+), 12 deletions(-) + create mode 100644 sysdeps/pthread/tst-create1.c + create mode 100644 sysdeps/pthread/tst-create1mod.c + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 93ff5c9..cfe0f1c 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -549,6 +549,9 @@ _dl_close_worker (struct link_map *map, bool force) + size_t tls_free_end; + tls_free_start = tls_free_end = NO_TLS_OFFSET; + ++ /* Protects global and module specitic TLS state. */ ++ __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); ++ + /* We modify the list of loaded objects. */ + __rtld_lock_lock_recursive (GL(dl_load_write_lock)); + +@@ -784,6 +787,9 @@ _dl_close_worker (struct link_map *map, bool force) + GL(dl_tls_static_used) = tls_free_start; + } + ++ /* TLS is cleaned up for the unloaded modules. */ ++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); ++ + #ifdef SHARED + /* Auditing checkpoint: we have deleted all objects. */ + if (__glibc_unlikely (do_audit)) +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 5295e93..6ea5dd2 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -66,6 +66,9 @@ struct dl_open_args + libc_map value in the namespace in case of a dlopen failure. */ + bool libc_already_loaded; + ++ /* Set to true if the end of dl_open_worker_begin was reached. */ ++ bool worker_continue; ++ + /* Original parameters to the program and the current environment. */ + int argc; + char **argv; +@@ -482,7 +485,7 @@ call_dl_init (void *closure) + } + + static void +-dl_open_worker (void *a) ++dl_open_worker_begin (void *a) + { + struct dl_open_args *args = a; + const char *file = args->file; +@@ -774,6 +777,36 @@ dl_open_worker (void *a) + _dl_call_libc_early_init (libc_map, false); + } + ++ args->worker_continue = true; ++} ++ ++static void ++dl_open_worker (void *a) ++{ ++ struct dl_open_args *args = a; ++ ++ args->worker_continue = false; ++ ++ { ++ /* Protects global and module specific TLS state. */ ++ __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); ++ ++ struct dl_exception ex; ++ int err = _dl_catch_exception (&ex, dl_open_worker_begin, args); ++ ++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); ++ ++ if (__glibc_unlikely (ex.errstring != NULL)) ++ /* Reraise the error. */ ++ _dl_signal_exception (err, &ex, NULL); ++ } ++ ++ if (!args->worker_continue) ++ return; ++ ++ int mode = args->mode; ++ struct link_map *new = args->map; ++ + /* Run the initializer functions of new objects. Temporarily + disable the exception handler, so that lazy binding failures are + fatal. */ +diff --git a/elf/dl-support.c b/elf/dl-support.c +index 02e2ed7..d99c1f1 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -228,6 +228,13 @@ __rtld_lock_define_initialized_recursive (, _dl_load_lock) + list of loaded objects while an object is added to or removed from + that list. */ + __rtld_lock_define_initialized_recursive (, _dl_load_write_lock) ++ /* This lock protects global and module specific TLS related data. ++ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation), ++ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are ++ accessed and when TLS related relocations are processed for a ++ module. It was introduced to keep pthread_create accessing TLS ++ state that is being set up. */ ++__rtld_lock_define_initialized_recursive (, _dl_load_tls_lock) + + + #ifdef HAVE_AUX_VECTOR +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index d554ae4..9260d2d 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -532,7 +532,7 @@ _dl_allocate_tls_init (void *result) + size_t maxgen = 0; + + /* Protects global dynamic TLS related state. */ +- __rtld_lock_lock_recursive (GL(dl_load_lock)); ++ __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); + + /* Check if the current dtv is big enough. */ + if (dtv[-1].counter < GL(dl_tls_max_dtv_idx)) +@@ -606,7 +606,7 @@ _dl_allocate_tls_init (void *result) + listp = listp->next; + assert (listp != NULL); + } +- __rtld_lock_unlock_recursive (GL(dl_load_lock)); ++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); + + /* The DTV version is up-to-date now. */ + dtv[0].counter = maxgen; +@@ -745,7 +745,7 @@ _dl_update_slotinfo (unsigned long int req_modid) + + Here the dtv needs to be updated to new_gen generation count. + +- This code may be called during TLS access when GL(dl_load_lock) ++ This code may be called during TLS access when GL(dl_load_tls_lock) + is not held. In that case the user code has to synchronize with + dlopen and dlclose calls of relevant modules. A module m is + relevant if the generation of m <= new_gen and dlclose of m is +@@ -867,11 +867,11 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map) + if (__glibc_unlikely (the_map->l_tls_offset + != FORCED_DYNAMIC_TLS_OFFSET)) + { +- __rtld_lock_lock_recursive (GL(dl_load_lock)); ++ __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); + if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET)) + { + the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET; +- __rtld_lock_unlock_recursive (GL(dl_load_lock)); ++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); + } + else if (__glibc_likely (the_map->l_tls_offset + != FORCED_DYNAMIC_TLS_OFFSET)) +@@ -883,7 +883,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map) + #else + # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" + #endif +- __rtld_lock_unlock_recursive (GL(dl_load_lock)); ++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); + + dtv[GET_ADDR_MODULE].pointer.to_free = NULL; + dtv[GET_ADDR_MODULE].pointer.val = p; +@@ -891,7 +891,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map) + return (char *) p + GET_ADDR_OFFSET; + } + else +- __rtld_lock_unlock_recursive (GL(dl_load_lock)); ++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); + } + struct dtv_pointer result = allocate_and_init (the_map); + dtv[GET_ADDR_MODULE].pointer = result; +@@ -962,7 +962,7 @@ _dl_tls_get_addr_soft (struct link_map *l) + return NULL; + + dtv_t *dtv = THREAD_DTV (); +- /* This may be called without holding the GL(dl_load_lock). Reading ++ /* This may be called without holding the GL(dl_load_tls_lock). Reading + arbitrary gen value is fine since this is best effort code. */ + size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); + if (__glibc_unlikely (dtv[0].counter != gen)) +diff --git a/elf/rtld.c b/elf/rtld.c +index 8d2bba3..9642eb9 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -322,6 +322,7 @@ struct rtld_global _rtld_global = + #ifdef _LIBC_REENTRANT + ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, + ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, ++ ._dl_load_tls_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, + #endif + ._dl_nns = 1, + ._dl_ns = +diff --git a/posix/fork.c b/posix/fork.c +index c471f7b..021691b 100644 +--- a/posix/fork.c ++++ b/posix/fork.c +@@ -99,6 +99,9 @@ __libc_fork (void) + /* Reset the lock the dynamic loader uses to protect its data. */ + __rtld_lock_initialize (GL(dl_load_lock)); + ++ /* Reset the lock protecting dynamic TLS related data. */ ++ __rtld_lock_initialize (GL(dl_load_tls_lock)); ++ + reclaim_stacks (); + + /* Run the handlers registered for the child. */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index d49529d..9ec1511 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -369,6 +369,13 @@ struct rtld_global + list of loaded objects while an object is added to or removed + from that list. */ + __rtld_lock_define_recursive (EXTERN, _dl_load_write_lock) ++ /* This lock protects global and module specific TLS related data. ++ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation), ++ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are ++ accessed and when TLS related relocations are processed for a ++ module. It was introduced to keep pthread_create accessing TLS ++ state that is being set up. */ ++ __rtld_lock_define_recursive (EXTERN, _dl_load_tls_lock) + + /* Incremented whenever something may have been added to dl_loaded. */ + EXTERN unsigned long long _dl_load_adds; +@@ -1268,7 +1275,7 @@ extern int _dl_scope_free (void *) attribute_hidden; + + /* Add module to slot information data. If DO_ADD is false, only the + required memory is allocated. Must be called with GL +- (dl_load_lock) acquired. If the function has already been called ++ (dl_load_tls_lock) acquired. If the function has already been called + for the link map L with !do_add, then this function will not raise + an exception, otherwise it is possible that it encounters a memory + allocation failure. */ +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index 0af9c59..df8943f 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -152,15 +152,17 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx6 tst-cancelx8 tst-cancelx9 \ + tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 + + ifeq ($(build-shared),yes) +-tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1 ++tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1 tst-create1 + tests-nolibpthread += tst-fini1 + endif + + modules-names += tst-atfork2mod tst-tls4moda tst-tls4modb \ +- tst-_res1mod1 tst-_res1mod2 tst-fini1mod ++ tst-_res1mod1 tst-_res1mod2 tst-fini1mod \ ++ tst-create1mod + test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) + + tst-atfork2mod.so-no-z-defs = yes ++tst-create1mod.so-no-z-defs = yes + + ifeq ($(build-shared),yes) + # Build all the modules even when not actually running test programs. +@@ -279,4 +281,8 @@ LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so + + CFLAGS-tst-unwind-thread.c += -funwind-tables + ++LDFLAGS-tst-create1 = -Wl,-export-dynamic ++$(objpfx)tst-create1: $(shared-thread-library) ++$(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so ++ + endif +diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c +new file mode 100644 +index 0000000..932586c +--- /dev/null ++++ b/sysdeps/pthread/tst-create1.c +@@ -0,0 +1,119 @@ ++/* Verify that pthread_create does not deadlock when ctors take locks. ++ Copyright (C) 2021 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 ++ ++/* ++Check if ctor and pthread_create deadlocks in ++ ++thread 1: dlopen -> ctor -> lock(user_lock) ++thread 2: lock(user_lock) -> pthread_create ++ ++or in ++ ++thread 1: dlclose -> dtor -> lock(user_lock) ++thread 2: lock(user_lock) -> pthread_create ++*/ ++ ++static pthread_barrier_t bar_ctor; ++static pthread_barrier_t bar_dtor; ++static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER; ++ ++void ++ctor (void) ++{ ++ xpthread_barrier_wait (&bar_ctor); ++ dprintf (1, "thread 1: in ctor: started.\n"); ++ xpthread_mutex_lock (&user_lock); ++ dprintf (1, "thread 1: in ctor: locked user_lock.\n"); ++ xpthread_mutex_unlock (&user_lock); ++ dprintf (1, "thread 1: in ctor: unlocked user_lock.\n"); ++ dprintf (1, "thread 1: in ctor: done.\n"); ++} ++ ++void ++dtor (void) ++{ ++ xpthread_barrier_wait (&bar_dtor); ++ dprintf (1, "thread 1: in dtor: started.\n"); ++ xpthread_mutex_lock (&user_lock); ++ dprintf (1, "thread 1: in dtor: locked user_lock.\n"); ++ xpthread_mutex_unlock (&user_lock); ++ dprintf (1, "thread 1: in dtor: unlocked user_lock.\n"); ++ dprintf (1, "thread 1: in dtor: done.\n"); ++} ++ ++static void * ++thread3 (void *a) ++{ ++ dprintf (1, "thread 3: started.\n"); ++ dprintf (1, "thread 3: done.\n"); ++ return 0; ++} ++ ++static void * ++thread2 (void *a) ++{ ++ pthread_t t3; ++ dprintf (1, "thread 2: started.\n"); ++ ++ xpthread_mutex_lock (&user_lock); ++ dprintf (1, "thread 2: locked user_lock.\n"); ++ xpthread_barrier_wait (&bar_ctor); ++ t3 = xpthread_create (0, thread3, 0); ++ xpthread_mutex_unlock (&user_lock); ++ dprintf (1, "thread 2: unlocked user_lock.\n"); ++ xpthread_join (t3); ++ ++ xpthread_mutex_lock (&user_lock); ++ dprintf (1, "thread 2: locked user_lock.\n"); ++ xpthread_barrier_wait (&bar_dtor); ++ t3 = xpthread_create (0, thread3, 0); ++ xpthread_mutex_unlock (&user_lock); ++ dprintf (1, "thread 2: unlocked user_lock.\n"); ++ xpthread_join (t3); ++ ++ dprintf (1, "thread 2: done.\n"); ++ return 0; ++} ++ ++static void ++thread1 (void) ++{ ++ dprintf (1, "thread 1: started.\n"); ++ xpthread_barrier_init (&bar_ctor, NULL, 2); ++ xpthread_barrier_init (&bar_dtor, NULL, 2); ++ pthread_t t2 = xpthread_create (0, thread2, 0); ++ void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL); ++ dprintf (1, "thread 1: dlopen done.\n"); ++ xdlclose (p); ++ dprintf (1, "thread 1: dlclose done.\n"); ++ xpthread_join (t2); ++ dprintf (1, "thread 1: done.\n"); ++} ++ ++static int ++do_test (void) ++{ ++ thread1 (); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/pthread/tst-create1mod.c b/sysdeps/pthread/tst-create1mod.c +new file mode 100644 +index 0000000..62c9006 +--- /dev/null ++++ b/sysdeps/pthread/tst-create1mod.c +@@ -0,0 +1,41 @@ ++/* Verify that pthread_create does not deadlock when ctors take locks. ++ Copyright (C) 2021 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 ++ ++/* Require TLS setup for the module. */ ++__thread int tlsvar; ++ ++void ctor (void); ++void dtor (void); ++ ++static void __attribute__ ((constructor)) ++do_init (void) ++{ ++ dprintf (1, "constructor started: %d.\n", tlsvar++); ++ ctor (); ++ dprintf (1, "constructor done: %d.\n", tlsvar++); ++} ++ ++static void __attribute__ ((destructor)) ++do_end (void) ++{ ++ dprintf (1, "destructor started: %d.\n", tlsvar++); ++ dtor (); ++ dprintf (1, "destructor done: %d.\n", tlsvar++); ++} +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index a8b1ad5..555d7e2 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 23 +Release: 24 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -128,6 +128,10 @@ Patch41: nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch Patch42: nptl-pthread_kill-must-send-signals-to-a-specific-th.patch Patch43: iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch Patch44: gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch +Patch45: elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch +Patch46: ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch +Patch47: ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch +Patch48: Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1317,6 +1321,10 @@ fi %endif %changelog +* Mon Nov 15 2021 Qingqing Li - 2.34-24 +- elf: fix ld.so crash while loading a DSO with a read-only dynamic section + https://sourceware.org/bugzilla/show_bug.cgi?id=28340 + * Wed Nov 10 2021 Qingqing Li - 2.34-23 - gconv: Do not emit spurious NUL character in ISO-2022-JP-3, this also fix CVE-2021-43396. diff --git a/ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch b/ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch new file mode 100644 index 0000000..d1f4271 --- /dev/null +++ b/ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch @@ -0,0 +1,124 @@ +From 2ec99d8c42b2ff1a1231e4df462a0910a9b7fdef Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Thu, 23 Sep 2021 09:06:49 -0700 +Subject: [PATCH] ld.so: Initialize bootstrap_map.l_ld_readonly [BZ #28340] + +1. Define DL_RO_DYN_SECTION to initalize bootstrap_map.l_ld_readonly +before calling elf_get_dynamic_info to get dynamic info in bootstrap_map, +2. Define a single + +static inline bool +dl_relocate_ld (const struct link_map *l) +{ + /* Don't relocate dynamic section if it is readonly */ + return !(l->l_ld_readonly || DL_RO_DYN_SECTION); +} + +This updates BZ #28340 fix. +--- + elf/rtld.c | 1 + + sysdeps/generic/dl-relocate-ld.h | 11 ++--------- + sysdeps/generic/ldsodefs.h | 10 ++++++++++ + sysdeps/mips/dl-relocate-ld.h | 11 ++--------- + sysdeps/riscv/dl-relocate-ld.h | 11 ++--------- + 5 files changed, 17 insertions(+), 27 deletions(-) + +diff --git a/elf/rtld.c b/elf/rtld.c +index c66a1d0..b8ba2d8 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -547,6 +547,7 @@ _dl_start (void *arg) + + /* Read our own dynamic section and fill in the info array. */ + bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); ++ bootstrap_map.l_ld_readonly = DL_RO_DYN_SECTION; + elf_get_dynamic_info (&bootstrap_map); + + #if NO_TLS_OFFSET != 0 +diff --git a/sysdeps/generic/dl-relocate-ld.h b/sysdeps/generic/dl-relocate-ld.h +index 5fae206..cfb86c2 100644 +--- a/sysdeps/generic/dl-relocate-ld.h ++++ b/sysdeps/generic/dl-relocate-ld.h +@@ -19,14 +19,7 @@ + #ifndef _DL_RELOCATE_LD_H + #define _DL_RELOCATE_LD_H + +-/* Return true if dynamic section in the shared library L should be +- relocated. */ +- +-static inline bool +-dl_relocate_ld (const struct link_map *l) +-{ +- /* Don't relocate dynamic section if it is readonly */ +- return !l->l_ld_readonly; +-} ++/* The dynamic section is writable. */ ++#define DL_RO_DYN_SECTION 0 + + #endif /* _DL_RELOCATE_LD_H */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 9ec1511..0410f77 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -69,6 +69,16 @@ __BEGIN_DECLS + `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ + #define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type) + ++/* Return true if dynamic section in the shared library L should be ++ relocated. */ ++ ++static inline bool ++dl_relocate_ld (const struct link_map *l) ++{ ++ /* Don't relocate dynamic section if it is readonly */ ++ return !(l->l_ld_readonly || DL_RO_DYN_SECTION); ++} ++ + /* All references to the value of l_info[DT_PLTGOT], + l_info[DT_STRTAB], l_info[DT_SYMTAB], l_info[DT_RELA], + l_info[DT_REL], l_info[DT_JMPREL], and l_info[VERSYMIDX (DT_VERSYM)] +diff --git a/sysdeps/mips/dl-relocate-ld.h b/sysdeps/mips/dl-relocate-ld.h +index 0c18d9a..376ad75 100644 +--- a/sysdeps/mips/dl-relocate-ld.h ++++ b/sysdeps/mips/dl-relocate-ld.h +@@ -19,14 +19,7 @@ + #ifndef _DL_RELOCATE_LD_H + #define _DL_RELOCATE_LD_H + +-/* Return true if dynamic section in the shared library L should be +- relocated. */ +- +-static inline bool +-dl_relocate_ld (const struct link_map *l) +-{ +- /* Never relocate dynamic section. */ +- return false; +-} ++/* The dynamic section is readonly. */ ++#define DL_RO_DYN_SECTION 1 + + #endif /* _DL_RELOCATE_LD_H */ +diff --git a/sysdeps/riscv/dl-relocate-ld.h b/sysdeps/riscv/dl-relocate-ld.h +index 1032745..2ab2b8a 100644 +--- a/sysdeps/riscv/dl-relocate-ld.h ++++ b/sysdeps/riscv/dl-relocate-ld.h +@@ -19,14 +19,7 @@ + #ifndef _DL_RELOCATE_LD_H + #define _DL_RELOCATE_LD_H + +-/* Return true if dynamic section in the shared library L should be +- relocated. */ +- +-static inline bool +-dl_relocate_ld (const struct link_map *l) +-{ +- /* Never relocate dynamic section for ABI compatibility. */ +- return false; +-} ++/* The dynamic section is readonly for ABI compatibility. */ ++#define DL_RO_DYN_SECTION 1 + + #endif /* _DL_RELOCATE_LD_H */ +-- +1.8.3.1 + diff --git a/ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch b/ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch new file mode 100644 index 0000000..077b996 --- /dev/null +++ b/ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch @@ -0,0 +1,515 @@ +From b413280cfb16834450f66f554bc0d618bb513851 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Thu, 16 Sep 2021 08:15:29 -0700 +Subject: [PATCH] ld.so: Replace DL_RO_DYN_SECTION with dl_relocate_ld [BZ + #28340] + +We can't relocate entries in dynamic section if it is readonly: + +1. Add a l_ld_readonly field to struct link_map to indicate if dynamic +section is readonly and set it based on p_flags of PT_DYNAMIC segment. +2. Replace DL_RO_DYN_SECTION with dl_relocate_ld to decide if dynamic +section should be relocated. +3. Remove DL_RO_DYN_TEMP_CNT. +4. Don't use a static dynamic section to make readonly dynamic section +in vDSO writable. +5. Remove the temp argument from elf_get_dynamic_info. + +This fixes BZ #28340. + +Reviewed-by: Siddhesh Poyarekar +--- + elf/Makefile | 11 +++++++++-- + elf/dl-load.c | 3 ++- + elf/dl-reloc-static-pie.c | 12 +++++++++++- + elf/get-dynamic-info.h | 21 +++------------------ + elf/rtld.c | 6 ++++-- + elf/setup-vdso.h | 5 ++--- + elf/tst-ro-dynamic-mod.c | 19 +++++++++++++++++++ + elf/tst-ro-dynamic-mod.map | 16 ++++++++++++++++ + elf/tst-ro-dynamic.c | 31 +++++++++++++++++++++++++++++++ + include/link.h | 3 +++ + sysdeps/generic/dl-relocate-ld.h | 32 ++++++++++++++++++++++++++++++++ + sysdeps/generic/ldsodefs.h | 7 ++----- + sysdeps/mips/dl-relocate-ld.h | 32 ++++++++++++++++++++++++++++++++ + sysdeps/mips/ldsodefs.h | 4 ---- + sysdeps/riscv/dl-relocate-ld.h | 32 ++++++++++++++++++++++++++++++++ + sysdeps/riscv/ldsodefs.h | 5 ----- + 16 files changed, 198 insertions(+), 41 deletions(-) + create mode 100644 elf/tst-ro-dynamic-mod.c + create mode 100644 elf/tst-ro-dynamic-mod.map + create mode 100644 elf/tst-ro-dynamic.c + create mode 100644 sysdeps/generic/dl-relocate-ld.h + create mode 100644 sysdeps/mips/dl-relocate-ld.h + create mode 100644 sysdeps/riscv/dl-relocate-ld.h + +diff --git a/elf/Makefile b/elf/Makefile +index 835b85b..0cdccaa 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -224,7 +224,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-tls-ie tst-tls-ie-dlmopen argv0test \ + tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ + tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \ +- tst-dl-is_dso ++ tst-dl-is_dso tst-ro-dynamic + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -360,7 +360,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ + tst-tls20mod-bad tst-tls21mod tst-dlmopen-dlerror-mod \ + tst-auxvalmod \ +- tst-dlmopen-gethostbyname-mod \ ++ tst-dlmopen-gethostbyname-mod tst-ro-dynamic-mod \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1911,3 +1911,10 @@ $(objpfx)tst-getauxval-static.out: $(objpfx)tst-auxvalmod.so + tst-getauxval-static-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx) + + $(objpfx)tst-dlmopen-gethostbyname.out: $(objpfx)tst-dlmopen-gethostbyname-mod.so ++ ++$(objpfx)tst-ro-dynamic: $(objpfx)tst-ro-dynamic-mod.so ++$(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \ ++ tst-ro-dynamic-mod.map ++ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \ ++ -Wl,--script=tst-ro-dynamic-mod.map \ ++ $(objpfx)tst-ro-dynamic-mod.os +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 39e0d07..6ea7107 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1149,6 +1149,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + such a segment to avoid a crash later. */ + l->l_ld = (void *) ph->p_vaddr; + l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn)); ++ l->l_ld_readonly = (ph->p_flags & PF_W) == 0; + } + break; + +@@ -1292,7 +1293,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + else + l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr); + +- elf_get_dynamic_info (l, NULL); ++ elf_get_dynamic_info (l); + + /* Make sure we are not dlopen'ing an object that has the + DF_1_NOOPEN flag set, or a PIE object. */ +diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c +index 289651b..68ded17 100644 +--- a/elf/dl-reloc-static-pie.c ++++ b/elf/dl-reloc-static-pie.c +@@ -40,7 +40,17 @@ _dl_relocate_static_pie (void) + + /* Read our own dynamic section and fill in the info array. */ + main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); +- elf_get_dynamic_info (main_map, NULL); ++ ++ const ElfW(Phdr) *ph, *phdr = GL(dl_phdr); ++ size_t phnum = GL(dl_phnum); ++ for (ph = phdr; ph < &phdr[phnum]; ++ph) ++ if (ph->p_type == PT_DYNAMIC) ++ { ++ main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0; ++ break; ++ } ++ ++ elf_get_dynamic_info (main_map); + + # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC + ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); +diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h +index d8ec323..4aa2058 100644 +--- a/elf/get-dynamic-info.h ++++ b/elf/get-dynamic-info.h +@@ -28,7 +28,7 @@ static + auto + #endif + inline void __attribute__ ((unused, always_inline)) +-elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) ++elf_get_dynamic_info (struct link_map *l) + { + #if __ELF_NATIVE_CLASS == 32 + typedef Elf32_Word d_tag_utype; +@@ -69,28 +69,15 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) + info[i] = dyn; + } + +-#define DL_RO_DYN_TEMP_CNT 8 +- +-#ifndef DL_RO_DYN_SECTION + /* Don't adjust .dynamic unnecessarily. */ +- if (l->l_addr != 0) ++ if (l->l_addr != 0 && dl_relocate_ld (l)) + { + ElfW(Addr) l_addr = l->l_addr; +- int cnt = 0; + + # define ADJUST_DYN_INFO(tag) \ + do \ + if (info[tag] != NULL) \ +- { \ +- if (temp) \ +- { \ +- temp[cnt].d_tag = info[tag]->d_tag; \ +- temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr; \ +- info[tag] = temp + cnt++; \ +- } \ +- else \ +- info[tag]->d_un.d_ptr += l_addr; \ +- } \ ++ info[tag]->d_un.d_ptr += l_addr; \ + while (0) + + ADJUST_DYN_INFO (DT_HASH); +@@ -107,9 +94,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) + ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM)); + ADJUST_DYN_INFO (ADDRIDX (DT_GNU_HASH)); + # undef ADJUST_DYN_INFO +- assert (cnt <= DL_RO_DYN_TEMP_CNT); + } +-#endif + if (info[DT_PLTREL] != NULL) + { + #if ELF_MACHINE_NO_RELA +diff --git a/elf/rtld.c b/elf/rtld.c +index 742c413..8d2bba3 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -463,6 +463,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) + #ifndef DONT_USE_BOOTSTRAP_MAP + GL(dl_rtld_map).l_addr = info->l.l_addr; + GL(dl_rtld_map).l_ld = info->l.l_ld; ++ GL(dl_rtld_map).l_ld_readonly = info->l.l_ld_readonly; + memcpy (GL(dl_rtld_map).l_info, info->l.l_info, + sizeof GL(dl_rtld_map).l_info); + GL(dl_rtld_map).l_mach = info->l.l_mach; +@@ -546,7 +547,7 @@ _dl_start (void *arg) + + /* Read our own dynamic section and fill in the info array. */ + bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); +- elf_get_dynamic_info (&bootstrap_map, NULL); ++ elf_get_dynamic_info (&bootstrap_map); + + #if NO_TLS_OFFSET != 0 + bootstrap_map.l_tls_offset = NO_TLS_OFFSET; +@@ -1468,6 +1469,7 @@ dl_main (const ElfW(Phdr) *phdr, + /* This tells us where to find the dynamic section, + which tells us everything we need to do. */ + main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr; ++ main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0; + break; + case PT_INTERP: + /* This "interpreter segment" was used by the program loader to +@@ -1613,7 +1615,7 @@ dl_main (const ElfW(Phdr) *phdr, + if (! rtld_is_main) + { + /* Extract the contents of the dynamic section for easy access. */ +- elf_get_dynamic_info (main_map, NULL); ++ elf_get_dynamic_info (main_map); + + /* If the main map is libc.so, update the base namespace to + refer to this map. If libc.so is loaded later, this happens +diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h +index 86c491e..f44748b 100644 +--- a/elf/setup-vdso.h ++++ b/elf/setup-vdso.h +@@ -33,8 +33,6 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), + 0, LM_ID_BASE); + if (__glibc_likely (l != NULL)) + { +- static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro; +- + l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso) + + GLRO(dl_sysinfo_dso)->e_phoff); + l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum; +@@ -45,6 +43,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), + { + l->l_ld = (void *) ph->p_vaddr; + l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn)); ++ l->l_ld_readonly = (ph->p_flags & PF_W) == 0; + } + else if (ph->p_type == PT_LOAD) + { +@@ -65,7 +64,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), + l->l_map_end += l->l_addr; + l->l_text_end += l->l_addr; + l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr); +- elf_get_dynamic_info (l, dyn_temp); ++ elf_get_dynamic_info (l); + _dl_setup_hash (l); + l->l_relocated = 1; + +diff --git a/elf/tst-ro-dynamic-mod.c b/elf/tst-ro-dynamic-mod.c +new file mode 100644 +index 0000000..6d99925 +--- /dev/null ++++ b/elf/tst-ro-dynamic-mod.c +@@ -0,0 +1,19 @@ ++/* Test case for DSO with readonly dynamic section. ++ Copyright (C) 2021 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 ++ . */ ++ ++int foo = -1; +diff --git a/elf/tst-ro-dynamic-mod.map b/elf/tst-ro-dynamic-mod.map +new file mode 100644 +index 0000000..2fe4a29 +--- /dev/null ++++ b/elf/tst-ro-dynamic-mod.map +@@ -0,0 +1,16 @@ ++SECTIONS ++{ ++ . = SIZEOF_HEADERS; ++ .dynamic : { *(.dynamic) } :text :dynamic ++ .rodata : { *(.data*) *(.bss*) } :text ++ /DISCARD/ : { ++ *(.note.gnu.property) ++ } ++ .note : { *(.note.*) } :text :note ++} ++PHDRS ++{ ++ text PT_LOAD FLAGS(5) FILEHDR PHDRS; ++ dynamic PT_DYNAMIC FLAGS(4); ++ note PT_NOTE FLAGS(4); ++} +diff --git a/elf/tst-ro-dynamic.c b/elf/tst-ro-dynamic.c +new file mode 100644 +index 0000000..3a18f87 +--- /dev/null ++++ b/elf/tst-ro-dynamic.c +@@ -0,0 +1,31 @@ ++/* Test case for DSO with readonly dynamic section. ++ Copyright (C) 2021 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 ++ ++extern int foo; ++ ++static int ++do_test (void) ++{ ++ TEST_COMPARE (foo, -1); ++ return 0; ++} ++ ++#include +diff --git a/include/link.h b/include/link.h +index 7b8250d..484ee6c 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -205,6 +205,7 @@ struct link_map + unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be + freed, ie. not allocated with + the dummy malloc in ld.so. */ ++ unsigned int l_ld_readonly:1; /* Nonzero if dynamic section is readonly. */ + + /* NODELETE status of the map. Only valid for maps of type + lt_loaded. Lazy binding sets l_nodelete_active directly, +@@ -342,6 +343,8 @@ struct link_map + unsigned long long int l_serial; + }; + ++#include ++ + /* Information used by audit modules. For most link maps, this data + immediate follows the link map in memory. For the dynamic linker, + it is allocated separately. See link_map_audit_state in +diff --git a/sysdeps/generic/dl-relocate-ld.h b/sysdeps/generic/dl-relocate-ld.h +new file mode 100644 +index 0000000..5fae206 +--- /dev/null ++++ b/sysdeps/generic/dl-relocate-ld.h +@@ -0,0 +1,32 @@ ++/* Check if dynamic section should be relocated. Generic version. ++ Copyright (C) 2021 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 _DL_RELOCATE_LD_H ++#define _DL_RELOCATE_LD_H ++ ++/* Return true if dynamic section in the shared library L should be ++ relocated. */ ++ ++static inline bool ++dl_relocate_ld (const struct link_map *l) ++{ ++ /* Don't relocate dynamic section if it is readonly */ ++ return !l->l_ld_readonly; ++} ++ ++#endif /* _DL_RELOCATE_LD_H */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 6e50fcd..d49529d 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -75,11 +75,8 @@ __BEGIN_DECLS + have to be accessed via the D_PTR macro. The macro is needed since for + most architectures the entry is already relocated - but for some not + and we need to relocate at access time. */ +-#ifdef DL_RO_DYN_SECTION +-# define D_PTR(map, i) ((map)->i->d_un.d_ptr + (map)->l_addr) +-#else +-# define D_PTR(map, i) (map)->i->d_un.d_ptr +-#endif ++#define D_PTR(map, i) \ ++ ((map)->i->d_un.d_ptr + (dl_relocate_ld (map) ? 0 : (map)->l_addr)) + + /* Result of the lookup functions and how to retrieve the base address. */ + typedef struct link_map *lookup_t; +diff --git a/sysdeps/mips/dl-relocate-ld.h b/sysdeps/mips/dl-relocate-ld.h +new file mode 100644 +index 0000000..0c18d9a +--- /dev/null ++++ b/sysdeps/mips/dl-relocate-ld.h +@@ -0,0 +1,32 @@ ++/* Check if dynamic section should be relocated. MIPS version. ++ Copyright (C) 2021 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 _DL_RELOCATE_LD_H ++#define _DL_RELOCATE_LD_H ++ ++/* Return true if dynamic section in the shared library L should be ++ relocated. */ ++ ++static inline bool ++dl_relocate_ld (const struct link_map *l) ++{ ++ /* Never relocate dynamic section. */ ++ return false; ++} ++ ++#endif /* _DL_RELOCATE_LD_H */ +diff --git a/sysdeps/mips/ldsodefs.h b/sysdeps/mips/ldsodefs.h +index 4db7c60..36fd09a 100644 +--- a/sysdeps/mips/ldsodefs.h ++++ b/sysdeps/mips/ldsodefs.h +@@ -75,10 +75,6 @@ struct La_mips_64_retval; + struct La_mips_64_retval *, \ + const char *); + +-/* The MIPS ABI specifies that the dynamic section has to be read-only. */ +- +-#define DL_RO_DYN_SECTION 1 +- + #include_next + + /* The 64-bit MIPS ELF ABI uses an unusual reloc format. Each +diff --git a/sysdeps/riscv/dl-relocate-ld.h b/sysdeps/riscv/dl-relocate-ld.h +new file mode 100644 +index 0000000..1032745 +--- /dev/null ++++ b/sysdeps/riscv/dl-relocate-ld.h +@@ -0,0 +1,32 @@ ++/* Check if dynamic section should be relocated. RISC-V version. ++ Copyright (C) 2021 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 _DL_RELOCATE_LD_H ++#define _DL_RELOCATE_LD_H ++ ++/* Return true if dynamic section in the shared library L should be ++ relocated. */ ++ ++static inline bool ++dl_relocate_ld (const struct link_map *l) ++{ ++ /* Never relocate dynamic section for ABI compatibility. */ ++ return false; ++} ++ ++#endif /* _DL_RELOCATE_LD_H */ +diff --git a/sysdeps/riscv/ldsodefs.h b/sysdeps/riscv/ldsodefs.h +index 0c69671..8947ffe 100644 +--- a/sysdeps/riscv/ldsodefs.h ++++ b/sysdeps/riscv/ldsodefs.h +@@ -38,11 +38,6 @@ struct La_riscv_retval; + struct La_riscv_retval *, \ + const char *); + +-/* Although the RISC-V ABI does not specify that the dynamic section has +- to be read-only, it needs to be kept for ABI compatibility. */ +- +-#define DL_RO_DYN_SECTION 1 +- + #include_next + + #endif +-- +1.8.3.1 + -- Gitee From 59c98cbb45237000c0a1308fe9d22a344a718bb1 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 15 Nov 2021 21:34:48 +0800 Subject: [PATCH 24/70] fix attribute access mode on getcwd [BZ #27476], supress -Wcast-qual warnings in bsearch (cherry picked from commit 05f7be52737763a2b31fc326413d86e2a02a0c58) --- Suppress-Wcast-qual-warnings-in-bsearch.patch | 46 +++++++++++++++++ glibc.spec | 8 ++- ...ibute-access-mode-on-getcwd-BZ-27476.patch | 50 +++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 Suppress-Wcast-qual-warnings-in-bsearch.patch create mode 100644 posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch diff --git a/Suppress-Wcast-qual-warnings-in-bsearch.patch b/Suppress-Wcast-qual-warnings-in-bsearch.patch new file mode 100644 index 0000000..656f412 --- /dev/null +++ b/Suppress-Wcast-qual-warnings-in-bsearch.patch @@ -0,0 +1,46 @@ +From a725ff1de965f4cc4f36a7e8ae795d40ca0350d7 Mon Sep 17 00:00:00 2001 +From: Jonathan Wakely +Date: Wed, 19 May 2021 16:48:19 +0100 +Subject: [PATCH] Suppress -Wcast-qual warnings in bsearch + +The first cast to (void *) is redundant but should be (const void *) +anyway, because that's the type of the lvalue being assigned to. + +The second cast is necessary and intentionally not const-correct, so +tell the compiler not to warn about it. + +Reviewed-by: Florian Weimer +--- + bits/stdlib-bsearch.h | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/bits/stdlib-bsearch.h b/bits/stdlib-bsearch.h +index 4132dc6..d688ed2 100644 +--- a/bits/stdlib-bsearch.h ++++ b/bits/stdlib-bsearch.h +@@ -29,14 +29,21 @@ bsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size, + while (__l < __u) + { + __idx = (__l + __u) / 2; +- __p = (void *) (((const char *) __base) + (__idx * __size)); ++ __p = (const void *) (((const char *) __base) + (__idx * __size)); + __comparison = (*__compar) (__key, __p); + if (__comparison < 0) + __u = __idx; + else if (__comparison > 0) + __l = __idx + 1; + else ++#if __GNUC_PREREQ(4, 6) ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wcast-qual" ++#endif + return (void *) __p; ++#if __GNUC_PREREQ(4, 6) ++# pragma GCC diagnostic pop ++#endif + } + + return NULL; +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index 555d7e2..4c23b05 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 24 +Release: 25 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -132,6 +132,8 @@ Patch45: elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch Patch46: ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch Patch47: ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch Patch48: Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch +Patch49: posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch +Patch50: Suppress-Wcast-qual-warnings-in-bsearch.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1321,6 +1323,10 @@ fi %endif %changelog +* Mon Nov 15 2021 Qingqing Li - 2.34-25 +- fix attribute access mode on getcwd [BZ #27476] +- supress -Wcast-qual warnings in bsearch + * Mon Nov 15 2021 Qingqing Li - 2.34-24 - elf: fix ld.so crash while loading a DSO with a read-only dynamic section https://sourceware.org/bugzilla/show_bug.cgi?id=28340 diff --git a/posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch b/posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch new file mode 100644 index 0000000..a9e8d26 --- /dev/null +++ b/posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch @@ -0,0 +1,50 @@ +From 433ec4f14a5753c7689c83c20c9972915c53c204 Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Fri, 10 Sep 2021 19:39:35 +0200 +Subject: [PATCH] posix: Fix attribute access mode on getcwd [BZ #27476] + +There is a GNU extension that allows to call getcwd(NULL, >0). It is +described in the documentation, but also directly in the unistd.h +header, just above the declaration. + +Therefore the attribute access mode added in commit 06febd8c6705 +is not correct. Drop it. +--- + posix/bits/unistd.h | 5 ++--- + posix/unistd.h | 3 +-- + 2 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h +index f083138..622adeb 100644 +--- a/posix/bits/unistd.h ++++ b/posix/bits/unistd.h +@@ -199,10 +199,9 @@ __NTH (readlinkat (int __fd, const char *__restrict __path, + #endif + + extern char *__getcwd_chk (char *__buf, size_t __size, size_t __buflen) +- __THROW __wur __attr_access ((__write_only__, 1, 2)); ++ __THROW __wur; + extern char *__REDIRECT_NTH (__getcwd_alias, +- (char *__buf, size_t __size), getcwd) +- __wur __attr_access ((__write_only__, 1, 2)); ++ (char *__buf, size_t __size), getcwd) __wur; + extern char *__REDIRECT_NTH (__getcwd_chk_warn, + (char *__buf, size_t __size, size_t __buflen), + __getcwd_chk) +diff --git a/posix/unistd.h b/posix/unistd.h +index 3dca657..8224c5f 100644 +--- a/posix/unistd.h ++++ b/posix/unistd.h +@@ -528,8 +528,7 @@ extern int fchdir (int __fd) __THROW __wur; + an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE == 0, in which case it is as + big as necessary. */ +-extern char *getcwd (char *__buf, size_t __size) __THROW __wur +- __attr_access ((__write_only__, 1, 2)); ++extern char *getcwd (char *__buf, size_t __size) __THROW __wur; + + #ifdef __USE_GNU + /* Return a malloc'd string containing the current directory name. +-- +1.8.3.1 + -- Gitee From e55f33687402f79ec5d7527dc5f8469e510b6f71 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Thu, 18 Nov 2021 17:34:46 +0800 Subject: [PATCH 25/70] revert supress -Wcast-qual warnings in bsearch (cherry picked from commit 1feba0288f96de12ea102ec6e8da994ceae77788) --- Suppress-Wcast-qual-warnings-in-bsearch.patch | 46 ------------------- glibc.spec | 6 ++- 2 files changed, 4 insertions(+), 48 deletions(-) delete mode 100644 Suppress-Wcast-qual-warnings-in-bsearch.patch diff --git a/Suppress-Wcast-qual-warnings-in-bsearch.patch b/Suppress-Wcast-qual-warnings-in-bsearch.patch deleted file mode 100644 index 656f412..0000000 --- a/Suppress-Wcast-qual-warnings-in-bsearch.patch +++ /dev/null @@ -1,46 +0,0 @@ -From a725ff1de965f4cc4f36a7e8ae795d40ca0350d7 Mon Sep 17 00:00:00 2001 -From: Jonathan Wakely -Date: Wed, 19 May 2021 16:48:19 +0100 -Subject: [PATCH] Suppress -Wcast-qual warnings in bsearch - -The first cast to (void *) is redundant but should be (const void *) -anyway, because that's the type of the lvalue being assigned to. - -The second cast is necessary and intentionally not const-correct, so -tell the compiler not to warn about it. - -Reviewed-by: Florian Weimer ---- - bits/stdlib-bsearch.h | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/bits/stdlib-bsearch.h b/bits/stdlib-bsearch.h -index 4132dc6..d688ed2 100644 ---- a/bits/stdlib-bsearch.h -+++ b/bits/stdlib-bsearch.h -@@ -29,14 +29,21 @@ bsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size, - while (__l < __u) - { - __idx = (__l + __u) / 2; -- __p = (void *) (((const char *) __base) + (__idx * __size)); -+ __p = (const void *) (((const char *) __base) + (__idx * __size)); - __comparison = (*__compar) (__key, __p); - if (__comparison < 0) - __u = __idx; - else if (__comparison > 0) - __l = __idx + 1; - else -+#if __GNUC_PREREQ(4, 6) -+# pragma GCC diagnostic push -+# pragma GCC diagnostic ignored "-Wcast-qual" -+#endif - return (void *) __p; -+#if __GNUC_PREREQ(4, 6) -+# pragma GCC diagnostic pop -+#endif - } - - return NULL; --- -1.8.3.1 - diff --git a/glibc.spec b/glibc.spec index 4c23b05..6631723 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 25 +Release: 26 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -133,7 +133,6 @@ Patch46: ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch Patch47: ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch Patch48: Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch Patch49: posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch -Patch50: Suppress-Wcast-qual-warnings-in-bsearch.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1323,6 +1322,9 @@ fi %endif %changelog +* Fri Nov 19 2021 Qingqing Li - 2.34-26 +- revert supress -Wcast-qual warnings in bsearch + * Mon Nov 15 2021 Qingqing Li - 2.34-25 - fix attribute access mode on getcwd [BZ #27476] - supress -Wcast-qual warnings in bsearch -- Gitee From 2a138b3c83dc227e0cd2b684f83bb17dc93dc704 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 23 Nov 2021 14:40:08 +0800 Subject: [PATCH 26/70] Refactor the libpthread-2.17.so code and pass all test cases. delete libpthread-2.17.so from glibc-devel (cherry picked from commit 8615244aa3b58b6251dfad0c2c660134bd96bfcd) --- ...iles-for-libphtread-condition-family.patch | 2321 ++++ ...-header-files-for-libphtread_2_17_so.patch | 2609 +++++ ...ript-and-files-of-libpthread_2_17_so.patch | 135 + ...eader-files-with-some-deleted-macros.patch | 166 + 0005-add-pthread-functions_h.patch | 140 + ...on-which-moved-to-libc-in-glibc-2.34.patch | 587 + 0007-add-lowlevellock_2_17_c.patch | 68 + 0008-add-pause_nocancel_2_17.patch | 56 + 0009-add-unwind-with-longjmp.patch | 161 + compat-2.17-libpthreadcond-so.patch | 9558 ----------------- glibc.spec | 18 +- 11 files changed, 6258 insertions(+), 9561 deletions(-) create mode 100644 0001-add-base-files-for-libphtread-condition-family.patch create mode 100644 0002-add-header-files-for-libphtread_2_17_so.patch create mode 100644 0003-add-build-script-and-files-of-libpthread_2_17_so.patch create mode 100644 0004-add-two-header-files-with-some-deleted-macros.patch create mode 100644 0005-add-pthread-functions_h.patch create mode 100644 0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch create mode 100644 0007-add-lowlevellock_2_17_c.patch create mode 100644 0008-add-pause_nocancel_2_17.patch create mode 100644 0009-add-unwind-with-longjmp.patch delete mode 100644 compat-2.17-libpthreadcond-so.patch diff --git a/0001-add-base-files-for-libphtread-condition-family.patch b/0001-add-base-files-for-libphtread-condition-family.patch new file mode 100644 index 0000000..9ca2225 --- /dev/null +++ b/0001-add-base-files-for-libphtread-condition-family.patch @@ -0,0 +1,2321 @@ +From 76a50749f7af5935ba3739e815aa6a16ae4440d1 Mon Sep 17 00:00:00 2001 +From: Ulrich Drepper +Date: Tue Nov 26 22:50:54 2002 +0000 +Subject: [PATCH 1/9] 0001 + +since https://sourceware.org/git/?p=glibc.git;a=commit;h=ed19993b5b0d05d62cc883571519a67dae481a14 +delete pthread_condtion function.However, using these interfaces has better performance. +Therefore, we add a subpacket to use these interfaces. +you can use it by adding LD_PRELOAD=./libpthreadcond.so in front of your program (eg: +LD_PRELOAD=./libpthreadcond.so ./test). use with-compat_2_17 to compile it. +WARNING:2.17 version does not meet the posix standard, you should pay attention when using it. +add pthread_cond_clockwait to prevent process hang up when libpthread-2.17 and libpthread-2.28 are used together. +use pthread_cond_common to implement the public functions of pthread_cond_clockwait,pthread_cond_clockwait and pthread_cond_timedwait. + +Add some base files for the libpthread_condition family. +Including but not limited to the following submission: +6efd481484e +a88c9263686 +76a50749f7a +69431c9a21f +5bd8a24966d + +--- + nptl_2_17/cancellation_2_17.c | 60 ++ + nptl_2_17/cleanup_compat_2_17.c | 50 ++ + nptl_2_17/pthread_cond_broadcast_2_17.c | 101 +++ + nptl_2_17/pthread_cond_destroy_2_17.c | 86 +++ + nptl_2_17/pthread_cond_init_2_17.c | 49 ++ + nptl_2_17/pthread_cond_signal_2_17.c | 84 +++ + nptl_2_17/pthread_cond_wait_2_17.c | 329 ++++++++++ + nptl_2_17/pthread_condattr_getclock_2_17.c | 28 + + nptl_2_17/pthread_condattr_getpshared_2_17.c | 28 + + nptl_2_17/pthread_condattr_init_2_17.c | 33 + + nptl_2_17/pthread_condattr_setclock_2_17.c | 45 ++ + nptl_2_17/pthread_mutex_cond_lock_2_17.c | 21 + + nptl_2_17/pthread_mutex_lock_2_17.c | 652 +++++++++++++++++++ + nptl_2_17/pthread_mutex_unlock_2_17.c | 361 ++++++++++ + nptl_2_17/tpp_2_17.c | 195 ++++++ + nptl_2_17/vars_2_17.c | 43 ++ + 16 files changed, 2165 insertions(+) + create mode 100644 nptl_2_17/cancellation_2_17.c + create mode 100644 nptl_2_17/cleanup_compat_2_17.c + create mode 100644 nptl_2_17/pthread_cond_broadcast_2_17.c + create mode 100644 nptl_2_17/pthread_cond_destroy_2_17.c + create mode 100644 nptl_2_17/pthread_cond_init_2_17.c + create mode 100644 nptl_2_17/pthread_cond_signal_2_17.c + create mode 100644 nptl_2_17/pthread_cond_wait_2_17.c + create mode 100644 nptl_2_17/pthread_condattr_getclock_2_17.c + create mode 100644 nptl_2_17/pthread_condattr_getpshared_2_17.c + create mode 100644 nptl_2_17/pthread_condattr_init_2_17.c + create mode 100644 nptl_2_17/pthread_condattr_setclock_2_17.c + create mode 100644 nptl_2_17/pthread_mutex_cond_lock_2_17.c + create mode 100644 nptl_2_17/pthread_mutex_lock_2_17.c + create mode 100644 nptl_2_17/pthread_mutex_unlock_2_17.c + create mode 100644 nptl_2_17/tpp_2_17.c + create mode 100644 nptl_2_17/vars_2_17.c + +diff --git a/nptl_2_17/cancellation_2_17.c b/nptl_2_17/cancellation_2_17.c +new file mode 100644 +index 00000000..5c9ce572 +--- /dev/null ++++ b/nptl_2_17/cancellation_2_17.c +@@ -0,0 +1,60 @@ ++/* Copyright (C) 2002-2018 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_enable_asynccancel (void) ++{ ++ struct pthread *self = THREAD_SELF; ++ ++ int oldval = THREAD_GETMEM (self, canceltype); ++ THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); ++ ++ int ch = THREAD_GETMEM (self, cancelhandling); ++ ++ if (self->cancelstate == PTHREAD_CANCEL_ENABLE ++ && (ch & CANCELED_BITMASK) ++ && !(ch & EXITING_BITMASK) ++ && !(ch & TERMINATED_BITMASK)) ++ { ++ THREAD_SETMEM (self, result, PTHREAD_CANCELED); ++ __do_cancel (); ++ } ++ ++ return oldval; ++} ++libc_hidden_def (__pthread_enable_asynccancel) ++ ++/* See the comment for __pthread_enable_asynccancel regarding ++ the AS-safety of this function. */ ++void ++__pthread_disable_asynccancel (int oldtype) ++{ ++ /* If asynchronous cancellation was enabled before we do not have ++ anything to do. */ ++ if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS) ++ return; ++ ++ struct pthread *self = THREAD_SELF; ++ self->canceltype = PTHREAD_CANCEL_DEFERRED; ++} ++libc_hidden_def (__pthread_disable_asynccancel) +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..53cf903d +--- /dev/null ++++ b/nptl_2_17/cleanup_compat_2_17.c +@@ -0,0 +1,50 @@ ++/* Copyright (C) 2002-2018 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 ++ ++ ++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/pthread_cond_broadcast_2_17.c b/nptl_2_17/pthread_cond_broadcast_2_17.c +new file mode 100644 +index 00000000..df39c99b +--- /dev/null ++++ b/nptl_2_17/pthread_cond_broadcast_2_17.c +@@ -0,0 +1,101 @@ ++/* 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 "kernel-features_2_17.h" ++#include "pthread_2_17.h" ++#include "pthreadP_2_17.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++/* We do the following steps from __pthread_cond_signal in one critical ++ section: (1) signal all waiters in G1, (2) close G1 so that it can become ++ the new G2 and make G2 the new G1, and (3) signal all waiters in the new ++ G1. We don't need to do all these steps if there are no waiters in G1 ++ and/or G2. See __pthread_cond_signal for further details. */ ++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..6342f471 +--- /dev/null ++++ b/nptl_2_17/pthread_cond_destroy_2_17.c +@@ -0,0 +1,86 @@ ++/* Copyright (C) 2002-2018 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 ++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..d590d1d0 +--- /dev/null ++++ b/nptl_2_17/pthread_cond_init_2_17.c +@@ -0,0 +1,49 @@ ++/* Copyright (C) 2002-2018 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..e6f08ac8 +--- /dev/null ++++ b/nptl_2_17/pthread_cond_signal_2_17.c +@@ -0,0 +1,84 @@ ++/* 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 "kernel-features_2_17.h" ++#include "pthread_2_17.h" ++#include "pthreadP_2_17.h" ++ ++#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_wait_2_17.c b/nptl_2_17/pthread_cond_wait_2_17.c +new file mode 100644 +index 00000000..ff651a00 +--- /dev/null ++++ b/nptl_2_17/pthread_cond_wait_2_17.c +@@ -0,0 +1,329 @@ ++/* 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 "kernel-features_2_17.h" ++#include "pthread_2_17.h" ++#include "pthreadP_2_17.h" ++ ++#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); ++} ++ ++static __always_inline int ++__pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex, ++ clockid_t clockid, ++ const struct timespec *abstime) ++{ ++ struct _pthread_cleanup_buffer buffer; ++ struct _condvar_cleanup_buffer cbuffer; ++ int result = 0; ++ ++ 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); ++ /* clockid will already have been checked by ++ __pthread_cond_clockwait or pthread_condattr_setclock, or we ++ don't use it if abstime is NULL, so we don't need to check it ++ here. */ ++ /* 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 (__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; ++ ++ /* Work around the fact that the kernel rejects negative timeout values ++ despite them being valid. */ ++ if (abstime != NULL && __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) ++ { ++ 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) ++ { ++ if (abstime == NULL) ++ { ++ err = lll_futex_wait_requeue_pi (&cond->__data.__futex, ++ futex_val, &mutex->__data.__lock, ++ pshared); ++ } ++ else ++ { ++ unsigned int clockbit = (clockid == CLOCK_REALTIME) ++ ? FUTEX_CLOCK_REALTIME : 0; ++ ++ err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex, ++ futex_val, abstime, clockbit, ++ &mutex->__data.__lock, ++ pshared); ++ } ++ pi_flag = (err == 0); ++ } ++ else ++#endif ++ /* Wait until woken by signal or broadcast. */ ++ { ++ if (abstime == NULL) ++ { ++ lll_futex_wait (&cond->__data.__futex, futex_val, pshared); ++ } ++ else ++ { ++ err = lll_futex_clock_wait_bitset (&cond->__data.__futex, futex_val, ++ clockid, abstime, 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; ++ if (val != seq && cond->__data.__woken_seq != val) ++ break; ++ ++ /* Not woken yet. Maybe the time expired? */ ++ if (abstime != NULL && __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_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; ++} ++/* See __pthread_cond_wait_common. */ ++int ++__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) ++{ ++ /* clockid is unused when abstime is NULL. */ ++ return __pthread_cond_wait_common (cond, mutex, 0, NULL); ++} ++ ++/* See __pthread_cond_wait_common. */ ++int ++__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, ++ const struct timespec *abstime) ++{ ++ /* Check parameter validity. This should also tell the compiler that ++ it can assume that abstime is not NULL. */ ++ if (abstime == NULL || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) ++ return EINVAL; ++ ++ clockid_t clockid = cond->__data.__nwaiters & 1; ++ ++ return __pthread_cond_wait_common (cond, mutex, clockid, abstime); ++} ++ ++/* See __pthread_cond_wait_common. */ ++int ++__pthread_cond_clockwait (pthread_cond_t *cond, pthread_mutex_t *mutex, ++ clockid_t clockid, ++ const struct timespec *abstime) ++{ ++ /* Check parameter validity. This should also tell the compiler that ++ it can assume that abstime is not NULL. */ ++ if (abstime == NULL || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) ++ return EINVAL; ++ ++ if (!futex_abstimed_supported_clockid (clockid)) ++ return EINVAL; ++ ++ return __pthread_cond_wait_common (cond, mutex, clockid, abstime); ++} ++ ++versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, ++ GLIBC_2_3_2); ++versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, ++ GLIBC_2_3_2); ++versioned_symbol (libpthread, __pthread_cond_clockwait, pthread_cond_clockwait, ++ GLIBC_2_34); +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..414a6856 +--- /dev/null ++++ b/nptl_2_17/pthread_condattr_getclock_2_17.c +@@ -0,0 +1,28 @@ ++/* Copyright (C) 2003-2018 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..2b85506f +--- /dev/null ++++ b/nptl_2_17/pthread_condattr_getpshared_2_17.c +@@ -0,0 +1,28 @@ ++/* Copyright (C) 2002-2018 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..c2765e96 +--- /dev/null ++++ b/nptl_2_17/pthread_condattr_init_2_17.c +@@ -0,0 +1,33 @@ ++/* Copyright (C) 2002-2018 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 ++ ++ ++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..69c64dcb +--- /dev/null ++++ b/nptl_2_17/pthread_condattr_setclock_2_17.c +@@ -0,0 +1,45 @@ ++/* Copyright (C) 2003-2018 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" ++#include ++#include ++#include ++#include ++#include ++ ++ ++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..87734543 +--- /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..b08a2472 +--- /dev/null ++++ b/nptl_2_17/pthread_mutex_lock_2_17.c +@@ -0,0 +1,652 @@ ++/* Copyright (C) 2002-2018 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 ++ ++#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 ++/* lll_lock with single-thread optimization. */ ++static inline void ++lll_mutex_lock_optimized (pthread_mutex_t *mutex) ++{ ++ /* The single-threaded optimization is only valid for private ++ mutexes. For process-shared mutexes, the mutex could be in a ++ shared mapping, so synchronization with another process is needed ++ even without any threads. If the lock is already marked as ++ acquired, POSIX requires that pthread_mutex_lock deadlocks for ++ normal mutexes, so skip the optimization in that case as ++ well. */ ++ int private = PTHREAD_MUTEX_PSHARED (mutex); ++ if (private == LLL_PRIVATE && SINGLE_THREAD_P && mutex->__data.__lock == 0) ++ mutex->__data.__lock = 1; ++ else ++ lll_lock (mutex->__data.__lock, private); ++} ++# define LLL_MUTEX_LOCK(mutex) \ ++ lll_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)) ++# define LLL_MUTEX_LOCK_OPTIMIZED(mutex) lll_mutex_lock_optimized (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)) ++# define PTHREAD_MUTEX_LOCK ___pthread_mutex_lock ++# define PTHREAD_MUTEX_VERSIONS 1 ++#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 ENABLE_ELISION_SUPPORT ++ 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 (MAX_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)); ++ INTERNAL_SYSCALL_DECL (__err); ++ int e = INTERNAL_SYSCALL (futex, 4, &mutex->__data.__lock, ++ __lll_private_flag (FUTEX_LOCK_PI, ++ private), 1, 0); ++ ++ if (INTERNAL_SYSCALL_ERROR_P (e) ++ && (INTERNAL_SYSCALL_ERRNO (e) == ESRCH ++ || INTERNAL_SYSCALL_ERRNO (e) == EDEADLK)) ++ { ++ assert (INTERNAL_SYSCALL_ERRNO (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 (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust); ++ ++ /* Delay the thread indefinitely. */ ++ while (1) ++ __pause_nocancel (); ++ } ++ ++ 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; ++ ++ INTERNAL_SYSCALL_DECL (__err); ++ INTERNAL_SYSCALL (futex, 4, &mutex->__data.__lock, ++ __lll_private_flag (FUTEX_UNLOCK_PI, ++ PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), ++ 0, 0); ++ ++ /* 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..00729d32 +--- /dev/null ++++ b/nptl_2_17/pthread_mutex_unlock_2_17.c +@@ -0,0 +1,361 @@ ++/* Copyright (C) 2002-2018 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))) ++ { ++ INTERNAL_SYSCALL_DECL (__err); ++ INTERNAL_SYSCALL (futex, 2, &mutex->__data.__lock, ++ __lll_private_flag (FUTEX_UNLOCK_PI, 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/tpp_2_17.c b/nptl_2_17/tpp_2_17.c +new file mode 100644 +index 00000000..45fff81a +--- /dev/null ++++ b/nptl_2_17/tpp_2_17.c +@@ -0,0 +1,195 @@ ++/* Thread Priority Protect helpers. ++ Copyright (C) 2006-2018 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 "pthreadP_2_17.h" ++#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/vars_2_17.c b/nptl_2_17/vars_2_17.c +new file mode 100644 +index 00000000..ae60c0f8 +--- /dev/null ++++ b/nptl_2_17/vars_2_17.c +@@ -0,0 +1,43 @@ ++/* Copyright (C) 2004-2018 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 "pthreadP_2_17.h" ++#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.30.0 + diff --git a/0002-add-header-files-for-libphtread_2_17_so.patch b/0002-add-header-files-for-libphtread_2_17_so.patch new file mode 100644 index 0000000..98db0ff --- /dev/null +++ b/0002-add-header-files-for-libphtread_2_17_so.patch @@ -0,0 +1,2609 @@ +From 76a50749f7af5935ba3739e815aa6a16ae4440d1 Mon Sep 17 00:00:00 2001 +From: Ulrich Drepper +Date: Tue Nov 26 22:50:54 2002 +0000 +Subject: [PATCH 2/9] build extra lipthreadcond so + +To successfully build some header files that reference glibc-2.17 + +Including but not limited to the following submission: +76a50749f7a +d5efd131d4e +eab380d8ec9 + +--- + nptl_2_17/bits/pthreadtypes_2_17.h | 127 +++ + nptl_2_17/bits/thread-shared-types_2_17.h | 186 ++++ + nptl_2_17/internaltypes_2_17.h | 179 ++++ + nptl_2_17/kernel-features_2_17.h | 162 +++ + nptl_2_17/pthreadP_2_17.h | 714 +++++++++++++ + nptl_2_17/pthread_2_17.h | 1175 +++++++++++++++++++++ + 6 files changed, 2543 insertions(+) + create mode 100644 nptl_2_17/bits/pthreadtypes_2_17.h + create mode 100644 nptl_2_17/bits/thread-shared-types_2_17.h + create mode 100644 nptl_2_17/internaltypes_2_17.h + create mode 100644 nptl_2_17/kernel-features_2_17.h + create mode 100644 nptl_2_17/pthreadP_2_17.h + create mode 100644 nptl_2_17/pthread_2_17.h + +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..da5521c1 +--- /dev/null ++++ b/nptl_2_17/bits/pthreadtypes_2_17.h +@@ -0,0 +1,127 @@ ++/* Declaration of common pthread types for all architectures. ++ Copyright (C) 2017-2018 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-shared-types_2_17.h" ++ ++/* Thread identifiers. The structure of the attribute type is not ++ exposed on purpose. */ ++typedef unsigned long int pthread_t; ++ ++ ++/* Data structures for mutex handling. The structure of the attribute ++ type is not exposed on purpose. */ ++typedef union ++{ ++ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; ++ int __align; ++} pthread_mutexattr_t; ++ ++ ++/* Data structure for condition variable handling. The structure of ++ the attribute type is not exposed on purpose. */ ++typedef union ++{ ++ char __size[__SIZEOF_PTHREAD_CONDATTR_T]; ++ int __align; ++} pthread_condattr_t; ++ ++ ++/* Keys for thread-specific data */ ++typedef unsigned int pthread_key_t; ++ ++ ++/* Once-only execution */ ++typedef int __ONCE_ALIGNMENT pthread_once_t; ++ ++ ++union pthread_attr_t ++{ ++ char __size[__SIZEOF_PTHREAD_ATTR_T]; ++ long int __align; ++}; ++#ifndef __have_pthread_attr_t ++typedef union pthread_attr_t pthread_attr_t; ++# define __have_pthread_attr_t 1 ++#endif ++ ++ ++typedef union ++{ ++ struct __pthread_mutex_s __data; ++ char __size[__SIZEOF_PTHREAD_MUTEX_T]; ++ long int __align; ++} pthread_mutex_t; ++ ++ ++typedef union ++{ ++struct ++{ ++ 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; ++}__data; ++ char __size[__SIZEOF_PTHREAD_COND_T]; ++ long int __align; ++} pthread_cond_t; ++ ++ ++/* 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; ++ ++ ++/* 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 +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..c855d0d8 +--- /dev/null ++++ b/nptl_2_17/bits/thread-shared-types_2_17.h +@@ -0,0 +1,186 @@ ++/* Common threading primitives definitions for both POSIX and C11. ++ Copyright (C) 2017-2018 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 ++ ++#include ++/* 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. ++ ++ Also, the following macros must be define for internal pthread_mutex_t ++ struct definitions (struct __pthread_mutex_s): ++ ++ __PTHREAD_COMPAT_PADDING_MID - any additional members after 'kind' ++ and before '__spin' (for 64 bits) or ++ '__nusers' (for 32 bits). ++ __PTHREAD_COMPAT_PADDING_END - any additional members at the end of ++ the internal structure. ++ __PTHREAD_MUTEX_LOCK_ELISION - 1 if the architecture supports lock ++ elision or 0 otherwise. ++ __PTHREAD_MUTEX_NUSERS_AFTER_KIND - control where to put __nusers. The ++ preferred value for new architectures ++ is 0. ++ __PTHREAD_MUTEX_USE_UNION - control whether internal __spins and ++ __list will be place inside a union for ++ linuxthreads compatibility. ++ The preferred value for new architectures ++ is 0. ++ ++ For a new port the preferred values for the required defines are: ++ ++ #define __PTHREAD_COMPAT_PADDING_MID ++ #define __PTHREAD_COMPAT_PADDING_END ++ #define __PTHREAD_MUTEX_LOCK_ELISION 0 ++ #define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 ++ #define __PTHREAD_MUTEX_USE_UNION 0 ++ ++ __PTHREAD_MUTEX_LOCK_ELISION can be set to 1 if the hardware plans to ++ eventually support lock elision using transactional memory. ++ ++ 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. ++ ++ And finally the internal pthread_rwlock_t (struct __pthread_rwlock_arch_t) ++ must be defined. ++ */ ++#include ++ ++/* Common definition of pthread_mutex_t. */ ++ ++#if !__PTHREAD_MUTEX_USE_UNION ++typedef struct __pthread_internal_list ++{ ++ struct __pthread_internal_list *__prev; ++ struct __pthread_internal_list *__next; ++} __pthread_list_t; ++#else ++typedef struct __pthread_internal_slist ++{ ++ struct __pthread_internal_slist *__next; ++} __pthread_slist_t; ++#endif ++ ++/* Lock elision support. */ ++#if __PTHREAD_MUTEX_LOCK_ELISION ++# if !__PTHREAD_MUTEX_USE_UNION ++# define __PTHREAD_SPINS_DATA \ ++ short __spins; \ ++ short __elision ++# define __PTHREAD_SPINS 0, 0 ++# else ++# define __PTHREAD_SPINS_DATA \ ++ struct \ ++ { \ ++ short __espins; \ ++ short __eelision; \ ++ } __elision_data ++# define __PTHREAD_SPINS { 0, 0 } ++# define __spins __elision_data.__espins ++# define __elision __elision_data.__eelision ++# endif ++#else ++# define __PTHREAD_SPINS_DATA int __spins ++/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */ ++# define __PTHREAD_SPINS 0 ++#endif ++ ++struct __pthread_mutex_s ++{ ++ int __lock __LOCK_ALIGNMENT; ++ unsigned int __count; ++ int __owner; ++#if !__PTHREAD_MUTEX_NUSERS_AFTER_KIND ++ unsigned int __nusers; ++#endif ++ /* KIND must stay at this position in the structure to maintain ++ binary compatibility with static initializers. ++ ++ Concurrency notes: ++ The __kind of a mutex is initialized either by the static ++ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init. ++ ++ After a mutex has been initialized, the __kind of a mutex is usually not ++ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can ++ be enabled. This is done concurrently in the pthread_mutex_*lock functions ++ by using the macro FORCE_ELISION. This macro is only defined for ++ architectures which supports lock elision. ++ ++ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and ++ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set ++ type of a mutex. ++ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set ++ with pthread_mutexattr_settype. ++ After a mutex has been initialized, the functions pthread_mutex_*lock can ++ enable elision - if the mutex-type and the machine supports it - by setting ++ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards ++ the lock / unlock functions are using specific elision code-paths. */ ++ int __kind; ++ __PTHREAD_COMPAT_PADDING_MID ++#if __PTHREAD_MUTEX_NUSERS_AFTER_KIND ++ unsigned int __nusers; ++#endif ++#if !__PTHREAD_MUTEX_USE_UNION ++ __PTHREAD_SPINS_DATA; ++ __pthread_list_t __list; ++# define __PTHREAD_MUTEX_HAVE_PREV 1 ++#else ++ __extension__ union ++ { ++ __PTHREAD_SPINS_DATA; ++ __pthread_slist_t __list; ++ }; ++# define __PTHREAD_MUTEX_HAVE_PREV 0 ++#endif ++ __PTHREAD_COMPAT_PADDING_END ++}; ++ ++ ++/* 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; ++ ++long int __align; ++}; ++ ++#endif /* _THREAD_SHARED_TYPES_H */ +diff --git a/nptl_2_17/internaltypes_2_17.h b/nptl_2_17/internaltypes_2_17.h +new file mode 100644 +index 00000000..603dc01c +--- /dev/null ++++ b/nptl_2_17/internaltypes_2_17.h +@@ -0,0 +1,179 @@ ++/* Copyright (C) 2002-2018 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/kernel-features_2_17.h b/nptl_2_17/kernel-features_2_17.h +new file mode 100644 +index 00000000..299ae0a1 +--- /dev/null ++++ b/nptl_2_17/kernel-features_2_17.h +@@ -0,0 +1,162 @@ ++/* Set flags signalling availability of kernel features based on given ++ kernel version number. ++ Copyright (C) 1999-2018 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 must not contain any C code. At least it must be protected ++ to allow using the file also in assembler files. */ ++ ++#ifndef __LINUX_KERNEL_VERSION_2_17 ++/* We assume the worst; all kernels should be supported. */ ++# define __LINUX_KERNEL_VERSION_2_17 0 ++#endif ++ ++/* We assume for __LINUX_KERNEL_VERSION the same encoding used in ++ linux/version.h. I.e., the major, minor, and subminor all get a ++ byte with the major number being in the highest byte. This means ++ we can do numeric comparisons. ++ ++ In the following we will define certain symbols depending on ++ whether the describes kernel feature is available in the kernel ++ version given by __LINUX_KERNEL_VERSION. We are not always exactly ++ recording the correct versions in which the features were ++ introduced. If somebody cares these values can afterwards be ++ corrected. */ ++ ++/* Some architectures use the socketcall multiplexer for some or all ++ socket-related operations instead of separate syscalls. ++ __ASSUME_SOCKETCALL is defined for such architectures. */ ++ ++/* The changed st_ino field appeared in 2.4.0-test6. However, SH is lame, ++ and still does not have a 64-bit inode field. */ ++#define __ASSUME_ST_INO_64_BIT 1 ++ ++/* The statfs64 syscalls are available in 2.5.74 (but not for alpha). */ ++#define __ASSUME_STATFS64 1 ++ ++/* pselect/ppoll were introduced just after 2.6.16-rc1. On x86_64 and ++ SH this appeared first in 2.6.19-rc1, on ia64 in 2.6.22-rc1. */ ++#define __ASSUME_PSELECT 1 ++ ++/* The *at syscalls were introduced just after 2.6.16-rc1. On PPC ++ they were introduced in 2.6.17-rc1, on SH in 2.6.19-rc1. */ ++#define __ASSUME_ATFCTS 1 ++ ++/* Support for inter-process robust mutexes was added in 2.6.17 (but ++ some architectures lack futex_atomic_cmpxchg_inatomic in some ++ configurations). */ ++#define __ASSUME_SET_ROBUST_LIST 1 ++ ++/* Support for various CLOEXEC and NONBLOCK flags was added in ++ 2.6.27. */ ++#define __ASSUME_IN_NONBLOCK 1 ++ ++/* Support for the FUTEX_CLOCK_REALTIME flag was added in 2.6.29. */ ++#define __ASSUME_FUTEX_CLOCK_REALTIME 1 ++ ++/* Support for preadv and pwritev was added in 2.6.30. */ ++#define __ASSUME_PREADV 1 ++#define __ASSUME_PWRITEV 1 ++ ++ ++/* Support for FUTEX_*_REQUEUE_PI was added in 2.6.31 (but some ++ * architectures lack futex_atomic_cmpxchg_inatomic in some ++ * configurations). */ ++#define __ASSUME_REQUEUE_PI 1 ++ ++/* Support for sendmmsg functionality was added in 3.0. */ ++#define __ASSUME_SENDMMSG 1 ++ ++/* On most architectures, most socket syscalls are supported for all ++ supported kernel versions, but on some socketcall architectures ++ separate syscalls were only added later. */ ++#define __ASSUME_SENDMSG_SYSCALL 1 ++#define __ASSUME_RECVMSG_SYSCALL 1 ++#define __ASSUME_ACCEPT_SYSCALL 1 ++#define __ASSUME_CONNECT_SYSCALL 1 ++#define __ASSUME_RECVFROM_SYSCALL 1 ++#define __ASSUME_SENDTO_SYSCALL 1 ++#define __ASSUME_ACCEPT4_SYSCALL 1 ++#define __ASSUME_RECVMMSG_SYSCALL 1 ++#define __ASSUME_SENDMMSG_SYSCALL 1 ++ ++/* Support for SysV IPC through wired syscalls. All supported architectures ++ either support ipc syscall and/or all the ipc correspondent syscalls. */ ++#define __ASSUME_DIRECT_SYSVIPC_SYSCALLS 1 ++ ++/* Support for p{read,write}v2 was added in 4.6. However Linux default ++ implementation does not assume the __ASSUME_* and instead use a fallback ++ implementation based on p{read,write}v and returning an error for ++ non supported flags. */ ++ ++/* Support for the renameat2 system call was added in kernel 3.15. */ ++#if __LINUX_KERNEL_VERSION >= 0x030F00 ++# define __ASSUME_RENAMEAT2 ++#endif ++ ++/* Support for the execveat syscall was added in 3.19. */ ++#if __LINUX_KERNEL_VERSION >= 0x031300 ++# define __ASSUME_EXECVEAT 1 ++#endif ++ ++#if __LINUX_KERNEL_VERSION >= 0x040400 ++# define __ASSUME_MLOCK2 1 ++#endif ++ ++#if __LINUX_KERNEL_VERSION >= 0x040500 ++# define __ASSUME_COPY_FILE_RANGE 1 ++#endif ++ ++/* Support for statx was added in kernel 4.11. */ ++#if __LINUX_KERNEL_VERSION >= 0x040B00 ++# define __ASSUME_STATX 1 ++#endif ++ ++/* Support for clone call used on fork. The signature varies across the ++ architectures with current 4 different variants: ++ ++ 1. long int clone (unsigned long flags, unsigned long newsp, ++ int *parent_tidptr, unsigned long tls, ++ int *child_tidptr) ++ ++ 2. long int clone (unsigned long newsp, unsigned long clone_flags, ++ int *parent_tidptr, int * child_tidptr, ++ unsigned long tls) ++ ++ 3. long int clone (unsigned long flags, unsigned long newsp, ++ int stack_size, int *parent_tidptr, ++ int *child_tidptr, unsigned long tls) ++ ++ 4. long int clone (unsigned long flags, unsigned long newsp, ++ int *parent_tidptr, int *child_tidptr, ++ unsigned long tls) ++ ++ The fourth variant is intended to be used as the default for newer ports, ++ Also IA64 uses the third variant but with __NR_clone2 instead of ++ __NR_clone. ++ ++ The macros names to define the variant used for the architecture is ++ similar to kernel: ++ ++ - __ASSUME_CLONE_BACKWARDS: for variant 1. ++ - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390). ++ - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze). ++ - __ASSUME_CLONE_DEFAULT: for variant 4. ++ - __ASSUME_CLONE2: for clone2 with variant 3 (ia64). ++ */ ++ ++#define __ASSUME_CLONE_DEFAULT 1 +diff --git a/nptl_2_17/pthreadP_2_17.h b/nptl_2_17/pthreadP_2_17.h +new file mode 100644 +index 00000000..3050fa54 +--- /dev/null ++++ b/nptl_2_17/pthreadP_2_17.h +@@ -0,0 +1,714 @@ ++/* Copyright (C) 2002-2018 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 "kernel-features_2_17.h" ++#include "pthread_2_17.h" ++#include "internaltypes_2_17.h" ++ ++#include ++#include ++#include ++#include "descr.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 ++ ++ ++/* Adaptive mutex definitions. */ ++#ifndef MAX_ADAPTIVE_COUNT ++# define MAX_ADAPTIVE_COUNT 100 ++#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) ++ ++ ++/* 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__)) ++ weak_function; ++extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) ++ __cleanup_fct_attribute __attribute ((__noreturn__)) ++ weak_function; ++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)); ++} ++ ++ ++/* Set cancellation mode to asynchronous. */ ++#define CANCEL_ASYNC() \ ++ __pthread_enable_asynccancel () ++/* Reset to previous cancellation mode. */ ++#define CANCEL_RESET(oldtype) \ ++ __pthread_disable_asynccancel (oldtype) ++ ++# undef LIBC_CANCEL_ASYNC ++# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC () ++ ++# undef LIBC_CANCEL_RESET ++# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val) ++ ++# define LIBC_CANCEL_HANDLED() \ ++ __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \ ++ __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel") ++ ++ ++/* 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 ++ ++/* Find a thread given its TID. */ ++extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden ++#ifdef SHARED ++; ++#else ++weak_function; ++#define __find_thread_by_id(tid) \ ++ (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL) ++#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_cond_clockwait (pthread_cond_t *cond, ++ pthread_mutex_t *mutex, ++ clockid_t clockid, ++ const struct timespec *abstime) ++ __nonnull ((1, 2, 4)); ++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_timedjoin_ex (pthread_t, void **, const struct timespec *, ++ bool); ++ ++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) ++hidden_proto (__pthread_timedjoin_ex) ++ ++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); ++ ++/* The two functions are in libc.so and not exported. */ ++extern int __libc_enable_asynccancel (void) attribute_hidden; ++extern void __libc_disable_asynccancel (int oldtype) attribute_hidden; ++ ++ ++/* The two functions are in librt.so and not exported. */ ++extern int __librt_enable_asynccancel (void) attribute_hidden; ++extern void __librt_disable_asynccancel (int oldtype) attribute_hidden; ++ ++/* 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)); } ++ ++# if defined __EXCEPTIONS && !defined __cplusplus ++/* Structure to hold the cleanup handler information. */ ++struct __pthread_cleanup_combined_frame ++{ ++ void (*__cancel_routine) (void *); ++ void *__cancel_arg; ++ int __do_it; ++ struct _pthread_cleanup_buffer __buffer; ++}; ++ ++/* Special cleanup macros which register cleanup both using ++ __pthread_cleanup_{push,pop} and using cleanup attribute. This is needed ++ for pthread_once, so that it supports both throwing exceptions from the ++ pthread_once callback (only cleanup attribute works there) and cancellation ++ of the thread running the callback if the callback or some routines it ++ calls don't have unwind information. */ ++ ++static __always_inline void ++__pthread_cleanup_combined_routine (struct __pthread_cleanup_combined_frame ++ *__frame) ++{ ++ if (__frame->__do_it) ++ { ++ __frame->__cancel_routine (__frame->__cancel_arg); ++ __frame->__do_it = 0; ++ __pthread_cleanup_pop (&__frame->__buffer, 0); ++ } ++} ++ ++static inline void ++__pthread_cleanup_combined_routine_voidptr (void *__arg) ++{ ++ struct __pthread_cleanup_combined_frame *__frame ++ = (struct __pthread_cleanup_combined_frame *) __arg; ++ if (__frame->__do_it) ++ { ++ __frame->__cancel_routine (__frame->__cancel_arg); ++ __frame->__do_it = 0; ++ } ++} ++ ++# define pthread_cleanup_combined_push(routine, arg) \ ++ do { \ ++ void (*__cancel_routine) (void *) = (routine); \ ++ struct __pthread_cleanup_combined_frame __clframe \ ++ __attribute__ ((__cleanup__ (__pthread_cleanup_combined_routine))) \ ++ = { .__cancel_routine = __cancel_routine, .__cancel_arg = (arg), \ ++ .__do_it = 1 }; \ ++ __pthread_cleanup_push (&__clframe.__buffer, \ ++ __pthread_cleanup_combined_routine_voidptr, \ ++ &__clframe); ++ ++# define pthread_cleanup_combined_pop(execute) \ ++ __pthread_cleanup_pop (&__clframe.__buffer, 0); \ ++ __clframe.__do_it = 0; \ ++ if (execute) \ ++ __cancel_routine (__clframe.__cancel_arg); \ ++ } while (0) ++ ++# endif ++ ++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)) ++ ++#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..3cb871a2 +--- /dev/null ++++ b/nptl_2_17/pthread_2_17.h +@@ -0,0 +1,1175 @@ ++/* Copyright (C) 2002-2018 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 "bits/pthreadtypes_2_17.h" ++ ++#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 ++ ++ ++#if __PTHREAD_MUTEX_HAVE_PREV ++# define PTHREAD_MUTEX_INITIALIZER \ ++ { { 0, 0, 0, 0, 0, __PTHREAD_SPINS, { 0, 0 } } } ++# ifdef __USE_GNU ++# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } ++# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __PTHREAD_SPINS, { 0, 0 } } } ++# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } ++ ++# endif ++#else ++# define PTHREAD_MUTEX_INITIALIZER \ ++ { { 0, 0, 0, 0, 0, { __PTHREAD_SPINS } } } ++# ifdef __USE_GNU ++# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { __PTHREAD_SPINS } } } ++# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { __PTHREAD_SPINS } } } ++# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ ++ { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { __PTHREAD_SPINS } } } ++ ++# endif ++#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 ++}; ++ ++/* Define __PTHREAD_RWLOCK_INT_FLAGS_SHARED to 1 if pthread_rwlock_t ++ has the shared field. All 64-bit architectures have the shared field ++ in pthread_rwlock_t. */ ++#ifndef __PTHREAD_RWLOCK_INT_FLAGS_SHARED ++# if __WORDSIZE == 64 ++# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1 ++# endif ++#endif ++ ++/* Read-write lock initializers. */ ++# define PTHREAD_RWLOCK_INITIALIZER \ ++ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } } ++# ifdef __USE_GNU ++# ifdef __PTHREAD_RWLOCK_INT_FLAGS_SHARED ++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, \ ++ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } ++# else ++# if __BYTE_ORDER == __LITTLE_ENDIAN ++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \ ++ 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } } ++# else ++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ ++ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\ ++ 0 } } ++# endif ++# endif ++# 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); ++#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 ++ ++/* 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 ++ ++/* 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 ++ ++/* 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)); ++ ++/* 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)); ++ ++/* 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 */ +-- +2.30.0 + diff --git a/0003-add-build-script-and-files-of-libpthread_2_17_so.patch b/0003-add-build-script-and-files-of-libpthread_2_17_so.patch new file mode 100644 index 0000000..75ca704 --- /dev/null +++ b/0003-add-build-script-and-files-of-libpthread_2_17_so.patch @@ -0,0 +1,135 @@ +From 7cb15fbef45361db6ad718077a4f0a6d2dc845f2 Mon Sep 17 00:00:00 2001 +From: Yang Yanchao +Date: Wed Nov 24 09:31:31 2021 +0800 +Subject: [PATCH 3/9] build extra lipthreadcond so + +Add the build script and file of libpthread-2.17.so + +--- + nptl_2_17/Makefile | 52 +++++++++++++++++++++++++++ + nptl_2_17/build_libpthread-2.17.so.sh | 10 ++++++ + nptl_2_17/libpthread-2.17-aarch64.map | 14 ++++++++ + nptl_2_17/libpthread-2.17-x86_64.map | 14 ++++++++ + 4 files changed, 90 insertions(+) + create mode 100644 nptl_2_17/Makefile + create mode 100644 nptl_2_17/build_libpthread-2.17.so.sh + create mode 100644 nptl_2_17/libpthread-2.17-aarch64.map + create mode 100644 nptl_2_17/libpthread-2.17-x86_64.map + +diff --git a/nptl_2_17/Makefile b/nptl_2_17/Makefile +new file mode 100644 +index 00000000..f248ce56 +--- /dev/null ++++ b/nptl_2_17/Makefile +@@ -0,0 +1,52 @@ ++include libpthread-2.17_config ++subdir=libpthread-2.17 ++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 = pthread_cond_wait_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 pthread_condattr_getclock_2_17.os pthread_condattr_getpshared_2_17.os pthread_condattr_init_2_17.os pthread_condattr_setclock_2_17.os cleanup_compat_2_17.os pthread_mutex_lock_2_17.os pthread_mutex_unlock_2_17.os tpp_2_17.os vars_2_17.os pause_nocancel_2_17.os lll_timedlock_wait_2_17.os pthread_mutex_cond_lock_2_17.os cancellation_2_17.os lowlevellock_2_17.os unwind_2_17.os ++ ++ifeq (x86_64, $(arch)) ++compile_obj += elision-timed_2_17.os elision-trylock_2_17.os elision-lock_2_17.os elision-unlock_2_17.os ++endif ++ ++exist_obj_dir = $(foreach n,$(exist_obj),../$(build_dir)/nptl/$(n)) ++ ++compile_obj_dir = $(foreach n,$(compile_obj),../$(build_dir)/nptl/$(n)) ++ ++CFLAGS = -c -std=gnu11 -fgnu89-inline -fPIE -DNDEBUG -O2 -Wall -Werror -Wp,-D_GLIBCXX_ASSERTIONS -Wundef -Wwrite-strings -fasynchronous-unwind-tables -fmerge-all-constants -frounding-math -fstack-clash-protection -fstack-protector-strong -g -mtune=generic -Wstrict-prototypes -Wold-style-definition -fno-math-errno -fPIC -fexceptions -fasynchronous-unwind-tables -ftls-model=initial-exec -D_FORTIFY_SOURCE=2 -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: libpthread-2.17.so ++ ++libpthread-2.17.so : $(compile_obj) libpthread-2.17_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=libpthread-2.17-$(arch).map -Wl,-soname=libpthread-2.17.so.0 -Wl,-z,noexecstack -Wtrampolines -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -Wl,-z,now -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst -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/libpthread-2.17.so ../$(build_dir)/csu/abi-note.o -Wl,--whole-archive ../$(build_dir)/nptl/libpthread-2.17_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 ++ ++libpthread-2.17_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/build_libpthread-2.17.so.sh b/nptl_2_17/build_libpthread-2.17.so.sh +new file mode 100644 +index 00000000..bdb97d0f +--- /dev/null ++++ b/nptl_2_17/build_libpthread-2.17.so.sh +@@ -0,0 +1,10 @@ ++#!/bin/sh ++set -e ++build_arch=$1 ++build_dir=$2 ++config_dir=libpthread-2.17_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/libpthread-2.17-aarch64.map b/nptl_2_17/libpthread-2.17-aarch64.map +new file mode 100644 +index 00000000..2c49fe17 +--- /dev/null ++++ b/nptl_2_17/libpthread-2.17-aarch64.map +@@ -0,0 +1,14 @@ ++GLIBC_2.17 { ++ global: ++ pthread_cond_init; pthread_cond_destroy; ++ pthread_cond_signal; pthread_cond_broadcast; ++ pthread_cond_wait; pthread_cond_timedwait; ++ local: ++ *; ++}; ++GLIBC_2.34 { ++ global: ++ pthread_cond_clockwait; ++ local: ++ *; ++}; +diff --git a/nptl_2_17/libpthread-2.17-x86_64.map b/nptl_2_17/libpthread-2.17-x86_64.map +new file mode 100644 +index 00000000..b01e7d0d +--- /dev/null ++++ b/nptl_2_17/libpthread-2.17-x86_64.map +@@ -0,0 +1,14 @@ ++GLIBC_2.3.2 { ++ global: ++ pthread_cond_init; pthread_cond_destroy; ++ pthread_cond_signal; pthread_cond_broadcast; ++ pthread_cond_wait; pthread_cond_timedwait; ++ local: ++ *; ++}; ++GLIBC_2.34 { ++ global: ++ pthread_cond_clockwait; ++ local: ++ *; ++}; +-- +2.30.0 + diff --git a/0004-add-two-header-files-with-some-deleted-macros.patch b/0004-add-two-header-files-with-some-deleted-macros.patch new file mode 100644 index 0000000..7acb8e2 --- /dev/null +++ b/0004-add-two-header-files-with-some-deleted-macros.patch @@ -0,0 +1,166 @@ +From d6e6184b4f10ef2cbdec09eae60350ced71e3de7 Mon Sep 17 00:00:00 2001 +From: Yang Yanchao +Date: Wed Nov 24 09:31:31 2021 +0800 +Subject: [PATCH 4/9] build extra lipthreadcond so + +For compatibility with glibc2.17, two header files are added with some +deleted macros. + +--- + nptl_2_17/compat_pthread_2_17.h | 61 +++++++++++++++++++++++++++ + nptl_2_17/old_macros_2_17.h | 75 +++++++++++++++++++++++++++++++++ + 2 files changed, 136 insertions(+) + create mode 100644 nptl_2_17/compat_pthread_2_17.h + create mode 100644 nptl_2_17/old_macros_2_17.h + +diff --git a/nptl_2_17/compat_pthread_2_17.h b/nptl_2_17/compat_pthread_2_17.h +new file mode 100644 +index 00000000..d13051ba +--- /dev/null ++++ b/nptl_2_17/compat_pthread_2_17.h +@@ -0,0 +1,61 @@ ++#ifndef _COMPAT_PTHREAD_2_17_H ++#define _COMPAT_PTHREAD_2_17_H 1 ++ ++#include ++#include ++ ++#ifdef __x86_64__ ++#define __PTHREAD_COMPAT_PADDING_MID ++#define __PTHREAD_COMPAT_PADDING_END ++#define __PTHREAD_MUTEX_LOCK_ELISION 1 ++# define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 ++# define __PTHREAD_MUTEX_USE_UNION 0 ++//# define ENABLE_ELISION_SUPPORT 1 ++#else ++#define __PTHREAD_COMPAT_PADDING_MID ++#define __PTHREAD_COMPAT_PADDING_END ++#define __PTHREAD_MUTEX_LOCK_ELISION 0 ++#define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 ++#define __PTHREAD_MUTEX_USE_UNION 0 ++#endif ++ ++#define CANCELSTATE_BIT 0 ++#define CANCELSTATE_BITMASK (0x01 << CANCELSTATE_BIT) ++ /* Bit set if asynchronous cancellation mode is selected. */ ++#define CANCELTYPE_BIT 1 ++#define CANCELTYPE_BITMASK (0x01 << CANCELTYPE_BIT) ++ /* Bit set if canceling has been initiated. */ ++#define CANCELING_BIT 2 ++#define CANCELING_BITMASK (0x01 << CANCELING_BIT) ++ /* Bit set if canceled. */ ++#define CANCELED_BIT 3 ++#define CANCELED_BITMASK (0x01 << CANCELED_BIT) ++ /* Bit set if thread is exiting. */ ++#define EXITING_BIT 4 ++#define EXITING_BITMASK (0x01 << EXITING_BIT) ++ /* Bit set if thread terminated and TCB is freed. */ ++#define TERMINATED_BIT 5 ++#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT) ++ /* Bit set if thread is supposed to change XID. */ ++#define SETXID_BIT 6 ++#define SETXID_BITMASK (0x01 << SETXID_BIT) ++ /* Mask for the rest. Helps the compiler to optimize. */ ++#define CANCEL_RESTMASK 0xffffff80 ++ ++ ++#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \ ++ (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK \ ++ | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK)) \ ++ == (CANCELTYPE_BITMASK | CANCELED_BITMASK)) ++ ++# define INTERNAL_SYSCALL_DECL(err) do { } while (0) ++ ++/* ++ * __pause_nocancel delete by fbb4a3143724ef3f044a4f05351,add it ++ */ ++ ++__typeof (pause) __pause_nocancel; ++hidden_proto (__pause_nocancel) ++ ++#endif ++ +diff --git a/nptl_2_17/old_macros_2_17.h b/nptl_2_17/old_macros_2_17.h +new file mode 100644 +index 00000000..334b2ab1 +--- /dev/null ++++ b/nptl_2_17/old_macros_2_17.h +@@ -0,0 +1,75 @@ ++#ifndef _OLD_MACROS_2_17_H ++#define _OLD_MACROS_2_17_H 1 ++ ++/* ++ * Contains macros that have been defined in glibc2.34. ++ * Cancel the definition and use the old version. ++ * This header file needs to be included at the end. ++ */ ++#undef __lll_unlock ++#define __lll_unlock(futex, private) \ ++ ((void) \ ++ ({ \ ++ int *__futex = (futex); \ ++ int __private = (private); \ ++ int __oldval = atomic_exchange_rel (__futex, 0); \ ++ if (__glibc_unlikely (__oldval > 1)) \ ++ lll_futex_wake (__futex, 1, __private); \ ++ })) ++ ++#undef lll_unlock ++#define lll_unlock(futex, private) \ ++ __lll_unlock (&(futex), private) ++ ++extern int __lll_timedlock_wait (int *futex, const struct timespec *, ++ int private) attribute_hidden; ++ ++ ++/* As __lll_lock, but with a timeout. If the timeout occurs then return ++ ETIMEDOUT. If ABSTIME is invalid, return EINVAL. */ ++#define __lll_timedlock(futex, abstime, private) \ ++ ({ \ ++ int *__futex = (futex); \ ++ int __val = 0; \ ++ \ ++ if (__glibc_unlikely \ ++ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \ ++ __val = __lll_timedlock_wait (__futex, abstime, private); \ ++ __val; \ ++ }) ++#define lll_timedlock(futex, abstime, private) \ ++ __lll_timedlock (&(futex), abstime, private) ++ ++/* Verify whether the supplied clockid is supported by ++ lll_futex_clock_wait_bitset. */ ++#define lll_futex_supported_clockid(clockid) \ ++ ((clockid) == CLOCK_REALTIME || (clockid) == CLOCK_MONOTONIC) ++ ++/* The kernel currently only supports CLOCK_MONOTONIC or ++ CLOCK_REALTIME timeouts for FUTEX_WAIT_BITSET. We could attempt to ++ convert others here but currently do not. */ ++#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \ ++ ({ \ ++ long int __ret; \ ++ if (lll_futex_supported_clockid (clockid)) \ ++ { \ ++ const unsigned int clockbit = \ ++ (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0; \ ++ const int op = \ ++ __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private); \ ++ \ ++ __ret = lll_futex_syscall (6, futexp, op, val, \ ++ timeout, NULL /* Unused. */, \ ++ FUTEX_BITSET_MATCH_ANY); \ ++ } \ ++ else \ ++ __ret = -EINVAL; \ ++ __ret; \ ++ }) ++ ++# undef INTERNAL_VSYSCALL ++# define INTERNAL_VSYSCALL INTERNAL_SYSCALL ++# undef INLINE_VSYSCALL ++# define INLINE_VSYSCALL INLINE_SYSCALL ++ ++#endif +-- +2.30.0 + diff --git a/0005-add-pthread-functions_h.patch b/0005-add-pthread-functions_h.patch new file mode 100644 index 0000000..f169140 --- /dev/null +++ b/0005-add-pthread-functions_h.patch @@ -0,0 +1,140 @@ +From 463dc947b4f9bc4137c9919ee72b896403926474 Mon Sep 17 00:00:00 2001 +From: Roland McGrath +Date: Thu Jun 12 13:48:47 2014 -0700 +Subject: [PATCH 5/9] build extra lipthreadcond so + +add pthread-functions.h which delete by 1d67cf9e8a0194588e66fb3b7afcbdc3bf836a + +--- + nptl_2_17/pthread-functions_2_17.h | 119 +++++++++++++++++++++++++++++ + 1 file changed, 119 insertions(+) + create mode 100644 nptl_2_17/pthread-functions_2_17.h + +diff --git a/nptl_2_17/pthread-functions_2_17.h b/nptl_2_17/pthread-functions_2_17.h +new file mode 100644 +index 00000000..07ca8e7e +--- /dev/null ++++ b/nptl_2_17/pthread-functions_2_17.h +@@ -0,0 +1,119 @@ ++/* Copyright (C) 2003-2018 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 ++ . */ ++ ++#ifndef _PTHREAD_FUNCTIONS_H ++#define _PTHREAD_FUNCTIONS_H 1 ++ ++#include ++#include ++#include ++#include ++ ++struct xid_command; ++ ++/* Data type shared with libc. The libc uses it to pass on calls to ++ the thread functions. */ ++struct pthread_functions ++{ ++ int (*ptr_pthread_attr_destroy) (pthread_attr_t *); ++ int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *); ++ int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *); ++ int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); ++ int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); ++ int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); ++ int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); ++ int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, ++ struct sched_param *); ++ int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, ++ const struct sched_param *); ++ int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); ++ int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); ++ int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); ++ int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); ++ int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); ++ int (*ptr_pthread_condattr_init) (pthread_condattr_t *); ++ int (*ptr___pthread_cond_broadcast) (pthread_cond_t *); ++ int (*ptr___pthread_cond_destroy) (pthread_cond_t *); ++ int (*ptr___pthread_cond_init) (pthread_cond_t *, ++ const pthread_condattr_t *); ++ int (*ptr___pthread_cond_signal) (pthread_cond_t *); ++ int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); ++ int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, ++ const struct timespec *); ++ int (*ptr___pthread_cond_clockwait) (pthread_cond_t *, ++ pthread_mutex_t *, ++ clockid_t, ++ const struct timespec *); ++ int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *); ++ int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *); ++ int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *, ++ const pthread_condattr_t *); ++ int (*ptr___pthread_cond_signal_2_0) (pthread_cond_2_0_t *); ++ int (*ptr___pthread_cond_wait_2_0) (pthread_cond_2_0_t *, pthread_mutex_t *); ++ int (*ptr___pthread_cond_timedwait_2_0) (pthread_cond_2_0_t *, ++ pthread_mutex_t *, ++ const struct timespec *); ++ int (*ptr_pthread_equal) (pthread_t, pthread_t); ++ void (*ptr___pthread_exit) (void *) __attribute__ ((__noreturn__)); ++ int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); ++ int (*ptr_pthread_setschedparam) (pthread_t, int, ++ const struct sched_param *); ++ int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); ++ int (*ptr_pthread_mutex_init) (pthread_mutex_t *, ++ const pthread_mutexattr_t *); ++ int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); ++ int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); ++ int (*ptr___pthread_setcancelstate) (int, int *); ++ int (*ptr_pthread_setcanceltype) (int, int *); ++ void (*ptr___pthread_cleanup_upto) (__jmp_buf, char *); ++ int (*ptr___pthread_once) (pthread_once_t *, void (*) (void)); ++ int (*ptr___pthread_rwlock_rdlock) (pthread_rwlock_t *); ++ int (*ptr___pthread_rwlock_wrlock) (pthread_rwlock_t *); ++ int (*ptr___pthread_rwlock_unlock) (pthread_rwlock_t *); ++ int (*ptr___pthread_key_create) (pthread_key_t *, void (*) (void *)); ++ void *(*ptr___pthread_getspecific) (pthread_key_t); ++ int (*ptr___pthread_setspecific) (pthread_key_t, const void *); ++ void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer *, ++ void (*) (void *), void *); ++ void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer *, ++ int); ++#define HAVE_PTR_NTHREADS ++ unsigned int *ptr_nthreads; ++ void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *) ++ __attribute ((noreturn)) __cleanup_fct_attribute; ++ void (*ptr__nptl_deallocate_tsd) (void); ++ int (*ptr__nptl_setxid) (struct xid_command *); ++ void (*ptr_set_robust) (struct pthread *); ++}; ++ ++/* Variable in libc.so. */ ++extern struct pthread_functions __libc_pthread_functions attribute_hidden; ++extern int __libc_pthread_functions_init attribute_hidden; ++ ++#ifdef PTR_DEMANGLE ++# define PTHFCT_CALL(fct, params) \ ++ ({ __typeof (__libc_pthread_functions.fct) __p; \ ++ __p = __libc_pthread_functions.fct; \ ++ PTR_DEMANGLE (__p); \ ++ __p params; }) ++#else ++# define PTHFCT_CALL(fct, params) \ ++ __libc_pthread_functions.fct params ++#endif ++ ++#endif /* pthread-functions.h */ +-- +2.30.0 + diff --git a/0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch b/0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch new file mode 100644 index 0000000..e60fc08 --- /dev/null +++ b/0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch @@ -0,0 +1,587 @@ +From 1cdbe579482c07e9f4bb3baa4864da2d3e7eb837 Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Sat, 10 Nov 2012 00:51:26 -0800i +Subject: [PATCH 6/9] build extra lipthreadcond so + +add elsion functions which moved to libc in glibc-2.34. +Some attributes are changed and cannot be directly referenced. + + +--- + nptl_2_17/lll_timedlock_wait_2_17.c | 59 +++++++++++++++++++++++++++++ + nptl_2_17/elision-conf_2_17.c | 138 +++++++++++++++++++++++++++++++ + nptl_2_17/elision-lock_2_17.c | 107 ++++++++++++++++++++++++ + nptl_2_17/elision-timed_2_17.c | 27 ++++++ + nptl_2_17/elision-trylock_2_17.c | 75 +++++++++++++++++ + nptl_2_17/elision-unlock_2_17.c | 34 ++++++++ + nptl_2_17/hle_2_17.h | 75 +++++++++++++++++ + 6 files changed, 515 + insertions(+) + create mode 100644 nptl_2_17/lll_timedlock_wait_2_17.c + create mode 100644 nptl_2_17/elision-conf_2_17.c + create mode 100644 nptl_2_17/elision-lock_2_17.c + create mode 100644 nptl_2_17/elision-timed_2_17.c + create mode 100644 nptl_2_17/elision-trylock_2_17.c + create mode 100644 nptl_2_17/elision-unlock_2_17.c + create mode 100644 nptl_2_17/hle_2_17.h + +diff --git a/nptl_2_17/lll_timedlock_wait_2_17.c b/nptl_2_17/lll_timedlock_wait_2_17.c +new file mode 100644 +index 00000000..91bf9637 +--- /dev/null ++++ b/nptl_2_17/lll_timedlock_wait_2_17.c +@@ -0,0 +1,59 @@ ++/* Timed low level locking for pthread library. Generic futex-using version. ++ Copyright (C) 2003-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Paul Mackerras , 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 ++ ++ ++int ++__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) ++{ ++ /* Reject invalid timeouts. */ ++ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) ++ return EINVAL; ++ ++ /* Try locking. */ ++ while (atomic_exchange_acq (futex, 2) != 0) ++ { ++ struct timeval tv; ++ ++ /* Get the current time. */ ++ (void) __gettimeofday (&tv, NULL); ++ ++ /* Compute relative timeout. */ ++ struct timespec rt; ++ rt.tv_sec = abstime->tv_sec - tv.tv_sec; ++ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; ++ if (rt.tv_nsec < 0) ++ { ++ rt.tv_nsec += 1000000000; ++ --rt.tv_sec; ++ } ++ ++ if (rt.tv_sec < 0) ++ return ETIMEDOUT; ++ ++ /* If *futex == 2, wait until woken or timeout. */ ++ lll_futex_timed_wait (futex, 2, &rt, private); ++ } ++ ++ return 0; ++} +diff --git a/nptl_2_17/elision-conf_2_17.c b/nptl_2_17/elision-conf_2_17.c +new file mode 100644 +index 00000000..22af2944 +--- /dev/null ++++ b/nptl_2_17/elision-conf_2_17.c +@@ -0,0 +1,138 @@ ++/* elision-conf.c: Lock elision tunable parameters. ++ Copyright (C) 2013-2018 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 "config.h" ++#include ++#include ++#include ++#include ++ ++#if HAVE_TUNABLES ++# define TUNABLE_NAMESPACE elision ++#endif ++#include ++ ++/* Reasonable initial tuning values, may be revised in the future. ++ This is a conservative initial value. */ ++ ++struct elision_config __elision_aconf = ++ { ++ /* How often to not attempt to use elision if a transaction aborted ++ because the lock is already acquired. Expressed in number of lock ++ acquisition attempts. */ ++ .skip_lock_busy = 3, ++ /* How often to not attempt to use elision if a transaction aborted due ++ to reasons other than other threads' memory accesses. Expressed in ++ number of lock acquisition attempts. */ ++ .skip_lock_internal_abort = 3, ++ /* How often we retry using elision if there is chance for the transaction ++ to finish execution (e.g., it wasn't aborted due to the lock being ++ already acquired. */ ++ .retry_try_xbegin = 3, ++ /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock. */ ++ .skip_trylock_internal_abort = 3, ++ }; ++ ++/* Force elision for all new locks. This is used to decide whether existing ++ DEFAULT locks should be automatically upgraded to elision in ++ pthread_mutex_lock(). Disabled for suid programs. Only used when elision ++ is available. */ ++ ++int __pthread_force_elision attribute_hidden = 0; ++ ++#if HAVE_TUNABLES ++static inline void ++__always_inline ++do_set_elision_enable (int32_t elision_enable) ++{ ++ /* Enable elision if it's avaliable in hardware. It's not necessary to check ++ if __libc_enable_secure isn't enabled since elision_enable will be set ++ according to the default, which is disabled. */ ++ if (elision_enable == 1) ++ __pthread_force_elision = HAS_CPU_FEATURE (RTM) ? 1 : 0; ++} ++ ++/* The pthread->elision_enable tunable is 0 or 1 indicating that elision ++ should be disabled or enabled respectively. The feature will only be used ++ if it's supported by the hardware. */ ++ ++void ++TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *valp) ++{ ++ int32_t elision_enable = (int32_t) valp->numval; ++ do_set_elision_enable (elision_enable); ++} ++ ++#define TUNABLE_CALLBACK_FNDECL(__name, __type) \ ++static inline void \ ++__always_inline \ ++do_set_elision_ ## __name (__type value) \ ++{ \ ++ __elision_aconf.__name = value; \ ++} \ ++void \ ++TUNABLE_CALLBACK (set_elision_ ## __name) (tunable_val_t *valp) \ ++{ \ ++ __type value = (__type) (valp)->numval; \ ++ do_set_elision_ ## __name (value); \ ++} ++ ++TUNABLE_CALLBACK_FNDECL (skip_lock_busy, int32_t); ++TUNABLE_CALLBACK_FNDECL (skip_lock_internal_abort, int32_t); ++TUNABLE_CALLBACK_FNDECL (retry_try_xbegin, int32_t); ++TUNABLE_CALLBACK_FNDECL (skip_trylock_internal_abort, int32_t); ++#endif ++ ++/* Initialize elision. */ ++ ++static void ++elision_init (int argc __attribute__ ((unused)), ++ char **argv __attribute__ ((unused)), ++ char **environ) ++{ ++#if HAVE_TUNABLES ++ /* Elision depends on tunables and must be explicitly turned on by setting ++ the appropriate tunable on a supported platform. */ ++ ++ TUNABLE_GET (enable, int32_t, ++ TUNABLE_CALLBACK (set_elision_enable)); ++ TUNABLE_GET (skip_lock_busy, int32_t, ++ TUNABLE_CALLBACK (set_elision_skip_lock_busy)); ++ TUNABLE_GET (skip_lock_internal_abort, int32_t, ++ TUNABLE_CALLBACK (set_elision_skip_lock_internal_abort)); ++ TUNABLE_GET (tries, int32_t, ++ TUNABLE_CALLBACK (set_elision_retry_try_xbegin)); ++ TUNABLE_GET (skip_trylock_internal_abort, int32_t, ++ TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort)); ++#endif ++ ++ if (!__pthread_force_elision) ++ __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks. */ ++} ++ ++#ifdef SHARED ++# define INIT_SECTION ".init_array" ++#else ++# define INIT_SECTION ".preinit_array" ++#endif ++ ++void (*const __pthread_init_array []) (int, char **, char **) ++ __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) = ++{ ++ &elision_init ++}; +diff --git a/nptl_2_17/elision-lock_2_17.c b/nptl_2_17/elision-lock_2_17.c +new file mode 100644 +index 00000000..e6dbbc21 +--- /dev/null ++++ b/nptl_2_17/elision-lock_2_17.c +@@ -0,0 +1,107 @@ ++/* elision-lock.c: Elided pthread mutex lock. ++ Copyright (C) 2011-2018 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 "pthreadP_2_17.h" ++#include "lowlevellock.h" ++#include "hle_2_17.h" ++#include ++ ++#if !defined(LLL_LOCK) && !defined(EXTRAARG) ++/* Make sure the configuration code is always linked in for static ++ libraries. */ ++#include "elision-conf_2_17.c" ++#endif ++ ++#ifndef EXTRAARG ++#define EXTRAARG ++#endif ++#ifndef LLL_LOCK ++#define LLL_LOCK(a,b) lll_lock(a,b), 0 ++#endif ++ ++#define aconf __elision_aconf ++ ++/* Adaptive lock using transactions. ++ By default the lock region is run as a transaction, and when it ++ aborts or the lock is busy the lock adapts itself. */ ++ ++int ++__lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int private) ++{ ++ /* adapt_count can be accessed concurrently; these accesses can be both ++ inside of transactions (if critical sections are nested and the outer ++ critical section uses lock elision) and outside of transactions. Thus, ++ we need to use atomic accesses to avoid data races. However, the ++ value of adapt_count is just a hint, so relaxed MO accesses are ++ sufficient. */ ++ if (atomic_load_relaxed (adapt_count) <= 0) ++ { ++ unsigned status; ++ int try_xbegin; ++ ++ for (try_xbegin = aconf.retry_try_xbegin; ++ try_xbegin > 0; ++ try_xbegin--) ++ { ++ if ((status = _xbegin()) == _XBEGIN_STARTED) ++ { ++ if (*futex == 0) ++ return 0; ++ ++ /* Lock was busy. Fall back to normal locking. ++ Could also _xend here but xabort with 0xff code ++ is more visible in the profiler. */ ++ _xabort (_ABORT_LOCK_BUSY); ++ } ++ ++ if (!(status & _XABORT_RETRY)) ++ { ++ if ((status & _XABORT_EXPLICIT) ++ && _XABORT_CODE (status) == _ABORT_LOCK_BUSY) ++ { ++ /* Right now we skip here. Better would be to wait a bit ++ and retry. This likely needs some spinning. See ++ above for why relaxed MO is sufficient. */ ++ if (atomic_load_relaxed (adapt_count) ++ != aconf.skip_lock_busy) ++ atomic_store_relaxed (adapt_count, aconf.skip_lock_busy); ++ } ++ /* Internal abort. There is no chance for retry. ++ Use the normal locking and next time use lock. ++ Be careful to avoid writing to the lock. See above for why ++ relaxed MO is sufficient. */ ++ else if (atomic_load_relaxed (adapt_count) ++ != aconf.skip_lock_internal_abort) ++ atomic_store_relaxed (adapt_count, ++ aconf.skip_lock_internal_abort); ++ break; ++ } ++ } ++ } ++ else ++ { ++ /* Use a normal lock until the threshold counter runs out. ++ Lost updates possible. */ ++ atomic_store_relaxed (adapt_count, ++ atomic_load_relaxed (adapt_count) - 1); ++ } ++ ++ /* Use a normal lock here. */ ++ return LLL_LOCK ((*futex), private); ++} +diff --git a/nptl_2_17/elision-timed_2_17.c b/nptl_2_17/elision-timed_2_17.c +new file mode 100644 +index 00000000..5050f2d1 +--- /dev/null ++++ b/nptl_2_17/elision-timed_2_17.c +@@ -0,0 +1,27 @@ ++/* elision-timed.c: Lock elision timed lock. ++ Copyright (C) 2013-2018 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 "lowlevellock.h" ++#include ++#define __lll_lock_elision __lll_timedlock_elision ++#define EXTRAARG const struct timespec *t, ++#undef LLL_LOCK ++#define LLL_LOCK(a, b) lll_timedlock(a, t, b) ++#include "elision-lock_2_17.c" +diff --git a/nptl_2_17/elision-trylock_2_17.c b/nptl_2_17/elision-trylock_2_17.c +new file mode 100644 +index 00000000..70d8f8b9 +--- /dev/null ++++ b/nptl_2_17/elision-trylock_2_17.c +@@ -0,0 +1,75 @@ ++/* elision-trylock.c: Lock eliding trylock for pthreads. ++ Copyright (C) 2013-2018 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 "hle_2_17.h" ++#include ++ ++#define aconf __elision_aconf ++ ++/* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is ++ the adaptation counter in the mutex. */ ++ ++int ++__lll_trylock_elision (int *futex, short *adapt_count) ++{ ++ /* Implement POSIX semantics by forbiding nesting ++ trylock. Sorry. After the abort the code is re-executed ++ non transactional and if the lock was already locked ++ return an error. */ ++ _xabort (_ABORT_NESTED_TRYLOCK); ++ ++ /* Only try a transaction if it's worth it. See __lll_lock_elision for ++ why we need atomic accesses. Relaxed MO is sufficient because this is ++ just a hint. */ ++ if (atomic_load_relaxed (adapt_count) <= 0) ++ { ++ unsigned status; ++ ++ if ((status = _xbegin()) == _XBEGIN_STARTED) ++ { ++ if (*futex == 0) ++ return 0; ++ ++ /* Lock was busy. Fall back to normal locking. ++ Could also _xend here but xabort with 0xff code ++ is more visible in the profiler. */ ++ _xabort (_ABORT_LOCK_BUSY); ++ } ++ ++ if (!(status & _XABORT_RETRY)) ++ { ++ /* Internal abort. No chance for retry. For future ++ locks don't try speculation for some time. See above for MO. */ ++ if (atomic_load_relaxed (adapt_count) ++ != aconf.skip_lock_internal_abort) ++ atomic_store_relaxed (adapt_count, aconf.skip_lock_internal_abort); ++ } ++ /* Could do some retries here. */ ++ } ++ else ++ { ++ /* Lost updates are possible but harmless (see above). */ ++ atomic_store_relaxed (adapt_count, ++ atomic_load_relaxed (adapt_count) - 1); ++ } ++ ++ return lll_trylock (*futex); ++} +diff --git a/nptl_2_17/elision-unlock_2_17.c b/nptl_2_17/elision-unlock_2_17.c +new file mode 100644 +index 00000000..b5d38c5f +--- /dev/null ++++ b/nptl_2_17/elision-unlock_2_17.c +@@ -0,0 +1,34 @@ ++/* elision-unlock.c: Commit an elided pthread lock. ++ Copyright (C) 2013-2018 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 "pthreadP_2_17.h" ++#include "lowlevellock.h" ++#include "hle_2_17.h" ++#include ++ ++int ++__lll_unlock_elision(int *lock, int private) ++{ ++ /* When the lock was free we're in a transaction. ++ When you crash here you unlocked a free lock. */ ++ if (*lock == 0) ++ _xend(); ++ else ++ lll_unlock ((*lock), private); ++ return 0; ++} +diff --git a/nptl_2_17/hle_2_17.h b/nptl_2_17/hle_2_17.h +new file mode 100644 +index 00000000..4a7b9e3b +--- /dev/null ++++ b/nptl_2_17/hle_2_17.h +@@ -0,0 +1,75 @@ ++/* Shared RTM header. Emulate TSX intrinsics for compilers and assemblers ++ that do not support the intrinsics and instructions yet. */ ++#ifndef _HLE_H ++#define _HLE_H 1 ++ ++#ifdef __ASSEMBLER__ ++ ++.macro XBEGIN target ++ .byte 0xc7,0xf8 ++ .long \target-1f ++1: ++.endm ++ ++.macro XEND ++ .byte 0x0f,0x01,0xd5 ++.endm ++ ++.macro XABORT code ++ .byte 0xc6,0xf8,\code ++.endm ++ ++.macro XTEST ++ .byte 0x0f,0x01,0xd6 ++.endm ++ ++#endif ++ ++/* Official RTM intrinsics interface matching gcc/icc, but works ++ on older gcc compatible compilers and binutils. ++ We should somehow detect if the compiler supports it, because ++ it may be able to generate slightly better code. */ ++ ++#define _XBEGIN_STARTED (~0u) ++#define _XABORT_EXPLICIT (1 << 0) ++#define _XABORT_RETRY (1 << 1) ++#define _XABORT_CONFLICT (1 << 2) ++#define _XABORT_CAPACITY (1 << 3) ++#define _XABORT_DEBUG (1 << 4) ++#define _XABORT_NESTED (1 << 5) ++#define _XABORT_CODE(x) (((x) >> 24) & 0xff) ++ ++#define _ABORT_LOCK_BUSY 0xff ++#define _ABORT_LOCK_IS_LOCKED 0xfe ++#define _ABORT_NESTED_TRYLOCK 0xfd ++ ++#ifndef __ASSEMBLER__ ++ ++#define __force_inline __attribute__((__always_inline__)) inline ++ ++static __force_inline int _xbegin(void) ++{ ++ int ret = _XBEGIN_STARTED; ++ asm volatile (".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory"); ++ return ret; ++} ++ ++static __force_inline void _xend(void) ++{ ++ asm volatile (".byte 0x0f,0x01,0xd5" ::: "memory"); ++} ++ ++static __force_inline void _xabort(const unsigned int status) ++{ ++ asm volatile (".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); ++} ++ ++static __force_inline int _xtest(void) ++{ ++ unsigned char out; ++ asm volatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : "=r" (out) :: "memory"); ++ return out; ++} ++ ++#endif ++#endif +-- +2.30.0 + diff --git a/0007-add-lowlevellock_2_17_c.patch b/0007-add-lowlevellock_2_17_c.patch new file mode 100644 index 0000000..b516e77 --- /dev/null +++ b/0007-add-lowlevellock_2_17_c.patch @@ -0,0 +1,68 @@ +From 3df6f22e5fde470a6e0242e582e58919493bdd54 Mon Sep 17 00:00:00 2001 +From: Roland McGrath +Date: Tue, 15 Jul 2014 15:23:06 -0700 +Subject: [PATCH 7/9] build extra lipthreadcond so + +since 78fe624d44b8f6489b2d0de9bfdc09290a719a7, lowlevellock.c depends futex-internal.h which uses the private symbol __GI___libc_fatal of glibc. +We can't reference it in libpthread-2.17.so. Therefore, recompile in libphtread-2.17.so + +--- + nptl_2_17/lowlevellock_2_17.c | 46 ++++++++++++++++++++++ + 2 files changed, 46 insertions(+) + create mode 100644 nptl_2_17/lowlevellock_2_17.c + +diff --git a/nptl_2_17/lowlevellock_2_17.c b/nptl_2_17/lowlevellock_2_17.c +new file mode 100644 +index 00000000..bf1ca6b9 +--- /dev/null ++++ b/nptl_2_17/lowlevellock_2_17.c +@@ -0,0 +1,46 @@ ++/* low level locking for pthread library. Generic futex-using version. ++ Copyright (C) 2003-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Paul Mackerras , 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 ++ ++void ++__lll_lock_wait_private (int *futex) ++{ ++ if (*futex == 2) ++ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */ ++ ++ while (atomic_exchange_acq (futex, 2) != 0) ++ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */ ++} ++ ++ ++/* This function doesn't get included in libc. */ ++void ++__lll_lock_wait (int *futex, int private) ++{ ++ if (*futex == 2) ++ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */ ++ ++ while (atomic_exchange_acq (futex, 2) != 0) ++ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */ ++} +-- +2.30.0 + diff --git a/0008-add-pause_nocancel_2_17.patch b/0008-add-pause_nocancel_2_17.patch new file mode 100644 index 0000000..8d7ec88 --- /dev/null +++ b/0008-add-pause_nocancel_2_17.patch @@ -0,0 +1,56 @@ +From 329ea513b451ae8322aa7a24ed84da13992af2dd Mon Sep 17 00:00:00 2001 +From: Zack Weinberg +Date: Tue, 3 Apr 2018 18:26:44 -0400 +Subject: [PATCH 8/9] build extra lipthreadcond so + +since bb4a3143724ef3f044a4f05351fe041300ee382, Remove pause and nanosleep not cancel wrappers +To build libtphread-2.17.so, we added it back. + +--- + nptl_2_17/pause_nocancel_2_17.c | 34 +++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + create mode 100644 nptl_2_17/pause_nocancel_2_17.c + +diff --git a/nptl_2_17/pause_nocancel_2_17.c b/nptl_2_17/pause_nocancel_2_17.c +new file mode 100644 +index 00000000..ab8e78d2 +--- /dev/null ++++ b/nptl_2_17/pause_nocancel_2_17.c +@@ -0,0 +1,34 @@ ++/* Linux pause syscall implementation -- non-cancellable. ++ Copyright (C) 2018 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 ++ ++int ++__pause_nocancel (void) ++{ ++#ifdef __NR_pause ++ return INLINE_SYSCALL_CALL (pause); ++#else ++ return INLINE_SYSCALL_CALL (ppoll, NULL, 0, NULL, NULL); ++#endif ++} ++hidden_def (__pause_nocancel) +-- +2.30.0 + diff --git a/0009-add-unwind-with-longjmp.patch b/0009-add-unwind-with-longjmp.patch new file mode 100644 index 0000000..cfe1ecb --- /dev/null +++ b/0009-add-unwind-with-longjmp.patch @@ -0,0 +1,161 @@ +From 09d65ff393e9183eecba1e5cb877e95dbdd3d4a4 Mon Sep 17 00:00:00 2001 +From: Ulrich Drepper +Date: Sat, 12 Apr 2003 00:58:26 +0000 +Subject: [PATCH 9/9] build extra lipthreadcond so + +since 6253bacdc00de132dec452ff7c6ce3ba7fa23d81, __libc_longjmp became a +private interface.We can't quote directly. +Change it to longjmp + +--- + nptl_2_17/unwind_2_17.c | 138 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 138 insertions(+) + create mode 100644 nptl_2_17/unwind_2_17.c + +diff --git a/nptl_2_17/unwind_2_17.c b/nptl_2_17/unwind_2_17.c +new file mode 100644 +index 00000000..ada8f74d +--- /dev/null ++++ b/nptl_2_17/unwind_2_17.c +@@ -0,0 +1,138 @@ ++/* Copyright (C) 2003-2016 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) ++ 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) +-- +2.30.0 + diff --git a/compat-2.17-libpthreadcond-so.patch b/compat-2.17-libpthreadcond-so.patch deleted file mode 100644 index b7c62fe..0000000 --- a/compat-2.17-libpthreadcond-so.patch +++ /dev/null @@ -1,9558 +0,0 @@ -commit a88c9263686012ca2a336379b7d66e59dea2b43b -Author: Ulrich Drepper -Date: Wed Feb 5 09:54:24 2003 +0000 -Subject: [PATCH] build extra lipthreadcond so - -since https://sourceware.org/git/?p=glibc.git;a=commit;h=ed19993b5b0d05d62cc883571519a67dae481a14 -delete pthread_condtion function.However, using these interfaces has better performance. -Therefore, we add a subpacket to use these interfaces. -you can use it by adding LD_PRELOAD=./libpthreadcond.so in front of your program (eg: -LD_PRELOAD=./libpthreadcond.so ./test). use with-compat_2_17 to compile it. -WARNING:2.17 version does not meet the posix standard, you should pay attention when using it. - -This patch contains, but is not limited to, the following submissions: -a88c9263686,59ba27a63ad,9bc6103d046,5acf7263d52,7ce5c1640cb,3e976b962a8,5bd8a24966d - -During the evolution of glibc, many header files are changed. To ensure the stability -of libpthread-2.17, header files of earlier versions are used, such as lowlevellock.h, sysdep.h, -descr.h, and futex-internal.h,pthread-function.h,pthreadtypes-arch.h,no-cancel.h.etc. Of course, -there are some interface modifications, such as __pause_nocancel. - ---- - nptl_2_17/Makefile | 50 + - nptl_2_17/bits/pthreadtypes_2_17.h | 127 ++ - nptl_2_17/bits/thread-shared-types_2_17.h | 185 +++ - nptl_2_17/build_libpthread-2.17.so.sh | 10 + - nptl_2_17/cancellation_2_17.c | 102 ++ - nptl_2_17/cleanup_compat_2_17.c | 50 + - nptl_2_17/descr_2_17.h | 412 ++++++ - nptl_2_17/elision-conf_2_17.c | 137 ++ - nptl_2_17/elision-conf_2_17.h | 41 + - nptl_2_17/elision-lock_2_17.c | 107 ++ - nptl_2_17/elision-timed_2_17.c | 26 + - nptl_2_17/elision-trylock_2_17.c | 75 ++ - nptl_2_17/elision-unlock_2_17.c | 33 + - nptl_2_17/futex-internal_2_17.h | 263 ++++ - nptl_2_17/hle_2_17.h | 75 ++ - nptl_2_17/internaltypes_2_17.h | 179 +++ - nptl_2_17/kernel-features_2_17.h | 162 +++ - nptl_2_17/libpthread-2.17-aarch64.map | 8 + - nptl_2_17/libpthread-2.17-x86_64.map | 8 + - nptl_2_17/lll_timedlock_wait_2_17.c | 59 + - nptl_2_17/lowlevellock_2_17.c | 46 + - nptl_2_17/pthread-functions_2_17.h | 116 ++ - nptl_2_17/pthreadP_2_17.h | 714 ++++++++++ - nptl_2_17/pthread_2_17.h | 1162 +++++++++++++++++ - nptl_2_17/pthread_cond_broadcast_2_17.c | 98 ++ - nptl_2_17/pthread_cond_destroy_2_17.c | 85 ++ - nptl_2_17/pthread_cond_init_2_17.c | 50 + - nptl_2_17/pthread_cond_signal_2_17.c | 82 ++ - nptl_2_17/pthread_cond_timedwait_2_17.c | 266 ++++ - nptl_2_17/pthread_cond_wait_2_17.c | 234 ++++ - nptl_2_17/pthread_condattr_getclock_2_17.c | 28 + - nptl_2_17/pthread_condattr_getpshared_2_17.c | 28 + - nptl_2_17/pthread_condattr_init_2_17.c | 33 + - nptl_2_17/pthread_condattr_setclock_2_17.c | 45 + - nptl_2_17/pthread_mutex_cond_lock_2_17.c | 21 + - nptl_2_17/pthread_mutex_lock_2_17.c | 635 +++++++++ - nptl_2_17/pthread_mutex_unlock_2_17.c | 359 +++++ - .../nptl/bits/pthreadtypes-arch_2_17.h | 71 + - nptl_2_17/sysdeps/generic/sysdep_2_17.h | 97 ++ - nptl_2_17/sysdeps/nptl/futex-internal_2_17.h | 210 +++ - nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h | 208 +++ - nptl_2_17/sysdeps/unix/sysdep_2_17.h | 148 +++ - .../unix/sysv/linux/aarch64/sysdep_2_17.h | 301 +++++ - .../unix/sysv/linux/generic/sysdep_2_17.h | 35 + - .../unix/sysv/linux/internal-signals_2_17.h | 91 ++ - .../unix/sysv/linux/lowlevellock-futex_2_17.h | 150 +++ - .../sysdeps/unix/sysv/linux/not-cancel_2_17.h | 93 ++ - .../sysdeps/unix/sysv/linux/sysdep_2_17.h | 68 + - .../unix/sysv/linux/x86_64/sysdep_2_17.h | 432 ++++++ - nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h | 34 + - nptl_2_17/sysdeps/x86/sysdep_2_17.h | 104 ++ - .../x86_64/nptl/bits/pthreadtypes-arch_2_17.h | 106 ++ - nptl_2_17/sysdeps/x86_64/sysdep_2_17.h | 129 ++ - nptl_2_17/thread_db_2_17.h | 458 +++++++ - nptl_2_17/tpp_2_17.c | 195 +++ - nptl_2_17/vars_2_17.c | 43 + - 56 files changed, 9084 insertions(+) - create mode 100644 nptl_2_17/Makefile - create mode 100644 nptl_2_17/bits/pthreadtypes_2_17.h - create mode 100644 nptl_2_17/bits/thread-shared-types_2_17.h - create mode 100644 nptl_2_17/build_libpthread-2.17.so.sh - create mode 100644 nptl_2_17/cancellation_2_17.c - create mode 100644 nptl_2_17/cleanup_compat_2_17.c - create mode 100644 nptl_2_17/descr_2_17.h - create mode 100644 nptl_2_17/elision-conf_2_17.c - create mode 100644 nptl_2_17/elision-conf_2_17.h - create mode 100644 nptl_2_17/elision-lock_2_17.c - create mode 100644 nptl_2_17/elision-timed_2_17.c - create mode 100644 nptl_2_17/elision-trylock_2_17.c - create mode 100644 nptl_2_17/elision-unlock_2_17.c - create mode 100644 nptl_2_17/futex-internal_2_17.h - create mode 100644 nptl_2_17/hle_2_17.h - create mode 100644 nptl_2_17/internaltypes_2_17.h - create mode 100644 nptl_2_17/kernel-features_2_17.h - create mode 100644 nptl_2_17/libpthread-2.17-aarch64.map - create mode 100644 nptl_2_17/libpthread-2.17-x86_64.map - create mode 100644 nptl_2_17/lll_timedlock_wait_2_17.c - create mode 100644 nptl_2_17/lowlevellock_2_17.c - create mode 100644 nptl_2_17/pthread-functions_2_17.h - create mode 100644 nptl_2_17/pthreadP_2_17.h - create mode 100644 nptl_2_17/pthread_2_17.h - create mode 100644 nptl_2_17/pthread_cond_broadcast_2_17.c - create mode 100644 nptl_2_17/pthread_cond_destroy_2_17.c - create mode 100644 nptl_2_17/pthread_cond_init_2_17.c - create mode 100644 nptl_2_17/pthread_cond_signal_2_17.c - create mode 100644 nptl_2_17/pthread_cond_timedwait_2_17.c - create mode 100644 nptl_2_17/pthread_cond_wait_2_17.c - create mode 100644 nptl_2_17/pthread_condattr_getclock_2_17.c - create mode 100644 nptl_2_17/pthread_condattr_getpshared_2_17.c - create mode 100644 nptl_2_17/pthread_condattr_init_2_17.c - create mode 100644 nptl_2_17/pthread_condattr_setclock_2_17.c - create mode 100644 nptl_2_17/pthread_mutex_cond_lock_2_17.c - create mode 100644 nptl_2_17/pthread_mutex_lock_2_17.c - create mode 100644 nptl_2_17/pthread_mutex_unlock_2_17.c - create mode 100644 nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h - create mode 100644 nptl_2_17/sysdeps/generic/sysdep_2_17.h - create mode 100644 nptl_2_17/sysdeps/nptl/futex-internal_2_17.h - create mode 100644 nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/sysdep_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h - create mode 100644 nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h - create mode 100644 nptl_2_17/sysdeps/x86/sysdep_2_17.h - create mode 100644 nptl_2_17/sysdeps/x86_64/nptl/bits/pthreadtypes-arch_2_17.h - create mode 100644 nptl_2_17/sysdeps/x86_64/sysdep_2_17.h - create mode 100644 nptl_2_17/thread_db_2_17.h - create mode 100644 nptl_2_17/tpp_2_17.c - create mode 100644 nptl_2_17/vars_2_17.c - -diff --git a/nptl_2_17/Makefile b/nptl_2_17/Makefile -new file mode 100644 -index 00000000..4c66b2b6 ---- /dev/null -+++ b/nptl_2_17/Makefile -@@ -0,0 +1,50 @@ -+include libpthread-2.17_config -+subdir=libpthread-2.17 -+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 = 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 pthread_condattr_getclock_2_17.os pthread_condattr_getpshared_2_17.os pthread_condattr_init_2_17.os pthread_condattr_setclock_2_17.os cleanup_compat_2_17.os cancellation_2_17.os pthread_mutex_lock_2_17.os pthread_mutex_unlock_2_17.os tpp_2_17.os vars_2_17.os pthread_mutex_cond_lock_2_17.os lll_timedlock_wait_2_17.os lowlevellock_2_17.os -+ -+ifeq (x86_64, $(arch)) -+compile_obj += elision-lock_2_17.os elision-unlock_2_17.os elision-timed_2_17.os elision-trylock_2_17.os -+endif -+ -+compile_obj_dir = $(foreach n,$(compile_obj),../$(build_dir)/nptl/$(n)) -+ -+CFLAGS = -c -std=gnu11 -fgnu89-inline -fPIE -DNDEBUG -O2 -Wall -Werror -Wp,-D_GLIBCXX_ASSERTIONS -Wundef -Wwrite-strings -fasynchronous-unwind-tables -fmerge-all-constants -frounding-math -fstack-clash-protection -fstack-protector-strong -g -mtune=generic -Wstrict-prototypes -Wold-style-definition -fno-math-errno -fPIC -fexceptions -fasynchronous-unwind-tables -ftls-model=initial-exec -D_FORTIFY_SOURCE=2 -DSHARED -DTOP_NAMESPACE=glibc -+ -+Headers = -I../include -I../$(build_dir)/nptl $(+sysdep-includes) -I../nptl_2_17 -I../nptl -I../libio -I../. -I../nptl_2_17/sysdeps/$(arch)/nptl -I../nptl_2_17/sysdeps/nptl -I../nptl_2_17/sysdeps/unix/sysv/linux/$(arch) -I../nptl_2_17/sysdeps/unix/sysv/linux -D_LIBC_REENTRANT -include ../$(build_dir)/libc-modules.h -include include/libc-symbols.h -+ -+all: libpthread-2.17.so -+ -+libpthread-2.17.so : $(compile_obj) libpthread-2.17_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=libpthread-2.17-$(arch).map -Wl,-soname=libpthread-2.17.so.0 -Wl,-z,noexecstack -Wtrampolines -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -Wl,-z,now -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst -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/libpthread-2.17.so ../$(build_dir)/csu/abi-note.o -Wl,--whole-archive ../$(build_dir)/nptl/libpthread-2.17_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 -+ -+libpthread-2.17_pic.a : $(compile_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..da5521c1 ---- /dev/null -+++ b/nptl_2_17/bits/pthreadtypes_2_17.h -@@ -0,0 +1,127 @@ -+/* Declaration of common pthread types for all architectures. -+ Copyright (C) 2017-2018 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-shared-types_2_17.h" -+ -+/* Thread identifiers. The structure of the attribute type is not -+ exposed on purpose. */ -+typedef unsigned long int pthread_t; -+ -+ -+/* Data structures for mutex handling. The structure of the attribute -+ type is not exposed on purpose. */ -+typedef union -+{ -+ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; -+ int __align; -+} pthread_mutexattr_t; -+ -+ -+/* Data structure for condition variable handling. The structure of -+ the attribute type is not exposed on purpose. */ -+typedef union -+{ -+ char __size[__SIZEOF_PTHREAD_CONDATTR_T]; -+ int __align; -+} pthread_condattr_t; -+ -+ -+/* Keys for thread-specific data */ -+typedef unsigned int pthread_key_t; -+ -+ -+/* Once-only execution */ -+typedef int __ONCE_ALIGNMENT pthread_once_t; -+ -+ -+union pthread_attr_t -+{ -+ char __size[__SIZEOF_PTHREAD_ATTR_T]; -+ long int __align; -+}; -+#ifndef __have_pthread_attr_t -+typedef union pthread_attr_t pthread_attr_t; -+# define __have_pthread_attr_t 1 -+#endif -+ -+ -+typedef union -+{ -+ struct __pthread_mutex_s __data; -+ char __size[__SIZEOF_PTHREAD_MUTEX_T]; -+ long int __align; -+} pthread_mutex_t; -+ -+ -+typedef union -+{ -+struct -+{ -+ 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; -+}__data; -+ char __size[__SIZEOF_PTHREAD_COND_T]; -+ long int __align; -+} pthread_cond_t; -+ -+ -+/* 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; -+ -+ -+/* 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 -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..497e6903 ---- /dev/null -+++ b/nptl_2_17/bits/thread-shared-types_2_17.h -@@ -0,0 +1,185 @@ -+/* Common threading primitives definitions for both POSIX and C11. -+ Copyright (C) 2017-2018 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. -+ -+ Also, the following macros must be define for internal pthread_mutex_t -+ struct definitions (struct __pthread_mutex_s): -+ -+ __PTHREAD_COMPAT_PADDING_MID - any additional members after 'kind' -+ and before '__spin' (for 64 bits) or -+ '__nusers' (for 32 bits). -+ __PTHREAD_COMPAT_PADDING_END - any additional members at the end of -+ the internal structure. -+ __PTHREAD_MUTEX_LOCK_ELISION - 1 if the architecture supports lock -+ elision or 0 otherwise. -+ __PTHREAD_MUTEX_NUSERS_AFTER_KIND - control where to put __nusers. The -+ preferred value for new architectures -+ is 0. -+ __PTHREAD_MUTEX_USE_UNION - control whether internal __spins and -+ __list will be place inside a union for -+ linuxthreads compatibility. -+ The preferred value for new architectures -+ is 0. -+ -+ For a new port the preferred values for the required defines are: -+ -+ #define __PTHREAD_COMPAT_PADDING_MID -+ #define __PTHREAD_COMPAT_PADDING_END -+ #define __PTHREAD_MUTEX_LOCK_ELISION 0 -+ #define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 -+ #define __PTHREAD_MUTEX_USE_UNION 0 -+ -+ __PTHREAD_MUTEX_LOCK_ELISION can be set to 1 if the hardware plans to -+ eventually support lock elision using transactional memory. -+ -+ 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. -+ -+ And finally the internal pthread_rwlock_t (struct __pthread_rwlock_arch_t) -+ must be defined. -+ */ -+#include -+ -+/* Common definition of pthread_mutex_t. */ -+ -+#if !__PTHREAD_MUTEX_USE_UNION -+typedef struct __pthread_internal_list -+{ -+ struct __pthread_internal_list *__prev; -+ struct __pthread_internal_list *__next; -+} __pthread_list_t; -+#else -+typedef struct __pthread_internal_slist -+{ -+ struct __pthread_internal_slist *__next; -+} __pthread_slist_t; -+#endif -+ -+/* Lock elision support. */ -+#if __PTHREAD_MUTEX_LOCK_ELISION -+# if !__PTHREAD_MUTEX_USE_UNION -+# define __PTHREAD_SPINS_DATA \ -+ short __spins; \ -+ short __elision -+# define __PTHREAD_SPINS 0, 0 -+# else -+# define __PTHREAD_SPINS_DATA \ -+ struct \ -+ { \ -+ short __espins; \ -+ short __eelision; \ -+ } __elision_data -+# define __PTHREAD_SPINS { 0, 0 } -+# define __spins __elision_data.__espins -+# define __elision __elision_data.__eelision -+# endif -+#else -+# define __PTHREAD_SPINS_DATA int __spins -+/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */ -+# define __PTHREAD_SPINS 0 -+#endif -+ -+struct __pthread_mutex_s -+{ -+ int __lock __LOCK_ALIGNMENT; -+ unsigned int __count; -+ int __owner; -+#if !__PTHREAD_MUTEX_NUSERS_AFTER_KIND -+ unsigned int __nusers; -+#endif -+ /* KIND must stay at this position in the structure to maintain -+ binary compatibility with static initializers. -+ -+ Concurrency notes: -+ The __kind of a mutex is initialized either by the static -+ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init. -+ -+ After a mutex has been initialized, the __kind of a mutex is usually not -+ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can -+ be enabled. This is done concurrently in the pthread_mutex_*lock functions -+ by using the macro FORCE_ELISION. This macro is only defined for -+ architectures which supports lock elision. -+ -+ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and -+ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set -+ type of a mutex. -+ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set -+ with pthread_mutexattr_settype. -+ After a mutex has been initialized, the functions pthread_mutex_*lock can -+ enable elision - if the mutex-type and the machine supports it - by setting -+ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards -+ the lock / unlock functions are using specific elision code-paths. */ -+ int __kind; -+ __PTHREAD_COMPAT_PADDING_MID -+#if __PTHREAD_MUTEX_NUSERS_AFTER_KIND -+ unsigned int __nusers; -+#endif -+#if !__PTHREAD_MUTEX_USE_UNION -+ __PTHREAD_SPINS_DATA; -+ __pthread_list_t __list; -+# define __PTHREAD_MUTEX_HAVE_PREV 1 -+#else -+ __extension__ union -+ { -+ __PTHREAD_SPINS_DATA; -+ __pthread_slist_t __list; -+ }; -+# define __PTHREAD_MUTEX_HAVE_PREV 0 -+#endif -+ __PTHREAD_COMPAT_PADDING_END -+}; -+ -+ -+/* 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; -+ -+long int __align; -+}; -+ -+#endif /* _THREAD_SHARED_TYPES_H */ -diff --git a/nptl_2_17/build_libpthread-2.17.so.sh b/nptl_2_17/build_libpthread-2.17.so.sh -new file mode 100644 -index 00000000..bdb97d0f ---- /dev/null -+++ b/nptl_2_17/build_libpthread-2.17.so.sh -@@ -0,0 +1,10 @@ -+#!/bin/sh -+set -e -+build_arch=$1 -+build_dir=$2 -+config_dir=libpthread-2.17_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..db299fec ---- /dev/null -+++ b/nptl_2_17/cancellation_2_17.c -@@ -0,0 +1,102 @@ -+/* Copyright (C) 2002-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Ulrich Drepper , 2002. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+#include "pthreadP_2_17.h" -+#include -+#include -+#include "futex-internal_2_17.h" -+ -+/* The next two functions are similar to pthread_setcanceltype() but -+ more specialized for the use in the cancelable functions like write(). -+ They do not need to check parameters etc. */ -+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; -+} -+ -+ -+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..53cf903d ---- /dev/null -+++ b/nptl_2_17/cleanup_compat_2_17.c -@@ -0,0 +1,50 @@ -+/* Copyright (C) 2002-2018 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 -+ -+ -+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/descr_2_17.h b/nptl_2_17/descr_2_17.h -new file mode 100644 -index 00000000..5148c852 ---- /dev/null -+++ b/nptl_2_17/descr_2_17.h -@@ -0,0 +1,412 @@ -+/* Copyright (C) 2002-2018 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 _DESCR_H -+#define _DESCR_H 1 -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "thread_db_2_17.h" -+#include -+#include -+#include -+#include -+ -+#ifndef TCB_ALIGNMENT -+# define TCB_ALIGNMENT sizeof (double) -+#endif -+ -+ -+/* We keep thread specific data in a special data structure, a two-level -+ array. The top-level array contains pointers to dynamically allocated -+ arrays of a certain number of data pointers. So we can implement a -+ sparse array. Each dynamic second-level array has -+ PTHREAD_KEY_2NDLEVEL_SIZE -+ entries. This value shouldn't be too large. */ -+#define PTHREAD_KEY_2NDLEVEL_SIZE 32 -+ -+/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE -+ keys in each subarray. */ -+#define PTHREAD_KEY_1STLEVEL_SIZE \ -+ ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ -+ / PTHREAD_KEY_2NDLEVEL_SIZE) -+ -+ -+ -+ -+/* Internal version of the buffer to store cancellation handler -+ information. */ -+struct pthread_unwind_buf -+{ -+ struct -+ { -+ __jmp_buf jmp_buf; -+ int mask_was_saved; -+ } cancel_jmp_buf[1]; -+ -+ union -+ { -+ /* This is the placeholder of the public version. */ -+ void *pad[4]; -+ -+ struct -+ { -+ /* Pointer to the previous cleanup buffer. */ -+ struct pthread_unwind_buf *prev; -+ -+ /* Backward compatibility: state of the old-style cleanup -+ handler at the time of the previous new-style cleanup handler -+ installment. */ -+ struct _pthread_cleanup_buffer *cleanup; -+ -+ /* Cancellation type before the push call. */ -+ int canceltype; -+ } data; -+ } priv; -+}; -+ -+ -+/* Opcodes and data types for communication with the signal handler to -+ change user/group IDs. */ -+struct xid_command -+{ -+ int syscall_no; -+ /* Enforce zero-extension for the pointer argument in -+ -+ int setgroups (size_t size, const gid_t *list); -+ -+ The kernel XID arguments are unsigned and do not require sign -+ extension. */ -+ unsigned long int id[3]; -+ volatile int cntr; -+ volatile int error; /* -1: no call yet, 0: success seen, >0: error seen. */ -+}; -+ -+ -+/* Data structure used by the kernel to find robust futexes. */ -+struct robust_list_head -+{ -+ void *list; -+ long int futex_offset; -+ void *list_op_pending; -+}; -+ -+ -+/* Data strcture used to handle thread priority protection. */ -+struct priority_protection_data -+{ -+ int priomax; -+ unsigned int priomap[]; -+}; -+ -+ -+/* Thread descriptor data structure. */ -+struct pthread -+{ -+ union -+ { -+#if !TLS_DTV_AT_TP -+ /* This overlaps the TCB as used for TLS without threads (see tls.h). */ -+ tcbhead_t header; -+#else -+ struct -+ { -+ /* multiple_threads is enabled either when the process has spawned at -+ least one thread or when a single-threaded process cancels itself. -+ This enables additional code to introduce locking before doing some -+ compare_and_exchange operations and also enable cancellation points. -+ The concepts of multiple threads and cancellation points ideally -+ should be separate, since it is not necessary for multiple threads to -+ have been created for cancellation points to be enabled, as is the -+ case is when single-threaded process cancels itself. -+ -+ Since enabling multiple_threads enables additional code in -+ cancellation points and compare_and_exchange operations, there is a -+ potential for an unneeded performance hit when it is enabled in a -+ single-threaded, self-canceling process. This is OK though, since a -+ single-threaded process will enable async cancellation only when it -+ looks to cancel itself and is hence going to end anyway. */ -+ int multiple_threads; -+ int gscope_flag; -+ } header; -+#endif -+ -+ /* This extra padding has no special purpose, and this structure layout -+ is private and subject to change without affecting the official ABI. -+ We just have it here in case it might be convenient for some -+ implementation-specific instrumentation hack or suchlike. */ -+ void *__padding[24]; -+ }; -+ -+ /* This descriptor's link on the `stack_used' or `__stack_user' list. */ -+ list_t list; -+ -+ /* Thread ID - which is also a 'is this thread descriptor (and -+ therefore stack) used' flag. */ -+ pid_t tid; -+ -+ /* Ununsed. */ -+ pid_t pid_ununsed; -+ -+ /* List of robust mutexes the thread is holding. */ -+#if __PTHREAD_MUTEX_HAVE_PREV -+ void *robust_prev; -+ struct robust_list_head robust_head; -+ -+ /* The list above is strange. It is basically a double linked list -+ but the pointer to the next/previous element of the list points -+ in the middle of the object, the __next element. Whenever -+ casting to __pthread_list_t we need to adjust the pointer -+ first. -+ These operations are effectively concurrent code in that the thread -+ can get killed at any point in time and the kernel takes over. Thus, -+ the __next elements are a kind of concurrent list and we need to -+ enforce using compiler barriers that the individual operations happen -+ in such a way that the kernel always sees a consistent list. The -+ backward links (ie, the __prev elements) are not used by the kernel. -+ FIXME We should use relaxed MO atomic operations here and signal fences -+ because this kind of concurrency is similar to synchronizing with a -+ signal handler. */ -+# define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next)) -+ -+# define ENQUEUE_MUTEX_BOTH(mutex, val) \ -+ do { \ -+ __pthread_list_t *next = (__pthread_list_t *) \ -+ ((((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_head.list)) & ~1ul) \ -+ - QUEUE_PTR_ADJUST); \ -+ next->__prev = (void *) &mutex->__data.__list.__next; \ -+ mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF, \ -+ robust_head.list); \ -+ mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head; \ -+ /* Ensure that the new list entry is ready before we insert it. */ \ -+ __asm ("" ::: "memory"); \ -+ THREAD_SETMEM (THREAD_SELF, robust_head.list, \ -+ (void *) (((uintptr_t) &mutex->__data.__list.__next) \ -+ | val)); \ -+ } while (0) -+# define DEQUEUE_MUTEX(mutex) \ -+ do { \ -+ __pthread_list_t *next = (__pthread_list_t *) \ -+ ((char *) (((uintptr_t) mutex->__data.__list.__next) & ~1ul) \ -+ - QUEUE_PTR_ADJUST); \ -+ next->__prev = mutex->__data.__list.__prev; \ -+ __pthread_list_t *prev = (__pthread_list_t *) \ -+ ((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul) \ -+ - QUEUE_PTR_ADJUST); \ -+ prev->__next = mutex->__data.__list.__next; \ -+ /* Ensure that we remove the entry from the list before we change the \ -+ __next pointer of the entry, which is read by the kernel. */ \ -+ __asm ("" ::: "memory"); \ -+ mutex->__data.__list.__prev = NULL; \ -+ mutex->__data.__list.__next = NULL; \ -+ } while (0) -+#else -+ union -+ { -+ __pthread_slist_t robust_list; -+ struct robust_list_head robust_head; -+ }; -+ -+# define ENQUEUE_MUTEX_BOTH(mutex, val) \ -+ do { \ -+ mutex->__data.__list.__next \ -+ = THREAD_GETMEM (THREAD_SELF, robust_list.__next); \ -+ /* Ensure that the new list entry is ready before we insert it. */ \ -+ __asm ("" ::: "memory"); \ -+ THREAD_SETMEM (THREAD_SELF, robust_list.__next, \ -+ (void *) (((uintptr_t) &mutex->__data.__list) | val)); \ -+ } while (0) -+# define DEQUEUE_MUTEX(mutex) \ -+ do { \ -+ __pthread_slist_t *runp = (__pthread_slist_t *) \ -+ (((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_list.__next)) & ~1ul); \ -+ if (runp == &mutex->__data.__list) \ -+ THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next); \ -+ else \ -+ { \ -+ __pthread_slist_t *next = (__pthread_slist_t *) \ -+ (((uintptr_t) runp->__next) & ~1ul); \ -+ while (next != &mutex->__data.__list) \ -+ { \ -+ runp = next; \ -+ next = (__pthread_slist_t *) (((uintptr_t) runp->__next) & ~1ul); \ -+ } \ -+ \ -+ runp->__next = next->__next; \ -+ /* Ensure that we remove the entry from the list before we change the \ -+ __next pointer of the entry, which is read by the kernel. */ \ -+ __asm ("" ::: "memory"); \ -+ mutex->__data.__list.__next = NULL; \ -+ } \ -+ } while (0) -+#endif -+#define ENQUEUE_MUTEX(mutex) ENQUEUE_MUTEX_BOTH (mutex, 0) -+#define ENQUEUE_MUTEX_PI(mutex) ENQUEUE_MUTEX_BOTH (mutex, 1) -+ -+ /* List of cleanup buffers. */ -+ struct _pthread_cleanup_buffer *cleanup; -+ -+ /* Unwind information. */ -+ struct pthread_unwind_buf *cleanup_jmp_buf; -+#define HAVE_CLEANUP_JMP_BUF -+ -+ /* Flags determining processing of cancellation. */ -+ int cancelhandling; -+ /* Bit set if cancellation is disabled. */ -+#define CANCELSTATE_BIT 0 -+#define CANCELSTATE_BITMASK (0x01 << CANCELSTATE_BIT) -+ /* Bit set if asynchronous cancellation mode is selected. */ -+#define CANCELTYPE_BIT 1 -+#define CANCELTYPE_BITMASK (0x01 << CANCELTYPE_BIT) -+ /* Bit set if canceling has been initiated. */ -+#define CANCELING_BIT 2 -+#define CANCELING_BITMASK (0x01 << CANCELING_BIT) -+ /* Bit set if canceled. */ -+#define CANCELED_BIT 3 -+#define CANCELED_BITMASK (0x01 << CANCELED_BIT) -+ /* Bit set if thread is exiting. */ -+#define EXITING_BIT 4 -+#define EXITING_BITMASK (0x01 << EXITING_BIT) -+ /* Bit set if thread terminated and TCB is freed. */ -+#define TERMINATED_BIT 5 -+#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT) -+ /* Bit set if thread is supposed to change XID. */ -+#define SETXID_BIT 6 -+#define SETXID_BITMASK (0x01 << SETXID_BIT) -+ /* Mask for the rest. Helps the compiler to optimize. */ -+#define CANCEL_RESTMASK 0xffffff80 -+ -+#define CANCEL_ENABLED_AND_CANCELED(value) \ -+ (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK \ -+ | CANCEL_RESTMASK | TERMINATED_BITMASK)) == CANCELED_BITMASK) -+#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \ -+ (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK \ -+ | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK)) \ -+ == (CANCELTYPE_BITMASK | CANCELED_BITMASK)) -+ -+ /* Flags. Including those copied from the thread attribute. */ -+ int flags; -+ -+ /* We allocate one block of references here. This should be enough -+ to avoid allocating any memory dynamically for most applications. */ -+ struct pthread_key_data -+ { -+ /* Sequence number. 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; -+ -+ /* Data pointer. */ -+ void *data; -+ } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE]; -+ -+ /* Two-level array for the thread-specific data. */ -+ struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE]; -+ -+ /* Flag which is set when specific data is set. */ -+ bool specific_used; -+ -+ /* True if events must be reported. */ -+ bool report_events; -+ -+ /* True if the user provided the stack. */ -+ bool user_stack; -+ -+ /* True if thread must stop at startup time. */ -+ bool stopped_start; -+ -+ /* The parent's cancel handling at the time of the pthread_create -+ call. This might be needed to undo the effects of a cancellation. */ -+ int parent_cancelhandling; -+ -+ /* Lock to synchronize access to the descriptor. */ -+ int lock; -+ -+ /* Lock for synchronizing setxid calls. */ -+ unsigned int setxid_futex; -+ -+#ifdef __x86_64__ -+ /* Offset of the CPU clock at start thread start time. */ -+ hp_timing_t cpuclock_offset; -+#endif -+ -+ /* If the thread waits to join another one the ID of the latter is -+ stored here. -+ -+ In case a thread is detached this field contains a pointer of the -+ TCB if the thread itself. This is something which cannot happen -+ in normal operation. */ -+ struct pthread *joinid; -+ /* Check whether a thread is detached. */ -+#define IS_DETACHED(pd) ((pd)->joinid == (pd)) -+ -+ /* The result of the thread function. */ -+ void *result; -+ -+ /* Scheduling parameters for the new thread. */ -+ struct sched_param schedparam; -+ int schedpolicy; -+ -+ /* Start position of the code to be executed and the argument passed -+ to the function. */ -+ void *(*start_routine) (void *); -+ void *arg; -+ -+ /* Debug state. */ -+ td_eventbuf_t eventbuf; -+ /* Next descriptor with a pending event. */ -+ struct pthread *nextevent; -+ -+ /* Machine-specific unwind info. */ -+ struct _Unwind_Exception exc; -+ -+ /* If nonzero, pointer to the area allocated for the stack and guard. */ -+ void *stackblock; -+ /* Size of the stackblock area including the guard. */ -+ size_t stackblock_size; -+ /* Size of the included guard area. */ -+ size_t guardsize; -+ /* This is what the user specified and what we will report. */ -+ size_t reported_guardsize; -+ -+ /* Thread Priority Protection data. */ -+ struct priority_protection_data *tpp; -+ -+ /* Resolver state. */ -+ struct __res_state res; -+ -+ /* Indicates whether is a C11 thread created by thrd_creat. */ -+ bool c11; -+ -+ /* This member must be last. */ -+ char end_padding[]; -+ -+#define PTHREAD_STRUCT_END_PADDING \ -+ (sizeof (struct pthread) - offsetof (struct pthread, end_padding)) -+} __attribute ((aligned (TCB_ALIGNMENT))); -+ -+ -+#endif /* descr.h */ -diff --git a/nptl_2_17/elision-conf_2_17.c b/nptl_2_17/elision-conf_2_17.c -new file mode 100644 -index 00000000..13dd985e ---- /dev/null -+++ b/nptl_2_17/elision-conf_2_17.c -@@ -0,0 +1,137 @@ -+/* elision-conf.c: Lock elision tunable parameters. -+ Copyright (C) 2013-2018 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 "config.h" -+#include -+#include -+#include -+#include -+ -+# define TUNABLE_NAMESPACE elision -+# define TOP_NAMESPACE glibc -+#include -+ -+/* Reasonable initial tuning values, may be revised in the future. -+ This is a conservative initial value. */ -+ -+struct elision_config __elision_aconf = -+ { -+ /* How often to not attempt to use elision if a transaction aborted -+ because the lock is already acquired. Expressed in number of lock -+ acquisition attempts. */ -+ .skip_lock_busy = 3, -+ /* How often to not attempt to use elision if a transaction aborted due -+ to reasons other than other threads' memory accesses. Expressed in -+ number of lock acquisition attempts. */ -+ .skip_lock_internal_abort = 3, -+ /* How often we retry using elision if there is chance for the transaction -+ to finish execution (e.g., it wasn't aborted due to the lock being -+ already acquired. */ -+ .retry_try_xbegin = 3, -+ /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock. */ -+ .skip_trylock_internal_abort = 3, -+ }; -+ -+/* Force elision for all new locks. This is used to decide whether existing -+ DEFAULT locks should be automatically upgraded to elision in -+ pthread_mutex_lock(). Disabled for suid programs. Only used when elision -+ is available. */ -+ -+int __pthread_force_elision attribute_hidden = 0; -+ -+#if HAVE_TUNABLES -+static inline void -+__always_inline -+do_set_elision_enable (int32_t elision_enable) -+{ -+ /* Enable elision if it's avaliable in hardware. It's not necessary to check -+ if __libc_enable_secure isn't enabled since elision_enable will be set -+ according to the default, which is disabled. */ -+ if (elision_enable == 1) -+ __pthread_force_elision = HAS_CPU_FEATURE (RTM) ? 1 : 0; -+} -+ -+/* The pthread->elision_enable tunable is 0 or 1 indicating that elision -+ should be disabled or enabled respectively. The feature will only be used -+ if it's supported by the hardware. */ -+ -+void -+TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *valp) -+{ -+ int32_t elision_enable = (int32_t) valp->numval; -+ do_set_elision_enable (elision_enable); -+} -+ -+#define TUNABLE_CALLBACK_FNDECL(__name, __type) \ -+static inline void \ -+__always_inline \ -+do_set_elision_ ## __name (__type value) \ -+{ \ -+ __elision_aconf.__name = value; \ -+} \ -+void \ -+TUNABLE_CALLBACK (set_elision_ ## __name) (tunable_val_t *valp) \ -+{ \ -+ __type value = (__type) (valp)->numval; \ -+ do_set_elision_ ## __name (value); \ -+} -+ -+TUNABLE_CALLBACK_FNDECL (skip_lock_busy, int32_t); -+TUNABLE_CALLBACK_FNDECL (skip_lock_internal_abort, int32_t); -+TUNABLE_CALLBACK_FNDECL (retry_try_xbegin, int32_t); -+TUNABLE_CALLBACK_FNDECL (skip_trylock_internal_abort, int32_t); -+#endif -+ -+/* Initialize elision. */ -+ -+static void -+elision_init (int argc __attribute__ ((unused)), -+ char **argv __attribute__ ((unused)), -+ char **environ) -+{ -+#if HAVE_TUNABLES -+ /* Elision depends on tunables and must be explicitly turned on by setting -+ the appropriate tunable on a supported platform. */ -+ -+ TUNABLE_GET (enable, int32_t, -+ TUNABLE_CALLBACK (set_elision_enable)); -+ TUNABLE_GET (skip_lock_busy, int32_t, -+ TUNABLE_CALLBACK (set_elision_skip_lock_busy)); -+ TUNABLE_GET (skip_lock_internal_abort, int32_t, -+ TUNABLE_CALLBACK (set_elision_skip_lock_internal_abort)); -+ TUNABLE_GET (tries, int32_t, -+ TUNABLE_CALLBACK (set_elision_retry_try_xbegin)); -+ TUNABLE_GET (skip_trylock_internal_abort, int32_t, -+ TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort)); -+#endif -+ -+ if (!__pthread_force_elision) -+ __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks. */ -+} -+ -+#ifdef SHARED -+# define INIT_SECTION ".init_array" -+#else -+# define INIT_SECTION ".preinit_array" -+#endif -+ -+void (*const __pthread_init_array []) (int, char **, char **) -+ __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) = -+{ -+ &elision_init -+}; -diff --git a/nptl_2_17/elision-conf_2_17.h b/nptl_2_17/elision-conf_2_17.h -new file mode 100644 -index 00000000..9cd38962 ---- /dev/null -+++ b/nptl_2_17/elision-conf_2_17.h -@@ -0,0 +1,41 @@ -+/* elision-conf.h: Lock elision tunable parameters. -+ Copyright (C) 2013-2018 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 _ELISION_CONF_H -+#define _ELISION_CONF_H 1 -+ -+#include -+#include -+ -+/* Should make sure there is no false sharing on this. */ -+ -+struct elision_config -+{ -+ int skip_lock_busy; -+ int skip_lock_internal_abort; -+ int retry_try_xbegin; -+ int skip_trylock_internal_abort; -+}; -+ -+extern struct elision_config __elision_aconf attribute_hidden; -+ -+extern int __pthread_force_elision attribute_hidden; -+ -+/* Tell the test suite to test elision for this architecture. */ -+#define HAVE_ELISION 1 -+ -+#endif -diff --git a/nptl_2_17/elision-lock_2_17.c b/nptl_2_17/elision-lock_2_17.c -new file mode 100644 -index 00000000..6eebde8a ---- /dev/null -+++ b/nptl_2_17/elision-lock_2_17.c -@@ -0,0 +1,107 @@ -+/* elision-lock.c: Elided pthread mutex lock. -+ Copyright (C) 2011-2018 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 "pthreadP_2_17.h" -+#include "lowlevellock_2_17.h" -+#include "hle_2_17.h" -+#include -+ -+#if !defined(LLL_LOCK) && !defined(EXTRAARG) -+/* Make sure the configuration code is always linked in for static -+ libraries. */ -+#include "elision-conf_2_17.c" -+#endif -+ -+#ifndef EXTRAARG -+#define EXTRAARG -+#endif -+#ifndef LLL_LOCK -+#define LLL_LOCK(a,b) lll_lock(a,b), 0 -+#endif -+ -+#define aconf __elision_aconf -+ -+/* Adaptive lock using transactions. -+ By default the lock region is run as a transaction, and when it -+ aborts or the lock is busy the lock adapts itself. */ -+ -+int -+__lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int private) -+{ -+ /* adapt_count can be accessed concurrently; these accesses can be both -+ inside of transactions (if critical sections are nested and the outer -+ critical section uses lock elision) and outside of transactions. Thus, -+ we need to use atomic accesses to avoid data races. However, the -+ value of adapt_count is just a hint, so relaxed MO accesses are -+ sufficient. */ -+ if (atomic_load_relaxed (adapt_count) <= 0) -+ { -+ unsigned status; -+ int try_xbegin; -+ -+ for (try_xbegin = aconf.retry_try_xbegin; -+ try_xbegin > 0; -+ try_xbegin--) -+ { -+ if ((status = _xbegin()) == _XBEGIN_STARTED) -+ { -+ if (*futex == 0) -+ return 0; -+ -+ /* Lock was busy. Fall back to normal locking. -+ Could also _xend here but xabort with 0xff code -+ is more visible in the profiler. */ -+ _xabort (_ABORT_LOCK_BUSY); -+ } -+ -+ if (!(status & _XABORT_RETRY)) -+ { -+ if ((status & _XABORT_EXPLICIT) -+ && _XABORT_CODE (status) == _ABORT_LOCK_BUSY) -+ { -+ /* Right now we skip here. Better would be to wait a bit -+ and retry. This likely needs some spinning. See -+ above for why relaxed MO is sufficient. */ -+ if (atomic_load_relaxed (adapt_count) -+ != aconf.skip_lock_busy) -+ atomic_store_relaxed (adapt_count, aconf.skip_lock_busy); -+ } -+ /* Internal abort. There is no chance for retry. -+ Use the normal locking and next time use lock. -+ Be careful to avoid writing to the lock. See above for why -+ relaxed MO is sufficient. */ -+ else if (atomic_load_relaxed (adapt_count) -+ != aconf.skip_lock_internal_abort) -+ atomic_store_relaxed (adapt_count, -+ aconf.skip_lock_internal_abort); -+ break; -+ } -+ } -+ } -+ else -+ { -+ /* Use a normal lock until the threshold counter runs out. -+ Lost updates possible. */ -+ atomic_store_relaxed (adapt_count, -+ atomic_load_relaxed (adapt_count) - 1); -+ } -+ -+ /* Use a normal lock here. */ -+ return LLL_LOCK ((*futex), private); -+} -diff --git a/nptl_2_17/elision-timed_2_17.c b/nptl_2_17/elision-timed_2_17.c -new file mode 100644 -index 00000000..b103f9aa ---- /dev/null -+++ b/nptl_2_17/elision-timed_2_17.c -@@ -0,0 +1,26 @@ -+/* elision-timed.c: Lock elision timed lock. -+ Copyright (C) 2013-2018 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 "lowlevellock_2_17.h" -+#define __lll_lock_elision __lll_timedlock_elision -+#define EXTRAARG const struct timespec *t, -+#undef LLL_LOCK -+#define LLL_LOCK(a, b) lll_timedlock(a, t, b) -+#include "elision-lock_2_17.c" -diff --git a/nptl_2_17/elision-trylock_2_17.c b/nptl_2_17/elision-trylock_2_17.c -new file mode 100644 -index 00000000..8ed92198 ---- /dev/null -+++ b/nptl_2_17/elision-trylock_2_17.c -@@ -0,0 +1,75 @@ -+/* elision-trylock.c: Lock eliding trylock for pthreads. -+ Copyright (C) 2013-2018 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 "hle_2_17.h" -+#include -+ -+#define aconf __elision_aconf -+ -+/* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is -+ the adaptation counter in the mutex. */ -+ -+int -+__lll_trylock_elision (int *futex, short *adapt_count) -+{ -+ /* Implement POSIX semantics by forbiding nesting -+ trylock. Sorry. After the abort the code is re-executed -+ non transactional and if the lock was already locked -+ return an error. */ -+ _xabort (_ABORT_NESTED_TRYLOCK); -+ -+ /* Only try a transaction if it's worth it. See __lll_lock_elision for -+ why we need atomic accesses. Relaxed MO is sufficient because this is -+ just a hint. */ -+ if (atomic_load_relaxed (adapt_count) <= 0) -+ { -+ unsigned status; -+ -+ if ((status = _xbegin()) == _XBEGIN_STARTED) -+ { -+ if (*futex == 0) -+ return 0; -+ -+ /* Lock was busy. Fall back to normal locking. -+ Could also _xend here but xabort with 0xff code -+ is more visible in the profiler. */ -+ _xabort (_ABORT_LOCK_BUSY); -+ } -+ -+ if (!(status & _XABORT_RETRY)) -+ { -+ /* Internal abort. No chance for retry. For future -+ locks don't try speculation for some time. See above for MO. */ -+ if (atomic_load_relaxed (adapt_count) -+ != aconf.skip_lock_internal_abort) -+ atomic_store_relaxed (adapt_count, aconf.skip_lock_internal_abort); -+ } -+ /* Could do some retries here. */ -+ } -+ else -+ { -+ /* Lost updates are possible but harmless (see above). */ -+ atomic_store_relaxed (adapt_count, -+ atomic_load_relaxed (adapt_count) - 1); -+ } -+ -+ return lll_trylock (*futex); -+} -diff --git a/nptl_2_17/elision-unlock_2_17.c b/nptl_2_17/elision-unlock_2_17.c -new file mode 100644 -index 00000000..20b658a8 ---- /dev/null -+++ b/nptl_2_17/elision-unlock_2_17.c -@@ -0,0 +1,33 @@ -+/* elision-unlock.c: Commit an elided pthread lock. -+ Copyright (C) 2013-2018 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 "pthreadP_2_17.h" -+#include "lowlevellock_2_17.h" -+#include "hle_2_17.h" -+ -+int -+__lll_unlock_elision(int *lock, int private) -+{ -+ /* When the lock was free we're in a transaction. -+ When you crash here you unlocked a free lock. */ -+ if (*lock == 0) -+ _xend(); -+ else -+ lll_unlock ((*lock), private); -+ return 0; -+} -diff --git a/nptl_2_17/futex-internal_2_17.h b/nptl_2_17/futex-internal_2_17.h -new file mode 100644 -index 00000000..b0512da0 ---- /dev/null -+++ b/nptl_2_17/futex-internal_2_17.h -@@ -0,0 +1,263 @@ -+/* futex operations for glibc-internal use. Linux version. -+ Copyright (C) 2014-2018 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 FUTEX_INTERNAL_H -+#define FUTEX_INTERNAL_H -+ -+#include -+#include -+#include -+#include -+ -+/* See sysdeps/nptl/futex-internal.h for documentation; this file only -+ contains Linux-specific comments. -+ -+ The Linux kernel treats provides absolute timeouts based on the -+ CLOCK_REALTIME clock and relative timeouts measured against the -+ CLOCK_MONOTONIC clock. -+ -+ We expect a Linux kernel version of 2.6.22 or more recent (since this -+ version, EINTR is not returned on spurious wake-ups anymore). */ -+ -+/* FUTEX_SHARED is always supported by the Linux kernel. */ -+static __always_inline int -+futex_supports_pshared (int pshared) -+{ -+ if (__glibc_likely (pshared == PTHREAD_PROCESS_PRIVATE)) -+ return 0; -+ else if (pshared == PTHREAD_PROCESS_SHARED) -+ return 0; -+ else -+ return EINVAL; -+} -+ -+/* The Linux kernel supports relative timeouts measured against the -+ CLOCK_MONOTONIC clock. */ -+static __always_inline bool -+futex_supports_exact_relative_timeouts (void) -+{ -+ return true; -+} -+ -+/* See sysdeps/nptl/futex-internal.h for details. */ -+static __always_inline int -+futex_wait (unsigned int *futex_word, unsigned int expected, int private) -+{ -+ int err = lll_futex_timed_wait (futex_word, expected, NULL, private); -+ switch (err) -+ { -+ case 0: -+ case -EAGAIN: -+ case -EINTR: -+ return -err; -+ -+ case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */ -+ case -EFAULT: /* Must have been caused by a glibc or application bug. */ -+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not -+ being normalized. Must have been caused by a glibc or -+ application bug. */ -+ case -ENOSYS: /* Must have been caused by a glibc bug. */ -+ /* No other errors are documented at this time. */ -+ default: -+ futex_fatal_error (); -+ } -+} -+ -+/* See sysdeps/nptl/futex-internal.h for details. */ -+static __always_inline int -+futex_wait_cancelable (unsigned int *futex_word, unsigned int expected, -+ int private) -+{ -+ int oldtype; -+ oldtype = __pthread_enable_asynccancel (); -+ int err = lll_futex_timed_wait (futex_word, expected, NULL, private); -+ __pthread_disable_asynccancel (oldtype); -+ switch (err) -+ { -+ case 0: -+ case -EAGAIN: -+ case -EINTR: -+ return -err; -+ -+ case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */ -+ case -EFAULT: /* Must have been caused by a glibc or application bug. */ -+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not -+ being normalized. Must have been caused by a glibc or -+ application bug. */ -+ case -ENOSYS: /* Must have been caused by a glibc bug. */ -+ /* No other errors are documented at this time. */ -+ default: -+ futex_fatal_error (); -+ } -+} -+ -+/* See sysdeps/nptl/futex-internal.h for details. */ -+static __always_inline int -+futex_reltimed_wait (unsigned int *futex_word, unsigned int expected, -+ const struct timespec *reltime, int private) -+{ -+ int err = lll_futex_timed_wait (futex_word, expected, reltime, private); -+ switch (err) -+ { -+ case 0: -+ case -EAGAIN: -+ case -EINTR: -+ case -ETIMEDOUT: -+ return -err; -+ -+ case -EFAULT: /* Must have been caused by a glibc or application bug. */ -+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not -+ being normalized. Must have been caused by a glibc or -+ application bug. */ -+ case -ENOSYS: /* Must have been caused by a glibc bug. */ -+ /* No other errors are documented at this time. */ -+ default: -+ futex_fatal_error (); -+ } -+} -+ -+/* See sysdeps/nptl/futex-internal.h for details. */ -+static __always_inline int -+futex_reltimed_wait_cancelable (unsigned int *futex_word, -+ unsigned int expected, -+ const struct timespec *reltime, int private) -+{ -+ int oldtype; -+ oldtype = __pthread_enable_asynccancel (); -+ int err = lll_futex_timed_wait (futex_word, expected, reltime, private); -+ __pthread_disable_asynccancel (oldtype); -+ switch (err) -+ { -+ case 0: -+ case -EAGAIN: -+ case -EINTR: -+ case -ETIMEDOUT: -+ return -err; -+ -+ case -EFAULT: /* Must have been caused by a glibc or application bug. */ -+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not -+ being normalized. Must have been caused by a glibc or -+ application bug. */ -+ case -ENOSYS: /* Must have been caused by a glibc bug. */ -+ /* No other errors are documented at this time. */ -+ default: -+ futex_fatal_error (); -+ } -+} -+ -+/* See sysdeps/nptl/futex-internal.h for details. */ -+static __always_inline int -+futex_abstimed_supported_clockid (clockid_t clockid) -+{ -+ return lll_futex_supported_clockid (clockid); -+} -+ -+/* See sysdeps/nptl/futex-internal.h for details. */ -+static __always_inline int -+futex_abstimed_wait (unsigned int *futex_word, unsigned int expected, -+ clockid_t clockid, -+ const struct timespec *abstime, int private) -+{ -+ /* Work around the fact that the kernel rejects negative timeout values -+ despite them being valid. */ -+ if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0))) -+ return ETIMEDOUT; -+ int err = lll_futex_clock_wait_bitset (futex_word, expected, -+ clockid, abstime, -+ private); -+ switch (err) -+ { -+ case 0: -+ case -EAGAIN: -+ case -EINTR: -+ case -ETIMEDOUT: -+ return -err; -+ -+ case -EFAULT: /* Must have been caused by a glibc or application bug. */ -+ case -EINVAL: /* Either due to wrong alignment, unsupported -+ clockid or due to the timeout not being -+ normalized. Must have been caused by a glibc or -+ application bug. */ -+ case -ENOSYS: /* Must have been caused by a glibc bug. */ -+ /* No other errors are documented at this time. */ -+ default: -+ futex_fatal_error (); -+ } -+} -+ -+/* See sysdeps/nptl/futex-internal.h for details. */ -+static __always_inline int -+futex_abstimed_wait_cancelable (unsigned int *futex_word, -+ unsigned int expected, -+ clockid_t clockid, -+ const struct timespec *abstime, int private) -+{ -+ /* Work around the fact that the kernel rejects negative timeout values -+ despite them being valid. */ -+ if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0))) -+ return ETIMEDOUT; -+ int oldtype; -+ oldtype = __pthread_enable_asynccancel (); -+ int err = lll_futex_clock_wait_bitset (futex_word, expected, -+ clockid, abstime, -+ private); -+ __pthread_disable_asynccancel (oldtype); -+ switch (err) -+ { -+ case 0: -+ case -EAGAIN: -+ case -EINTR: -+ case -ETIMEDOUT: -+ return -err; -+ -+ case -EFAULT: /* Must have been caused by a glibc or application bug. */ -+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not -+ being normalized. Must have been caused by a glibc or -+ application bug. */ -+ case -ENOSYS: /* Must have been caused by a glibc bug. */ -+ /* No other errors are documented at this time. */ -+ default: -+ futex_fatal_error (); -+ } -+} -+ -+/* See sysdeps/nptl/futex-internal.h for details. */ -+static __always_inline void -+futex_wake (unsigned int *futex_word, int processes_to_wake, int private) -+{ -+ int res = lll_futex_wake (futex_word, processes_to_wake, private); -+ /* No error. Ignore the number of woken processes. */ -+ if (res >= 0) -+ return; -+ switch (res) -+ { -+ case -EFAULT: /* Could have happened due to memory reuse. */ -+ case -EINVAL: /* Could be either due to incorrect alignment (a bug in -+ glibc or in the application) or due to memory being -+ reused for a PI futex. We cannot distinguish between the -+ two causes, and one of them is correct use, so we do not -+ act in this case. */ -+ return; -+ case -ENOSYS: /* Must have been caused by a glibc bug. */ -+ /* No other errors are documented at this time. */ -+ default: -+ futex_fatal_error (); -+ } -+} -+ -+#endif /* futex-internal.h */ -diff --git a/nptl_2_17/hle_2_17.h b/nptl_2_17/hle_2_17.h -new file mode 100644 -index 00000000..4a7b9e3b ---- /dev/null -+++ b/nptl_2_17/hle_2_17.h -@@ -0,0 +1,75 @@ -+/* Shared RTM header. Emulate TSX intrinsics for compilers and assemblers -+ that do not support the intrinsics and instructions yet. */ -+#ifndef _HLE_H -+#define _HLE_H 1 -+ -+#ifdef __ASSEMBLER__ -+ -+.macro XBEGIN target -+ .byte 0xc7,0xf8 -+ .long \target-1f -+1: -+.endm -+ -+.macro XEND -+ .byte 0x0f,0x01,0xd5 -+.endm -+ -+.macro XABORT code -+ .byte 0xc6,0xf8,\code -+.endm -+ -+.macro XTEST -+ .byte 0x0f,0x01,0xd6 -+.endm -+ -+#endif -+ -+/* Official RTM intrinsics interface matching gcc/icc, but works -+ on older gcc compatible compilers and binutils. -+ We should somehow detect if the compiler supports it, because -+ it may be able to generate slightly better code. */ -+ -+#define _XBEGIN_STARTED (~0u) -+#define _XABORT_EXPLICIT (1 << 0) -+#define _XABORT_RETRY (1 << 1) -+#define _XABORT_CONFLICT (1 << 2) -+#define _XABORT_CAPACITY (1 << 3) -+#define _XABORT_DEBUG (1 << 4) -+#define _XABORT_NESTED (1 << 5) -+#define _XABORT_CODE(x) (((x) >> 24) & 0xff) -+ -+#define _ABORT_LOCK_BUSY 0xff -+#define _ABORT_LOCK_IS_LOCKED 0xfe -+#define _ABORT_NESTED_TRYLOCK 0xfd -+ -+#ifndef __ASSEMBLER__ -+ -+#define __force_inline __attribute__((__always_inline__)) inline -+ -+static __force_inline int _xbegin(void) -+{ -+ int ret = _XBEGIN_STARTED; -+ asm volatile (".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory"); -+ return ret; -+} -+ -+static __force_inline void _xend(void) -+{ -+ asm volatile (".byte 0x0f,0x01,0xd5" ::: "memory"); -+} -+ -+static __force_inline void _xabort(const unsigned int status) -+{ -+ asm volatile (".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); -+} -+ -+static __force_inline int _xtest(void) -+{ -+ unsigned char out; -+ asm volatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : "=r" (out) :: "memory"); -+ return out; -+} -+ -+#endif -+#endif -diff --git a/nptl_2_17/internaltypes_2_17.h b/nptl_2_17/internaltypes_2_17.h -new file mode 100644 -index 00000000..603dc01c ---- /dev/null -+++ b/nptl_2_17/internaltypes_2_17.h -@@ -0,0 +1,179 @@ -+/* Copyright (C) 2002-2018 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/kernel-features_2_17.h b/nptl_2_17/kernel-features_2_17.h -new file mode 100644 -index 00000000..299ae0a1 ---- /dev/null -+++ b/nptl_2_17/kernel-features_2_17.h -@@ -0,0 +1,162 @@ -+/* Set flags signalling availability of kernel features based on given -+ kernel version number. -+ Copyright (C) 1999-2018 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 must not contain any C code. At least it must be protected -+ to allow using the file also in assembler files. */ -+ -+#ifndef __LINUX_KERNEL_VERSION_2_17 -+/* We assume the worst; all kernels should be supported. */ -+# define __LINUX_KERNEL_VERSION_2_17 0 -+#endif -+ -+/* We assume for __LINUX_KERNEL_VERSION the same encoding used in -+ linux/version.h. I.e., the major, minor, and subminor all get a -+ byte with the major number being in the highest byte. This means -+ we can do numeric comparisons. -+ -+ In the following we will define certain symbols depending on -+ whether the describes kernel feature is available in the kernel -+ version given by __LINUX_KERNEL_VERSION. We are not always exactly -+ recording the correct versions in which the features were -+ introduced. If somebody cares these values can afterwards be -+ corrected. */ -+ -+/* Some architectures use the socketcall multiplexer for some or all -+ socket-related operations instead of separate syscalls. -+ __ASSUME_SOCKETCALL is defined for such architectures. */ -+ -+/* The changed st_ino field appeared in 2.4.0-test6. However, SH is lame, -+ and still does not have a 64-bit inode field. */ -+#define __ASSUME_ST_INO_64_BIT 1 -+ -+/* The statfs64 syscalls are available in 2.5.74 (but not for alpha). */ -+#define __ASSUME_STATFS64 1 -+ -+/* pselect/ppoll were introduced just after 2.6.16-rc1. On x86_64 and -+ SH this appeared first in 2.6.19-rc1, on ia64 in 2.6.22-rc1. */ -+#define __ASSUME_PSELECT 1 -+ -+/* The *at syscalls were introduced just after 2.6.16-rc1. On PPC -+ they were introduced in 2.6.17-rc1, on SH in 2.6.19-rc1. */ -+#define __ASSUME_ATFCTS 1 -+ -+/* Support for inter-process robust mutexes was added in 2.6.17 (but -+ some architectures lack futex_atomic_cmpxchg_inatomic in some -+ configurations). */ -+#define __ASSUME_SET_ROBUST_LIST 1 -+ -+/* Support for various CLOEXEC and NONBLOCK flags was added in -+ 2.6.27. */ -+#define __ASSUME_IN_NONBLOCK 1 -+ -+/* Support for the FUTEX_CLOCK_REALTIME flag was added in 2.6.29. */ -+#define __ASSUME_FUTEX_CLOCK_REALTIME 1 -+ -+/* Support for preadv and pwritev was added in 2.6.30. */ -+#define __ASSUME_PREADV 1 -+#define __ASSUME_PWRITEV 1 -+ -+ -+/* Support for FUTEX_*_REQUEUE_PI was added in 2.6.31 (but some -+ * architectures lack futex_atomic_cmpxchg_inatomic in some -+ * configurations). */ -+#define __ASSUME_REQUEUE_PI 1 -+ -+/* Support for sendmmsg functionality was added in 3.0. */ -+#define __ASSUME_SENDMMSG 1 -+ -+/* On most architectures, most socket syscalls are supported for all -+ supported kernel versions, but on some socketcall architectures -+ separate syscalls were only added later. */ -+#define __ASSUME_SENDMSG_SYSCALL 1 -+#define __ASSUME_RECVMSG_SYSCALL 1 -+#define __ASSUME_ACCEPT_SYSCALL 1 -+#define __ASSUME_CONNECT_SYSCALL 1 -+#define __ASSUME_RECVFROM_SYSCALL 1 -+#define __ASSUME_SENDTO_SYSCALL 1 -+#define __ASSUME_ACCEPT4_SYSCALL 1 -+#define __ASSUME_RECVMMSG_SYSCALL 1 -+#define __ASSUME_SENDMMSG_SYSCALL 1 -+ -+/* Support for SysV IPC through wired syscalls. All supported architectures -+ either support ipc syscall and/or all the ipc correspondent syscalls. */ -+#define __ASSUME_DIRECT_SYSVIPC_SYSCALLS 1 -+ -+/* Support for p{read,write}v2 was added in 4.6. However Linux default -+ implementation does not assume the __ASSUME_* and instead use a fallback -+ implementation based on p{read,write}v and returning an error for -+ non supported flags. */ -+ -+/* Support for the renameat2 system call was added in kernel 3.15. */ -+#if __LINUX_KERNEL_VERSION >= 0x030F00 -+# define __ASSUME_RENAMEAT2 -+#endif -+ -+/* Support for the execveat syscall was added in 3.19. */ -+#if __LINUX_KERNEL_VERSION >= 0x031300 -+# define __ASSUME_EXECVEAT 1 -+#endif -+ -+#if __LINUX_KERNEL_VERSION >= 0x040400 -+# define __ASSUME_MLOCK2 1 -+#endif -+ -+#if __LINUX_KERNEL_VERSION >= 0x040500 -+# define __ASSUME_COPY_FILE_RANGE 1 -+#endif -+ -+/* Support for statx was added in kernel 4.11. */ -+#if __LINUX_KERNEL_VERSION >= 0x040B00 -+# define __ASSUME_STATX 1 -+#endif -+ -+/* Support for clone call used on fork. The signature varies across the -+ architectures with current 4 different variants: -+ -+ 1. long int clone (unsigned long flags, unsigned long newsp, -+ int *parent_tidptr, unsigned long tls, -+ int *child_tidptr) -+ -+ 2. long int clone (unsigned long newsp, unsigned long clone_flags, -+ int *parent_tidptr, int * child_tidptr, -+ unsigned long tls) -+ -+ 3. long int clone (unsigned long flags, unsigned long newsp, -+ int stack_size, int *parent_tidptr, -+ int *child_tidptr, unsigned long tls) -+ -+ 4. long int clone (unsigned long flags, unsigned long newsp, -+ int *parent_tidptr, int *child_tidptr, -+ unsigned long tls) -+ -+ The fourth variant is intended to be used as the default for newer ports, -+ Also IA64 uses the third variant but with __NR_clone2 instead of -+ __NR_clone. -+ -+ The macros names to define the variant used for the architecture is -+ similar to kernel: -+ -+ - __ASSUME_CLONE_BACKWARDS: for variant 1. -+ - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390). -+ - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze). -+ - __ASSUME_CLONE_DEFAULT: for variant 4. -+ - __ASSUME_CLONE2: for clone2 with variant 3 (ia64). -+ */ -+ -+#define __ASSUME_CLONE_DEFAULT 1 -diff --git a/nptl_2_17/libpthread-2.17-aarch64.map b/nptl_2_17/libpthread-2.17-aarch64.map -new file mode 100644 -index 00000000..d970af06 ---- /dev/null -+++ b/nptl_2_17/libpthread-2.17-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/libpthread-2.17-x86_64.map b/nptl_2_17/libpthread-2.17-x86_64.map -new file mode 100644 -index 00000000..d7f23322 ---- /dev/null -+++ b/nptl_2_17/libpthread-2.17-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/lll_timedlock_wait_2_17.c b/nptl_2_17/lll_timedlock_wait_2_17.c -new file mode 100644 -index 00000000..45ca994e ---- /dev/null -+++ b/nptl_2_17/lll_timedlock_wait_2_17.c -@@ -0,0 +1,59 @@ -+/* Timed low level locking for pthread library. Generic futex-using version. -+ Copyright (C) 2003-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Paul Mackerras , 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 -+ -+ -+int -+__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) -+{ -+ /* Reject invalid timeouts. */ -+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) -+ return EINVAL; -+ -+ /* Try locking. */ -+ while (atomic_exchange_acq (futex, 2) != 0) -+ { -+ struct timeval tv; -+ -+ /* Get the current time. */ -+ (void) __gettimeofday (&tv, NULL); -+ -+ /* Compute relative timeout. */ -+ struct timespec rt; -+ rt.tv_sec = abstime->tv_sec - tv.tv_sec; -+ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; -+ if (rt.tv_nsec < 0) -+ { -+ rt.tv_nsec += 1000000000; -+ --rt.tv_sec; -+ } -+ -+ if (rt.tv_sec < 0) -+ return ETIMEDOUT; -+ -+ /* If *futex == 2, wait until woken or timeout. */ -+ lll_futex_timed_wait (futex, 2, &rt, private); -+ } -+ -+ return 0; -+} -diff --git a/nptl_2_17/lowlevellock_2_17.c b/nptl_2_17/lowlevellock_2_17.c -new file mode 100644 -index 00000000..9bbcc924 ---- /dev/null -+++ b/nptl_2_17/lowlevellock_2_17.c -@@ -0,0 +1,46 @@ -+/* low level locking for pthread library. Generic futex-using version. -+ Copyright (C) 2003-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Paul Mackerras , 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 -+ -+void -+__lll_lock_wait_private (int *futex) -+{ -+ if (*futex == 2) -+ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */ -+ -+ while (atomic_exchange_acq (futex, 2) != 0) -+ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */ -+} -+ -+ -+/* This function doesn't get included in libc. */ -+void -+__lll_lock_wait (int *futex, int private) -+{ -+ if (*futex == 2) -+ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */ -+ -+ while (atomic_exchange_acq (futex, 2) != 0) -+ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */ -+} -diff --git a/nptl_2_17/pthread-functions_2_17.h b/nptl_2_17/pthread-functions_2_17.h -new file mode 100644 -index 00000000..9e2a79f5 ---- /dev/null -+++ b/nptl_2_17/pthread-functions_2_17.h -@@ -0,0 +1,116 @@ -+/* Copyright (C) 2003-2018 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 -+ . */ -+ -+#ifndef _PTHREAD_FUNCTIONS_H -+#define _PTHREAD_FUNCTIONS_H 1 -+ -+#include -+#include -+#include -+#include -+ -+struct xid_command; -+ -+/* Data type shared with libc. The libc uses it to pass on calls to -+ the thread functions. */ -+struct pthread_functions -+{ -+ int (*ptr_pthread_attr_destroy) (pthread_attr_t *); -+ int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *); -+ int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *); -+ int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); -+ int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); -+ int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); -+ int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); -+ int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, -+ struct sched_param *); -+ int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, -+ const struct sched_param *); -+ int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); -+ int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); -+ int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); -+ int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); -+ int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); -+ int (*ptr_pthread_condattr_init) (pthread_condattr_t *); -+ int (*ptr___pthread_cond_broadcast) (pthread_cond_t *); -+ int (*ptr___pthread_cond_destroy) (pthread_cond_t *); -+ int (*ptr___pthread_cond_init) (pthread_cond_t *, -+ const pthread_condattr_t *); -+ -+ int (*ptr___pthread_cond_signal) (pthread_cond_t *); -+ int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); -+ int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, -+ const struct timespec *); -+ int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *); -+ int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *); -+ int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *, -+ const pthread_condattr_t *); -+ int (*ptr___pthread_cond_signal_2_0) (pthread_cond_2_0_t *); -+ int (*ptr___pthread_cond_wait_2_0) (pthread_cond_2_0_t *, pthread_mutex_t *); -+ int (*ptr___pthread_cond_timedwait_2_0) (pthread_cond_2_0_t *, -+ pthread_mutex_t *, -+ const struct timespec *); -+ int (*ptr_pthread_equal) (pthread_t, pthread_t); -+ void (*ptr___pthread_exit) (void *) __attribute__ ((__noreturn__)); -+ int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); -+ int (*ptr_pthread_setschedparam) (pthread_t, int, -+ const struct sched_param *); -+ int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); -+ int (*ptr_pthread_mutex_init) (pthread_mutex_t *, -+ const pthread_mutexattr_t *); -+ int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); -+ int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); -+ int (*ptr___pthread_setcancelstate) (int, int *); -+ int (*ptr_pthread_setcanceltype) (int, int *); -+ void (*ptr___pthread_cleanup_upto) (__jmp_buf, char *); -+ int (*ptr___pthread_once) (pthread_once_t *, void (*) (void)); -+ int (*ptr___pthread_rwlock_rdlock) (pthread_rwlock_t *); -+ int (*ptr___pthread_rwlock_wrlock) (pthread_rwlock_t *); -+ int (*ptr___pthread_rwlock_unlock) (pthread_rwlock_t *); -+ int (*ptr___pthread_key_create) (pthread_key_t *, void (*) (void *)); -+ void *(*ptr___pthread_getspecific) (pthread_key_t); -+ int (*ptr___pthread_setspecific) (pthread_key_t, const void *); -+ void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer *, -+ void (*) (void *), void *); -+ void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer *, -+ int); -+#define HAVE_PTR_NTHREADS -+ unsigned int *ptr_nthreads; -+ void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *) -+ __attribute ((noreturn)) __cleanup_fct_attribute; -+ void (*ptr__nptl_deallocate_tsd) (void); -+ int (*ptr__nptl_setxid) (struct xid_command *); -+ void (*ptr_set_robust) (struct pthread *); -+}; -+ -+/* Variable in libc.so. */ -+extern struct pthread_functions __libc_pthread_functions attribute_hidden; -+extern int __libc_pthread_functions_init attribute_hidden; -+ -+#ifdef PTR_DEMANGLE -+# define PTHFCT_CALL(fct, params) \ -+ ({ __typeof (__libc_pthread_functions.fct) __p; \ -+ __p = __libc_pthread_functions.fct; \ -+ PTR_DEMANGLE (__p); \ -+ __p params; }) -+#else -+# define PTHFCT_CALL(fct, params) \ -+ __libc_pthread_functions.fct params -+#endif -+ -+#endif /* pthread-functions.h */ -diff --git a/nptl_2_17/pthreadP_2_17.h b/nptl_2_17/pthreadP_2_17.h -new file mode 100644 -index 00000000..ee1488c0 ---- /dev/null -+++ b/nptl_2_17/pthreadP_2_17.h -@@ -0,0 +1,714 @@ -+/* Copyright (C) 2002-2018 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 "kernel-features_2_17.h" -+#include "pthread_2_17.h" -+#include -+#include "internaltypes_2_17.h" -+#include -+#include "descr_2_17.h" -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+/* 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 -+ -+ -+/* Adaptive mutex definitions. */ -+#ifndef MAX_ADAPTIVE_COUNT -+# define MAX_ADAPTIVE_COUNT 100 -+#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) -+ -+ -+/* 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__)) -+ weak_function -+ ; -+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)); -+} -+ -+ -+/* Set cancellation mode to asynchronous. */ -+#define CANCEL_ASYNC() \ -+ __pthread_enable_asynccancel () -+/* Reset to previous cancellation mode. */ -+#define CANCEL_RESET(oldtype) \ -+ __pthread_disable_asynccancel (oldtype) -+ -+# ifdef LIBC_CANCEL_ASYNC -+# undef LIBC_CANCEL_ASYNC -+# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC () -+# endif -+# ifdef LIBC_CANCEL_RESET -+# undef LIBC_CANCEL_RESET -+# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val) -+# endif -+# define LIBC_CANCEL_HANDLED() \ -+ __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \ -+ __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel") -+ -+ -+/* 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 -+ -+/* Find a thread given its TID. */ -+extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden -+#ifdef SHARED -+; -+#else -+weak_function; -+#define __find_thread_by_id(tid) \ -+ (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL) -+#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_timedjoin_ex (pthread_t, void **, const struct timespec *, -+ bool); -+ -+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) -+hidden_proto (__pthread_timedjoin_ex) -+ -+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); -+ -+/* The two functions are in libc.so and not exported. */ -+extern int __libc_enable_asynccancel (void) attribute_hidden; -+extern void __libc_disable_asynccancel (int oldtype) attribute_hidden; -+ -+ -+/* The two functions are in librt.so and not exported. */ -+extern int __librt_enable_asynccancel (void) attribute_hidden; -+extern void __librt_disable_asynccancel (int oldtype) attribute_hidden; -+ -+/* 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)); } -+ -+# if defined __EXCEPTIONS && !defined __cplusplus -+/* Structure to hold the cleanup handler information. */ -+struct __pthread_cleanup_combined_frame -+{ -+ void (*__cancel_routine) (void *); -+ void *__cancel_arg; -+ int __do_it; -+ struct _pthread_cleanup_buffer __buffer; -+}; -+ -+/* Special cleanup macros which register cleanup both using -+ __pthread_cleanup_{push,pop} and using cleanup attribute. This is needed -+ for pthread_once, so that it supports both throwing exceptions from the -+ pthread_once callback (only cleanup attribute works there) and cancellation -+ of the thread running the callback if the callback or some routines it -+ calls don't have unwind information. */ -+ -+static __always_inline void -+__pthread_cleanup_combined_routine (struct __pthread_cleanup_combined_frame -+ *__frame) -+{ -+ if (__frame->__do_it) -+ { -+ __frame->__cancel_routine (__frame->__cancel_arg); -+ __frame->__do_it = 0; -+ __pthread_cleanup_pop (&__frame->__buffer, 0); -+ } -+} -+ -+static inline void -+__pthread_cleanup_combined_routine_voidptr (void *__arg) -+{ -+ struct __pthread_cleanup_combined_frame *__frame -+ = (struct __pthread_cleanup_combined_frame *) __arg; -+ if (__frame->__do_it) -+ { -+ __frame->__cancel_routine (__frame->__cancel_arg); -+ __frame->__do_it = 0; -+ } -+} -+ -+# define pthread_cleanup_combined_push(routine, arg) \ -+ do { \ -+ void (*__cancel_routine) (void *) = (routine); \ -+ struct __pthread_cleanup_combined_frame __clframe \ -+ __attribute__ ((__cleanup__ (__pthread_cleanup_combined_routine))) \ -+ = { .__cancel_routine = __cancel_routine, .__cancel_arg = (arg), \ -+ .__do_it = 1 }; \ -+ __pthread_cleanup_push (&__clframe.__buffer, \ -+ __pthread_cleanup_combined_routine_voidptr, \ -+ &__clframe); -+ -+# define pthread_cleanup_combined_pop(execute) \ -+ __pthread_cleanup_pop (&__clframe.__buffer, 0); \ -+ __clframe.__do_it = 0; \ -+ if (execute) \ -+ __cancel_routine (__clframe.__cancel_arg); \ -+ } while (0) -+ -+# endif -+ -+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)) -+ -+#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..f2d9c226 ---- /dev/null -+++ b/nptl_2_17/pthread_2_17.h -@@ -0,0 +1,1162 @@ -+/* Copyright (C) 2002-2018 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 "bits/pthreadtypes_2_17.h" -+ -+#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 -+ -+ -+#if __PTHREAD_MUTEX_HAVE_PREV -+# define PTHREAD_MUTEX_INITIALIZER \ -+ { { 0, 0, 0, 0, 0, __PTHREAD_SPINS, { 0, 0 } } } -+# ifdef __USE_GNU -+# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } -+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __PTHREAD_SPINS, { 0, 0 } } } -+# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } -+ -+# endif -+#else -+# define PTHREAD_MUTEX_INITIALIZER \ -+ { { 0, 0, 0, 0, 0, { __PTHREAD_SPINS } } } -+# ifdef __USE_GNU -+# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { __PTHREAD_SPINS } } } -+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { __PTHREAD_SPINS } } } -+# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { __PTHREAD_SPINS } } } -+ -+# endif -+#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 -+}; -+ -+/* Define __PTHREAD_RWLOCK_INT_FLAGS_SHARED to 1 if pthread_rwlock_t -+ has the shared field. All 64-bit architectures have the shared field -+ in pthread_rwlock_t. */ -+#ifndef __PTHREAD_RWLOCK_INT_FLAGS_SHARED -+# if __WORDSIZE == 64 -+# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1 -+# endif -+#endif -+ -+/* Read-write lock initializers. */ -+# define PTHREAD_RWLOCK_INITIALIZER \ -+ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } } -+# ifdef __USE_GNU -+# ifdef __PTHREAD_RWLOCK_INT_FLAGS_SHARED -+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ -+ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, \ -+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } -+# else -+# if __BYTE_ORDER == __LITTLE_ENDIAN -+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ -+ { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \ -+ 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } } -+# else -+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ -+ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\ -+ 0 } } -+# endif -+# endif -+# 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); -+#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 -+ -+/* 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 -+ -+/* 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 -+ -+/* 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)); -+ -+/* 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..d9b68f79 ---- /dev/null -+++ b/nptl_2_17/pthread_cond_broadcast_2_17.c -@@ -0,0 +1,98 @@ -+/* 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 "kernel-features_2_17.h" -+#include "pthread_2_17.h" -+#include "pthreadP_2_17.h" -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* We do the following steps from __pthread_cond_signal in one critical -+ section: (1) signal all waiters in G1, (2) close G1 so that it can become -+ the new G2 and make G2 the new G1, and (3) signal all waiters in the new -+ G1. We don't need to do all these steps if there are no waiters in G1 -+ and/or G2. See __pthread_cond_signal for further details. */ -+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..f5bd7ade ---- /dev/null -+++ b/nptl_2_17/pthread_cond_destroy_2_17.c -@@ -0,0 +1,85 @@ -+/* Copyright (C) 2002-2018 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..f4eff6ab ---- /dev/null -+++ b/nptl_2_17/pthread_cond_init_2_17.c -@@ -0,0 +1,50 @@ -+/* Copyright (C) 2002-2018 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..5d79b894 ---- /dev/null -+++ b/nptl_2_17/pthread_cond_signal_2_17.c -@@ -0,0 +1,82 @@ -+/* 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 "kernel-features_2_17.h" -+#include "pthread_2_17.h" -+#include "pthreadP_2_17.h" -+#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..ab497195 ---- /dev/null -+++ b/nptl_2_17/pthread_cond_timedwait_2_17.c -@@ -0,0 +1,266 @@ -+/* 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 "kernel-features_2_17.h" -+#include "bits/thread-shared-types_2_17.h" -+#include -+#include "pthread_2_17.h" -+#include "pthreadP_2_17.h" -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+# undef INTERNAL_VSYSCALL -+# define INTERNAL_VSYSCALL INTERNAL_SYSCALL -+# undef INLINE_VSYSCALL -+# define INLINE_VSYSCALL INLINE_SYSCALL -+ -+/* 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..966ecab1 ---- /dev/null -+++ b/nptl_2_17/pthread_cond_wait_2_17.c -@@ -0,0 +1,234 @@ -+/* 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 "bits/thread-shared-types_2_17.h" -+#include -+#include -+#include "kernel-features_2_17.h" -+#include "pthread_2_17.h" -+#include "pthreadP_2_17.h" -+ -+#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..414a6856 ---- /dev/null -+++ b/nptl_2_17/pthread_condattr_getclock_2_17.c -@@ -0,0 +1,28 @@ -+/* Copyright (C) 2003-2018 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..2b85506f ---- /dev/null -+++ b/nptl_2_17/pthread_condattr_getpshared_2_17.c -@@ -0,0 +1,28 @@ -+/* Copyright (C) 2002-2018 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..427a349c ---- /dev/null -+++ b/nptl_2_17/pthread_condattr_init_2_17.c -@@ -0,0 +1,33 @@ -+/* Copyright (C) 2002-2018 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 -+ -+ -+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..69c64dcb ---- /dev/null -+++ b/nptl_2_17/pthread_condattr_setclock_2_17.c -@@ -0,0 +1,45 @@ -+/* Copyright (C) 2003-2018 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" -+#include -+#include -+#include -+#include -+#include -+ -+ -+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..674ae77b ---- /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..787f37b0 ---- /dev/null -+++ b/nptl_2_17/pthread_mutex_lock_2_17.c -@@ -0,0 +1,635 @@ -+/* Copyright (C) 2002-2018 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 (MAX_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)); -+ INTERNAL_SYSCALL_DECL (__err); -+ int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, -+ __lll_private_flag (FUTEX_LOCK_PI, -+ private), 1, 0); -+ -+ if (INTERNAL_SYSCALL_ERROR_P (e, __err) -+ && (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH -+ || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)) -+ { -+ assert (INTERNAL_SYSCALL_ERRNO (e, __err) != 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 (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust); -+ -+ /* Delay the thread indefinitely. */ -+ while (1) -+ pause (); -+ } -+ -+ 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; -+ -+ INTERNAL_SYSCALL_DECL (__err); -+ INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, -+ __lll_private_flag (FUTEX_UNLOCK_PI, -+ PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), -+ 0, 0); -+ -+ /* 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..cca86029 ---- /dev/null -+++ b/nptl_2_17/pthread_mutex_unlock_2_17.c -@@ -0,0 +1,359 @@ -+/* Copyright (C) 2002-2018 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 -+ -+#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))) -+ { -+ INTERNAL_SYSCALL_DECL (__err); -+ INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock, -+ __lll_private_flag (FUTEX_UNLOCK_PI, 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/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h b/nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h -new file mode 100644 -index 00000000..008aa7e0 ---- /dev/null -+++ b/nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h -@@ -0,0 +1,71 @@ -+/* Copyright (C) 2002-2018 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_ARCH_H -+#define _BITS_PTHREADTYPES_ARCH_H 1 -+ -+#include -+ -+#ifdef __ILP32__ -+# define __SIZEOF_PTHREAD_ATTR_T 32 -+# define __SIZEOF_PTHREAD_MUTEX_T 32 -+# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 -+# define __SIZEOF_PTHREAD_CONDATTR_T 4 -+# define __SIZEOF_PTHREAD_RWLOCK_T 48 -+# define __SIZEOF_PTHREAD_BARRIER_T 20 -+# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 -+#else -+# define __SIZEOF_PTHREAD_ATTR_T 64 -+# define __SIZEOF_PTHREAD_MUTEX_T 48 -+# define __SIZEOF_PTHREAD_MUTEXATTR_T 8 -+# define __SIZEOF_PTHREAD_CONDATTR_T 8 -+# define __SIZEOF_PTHREAD_RWLOCK_T 56 -+# define __SIZEOF_PTHREAD_BARRIER_T 32 -+# define __SIZEOF_PTHREAD_BARRIERATTR_T 8 -+#endif -+#define __SIZEOF_PTHREAD_COND_T 48 -+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 -+ -+/* Definitions for internal mutex struct. */ -+#define __PTHREAD_COMPAT_PADDING_MID -+#define __PTHREAD_COMPAT_PADDING_END -+#define __PTHREAD_MUTEX_LOCK_ELISION 0 -+#define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 -+#define __PTHREAD_MUTEX_USE_UNION 0 -+ -+#define __LOCK_ALIGNMENT -+#define __ONCE_ALIGNMENT -+ -+struct __pthread_rwlock_arch_t -+{ -+ unsigned int __readers; -+ unsigned int __writers; -+ unsigned int __wrphase_futex; -+ unsigned int __writers_futex; -+ unsigned int __pad3; -+ unsigned int __pad4; -+ int __cur_writer; -+ int __shared; -+ unsigned long int __pad1; -+ unsigned long int __pad2; -+ unsigned int __flags; -+}; -+ -+#define __PTHREAD_RWLOCK_ELISION_EXTRA 0 -+ -+#endif /* bits/pthreadtypes.h */ -diff --git a/nptl_2_17/sysdeps/generic/sysdep_2_17.h b/nptl_2_17/sysdeps/generic/sysdep_2_17.h -new file mode 100644 -index 00000000..934d4da8 ---- /dev/null -+++ b/nptl_2_17/sysdeps/generic/sysdep_2_17.h -@@ -0,0 +1,97 @@ -+/* Generic asm macros used on many machines. -+ Copyright (C) 1991-2018 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 C_LABEL -+ -+/* Define a macro we can use to construct the asm name for a C symbol. */ -+# define C_LABEL(name) name##: -+ -+#endif -+ -+#ifdef __ASSEMBLER__ -+/* Mark the end of function named SYM. This is used on some platforms -+ to generate correct debugging information. */ -+# ifndef END -+# define END(sym) -+# endif -+ -+# ifndef JUMPTARGET -+# define JUMPTARGET(sym) sym -+# endif -+#endif -+ -+/* Makros to generate eh_frame unwind information. */ -+#ifdef __ASSEMBLER__ -+# define cfi_startproc .cfi_startproc -+# define cfi_endproc .cfi_endproc -+# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off -+# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg -+# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off -+# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off -+# define cfi_offset(reg, off) .cfi_offset reg, off -+# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off -+# define cfi_register(r1, r2) .cfi_register r1, r2 -+# define cfi_return_column(reg) .cfi_return_column reg -+# define cfi_restore(reg) .cfi_restore reg -+# define cfi_same_value(reg) .cfi_same_value reg -+# define cfi_undefined(reg) .cfi_undefined reg -+# define cfi_remember_state .cfi_remember_state -+# define cfi_restore_state .cfi_restore_state -+# define cfi_window_save .cfi_window_save -+# define cfi_personality(enc, exp) .cfi_personality enc, exp -+# define cfi_lsda(enc, exp) .cfi_lsda enc, exp -+ -+#else /* ! ASSEMBLER */ -+ -+# define CFI_STRINGIFY(Name) CFI_STRINGIFY2 (Name) -+# define CFI_STRINGIFY2(Name) #Name -+# define CFI_STARTPROC ".cfi_startproc" -+# define CFI_ENDPROC ".cfi_endproc" -+# define CFI_DEF_CFA(reg, off) \ -+ ".cfi_def_cfa " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) -+# define CFI_DEF_CFA_REGISTER(reg) \ -+ ".cfi_def_cfa_register " CFI_STRINGIFY(reg) -+# define CFI_DEF_CFA_OFFSET(off) \ -+ ".cfi_def_cfa_offset " CFI_STRINGIFY(off) -+# define CFI_ADJUST_CFA_OFFSET(off) \ -+ ".cfi_adjust_cfa_offset " CFI_STRINGIFY(off) -+# define CFI_OFFSET(reg, off) \ -+ ".cfi_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) -+# define CFI_REL_OFFSET(reg, off) \ -+ ".cfi_rel_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) -+# define CFI_REGISTER(r1, r2) \ -+ ".cfi_register " CFI_STRINGIFY(r1) "," CFI_STRINGIFY(r2) -+# define CFI_RETURN_COLUMN(reg) \ -+ ".cfi_return_column " CFI_STRINGIFY(reg) -+# define CFI_RESTORE(reg) \ -+ ".cfi_restore " CFI_STRINGIFY(reg) -+# define CFI_UNDEFINED(reg) \ -+ ".cfi_undefined " CFI_STRINGIFY(reg) -+# define CFI_REMEMBER_STATE \ -+ ".cfi_remember_state" -+# define CFI_RESTORE_STATE \ -+ ".cfi_restore_state" -+# define CFI_WINDOW_SAVE \ -+ ".cfi_window_save" -+# define CFI_PERSONALITY(enc, exp) \ -+ ".cfi_personality " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp) -+# define CFI_LSDA(enc, exp) \ -+ ".cfi_lsda " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp) -+#endif -+ -+#include "dwarf2.h" -diff --git a/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h b/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h -new file mode 100644 -index 00000000..353fdfb9 ---- /dev/null -+++ b/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h -@@ -0,0 +1,210 @@ -+/* futex operations for glibc-internal use. Stub version; do not include -+ this file directly. -+ Copyright (C) 2014-2018 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 STUB_FUTEX_INTERNAL_H -+#define STUB_FUTEX_INTERNAL_H -+ -+#include -+#include -+#include -+#include -+ -+/* This file defines futex operations used internally in glibc. A futex -+ consists of the so-called futex word in userspace, which is of type -+ unsigned int and represents an application-specific condition, and kernel -+ state associated with this particular futex word (e.g., wait queues). The -+ futex operations we provide are wrappers for the futex syscalls and add -+ glibc-specific error checking of the syscall return value. We abort on -+ error codes that are caused by bugs in glibc or in the calling application, -+ or when an error code is not known. We return error codes that can arise -+ in correct executions to the caller. Each operation calls out exactly the -+ return values that callers need to handle. -+ -+ The private flag must be either FUTEX_PRIVATE or FUTEX_SHARED. -+ FUTEX_PRIVATE is always supported, and the implementation can internally -+ use FUTEX_SHARED when FUTEX_PRIVATE is requested. FUTEX_SHARED is not -+ necessarily supported (use futex_supports_pshared to detect this). -+ -+ We expect callers to only use these operations if futexes and the -+ specific futex operations being used are supported (e.g., FUTEX_SHARED). -+ -+ Given that waking other threads waiting on a futex involves concurrent -+ accesses to the futex word, you must use atomic operations to access the -+ futex word. -+ -+ Both absolute and relative timeouts can be used. An absolute timeout -+ expires when the given specific point in time on the specified clock -+ passes, or when it already has passed. A relative timeout expires when -+ the given duration of time on the CLOCK_MONOTONIC clock passes. Relative -+ timeouts may be imprecise (see futex_supports_exact_relative_timeouts). -+ -+ Due to POSIX requirements on when synchronization data structures such -+ as mutexes or semaphores can be destroyed and due to the futex design -+ having separate fast/slow paths for wake-ups, we need to consider that -+ futex_wake calls might effectively target a data structure that has been -+ destroyed and reused for another object, or unmapped; thus, some -+ errors or spurious wake-ups can happen in correct executions that would -+ not be possible in a program using just a single futex whose lifetime -+ does not end before the program terminates. For background, see: -+ https://sourceware.org/ml/libc-alpha/2014-04/msg00075.html -+ https://lkml.org/lkml/2014/11/27/472 */ -+ -+/* Defined this way for interoperability with lowlevellock. -+ FUTEX_PRIVATE must be zero because the initializers for pthread_mutex_t, -+ pthread_rwlock_t, and pthread_cond_t initialize the respective field of -+ those structures to zero, and we want FUTEX_PRIVATE to be the default. */ -+#define FUTEX_PRIVATE LLL_PRIVATE -+#define FUTEX_SHARED LLL_SHARED -+#if FUTEX_PRIVATE != 0 -+# error FUTEX_PRIVATE must be equal to 0 -+#endif -+ -+/* Returns EINVAL if PSHARED is neither PTHREAD_PROCESS_PRIVATE nor -+ PTHREAD_PROCESS_SHARED; otherwise, returns 0 if PSHARED is supported, and -+ ENOTSUP if not. */ -+static __always_inline int -+futex_supports_pshared (int pshared); -+ -+/* Returns true if relative timeouts are robust to concurrent changes to the -+ system clock. If this returns false, relative timeouts can still be used -+ but might be effectively longer or shorter than requested. */ -+static __always_inline bool -+futex_supports_exact_relative_timeouts (void); -+ -+/* Atomically wrt other futex operations on the same futex, this blocks iff -+ the value *FUTEX_WORD matches the expected value. This is -+ semantically equivalent to: -+ l = (FUTEX_WORD); -+ wait_flag = (FUTEX_WORD); -+ lock (l); -+ val = atomic_load_relaxed (FUTEX_WORD); -+ if (val != expected) { unlock (l); return EAGAIN; } -+ atomic_store_relaxed (wait_flag, true); -+ unlock (l); -+ // Now block; can time out in futex_time_wait (see below) -+ while (atomic_load_relaxed(wait_flag) && !); -+ -+ Note that no guarantee of a happens-before relation between a woken -+ futex_wait and a futex_wake is documented; however, this does not matter -+ in practice because we have to consider spurious wake-ups (see below), -+ and thus would not be able to reliably reason about which futex_wake woke -+ us. -+ -+ Returns 0 if woken by a futex operation or spuriously. (Note that due to -+ the POSIX requirements mentioned above, we need to conservatively assume -+ that unrelated futex_wake operations could wake this futex; it is easiest -+ to just be prepared for spurious wake-ups.) -+ Returns EAGAIN if the futex word did not match the expected value. -+ Returns EINTR if waiting was interrupted by a signal. -+ -+ Note that some previous code in glibc assumed the underlying futex -+ operation (e.g., syscall) to start with or include the equivalent of a -+ seq_cst fence; this allows one to avoid an explicit seq_cst fence before -+ a futex_wait call when synchronizing similar to Dekker synchronization. -+ However, we make no such guarantee here. */ -+static __always_inline int -+futex_wait (unsigned int *futex_word, unsigned int expected, int private); -+ -+/* Like futex_wait but does not provide any indication why we stopped waiting. -+ Thus, when this function returns, you have to always check FUTEX_WORD to -+ determine whether you need to continue waiting, and you cannot detect -+ whether the waiting was interrupted by a signal. Example use: -+ while (atomic_load_relaxed (&futex_word) == 23) -+ futex_wait_simple (&futex_word, 23, FUTEX_PRIVATE); -+ This is common enough to make providing this wrapper worthwhile. */ -+static __always_inline void -+futex_wait_simple (unsigned int *futex_word, unsigned int expected, -+ int private) -+{ -+ ignore_value (futex_wait (futex_word, expected, private)); -+} -+ -+ -+/* Like futex_wait but is a POSIX cancellation point. */ -+static __always_inline int -+futex_wait_cancelable (unsigned int *futex_word, unsigned int expected, -+ int private); -+ -+/* Like futex_wait, but will eventually time out (i.e., stop being -+ blocked) after the duration of time provided (i.e., RELTIME) has -+ passed. The caller must provide a normalized RELTIME. RELTIME can also -+ equal NULL, in which case this function behaves equivalent to futex_wait. -+ -+ Returns the same values as futex_wait under those same conditions; -+ additionally, returns ETIMEDOUT if the timeout expired. -+ */ -+static __always_inline int -+futex_reltimed_wait (unsigned int* futex_word, unsigned int expected, -+ const struct timespec* reltime, int private); -+ -+/* Like futex_reltimed_wait but is a POSIX cancellation point. */ -+static __always_inline int -+futex_reltimed_wait_cancelable (unsigned int* futex_word, -+ unsigned int expected, -+ const struct timespec* reltime, int private); -+ -+/* Check whether the specified clockid is supported by -+ futex_abstimed_wait and futex_abstimed_wait_cancelable. */ -+static __always_inline int -+futex_abstimed_supported_clockid (clockid_t clockid); -+ -+/* Like futex_reltimed_wait, but the provided timeout (ABSTIME) is an -+ absolute point in time; a call will time out after this point in time. */ -+static __always_inline int -+futex_abstimed_wait (unsigned int* futex_word, unsigned int expected, -+ clockid_t clockid, -+ const struct timespec* abstime, int private); -+ -+/* Like futex_reltimed_wait but is a POSIX cancellation point. */ -+static __always_inline int -+futex_abstimed_wait_cancelable (unsigned int* futex_word, -+ unsigned int expected, -+ clockid_t clockid, -+ const struct timespec* abstime, int private); -+ -+/* Atomically wrt other futex operations on the same futex, this unblocks the -+ specified number of processes, or all processes blocked on this futex if -+ there are fewer than the specified number. Semantically, this is -+ equivalent to: -+ l = (FUTEX_WORD); -+ lock (l); -+ for (res = 0; PROCESSES_TO_WAKE > 0; PROCESSES_TO_WAKE--, res++) { -+ if () break; -+ wf = (FUTEX_WORD); -+ // No happens-before guarantee with woken futex_wait (see above) -+ atomic_store_relaxed (wf, 0); -+ } -+ return res; -+ -+ Note that we need to support futex_wake calls to past futexes whose memory -+ has potentially been reused due to POSIX' requirements on synchronization -+ object destruction (see above); therefore, we must not report or abort -+ on most errors. */ -+static __always_inline void -+futex_wake (unsigned int* futex_word, int processes_to_wake, int private); -+ -+/* Calls __libc_fatal with an error message. Convenience function for -+ concrete implementations of the futex interface. */ -+static __always_inline __attribute__ ((__noreturn__)) void -+futex_fatal_error (void) -+{ -+ __libc_fatal ("The futex facility returned an unexpected error code."); -+} -+ -+#endif /* futex-internal.h */ -diff --git a/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h b/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h -new file mode 100644 -index 00000000..1247949a ---- /dev/null -+++ b/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h -@@ -0,0 +1,208 @@ -+/* Low-level lock implementation. Generic futex-based version. -+ Copyright (C) 2005-2018 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 _LOWLEVELLOCK_H -+#define _LOWLEVELLOCK_H 1 -+ -+#include -+#include -+ -+/* Low-level locks use a combination of atomic operations (to acquire and -+ release lock ownership) and futex operations (to block until the state -+ of a lock changes). A lock can be in one of three states: -+ 0: not acquired, -+ 1: acquired with no waiters; no other threads are blocked or about to block -+ for changes to the lock state, -+ >1: acquired, possibly with waiters; there may be other threads blocked or -+ about to block for changes to the lock state. -+ -+ We expect that the common case is an uncontended lock, so we just need -+ to transition the lock between states 0 and 1; releasing the lock does -+ not need to wake any other blocked threads. If the lock is contended -+ and a thread decides to block using a futex operation, then this thread -+ needs to first change the state to >1; if this state is observed during -+ lock release, the releasing thread will wake one of the potentially -+ blocked threads. -+ -+ Much of this code takes a 'private' parameter. This may be: -+ LLL_PRIVATE: lock only shared within a process -+ LLL_SHARED: lock may be shared across processes. -+ -+ Condition variables contain an optimization for broadcasts that requeues -+ waiting threads on a lock's futex. Therefore, there is a special -+ variant of the locks (whose name contains "cond") that makes sure to -+ always set the lock state to >1 and not just 1. -+ -+ Robust locks set the lock to the id of the owner. This allows detection -+ of the case where the owner exits without releasing the lock. Flags are -+ OR'd with the owner id to record additional information about lock state. -+ Therefore the states of robust locks are: -+ 0: not acquired -+ id: acquired (by user identified by id & FUTEX_TID_MASK) -+ -+ The following flags may be set in the robust lock value: -+ FUTEX_WAITERS - possibly has waiters -+ FUTEX_OWNER_DIED - owning user has exited without releasing the futex. */ -+ -+ -+/* If LOCK is 0 (not acquired), set to 1 (acquired with no waiters) and return -+ 0. Otherwise leave lock unchanged and return non-zero to indicate that the -+ lock was not acquired. */ -+#define lll_trylock(lock) \ -+ __glibc_unlikely (atomic_compare_and_exchange_bool_acq (&(lock), 1, 0)) -+ -+/* If LOCK is 0 (not acquired), set to 2 (acquired, possibly with waiters) and -+ return 0. Otherwise leave lock unchanged and return non-zero to indicate -+ that the lock was not acquired. */ -+#define lll_cond_trylock(lock) \ -+ __glibc_unlikely (atomic_compare_and_exchange_bool_acq (&(lock), 2, 0)) -+ -+extern void __lll_lock_wait_private (int *futex) attribute_hidden; -+extern void __lll_lock_wait (int *futex, int private) attribute_hidden; -+ -+/* This is an expression rather than a statement even though its value is -+ void, so that it can be used in a comma expression or as an expression -+ that's cast to void. */ -+/* The inner conditional compiles to a call to __lll_lock_wait_private if -+ private is known at compile time to be LLL_PRIVATE, and to a call to -+ __lll_lock_wait otherwise. */ -+/* If FUTEX is 0 (not acquired), set to 1 (acquired with no waiters) and -+ return. Otherwise, ensure that it is >1 (acquired, possibly with waiters) -+ and then block until we acquire the lock, at which point FUTEX will still be -+ >1. The lock is always acquired on return. */ -+#define __lll_lock(futex, private) \ -+ ((void) \ -+ ({ \ -+ int *__futex = (futex); \ -+ if (__glibc_unlikely \ -+ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \ -+ { \ -+ if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ -+ __lll_lock_wait_private (__futex); \ -+ else \ -+ __lll_lock_wait (__futex, private); \ -+ } \ -+ })) -+#define lll_lock(futex, private) \ -+ __lll_lock (&(futex), private) -+ -+ -+/* This is an expression rather than a statement even though its value is -+ void, so that it can be used in a comma expression or as an expression -+ that's cast to void. */ -+/* Unconditionally set FUTEX to 2 (acquired, possibly with waiters). If FUTEX -+ was 0 (not acquired) then return. Otherwise, block until the lock is -+ acquired, at which point FUTEX is 2 (acquired, possibly with waiters). The -+ lock is always acquired on return. */ -+#define __lll_cond_lock(futex, private) \ -+ ((void) \ -+ ({ \ -+ int *__futex = (futex); \ -+ if (__glibc_unlikely (atomic_exchange_acq (__futex, 2) != 0)) \ -+ __lll_lock_wait (__futex, private); \ -+ })) -+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) -+ -+ -+extern int __lll_timedlock_wait (int *futex, const struct timespec *, -+ int private) attribute_hidden; -+ -+ -+/* As __lll_lock, but with a timeout. If the timeout occurs then return -+ ETIMEDOUT. If ABSTIME is invalid, return EINVAL. */ -+#define __lll_timedlock(futex, abstime, private) \ -+ ({ \ -+ int *__futex = (futex); \ -+ int __val = 0; \ -+ \ -+ if (__glibc_unlikely \ -+ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \ -+ __val = __lll_timedlock_wait (__futex, abstime, private); \ -+ __val; \ -+ }) -+#define lll_timedlock(futex, abstime, private) \ -+ __lll_timedlock (&(futex), abstime, private) -+ -+ -+/* This is an expression rather than a statement even though its value is -+ void, so that it can be used in a comma expression or as an expression -+ that's cast to void. */ -+/* Unconditionally set FUTEX to 0 (not acquired), releasing the lock. If FUTEX -+ was >1 (acquired, possibly with waiters), then wake any waiters. The waiter -+ that acquires the lock will set FUTEX to >1. -+ Evaluate PRIVATE before releasing the lock so that we do not violate the -+ mutex destruction requirements. Specifically, we need to ensure that -+ another thread can destroy the mutex (and reuse its memory) once it -+ acquires the lock and when there will be no further lock acquisitions; -+ thus, we must not access the lock after releasing it, or those accesses -+ could be concurrent with mutex destruction or reuse of the memory. */ -+#define __lll_unlock(futex, private) \ -+ ((void) \ -+ ({ \ -+ int *__futex = (futex); \ -+ int __private = (private); \ -+ int __oldval = atomic_exchange_rel (__futex, 0); \ -+ if (__glibc_unlikely (__oldval > 1)) \ -+ lll_futex_wake (__futex, 1, __private); \ -+ })) -+#define lll_unlock(futex, private) \ -+ __lll_unlock (&(futex), private) -+ -+ -+#define lll_islocked(futex) \ -+ ((futex) != LLL_LOCK_INITIALIZER) -+ -+ -+/* Our internal lock implementation is identical to the binary-compatible -+ mutex implementation. */ -+ -+/* Initializers for lock. */ -+#define LLL_LOCK_INITIALIZER (0) -+#define LLL_LOCK_INITIALIZER_LOCKED (1) -+ -+ -+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex -+ wake-up when the clone terminates. The memory location contains the -+ thread ID while the clone is running and is reset to zero by the kernel -+ afterwards. The kernel up to version 3.16.3 does not use the private futex -+ operations for futex wake-up when the clone terminates. */ -+#define lll_wait_tid(tid) \ -+ do { \ -+ __typeof (tid) __tid; \ -+ /* We need acquire MO here so that we synchronize \ -+ with the kernel's store to 0 when the clone \ -+ terminates. (see above) */ \ -+ while ((__tid = atomic_load_acquire (&(tid))) != 0) \ -+ lll_futex_wait (&(tid), __tid, LLL_SHARED); \ -+ } while (0) -+ -+extern int __lll_timedwait_tid (int *, const struct timespec *) -+ attribute_hidden; -+ -+/* As lll_wait_tid, but with a timeout. If the timeout occurs then return -+ ETIMEDOUT. If ABSTIME is invalid, return EINVAL. */ -+#define lll_timedwait_tid(tid, abstime) \ -+ ({ \ -+ int __res = 0; \ -+ if ((tid) != 0) \ -+ __res = __lll_timedwait_tid (&(tid), (abstime)); \ -+ __res; \ -+ }) -+ -+ -+#endif /* lowlevellock.h */ -diff --git a/nptl_2_17/sysdeps/unix/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysdep_2_17.h -new file mode 100644 -index 00000000..a9905ff9 ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/sysdep_2_17.h -@@ -0,0 +1,148 @@ -+/* Copyright (C) 1991-2018 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 -+#define HAVE_SYSCALLS -+ -+/* Note that using a `PASTE' macro loses. */ -+#define SYSCALL__(name, args) PSEUDO (__##name, name, args) -+#define SYSCALL(name, args) PSEUDO (name, name, args) -+ -+#define __SYSCALL_CONCAT_X(a,b) a##b -+#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X (a, b) -+ -+ -+#define __INTERNAL_SYSCALL0(name, err) \ -+ INTERNAL_SYSCALL (name, err, 0) -+#define __INTERNAL_SYSCALL1(name, err, a1) \ -+ INTERNAL_SYSCALL (name, err, 1, a1) -+#define __INTERNAL_SYSCALL2(name, err, a1, a2) \ -+ INTERNAL_SYSCALL (name, err, 2, a1, a2) -+#define __INTERNAL_SYSCALL3(name, err, a1, a2, a3) \ -+ INTERNAL_SYSCALL (name, err, 3, a1, a2, a3) -+#define __INTERNAL_SYSCALL4(name, err, a1, a2, a3, a4) \ -+ INTERNAL_SYSCALL (name, err, 4, a1, a2, a3, a4) -+#define __INTERNAL_SYSCALL5(name, err, a1, a2, a3, a4, a5) \ -+ INTERNAL_SYSCALL (name, err, 5, a1, a2, a3, a4, a5) -+#define __INTERNAL_SYSCALL6(name, err, a1, a2, a3, a4, a5, a6) \ -+ INTERNAL_SYSCALL (name, err, 6, a1, a2, a3, a4, a5, a6) -+#define __INTERNAL_SYSCALL7(name, err, a1, a2, a3, a4, a5, a6, a7) \ -+ INTERNAL_SYSCALL (name, err, 7, a1, a2, a3, a4, a5, a6, a7) -+ -+#define __INTERNAL_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,o,...) o -+#define __INTERNAL_SYSCALL_NARGS(...) \ -+ __INTERNAL_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,) -+#define __INTERNAL_SYSCALL_DISP(b,...) \ -+ __SYSCALL_CONCAT (b,__INTERNAL_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) -+ -+/* Issue a syscall defined by syscall number plus any other argument required. -+ It is similar to INTERNAL_SYSCALL macro, but without the need to pass the -+ expected argument number as second parameter. */ -+#define INTERNAL_SYSCALL_CALL(...) \ -+ __INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL, __VA_ARGS__) -+ -+#define __INLINE_SYSCALL0(name) \ -+ INLINE_SYSCALL (name, 0) -+#define __INLINE_SYSCALL1(name, a1) \ -+ INLINE_SYSCALL (name, 1, a1) -+#define __INLINE_SYSCALL2(name, a1, a2) \ -+ INLINE_SYSCALL (name, 2, a1, a2) -+#define __INLINE_SYSCALL3(name, a1, a2, a3) \ -+ INLINE_SYSCALL (name, 3, a1, a2, a3) -+#define __INLINE_SYSCALL4(name, a1, a2, a3, a4) \ -+ INLINE_SYSCALL (name, 4, a1, a2, a3, a4) -+#define __INLINE_SYSCALL5(name, a1, a2, a3, a4, a5) \ -+ INLINE_SYSCALL (name, 5, a1, a2, a3, a4, a5) -+#define __INLINE_SYSCALL6(name, a1, a2, a3, a4, a5, a6) \ -+ INLINE_SYSCALL (name, 6, a1, a2, a3, a4, a5, a6) -+#define __INLINE_SYSCALL7(name, a1, a2, a3, a4, a5, a6, a7) \ -+ INLINE_SYSCALL (name, 7, a1, a2, a3, a4, a5, a6, a7) -+ -+#define __INLINE_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n -+#define __INLINE_SYSCALL_NARGS(...) \ -+ __INLINE_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,) -+#define __INLINE_SYSCALL_DISP(b,...) \ -+ __SYSCALL_CONCAT (b,__INLINE_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) -+ -+/* Issue a syscall defined by syscall number plus any other argument -+ required. Any error will be handled using arch defined macros and errno -+ will be set accordingly. -+ It is similar to INLINE_SYSCALL macro, but without the need to pass the -+ expected argument number as second parameter. */ -+#define INLINE_SYSCALL_CALL(...) \ -+ __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__) -+ -+#define SYSCALL_CANCEL(...) \ -+ ({ \ -+ long int sc_ret; \ -+ if (SINGLE_THREAD_P) \ -+ sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \ -+ else \ -+ { \ -+ int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \ -+ sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \ -+ LIBC_CANCEL_RESET (sc_cancel_oldtype); \ -+ } \ -+ sc_ret; \ -+ }) -+ -+/* Issue a syscall defined by syscall number plus any other argument -+ required. Any error will be returned unmodified (including errno). */ -+#define INTERNAL_SYSCALL_CANCEL(...) \ -+ ({ \ -+ long int sc_ret; \ -+ if (SINGLE_THREAD_P) \ -+ sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); \ -+ else \ -+ { \ -+ int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \ -+ sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); \ -+ LIBC_CANCEL_RESET (sc_cancel_oldtype); \ -+ } \ -+ sc_ret; \ -+ }) -+ -+/* Machine-dependent sysdep.h files are expected to define the macro -+ PSEUDO (function_name, syscall_name) to emit assembly code to define the -+ C-callable function FUNCTION_NAME to do system call SYSCALL_NAME. -+ r0 and r1 are the system call outputs. MOVE(x, y) should be defined as -+ an instruction such that "MOVE(r1, r0)" works. ret should be defined -+ as the return instruction. */ -+ -+#ifndef SYS_ify -+#define SYS_ify(syscall_name) SYS_##syscall_name -+#endif -+ -+/* Terminate a system call named SYM. This is used on some platforms -+ to generate correct debugging information. */ -+#ifndef PSEUDO_END -+#define PSEUDO_END(sym) -+#endif -+#ifndef PSEUDO_END_NOERRNO -+#define PSEUDO_END_NOERRNO(sym) PSEUDO_END(sym) -+#endif -+#ifndef PSEUDO_END_ERRVAL -+#define PSEUDO_END_ERRVAL(sym) PSEUDO_END(sym) -+#endif -+ -+/* Wrappers around system calls should normally inline the system call code. -+ But sometimes it is not possible or implemented and we use this code. */ -+#ifndef INLINE_SYSCALL -+#define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args) -+#endif -diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h -new file mode 100644 -index 00000000..76f41900 ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h -@@ -0,0 +1,301 @@ -+/* Copyright (C) 2005-2018 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 _LINUX_AARCH64_SYSDEP_H -+#define _LINUX_AARCH64_SYSDEP_H 1 -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */ -+#include -+ -+#include -+ -+/* In order to get __set_errno() definition in INLINE_SYSCALL. */ -+#ifndef __ASSEMBLER__ -+#include -+#endif -+ -+/* For Linux we can use the system call table in the header file -+ /usr/include/asm/unistd.h -+ of the kernel. But these symbols do not follow the SYS_* syntax -+ so we have to redefine the `SYS_ify' macro here. */ -+#undef SYS_ify -+#define SYS_ify(syscall_name) (__NR_##syscall_name) -+ -+#ifdef __ASSEMBLER__ -+ -+/* Linux uses a negative return value to indicate syscall errors, -+ unlike most Unices, which use the condition codes' carry flag. -+ -+ Since version 2.1 the return value of a system call might be -+ negative even if the call succeeded. E.g., the `lseek' system call -+ might return a large offset. Therefore we must not anymore test -+ for < 0, but test for a real error by making sure the value in R0 -+ is a real error number. Linus said he will make sure the no syscall -+ returns a value in -1 .. -4095 as a valid result so we can safely -+ test with -4095. */ -+ -+# undef PSEUDO -+# define PSEUDO(name, syscall_name, args) \ -+ .text; \ -+ ENTRY (name); \ -+ DO_CALL (syscall_name, args); \ -+ cmn x0, #4095; \ -+ b.cs .Lsyscall_error; -+ -+# undef PSEUDO_END -+# define PSEUDO_END(name) \ -+ SYSCALL_ERROR_HANDLER \ -+ END (name) -+ -+# undef PSEUDO_NOERRNO -+# define PSEUDO_NOERRNO(name, syscall_name, args) \ -+ .text; \ -+ ENTRY (name); \ -+ DO_CALL (syscall_name, args); -+ -+# undef PSEUDO_END_NOERRNO -+# define PSEUDO_END_NOERRNO(name) \ -+ END (name) -+ -+# define ret_NOERRNO ret -+ -+/* The function has to return the error code. */ -+# undef PSEUDO_ERRVAL -+# define PSEUDO_ERRVAL(name, syscall_name, args) \ -+ .text; \ -+ ENTRY (name) \ -+ DO_CALL (syscall_name, args); \ -+ neg x0, x0 -+ -+# undef PSEUDO_END_ERRVAL -+# define PSEUDO_END_ERRVAL(name) \ -+ END (name) -+ -+# define ret_ERRVAL ret -+ -+# if !IS_IN (libc) -+# define SYSCALL_ERROR .Lsyscall_error -+# if RTLD_PRIVATE_ERRNO -+# define SYSCALL_ERROR_HANDLER \ -+.Lsyscall_error: \ -+ adrp x1, C_SYMBOL_NAME(rtld_errno); \ -+ neg w0, w0; \ -+ str w0, [x1, :lo12:C_SYMBOL_NAME(rtld_errno)]; \ -+ mov x0, -1; \ -+ RET; -+# else -+ -+# define SYSCALL_ERROR_HANDLER \ -+.Lsyscall_error: \ -+ adrp x1, :gottprel:errno; \ -+ neg w2, w0; \ -+ ldr PTR_REG(1), [x1, :gottprel_lo12:errno]; \ -+ mrs x3, tpidr_el0; \ -+ mov x0, -1; \ -+ str w2, [x1, x3]; \ -+ RET; -+# endif -+# else -+# define SYSCALL_ERROR __syscall_error -+# define SYSCALL_ERROR_HANDLER \ -+.Lsyscall_error: \ -+ b __syscall_error; -+# endif -+ -+/* Linux takes system call args in registers: -+ syscall number x8 -+ arg 1 x0 -+ arg 2 x1 -+ arg 3 x2 -+ arg 4 x3 -+ arg 5 x4 -+ arg 6 x5 -+ arg 7 x6 -+ -+ The compiler is going to form a call by coming here, through PSEUDO, with -+ arguments -+ syscall number in the DO_CALL macro -+ arg 1 x0 -+ arg 2 x1 -+ arg 3 x2 -+ arg 4 x3 -+ arg 5 x4 -+ arg 6 x5 -+ arg 7 x6 -+ -+*/ -+ -+# undef DO_CALL -+# define DO_CALL(syscall_name, args) \ -+ mov x8, SYS_ify (syscall_name); \ -+ svc 0 -+ -+#else /* not __ASSEMBLER__ */ -+ -+ -+/* List of system calls which are supported as vsyscalls. */ -+# define HAVE_CLOCK_GETRES_VSYSCALL 1 -+# define HAVE_CLOCK_GETTIME_VSYSCALL 1 -+# define HAVE_GETTIMEOFDAY_VSYSCALL 1 -+ -+/* Previously AArch64 used the generic version without the libc_hidden_def -+ which lead in a non existent __send symbol in libc.so. */ -+# undef HAVE_INTERNAL_SEND_SYMBOL -+ -+# define SINGLE_THREAD_BY_GLOBAL 1 -+ -+/* Define a macro which expands into the inline wrapper code for a system -+ call. */ -+# undef INLINE_SYSCALL -+# define INLINE_SYSCALL(name, nr, args...) \ -+ ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); \ -+ if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))\ -+ { \ -+ __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \ -+ _sys_result = (unsigned long) -1; \ -+ } \ -+ (long) _sys_result; }) -+ -+# undef INTERNAL_SYSCALL_DECL -+# define INTERNAL_SYSCALL_DECL(err) do { } while (0) -+ -+# undef INTERNAL_SYSCALL_RAW -+# define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ -+ ({ long _sys_result; \ -+ { \ -+ LOAD_ARGS_##nr (args) \ -+ register long _x8 asm ("x8") = (name); \ -+ asm volatile ("svc 0 // syscall " # name \ -+ : "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr : "memory"); \ -+ _sys_result = _x0; \ -+ } \ -+ _sys_result; }) -+ -+# undef INTERNAL_SYSCALL -+# define INTERNAL_SYSCALL(name, err, nr, args...) \ -+ INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args) -+ -+# undef INTERNAL_SYSCALL_AARCH64 -+# define INTERNAL_SYSCALL_AARCH64(name, err, nr, args...) \ -+ INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args) -+ -+# undef INTERNAL_SYSCALL_ERROR_P -+# define INTERNAL_SYSCALL_ERROR_P(val, err) \ -+ ((unsigned long) (val) >= (unsigned long) -4095) -+ -+# undef INTERNAL_SYSCALL_ERRNO -+# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) -+ -+# define LOAD_ARGS_0() \ -+ register long _x0 asm ("x0"); -+# define LOAD_ARGS_1(x0) \ -+ long _x0tmp = (long) (x0); \ -+ LOAD_ARGS_0 () \ -+ _x0 = _x0tmp; -+# define LOAD_ARGS_2(x0, x1) \ -+ long _x1tmp = (long) (x1); \ -+ LOAD_ARGS_1 (x0) \ -+ register long _x1 asm ("x1") = _x1tmp; -+# define LOAD_ARGS_3(x0, x1, x2) \ -+ long _x2tmp = (long) (x2); \ -+ LOAD_ARGS_2 (x0, x1) \ -+ register long _x2 asm ("x2") = _x2tmp; -+# define LOAD_ARGS_4(x0, x1, x2, x3) \ -+ long _x3tmp = (long) (x3); \ -+ LOAD_ARGS_3 (x0, x1, x2) \ -+ register long _x3 asm ("x3") = _x3tmp; -+# define LOAD_ARGS_5(x0, x1, x2, x3, x4) \ -+ long _x4tmp = (long) (x4); \ -+ LOAD_ARGS_4 (x0, x1, x2, x3) \ -+ register long _x4 asm ("x4") = _x4tmp; -+# define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5) \ -+ long _x5tmp = (long) (x5); \ -+ LOAD_ARGS_5 (x0, x1, x2, x3, x4) \ -+ register long _x5 asm ("x5") = _x5tmp; -+# define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\ -+ long _x6tmp = (long) (x6); \ -+ LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5) \ -+ register long _x6 asm ("x6") = _x6tmp; -+ -+# define ASM_ARGS_0 -+# define ASM_ARGS_1 , "r" (_x0) -+# define ASM_ARGS_2 ASM_ARGS_1, "r" (_x1) -+# define ASM_ARGS_3 ASM_ARGS_2, "r" (_x2) -+# define ASM_ARGS_4 ASM_ARGS_3, "r" (_x3) -+# define ASM_ARGS_5 ASM_ARGS_4, "r" (_x4) -+# define ASM_ARGS_6 ASM_ARGS_5, "r" (_x5) -+# define ASM_ARGS_7 ASM_ARGS_6, "r" (_x6) -+ -+# undef INTERNAL_SYSCALL_NCS -+# define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ -+ INTERNAL_SYSCALL_RAW (number, err, nr, args) -+ -+#endif /* __ASSEMBLER__ */ -+ -+/* Pointer mangling is supported for AArch64. */ -+#if (IS_IN (rtld) || \ -+ (!defined SHARED && (IS_IN (libc) \ -+ || IS_IN (libpthread)))) -+# ifdef __ASSEMBLER__ -+/* Note, dst, src, guard, and tmp are all register numbers rather than -+ register names so they will work with both ILP32 and LP64. */ -+# define PTR_MANGLE(dst, src, guard, tmp) \ -+ LDST_PCREL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); \ -+ PTR_MANGLE2 (dst, src, guard) -+/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ -+# define PTR_MANGLE2(dst, src, guard)\ -+ eor x##dst, x##src, x##guard -+# define PTR_DEMANGLE(dst, src, guard, tmp)\ -+ PTR_MANGLE (dst, src, guard, tmp) -+# define PTR_DEMANGLE2(dst, src, guard)\ -+ PTR_MANGLE2 (dst, src, guard) -+# else -+extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; -+# define PTR_MANGLE(var) \ -+ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local) -+# define PTR_DEMANGLE(var) PTR_MANGLE (var) -+# endif -+#else -+# ifdef __ASSEMBLER__ -+/* Note, dst, src, guard, and tmp are all register numbers rather than -+ register names so they will work with both ILP32 and LP64. */ -+# define PTR_MANGLE(dst, src, guard, tmp) \ -+ LDST_GLOBAL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard)); \ -+ PTR_MANGLE2 (dst, src, guard) -+/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ -+# define PTR_MANGLE2(dst, src, guard)\ -+ eor x##dst, x##src, x##guard -+# define PTR_DEMANGLE(dst, src, guard, tmp)\ -+ PTR_MANGLE (dst, src, guard, tmp) -+# define PTR_DEMANGLE2(dst, src, guard)\ -+ PTR_MANGLE2 (dst, src, guard) -+# else -+extern uintptr_t __pointer_chk_guard attribute_relro; -+# define PTR_MANGLE(var) \ -+ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard) -+# define PTR_DEMANGLE(var) PTR_MANGLE (var) -+# endif -+#endif -+ -+#endif /* linux/aarch64/sysdep.h */ -diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h -new file mode 100644 -index 00000000..1898464d ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h -@@ -0,0 +1,35 @@ -+/* Copyright (C) 2011-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Chris Metcalf , 2011. -+ -+ 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 -+ -+/* Provide the common name to allow more code reuse. */ -+#ifdef __NR_llseek -+# define __NR__llseek __NR_llseek -+#endif -+ -+#if __WORDSIZE == 64 -+/* By defining the older names, glibc will build syscall wrappers for -+ both pread and pread64; sysdeps/unix/sysv/linux/wordsize-64/pread64.c -+ will suppress generating any separate code for pread64.c. */ -+#define __NR_pread __NR_pread64 -+#define __NR_pwrite __NR_pwrite64 -+#endif -diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h -new file mode 100644 -index 00000000..8f2b45c3 ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h -@@ -0,0 +1,91 @@ -+/* Special use of signals internally. Linux version. -+ Copyright (C) 2014-2018 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 __INTERNAL_SIGNALS_H -+# define __INTERNAL_SIGNALS_H -+ -+#include -+#include -+#include -+#include -+ -+/* The signal used for asynchronous cancelation. */ -+#define SIGCANCEL __SIGRTMIN -+ -+ -+/* Signal needed for the kernel-supported POSIX timer implementation. -+ We can reuse the cancellation signal since we can distinguish -+ cancellation from timer expirations. */ -+#define SIGTIMER SIGCANCEL -+ -+ -+/* Signal used to implement the setuid et.al. functions. */ -+#define SIGSETXID (__SIGRTMIN + 1) -+ -+ -+/* Return is sig is used internally. */ -+static inline bool -+__is_internal_signal (int sig) -+{ -+ return (sig == SIGCANCEL) || (sig == SIGSETXID); -+} -+ -+/* Remove internal glibc signal from the mask. */ -+static inline void -+__clear_internal_signals (sigset_t *set) -+{ -+ __sigdelset (set, SIGCANCEL); -+ __sigdelset (set, SIGSETXID); -+} -+ -+#define SIGALL_SET \ -+ ((__sigset_t) { .__val = {[0 ... _SIGSET_NWORDS-1 ] = -1 } }) -+ -+/* Block all signals, including internal glibc ones. */ -+static inline int -+__libc_signal_block_all (sigset_t *set) -+{ -+ INTERNAL_SYSCALL_DECL (err); -+ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &SIGALL_SET, -+ set, _NSIG / 8); -+} -+ -+/* Block all application signals (excluding internal glibc ones). */ -+static inline int -+__libc_signal_block_app (sigset_t *set) -+{ -+ sigset_t allset = SIGALL_SET; -+ __clear_internal_signals (&allset); -+ INTERNAL_SYSCALL_DECL (err); -+ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &allset, set, -+ _NSIG / 8); -+} -+ -+/* Restore current process signal mask. */ -+static inline int -+__libc_signal_restore_set (const sigset_t *set) -+{ -+ INTERNAL_SYSCALL_DECL (err); -+ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, set, NULL, -+ _NSIG / 8); -+} -+ -+/* Used to communicate with signal handler. */ -+extern struct xid_command *__xidcmd attribute_hidden; -+ -+#endif -diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h -new file mode 100644 -index 00000000..399de2e5 ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h -@@ -0,0 +1,150 @@ -+/* Low-level locking access to futex facilities. Linux version. -+ Copyright (C) 2005-2018 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 _LOWLEVELLOCK_FUTEX_H -+#define _LOWLEVELLOCK_FUTEX_H 1 -+ -+#ifndef __ASSEMBLER__ -+#include -+#include -+#include -+#endif -+ -+#define FUTEX_WAIT 0 -+#define FUTEX_WAKE 1 -+#define FUTEX_REQUEUE 3 -+#define FUTEX_CMP_REQUEUE 4 -+#define FUTEX_WAKE_OP 5 -+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) -+#define FUTEX_LOCK_PI 6 -+#define FUTEX_UNLOCK_PI 7 -+#define FUTEX_TRYLOCK_PI 8 -+#define FUTEX_WAIT_BITSET 9 -+#define FUTEX_WAKE_BITSET 10 -+#define FUTEX_WAIT_REQUEUE_PI 11 -+#define FUTEX_CMP_REQUEUE_PI 12 -+#define FUTEX_PRIVATE_FLAG 128 -+#define FUTEX_CLOCK_REALTIME 256 -+ -+#define FUTEX_BITSET_MATCH_ANY 0xffffffff -+ -+/* Values for 'private' parameter of locking macros. Yes, the -+ definition seems to be backwards. But it is not. The bit will be -+ reversed before passing to the system call. */ -+#define LLL_PRIVATE 0 -+#define LLL_SHARED FUTEX_PRIVATE_FLAG -+ -+#ifndef __ASSEMBLER__ -+ -+#if IS_IN (libc) || IS_IN (rtld) -+/* In libc.so or ld.so all futexes are private. */ -+# define __lll_private_flag(fl, private) \ -+ ({ \ -+ /* Prevent warnings in callers of this macro. */ \ -+ int __lll_private_flag_priv __attribute__ ((unused)); \ -+ __lll_private_flag_priv = (private); \ -+ ((fl) | FUTEX_PRIVATE_FLAG); \ -+ }) -+#else -+# define __lll_private_flag(fl, private) \ -+ (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) -+#endif -+ -+#define lll_futex_syscall(nargs, futexp, op, ...) \ -+ ({ \ -+ INTERNAL_SYSCALL_DECL (__err); \ -+ long int __ret = INTERNAL_SYSCALL (futex, __err, nargs, futexp, op, \ -+ __VA_ARGS__); \ -+ (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__ret, __err)) \ -+ ? -INTERNAL_SYSCALL_ERRNO (__ret, __err) : 0); \ -+ }) -+ -+#define lll_futex_wait(futexp, val, private) \ -+ lll_futex_timed_wait (futexp, val, NULL, private) -+ -+#define lll_futex_timed_wait(futexp, val, timeout, private) \ -+ lll_futex_syscall (4, futexp, \ -+ __lll_private_flag (FUTEX_WAIT, private), \ -+ val, timeout) -+ -+/* Verify whether the supplied clockid is supported by -+ lll_futex_clock_wait_bitset. */ -+#define lll_futex_supported_clockid(clockid) \ -+ ((clockid) == CLOCK_REALTIME || (clockid) == CLOCK_MONOTONIC) -+ -+/* The kernel currently only supports CLOCK_MONOTONIC or -+ CLOCK_REALTIME timeouts for FUTEX_WAIT_BITSET. We could attempt to -+ convert others here but currently do not. */ -+#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \ -+ ({ \ -+ long int __ret; \ -+ if (lll_futex_supported_clockid (clockid)) \ -+ { \ -+ const unsigned int clockbit = \ -+ (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0; \ -+ const int op = \ -+ __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private); \ -+ \ -+ __ret = lll_futex_syscall (6, futexp, op, val, \ -+ timeout, NULL /* Unused. */, \ -+ FUTEX_BITSET_MATCH_ANY); \ -+ } \ -+ else \ -+ __ret = -EINVAL; \ -+ __ret; \ -+ }) -+ -+#define lll_futex_wake(futexp, nr, private) \ -+ lll_futex_syscall (4, futexp, \ -+ __lll_private_flag (FUTEX_WAKE, private), nr, 0) -+ -+/* Returns non-zero if error happened, zero if success. */ -+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ -+ lll_futex_syscall (6, futexp, \ -+ __lll_private_flag (FUTEX_CMP_REQUEUE, private), \ -+ nr_wake, nr_move, mutex, val) -+ -+/* Returns non-zero if error happened, zero if success. */ -+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ -+ lll_futex_syscall (6, futexp, \ -+ __lll_private_flag (FUTEX_WAKE_OP, private), \ -+ nr_wake, nr_wake2, futexp2, \ -+ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE) -+ -+/* Priority Inheritance support. */ -+#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \ -+ lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private) -+ -+#define lll_futex_timed_wait_requeue_pi(futexp, val, timeout, clockbit, \ -+ mutex, private) \ -+ lll_futex_syscall (5, futexp, \ -+ __lll_private_flag (FUTEX_WAIT_REQUEUE_PI \ -+ | (clockbit), private), \ -+ val, timeout, mutex) -+ -+ -+#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, \ -+ val, private) \ -+ lll_futex_syscall (6, futexp, \ -+ __lll_private_flag (FUTEX_CMP_REQUEUE_PI, \ -+ private), \ -+ nr_wake, nr_move, mutex, val) -+ -+#endif /* !__ASSEMBLER__ */ -+ -+#endif /* lowlevellock-futex.h */ -diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h -new file mode 100644 -index 00000000..602307db ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h -@@ -0,0 +1,93 @@ -+/* Uncancelable versions of cancelable interfaces. Linux/NPTL version. -+ Copyright (C) 2003-2018 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 -+ . */ -+ -+#ifndef NOT_CANCEL_H -+# define NOT_CANCEL_H -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Non cancellable open syscall. */ -+__typeof (open) __open_nocancel; -+ -+/* Non cancellable open syscall (LFS version). */ -+__typeof (open64) __open64_nocancel; -+ -+/* Non cancellable openat syscall. */ -+__typeof (openat) __openat_nocancel; -+ -+/* Non cacellable openat syscall (LFS version). */ -+__typeof (openat64) __openat64_nocancel; -+ -+/* Non cancellable read syscall. */ -+__typeof (__read) __read_nocancel; -+ -+/* Uncancelable write. */ -+__typeof (__write) __write_nocancel; -+ -+/* Uncancelable close. */ -+__typeof (__close) __close_nocancel; -+ -+/* Non cancellable close syscall that does not also set errno in case of -+ failure. */ -+static inline void -+__close_nocancel_nostatus (int fd) -+{ -+ __close_nocancel (fd); -+} -+ -+/* Non cancellable writev syscall that does not also set errno in case of -+ failure. */ -+static inline void -+__writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt) -+{ -+ INTERNAL_SYSCALL_DECL (err); -+ INTERNAL_SYSCALL_CALL (writev, err, fd, iov, iovcnt); -+} -+ -+/* Uncancelable waitpid. */ -+__typeof (waitpid) __waitpid_nocancel; -+ -+/* Uncancelable pause. */ -+__typeof (pause) __pause_nocancel; -+ -+/* Uncancelable nanosleep. */ -+__typeof (__nanosleep) __nanosleep_nocancel; -+ -+/* Uncancelable fcntl. */ -+__typeof (__fcntl) __fcntl64_nocancel; -+ -+hidden_proto (__open_nocancel) -+hidden_proto (__open64_nocancel) -+hidden_proto (__openat_nocancel) -+hidden_proto (__openat64_nocancel) -+hidden_proto (__read_nocancel) -+hidden_proto (__write_nocancel) -+hidden_proto (__close_nocancel) -+hidden_proto (__waitpid_nocancel) -+hidden_proto (__pause_nocancel) -+hidden_proto (__nanosleep_nocancel) -+hidden_proto (__fcntl64_nocancel) -+ -+#endif /* NOT_CANCEL_H */ -diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h -new file mode 100644 -index 00000000..4fd0a9ba ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h -@@ -0,0 +1,68 @@ -+/* Copyright (C) 2015-2018 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 -+ -+/* Set error number and return -1. A target may choose to return the -+ internal function, __syscall_error, which sets errno and returns -1. -+ We use -1l, instead of -1, so that it can be casted to (void *). */ -+#define INLINE_SYSCALL_ERROR_RETURN_VALUE(err) \ -+ ({ \ -+ __set_errno (err); \ -+ -1l; \ -+ }) -+ -+/* Provide a dummy argument that can be used to force register -+ alignment for register pairs if required by the syscall ABI. */ -+#ifdef __ASSUME_ALIGNED_REGISTER_PAIRS -+#define __ALIGNMENT_ARG 0, -+#define __ALIGNMENT_COUNT(a,b) b -+#else -+#define __ALIGNMENT_ARG -+#define __ALIGNMENT_COUNT(a,b) a -+#endif -+ -+/* Provide a common macro to pass 64-bit value on syscalls. */ -+#if __WORDSIZE == 64 || defined __ASSUME_WORDSIZE64_ILP32 -+# define SYSCALL_LL(val) (val) -+# define SYSCALL_LL64(val) (val) -+#else -+#define SYSCALL_LL(val) \ -+ __LONG_LONG_PAIR ((val) >> 31, (val)) -+#define SYSCALL_LL64(val) \ -+ __LONG_LONG_PAIR ((long) ((val) >> 32), (long) ((val) & 0xffffffff)) -+#endif -+ -+/* Provide a common macro to pass 64-bit value on pread and pwrite -+ syscalls. */ -+#ifdef __ASSUME_PRW_DUMMY_ARG -+# define SYSCALL_LL_PRW(val) 0, SYSCALL_LL (val) -+# define SYSCALL_LL64_PRW(val) 0, SYSCALL_LL64 (val) -+#else -+# define SYSCALL_LL_PRW(val) __ALIGNMENT_ARG SYSCALL_LL (val) -+# define SYSCALL_LL64_PRW(val) __ALIGNMENT_ARG SYSCALL_LL64 (val) -+#endif -+ -+/* Provide a macro to pass the off{64}_t argument on p{readv,writev}{64}. */ -+#define LO_HI_LONG(val) \ -+ (long) (val), \ -+ (long) (((uint64_t) (val)) >> 32) -+ -+/* Exports the __send symbol on send.c linux implementation (some ABI have -+ it missing due the usage of a old generic version without it). */ -+#define HAVE_INTERNAL_SEND_SYMBOL 1 -diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h -new file mode 100644 -index 00000000..8cf61c21 ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h -@@ -0,0 +1,432 @@ -+/* Copyright (C) 2001-2018 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 _LINUX_X86_64_SYSDEP_H -+#define _LINUX_X86_64_SYSDEP_H 1 -+ -+/* There is some commonality. */ -+#include -+#include -+#include "descr_2_17.h" -+#include -+ -+/* Defines RTLD_PRIVATE_ERRNO. */ -+#include -+ -+/* For Linux we can use the system call table in the header file -+ /usr/include/asm/unistd.h -+ of the kernel. But these symbols do not follow the SYS_* syntax -+ so we have to redefine the `SYS_ify' macro here. */ -+#undef SYS_ify -+#define SYS_ify(syscall_name) __NR_##syscall_name -+ -+/* This is a kludge to make syscalls.list find these under the names -+ pread and pwrite, since some kernel headers define those names -+ and some define the *64 names for the same system calls. */ -+#if !defined __NR_pread && defined __NR_pread64 -+# define __NR_pread __NR_pread64 -+#endif -+#if !defined __NR_pwrite && defined __NR_pwrite64 -+# define __NR_pwrite __NR_pwrite64 -+#endif -+ -+/* This is to help the old kernel headers where __NR_semtimedop is not -+ available. */ -+#ifndef __NR_semtimedop -+# define __NR_semtimedop 220 -+#endif -+ -+ -+#ifdef __ASSEMBLER__ -+ -+/* Linux uses a negative return value to indicate syscall errors, -+ unlike most Unices, which use the condition codes' carry flag. -+ -+ Since version 2.1 the return value of a system call might be -+ negative even if the call succeeded. E.g., the `lseek' system call -+ might return a large offset. Therefore we must not anymore test -+ for < 0, but test for a real error by making sure the value in %eax -+ is a real error number. Linus said he will make sure the no syscall -+ returns a value in -1 .. -4095 as a valid result so we can savely -+ test with -4095. */ -+ -+/* We don't want the label for the error handle to be global when we define -+ it here. */ -+# ifdef PIC -+# define SYSCALL_ERROR_LABEL 0f -+# else -+# define SYSCALL_ERROR_LABEL syscall_error -+# endif -+ -+# undef PSEUDO -+# define PSEUDO(name, syscall_name, args) \ -+ .text; \ -+ ENTRY (name) \ -+ DO_CALL (syscall_name, args); \ -+ cmpq $-4095, %rax; \ -+ jae SYSCALL_ERROR_LABEL -+ -+# undef PSEUDO_END -+# define PSEUDO_END(name) \ -+ SYSCALL_ERROR_HANDLER \ -+ END (name) -+ -+# undef PSEUDO_NOERRNO -+# define PSEUDO_NOERRNO(name, syscall_name, args) \ -+ .text; \ -+ ENTRY (name) \ -+ DO_CALL (syscall_name, args) -+ -+# undef PSEUDO_END_NOERRNO -+# define PSEUDO_END_NOERRNO(name) \ -+ END (name) -+ -+# define ret_NOERRNO ret -+ -+# undef PSEUDO_ERRVAL -+# define PSEUDO_ERRVAL(name, syscall_name, args) \ -+ .text; \ -+ ENTRY (name) \ -+ DO_CALL (syscall_name, args); \ -+ negq %rax -+ -+# undef PSEUDO_END_ERRVAL -+# define PSEUDO_END_ERRVAL(name) \ -+ END (name) -+ -+# define ret_ERRVAL ret -+ -+# if defined PIC && RTLD_PRIVATE_ERRNO -+# define SYSCALL_SET_ERRNO \ -+ lea rtld_errno(%rip), %RCX_LP; \ -+ neg %eax; \ -+ movl %eax, (%rcx) -+# else -+# if IS_IN (libc) -+# define SYSCALL_ERROR_ERRNO __libc_errno -+# else -+# define SYSCALL_ERROR_ERRNO errno -+# endif -+# define SYSCALL_SET_ERRNO \ -+ movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\ -+ neg %eax; \ -+ movl %eax, %fs:(%rcx); -+# endif -+ -+# ifndef PIC -+# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ -+# else -+# define SYSCALL_ERROR_HANDLER \ -+0: \ -+ SYSCALL_SET_ERRNO; \ -+ or $-1, %RAX_LP; \ -+ ret; -+# endif /* PIC */ -+ -+/* The Linux/x86-64 kernel expects the system call parameters in -+ registers according to the following table: -+ -+ syscall number rax -+ arg 1 rdi -+ arg 2 rsi -+ arg 3 rdx -+ arg 4 r10 -+ arg 5 r8 -+ arg 6 r9 -+ -+ The Linux kernel uses and destroys internally these registers: -+ return address from -+ syscall rcx -+ eflags from syscall r11 -+ -+ Normal function call, including calls to the system call stub -+ functions in the libc, get the first six parameters passed in -+ registers and the seventh parameter and later on the stack. The -+ register use is as follows: -+ -+ system call number in the DO_CALL macro -+ arg 1 rdi -+ arg 2 rsi -+ arg 3 rdx -+ arg 4 rcx -+ arg 5 r8 -+ arg 6 r9 -+ -+ We have to take care that the stack is aligned to 16 bytes. When -+ called the stack is not aligned since the return address has just -+ been pushed. -+ -+ -+ Syscalls of more than 6 arguments are not supported. */ -+ -+# undef DO_CALL -+# define DO_CALL(syscall_name, args) \ -+ DOARGS_##args \ -+ movl $SYS_ify (syscall_name), %eax; \ -+ syscall; -+ -+# define DOARGS_0 /* nothing */ -+# define DOARGS_1 /* nothing */ -+# define DOARGS_2 /* nothing */ -+# define DOARGS_3 /* nothing */ -+# define DOARGS_4 movq %rcx, %r10; -+# define DOARGS_5 DOARGS_4 -+# define DOARGS_6 DOARGS_5 -+ -+#else /* !__ASSEMBLER__ */ -+/* Define a macro which expands inline into the wrapper code for a system -+ call. */ -+# undef INLINE_SYSCALL -+# define INLINE_SYSCALL(name, nr, args...) \ -+ ({ \ -+ unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args); \ -+ if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \ -+ { \ -+ __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ -+ resultvar = (unsigned long int) -1; \ -+ } \ -+ (long int) resultvar; }) -+ -+/* Define a macro with explicit types for arguments, which expands inline -+ into the wrapper code for a system call. It should be used when size -+ of any argument > size of long int. */ -+# undef INLINE_SYSCALL_TYPES -+# define INLINE_SYSCALL_TYPES(name, nr, args...) \ -+ ({ \ -+ unsigned long int resultvar = INTERNAL_SYSCALL_TYPES (name, , nr, args); \ -+ if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \ -+ { \ -+ __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ -+ resultvar = (unsigned long int) -1; \ -+ } \ -+ (long int) resultvar; }) -+ -+# undef INTERNAL_SYSCALL_DECL -+# define INTERNAL_SYSCALL_DECL(err) do { } while (0) -+ -+/* Registers clobbered by syscall. */ -+# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx" -+ -+/* Create a variable 'name' based on type 'X' to avoid explicit types. -+ This is mainly used set use 64-bits arguments in x32. */ -+#define TYPEFY(X, name) __typeof__ ((X) - (X)) name -+/* Explicit cast the argument to avoid integer from pointer warning on -+ x32. */ -+#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) -+ -+#undef INTERNAL_SYSCALL -+#define INTERNAL_SYSCALL(name, err, nr, args...) \ -+ internal_syscall##nr (SYS_ify (name), err, args) -+ -+#undef INTERNAL_SYSCALL_NCS -+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ -+ internal_syscall##nr (number, err, args) -+ -+#undef internal_syscall0 -+#define internal_syscall0(number, err, dummy...) \ -+({ \ -+ unsigned long int resultvar; \ -+ asm volatile ( \ -+ "syscall\n\t" \ -+ : "=a" (resultvar) \ -+ : "0" (number) \ -+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ -+ (long int) resultvar; \ -+}) -+ -+#undef internal_syscall1 -+#define internal_syscall1(number, err, arg1) \ -+({ \ -+ unsigned long int resultvar; \ -+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ -+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ -+ asm volatile ( \ -+ "syscall\n\t" \ -+ : "=a" (resultvar) \ -+ : "0" (number), "r" (_a1) \ -+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ -+ (long int) resultvar; \ -+}) -+ -+#undef internal_syscall2 -+#define internal_syscall2(number, err, arg1, arg2) \ -+({ \ -+ unsigned long int resultvar; \ -+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ -+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ -+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ -+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ -+ asm volatile ( \ -+ "syscall\n\t" \ -+ : "=a" (resultvar) \ -+ : "0" (number), "r" (_a1), "r" (_a2) \ -+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ -+ (long int) resultvar; \ -+}) -+ -+#undef internal_syscall3 -+#define internal_syscall3(number, err, arg1, arg2, arg3) \ -+({ \ -+ unsigned long int resultvar; \ -+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ -+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ -+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ -+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \ -+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ -+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ -+ asm volatile ( \ -+ "syscall\n\t" \ -+ : "=a" (resultvar) \ -+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3) \ -+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ -+ (long int) resultvar; \ -+}) -+ -+#undef internal_syscall4 -+#define internal_syscall4(number, err, arg1, arg2, arg3, arg4) \ -+({ \ -+ unsigned long int resultvar; \ -+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \ -+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ -+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ -+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ -+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \ -+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \ -+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ -+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ -+ asm volatile ( \ -+ "syscall\n\t" \ -+ : "=a" (resultvar) \ -+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4) \ -+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ -+ (long int) resultvar; \ -+}) -+ -+#undef internal_syscall5 -+#define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5) \ -+({ \ -+ unsigned long int resultvar; \ -+ TYPEFY (arg5, __arg5) = ARGIFY (arg5); \ -+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \ -+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ -+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ -+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ -+ register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \ -+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \ -+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \ -+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ -+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ -+ asm volatile ( \ -+ "syscall\n\t" \ -+ : "=a" (resultvar) \ -+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \ -+ "r" (_a5) \ -+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ -+ (long int) resultvar; \ -+}) -+ -+#undef internal_syscall6 -+#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \ -+({ \ -+ unsigned long int resultvar; \ -+ TYPEFY (arg6, __arg6) = ARGIFY (arg6); \ -+ TYPEFY (arg5, __arg5) = ARGIFY (arg5); \ -+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \ -+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \ -+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \ -+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \ -+ register TYPEFY (arg6, _a6) asm ("r9") = __arg6; \ -+ register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \ -+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \ -+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \ -+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \ -+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \ -+ asm volatile ( \ -+ "syscall\n\t" \ -+ : "=a" (resultvar) \ -+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \ -+ "r" (_a5), "r" (_a6) \ -+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \ -+ (long int) resultvar; \ -+}) -+ -+# undef INTERNAL_SYSCALL_ERROR_P -+# define INTERNAL_SYSCALL_ERROR_P(val, err) \ -+ ((unsigned long int) (long int) (val) >= -4095L) -+ -+# undef INTERNAL_SYSCALL_ERRNO -+# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) -+ -+/* List of system calls which are supported as vsyscalls. */ -+# define HAVE_CLOCK_GETTIME_VSYSCALL 1 -+# define HAVE_GETTIMEOFDAY_VSYSCALL 1 -+# define HAVE_GETCPU_VSYSCALL 1 -+ -+# define SINGLE_THREAD_BY_GLOBAL 1 -+ -+#endif /* __ASSEMBLER__ */ -+ -+ -+/* Pointer mangling support. */ -+#if IS_IN (rtld) -+/* We cannot use the thread descriptor because in ld.so we use setjmp -+ earlier than the descriptor is initialized. */ -+# ifdef __ASSEMBLER__ -+# define PTR_MANGLE(reg) xor __pointer_chk_guard_local(%rip), reg; \ -+ rol $2*LP_SIZE+1, reg -+# define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \ -+ xor __pointer_chk_guard_local(%rip), reg -+# else -+# define PTR_MANGLE(reg) asm ("xor __pointer_chk_guard_local(%%rip), %0\n" \ -+ "rol $2*" LP_SIZE "+1, %0" \ -+ : "=r" (reg) : "0" (reg)) -+# define PTR_DEMANGLE(reg) asm ("ror $2*" LP_SIZE "+1, %0\n" \ -+ "xor __pointer_chk_guard_local(%%rip), %0" \ -+ : "=r" (reg) : "0" (reg)) -+# endif -+#else -+# ifdef __ASSEMBLER__ -+# define PTR_MANGLE(reg) xor %fs:POINTER_GUARD, reg; \ -+ rol $2*LP_SIZE+1, reg -+# define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \ -+ xor %fs:POINTER_GUARD, reg -+# else -+# define PTR_MANGLE(var) asm ("xor %%fs:%c2, %0\n" \ -+ "rol $2*" LP_SIZE "+1, %0" \ -+ : "=r" (var) \ -+ : "0" (var), \ -+ "i" (offsetof (tcbhead_t, \ -+ pointer_guard))) -+# define PTR_DEMANGLE(var) asm ("ror $2*" LP_SIZE "+1, %0\n" \ -+ "xor %%fs:%c2, %0" \ -+ : "=r" (var) \ -+ : "0" (var), \ -+ "i" (offsetof (tcbhead_t, \ -+ pointer_guard))) -+# endif -+#endif -+ -+/* How to pass the off{64}_t argument on p{readv,writev}{64}. */ -+#undef LO_HI_LONG -+#define LO_HI_LONG(val) (val), 0 -+ -+/* Each shadow stack slot takes 8 bytes. Assuming that each stack -+ frame takes 256 bytes, this is used to compute shadow stack size -+ from stack size. */ -+#define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5 -+ -+#endif /* linux/x86_64/sysdep.h */ -diff --git a/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h -new file mode 100644 -index 00000000..5d61be20 ---- /dev/null -+++ b/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h -@@ -0,0 +1,34 @@ -+/* Copyright (C) 1991-2018 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 -+ -+#ifdef __ASSEMBLER__ -+ -+/* This is defined as a separate macro so that other sysdep.h files -+ can include this one and then redefine DO_CALL. */ -+ -+#define DO_CALL(syscall_name, args) \ -+ lea SYS_ify (syscall_name), %rax; \ -+ syscall -+ -+#define r0 %rax /* Normal return-value register. */ -+#define r1 %rbx /* Secondary return-value register. */ -+#define MOVE(x,y) movq x, y -+ -+#endif /* __ASSEMBLER__ */ -diff --git a/nptl_2_17/sysdeps/x86/sysdep_2_17.h b/nptl_2_17/sysdeps/x86/sysdep_2_17.h -new file mode 100644 -index 00000000..9f319ea4 ---- /dev/null -+++ b/nptl_2_17/sysdeps/x86/sysdep_2_17.h -@@ -0,0 +1,104 @@ -+/* Assembler macros for x86. -+ Copyright (C) 2017-2018 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 _X86_SYSDEP_H -+#define _X86_SYSDEP_H 1 -+ -+#include -+ -+/* __CET__ is defined by GCC with Control-Flow Protection values: -+ -+enum cf_protection_level -+{ -+ CF_NONE = 0, -+ CF_BRANCH = 1 << 0, -+ CF_RETURN = 1 << 1, -+ CF_FULL = CF_BRANCH | CF_RETURN, -+ CF_SET = 1 << 2 -+}; -+*/ -+ -+/* Set if CF_BRANCH (IBT) is enabled. */ -+#define X86_FEATURE_1_IBT (1U << 0) -+/* Set if CF_RETURN (SHSTK) is enabled. */ -+#define X86_FEATURE_1_SHSTK (1U << 1) -+ -+#ifdef __CET__ -+# define CET_ENABLED 1 -+# define IBT_ENABLED (__CET__ & X86_FEATURE_1_IBT) -+# define SHSTK_ENABLED (__CET__ & X86_FEATURE_1_SHSTK) -+#else -+# define CET_ENABLED 0 -+# define IBT_ENABLED 0 -+# define SHSTK_ENABLED 0 -+#endif -+ -+#ifdef __ASSEMBLER__ -+ -+/* Syntactic details of assembler. */ -+ -+#ifdef _CET_ENDBR -+# define _CET_NOTRACK notrack -+#else -+# define _CET_ENDBR -+# define _CET_NOTRACK -+#endif -+ -+/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ -+#define ALIGNARG(log2) 1<. */ -+ -+#ifndef _BITS_PTHREADTYPES_ARCH_H -+#define _BITS_PTHREADTYPES_ARCH_H 1 -+ -+#include -+ -+#ifdef __x86_64__ -+# if __WORDSIZE == 64 -+# define __SIZEOF_PTHREAD_MUTEX_T 40 -+# define __SIZEOF_PTHREAD_ATTR_T 56 -+# define __SIZEOF_PTHREAD_MUTEX_T 40 -+# define __SIZEOF_PTHREAD_RWLOCK_T 56 -+# define __SIZEOF_PTHREAD_BARRIER_T 32 -+# else -+# define __SIZEOF_PTHREAD_MUTEX_T 32 -+# define __SIZEOF_PTHREAD_ATTR_T 32 -+# define __SIZEOF_PTHREAD_MUTEX_T 32 -+# define __SIZEOF_PTHREAD_RWLOCK_T 44 -+# define __SIZEOF_PTHREAD_BARRIER_T 20 -+# endif -+#else -+# define __SIZEOF_PTHREAD_MUTEX_T 24 -+# define __SIZEOF_PTHREAD_ATTR_T 36 -+# define __SIZEOF_PTHREAD_MUTEX_T 24 -+# define __SIZEOF_PTHREAD_RWLOCK_T 32 -+# define __SIZEOF_PTHREAD_BARRIER_T 20 -+#endif -+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 -+#define __SIZEOF_PTHREAD_COND_T 48 -+#define __SIZEOF_PTHREAD_CONDATTR_T 4 -+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 -+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 -+ -+/* Definitions for internal mutex struct. */ -+#define __PTHREAD_COMPAT_PADDING_MID -+#define __PTHREAD_COMPAT_PADDING_END -+#define __PTHREAD_MUTEX_LOCK_ELISION 1 -+#ifdef __x86_64__ -+# define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 -+# define __PTHREAD_MUTEX_USE_UNION 0 -+#else -+# define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 1 -+# define __PTHREAD_MUTEX_USE_UNION 1 -+#endif -+ -+#define __LOCK_ALIGNMENT -+#define __ONCE_ALIGNMENT -+ -+struct __pthread_rwlock_arch_t -+{ -+ unsigned int __readers; -+ unsigned int __writers; -+ unsigned int __wrphase_futex; -+ unsigned int __writers_futex; -+ unsigned int __pad3; -+ unsigned int __pad4; -+#ifdef __x86_64__ -+ int __cur_writer; -+ int __shared; -+ signed char __rwelision; -+# ifdef __ILP32__ -+ unsigned char __pad1[3]; -+# define __PTHREAD_RWLOCK_ELISION_EXTRA 0, { 0, 0, 0 } -+# else -+ unsigned char __pad1[7]; -+# define __PTHREAD_RWLOCK_ELISION_EXTRA 0, { 0, 0, 0, 0, 0, 0, 0 } -+# endif -+ unsigned long int __pad2; -+ /* FLAGS must stay at this position in the structure to maintain -+ binary compatibility. */ -+ unsigned int __flags; -+# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1 -+#else -+ /* FLAGS must stay at this position in the structure to maintain -+ binary compatibility. */ -+ unsigned char __flags; -+ unsigned char __shared; -+ signed char __rwelision; -+# define __PTHREAD_RWLOCK_ELISION_EXTRA 0 -+ unsigned char __pad2; -+ int __cur_writer; -+#endif -+}; -+ -+#ifndef __x86_64__ -+/* Extra attributes for the cleanup functions. */ -+# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1))) -+#endif -+ -+#endif /* bits/pthreadtypes.h */ -diff --git a/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h -new file mode 100644 -index 00000000..ab1b6bea ---- /dev/null -+++ b/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h -@@ -0,0 +1,129 @@ -+/* Assembler macros for x86-64. -+ Copyright (C) 2001-2018 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 _X86_64_SYSDEP_H -+#define _X86_64_SYSDEP_H 1 -+ -+#include -+ -+#ifdef __ASSEMBLER__ -+ -+/* Syntactic details of assembler. */ -+ -+/* This macro is for setting proper CFI with DW_CFA_expression describing -+ the register as saved relative to %rsp instead of relative to the CFA. -+ Expression is DW_OP_drop, DW_OP_breg7 (%rsp is register 7), sleb128 offset -+ from %rsp. */ -+#define cfi_offset_rel_rsp(regn, off) .cfi_escape 0x10, regn, 0x4, 0x13, \ -+ 0x77, off & 0x7F | 0x80, off >> 7 -+ -+/* If compiled for profiling, call `mcount' at the start of each function. */ -+#ifdef PROF -+/* The mcount code relies on a normal frame pointer being on the stack -+ to locate our caller, so push one just for its benefit. */ -+#define CALL_MCOUNT \ -+ pushq %rbp; \ -+ cfi_adjust_cfa_offset(8); \ -+ movq %rsp, %rbp; \ -+ cfi_def_cfa_register(%rbp); \ -+ call JUMPTARGET(mcount); \ -+ popq %rbp; \ -+ cfi_def_cfa(rsp,8); -+#else -+#define CALL_MCOUNT /* Do nothing. */ -+#endif -+ -+#define PSEUDO(name, syscall_name, args) \ -+lose: \ -+ jmp JUMPTARGET(syscall_error) \ -+ .globl syscall_error; \ -+ ENTRY (name) \ -+ DO_CALL (syscall_name, args); \ -+ jb lose -+ -+#undef JUMPTARGET -+#ifdef SHARED -+# ifdef BIND_NOW -+# define JUMPTARGET(name) *name##@GOTPCREL(%rip) -+# else -+# define JUMPTARGET(name) name##@PLT -+# endif -+#else -+/* For static archives, branch to target directly. */ -+# define JUMPTARGET(name) name -+#endif -+ -+/* Long and pointer size in bytes. */ -+#define LP_SIZE 8 -+ -+/* Instruction to operate on long and pointer. */ -+#define LP_OP(insn) insn##q -+ -+/* Assembler address directive. */ -+#define ASM_ADDR .quad -+ -+/* Registers to hold long and pointer. */ -+#define RAX_LP rax -+#define RBP_LP rbp -+#define RBX_LP rbx -+#define RCX_LP rcx -+#define RDI_LP rdi -+#define RDX_LP rdx -+#define RSI_LP rsi -+#define RSP_LP rsp -+#define R8_LP r8 -+#define R9_LP r9 -+#define R10_LP r10 -+#define R11_LP r11 -+#define R12_LP r12 -+#define R13_LP r13 -+#define R14_LP r14 -+#define R15_LP r15 -+ -+#else /* __ASSEMBLER__ */ -+ -+/* Long and pointer size in bytes. */ -+#define LP_SIZE "8" -+ -+/* Instruction to operate on long and pointer. */ -+#define LP_OP(insn) #insn "q" -+ -+/* Assembler address directive. */ -+#define ASM_ADDR ".quad" -+ -+/* Registers to hold long and pointer. */ -+#define RAX_LP "rax" -+#define RBP_LP "rbp" -+#define RBX_LP "rbx" -+#define RCX_LP "rcx" -+#define RDI_LP "rdi" -+#define RDX_LP "rdx" -+#define RSI_LP "rsi" -+#define RSP_LP "rsp" -+#define R8_LP "r8" -+#define R9_LP "r9" -+#define R10_LP "r10" -+#define R11_LP "r11" -+#define R12_LP "r12" -+#define R13_LP "r13" -+#define R14_LP "r14" -+#define R15_LP "r15" -+ -+#endif /* __ASSEMBLER__ */ -+ -+#endif /* _X86_64_SYSDEP_H */ -diff --git a/nptl_2_17/thread_db_2_17.h b/nptl_2_17/thread_db_2_17.h -new file mode 100644 -index 00000000..4206aed0 ---- /dev/null -+++ b/nptl_2_17/thread_db_2_17.h -@@ -0,0 +1,458 @@ -+/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread -+ Copyright (C) 1999-2018 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_DB_H -+#define _THREAD_DB_H 1 -+ -+/* This is the debugger interface for the NPTL library. It is -+ modelled closely after the interface with same names in Solaris -+ with the goal to share the same code in the debugger. */ -+#include -+#include -+#include -+#include -+ -+ -+/* Error codes of the library. */ -+typedef enum -+{ -+ TD_OK, /* No error. */ -+ TD_ERR, /* No further specified error. */ -+ TD_NOTHR, /* No matching thread found. */ -+ TD_NOSV, /* No matching synchronization handle found. */ -+ TD_NOLWP, /* No matching light-weighted process found. */ -+ TD_BADPH, /* Invalid process handle. */ -+ TD_BADTH, /* Invalid thread handle. */ -+ TD_BADSH, /* Invalid synchronization handle. */ -+ TD_BADTA, /* Invalid thread agent. */ -+ TD_BADKEY, /* Invalid key. */ -+ TD_NOMSG, /* No event available. */ -+ TD_NOFPREGS, /* No floating-point register content available. */ -+ TD_NOLIBTHREAD, /* Application not linked with thread library. */ -+ TD_NOEVENT, /* Requested event is not supported. */ -+ TD_NOCAPAB, /* Capability not available. */ -+ TD_DBERR, /* Internal debug library error. */ -+ TD_NOAPLIC, /* Operation is not applicable. */ -+ TD_NOTSD, /* No thread-specific data available. */ -+ TD_MALLOC, /* Out of memory. */ -+ TD_PARTIALREG, /* Not entire register set was read or written. */ -+ TD_NOXREGS, /* X register set not available for given thread. */ -+ TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */ -+ TD_NOTALLOC = TD_TLSDEFER, -+ TD_VERSION, /* Version if libpthread and libthread_db do not match. */ -+ TD_NOTLS /* There is no TLS segment in the given module. */ -+} td_err_e; -+ -+ -+/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to -+ select threads regardless of state in td_ta_thr_iter(). */ -+typedef enum -+{ -+ TD_THR_ANY_STATE, -+ TD_THR_UNKNOWN, -+ TD_THR_STOPPED, -+ TD_THR_RUN, -+ TD_THR_ACTIVE, -+ TD_THR_ZOMBIE, -+ TD_THR_SLEEP, -+ TD_THR_STOPPED_ASLEEP -+} td_thr_state_e; -+ -+/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used -+ to select threads regardless of type in td_ta_thr_iter(). */ -+typedef enum -+{ -+ TD_THR_ANY_TYPE, -+ TD_THR_USER, -+ TD_THR_SYSTEM -+} td_thr_type_e; -+ -+ -+/* Types of the debugging library. */ -+ -+/* Handle for a process. This type is opaque. */ -+typedef struct td_thragent td_thragent_t; -+ -+/* The actual thread handle type. This is also opaque. */ -+typedef struct td_thrhandle -+{ -+ td_thragent_t *th_ta_p; -+ psaddr_t th_unique; -+} td_thrhandle_t; -+ -+ -+/* Forward declaration of a type defined by and for the dynamic linker. */ -+struct link_map; -+ -+ -+/* Flags for `td_ta_thr_iter'. */ -+#define TD_THR_ANY_USER_FLAGS 0xffffffff -+#define TD_THR_LOWEST_PRIORITY -20 -+#define TD_SIGNO_MASK NULL -+ -+ -+#define TD_EVENTSIZE 2 -+#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */ -+#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per unsigned int */ -+#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */ -+ -+/* Bitmask of enabled events. */ -+typedef struct td_thr_events -+{ -+ uint32_t event_bits[TD_EVENTSIZE]; -+} td_thr_events_t; -+ -+/* Event set manipulation macros. */ -+#define __td_eventmask(n) \ -+ (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) -+#define __td_eventword(n) \ -+ ((UINT32_C ((n) - 1)) >> BT_UISHIFT) -+ -+#define td_event_emptyset(setp) \ -+ do { \ -+ int __i; \ -+ for (__i = TD_EVENTSIZE; __i > 0; --__i) \ -+ (setp)->event_bits[__i - 1] = 0; \ -+ } while (0) -+ -+#define td_event_fillset(setp) \ -+ do { \ -+ int __i; \ -+ for (__i = TD_EVENTSIZE; __i > 0; --__i) \ -+ (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \ -+ } while (0) -+ -+#define td_event_addset(setp, n) \ -+ (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) -+#define td_event_delset(setp, n) \ -+ (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) -+#define td_eventismember(setp, n) \ -+ (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) -+#if TD_EVENTSIZE == 2 -+# define td_eventisempty(setp) \ -+ (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) -+#else -+# error "td_eventisempty must be changed to match TD_EVENTSIZE" -+#endif -+ -+/* Events reportable by the thread implementation. */ -+typedef enum -+{ -+ TD_ALL_EVENTS, /* Pseudo-event number. */ -+ TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */ -+ TD_READY, /* Is executable now. */ -+ TD_SLEEP, /* Blocked in a synchronization obj. */ -+ TD_SWITCHTO, /* Now assigned to a process. */ -+ TD_SWITCHFROM, /* Not anymore assigned to a process. */ -+ TD_LOCK_TRY, /* Trying to get an unavailable lock. */ -+ TD_CATCHSIG, /* Signal posted to the thread. */ -+ TD_IDLE, /* Process getting idle. */ -+ TD_CREATE, /* New thread created. */ -+ TD_DEATH, /* Thread terminated. */ -+ TD_PREEMPT, /* Preempted. */ -+ TD_PRI_INHERIT, /* Inherited elevated priority. */ -+ TD_REAP, /* Reaped. */ -+ TD_CONCURRENCY, /* Number of processes changing. */ -+ TD_TIMEOUT, /* Conditional variable wait timed out. */ -+ TD_MIN_EVENT_NUM = TD_READY, -+ TD_MAX_EVENT_NUM = TD_TIMEOUT, -+ TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */ -+} td_event_e; -+ -+/* Values representing the different ways events are reported. */ -+typedef enum -+{ -+ NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */ -+ NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically -+ inserted. */ -+ NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */ -+} td_notify_e; -+ -+/* Description how event type is reported. */ -+typedef struct td_notify -+{ -+ td_notify_e type; /* Way the event is reported. */ -+ union -+ { -+ psaddr_t bptaddr; /* Address of breakpoint. */ -+ int syscallno; /* Number of system call used. */ -+ } u; -+} td_notify_t; -+ -+/* Structure used to report event. */ -+typedef struct td_event_msg -+{ -+ td_event_e event; /* Event type being reported. */ -+ const td_thrhandle_t *th_p; /* Thread reporting the event. */ -+ union -+ { -+# if 0 -+ td_synchandle_t *sh; /* Handle of synchronization object. */ -+#endif -+ uintptr_t data; /* Event specific data. */ -+ } msg; -+} td_event_msg_t; -+ -+/* Structure containing event data available in each thread structure. */ -+typedef struct -+{ -+ td_thr_events_t eventmask; /* Mask of enabled events. */ -+ td_event_e eventnum; /* Number of last event. */ -+ void *eventdata; /* Data associated with event. */ -+} td_eventbuf_t; -+ -+ -+/* Gathered statistics about the process. */ -+typedef struct td_ta_stats -+{ -+ int nthreads; /* Total number of threads in use. */ -+ int r_concurrency; /* Concurrency level requested by user. */ -+ int nrunnable_num; /* Average runnable threads, numerator. */ -+ int nrunnable_den; /* Average runnable threads, denominator. */ -+ int a_concurrency_num; /* Achieved concurrency level, numerator. */ -+ int a_concurrency_den; /* Achieved concurrency level, denominator. */ -+ int nlwps_num; /* Average number of processes in use, -+ numerator. */ -+ int nlwps_den; /* Average number of processes in use, -+ denominator. */ -+ int nidle_num; /* Average number of idling processes, -+ numerator. */ -+ int nidle_den; /* Average number of idling processes, -+ denominator. */ -+} td_ta_stats_t; -+ -+ -+/* Since Sun's library is based on Solaris threads we have to define a few -+ types to map them to POSIX threads. */ -+typedef pthread_t thread_t; -+typedef pthread_key_t thread_key_t; -+ -+ -+/* Callback for iteration over threads. */ -+typedef int td_thr_iter_f (const td_thrhandle_t *, void *); -+ -+/* Callback for iteration over thread local data. */ -+typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); -+ -+ -+ -+/* Forward declaration. This has to be defined by the user. */ -+struct ps_prochandle; -+ -+ -+/* Information about the thread. */ -+typedef struct td_thrinfo -+{ -+ td_thragent_t *ti_ta_p; /* Process handle. */ -+ unsigned int ti_user_flags; /* Unused. */ -+ thread_t ti_tid; /* Thread ID returned by -+ pthread_create(). */ -+ char *ti_tls; /* Pointer to thread-local data. */ -+ psaddr_t ti_startfunc; /* Start function passed to -+ pthread_create(). */ -+ psaddr_t ti_stkbase; /* Base of thread's stack. */ -+ long int ti_stksize; /* Size of thread's stack. */ -+ psaddr_t ti_ro_area; /* Unused. */ -+ int ti_ro_size; /* Unused. */ -+ td_thr_state_e ti_state; /* Thread state. */ -+ unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */ -+ td_thr_type_e ti_type; /* Type of the thread (system vs -+ user thread). */ -+ intptr_t ti_pc; /* Unused. */ -+ intptr_t ti_sp; /* Unused. */ -+ short int ti_flags; /* Unused. */ -+ int ti_pri; /* Thread priority. */ -+ lwpid_t ti_lid; /* Kernel PID for this thread. */ -+ sigset_t ti_sigmask; /* Signal mask. */ -+ unsigned char ti_traceme; /* Nonzero if event reporting -+ enabled. */ -+ unsigned char ti_preemptflag; /* Unused. */ -+ unsigned char ti_pirecflag; /* Unused. */ -+ sigset_t ti_pending; /* Set of pending signals. */ -+ td_thr_events_t ti_events; /* Set of enabled events. */ -+} td_thrinfo_t; -+ -+ -+ -+/* Prototypes for exported library functions. */ -+ -+/* Initialize the thread debug support library. */ -+extern td_err_e td_init (void); -+ -+/* Historical relict. Should not be used anymore. */ -+extern td_err_e td_log (void); -+ -+/* Return list of symbols the library can request. */ -+extern const char **td_symbol_list (void); -+ -+/* Generate new thread debug library handle for process PS. */ -+extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); -+ -+/* Free resources allocated for TA. */ -+extern td_err_e td_ta_delete (td_thragent_t *__ta); -+ -+/* Get number of currently running threads in process associated with TA. */ -+extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); -+ -+/* Return process handle passed in `td_ta_new' for process associated with -+ TA. */ -+extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, -+ struct ps_prochandle **__ph); -+ -+/* Map thread library handle PT to thread debug library handle for process -+ associated with TA and store result in *TH. */ -+extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, -+ td_thrhandle_t *__th); -+ -+/* Map process ID LWPID to thread debug library handle for process -+ associated with TA and store result in *TH. */ -+extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, -+ td_thrhandle_t *__th); -+ -+ -+/* Call for each thread in a process associated with TA the callback function -+ CALLBACK. */ -+extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, -+ td_thr_iter_f *__callback, void *__cbdata_p, -+ td_thr_state_e __state, int __ti_pri, -+ sigset_t *__ti_sigmask_p, -+ unsigned int __ti_user_flags); -+ -+/* Call for each defined thread local data entry the callback function KI. */ -+extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, -+ void *__p); -+ -+ -+/* Get event address for EVENT. */ -+extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, -+ td_event_e __event, td_notify_t *__ptr); -+ -+/* Enable EVENT in global mask. */ -+extern td_err_e td_ta_set_event (const td_thragent_t *__ta, -+ td_thr_events_t *__event); -+ -+/* Disable EVENT in global mask. */ -+extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, -+ td_thr_events_t *__event); -+ -+/* Return information about last event. */ -+extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, -+ td_event_msg_t *__msg); -+ -+ -+/* Set suggested concurrency level for process associated with TA. */ -+extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); -+ -+ -+/* Enable collecting statistics for process associated with TA. */ -+extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); -+ -+/* Reset statistics. */ -+extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); -+ -+/* Retrieve statistics from process associated with TA. */ -+extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, -+ td_ta_stats_t *__statsp); -+ -+ -+/* Validate that TH is a thread handle. */ -+extern td_err_e td_thr_validate (const td_thrhandle_t *__th); -+ -+/* Return information about thread TH. */ -+extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, -+ td_thrinfo_t *__infop); -+ -+/* Retrieve floating-point register contents of process running thread TH. */ -+extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, -+ prfpregset_t *__regset); -+ -+/* Retrieve general register contents of process running thread TH. */ -+extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, -+ prgregset_t __gregs); -+ -+/* Retrieve extended register contents of process running thread TH. */ -+extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); -+ -+/* Get size of extended register set of process running thread TH. */ -+extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); -+ -+/* Set floating-point register contents of process running thread TH. */ -+extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, -+ const prfpregset_t *__fpregs); -+ -+/* Set general register contents of process running thread TH. */ -+extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, -+ prgregset_t __gregs); -+ -+/* Set extended register contents of process running thread TH. */ -+extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, -+ const void *__addr); -+ -+ -+/* Get address of the given module's TLS storage area for the given thread. */ -+extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, -+ unsigned long int __modid, -+ psaddr_t *__base); -+ -+/* Get address of thread local variable. */ -+extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, -+ psaddr_t __map_address, size_t __offset, -+ psaddr_t *__address); -+ -+ -+/* Enable reporting for EVENT for thread TH. */ -+extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); -+ -+/* Enable EVENT for thread TH. */ -+extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, -+ td_thr_events_t *__event); -+ -+/* Disable EVENT for thread TH. */ -+extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, -+ td_thr_events_t *__event); -+ -+/* Get event message for thread TH. */ -+extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, -+ td_event_msg_t *__msg); -+ -+ -+/* Set priority of thread TH. */ -+extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); -+ -+ -+/* Set pending signals for thread TH. */ -+extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, -+ unsigned char __n, const sigset_t *__ss); -+ -+/* Set signal mask for thread TH. */ -+extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, -+ const sigset_t *__ss); -+ -+ -+/* Return thread local data associated with key TK in thread TH. */ -+extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, -+ const thread_key_t __tk, void **__data); -+ -+ -+/* Suspend execution of thread TH. */ -+extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); -+ -+/* Resume execution of thread TH. */ -+extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); -+ -+#endif /* thread_db.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..45fff81a ---- /dev/null -+++ b/nptl_2_17/tpp_2_17.c -@@ -0,0 +1,195 @@ -+/* Thread Priority Protect helpers. -+ Copyright (C) 2006-2018 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 "pthreadP_2_17.h" -+#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/vars_2_17.c b/nptl_2_17/vars_2_17.c -new file mode 100644 -index 00000000..ae60c0f8 ---- /dev/null -+++ b/nptl_2_17/vars_2_17.c -@@ -0,0 +1,43 @@ -+/* Copyright (C) 2004-2018 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 "pthreadP_2_17.h" -+#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.30.0 - diff --git a/glibc.spec b/glibc.spec index 6631723..857aa33 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 26 +Release: 27 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -136,7 +136,15 @@ Patch49: posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch -Patch9002: compat-2.17-libpthreadcond-so.patch +Patch9002: 0001-add-base-files-for-libphtread-condition-family.patch +Patch9003: 0002-add-header-files-for-libphtread_2_17_so.patch +Patch9004: 0003-add-build-script-and-files-of-libpthread_2_17_so.patch +Patch9005: 0004-add-two-header-files-with-some-deleted-macros.patch +Patch9006: 0005-add-pthread-functions_h.patch +Patch9007: 0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch +Patch9008: 0007-add-lowlevellock_2_17_c.patch +Patch9009: 0008-add-pause_nocancel_2_17.patch +Patch9010: 0009-add-unwind-with-longjmp.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -765,7 +773,7 @@ touch compat-2.17.filelist -e '\,.*/etc/\(localtime\|nsswitch.conf\|ld\.so\.conf\|ld\.so\.cache\|default\|rpc\|gai\.conf\),d' \ -e '\,.*/%{_libdir}/lib\(pcprofile\|memusage\)\.so,d' \ %if %{with compat_2_17} - -e '\,.*/%{_libdir}/libpthread-2.17.so,d' \ + -e '\,.*%{_libdir}/libpthread-2.17.so,d' \ %endif -e '\,.*/bin/\(memusage\|mtrace\|xtrace\|pcprofiledump\),d' } | sort > master.filelist @@ -1322,6 +1330,10 @@ fi %endif %changelog +* Wed Nov 24 2021 Yang Yanchao - 2.34-27 +- Refactor the libpthread-2.17.so code and pass all test cases. + delete libpthread-2.17.so from glibc-devel + * Fri Nov 19 2021 Qingqing Li - 2.34-26 - revert supress -Wcast-qual warnings in bsearch -- Gitee From 3930cde25a44da27c1d3f43d6497ec8b3a044518 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Nov 2021 10:14:26 +0800 Subject: [PATCH 27/70] Linux: Simplify __opensock and fix race condition [BZ #28353] AF_NETLINK support is not quite optional on modern Linux systems anymore, so it is likely that the first attempt will always succeed. Consequently, there is no need to cache the result. Keep AF_UNIX and the Internet address families as a fallback, for the rare case that AF_NETLINK is missing. The other address families previously probed are totally obsolete be now, so remove them. Use this simplified version as the generic implementation, disabling Netlink support as needed. Signed-off-by: Bin Wang (cherry picked from commit b91290ce417b9a6dec5d1d044fa8ab361d0e300a) --- ..._opensock-and-fix-race-condition-BZ-.patch | 241 ++++++++++++++++++ glibc.spec | 6 +- 2 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch diff --git a/Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch b/Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch new file mode 100644 index 0000000..b7cbeef --- /dev/null +++ b/Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch @@ -0,0 +1,241 @@ +From 5bf07e1b3a74232bfb8332275110be1a5da50f83 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Tue, 28 Sep 2021 18:55:49 +0200 +Subject: [PATCH] Linux: Simplify __opensock and fix race condition [BZ #28353] + +AF_NETLINK support is not quite optional on modern Linux systems +anymore, so it is likely that the first attempt will always succeed. +Consequently, there is no need to cache the result. Keep AF_UNIX +and the Internet address families as a fallback, for the rare case +that AF_NETLINK is missing. The other address families previously +probed are totally obsolete be now, so remove them. + +Use this simplified version as the generic implementation, disabling +Netlink support as needed. +--- + socket/opensock.c | 65 +++++--------- + sysdeps/unix/sysv/linux/opensock.c | 114 ------------------------ + sysdeps/unix/sysv/linux/s390/opensock.c | 2 - + 3 files changed, 22 insertions(+), 159 deletions(-) + delete mode 100644 sysdeps/unix/sysv/linux/opensock.c + delete mode 100644 sysdeps/unix/sysv/linux/s390/opensock.c + +diff --git a/socket/opensock.c b/socket/opensock.c +index 37148d4743..ff94d27a61 100644 +--- a/socket/opensock.c ++++ b/socket/opensock.c +@@ -1,4 +1,5 @@ +-/* Copyright (C) 1999-2021 Free Software Foundation, Inc. ++/* Create socket with an unspecified address family for use with ioctl. ++ Copyright (C) 1999-2021 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 +@@ -15,56 +16,34 @@ + License along with the GNU C Library; if not, see + . */ + +-#include ++#include + #include +-#include + + /* Return a socket of any type. The socket can be used in subsequent + ioctl calls to talk to the kernel. */ + int + __opensock (void) + { +- /* Cache the last AF that worked, to avoid many redundant calls to +- socket(). */ +- static int sock_af = -1; +- int fd = -1; +- __libc_lock_define_initialized (static, lock); +- +- if (sock_af != -1) +- { +- fd = __socket (sock_af, SOCK_DGRAM, 0); +- if (fd != -1) +- return fd; +- } +- +- __libc_lock_lock (lock); +- +- if (sock_af != -1) +- fd = __socket (sock_af, SOCK_DGRAM, 0); +- +- if (fd == -1) +- { +-#ifdef AF_INET +- fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0); +-#endif +-#ifdef AF_INET6 +- if (fd < 0) +- fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0); +-#endif +-#ifdef AF_IPX +- if (fd < 0) +- fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0); +-#endif +-#ifdef AF_AX25 +- if (fd < 0) +- fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0); +-#endif +-#ifdef AF_APPLETALK +- if (fd < 0) +- fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0); ++ /* SOCK_DGRAM is supported by all address families. (Netlink does ++ not support SOCK_STREAM.) */ ++ int type = SOCK_DGRAM | SOCK_CLOEXEC; ++ int fd; ++ ++#ifdef AF_NETLINK ++ fd = __socket (AF_NETLINK, type, 0); ++ if (fd >= 0) ++ return fd; + #endif +- } + +- __libc_lock_unlock (lock); ++ fd = __socket (AF_UNIX, type, 0); ++ if (fd >= 0) ++ return fd; ++ fd = __socket (AF_INET, type, 0); ++ if (fd >= 0) ++ return fd; ++ fd = __socket (AF_INET6, type, 0); ++ if (fd >= 0) ++ return fd; ++ __set_errno (ENOENT); + return fd; + } +diff --git a/sysdeps/unix/sysv/linux/opensock.c b/sysdeps/unix/sysv/linux/opensock.c +deleted file mode 100644 +index e87d6e58b0..0000000000 +--- a/sysdeps/unix/sysv/linux/opensock.c ++++ /dev/null +@@ -1,114 +0,0 @@ +-/* Copyright (C) 1999-2021 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 +- +-/* Return a socket of any type. The socket can be used in subsequent +- ioctl calls to talk to the kernel. */ +-int +-__opensock (void) +-{ +- static int last_family; /* Available socket family we will use. */ +- static int last_type; +- static const struct +- { +- int family; +- const char procname[15]; +- } afs[] = +- { +- { AF_UNIX, "net/unix" }, +- { AF_INET, "" }, +- { AF_INET6, "net/if_inet6" }, +- { AF_AX25, "net/ax25" }, +- { AF_NETROM, "net/nr" }, +- { AF_ROSE, "net/rose" }, +- { AF_IPX, "net/ipx" }, +- { AF_APPLETALK, "net/appletalk" }, +- { AF_ECONET, "sys/net/econet" }, +- { AF_ASH, "sys/net/ash" }, +- { AF_X25, "net/x25" }, +-#ifdef NEED_AF_IUCV +- { AF_IUCV, "net/iucv" } +-#endif +- }; +-#define nafs (sizeof (afs) / sizeof (afs[0])) +- char fname[sizeof "/proc/" + 14]; +- int result; +- int has_proc; +- size_t cnt; +- +- /* We already know which family to use from the last call. Use it +- again. */ +- if (last_family != 0) +- { +- assert (last_type != 0); +- +- result = __socket (last_family, last_type | SOCK_CLOEXEC, 0); +- if (result != -1 || errno != EAFNOSUPPORT) +- /* Maybe the socket type isn't supported anymore (module is +- unloaded). In this case again try to find the type. */ +- return result; +- +- /* Reset the values. They seem not valid anymore. */ +- last_family = 0; +- last_type = 0; +- } +- +- /* Check whether the /proc filesystem is available. */ +- has_proc = __access ("/proc/net", R_OK) != -1; +- strcpy (fname, "/proc/"); +- +- /* Iterate over the interface families and find one which is +- available. */ +- for (cnt = 0; cnt < nafs; ++cnt) +- { +- int type = SOCK_DGRAM; +- +- if (has_proc && afs[cnt].procname[0] != '\0') +- { +- strcpy (fname + 6, afs[cnt].procname); +- if (__access (fname, R_OK) == -1) +- /* The /proc entry is not available. I.e., we cannot +- create a socket of this type (without loading the +- module). Don't look for it since this might trigger +- loading the module. */ +- continue; +- } +- +- if (afs[cnt].family == AF_NETROM || afs[cnt].family == AF_X25) +- type = SOCK_SEQPACKET; +- +- result = __socket (afs[cnt].family, type | SOCK_CLOEXEC, 0); +- if (result != -1) +- { +- /* Found an available family. */ +- last_type = type; +- last_family = afs[cnt].family; +- return result; +- } +- } +- +- /* None of the protocol families is available. It is unclear what kind +- of error is returned. ENOENT seems like a reasonable choice. */ +- __set_errno (ENOENT); +- return -1; +-} +diff --git a/sysdeps/unix/sysv/linux/s390/opensock.c b/sysdeps/unix/sysv/linux/s390/opensock.c +deleted file mode 100644 +index f099d651ff..0000000000 +--- a/sysdeps/unix/sysv/linux/s390/opensock.c ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define NEED_AF_IUCV 1 +-#include "../opensock.c" +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 857aa33..af2dbad 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 27 +Release: 28 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -133,6 +133,7 @@ Patch46: ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch Patch47: ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch Patch48: Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch Patch49: posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch +Patch50: Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1330,6 +1331,9 @@ fi %endif %changelog +* Tue Nov 30 2021 Bin Wang - 2.34-28 +- Linux: Simplify __opensock and fix race condition [BZ #28353] + * Wed Nov 24 2021 Yang Yanchao - 2.34-27 - Refactor the libpthread-2.17.so code and pass all test cases. delete libpthread-2.17.so from glibc-devel -- Gitee From 738782294d8fc4b27a95ccd1434526787287de5c Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Thu, 2 Dec 2021 19:28:14 +0800 Subject: [PATCH 28/70] revert the use of sched_getaffinity [BZ #28310] (cherry picked from commit 0057d144a90d6b57f3e3ba185dfca19d1a3282d7) --- glibc.spec | 8 +- ...-use-of-sched_getaffinity-on-get_npr.patch | 206 +++++++++++++++++ linux-Simplify-get_nprocs.patch | 216 ++++++++++++++++++ misc-Add-__get_nprocs_sched.patch | 110 +++++++++ 4 files changed, 539 insertions(+), 1 deletion(-) create mode 100644 linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch create mode 100644 linux-Simplify-get_nprocs.patch create mode 100644 misc-Add-__get_nprocs_sched.patch diff --git a/glibc.spec b/glibc.spec index af2dbad..4c8bcda 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 28 +Release: 29 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -134,6 +134,9 @@ Patch47: ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch Patch48: Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch Patch49: posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch Patch50: Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch +Patch51: linux-Simplify-get_nprocs.patch +Patch52: misc-Add-__get_nprocs_sched.patch +Patch53: linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch #Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1331,6 +1334,9 @@ fi %endif %changelog +* Thu Dec 2 2021 Qingqing Li - 2.34-29 +- revert the use of sched_getaffinity [BZ #28310] + * Tue Nov 30 2021 Bin Wang - 2.34-28 - Linux: Simplify __opensock and fix race condition [BZ #28353] diff --git a/linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch b/linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch new file mode 100644 index 0000000..17a7a5c --- /dev/null +++ b/linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch @@ -0,0 +1,206 @@ +From 342298278eabc75baabcaced110a11a02c3d3580 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 6 Sep 2021 14:19:51 -0300 +Subject: [PATCH] linux: Revert the use of sched_getaffinity on get_nproc (BZ + #28310) + +The use of sched_getaffinity on get_nproc and +sysconf (_SC_NPROCESSORS_ONLN) done in 903bc7dcc2acafc40 (BZ #27645) +breaks the top command in common hypervisor configurations and also +other monitoring tools. + +The main issue using sched_getaffinity changed the symbols semantic +from system-wide scope of online CPUs to per-process one (which can +be changed with kernel cpusets or book parameters in VM). + +This patch reverts mostly of the 903bc7dcc2acafc40, with the +exceptions: + + * No more cached values and atomic updates, since they are inherent + racy. + + * No /proc/cpuinfo fallback, since /proc/stat is already used and + it would require to revert more arch-specific code. + + * The alloca is replace with a static buffer of 1024 bytes. + +So the implementation first consult the sysfs, and fallbacks to procfs. + +Checked on x86_64-linux-gnu. + +Reviewed-by: Florian Weimer +--- + sysdeps/unix/sysv/linux/getsysstats.c | 139 ++++++++++++++++++++++++++++++++-- + 1 file changed, 134 insertions(+), 5 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c +index 1e3d886..15ad91c 100644 +--- a/sysdeps/unix/sysv/linux/getsysstats.c ++++ b/sysdeps/unix/sysv/linux/getsysstats.c +@@ -17,6 +17,8 @@ + . */ + + #include ++#include ++#include + #include + #include + #include +@@ -29,7 +31,7 @@ + #include + + int +-__get_nprocs (void) ++__get_nprocs_sched (void) + { + enum + { +@@ -52,14 +54,141 @@ __get_nprocs (void) + atomics are needed). */ + return 2; + } +-libc_hidden_def (__get_nprocs) +-weak_alias (__get_nprocs, get_nprocs) ++ ++static char * ++next_line (int fd, char *const buffer, char **cp, char **re, ++ char *const buffer_end) ++{ ++ char *res = *cp; ++ char *nl = memchr (*cp, '\n', *re - *cp); ++ if (nl == NULL) ++ { ++ if (*cp != buffer) ++ { ++ if (*re == buffer_end) ++ { ++ memmove (buffer, *cp, *re - *cp); ++ *re = buffer + (*re - *cp); ++ *cp = buffer; ++ ++ ssize_t n = __read_nocancel (fd, *re, buffer_end - *re); ++ if (n < 0) ++ return NULL; ++ ++ *re += n; ++ ++ nl = memchr (*cp, '\n', *re - *cp); ++ while (nl == NULL && *re == buffer_end) ++ { ++ /* Truncate too long lines. */ ++ *re = buffer + 3 * (buffer_end - buffer) / 4; ++ n = __read_nocancel (fd, *re, buffer_end - *re); ++ if (n < 0) ++ return NULL; ++ ++ nl = memchr (*re, '\n', n); ++ **re = '\n'; ++ *re += n; ++ } ++ } ++ else ++ nl = memchr (*cp, '\n', *re - *cp); ++ ++ res = *cp; ++ } ++ ++ if (nl == NULL) ++ nl = *re - 1; ++ } ++ ++ *cp = nl + 1; ++ assert (*cp <= *re); ++ ++ return res == *re ? NULL : res; ++} ++ + + int +-__get_nprocs_sched (void) ++__get_nprocs (void) + { +- return __get_nprocs (); ++ enum { buffer_size = 1024 }; ++ char buffer[buffer_size]; ++ char *buffer_end = buffer + buffer_size; ++ char *cp = buffer_end; ++ char *re = buffer_end; ++ ++ const int flags = O_RDONLY | O_CLOEXEC; ++ /* This file contains comma-separated ranges. */ ++ int fd = __open_nocancel ("/sys/devices/system/cpu/online", flags); ++ char *l; ++ int result = 0; ++ if (fd != -1) ++ { ++ l = next_line (fd, buffer, &cp, &re, buffer_end); ++ if (l != NULL) ++ do ++ { ++ char *endp; ++ unsigned long int n = strtoul (l, &endp, 10); ++ if (l == endp) ++ { ++ result = 0; ++ break; ++ } ++ ++ unsigned long int m = n; ++ if (*endp == '-') ++ { ++ l = endp + 1; ++ m = strtoul (l, &endp, 10); ++ if (l == endp) ++ { ++ result = 0; ++ break; ++ } ++ } ++ ++ result += m - n + 1; ++ ++ l = endp; ++ if (l < re && *l == ',') ++ ++l; ++ } ++ while (l < re && *l != '\n'); ++ ++ __close_nocancel_nostatus (fd); ++ ++ if (result > 0) ++ return result; ++ } ++ ++ cp = buffer_end; ++ re = buffer_end; ++ ++ /* Default to an SMP system in case we cannot obtain an accurate ++ number. */ ++ result = 2; ++ ++ fd = __open_nocancel ("/proc/stat", flags); ++ if (fd != -1) ++ { ++ result = 0; ++ ++ while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) ++ /* The current format of /proc/stat has all the cpu* entries ++ at the front. We assume here that stays this way. */ ++ if (strncmp (l, "cpu", 3) != 0) ++ break; ++ else if (isdigit (l[3])) ++ ++result; ++ ++ __close_nocancel_nostatus (fd); ++ } ++ ++ return result; + } ++libc_hidden_def (__get_nprocs) ++weak_alias (__get_nprocs, get_nprocs) + + + /* On some architectures it is possible to distinguish between configured +-- +1.8.3.1 + diff --git a/linux-Simplify-get_nprocs.patch b/linux-Simplify-get_nprocs.patch new file mode 100644 index 0000000..55c49b2 --- /dev/null +++ b/linux-Simplify-get_nprocs.patch @@ -0,0 +1,216 @@ +From cda99af14e82b4bb6abaecd717ebe3b57c0aa534 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 6 Sep 2021 12:28:24 -0300 +Subject: [PATCH] linux: Simplify get_nprocs + +This patch simplifies the memory allocation code and uses the sched +routines instead of reimplement it. This still uses a stack +allocation buffer, so it can be used on malloc initialization code. + +Linux currently supports at maximum of 4096 cpus for most architectures: + +$ find -iname Kconfig | xargs git grep -A10 -w NR_CPUS | grep -w range +arch/alpha/Kconfig- range 2 32 +arch/arc/Kconfig- range 2 4096 +arch/arm/Kconfig- range 2 16 if DEBUG_KMAP_LOCAL +arch/arm/Kconfig- range 2 32 if !DEBUG_KMAP_LOCAL +arch/arm64/Kconfig- range 2 4096 +arch/csky/Kconfig- range 2 32 +arch/hexagon/Kconfig- range 2 6 if SMP +arch/ia64/Kconfig- range 2 4096 +arch/mips/Kconfig- range 2 256 +arch/openrisc/Kconfig- range 2 32 +arch/parisc/Kconfig- range 2 32 +arch/riscv/Kconfig- range 2 32 +arch/s390/Kconfig- range 2 512 +arch/sh/Kconfig- range 2 32 +arch/sparc/Kconfig- range 2 32 if SPARC32 +arch/sparc/Kconfig- range 2 4096 if SPARC64 +arch/um/Kconfig- range 1 1 +arch/x86/Kconfig-# [NR_CPUS_RANGE_BEGIN ... NR_CPUS_RANGE_END] range. +arch/x86/Kconfig- range NR_CPUS_RANGE_BEGIN NR_CPUS_RANGE_END +arch/xtensa/Kconfig- range 2 32 + +With x86 supporting 8192: + +arch/x86/Kconfig + 976 config NR_CPUS_RANGE_END + 977 int + 978 depends on X86_64 + 979 default 8192 if SMP && CPUMASK_OFFSTACK + 980 default 512 if SMP && !CPUMASK_OFFSTACK + 981 default 1 if !SMP + +So using a maximum of 32k cpu should cover all cases (and I would +expect once we start to have many more CPUs that Linux would provide +a more straightforward way to query for such information). + +A test is added to check if sched_getaffinity can successfully return +with large buffers. + +Checked on x86_64-linux-gnu and i686-linux-gnu. + +Reviewed-by: Florian Weimer +(cherry picked from commit 33099d72e41cf8a129b362e9709eb2be9372d844) +--- + posix/Makefile | 3 +- + posix/tst-sched_getaffinity.c | 48 +++++++++++++++++++++++++ + sysdeps/unix/sysv/linux/getsysstats.c | 68 ++++++++++------------------------- + 3 files changed, 68 insertions(+), 51 deletions(-) + create mode 100644 posix/tst-sched_getaffinity.c + +diff --git a/posix/Makefile b/posix/Makefile +index 059efb3..09460a2 100644 +--- a/posix/Makefile ++++ b/posix/Makefile +@@ -107,7 +107,8 @@ tests := test-errno tstgetopt testfnm runtests runptests \ + tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \ + tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \ + bug-regex38 tst-regcomp-truncated tst-spawn-chdir \ +- tst-wordexp-nocmd tst-execveat tst-spawn5 ++ tst-wordexp-nocmd tst-execveat tst-spawn5 \ ++ tst-sched_getaffinity + + # Test for the glob symbol version that was replaced in glibc 2.27. + ifeq ($(have-GLIBC_2.26)$(build-shared),yesyes) +diff --git a/posix/tst-sched_getaffinity.c b/posix/tst-sched_getaffinity.c +new file mode 100644 +index 0000000..db9d517 +--- /dev/null ++++ b/posix/tst-sched_getaffinity.c +@@ -0,0 +1,48 @@ ++/* Tests for sched_getaffinity with large buffers. ++ Copyright (C) 2021 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 ++ ++/* NB: this test may fail on system with more than 32k cpus. */ ++ ++static int ++do_test (void) ++{ ++ /* The values are larger than the default cpu_set_t. */ ++ const int bufsize[] = { 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, 1<<16, 1<<17 }; ++ int cpucount[array_length (bufsize)]; ++ ++ for (int i = 0; i < array_length (bufsize); i++) ++ { ++ cpu_set_t *cpuset = CPU_ALLOC (bufsize[i]); ++ TEST_VERIFY (cpuset != NULL); ++ size_t size = CPU_ALLOC_SIZE (bufsize[i]); ++ TEST_COMPARE (sched_getaffinity (0, size, cpuset), 0); ++ cpucount[i] = CPU_COUNT_S (size, cpuset); ++ CPU_FREE (cpuset); ++ } ++ ++ for (int i = 0; i < array_length (cpucount) - 1; i++) ++ TEST_COMPARE (cpucount[i], cpucount[i + 1]); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c +index 120ce1b..61d20e7 100644 +--- a/sysdeps/unix/sysv/linux/getsysstats.c ++++ b/sysdeps/unix/sysv/linux/getsysstats.c +@@ -29,61 +29,29 @@ + #include + #include + +-/* Compute the population count of the entire array. */ +-static int +-__get_nprocs_count (const unsigned long int *array, size_t length) +-{ +- int count = 0; +- for (size_t i = 0; i < length; ++i) +- if (__builtin_add_overflow (count, __builtin_popcountl (array[i]), +- &count)) +- return INT_MAX; +- return count; +-} +- +-/* __get_nprocs with a large buffer. */ +-static int +-__get_nprocs_large (void) +-{ +- /* This code cannot use scratch_buffer because it is used during +- malloc initialization. */ +- size_t pagesize = GLRO (dl_pagesize); +- unsigned long int *page = __mmap (0, pagesize, PROT_READ | PROT_WRITE, +- MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); +- if (page == MAP_FAILED) +- return 2; +- int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, pagesize, page); +- int count; +- if (r > 0) +- count = __get_nprocs_count (page, pagesize / sizeof (unsigned long int)); +- else if (r == -EINVAL) +- /* One page is still not enough to store the bits. A more-or-less +- arbitrary value. This assumes t hat such large systems never +- happen in practice. */ +- count = GLRO (dl_pagesize) * CHAR_BIT; +- else +- count = 2; +- __munmap (page, GLRO (dl_pagesize)); +- return count; +-} +- + int + __get_nprocs (void) + { +- /* Fast path for most systems. The kernel expects a buffer size +- that is a multiple of 8. */ +- unsigned long int small_buffer[1024 / CHAR_BIT / sizeof (unsigned long int)]; +- int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, +- sizeof (small_buffer), small_buffer); ++ enum ++ { ++ max_num_cpus = 32768, ++ cpu_bits_size = CPU_ALLOC_SIZE (32768) ++ }; ++ ++ /* This cannot use malloc because it is used on malloc initialization. */ ++ __cpu_mask cpu_bits[cpu_bits_size / sizeof (__cpu_mask)]; ++ int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size, ++ cpu_bits); + if (r > 0) +- return __get_nprocs_count (small_buffer, r / sizeof (unsigned long int)); ++ return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits); + else if (r == -EINVAL) +- /* The kernel requests a larger buffer to store the data. */ +- return __get_nprocs_large (); +- else +- /* Some other error. 2 is conservative (not a uniprocessor +- system, so atomics are needed). */ +- return 2; ++ /* The input buffer is still not enough to store the number of cpus. This ++ is an arbitrary values assuming such systems should be rare and there ++ is no offline cpus. */ ++ return max_num_cpus; ++ /* Some other error. 2 is conservative (not a uniprocessor system, so ++ atomics are needed). */ ++ return 2; + } + libc_hidden_def (__get_nprocs) + weak_alias (__get_nprocs, get_nprocs) +-- +1.8.3.1 + diff --git a/misc-Add-__get_nprocs_sched.patch b/misc-Add-__get_nprocs_sched.patch new file mode 100644 index 0000000..68e1208 --- /dev/null +++ b/misc-Add-__get_nprocs_sched.patch @@ -0,0 +1,110 @@ +From e870aac8974cda746157a5a3c9f452ccd70da29b Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 6 Sep 2021 12:22:54 -0300 +Subject: [PATCH] misc: Add __get_nprocs_sched + +This is an internal function meant to return the number of avaliable +processor where the process can scheduled, different than the +__get_nprocs which returns a the system available online CPU. + +The Linux implementation currently only calls __get_nprocs(), which +in tuns calls sched_getaffinity. + +Reviewed-by: Florian Weimer +(cherry picked from commit 11a02b035b464ab6813676adfd19c4a59c36d907) +--- + include/sys/sysinfo.h | 7 ++++++- + malloc/arena.c | 2 +- + misc/getsysstats.c | 6 ++++++ + sysdeps/mach/getsysstats.c | 6 ++++++ + sysdeps/unix/sysv/linux/getsysstats.c | 6 ++++++ + 5 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/include/sys/sysinfo.h b/include/sys/sysinfo.h +index 7388356..c490561 100644 +--- a/include/sys/sysinfo.h ++++ b/include/sys/sysinfo.h +@@ -9,10 +9,15 @@ + extern int __get_nprocs_conf (void); + libc_hidden_proto (__get_nprocs_conf) + +-/* Return number of available processors. */ ++/* Return number of available processors (not all of them will be ++ available to the caller process). */ + extern int __get_nprocs (void); + libc_hidden_proto (__get_nprocs) + ++/* Return the number of available processors which the process can ++ be scheduled. */ ++extern int __get_nprocs_sched (void) attribute_hidden; ++ + /* Return number of physical pages of memory in the system. */ + extern long int __get_phys_pages (void); + libc_hidden_proto (__get_phys_pages) +diff --git a/malloc/arena.c b/malloc/arena.c +index 6674846..f1f0af8 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -879,7 +879,7 @@ arena_get2 (size_t size, mstate avoid_arena) + narenas_limit = mp_.arena_max; + else if (narenas > mp_.arena_test) + { +- int n = __get_nprocs (); ++ int n = __get_nprocs_sched (); + + if (n >= 1) + narenas_limit = NARENAS_FROM_NCORES (n); +diff --git a/misc/getsysstats.c b/misc/getsysstats.c +index 0eedfac..57d9360 100644 +--- a/misc/getsysstats.c ++++ b/misc/getsysstats.c +@@ -45,6 +45,12 @@ weak_alias (__get_nprocs, get_nprocs) + link_warning (get_nprocs, "warning: get_nprocs will always return 1") + + ++int ++__get_nprocs_sched (void) ++{ ++ return 1; ++} ++ + long int + __get_phys_pages (void) + { +diff --git a/sysdeps/mach/getsysstats.c b/sysdeps/mach/getsysstats.c +index 1267f39..cc8023f 100644 +--- a/sysdeps/mach/getsysstats.c ++++ b/sysdeps/mach/getsysstats.c +@@ -62,6 +62,12 @@ __get_nprocs (void) + libc_hidden_def (__get_nprocs) + weak_alias (__get_nprocs, get_nprocs) + ++int ++__get_nprocs_sched (void) ++{ ++ return __get_nprocs (); ++} ++ + /* Return the number of physical pages on the system. */ + long int + __get_phys_pages (void) +diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c +index 1391e36..120ce1b 100644 +--- a/sysdeps/unix/sysv/linux/getsysstats.c ++++ b/sysdeps/unix/sysv/linux/getsysstats.c +@@ -88,6 +88,12 @@ __get_nprocs (void) + libc_hidden_def (__get_nprocs) + weak_alias (__get_nprocs, get_nprocs) + ++int ++__get_nprocs_sched (void) ++{ ++ return __get_nprocs (); ++} ++ + + /* On some architectures it is possible to distinguish between configured + and active cpus. */ +-- +1.8.3.1 + -- Gitee From f573e88f9482e6ee9347c713c859ca24b7b3cc24 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Fri, 3 Dec 2021 11:13:07 +0800 Subject: [PATCH 29/70] turn the default value of x86_rep_stosb_threshold from 2k to 1M Signed-off-by: Yang Yanchao (cherry picked from commit 6495a142f4b026f769f6162f18be549ede7a1476) --- glibc.spec | 7 ++- turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch | 45 ------------------- ...86_rep_stosb_threshold_form_2K_to_1M.patch | 29 ++++++++++++ 3 files changed, 34 insertions(+), 47 deletions(-) delete mode 100644 turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch create mode 100644 turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch diff --git a/glibc.spec b/glibc.spec index 4c8bcda..e9115f9 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 29 +Release: 30 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -138,7 +138,7 @@ Patch51: linux-Simplify-get_nprocs.patch Patch52: misc-Add-__get_nprocs_sched.patch Patch53: linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch -#Patch9000: turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch +Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch Patch9002: 0001-add-base-files-for-libphtread-condition-family.patch Patch9003: 0002-add-header-files-for-libphtread_2_17_so.patch @@ -1334,6 +1334,9 @@ fi %endif %changelog +* Thu Dec 3 2021 Yang Yanchao - 2.34-30 +- turn the default value of x86_rep_stosb_threshold from 2k to 1M + * Thu Dec 2 2021 Qingqing Li - 2.34-29 - revert the use of sched_getaffinity [BZ #28310] diff --git a/turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch b/turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch deleted file mode 100644 index 17bebd3..0000000 --- a/turn-REP_STOSB_THRESHOLD-from-2k-to-1M.patch +++ /dev/null @@ -1,45 +0,0 @@ -From dc8c5d3ba8ec3c2de8ca0898d682d89492d275b3 Mon Sep 17 00:00:00 2001 -From: Shuo Wang -Date: Tue, 2 Mar 2021 10:41:09 +0800 -Subject: [PATCH] turn REP_STOSB_THRESHOLD from 2k to 1M - -REP_STOSB_THRESHOLD is designed to choose vec mov or stosb. -The default threshold (2k) will lead to performance degradation if the -memcpy size is between 2k and 1M. ---- - sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S | 12 +++++++++++- - 1 file changed, 11 insertions(+), 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 faa40856..76f84748 100644 ---- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S -+++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S -@@ -58,6 +58,16 @@ - # endif - #endif - -+/* Threshold to use Enhanced REP STOSB. Since there is overhead to set -+ up REP STOSB operation, REP STOSB isn't faster on short data. The -+ memset micro benchmark in glibc shows that 2KB is the approximate -+ value above which REP STOSB becomes faster on processors with -+ 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 1048576 -+#endif -+ - #ifndef SECTION - # error SECTION is not defined! - #endif -@@ -171,7 +181,7 @@ ENTRY (MEMSET_SYMBOL (__memset, unaligned_erms)) - ret - - L(stosb_more_2x_vec): -- cmp __x86_rep_stosb_threshold(%rip), %RDX_LP -+ cmp $REP_STOSB_THRESHOLD, %RDX_LP - ja L(stosb) - #endif - L(more_2x_vec): --- -2.23.0 - diff --git a/turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch b/turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch new file mode 100644 index 0000000..e9e053d --- /dev/null +++ b/turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch @@ -0,0 +1,29 @@ +From 4dee2794b8c78ccd540e3f72bc07585828e0143b Mon Sep 17 00:00:00 2001 +From: Yang Yanchao +Date: Thu, 2 Dec 2021 19:56:20 +0800 +Subject: [PATCH] turn the default value of x86_rep_stosb_threshold from 2k to 1M + +x86_rep_stosb_threshold is designed to choose vec mov or stosb. +For the libMicro, after set this x86_rep_stosb_threshold to 1 MB. +The performance of memset_256_u, memset_4k_uc, and memset_1m is improved. +The performance deteriorates in the memset_4k and memset_10k scenarios. +--- + sysdeps/x86/dl-tunables.list | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list +index dd6e1d65..a4c3af69 100644 +--- a/sysdeps/x86/dl-tunables.list ++++ b/sysdeps/x86/dl-tunables.list +@@ -54,7 +54,7 @@ glibc { + # stored value is fixed, larger register size has minimal impact + # on threshold. + minval: 1 +- default: 2048 ++ default: 1048576 + } + x86_data_cache_size { + type: SIZE_T +-- +2.30.0 + -- Gitee From 6e7a05a84483b63ccb5767f7832b799c092f542d Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Thu, 9 Dec 2021 16:43:24 +0800 Subject: [PATCH 30/70] support all Chinese and English by default add zh_* and en_* to glibc-common the size of glibc-common is increased from 1.8MB to 3.5MB Signed-off-by: Yang Yanchao (cherry picked from commit f5e24fbbc91f5674b85d32b2f71148638bc7c920) --- glibc.spec | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/glibc.spec b/glibc.spec index e9115f9..e0f150d 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 30 +Release: 31 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -1253,20 +1253,20 @@ fi %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}/lib/locale/zh* +%{_prefix}/lib/locale/en* +%{_prefix}/share/locale/zh* +%{_prefix}/share/locale/en* %files -f libc.lang all-langpacks %{_prefix}/lib/locale %exclude %{_prefix}/lib/locale/locale-archive %exclude %{_prefix}/lib/locale/locale-archive.update %exclude %{_prefix}/lib/locale/C.utf8 -%exclude %{_prefix}/lib/locale/zh_CN.utf8 -%exclude %{_prefix}/lib/locale/en_US.utf8 -%exclude %{_prefix}/share/locale/zh_CN -%exclude %{_prefix}/share/locale/en_GB +%exclude %{_prefix}/lib/locale/zh* +%exclude %{_prefix}/lib/locale/en* +%exclude %{_prefix}/share/locale/zh* +%exclude %{_prefix}/share/locale/en* %files locale-source %dir %{_prefix}/share/i18n/locales @@ -1334,7 +1334,12 @@ fi %endif %changelog -* Thu Dec 3 2021 Yang Yanchao - 2.34-30 +* Thu Dec 9 2021 Yang Yanchao - 2.34-31 +- support all Chinese and English by default + add zh_* and en_* to glibc-common + the size of glibc-common is increased from 1.8MB to 3.5MB + +* Fri Dec 3 2021 Yang Yanchao - 2.34-30 - turn the default value of x86_rep_stosb_threshold from 2k to 1M * Thu Dec 2 2021 Qingqing Li - 2.34-29 -- Gitee From 3369b7a7b28db02d42ca87fd03602f4f81615598 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Thu, 9 Dec 2021 21:14:02 +0800 Subject: [PATCH 31/70] Deleted some unnecessary command when make master.filelist Signed-off-by: Yang Yanchao (cherry picked from commit 91e26f23d233769007ccca102b720697dc69ecf9) --- glibc.spec | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/glibc.spec b/glibc.spec index e0f150d..d4236c7 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 31 +Release: 32 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -775,7 +775,7 @@ touch compat-2.17.filelist -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 '\,.*%{_libdir}/lib\(pcprofile\|memusage\)\.so,d' \ %if %{with compat_2_17} -e '\,.*%{_libdir}/libpthread-2.17.so,d' \ %endif @@ -813,7 +813,9 @@ for module in compat files dns; do -e "/libnss_$module(\.so\.[0-9.]+|-[0-9.]+\.so)$" \ >> glibc.filelist done -grep -e "libmemusage.so" -e "libpcprofile.so" master.filelist >> glibc.filelist + +echo '%{_libdir}/libmemusage.so' >> glibc.filelist +echo '%{_libdir}/libpcprofile.so' >> glibc.filelist ############################################################################## # glibc "common" sub-package @@ -844,10 +846,7 @@ grep '%{_libdir}/lib.*\.a' master.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 +sed -i -e '\,/libnss_[a-z]*\.so$,d' devel.filelist grep '%{_prefix}/include' < master.filelist >> devel.filelist @@ -1334,6 +1333,9 @@ fi %endif %changelog +* Thu Dec 9 2021 Yang Yanchao - 2.34-32 +- Deleted some unnecessary command when make master.filelist + * Thu Dec 9 2021 Yang Yanchao - 2.34-31 - support all Chinese and English by default add zh_* and en_* to glibc-common -- Gitee From d2217b5497322c42abe9c4e480a3aa82876e5e82 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Wed, 15 Dec 2021 19:33:12 +0800 Subject: [PATCH 32/70] pthread/tst-cancel28: Fix barrier re-init race condition (cherry picked from commit 4405c4286873be3f9f04f742112af22caf8839bb) --- glibc.spec | 6 ++- ...el28-Fix-barrier-re-init-race-condit.patch | 41 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch diff --git a/glibc.spec b/glibc.spec index d4236c7..ad8575a 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 32 +Release: 33 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -137,6 +137,7 @@ Patch50: Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch Patch51: linux-Simplify-get_nprocs.patch Patch52: misc-Add-__get_nprocs_sched.patch Patch53: linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch +Patch54: pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1333,6 +1334,9 @@ fi %endif %changelog +* Wed Dec 15 2021 Qingqing Li - 2.34-33 +- pthread/tst-cancel28: Fix barrier re-init race condition + * Thu Dec 9 2021 Yang Yanchao - 2.34-32 - Deleted some unnecessary command when make master.filelist diff --git a/pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch b/pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch new file mode 100644 index 0000000..2088212 --- /dev/null +++ b/pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch @@ -0,0 +1,41 @@ +From 9874ca536b1d0662b1cea46af3ce09a4d42aeb32 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sat, 25 Sep 2021 17:02:06 +0900 +Subject: [PATCH] pthread/tst-cancel28: Fix barrier re-init race condition + +When running this test on the OpenRISC port I am working on this test +fails with a timeout. The test passes when being straced or debugged. +Looking at the code there seems to be a race condition in that: + + 1 main thread: calls xpthread_cancel + 2 sub thread : receives cancel signal + 3 sub thread : cleanup routine waits on barrier + 4 main thread: re-inits barrier + 5 main thread: waits on barrier + +After getting to 5 the main thread and sub thread wait forever as the 2 +barriers are no longer the same. + +Removing the barrier re-init seems to fix this issue. Also, the barrier +does not need to be reinitialized as that is done by default. + +Reviewed-by: Adhemerval Zanella +--- + sysdeps/pthread/tst-cancel28.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/sysdeps/pthread/tst-cancel28.c b/sysdeps/pthread/tst-cancel28.c +index 627cbc8..9286c15 100644 +--- a/sysdeps/pthread/tst-cancel28.c ++++ b/sysdeps/pthread/tst-cancel28.c +@@ -69,7 +69,6 @@ do_test (void) + + xpthread_cancel (timer_thread); + +- xpthread_barrier_init (&barrier, NULL, 2); + xpthread_barrier_wait (&barrier); + + return 0; +-- +1.8.3.1 + -- Gitee From 2517d33b7f71f6582ff024f6159250b884a293be Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Tue, 21 Dec 2021 10:00:35 +0800 Subject: [PATCH 33/70] fix glibc upstream bug BZ#28260 and nss/tst-nss-files-hosts-long and nptl/tst-create1 (cherry picked from commit c66918bc6053415d346a3b7f94553a73ba1df236) --- ...tst-nss-files-hosts-long-with-local-.patch | 37 ++ ..._dev_null_range-io-tst-closefrom-mis.patch | 212 ++++++++++ glibc.spec | 11 +- ...one-more-barrier-to-nptl-tst-create1.patch | 67 ++++ support-Add-support_open_dev_null_range.patch | 363 ++++++++++++++++++ 5 files changed, 689 insertions(+), 1 deletion(-) create mode 100644 Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch create mode 100644 Use-support_open_dev_null_range-io-tst-closefrom-mis.patch create mode 100644 nptl-Add-one-more-barrier-to-nptl-tst-create1.patch create mode 100644 support-Add-support_open_dev_null_range.patch diff --git a/Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch b/Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch new file mode 100644 index 0000000..f9cb581 --- /dev/null +++ b/Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch @@ -0,0 +1,37 @@ +From ae925404a10bf0ea63d6e8d41e3821f68b4d776c Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Fri, 3 Sep 2021 00:28:14 +0200 +Subject: [PATCH] Fix failing nss/tst-nss-files-hosts-long with local resolver + +When a local resolver like unbound is listening on the IPv4 loopback +address 127.0.0.1, the nss/tst-nss-files-hosts-long test fails. This is +due to: +- the default resolver in the absence of resolv.conf being 127.0.0.1 +- the default DNS NSS database configuration in the absence of + nsswitch.conf being 'hosts: dns [!UNAVAIL=return] file' + +This causes the requests for 'test4' and 'test6' to first be sent to the +local resolver, which responds with NXDOMAIN in the likely case those +records do no exist. In turn that causes the access to /etc/hosts to be +skipped, which is the purpose of that test. + +Fix that by providing a simple nsswitch.conf file forcing access to +/etc/hosts for that test. I have tested that the only changed result in +the testsuite is that test. + +(cherry picked from commit 2738480a4b0866723fb8c633f36bdd34a8767581) +--- + nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf + +diff --git a/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf b/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf +new file mode 100644 +index 0000000..5b0c6a4 +--- /dev/null ++++ b/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf +@@ -0,0 +1 @@ ++hosts: files +-- +1.8.3.1 + diff --git a/Use-support_open_dev_null_range-io-tst-closefrom-mis.patch b/Use-support_open_dev_null_range-io-tst-closefrom-mis.patch new file mode 100644 index 0000000..bd7da16 --- /dev/null +++ b/Use-support_open_dev_null_range-io-tst-closefrom-mis.patch @@ -0,0 +1,212 @@ +From 772e33411bc730f832f415f93eb3e7c67e4d5488 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 24 Aug 2021 16:15:50 -0300 +Subject: [PATCH] Use support_open_dev_null_range io/tst-closefrom, + misc/tst-close_range, and posix/tst-spawn5 (BZ #28260) + +It ensures a continuous range of file descriptor and avoid hitting +the RLIMIT_NOFILE. + +Checked on x86_64-linux-gnu. + +(cherry picked from commit 6b20880b22d1d0fce7e9f506baa6fe2d5c7fcfdc) +--- + io/tst-closefrom.c | 21 ++++++--------------- + posix/tst-spawn5.c | 13 +------------ + sysdeps/unix/sysv/linux/tst-close_range.c | 31 ++++++++++--------------------- + 3 files changed, 17 insertions(+), 48 deletions(-) + +diff --git a/io/tst-closefrom.c b/io/tst-closefrom.c +index d4c1870..395ec0d 100644 +--- a/io/tst-closefrom.c ++++ b/io/tst-closefrom.c +@@ -24,31 +24,22 @@ + #include + #include + #include ++#include + + #include + + #define NFDS 100 + + static int +-open_multiple_temp_files (void) +-{ +- /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); +- for (int i = 1; i <= NFDS; i++) +- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), lowfd + i); +- return lowfd; +-} +- +-static int + closefrom_test (void) + { + struct support_descriptors *descrs = support_descriptors_list (); + +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + +- const int maximum_fd = lowfd + NFDS; ++ const int maximum_fd = lowfd + NFDS - 1; + const int half_fd = lowfd + NFDS / 2; +- const int gap = maximum_fd / 4; ++ const int gap = lowfd + NFDS / 4; + + /* Close half of the descriptors and check result. */ + closefrom (half_fd); +@@ -58,7 +49,7 @@ closefrom_test (void) + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } +- for (int i = 0; i < half_fd; i++) ++ for (int i = lowfd; i < half_fd; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Create some gaps, close up to a threshold, and check result. */ +@@ -74,7 +65,7 @@ closefrom_test (void) + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } +- for (int i = 0; i < gap; i++) ++ for (int i = lowfd; i < gap; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Close the remmaining but the last one. */ +diff --git a/posix/tst-spawn5.c b/posix/tst-spawn5.c +index ac66738..a95199a 100644 +--- a/posix/tst-spawn5.c ++++ b/posix/tst-spawn5.c +@@ -48,17 +48,6 @@ static int initial_argv_count; + #define NFDS 100 + + static int +-open_multiple_temp_files (void) +-{ +- /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); +- for (int i = 1; i <= NFDS; i++) +- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), +- lowfd + i); +- return lowfd; +-} +- +-static int + parse_fd (const char *str) + { + char *endptr; +@@ -185,7 +174,7 @@ spawn_closefrom_test (posix_spawn_file_actions_t *fa, int lowfd, int highfd, + static void + do_test_closefrom (void) + { +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + const int half_fd = lowfd + NFDS / 2; + + /* Close half of the descriptors and check result. */ +diff --git a/sysdeps/unix/sysv/linux/tst-close_range.c b/sysdeps/unix/sysv/linux/tst-close_range.c +index dccb618..f5069d1 100644 +--- a/sysdeps/unix/sysv/linux/tst-close_range.c ++++ b/sysdeps/unix/sysv/linux/tst-close_range.c +@@ -36,23 +36,12 @@ + + #define NFDS 100 + +-static int +-open_multiple_temp_files (void) +-{ +- /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); +- for (int i = 1; i <= NFDS; i++) +- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), +- lowfd + i); +- return lowfd; +-} +- + static void + close_range_test_max_upper_limit (void) + { + struct support_descriptors *descrs = support_descriptors_list (); + +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + + { + int r = close_range (lowfd, ~0U, 0); +@@ -68,7 +57,7 @@ close_range_test_max_upper_limit (void) + static void + close_range_test_common (int lowfd, unsigned int flags) + { +- const int maximum_fd = lowfd + NFDS; ++ const int maximum_fd = lowfd + NFDS - 1; + const int half_fd = lowfd + NFDS / 2; + const int gap_1 = maximum_fd - 8; + +@@ -121,7 +110,7 @@ close_range_test (void) + struct support_descriptors *descrs = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + + close_range_test_common (lowfd, 0); + +@@ -146,7 +135,7 @@ close_range_test_subprocess (void) + struct support_descriptors *descrs = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + + struct support_stack stack = support_stack_alloc (4096); + +@@ -184,7 +173,7 @@ close_range_unshare_test (void) + struct support_descriptors *descrs1 = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + + struct support_descriptors *descrs2 = support_descriptors_list (); + +@@ -200,7 +189,7 @@ close_range_unshare_test (void) + + support_stack_free (&stack); + +- for (int i = 0; i < NFDS; i++) ++ for (int i = lowfd; i < lowfd + NFDS; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + support_descriptors_check (descrs2); +@@ -226,9 +215,9 @@ static void + close_range_cloexec_test (void) + { + /* Check if the temporary file descriptor has no no gaps. */ +- const int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + +- const int maximum_fd = lowfd + NFDS; ++ const int maximum_fd = lowfd + NFDS - 1; + const int half_fd = lowfd + NFDS / 2; + const int gap_1 = maximum_fd - 8; + +@@ -251,13 +240,13 @@ close_range_cloexec_test (void) + /* Create some gaps, close up to a threshold, and check result. */ + static int gap_close[] = { 57, 78, 81, 82, 84, 90 }; + for (int i = 0; i < array_length (gap_close); i++) +- xclose (gap_close[i]); ++ xclose (lowfd + gap_close[i]); + + TEST_COMPARE (close_range (half_fd + 1, gap_1, CLOSE_RANGE_CLOEXEC), 0); + for (int i = half_fd + 1; i < gap_1; i++) + { + int flags = fcntl (i, F_GETFD); +- if (is_in_array (gap_close, array_length (gap_close), i)) ++ if (is_in_array (gap_close, array_length (gap_close), i - lowfd)) + TEST_COMPARE (flags, -1); + else + { +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index ad8575a..ee69464 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 33 +Release: 34 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -138,6 +138,10 @@ Patch51: linux-Simplify-get_nprocs.patch Patch52: misc-Add-__get_nprocs_sched.patch Patch53: linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch Patch54: pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch +Patch55: support-Add-support_open_dev_null_range.patch +Patch56: Use-support_open_dev_null_range-io-tst-closefrom-mis.patch +Patch57: Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch +Patch58: nptl-Add-one-more-barrier-to-nptl-tst-create1.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1334,6 +1338,11 @@ fi %endif %changelog +* Tue Dec 21 2021 Qingqing Li - 2.34-34 +- tst: fix failing nss/tst-nss-files-hosts-long with local resolver + use support_open_dev_null_range io/tst-closefrom, mise/tst-close_range, and posix/tst-spawn5(BZ#28260) + nptl: add one more barrier to nptl/tst-create1 + * Wed Dec 15 2021 Qingqing Li - 2.34-33 - pthread/tst-cancel28: Fix barrier re-init race condition diff --git a/nptl-Add-one-more-barrier-to-nptl-tst-create1.patch b/nptl-Add-one-more-barrier-to-nptl-tst-create1.patch new file mode 100644 index 0000000..e18a8bc --- /dev/null +++ b/nptl-Add-one-more-barrier-to-nptl-tst-create1.patch @@ -0,0 +1,67 @@ +From 5cc338565479a620244c2f8ff35956629c4dbf81 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 10 Dec 2021 05:14:24 +0100 +Subject: [PATCH] nptl: Add one more barrier to nptl/tst-create1 + +Without the bar_ctor_finish barrier, it was possible that thread2 +re-locked user_lock before ctor had a chance to lock it. ctor then +blocked in its locking operation, xdlopen from the main thread +did not return, and thread2 was stuck waiting in bar_dtor: + +thread 1: started. +thread 2: started. +thread 2: locked user_lock. +constructor started: 0. +thread 1: in ctor: started. +thread 3: started. +thread 3: done. +thread 2: unlocked user_lock. +thread 2: locked user_lock. + +Fixes the test in commit 83b5323261bb72313bffcf37476c1b8f0847c736 +("elf: Avoid deadlock between pthread_create and ctors [BZ #28357]"). + +Reviewed-by: Szabolcs Nagy +--- + sysdeps/pthread/tst-create1.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c +index 932586c..763ded8 100644 +--- a/sysdeps/pthread/tst-create1.c ++++ b/sysdeps/pthread/tst-create1.c +@@ -33,6 +33,7 @@ thread 2: lock(user_lock) -> pthread_create + */ + + static pthread_barrier_t bar_ctor; ++static pthread_barrier_t bar_ctor_finish; + static pthread_barrier_t bar_dtor; + static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER; + +@@ -46,6 +47,7 @@ ctor (void) + xpthread_mutex_unlock (&user_lock); + dprintf (1, "thread 1: in ctor: unlocked user_lock.\n"); + dprintf (1, "thread 1: in ctor: done.\n"); ++ xpthread_barrier_wait (&bar_ctor_finish); + } + + void +@@ -81,6 +83,7 @@ thread2 (void *a) + xpthread_mutex_unlock (&user_lock); + dprintf (1, "thread 2: unlocked user_lock.\n"); + xpthread_join (t3); ++ xpthread_barrier_wait (&bar_ctor_finish); + + xpthread_mutex_lock (&user_lock); + dprintf (1, "thread 2: locked user_lock.\n"); +@@ -99,6 +102,7 @@ thread1 (void) + { + dprintf (1, "thread 1: started.\n"); + xpthread_barrier_init (&bar_ctor, NULL, 2); ++ xpthread_barrier_init (&bar_ctor_finish, NULL, 2); + xpthread_barrier_init (&bar_dtor, NULL, 2); + pthread_t t2 = xpthread_create (0, thread2, 0); + void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL); +-- +1.8.3.1 + diff --git a/support-Add-support_open_dev_null_range.patch b/support-Add-support_open_dev_null_range.patch new file mode 100644 index 0000000..0b78f8c --- /dev/null +++ b/support-Add-support_open_dev_null_range.patch @@ -0,0 +1,363 @@ +From e814f4b04ee413a7bb3dfa43e74c8fb4abf58359 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 24 Aug 2021 16:12:24 -0300 +Subject: [PATCH] support: Add support_open_dev_null_range + +It returns a range of file descriptor referring to the '/dev/null' +pathname. The function takes care of restarting the open range +if a file descriptor is found within the specified range and +also increases RLIMIT_NOFILE if required. + +Checked on x86_64-linux-gnu. +--- + support/Makefile | 2 + + support/support-open-dev-null-range.c | 134 ++++++++++++++++++++++++++ + support/support.h | 8 ++ + support/tst-support-open-dev-null-range.c | 155 ++++++++++++++++++++++++++++++ + 4 files changed, 299 insertions(+) + create mode 100644 support/support-open-dev-null-range.c + create mode 100644 support/tst-support-open-dev-null-range.c + +diff --git a/support/Makefile b/support/Makefile +index a462781..6332e7b 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -66,6 +66,7 @@ libsupport-routines = \ + support_path_support_time64 \ + support_process_state \ + support_ptrace \ ++ support-open-dev-null-range \ + support_openpty \ + support_paths \ + support_quote_blob \ +@@ -264,6 +265,7 @@ tests = \ + tst-support_capture_subprocess \ + tst-support_descriptors \ + tst-support_format_dns_packet \ ++ tst-support-open-dev-null-range \ + tst-support-process_state \ + tst-support_quote_blob \ + tst-support_quote_string \ +diff --git a/support/support-open-dev-null-range.c b/support/support-open-dev-null-range.c +new file mode 100644 +index 0000000..80d9dba +--- /dev/null ++++ b/support/support-open-dev-null-range.c +@@ -0,0 +1,134 @@ ++/* Return a range of open file descriptors. ++ Copyright (C) 2021 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 ++#include ++ ++static void ++increase_nofile (void) ++{ ++ struct rlimit rl; ++ if (getrlimit (RLIMIT_NOFILE, &rl) == -1) ++ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m"); ++ ++ rl.rlim_cur += 128; ++ ++ if (setrlimit (RLIMIT_NOFILE, &rl) == 1) ++ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m"); ++} ++ ++static int ++open_dev_null (int flags, mode_t mode) ++{ ++ int fd = open64 ("/dev/null", flags, mode); ++ if (fd > 0) ++ return fd; ++ ++ if (fd < 0 && errno != EMFILE) ++ FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode); ++ ++ increase_nofile (); ++ ++ return xopen ("/dev/null", flags, mode); ++} ++ ++struct range ++{ ++ int lowfd; ++ size_t len; ++}; ++ ++struct range_list ++{ ++ size_t total; ++ size_t used; ++ struct range *ranges; ++}; ++ ++static void ++range_init (struct range_list *r) ++{ ++ r->total = 8; ++ r->used = 0; ++ r->ranges = xmalloc (r->total * sizeof (struct range)); ++} ++ ++static void ++range_add (struct range_list *r, int lowfd, size_t len) ++{ ++ if (r->used == r->total) ++ { ++ r->total *= 2; ++ r->ranges = xrealloc (r->ranges, r->total * sizeof (struct range)); ++ } ++ r->ranges[r->used].lowfd = lowfd; ++ r->ranges[r->used].len = len; ++ r->used++; ++} ++ ++static void ++range_close (struct range_list *r) ++{ ++ for (size_t i = 0; i < r->used; i++) ++ { ++ int minfd = r->ranges[i].lowfd; ++ int maxfd = r->ranges[i].lowfd + r->ranges[i].len; ++ for (int fd = minfd; fd < maxfd; fd++) ++ xclose (fd); ++ } ++ free (r->ranges); ++} ++ ++int ++support_open_dev_null_range (int num, int flags, mode_t mode) ++{ ++ /* We keep track of the ranges that hit an already opened descriptor, so ++ we close them after we get a working range. */ ++ struct range_list rl; ++ range_init (&rl); ++ ++ int lowfd = open_dev_null (flags, mode); ++ int prevfd = lowfd; ++ while (true) ++ { ++ int i = 1; ++ for (; i < num; i++) ++ { ++ int fd = open_dev_null (flags, mode); ++ if (fd != lowfd + i) ++ { ++ range_add (&rl, lowfd, prevfd - lowfd + 1); ++ ++ prevfd = lowfd = fd; ++ break; ++ } ++ prevfd = fd; ++ } ++ if (i == num) ++ break; ++ } ++ ++ range_close (&rl); ++ ++ return lowfd; ++} +diff --git a/support/support.h b/support/support.h +index 834dba9..e6911e1 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -193,6 +193,14 @@ struct support_stack support_stack_alloc (size_t size); + /* Deallocate the STACK. */ + void support_stack_free (struct support_stack *stack); + ++ ++/* Create a range of NUM opened '/dev/null' file descriptors using FLAGS and ++ MODE. The function takes care of restarting the open range if a file ++ descriptor is found within the specified range and also increases ++ RLIMIT_NOFILE if required. ++ The returned value is the lowest file descriptor number. */ ++int support_open_dev_null_range (int num, int flags, mode_t mode); ++ + __END_DECLS + + #endif /* SUPPORT_H */ +diff --git a/support/tst-support-open-dev-null-range.c b/support/tst-support-open-dev-null-range.c +new file mode 100644 +index 0000000..8e29def +--- /dev/null ++++ b/support/tst-support-open-dev-null-range.c +@@ -0,0 +1,155 @@ ++/* Tests for support_open_dev_null_range. ++ Copyright (C) 2021 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 ++#include ++#include ++#include ++ ++#ifndef PATH_MAX ++# define PATH_MAX 1024 ++#endif ++ ++#include ++ ++static void ++check_path (int fd) ++{ ++ char *proc_fd_path = xasprintf ("/proc/self/fd/%d", fd); ++ char file_path[PATH_MAX]; ++ ssize_t file_path_length ++ = readlink (proc_fd_path, file_path, sizeof (file_path)); ++ free (proc_fd_path); ++ if (file_path_length < 0) ++ FAIL_EXIT1 ("readlink (%s, %p, %zu)", proc_fd_path, file_path, ++ sizeof (file_path)); ++ file_path[file_path_length] = '\0'; ++ TEST_COMPARE_STRING (file_path, "/dev/null"); ++} ++ ++static int ++number_of_opened_files (void) ++{ ++ DIR *fds = opendir ("/proc/self/fd"); ++ if (fds == NULL) ++ FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m"); ++ ++ int r = 0; ++ while (true) ++ { ++ errno = 0; ++ struct dirent64 *e = readdir64 (fds); ++ if (e == NULL) ++ { ++ if (errno != 0) ++ FAIL_EXIT1 ("readdir: %m"); ++ break; ++ } ++ ++ if (e->d_name[0] == '.') ++ continue; ++ ++ char *endptr; ++ long int fd = strtol (e->d_name, &endptr, 10); ++ if (*endptr != '\0' || fd < 0 || fd > INT_MAX) ++ FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s", ++ e->d_name); ++ ++ /* Skip the descriptor which is used to enumerate the ++ descriptors. */ ++ if (fd == dirfd (fds)) ++ continue; ++ ++ r = r + 1; ++ } ++ ++ closedir (fds); ++ ++ return r; ++} ++ ++static int ++do_test (void) ++{ ++ const int nfds1 = 8; ++ int lowfd = support_open_dev_null_range (nfds1, O_RDONLY, 0600); ++ for (int i = 0; i < nfds1; i++) ++ { ++ TEST_VERIFY (fcntl (lowfd + i, F_GETFL) > -1); ++ check_path (lowfd + i); ++ } ++ ++ /* create some gaps. */ ++ xclose (lowfd + 1); ++ xclose (lowfd + 5); ++ xclose (lowfd + 6); ++ ++ const int nfds2 = 16; ++ int lowfd2 = support_open_dev_null_range (nfds2, O_RDONLY, 0600); ++ for (int i = 0; i < nfds2; i++) ++ { ++ TEST_VERIFY (fcntl (lowfd2 + i, F_GETFL) > -1); ++ check_path (lowfd2 + i); ++ } ++ ++ /* Decrease the maximum number of files. */ ++ { ++ struct rlimit rl; ++ if (getrlimit (RLIMIT_NOFILE, &rl) == -1) ++ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m"); ++ ++ rl.rlim_cur = number_of_opened_files (); ++ ++ if (setrlimit (RLIMIT_NOFILE, &rl) == 1) ++ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m"); ++ } ++ ++ const int nfds3 = 16; ++ int lowfd3 = support_open_dev_null_range (nfds3, O_RDONLY, 0600); ++ for (int i = 0; i < nfds3; i++) ++ { ++ TEST_VERIFY (fcntl (lowfd3 + i, F_GETFL) > -1); ++ check_path (lowfd3 + i); ++ } ++ ++ /* create a lot of gaps to trigger the range extension. */ ++ xclose (lowfd3 + 1); ++ xclose (lowfd3 + 3); ++ xclose (lowfd3 + 5); ++ xclose (lowfd3 + 7); ++ xclose (lowfd3 + 9); ++ xclose (lowfd3 + 11); ++ xclose (lowfd3 + 13); ++ ++ const int nfds4 = 16; ++ int lowfd4 = support_open_dev_null_range (nfds4, O_RDONLY, 0600); ++ for (int i = 0; i < nfds4; i++) ++ { ++ TEST_VERIFY (fcntl (lowfd4 + i, F_GETFL) > -1); ++ check_path (lowfd4 + i); ++ } ++ ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + -- Gitee From 69524a30a5ca9255e55c0e887a0464c7e775f038 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Fri, 24 Dec 2021 15:09:14 +0800 Subject: [PATCH 34/70] io: Fix ftw internal realloc buffer (BZ #28126) (cherry picked from commit 83668a2e5d42180104021590f818d73052e4947b) --- glibc.spec | 6 +- ...ftw-internal-realloc-buffer-BZ-28126.patch | 210 ++++++++++++++++++ 2 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch diff --git a/glibc.spec b/glibc.spec index ee69464..09df504 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 34 +Release: 35 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -142,6 +142,7 @@ Patch55: support-Add-support_open_dev_null_range.patch Patch56: Use-support_open_dev_null_range-io-tst-closefrom-mis.patch Patch57: Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch Patch58: nptl-Add-one-more-barrier-to-nptl-tst-create1.patch +Patch59: io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1338,6 +1339,9 @@ fi %endif %changelog +* Fri Dec 24 2021 Qingqing Li - 2.34-35 +- io: Fix ftw internal realloc buffer (BZ #28126) + * Tue Dec 21 2021 Qingqing Li - 2.34-34 - tst: fix failing nss/tst-nss-files-hosts-long with local resolver use support_open_dev_null_range io/tst-closefrom, mise/tst-close_range, and posix/tst-spawn5(BZ#28260) diff --git a/io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch b/io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch new file mode 100644 index 0000000..09767bd --- /dev/null +++ b/io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch @@ -0,0 +1,210 @@ +From 1836bb2ebf62bd9a3588f2ed2d851c8ae810097a Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Wed, 25 Aug 2021 11:17:06 -0300 +Subject: [PATCH] io: Fix ftw internal realloc buffer (BZ #28126) + +The 106ff08526d3ca did not take in consideration the buffer might be +reallocated if the total path is larger than PATH_MAX. The realloc +uses 'dirbuf', where 'dirstreams' is the allocated buffer. + +Checked on x86_64-linux-gnu. + +Reviewed-by: H.J. Lu +--- + io/Makefile | 1 + + io/ftw.c | 39 ++++++++++----------- + io/tst-ftw-bz28126.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 117 insertions(+), 20 deletions(-) + create mode 100644 io/tst-ftw-bz28126.c + +diff --git a/io/Makefile b/io/Makefile +index 9871ecb..ecf65ab 100644 +--- a/io/Makefile ++++ b/io/Makefile +@@ -79,6 +79,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ + tst-futimens \ + tst-utimensat \ + tst-closefrom \ ++ tst-ftw-bz28126 + + tests-time64 := \ + tst-futimens-time64 \ +diff --git a/io/ftw.c b/io/ftw.c +index f0db173..fe95345 100644 +--- a/io/ftw.c ++++ b/io/ftw.c +@@ -203,6 +203,20 @@ struct ftw_data + void *known_objects; + }; + ++static bool ++ftw_allocate (struct ftw_data *data, size_t newsize) ++{ ++ void *newp = realloc (data->dirstreams, data->maxdir ++ * sizeof (struct dir_data *) ++ + newsize); ++ if (newp == NULL) ++ return false; ++ data->dirstreams = newp; ++ data->dirbufsize = newsize; ++ data->dirbuf = (char *) data->dirstreams ++ + data->maxdir * sizeof (struct dir_data *); ++ return true; ++} + + /* Internally we use the FTW_* constants used for `nftw'. When invoked + as `ftw', map each flag to the subset of values used by `ftw'. */ +@@ -388,17 +402,9 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, + return 0; + + new_buflen = data->ftw.base + namlen + 2; +- if (data->dirbufsize < new_buflen) +- { +- /* Enlarge the buffer. */ +- char *newp; +- +- data->dirbufsize = 2 * new_buflen; +- newp = (char *) realloc (data->dirbuf, data->dirbufsize); +- if (newp == NULL) +- return -1; +- data->dirbuf = newp; +- } ++ if (data->dirbufsize < new_buflen ++ && !ftw_allocate (data, 2 * new_buflen)) ++ return -1; + + *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; + +@@ -628,7 +634,7 @@ __attribute ((noinline)) + ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, + int flags) + { +- struct ftw_data data; ++ struct ftw_data data = { .dirstreams = NULL }; + struct STRUCT_STAT st; + int result = 0; + int save_err; +@@ -646,16 +652,9 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, + data.maxdir = descriptors < 1 ? 1 : descriptors; + data.actdir = 0; + /* PATH_MAX is always defined when we get here. */ +- data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX); +- data.dirstreams = malloc (data.maxdir * sizeof (struct dir_data *) +- + data.dirbufsize); +- if (data.dirstreams == NULL) ++ if (!ftw_allocate (&data, MAX (2 * strlen (dir), PATH_MAX))) + return -1; +- + memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); +- +- data.dirbuf = (char *) data.dirstreams +- + data.maxdir * sizeof (struct dir_data *); + cp = __stpcpy (data.dirbuf, dir); + /* Strip trailing slashes. */ + while (cp > data.dirbuf + 1 && cp[-1] == '/') +diff --git a/io/tst-ftw-bz28126.c b/io/tst-ftw-bz28126.c +new file mode 100644 +index 0000000..94044ab +--- /dev/null ++++ b/io/tst-ftw-bz28126.c +@@ -0,0 +1,97 @@ ++/* Check if internal buffer reallocation work for large paths (BZ #28126) ++ Copyright (C) 2021 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 ++#include ++#include ++#include ++#include ++ ++static int ++my_func (const char *file, const struct stat *sb, int flag) ++{ ++ return 0; ++} ++ ++static const char folder[NAME_MAX] = { [0 ... 253] = 'a', [254] = '\0' }; ++ ++#define NSUBFOLDERS 16 ++static int nsubfolders; ++ ++static void ++do_cleanup (void) ++{ ++ xchdir (".."); ++ for (int i = 0; i < nsubfolders; i++) ++ { ++ remove (folder); ++ xchdir (".."); ++ } ++ remove (folder); ++} ++#define CLEANUP_HANDLER do_cleanup ++ ++static void ++check_mkdir (const char *path) ++{ ++ int r = mkdir (path, 0777); ++ /* Some filesystem such as overlayfs does not support larger path required ++ to trigger the internal buffer reallocation. */ ++ if (r != 0) ++ { ++ if (errno == ENAMETOOLONG) ++ FAIL_UNSUPPORTED ("the filesystem does not support the required" ++ "large path"); ++ else ++ FAIL_EXIT1 ("mkdir (\"%s\", 0%o): %m", folder, 0777); ++ } ++} ++ ++static int ++do_test (void) ++{ ++ char *tempdir = support_create_temp_directory ("tst-bz28126"); ++ ++ /* Create path with various subfolders to force an internal buffer ++ reallocation within ntfw. */ ++ char *path = xasprintf ("%s/%s", tempdir, folder); ++ check_mkdir (path); ++ xchdir (path); ++ free (path); ++ for (int i = 0; i < NSUBFOLDERS - 1; i++) ++ { ++ check_mkdir (folder); ++ xchdir (folder); ++ nsubfolders++; ++ } ++ ++ TEST_COMPARE (ftw (tempdir, my_func, 20), 0); ++ ++ free (tempdir); ++ ++ do_cleanup (); ++ ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + -- Gitee From c8f284108918cad3639dec3a298d634aaf3ad0fd Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Fri, 24 Dec 2021 16:33:10 +0800 Subject: [PATCH 35/70] do not define tgmath.h fmaxmag, fminmag macros for C2X (BZ #28397) (cherry picked from commit cc054c6ba075a695abec8d3008e5183fdeea03f1) --- ...math.h-fmaxmag-fminmag-macros-for-C2.patch | 37 +++++++++++++++++++ glibc.spec | 6 ++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch diff --git a/Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch b/Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch new file mode 100644 index 0000000..ce25968 --- /dev/null +++ b/Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch @@ -0,0 +1,37 @@ +From 79850e1025aabeccd3586c32ca259aa854607582 Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Wed, 29 Sep 2021 17:38:32 +0000 +Subject: [PATCH] Do not define tgmath.h fmaxmag, fminmag macros for C2X (bug + 28397) + +C2X does not include fmaxmag and fminmag. When I updated feature test +macro handling accordingly (commit +858045ad1c5ac1682288bbcb3676632b97a21ddf, "Update floating-point +feature test macro handling for C2X", included in 2.34), I missed +updating tgmath.h so it doesn't define the corresponding type-generic +macros unless __STDC_WANT_IEC_60559_BFP_EXT__ is defined; I've now +reported this as bug 28397. Adjust the conditionals in tgmath.h +accordingly. + +Tested for x86_64. +--- + math/tgmath.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/math/tgmath.h b/math/tgmath.h +index 9868353..3d7b099 100644 +--- a/math/tgmath.h ++++ b/math/tgmath.h +@@ -921,7 +921,9 @@ + + /* Like ilogb, but returning long int. */ + # define llogb(Val) __TGMATH_UNARY_REAL_RET_ONLY (Val, llogb) ++#endif + ++#if __GLIBC_USE (IEC_60559_BFP_EXT) + /* Return value with maximum magnitude. */ + # define fmaxmag(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fmaxmag) + +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index 09df504..c4ea06c 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 35 +Release: 36 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -143,6 +143,7 @@ Patch56: Use-support_open_dev_null_range-io-tst-closefrom-mis.patch Patch57: Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch Patch58: nptl-Add-one-more-barrier-to-nptl-tst-create1.patch Patch59: io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch +Patch60: Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1339,6 +1340,9 @@ fi %endif %changelog +* Fri Dec 24 2021 Qingqing Li - 2.34-36 +- do not define tgmath.h fmaxmag, fminmag macros for C2X (BZ #28397) + * Fri Dec 24 2021 Qingqing Li - 2.34-35 - io: Fix ftw internal realloc buffer (BZ #28126) -- Gitee From 6c13f1369d9dd2214b5560dd0e72d81932663e3d Mon Sep 17 00:00:00 2001 From: liusirui Date: Sat, 25 Dec 2021 17:31:02 +0800 Subject: [PATCH 36/70] ld.so: Don't fill the DT_DEBUG entry in ld.so [BZ #28129] Signed-off-by: liusirui (cherry picked from commit 38869172b4e1b1a6945cf8f0fb78f41093c3797e) --- glibc.spec | 6 ++- ...-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch | 37 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch diff --git a/glibc.spec b/glibc.spec index c4ea06c..6a1a288 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 36 +Release: 37 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -144,6 +144,7 @@ Patch57: Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch Patch58: nptl-Add-one-more-barrier-to-nptl-tst-create1.patch Patch59: io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch Patch60: Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch +Patch61: ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1340,6 +1341,9 @@ fi %endif %changelog +* Sat Dec 25 2021 liusirui - 2.34-37 +- ld.so: Don't fill the DT_DEBUG entry in ld.so [BZ #28129] + * Fri Dec 24 2021 Qingqing Li - 2.34-36 - do not define tgmath.h fmaxmag, fminmag macros for C2X (BZ #28397) diff --git a/ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch b/ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch new file mode 100644 index 0000000..93d45e9 --- /dev/null +++ b/ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch @@ -0,0 +1,37 @@ +From 3234a31b489707f19ec6d4c9909af06f20ddb901 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Mon, 2 Aug 2021 13:52:36 -0700 +Subject: [PATCH] ld.so: Don't fill the DT_DEBUG entry in ld.so [BZ #28129] + +Linker creates the DT_DEBUG entry only in executables. Don't fill the +non-existent DT_DEBUG entry in ld.so with the run-time address of the +r_debug structure. This fixes BZ #28129. +--- + elf/rtld.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/elf/rtld.c b/elf/rtld.c +index 9642eb9c92..628245d8cd 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1761,17 +1761,11 @@ dl_main (const ElfW(Phdr) *phdr, + #ifdef ELF_MACHINE_DEBUG_SETUP + /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */ + ELF_MACHINE_DEBUG_SETUP (main_map, r); +- ELF_MACHINE_DEBUG_SETUP (&GL(dl_rtld_map), r); + #else + if (main_map->l_info[DT_DEBUG] != NULL) + /* There is a DT_DEBUG entry in the dynamic section. Fill it in + with the run-time address of the r_debug structure */ + main_map->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; +- +- /* Fill in the pointer in the dynamic linker's own dynamic section, in +- case you run gdb on the dynamic linker directly. */ +- if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL) +- GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; + #endif + + /* We start adding objects. */ +-- +2.25.1 + -- Gitee From 980c1e01c216234aacc8bdda3829080dfbe37a08 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 27 Dec 2021 09:27:05 +0800 Subject: [PATCH 37/70] elf replace nsid with args.nsid [BZ #27609] --- ...Replace-nsid-with-args.nsid-BZ-27609.patch | 50 +++++++++++++++++++ glibc.spec | 6 ++- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 elf-Replace-nsid-with-args.nsid-BZ-27609.patch diff --git a/elf-Replace-nsid-with-args.nsid-BZ-27609.patch b/elf-Replace-nsid-with-args.nsid-BZ-27609.patch new file mode 100644 index 0000000..47a7031 --- /dev/null +++ b/elf-Replace-nsid-with-args.nsid-BZ-27609.patch @@ -0,0 +1,50 @@ +From 1e1ecea62e899acb58c3fdf3b320a0833ddd0dff Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Thu, 30 Sep 2021 10:29:17 -0700 +Subject: [PATCH] elf: Replace nsid with args.nsid [BZ #27609] + +commit ec935dea6332cb22f9881cd1162bad156173f4b0 +Author: Florian Weimer +Date: Fri Apr 24 22:31:15 2020 +0200 + + elf: Implement __libc_early_init + +has + +@@ -856,6 +876,11 @@ no more namespaces available for dlmopen()")); + /* See if an error occurred during loading. */ + if (__glibc_unlikely (exception.errstring != NULL)) + { ++ /* Avoid keeping around a dangling reference to the libc.so link ++ map in case it has been cached in libc_map. */ ++ if (!args.libc_already_loaded) ++ GL(dl_ns)[nsid].libc_map = NULL; ++ + +do_dlopen calls _dl_open with nsid == __LM_ID_CALLER (-2), which calls +dl_open_worker with args.nsid = nsid. dl_open_worker updates args.nsid +if it is __LM_ID_CALLER. After dl_open_worker returns, it is wrong to +use nsid. + +Replace nsid with args.nsid after dl_open_worker returns. This fixes +BZ #27609. +--- + elf/dl-open.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index a25443f..5295e93 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -886,7 +886,7 @@ no more namespaces available for dlmopen()")); + /* Avoid keeping around a dangling reference to the libc.so link + map in case it has been cached in libc_map. */ + if (!args.libc_already_loaded) +- GL(dl_ns)[nsid].libc_map = NULL; ++ GL(dl_ns)[args.nsid].libc_map = NULL; + + /* Remove the object from memory. It may be in an inconsistent + state if relocation failed, for example. */ +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index 6a1a288..4f63e1b 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 37 +Release: 38 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -145,6 +145,7 @@ Patch58: nptl-Add-one-more-barrier-to-nptl-tst-create1.patch Patch59: io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch Patch60: Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch Patch61: ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch +Patch62: elf-Replace-nsid-with-args.nsid-BZ-27609.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1341,6 +1342,9 @@ fi %endif %changelog +* Mon Dec 27 2021 Qingqing Li - 2.34-38 +- elf: replace nsid with args.nsid [BZ #27609] + * Sat Dec 25 2021 liusirui - 2.34-37 - ld.so: Don't fill the DT_DEBUG entry in ld.so [BZ #28129] -- Gitee From fcfb718ec7a82eb9626915c67138dea05795814e Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Tue, 28 Dec 2021 20:45:07 +0800 Subject: [PATCH 38/70] support: Also return fd when it is 0 --- glibc.spec | 6 ++- support-Also-return-fd-when-it-is-0.patch | 45 +++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 support-Also-return-fd-when-it-is-0.patch diff --git a/glibc.spec b/glibc.spec index 4f63e1b..f836b33 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 38 +Release: 39 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -146,6 +146,7 @@ Patch59: io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch Patch60: Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch Patch61: ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch Patch62: elf-Replace-nsid-with-args.nsid-BZ-27609.patch +Patch63: support-Also-return-fd-when-it-is-0.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1342,6 +1343,9 @@ fi %endif %changelog +* Tue Dec 28 2021 Qingqing Li - 2.34-39 +- support: Also return fd when it is 0. + * Mon Dec 27 2021 Qingqing Li - 2.34-38 - elf: replace nsid with args.nsid [BZ #27609] diff --git a/support-Also-return-fd-when-it-is-0.patch b/support-Also-return-fd-when-it-is-0.patch new file mode 100644 index 0000000..150b4c3 --- /dev/null +++ b/support-Also-return-fd-when-it-is-0.patch @@ -0,0 +1,45 @@ +From 27b6edbb090f736b101f569620d8ad0e7217ddf8 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Wed, 6 Oct 2021 21:48:35 +0530 +Subject: [PATCH] support: Also return fd when it is 0 + +The fd validity check in open_dev_null checks if fd > 0, which would +lead to a leaked fd if it is == 0. + +Signed-off-by: Siddhesh Poyarekar +Reviewed-by: Adhemerval Zanella +--- + support/support-open-dev-null-range.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/support/support-open-dev-null-range.c b/support/support-open-dev-null-range.c +index 80d9dba..66a8504 100644 +--- a/support/support-open-dev-null-range.c ++++ b/support/support-open-dev-null-range.c +@@ -40,16 +40,16 @@ increase_nofile (void) + static int + open_dev_null (int flags, mode_t mode) + { +- int fd = open64 ("/dev/null", flags, mode); +- if (fd > 0) +- return fd; ++ int fd = open64 ("/dev/null", flags, mode); ++ if (fd >= 0) ++ return fd; + +- if (fd < 0 && errno != EMFILE) +- FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode); ++ if (fd < 0 && errno != EMFILE) ++ FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode); + +- increase_nofile (); ++ increase_nofile (); + +- return xopen ("/dev/null", flags, mode); ++ return xopen ("/dev/null", flags, mode); + } + + struct range +-- +1.8.3.1 + -- Gitee From 2b5fb604767f98a17259c912b55ae92bb6611bee Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Mon, 10 Jan 2022 14:41:26 +0800 Subject: [PATCH 39/70] build:add a switch, select find-debuginfo.sh rpm-build move find-debuginfo.sh into debugedit. and change the path from "/usr/lib/rpm" to "/usr/bin" adapts this change Signed-off-by: Yang Yanchao --- glibc.spec | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/glibc.spec b/glibc.spec index f836b33..db51aae 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 39 +Release: 40 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -950,7 +950,13 @@ find_debuginfo_args="$find_debuginfo_args \ " %endif -/usr/lib/rpm/find-debuginfo.sh $find_debuginfo_args -o debuginfo.filelist +if command -v find-debuginfo >/dev/null ; then + find_debuginfo=find-debuginfo +else + find_debuginfo=/usr/lib/rpm/find-debuginfo.sh +fi + +$find_debuginfo $find_debuginfo_args -o debuginfo.filelist %ifarch %{x86_arches} sed -i '\#^$RPM_BUILD_ROOT%{_prefix}/src/debug/#d' debuginfo_additional.filelist @@ -1343,6 +1349,11 @@ fi %endif %changelog +* Mon Jan 10 2022 Yang Yanchao - 2.34-40 +- rpm-build move find-debuginfo.sh into debugedit. + and change the path from "/usr/lib/rpm" to "/usr/bin" + adapts this change + * Tue Dec 28 2021 Qingqing Li - 2.34-39 - support: Also return fd when it is 0. -- Gitee From 5c4b6ffe5d97d0cab0d276ba2c7e86578c97db57 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Tue, 4 Jan 2022 20:40:43 +0800 Subject: [PATCH 40/70] backport some bugfix patches from mainline --- ...h64-Check-for-SVE-in-ifuncs-BZ-28744.patch | 55 ++++++ ...pt-error-with-odd-TZif-file-BZ-28338.patch | 31 ++++ ...input-to-malloc_usable_size-BZ-28506.patch | 158 ++++++++++++++++++ ...ing-dynamic-segment-check-in-_dl_map.patch | 73 ++++++++ glibc.spec | 26 ++- ...oid-conflicting-declarations-of-yyer.patch | 42 +++++ ...tat-fallback-for-__get_nprocs_conf-B.patch | 102 +++++++++++ ...signal-mask-on-second-setjmp-return-.patch | 111 ++++++++++++ ...s-as-the-default-for-the-hosts-datab.patch | 81 +++++++++ ...-fields-on-32-bit-TIMESIZE-64-system.patch | 45 +++++ ...truncated-timezones-from-tzcode-2021.patch | 57 +++++++ timezone-test-case-for-BZ-28707.patch | 138 +++++++++++++++ 12 files changed, 918 insertions(+), 1 deletion(-) create mode 100644 AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch create mode 100644 Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch create mode 100644 Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch create mode 100644 elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch create mode 100644 intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch create mode 100644 linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch create mode 100644 nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch create mode 100644 nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch create mode 100644 timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch create mode 100644 timezone-handle-truncated-timezones-from-tzcode-2021.patch create mode 100644 timezone-test-case-for-BZ-28707.patch diff --git a/AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch b/AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch new file mode 100644 index 0000000..1c41ca3 --- /dev/null +++ b/AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch @@ -0,0 +1,55 @@ +From e5fa62b8db546f8792ec9e5c61e6419f4f8e3f4d Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Thu, 6 Jan 2022 14:36:28 +0000 +Subject: [PATCH] AArch64: Check for SVE in ifuncs [BZ #28744] + +Add a check for SVE in the A64FX ifuncs for memcpy, memset and memmove. +This fixes BZ #28744. +--- + sysdeps/aarch64/multiarch/memcpy.c | 2 +- + sysdeps/aarch64/multiarch/memmove.c | 2 +- + sysdeps/aarch64/multiarch/memset.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c +index 7dac7b7..a476dd5 100644 +--- a/sysdeps/aarch64/multiarch/memcpy.c ++++ b/sysdeps/aarch64/multiarch/memcpy.c +@@ -48,7 +48,7 @@ libc_ifunc (__libc_memcpy, + || IS_NEOVERSE_V1 (midr) + ? __memcpy_simd + # if HAVE_AARCH64_SVE_ASM +- : (IS_A64FX (midr) ++ : (IS_A64FX (midr) && sve + ? __memcpy_a64fx + : __memcpy_generic)))))); + # else +diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c +index 48f8e46..4f7d7ee 100644 +--- a/sysdeps/aarch64/multiarch/memmove.c ++++ b/sysdeps/aarch64/multiarch/memmove.c +@@ -48,7 +48,7 @@ libc_ifunc (__libc_memmove, + || IS_NEOVERSE_V1 (midr) + ? __memmove_simd + # if HAVE_AARCH64_SVE_ASM +- : (IS_A64FX (midr) ++ : (IS_A64FX (midr) && sve + ? __memmove_a64fx + : __memmove_generic)))))); + # else +diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c +index 3692b07..c4008f3 100644 +--- a/sysdeps/aarch64/multiarch/memset.c ++++ b/sysdeps/aarch64/multiarch/memset.c +@@ -44,7 +44,7 @@ libc_ifunc (__libc_memset, + : (IS_EMAG (midr) && zva_size == 64 + ? __memset_emag + # if HAVE_AARCH64_SVE_ASM +- : (IS_A64FX (midr) ++ : (IS_A64FX (midr) && sve + ? __memset_a64fx + : __memset_generic)))); + # else +-- +1.8.3.1 + diff --git a/Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch b/Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch new file mode 100644 index 0000000..3825b15 --- /dev/null +++ b/Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch @@ -0,0 +1,31 @@ +From 645277434a42efc547d2cac8bfede4da10b4049f Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Mon, 13 Sep 2021 22:49:45 -0700 +Subject: [PATCH] Fix subscript error with odd TZif file [BZ #28338] + +* time/tzfile.c (__tzfile_compute): Fix unlikely off-by-one bug +that accessed before start of an array when an oddball-but-valid +TZif file was queried with an unusual time_t value. + +Reviewed-by: Adhemerval Zanella +--- + time/tzfile.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/time/tzfile.c b/time/tzfile.c +index 4377018..190a777 100644 +--- a/time/tzfile.c ++++ b/time/tzfile.c +@@ -765,8 +765,7 @@ __tzfile_compute (__time64_t timer, int use_localtime, + *leap_correct = leaps[i].change; + + if (timer == leaps[i].transition /* Exactly at the transition time. */ +- && ((i == 0 && leaps[i].change > 0) +- || leaps[i].change > leaps[i - 1].change)) ++ && (leaps[i].change > (i == 0 ? 0 : leaps[i - 1].change))) + { + *leap_hit = 1; + while (i > 0 +-- +1.8.3.1 + diff --git a/Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch b/Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch new file mode 100644 index 0000000..9115fc4 --- /dev/null +++ b/Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch @@ -0,0 +1,158 @@ +From 01bffc013cdad1e0c45db7aa57efb2bee61f3338 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Fri, 29 Oct 2021 14:53:55 +0530 +Subject: [PATCH] Handle NULL input to malloc_usable_size [BZ #28506] + +Hoist the NULL check for malloc_usable_size into its entry points in +malloc-debug and malloc and assume non-NULL in all callees. This fixes +BZ #28506 + +Signed-off-by: Siddhesh Poyarekar +Reviewed-by: Florian Weimer +Reviewed-by: Richard W.M. Jones +(cherry picked from commit 88e316b06414ee7c944cd6f8b30b07a972b78499) +--- + malloc/malloc-debug.c | 13 +++++++------ + malloc/malloc.c | 25 +++++++++---------------- + malloc/tst-malloc-usable.c | 22 +++++++++------------- + 3 files changed, 25 insertions(+), 35 deletions(-) + +diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c +index 9922ef5..3d7e6d4 100644 +--- a/malloc/malloc-debug.c ++++ b/malloc/malloc-debug.c +@@ -1,5 +1,6 @@ + /* Malloc debug DSO. + Copyright (C) 2021 Free Software Foundation, Inc. ++ Copyright The GNU Toolchain Authors. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -399,17 +400,17 @@ strong_alias (__debug_calloc, calloc) + size_t + malloc_usable_size (void *mem) + { ++ if (mem == NULL) ++ return 0; ++ + if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)) + return mcheck_usable_size (mem); + if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)) + return malloc_check_get_size (mem); + +- if (mem != NULL) +- { +- mchunkptr p = mem2chunk (mem); +- if (DUMPED_MAIN_ARENA_CHUNK (p)) +- return chunksize (p) - SIZE_SZ; +- } ++ mchunkptr p = mem2chunk (mem); ++ if (DUMPED_MAIN_ARENA_CHUNK (p)) ++ return chunksize (p) - SIZE_SZ; + + return musable (mem); + } +diff --git a/malloc/malloc.c b/malloc/malloc.c +index e065785..7882c70 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -1,5 +1,6 @@ + /* Malloc implementation for multiple threads without lock contention. + Copyright (C) 1996-2021 Free Software Foundation, Inc. ++ Copyright The GNU Toolchain Authors. + This file is part of the GNU C Library. + Contributed by Wolfram Gloger + and Doug Lea , 2001. +@@ -5009,20 +5010,13 @@ __malloc_trim (size_t s) + static size_t + musable (void *mem) + { +- mchunkptr p; +- if (mem != 0) +- { +- size_t result = 0; +- +- p = mem2chunk (mem); ++ mchunkptr p = mem2chunk (mem); + +- if (chunk_is_mmapped (p)) +- result = chunksize (p) - CHUNK_HDR_SZ; +- else if (inuse (p)) +- result = memsize (p); ++ if (chunk_is_mmapped (p)) ++ return chunksize (p) - CHUNK_HDR_SZ; ++ else if (inuse (p)) ++ return memsize (p); + +- return result; +- } + return 0; + } + +@@ -5030,10 +5024,9 @@ musable (void *mem) + size_t + __malloc_usable_size (void *m) + { +- size_t result; +- +- result = musable (m); +- return result; ++ if (m == NULL) ++ return 0; ++ return musable (m); + } + #endif + +diff --git a/malloc/tst-malloc-usable.c b/malloc/tst-malloc-usable.c +index a1074b7..b0d702b 100644 +--- a/malloc/tst-malloc-usable.c ++++ b/malloc/tst-malloc-usable.c +@@ -2,6 +2,7 @@ + MALLOC_CHECK_ exported to a positive value. + + Copyright (C) 2012-2021 Free Software Foundation, Inc. ++ Copyright The GNU Toolchain Authors. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -21,29 +22,24 @@ + #include + #include + #include ++#include ++#include + + static int + do_test (void) + { + size_t usable_size; + void *p = malloc (7); +- if (!p) +- { +- printf ("memory allocation failed\n"); +- return 1; +- } + ++ TEST_VERIFY_EXIT (p != NULL); + usable_size = malloc_usable_size (p); +- if (usable_size != 7) +- { +- printf ("malloc_usable_size: expected 7 but got %zu\n", usable_size); +- return 1; +- } +- ++ TEST_COMPARE (usable_size, 7); + memset (p, 0, usable_size); + free (p); ++ ++ TEST_COMPARE (malloc_usable_size (NULL), 0); ++ + return 0; + } + +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include "support/test-driver.c" +-- +1.8.3.1 + diff --git a/elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch b/elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch new file mode 100644 index 0000000..3d5bd60 --- /dev/null +++ b/elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch @@ -0,0 +1,73 @@ +From ea32ec354c65ddad11b82ca9d057010df13a9cea Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 5 Nov 2021 17:01:24 +0100 +Subject: [PATCH] elf: Earlier missing dynamic segment check in + _dl_map_object_from_fd + +Separated debuginfo files have PT_DYNAMIC with p_filesz == 0. We +need to check for that before the _dl_map_segments call because +that could attempt to write to mappings that extend beyond the end +of the file, resulting in SIGBUS. + +Reviewed-by: H.J. Lu +--- + elf/dl-load.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index a1f1682..9f4fa96 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1135,6 +1135,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + struct loadcmd loadcmds[l->l_phnum]; + size_t nloadcmds = 0; + bool has_holes = false; ++ bool empty_dynamic = false; + + /* The struct is initialized to zero so this is not necessary: + l->l_ld = 0; +@@ -1147,7 +1148,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + segments are mapped in. We record the addresses it says + verbatim, and later correct for the run-time load address. */ + case PT_DYNAMIC: +- if (ph->p_filesz) ++ if (ph->p_filesz == 0) ++ empty_dynamic = true; /* Usually separate debuginfo. */ ++ else + { + /* Debuginfo only files from "objcopy --only-keep-debug" + contain a PT_DYNAMIC segment with p_filesz == 0. Skip +@@ -1270,6 +1273,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + goto lose; + } + ++ /* This check recognizes most separate debuginfo files. */ ++ if (__glibc_unlikely ((l->l_ld == 0 && type == ET_DYN) || empty_dynamic)) ++ { ++ errstring = N_("object file has no dynamic section"); ++ goto lose; ++ } ++ + /* Length of the sections to be loaded. */ + maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart; + +@@ -1287,15 +1297,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + } + } + +- if (l->l_ld == 0) +- { +- if (__glibc_unlikely (type == ET_DYN)) +- { +- errstring = N_("object file has no dynamic section"); +- goto lose; +- } +- } +- else ++ if (l->l_ld != 0) + l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr); + + elf_get_dynamic_info (l); +-- +1.8.3.1 + diff --git a/glibc.spec b/glibc.spec index db51aae..5cc8051 100644 --- a/glibc.spec +++ b/glibc.spec @@ -65,7 +65,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 40 +Release: 41 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -147,6 +147,17 @@ Patch60: Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch Patch61: ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch Patch62: elf-Replace-nsid-with-args.nsid-BZ-27609.patch Patch63: support-Also-return-fd-when-it-is-0.patch +Patch64: elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch +Patch65: Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch +Patch66: intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch +Patch67: linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch +Patch68: nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch +Patch69: nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch +Patch70: timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch +Patch71: AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch +Patch72: Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch +Patch73: timezone-handle-truncated-timezones-from-tzcode-2021.patch +Patch74: timezone-test-case-for-BZ-28707.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1349,6 +1360,19 @@ fi %endif %changelog +* Mon Jan 10 2022 Qingqing Li - 2.34-41 +- timex: Use 64-bit fields on 32-bit TIMESIZE=64 systems. BZ #28469 +- malloc: Handle NULL input to malloc usable size. BZ #28506 +- elf: Earlier missing dynamic segment check in _dl_map_object_from_fd +- nptl: Do not set signal mask on second setjmp return. BZ #28607 +- linux: use /proc/stat fallback for __get_nprocs_conf. BZ #28624 +- nss: Use "file dns" as the default for the hosts database. BZ #28700 +- int/plural.y: Avoid conflicting declarations of yyerror and yylex +- aarch64: Check for SVE in ifuncs BZ #28744 +- Fix subscript error with odd TZif file BZ #28338 +- timezone: handle truncated timezones from tzcode 2021 +- timezone: test case for BZ #28707 + * Mon Jan 10 2022 Yang Yanchao - 2.34-40 - rpm-build move find-debuginfo.sh into debugedit. and change the path from "/usr/lib/rpm" to "/usr/bin" diff --git a/intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch b/intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch new file mode 100644 index 0000000..4931c9e --- /dev/null +++ b/intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch @@ -0,0 +1,42 @@ +From c6d7d6312c21bbcfb236d48bb7c11cedb234389f Mon Sep 17 00:00:00 2001 +From: Andrea Monaco +Date: Sun, 12 Dec 2021 10:24:28 +0100 +Subject: [PATCH] intl/plural.y: Avoid conflicting declarations of yyerror and + yylex + +bison-3.8 includes these lines in the generated intl/plural.c: + + #if !defined __gettexterror && !defined YYERROR_IS_DECLARED + void __gettexterror (struct parse_args *arg, const char *msg); + #endif + #if !defined __gettextlex && !defined YYLEX_IS_DECLARED + int __gettextlex (YYSTYPE *yylvalp, struct parse_args *arg); + #endif + +Those default prototypes provided by bison conflict with the +declarations later on in plural.y. This patch solves the issue. + +Reviewed-by: Arjun Shankar +--- + intl/plural.y | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/intl/plural.y b/intl/plural.y +index e02e745..2ee128b 100644 +--- a/intl/plural.y ++++ b/intl/plural.y +@@ -40,6 +40,11 @@ + # define __gettextparse PLURAL_PARSE + #endif + ++/* Later we provide those prototypes. Without these macros, bison may ++ generate its own prototypes with possible conflicts. */ ++#define YYLEX_IS_DECLARED ++#define YYERROR_IS_DECLARED ++ + %} + %parse-param {struct parse_args *arg} + %lex-param {struct parse_args *arg} +-- +1.8.3.1 + diff --git a/linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch b/linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch new file mode 100644 index 0000000..57c9aa2 --- /dev/null +++ b/linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch @@ -0,0 +1,102 @@ +From 137ed5ac440a4d3cf4178ce97f349b349a9c2c66 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Thu, 25 Nov 2021 09:12:00 -0300 +Subject: [PATCH] linux: Use /proc/stat fallback for __get_nprocs_conf (BZ + #28624) + +The /proc/statm fallback was removed by f13fb81ad3159 if sysfs is +not available, reinstate it. + +Checked on x86_64-linux-gnu. +--- + sysdeps/unix/sysv/linux/getsysstats.c | 60 ++++++++++++++++++++--------------- + 1 file changed, 35 insertions(+), 25 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c +index 15ad91c..d376f05 100644 +--- a/sysdeps/unix/sysv/linux/getsysstats.c ++++ b/sysdeps/unix/sysv/linux/getsysstats.c +@@ -107,6 +107,37 @@ next_line (int fd, char *const buffer, char **cp, char **re, + return res == *re ? NULL : res; + } + ++static int ++get_nproc_stat (char *buffer, size_t buffer_size) ++{ ++ char *buffer_end = buffer + buffer_size; ++ char *cp = buffer_end; ++ char *re = buffer_end; ++ ++ /* Default to an SMP system in case we cannot obtain an accurate ++ number. */ ++ int result = 2; ++ ++ const int flags = O_RDONLY | O_CLOEXEC; ++ int fd = __open_nocancel ("/proc/stat", flags); ++ if (fd != -1) ++ { ++ result = 0; ++ ++ char *l; ++ while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) ++ /* The current format of /proc/stat has all the cpu* entries ++ at the front. We assume here that stays this way. */ ++ if (strncmp (l, "cpu", 3) != 0) ++ break; ++ else if (isdigit (l[3])) ++ ++result; ++ ++ __close_nocancel_nostatus (fd); ++ } ++ ++ return result; ++} + + int + __get_nprocs (void) +@@ -162,30 +193,7 @@ __get_nprocs (void) + return result; + } + +- cp = buffer_end; +- re = buffer_end; +- +- /* Default to an SMP system in case we cannot obtain an accurate +- number. */ +- result = 2; +- +- fd = __open_nocancel ("/proc/stat", flags); +- if (fd != -1) +- { +- result = 0; +- +- while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) +- /* The current format of /proc/stat has all the cpu* entries +- at the front. We assume here that stays this way. */ +- if (strncmp (l, "cpu", 3) != 0) +- break; +- else if (isdigit (l[3])) +- ++result; +- +- __close_nocancel_nostatus (fd); +- } +- +- return result; ++ return get_nproc_stat (buffer, buffer_size); + } + libc_hidden_def (__get_nprocs) + weak_alias (__get_nprocs, get_nprocs) +@@ -219,7 +227,9 @@ __get_nprocs_conf (void) + return count; + } + +- return 1; ++ enum { buffer_size = 1024 }; ++ char buffer[buffer_size]; ++ return get_nproc_stat (buffer, buffer_size); + } + libc_hidden_def (__get_nprocs_conf) + weak_alias (__get_nprocs_conf, get_nprocs_conf) +-- +1.8.3.1 + diff --git a/nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch b/nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch new file mode 100644 index 0000000..8f5a571 --- /dev/null +++ b/nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch @@ -0,0 +1,111 @@ +From bfe68fe3c475fe34bed4e017d6e63196c305c934 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 24 Nov 2021 08:59:54 +0100 +Subject: [PATCH] nptl: Do not set signal mask on second setjmp return [BZ + #28607] + +__libc_signal_restore_set was in the wrong place: It also ran +when setjmp returned the second time (after pthread_exit or +pthread_cancel). This is observable with blocked pending +signals during thread exit. + +Fixes commit b3cae39dcbfa2432b3f3aa28854d8ac57f0de1b8 +("nptl: Start new threads with all signals blocked [BZ #25098]"). + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit e186fc5a31e46f2cbf5ea1a75223b4412907f3d8) +--- + nptl/pthread_create.c | 4 +-- + sysdeps/pthread/Makefile | 1 + + sysdeps/pthread/tst-pthread-exit-signal.c | 45 +++++++++++++++++++++++++++++++ + 3 files changed, 48 insertions(+), 2 deletions(-) + create mode 100644 sysdeps/pthread/tst-pthread-exit-signal.c + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index bc213f0..3db0c9f 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -407,8 +407,6 @@ start_thread (void *arg) + unwind_buf.priv.data.prev = NULL; + unwind_buf.priv.data.cleanup = NULL; + +- __libc_signal_restore_set (&pd->sigmask); +- + /* Allow setxid from now onwards. */ + if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2)) + futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE); +@@ -418,6 +416,8 @@ start_thread (void *arg) + /* Store the new cleanup handler info. */ + THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf); + ++ __libc_signal_restore_set (&pd->sigmask); ++ + LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg); + + /* Run the code the user provided. */ +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index df8943f..c657101 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -118,6 +118,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-unload \ + tst-unwind-thread \ + tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \ ++ tst-pthread-exit-signal \ + tst-pthread-setuid-loop \ + tst-pthread_cancel-exited \ + tst-pthread_cancel-select-loop \ +diff --git a/sysdeps/pthread/tst-pthread-exit-signal.c b/sysdeps/pthread/tst-pthread-exit-signal.c +new file mode 100644 +index 0000000..b4526fe +--- /dev/null ++++ b/sysdeps/pthread/tst-pthread-exit-signal.c +@@ -0,0 +1,45 @@ ++/* Test that pending signals are not delivered on thread exit (bug 28607). ++ Copyright (C) 2021 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 ++ . */ ++ ++/* Due to bug 28607, pthread_kill (or pthread_cancel) restored the ++ signal mask during during thread exit, triggering the delivery of a ++ blocked pending signal (SIGUSR1 in this test). */ ++ ++#include ++#include ++ ++static void * ++threadfunc (void *closure) ++{ ++ sigset_t sigmask; ++ sigfillset (&sigmask); ++ xpthread_sigmask (SIG_SETMASK, &sigmask, NULL); ++ xpthread_kill (pthread_self (), SIGUSR1); ++ pthread_exit (NULL); ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ pthread_t thr = xpthread_create (NULL, threadfunc, NULL); ++ xpthread_join (thr); ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + diff --git a/nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch b/nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch new file mode 100644 index 0000000..28ff860 --- /dev/null +++ b/nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch @@ -0,0 +1,81 @@ +From b99b0f93ee8762fe53ff65802deb6f00700b9924 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 17 Dec 2021 12:01:20 +0100 +Subject: [PATCH] nss: Use "files dns" as the default for the hosts database + (bug 28700) + +This matches what is currently in nss/nsswitch.conf. The new ordering +matches what most distributions use in their installed configuration +files. + +It is common to add localhost to /etc/hosts because the name does not +exist in the DNS, but is commonly used as a host name. + +With the built-in "dns [!UNAVAIL=return] files" default, dns is +searched first and provides an answer for "localhost" (NXDOMAIN). +We never look at the files database as a result, so the contents of +/etc/hosts is ignored. This means that "getent hosts localhost" +fail without a /etc/nsswitch.conf file, even though the host name +is listed in /etc/hosts. + +Reviewed-by: Carlos O'Donell +--- + manual/nss.texi | 5 ++--- + nss/XXX-lookup.c | 2 +- + nss/nss_database.c | 4 ++-- + 3 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/manual/nss.texi b/manual/nss.texi +index 3aaa778..524d22a 100644 +--- a/manual/nss.texi ++++ b/manual/nss.texi +@@ -324,9 +324,8 @@ missing. + + @cindex default value, and NSS + For the @code{hosts} and @code{networks} databases the default value is +-@code{dns [!UNAVAIL=return] files}. I.e., the system is prepared for +-the DNS service not to be available but if it is available the answer it +-returns is definitive. ++@code{files dns}. I.e., local configuration will override the contents ++of the domain name system (DNS). + + The @code{passwd}, @code{group}, and @code{shadow} databases was + traditionally handled in a special way. The appropriate files in the +diff --git a/nss/XXX-lookup.c b/nss/XXX-lookup.c +index 302c636..e129f69 100644 +--- a/nss/XXX-lookup.c ++++ b/nss/XXX-lookup.c +@@ -28,7 +28,7 @@ + |* ALTERNATE_NAME - name of another service which is examined in *| + |* case DATABASE_NAME is not found *| + |* *| +-|* DEFAULT_CONFIG - string for default conf (e.g. "dns files") *| ++|* DEFAULT_CONFIG - string for default conf (e.g. "files dns") *| + |* *| + \*******************************************************************/ + +diff --git a/nss/nss_database.c b/nss/nss_database.c +index ab121cb..54561f0 100644 +--- a/nss/nss_database.c ++++ b/nss/nss_database.c +@@ -80,7 +80,7 @@ enum nss_database_default + { + nss_database_default_defconfig = 0, /* "nis [NOTFOUND=return] files". */ + nss_database_default_compat, /* "compat [NOTFOUND=return] files". */ +- nss_database_default_dns, /* "dns [!UNAVAIL=return] files". */ ++ nss_database_default_dns, /* "files dns". */ + nss_database_default_files, /* "files". */ + nss_database_default_nis, /* "nis". */ + nss_database_default_nis_nisplus, /* "nis nisplus". */ +@@ -133,7 +133,7 @@ nss_database_select_default (struct nss_database_default_cache *cache, + #endif + + case nss_database_default_dns: +- line = "dns [!UNAVAIL=return] files"; ++ line = "files dns"; + break; + + case nss_database_default_files: +-- +1.8.3.1 + diff --git a/timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch b/timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch new file mode 100644 index 0000000..3c6d72b --- /dev/null +++ b/timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch @@ -0,0 +1,45 @@ +From 1d550265a75b412cea4889a50b101395f6a8e025 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Fri, 15 Oct 2021 06:17:41 +0900 +Subject: [PATCH] timex: Use 64-bit fields on 32-bit TIMESIZE=64 systems (BZ + #28469) + +This was found when testing the OpenRISC port I am working on. These +two tests fail with SIGSEGV: + + FAIL: misc/tst-ntp_gettime + FAIL: misc/tst-ntp_gettimex + +This was found to be due to the kernel overwriting the stack space +allocated by the timex structure. The reason for the overwrite being +that the kernel timex has 64-bit fields and user space code only +allocates enough stack space for timex with 32-bit fields. + +On 32-bit systems with TIMESIZE=64 __USE_TIME_BITS64 is not defined. +This causes the timex structure to use 32-bit fields with type +__syscall_slong_t. + +This patch adjusts the ifdef condition to allow 32-bit systems with +TIMESIZE=64 to use the 64-bit long long timex definition. + +Reviewed-by: Adhemerval Zanella +--- + sysdeps/unix/sysv/linux/bits/timex.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/unix/sysv/linux/bits/timex.h b/sysdeps/unix/sysv/linux/bits/timex.h +index ee37694..4a5db6d 100644 +--- a/sysdeps/unix/sysv/linux/bits/timex.h ++++ b/sysdeps/unix/sysv/linux/bits/timex.h +@@ -25,7 +25,7 @@ + + struct timex + { +-# ifdef __USE_TIME_BITS64 ++# if defined __USE_TIME_BITS64 || (__TIMESIZE == 64 && __WORDSIZE == 32) + unsigned int modes; /* mode selector */ + int :32; /* pad */ + long long offset; /* time offset (usec) */ +-- +1.8.3.1 + diff --git a/timezone-handle-truncated-timezones-from-tzcode-2021.patch b/timezone-handle-truncated-timezones-from-tzcode-2021.patch new file mode 100644 index 0000000..10ef9e8 --- /dev/null +++ b/timezone-handle-truncated-timezones-from-tzcode-2021.patch @@ -0,0 +1,57 @@ +From c36f64aa6dff13b12a1e03a185e75a50fa9f6a4c Mon Sep 17 00:00:00 2001 +From: Hans-Peter Nilsson +Date: Fri, 17 Dec 2021 21:38:00 +0100 +Subject: [PATCH] timezone: handle truncated timezones from tzcode-2021d and + later (BZ #28707) + +When using a timezone file with a truncated starting time, +generated by the zic in IANA tzcode-2021d a.k.a. tzlib-2021d +(also in tzlib-2021e; current as of this writing), glibc +asserts in __tzfile_read (on e.g. tzset() for this file) and +you may find lines matching "tzfile.c:435: __tzfile_read: +Assertion `num_types == 1' failed" in your syslog. + +One example of such a file is the tzfile for Asuncion +generated by tzlib-2021e as follows, using the tzlib-2021e zic: +"zic -d DEST -r @1546300800 -L /dev/null -b slim +SOURCE/southamerica". Note that in its type 2 header, it has +two entries in its "time-types" array (types), but only one +entry in its "transition types" array (type_idxs). + +This is valid and expected already in the published RFC8536, and +not even frowned upon: "Local time for timestamps before the +first transition is specified by the first time type (time type +0)" ... "every nonzero local time type index SHOULD appear at +least once in the transition type array". Note the "nonzero ... +index". Until the 2021d zic, index 0 has been shared by the +first valid transition but with 2021d it's separate, set apart +as a placeholder and only "implicitly" indexed. (A draft update +of the RFC mandates that the entry at index 0 is a placeholder +in this case, hence can no longer be shared.) + + * time/tzfile.c (__tzfile_read): Don't assert when no transitions + are found. + +Co-authored-by: Christopher Wong +--- + time/tzfile.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/time/tzfile.c b/time/tzfile.c +index 190a777..8668392 100644 +--- a/time/tzfile.c ++++ b/time/tzfile.c +@@ -431,8 +431,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap) + if (__tzname[0] == NULL) + { + /* This should only happen if there are no transition rules. +- In this case there should be only one single type. */ +- assert (num_types == 1); ++ In this case there's usually only one single type, unless ++ e.g. the data file has a truncated time-range. */ + __tzname[0] = __tzstring (zone_names); + } + if (__tzname[1] == NULL) +-- +1.8.3.1 + diff --git a/timezone-test-case-for-BZ-28707.patch b/timezone-test-case-for-BZ-28707.patch new file mode 100644 index 0000000..2b0b3fe --- /dev/null +++ b/timezone-test-case-for-BZ-28707.patch @@ -0,0 +1,138 @@ +From ebe899af0dc3215159a9c896ac6f35b72a18cb6e Mon Sep 17 00:00:00 2001 +From: Hans-Peter Nilsson +Date: Fri, 17 Dec 2021 21:45:54 +0100 +Subject: [PATCH] timezone: test-case for BZ #28707 + +This test-case is the tzfile for Asuncion generated by +tzlib-2021e as follows, using the tzlib-2021e zic: "zic -d +DEST -r @1546300800 -L /dev/null -b slim +SOURCE/southamerica". Note that in its type 2 header, it +has two entries in its "time-types" array (types), but only +one entry in its "transition types" array (type_idxs). + + * timezone/Makefile, timezone/tst-pr28707.c, + timezone/testdata/gen-XT5.sh: New test. + +Co-authored-by: Christopher Wong +--- + timezone/Makefile | 8 +++++++- + timezone/testdata/gen-XT5.sh | 16 +++++++++++++++ + timezone/tst-bz28707.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 69 insertions(+), 1 deletion(-) + create mode 100755 timezone/testdata/gen-XT5.sh + create mode 100644 timezone/tst-bz28707.c + +diff --git a/timezone/Makefile b/timezone/Makefile +index c624a18..f091663 100644 +--- a/timezone/Makefile ++++ b/timezone/Makefile +@@ -23,7 +23,7 @@ subdir := timezone + include ../Makeconfig + + others := zdump zic +-tests := test-tz tst-timezone tst-tzset ++tests := test-tz tst-timezone tst-tzset tst-bz28707 + + generated-dirs += testdata + +@@ -85,10 +85,12 @@ $(objpfx)tst-timezone.out: $(addprefix $(testdata)/, \ + America/Sao_Paulo Asia/Tokyo \ + Europe/London) + $(objpfx)tst-tzset.out: $(addprefix $(testdata)/XT, 1 2 3 4) ++$(objpfx)tst-bz28707.out: $(testdata)/XT5 + + test-tz-ENV = TZDIR=$(testdata) + tst-timezone-ENV = TZDIR=$(testdata) + tst-tzset-ENV = TZDIR=$(testdata) ++tst-bz28707-ENV = TZDIR=$(testdata) + + # Note this must come second in the deps list for $(built-program-cmd) to work. + zic-deps = $(objpfx)zic $(leapseconds) yearistype +@@ -122,6 +124,10 @@ $(testdata)/XT%: testdata/XT% + $(make-target-directory) + cp $< $@ + ++$(testdata)/XT%: testdata/gen-XT%.sh ++ $(SHELL) $< > $@.tmp ++ mv $@.tmp $@ ++ + $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make + sed -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \ + -e '/TZVERSION=/s|see_Makefile|"$(version)"|' \ +diff --git a/timezone/testdata/gen-XT5.sh b/timezone/testdata/gen-XT5.sh +new file mode 100755 +index 0000000..3cea056 +--- /dev/null ++++ b/timezone/testdata/gen-XT5.sh +@@ -0,0 +1,16 @@ ++#! /bin/sh ++ ++# This test-case is the tzfile for America/Asuncion ++# generated by tzlib-2021e as follows, using the tzlib-2021e ++# zic: "zic -d DEST -r @1546300800 -L /dev/null -b slim ++# SOURCE/southamerica". Note that in its type 2 header, it ++# has two entries in its "time-types" array (types), but ++# only one entry in its "transition types" array ++# (type_idxs). ++ ++printf \ ++'TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'\ ++'\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0TZif2\0\0\0\0\0\0\0\0'\ ++'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\b\0'\ ++'\0\0\0\*\255\200\1\0\0\0\0\0\0\377\377\325\320\1\4-00\0-03\0\n'\ ++'<-04>4<-03>,M10.1.0/0,M3.4.0/0\n' +diff --git a/timezone/tst-bz28707.c b/timezone/tst-bz28707.c +new file mode 100644 +index 0000000..0a9df1e +--- /dev/null ++++ b/timezone/tst-bz28707.c +@@ -0,0 +1,46 @@ ++/* Copyright (C) 2021 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 ++ ++/* Test that we can use a truncated timezone-file, where the time-type ++ at index 0 is not indexed by the transition-types array (and the ++ transition-types array does not contain at least both one DST and one ++ normal time members). */ ++ ++static int ++do_test (void) ++{ ++ if (setenv ("TZ", "XT5", 1)) ++ { ++ puts ("setenv failed."); ++ return 1; ++ } ++ ++ tzset (); ++ ++ return ++ /* Sanity-check that we got the right timezone-name for DST. For ++ normal time, we're likely to get "-00" (the "unspecified" marker), ++ even though the POSIX timezone string says "-04". Let's not test ++ that. */ ++ !(strcmp (tzname[1], "-03") == 0); ++} ++#include +-- +1.8.3.1 + -- Gitee From cc7c79d2a05a75dfd4f9209dbc27386ce469cb66 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 11 Jan 2022 10:20:56 +0800 Subject: [PATCH 41/70] delete macro __filter_GLIBC_PRIVATE which is not support in rpm-4.17 Use arbitrary filtering to control GLIBC_PRIVATE Signed-off-by: Yang Yanchao --- glibc.spec | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/glibc.spec b/glibc.spec index 5cc8051..83350f1 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,4 +1,5 @@ -%global __filter_GLIBC_PRIVATE 1 +%global __requires_exclude GLIBC_PRIVATE +%global __provides_exclude GLIBC_PRIVATE %define rpm_ver_major %(eval "echo `rpm -q rpm |cut -d '-' -f2 |cut -d. -f1`") %define rpm_ver_minor %(eval "echo `rpm -q rpm |cut -d '-' -f2 |cut -d. -f2`") @@ -65,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 41 +Release: 42 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -1360,6 +1361,10 @@ fi %endif %changelog +* Tue Jan 11 2022 Yang Yanchao - 2.34-42 +- delete macro __filter_GLIBC_PRIVATE which is not support in rpm-4.17 + Use arbitrary filtering to control GLIBC_PRIVATE + * Mon Jan 10 2022 Qingqing Li - 2.34-41 - timex: Use 64-bit fields on 32-bit TIMESIZE=64 systems. BZ #28469 - malloc: Handle NULL input to malloc usable size. BZ #28506 -- Gitee From c6eb2400b09d38ec862cc58ab43162a62be774f0 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Tue, 18 Jan 2022 17:04:00 +0800 Subject: [PATCH 42/70] fix CVE-2022-23218 and CVE-2022-23219 --- ...uffer-overflow-in-sunrpc-svcunix_cre.patch | 125 +++++++++++++ ...uffer-overflow-in-sunrpc-clnt_create.patch | 65 +++++++ glibc.spec | 9 +- ...t-Add-the-__sockaddr_un_set-function.patch | 174 ++++++++++++++++++ ...-for-clnt_create-unix-buffer-overflo.patch | 89 +++++++++ 5 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch create mode 100644 CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch create mode 100644 socket-Add-the-__sockaddr_un_set-function.patch create mode 100644 sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch diff --git a/CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch b/CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch new file mode 100644 index 0000000..401059d --- /dev/null +++ b/CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch @@ -0,0 +1,125 @@ +From f545ad4928fa1f27a3075265182b38a4f939a5f7 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 17 Jan 2022 10:21:34 +0100 +Subject: [PATCH] CVE-2022-23218: Buffer overflow in sunrpc svcunix_create (bug + 28768) + +The sunrpc function svcunix_create suffers from a stack-based buffer +overflow with overlong pathname arguments. + +Reviewed-by: Siddhesh Poyarekar +--- + NEWS | 3 +++ + sunrpc/Makefile | 2 +- + sunrpc/svc_unix.c | 11 ++++------- + sunrpc/tst-bug28768.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 50 insertions(+), 8 deletions(-) + create mode 100644 sunrpc/tst-bug28768.c + +diff --git a/NEWS b/NEWS +index 38a9ddb..38802f0 100644 +--- a/NEWS ++++ b/NEWS +@@ -14,6 +14,9 @@ Security related changes: + legacy function could result in a stack-based buffer overflow when + using the "unix" protocol. Reported by Martin Sebor. + ++ CVE-2022-23218: Passing an overlong file name to the svcunix_create ++ legacy function could result in a stack-based buffer overflow. ++ + The following bugs are resolved with this release: + + [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" +diff --git a/sunrpc/Makefile b/sunrpc/Makefile +index 183ef3d..a79a719 100644 +--- a/sunrpc/Makefile ++++ b/sunrpc/Makefile +@@ -65,7 +65,7 @@ shared-only-routines = $(routines) + endif + + tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \ +- tst-udp-nonblocking tst-bug22542 ++ tst-udp-nonblocking tst-bug22542 tst-bug28768 + + xtests := tst-getmyaddr + +diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c +index f2280b4..67177a2 100644 +--- a/sunrpc/svc_unix.c ++++ b/sunrpc/svc_unix.c +@@ -154,7 +154,10 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) + SVCXPRT *xprt; + struct unix_rendezvous *r; + struct sockaddr_un addr; +- socklen_t len = sizeof (struct sockaddr_in); ++ socklen_t len = sizeof (addr); ++ ++ if (__sockaddr_un_set (&addr, path) < 0) ++ return NULL; + + if (sock == RPC_ANYSOCK) + { +@@ -165,12 +168,6 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) + } + madesock = TRUE; + } +- memset (&addr, '\0', sizeof (addr)); +- addr.sun_family = AF_UNIX; +- len = strlen (path) + 1; +- memcpy (addr.sun_path, path, len); +- len += sizeof (addr.sun_family); +- + __bind (sock, (struct sockaddr *) &addr, len); + + if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0 +diff --git a/sunrpc/tst-bug28768.c b/sunrpc/tst-bug28768.c +new file mode 100644 +index 0000000..35a4b7b +--- /dev/null ++++ b/sunrpc/tst-bug28768.c +@@ -0,0 +1,42 @@ ++/* Test to verify that long path is rejected by svcunix_create (bug 28768). ++ Copyright (C) 2022 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 ++ ++/* svcunix_create does not have a default version in linkobj/libc.so. */ ++compat_symbol_reference (libc, svcunix_create, svcunix_create, GLIBC_2_1); ++ ++static int ++do_test (void) ++{ ++ char pathname[109]; ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ ++ errno = 0; ++ TEST_VERIFY (svcunix_create (RPC_ANYSOCK, 4096, 4096, pathname) == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + diff --git a/CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch b/CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch new file mode 100644 index 0000000..f5b0488 --- /dev/null +++ b/CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch @@ -0,0 +1,65 @@ +From 226b46770c82899b555986583294b049c6ec9b40 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 17 Jan 2022 10:21:34 +0100 +Subject: [PATCH] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for + "unix" (bug 22542) + +Processing an overlong pathname in the sunrpc clnt_create function +results in a stack-based buffer overflow. + +Reviewed-by: Siddhesh Poyarekar + +--- + NEWS | 14 ++++++++++++++ + sunrpc/clnt_gen.c | 10 +++++++--- + 2 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/NEWS b/NEWS +index 3c610744..dbe6f086 100644 +--- a/NEWS ++++ b/NEWS +@@ -4,6 +4,20 @@ See the end for copying conditions. + + Please send GNU C library bug reports via + using `glibc' in the "product" field. ++ ++^L ++Version 2.34.1 ++ ++Security related changes: ++ ++ CVE-2022-23219: Passing an overlong file name to the clnt_create ++ legacy function could result in a stack-based buffer overflow when ++ using the "unix" protocol. Reported by Martin Sebor. ++ ++The following bugs are resolved with this release: ++ ++ [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" ++ + + Version 2.34 + +diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c +index 13ced899..b44357cd 100644 +--- a/sunrpc/clnt_gen.c ++++ b/sunrpc/clnt_gen.c +@@ -57,9 +57,13 @@ clnt_create (const char *hostname, u_long prog, u_long vers, + + if (strcmp (proto, "unix") == 0) + { +- memset ((char *)&sun, 0, sizeof (sun)); +- sun.sun_family = AF_UNIX; +- strcpy (sun.sun_path, hostname); ++ if (__sockaddr_un_set (&sun, hostname) < 0) ++ { ++ struct rpc_createerr *ce = &get_rpc_createerr (); ++ ce->cf_stat = RPC_SYSTEMERROR; ++ ce->cf_error.re_errno = errno; ++ return NULL; ++ } + sock = RPC_ANYSOCK; + client = clntunix_create (&sun, prog, vers, &sock, 0, 0); + if (client == NULL) +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 83350f1..c7e6632 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 42 +Release: 43 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -159,6 +159,10 @@ Patch71: AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch Patch72: Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch Patch73: timezone-handle-truncated-timezones-from-tzcode-2021.patch Patch74: timezone-test-case-for-BZ-28707.patch +Patch75: socket-Add-the-__sockaddr_un_set-function.patch +Patch76: CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch +Patch77: sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch +Patch78: CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1361,6 +1365,9 @@ fi %endif %changelog +*Tue Jan 18 Qingqing Li - 2.34-43 +- fix CVE-2022-23218 and CVE-2022-23219 + * Tue Jan 11 2022 Yang Yanchao - 2.34-42 - delete macro __filter_GLIBC_PRIVATE which is not support in rpm-4.17 Use arbitrary filtering to control GLIBC_PRIVATE diff --git a/socket-Add-the-__sockaddr_un_set-function.patch b/socket-Add-the-__sockaddr_un_set-function.patch new file mode 100644 index 0000000..0b0997b --- /dev/null +++ b/socket-Add-the-__sockaddr_un_set-function.patch @@ -0,0 +1,174 @@ +From e368b12f6c16b6888dda99ba641e999b9c9643c8 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 17 Jan 2022 10:21:34 +0100 +Subject: [PATCH] socket: Add the __sockaddr_un_set function + +Reviewed-by: Siddhesh Poyarekar +--- + include/sys/un.h | 12 +++++++++ + socket/Makefile | 6 ++++- + socket/sockaddr_un_set.c | 41 +++++++++++++++++++++++++++++ + socket/tst-sockaddr_un_set.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 120 insertions(+), 1 deletion(-) + create mode 100644 socket/sockaddr_un_set.c + create mode 100644 socket/tst-sockaddr_un_set.c + +diff --git a/include/sys/un.h b/include/sys/un.h +index bdbee99..152afd9 100644 +--- a/include/sys/un.h ++++ b/include/sys/un.h +@@ -1 +1,13 @@ + #include ++ ++#ifndef _ISOMAC ++ ++/* Set ADDR->sun_family to AF_UNIX and ADDR->sun_path to PATHNAME. ++ Return 0 on success or -1 on failure (due to overlong PATHNAME). ++ The caller should always use sizeof (struct sockaddr_un) as the ++ socket address length, disregaring the length of PATHNAME. ++ Only concrete (non-abstract) pathnames are supported. */ ++int __sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) ++ attribute_hidden; ++ ++#endif /* _ISOMAC */ +diff --git a/socket/Makefile b/socket/Makefile +index 39333e1..156eec6 100644 +--- a/socket/Makefile ++++ b/socket/Makefile +@@ -29,13 +29,17 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \ + routines := accept bind connect getpeername getsockname getsockopt \ + listen recv recvfrom recvmsg send sendmsg sendto \ + setsockopt shutdown socket socketpair isfdtype opensock \ +- sockatmark accept4 recvmmsg sendmmsg ++ sockatmark accept4 recvmmsg sendmmsg sockaddr_un_set + + tests := \ + tst-accept4 \ + tst-sockopt \ + # tests + ++tests-internal := \ ++ tst-sockaddr_un_set \ ++ # tests-internal ++ + tests-time64 := \ + tst-sockopt-time64 \ + # tests +diff --git a/socket/sockaddr_un_set.c b/socket/sockaddr_un_set.c +new file mode 100644 +index 0000000..0bd40dc +--- /dev/null ++++ b/socket/sockaddr_un_set.c +@@ -0,0 +1,41 @@ ++/* Set the sun_path member of struct sockaddr_un. ++ Copyright (C) 2022 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 ++ ++int ++__sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) ++{ ++ size_t name_length = strlen (pathname); ++ ++ /* The kernel supports names of exactly sizeof (addr->sun_path) ++ bytes, without a null terminator, but userspace does not; see the ++ SUN_LEN macro. */ ++ if (name_length >= sizeof (addr->sun_path)) ++ { ++ __set_errno (EINVAL); /* Error code used by the kernel. */ ++ return -1; ++ } ++ ++ addr->sun_family = AF_UNIX; ++ memcpy (addr->sun_path, pathname, name_length + 1); ++ return 0; ++} +diff --git a/socket/tst-sockaddr_un_set.c b/socket/tst-sockaddr_un_set.c +new file mode 100644 +index 0000000..29c2a81 +--- /dev/null ++++ b/socket/tst-sockaddr_un_set.c +@@ -0,0 +1,62 @@ ++/* Test the __sockaddr_un_set function. ++ Copyright (C) 2022 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 ++ . */ ++ ++/* Re-compile the function because the version in libc is not ++ exported. */ ++#include "sockaddr_un_set.c" ++ ++#include ++ ++static int ++do_test (void) ++{ ++ struct sockaddr_un sun; ++ ++ memset (&sun, 0xcc, sizeof (sun)); ++ __sockaddr_un_set (&sun, ""); ++ TEST_COMPARE (sun.sun_family, AF_UNIX); ++ TEST_COMPARE (__sockaddr_un_set (&sun, ""), 0); ++ ++ memset (&sun, 0xcc, sizeof (sun)); ++ TEST_COMPARE (__sockaddr_un_set (&sun, "/example"), 0); ++ TEST_COMPARE_STRING (sun.sun_path, "/example"); ++ ++ { ++ char pathname[108]; /* Length of sun_path (ABI constant). */ ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ memset (&sun, 0xcc, sizeof (sun)); ++ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), 0); ++ TEST_COMPARE (sun.sun_family, AF_UNIX); ++ TEST_COMPARE_STRING (sun.sun_path, pathname); ++ } ++ ++ { ++ char pathname[109]; ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ memset (&sun, 0xcc, sizeof (sun)); ++ errno = 0; ++ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), -1); ++ TEST_COMPARE (errno, EINVAL); ++ } ++ ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + diff --git a/sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch b/sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch new file mode 100644 index 0000000..8d2bec4 --- /dev/null +++ b/sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch @@ -0,0 +1,89 @@ +From ef972a4c50014a16132b5c75571cfb6b30bef136 Mon Sep 17 00:00:00 2001 +From: Martin Sebor +Date: Mon, 17 Jan 2022 10:21:34 +0100 +Subject: [PATCH] sunrpc: Test case for clnt_create "unix" buffer overflow (bug + 22542) + +Reviewed-by: Siddhesh Poyarekar +--- + sunrpc/Makefile | 5 ++++- + sunrpc/tst-bug22542.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+), 1 deletion(-) + create mode 100644 sunrpc/tst-bug22542.c + +diff --git a/sunrpc/Makefile b/sunrpc/Makefile +index 9a31fe4..183ef3d 100644 +--- a/sunrpc/Makefile ++++ b/sunrpc/Makefile +@@ -65,7 +65,8 @@ shared-only-routines = $(routines) + endif + + tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \ +- tst-udp-nonblocking ++ tst-udp-nonblocking tst-bug22542 ++ + xtests := tst-getmyaddr + + ifeq ($(have-thread-library),yes) +@@ -110,6 +111,8 @@ $(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-udp-garbage: \ + $(common-objpfx)linkobj/libc.so $(shared-thread-library) + ++$(objpfx)tst-bug22542: $(common-objpfx)linkobj/libc.so ++ + else # !have-GLIBC_2.31 + + routines = $(routines-for-nss) +diff --git a/sunrpc/tst-bug22542.c b/sunrpc/tst-bug22542.c +new file mode 100644 +index 0000000..d6cd797 +--- /dev/null ++++ b/sunrpc/tst-bug22542.c +@@ -0,0 +1,44 @@ ++/* Test to verify that overlong hostname is rejected by clnt_create ++ and doesn't cause a buffer overflow (bug 22542). ++ ++ Copyright (C) 2022 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 ++ ++static int ++do_test (void) ++{ ++ /* Create an arbitrary hostname that's longer than fits in sun_path. */ ++ char name [sizeof ((struct sockaddr_un*)0)->sun_path * 2]; ++ memset (name, 'x', sizeof name - 1); ++ name [sizeof name - 1] = '\0'; ++ ++ errno = 0; ++ CLIENT *clnt = clnt_create (name, 0, 0, "unix"); ++ ++ TEST_VERIFY (clnt == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ return 0; ++} ++ ++#include +-- +1.8.3.1 + -- Gitee From 2fe3fe9429213335992d276e3081c66ada460ced Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Fri, 21 Jan 2022 10:40:22 +0800 Subject: [PATCH 43/70] support: Add check for TID zero in support_wait_for_thread_exit --- glibc.spec | 8 +++- ...k-for-TID-zero-in-support_wait_for_t.patch | 42 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 support-Add-check-for-TID-zero-in-support_wait_for_t.patch diff --git a/glibc.spec b/glibc.spec index c7e6632..3527254 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 43 +Release: 44 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -163,6 +163,7 @@ Patch75: socket-Add-the-__sockaddr_un_set-function.patch Patch76: CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch Patch77: sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch Patch78: CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch +Patch79: support-Add-check-for-TID-zero-in-support_wait_for_t.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1365,7 +1366,10 @@ fi %endif %changelog -*Tue Jan 18 Qingqing Li - 2.34-43 +* Fri Jan 21 Qingqing Li - 2.34-44 +- support: Add check for TID zero in support_wait_for_thread_exit + +* Tue Jan 18 Qingqing Li - 2.34-43 - fix CVE-2022-23218 and CVE-2022-23219 * Tue Jan 11 2022 Yang Yanchao - 2.34-42 diff --git a/support-Add-check-for-TID-zero-in-support_wait_for_t.patch b/support-Add-check-for-TID-zero-in-support_wait_for_t.patch new file mode 100644 index 0000000..faccebf --- /dev/null +++ b/support-Add-check-for-TID-zero-in-support_wait_for_t.patch @@ -0,0 +1,42 @@ +From 176c88f5214d8107d330971cbbfbbba5186a111f Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 1 Oct 2021 18:16:41 +0200 +Subject: [PATCH] support: Add check for TID zero in + support_wait_for_thread_exit + +Some kernel versions (observed with kernel 5.14 and earlier) can list +"0" entries in /proc/self/task. This happens when a thread exits +while the task list is being constructed. Treat this entry as not +present, like the proposed kernel patch does: + +[PATCH] procfs: Do not list TID 0 in /proc//task + + +Fixes commit 032d74eaf6179100048a5bf0ce942e97dc8b9a60 ("support: Add +support_wait_for_thread_exit"). + +Reviewed-by: Carlos O'Donell +Tested-by: Carlos O'Donell +--- + support/support_wait_for_thread_exit.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/support/support_wait_for_thread_exit.c b/support/support_wait_for_thread_exit.c +index 658a813..5e3be42 100644 +--- a/support/support_wait_for_thread_exit.c ++++ b/support/support_wait_for_thread_exit.c +@@ -43,7 +43,10 @@ support_wait_for_thread_exit (void) + return; + } + +- if (strcmp (e->d_name, ".") == 0 || strcmp (e->d_name, "..") == 0) ++ /* In some kernels, "0" entries denote a thread that has just ++ exited. */ ++ if (strcmp (e->d_name, ".") == 0 || strcmp (e->d_name, "..") == 0 ++ || strcmp (e->d_name, "0") == 0) + continue; + + int task_tid = atoi (e->d_name); +-- +1.8.3.1 + -- Gitee From 6e134fd0a5978ee9eb5a6caef2cede4d822ae59e Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Fri, 21 Jan 2022 09:17:17 +0800 Subject: [PATCH 44/70] disable check-installed-headers-c and check-installed-headers-cxx and delete glibc-benchtest to improve build speed Signed-off-by: Yang Yanchao --- ...talled-headers-c-and-check-installed.patch | 60 +++++++++++++++++++ glibc.spec | 9 ++- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 delete-check-installed-headers-c-and-check-installed.patch diff --git a/delete-check-installed-headers-c-and-check-installed.patch b/delete-check-installed-headers-c-and-check-installed.patch new file mode 100644 index 0000000..b4fa934 --- /dev/null +++ b/delete-check-installed-headers-c-and-check-installed.patch @@ -0,0 +1,60 @@ +From dd2efa50d197e2205acd8edbf29aba717d71bdbb Mon Sep 17 00:00:00 2001 +From: Yang Yanchao +Date: Tue, 4 Jan 2022 19:55:28 +0800 +Subject: [PATCH] testsuit: delete check-installed-headers-c and check-installed-headers-cxx + +check-installed-headers-c and check-installed-headers-cxx checked at CI +and can be deleted during building + +--- + Makefile | 4 ++-- + Rules | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Makefile b/Makefile +index f98d5a9e..83200a75 100644 +--- a/Makefile ++++ b/Makefile +@@ -532,7 +532,7 @@ $(objpfx)check-local-headers.out: scripts/check-local-headers.sh + + ifneq "$(headers)" "" + # Special test of all the installed headers in this directory. +-tests-special += $(objpfx)check-installed-headers-c.out ++# tests-special += $(objpfx)check-installed-headers-c.out + libof-check-installed-headers-c := testsuite + $(objpfx)check-installed-headers-c.out: \ + scripts/check-installed-headers.sh $(headers) +@@ -542,7 +541,7 @@ $(objpfx)check-installed-headers-c.out: \ + $(evaluate-test) + + ifneq "$(CXX)" "" +-tests-special += $(objpfx)check-installed-headers-cxx.out ++# tests-special += $(objpfx)check-installed-headers-cxx.out + libof-check-installed-headers-cxx := testsuite + $(objpfx)check-installed-headers-cxx.out: \ + scripts/check-installed-headers.sh $(headers) +diff --git a/Rules b/Rules +index b1137afe..ca29abd7 100644 +--- a/Rules ++++ b/Rules +@@ -84,7 +84,7 @@ common-generated += dummy.o dummy.c + ifneq "$(headers)" "" + # Test that all of the headers installed by this directory can be compiled + # in isolation. +-tests-special += $(objpfx)check-installed-headers-c.out ++# tests-special += $(objpfx)check-installed-headers-c.out + libof-check-installed-headers-c := testsuite + $(objpfx)check-installed-headers-c.out: \ + $(..)scripts/check-installed-headers.sh $(headers) +@@ -96,7 +95,7 @@ $(objpfx)check-installed-headers-c.out: \ + ifneq "$(CXX)" "" + # If a C++ compiler is available, also test that they can be compiled + # in isolation as C++. +-tests-special += $(objpfx)check-installed-headers-cxx.out ++# tests-special += $(objpfx)check-installed-headers-cxx.out + libof-check-installed-headers-cxx := testsuite + $(objpfx)check-installed-headers-cxx.out: \ + $(..)scripts/check-installed-headers.sh $(headers) +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 3527254..3cbe88b 100644 --- a/glibc.spec +++ b/glibc.spec @@ -28,7 +28,7 @@ # - Default: Always run valgrind tests if there is architecture support. ############################################################################## %bcond_without testsuite -%bcond_without benchtests +%bcond_with benchtests %bcond_with bootstrap %bcond_with werror %bcond_without docs @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 44 +Release: 45 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -176,6 +176,7 @@ Patch9007: 0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch Patch9008: 0007-add-lowlevellock_2_17_c.patch Patch9009: 0008-add-pause_nocancel_2_17.patch Patch9010: 0009-add-unwind-with-longjmp.patch +Patch9011: delete-check-installed-headers-c-and-check-installed.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1366,6 +1367,10 @@ fi %endif %changelog +* Fri Jan 21 Yang Yanchao - 2.34-45 +- disable check-installed-headers-c and check-installed-headers-cxx + and delete glibc-benchtest to improve build speed + * Fri Jan 21 Qingqing Li - 2.34-44 - support: Add check for TID zero in support_wait_for_thread_exit -- Gitee From 120d11e601cd89d9e5636089a03d121491b238a6 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 24 Jan 2022 15:02:34 +0800 Subject: [PATCH 45/70] fix CVE-2021-3998 and CVE-2021-3999 --- ...r-namespace-support-in-io-tst-getcwd.patch | 53 +++ ...o-to-ERANGE-for-size-1-CVE-2021-3999.patch | 355 ++++++++++++++++++ glibc.spec | 18 +- ...no-to-ENAMETOOLONG-for-result-larger.patch | 138 +++++++ ...formatting-of-tests-list-in-Makefile.patch | 178 +++++++++ stdlib-Sort-tests-in-Makefile.patch | 126 +++++++ ...ers-to-create-paths-longer-than-PATH.patch | 282 ++++++++++++++ tst-realpath-toolong-Fix-hurd-build.patch | 31 ++ 8 files changed, 1177 insertions(+), 4 deletions(-) create mode 100644 Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch create mode 100644 getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch create mode 100644 realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch create mode 100644 stdlib-Fix-formatting-of-tests-list-in-Makefile.patch create mode 100644 stdlib-Sort-tests-in-Makefile.patch create mode 100644 support-Add-helpers-to-create-paths-longer-than-PATH.patch create mode 100644 tst-realpath-toolong-Fix-hurd-build.patch diff --git a/Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch b/Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch new file mode 100644 index 0000000..9ae3ffb --- /dev/null +++ b/Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch @@ -0,0 +1,53 @@ +From 3438bbca90895d32825a52e31a77dc44d273c1c1 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 24 Jan 2022 18:14:24 +0100 +Subject: [PATCH] Linux: Detect user namespace support in + io/tst-getcwd-smallbuff + +Otherwise the test fails with certain container runtimes. + +Reviewed-by: Siddhesh Poyarekar +(cherry picked from commit 5b8e7980c5dabd9aaefeba4f0208baa8cf7653ee) +--- + sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +index d460d6e..55362f6 100644 +--- a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c ++++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -188,6 +189,23 @@ do_test (void) + xmkdir (MOUNT_NAME, S_IRWXU); + atexit (do_cleanup); + ++ /* Check whether user namespaces are supported. */ ++ { ++ pid_t pid = xfork (); ++ if (pid == 0) ++ { ++ if (unshare (CLONE_NEWUSER | CLONE_NEWNS) != 0) ++ _exit (EXIT_UNSUPPORTED); ++ else ++ _exit (0); ++ } ++ int status; ++ xwaitpid (pid, &status, 0); ++ TEST_VERIFY_EXIT (WIFEXITED (status)); ++ if (WEXITSTATUS (status) != 0) ++ return WEXITSTATUS (status); ++ } ++ + TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0); + pid_t child_pid = xclone (child_func, NULL, child_stack, + sizeof (child_stack), +-- +1.8.3.1 + diff --git a/getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch b/getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch new file mode 100644 index 0000000..6d258a2 --- /dev/null +++ b/getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch @@ -0,0 +1,355 @@ +From 472e799a5f2102bc0c3206dbd5a801765fceb39c Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Fri, 21 Jan 2022 23:32:56 +0530 +Subject: [PATCH] getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999) + +No valid path returned by getcwd would fit into 1 byte, so reject the +size early and return NULL with errno set to ERANGE. This change is +prompted by CVE-2021-3999, which describes a single byte buffer +underflow and overflow when all of the following conditions are met: + +- The buffer size (i.e. the second argument of getcwd) is 1 byte +- The current working directory is too long +- '/' is also mounted on the current working directory + +Sequence of events: + +- In sysdeps/unix/sysv/linux/getcwd.c, the syscall returns ENAMETOOLONG + because the linux kernel checks for name length before it checks + buffer size + +- The code falls back to the generic getcwd in sysdeps/posix + +- In the generic func, the buf[0] is set to '\0' on line 250 + +- this while loop on line 262 is bypassed: + + while (!(thisdev == rootdev && thisino == rootino)) + + since the rootfs (/) is bind mounted onto the directory and the flow + goes on to line 449, where it puts a '/' in the byte before the + buffer. + +- Finally on line 458, it moves 2 bytes (the underflowed byte and the + '\0') to the buf[0] and buf[1], resulting in a 1 byte buffer overflow. + +- buf is returned on line 469 and errno is not set. + +This resolves BZ #28769. + +Reviewed-by: Andreas Schwab +Reviewed-by: Adhemerval Zanella +Signed-off-by: Qualys Security Advisory +Signed-off-by: Siddhesh Poyarekar +(cherry picked from commit 23e0e8f5f1fb5ed150253d986ecccdc90c2dcd5e) +--- + NEWS | 6 + + sysdeps/posix/getcwd.c | 7 + + sysdeps/unix/sysv/linux/Makefile | 7 +- + .../unix/sysv/linux/tst-getcwd-smallbuff.c | 241 ++++++++++++++++++ + 4 files changed, 260 insertions(+), 1 deletion(-) + create mode 100644 sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c + +diff --git a/NEWS b/NEWS +index b4f81c2668..8d7467d2c1 100644 +--- a/NEWS ++++ b/NEWS +@@ -20,6 +20,12 @@ Security related changes: + function could result in a memory leak and potential access of + uninitialized memory. Reported by Qualys. + ++ CVE-2021-3999: Passing a buffer of size exactly 1 byte to the getcwd ++ function may result in an off-by-one buffer underflow and overflow ++ when the current working directory is longer than PATH_MAX and also ++ corresponds to the / directory through an unprivileged mount ++ namespace. Reported by Qualys. ++ + The following bugs are resolved with this release: + + [12889] nptl: Fix race between pthread_kill and thread exit +diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c +index 13680026ff..b6984a382c 100644 +--- a/sysdeps/posix/getcwd.c ++++ b/sysdeps/posix/getcwd.c +@@ -187,6 +187,13 @@ __getcwd_generic (char *buf, size_t size) + size_t allocated = size; + size_t used; + ++ /* A size of 1 byte is never useful. */ ++ if (allocated == 1) ++ { ++ __set_errno (ERANGE); ++ return NULL; ++ } ++ + #if HAVE_MINIMALLY_WORKING_GETCWD + /* If AT_FDCWD is not defined, the algorithm below is O(N**2) and + this is much slower than the system getcwd (at least on +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 76ad06361c..9380d3848d 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -331,7 +331,12 @@ sysdep_routines += xstatconv internal_statvfs \ + + sysdep_headers += bits/fcntl-linux.h + +-tests += tst-fallocate tst-fallocate64 tst-o_path-locks ++tests += \ ++ tst-fallocate \ ++ tst-fallocate64 \ ++ tst-getcwd-smallbuff \ ++ tst-o_path-locks \ ++# tests + endif + + ifeq ($(subdir),elf) +diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +new file mode 100644 +index 0000000000..d460d6e766 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +@@ -0,0 +1,241 @@ ++/* Verify that getcwd returns ERANGE for size 1 byte and does not underflow ++ buffer when the CWD is too long and is also a mount target of /. See bug ++ #28769 or CVE-2021-3999 for more context. ++ Copyright The GNU Toolchain Authors. ++ 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static char *base; ++#define BASENAME "tst-getcwd-smallbuff" ++#define MOUNT_NAME "mpoint" ++static int sockfd[2]; ++ ++static void ++do_cleanup (void) ++{ ++ support_chdir_toolong_temp_directory (base); ++ TEST_VERIFY_EXIT (rmdir (MOUNT_NAME) == 0); ++ free (base); ++} ++ ++static void ++send_fd (const int sock, const int fd) ++{ ++ struct msghdr msg = {0}; ++ union ++ { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE (sizeof (int))]; ++ } cmsgbuf = {0}; ++ struct cmsghdr *cmsg; ++ struct iovec vec; ++ char ch = 'A'; ++ ssize_t n; ++ ++ msg.msg_control = &cmsgbuf.buf; ++ msg.msg_controllen = sizeof (cmsgbuf.buf); ++ ++ cmsg = CMSG_FIRSTHDR (&msg); ++ cmsg->cmsg_len = CMSG_LEN (sizeof (int)); ++ cmsg->cmsg_level = SOL_SOCKET; ++ cmsg->cmsg_type = SCM_RIGHTS; ++ memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd)); ++ ++ vec.iov_base = &ch; ++ vec.iov_len = 1; ++ msg.msg_iov = &vec; ++ msg.msg_iovlen = 1; ++ ++ while ((n = sendmsg (sock, &msg, 0)) == -1 && errno == EINTR); ++ ++ TEST_VERIFY_EXIT (n == 1); ++} ++ ++static int ++recv_fd (const int sock) ++{ ++ struct msghdr msg = {0}; ++ union ++ { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE(sizeof(int))]; ++ } cmsgbuf = {0}; ++ struct cmsghdr *cmsg; ++ struct iovec vec; ++ ssize_t n; ++ char ch = '\0'; ++ int fd = -1; ++ ++ vec.iov_base = &ch; ++ vec.iov_len = 1; ++ msg.msg_iov = &vec; ++ msg.msg_iovlen = 1; ++ ++ msg.msg_control = &cmsgbuf.buf; ++ msg.msg_controllen = sizeof (cmsgbuf.buf); ++ ++ while ((n = recvmsg (sock, &msg, 0)) == -1 && errno == EINTR); ++ if (n != 1 || ch != 'A') ++ return -1; ++ ++ cmsg = CMSG_FIRSTHDR (&msg); ++ if (cmsg == NULL) ++ return -1; ++ if (cmsg->cmsg_type != SCM_RIGHTS) ++ return -1; ++ memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd)); ++ if (fd < 0) ++ return -1; ++ return fd; ++} ++ ++static int ++child_func (void * const arg) ++{ ++ xclose (sockfd[0]); ++ const int sock = sockfd[1]; ++ char ch; ++ ++ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1); ++ TEST_VERIFY_EXIT (ch == '1'); ++ ++ if (mount ("/", MOUNT_NAME, NULL, MS_BIND | MS_REC, NULL)) ++ FAIL_EXIT1 ("mount failed: %m\n"); ++ const int fd = xopen ("mpoint", ++ O_RDONLY | O_PATH | O_DIRECTORY | O_NOFOLLOW, 0); ++ ++ send_fd (sock, fd); ++ xclose (fd); ++ ++ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1); ++ TEST_VERIFY_EXIT (ch == 'a'); ++ ++ xclose (sock); ++ return 0; ++} ++ ++static void ++update_map (char * const mapping, const char * const map_file) ++{ ++ const size_t map_len = strlen (mapping); ++ ++ const int fd = xopen (map_file, O_WRONLY, 0); ++ xwrite (fd, mapping, map_len); ++ xclose (fd); ++} ++ ++static void ++proc_setgroups_write (const long child_pid, const char * const str) ++{ ++ const size_t str_len = strlen(str); ++ ++ char setgroups_path[sizeof ("/proc//setgroups") + INT_STRLEN_BOUND (long)]; ++ ++ snprintf (setgroups_path, sizeof (setgroups_path), ++ "/proc/%ld/setgroups", child_pid); ++ ++ const int fd = open (setgroups_path, O_WRONLY); ++ ++ if (fd < 0) ++ { ++ TEST_VERIFY_EXIT (errno == ENOENT); ++ FAIL_UNSUPPORTED ("/proc/%ld/setgroups not found\n", child_pid); ++ } ++ ++ xwrite (fd, str, str_len); ++ xclose(fd); ++} ++ ++static char child_stack[1024 * 1024]; ++ ++int ++do_test (void) ++{ ++ base = support_create_and_chdir_toolong_temp_directory (BASENAME); ++ ++ xmkdir (MOUNT_NAME, S_IRWXU); ++ atexit (do_cleanup); ++ ++ TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0); ++ pid_t child_pid = xclone (child_func, NULL, child_stack, ++ sizeof (child_stack), ++ CLONE_NEWUSER | CLONE_NEWNS | SIGCHLD); ++ ++ xclose (sockfd[1]); ++ const int sock = sockfd[0]; ++ ++ char map_path[sizeof ("/proc//uid_map") + INT_STRLEN_BOUND (long)]; ++ char map_buf[sizeof ("0 1") + INT_STRLEN_BOUND (long)]; ++ ++ snprintf (map_path, sizeof (map_path), "/proc/%ld/uid_map", ++ (long) child_pid); ++ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getuid()); ++ update_map (map_buf, map_path); ++ ++ proc_setgroups_write ((long) child_pid, "deny"); ++ snprintf (map_path, sizeof (map_path), "/proc/%ld/gid_map", ++ (long) child_pid); ++ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getgid()); ++ update_map (map_buf, map_path); ++ ++ TEST_VERIFY_EXIT (send (sock, "1", 1, MSG_NOSIGNAL) == 1); ++ const int fd = recv_fd (sock); ++ TEST_VERIFY_EXIT (fd >= 0); ++ TEST_VERIFY_EXIT (fchdir (fd) == 0); ++ ++ static char buf[2 * 10 + 1]; ++ memset (buf, 'A', sizeof (buf)); ++ ++ /* Finally, call getcwd and check if it resulted in a buffer underflow. */ ++ char * cwd = getcwd (buf + sizeof (buf) / 2, 1); ++ TEST_VERIFY (cwd == NULL); ++ TEST_VERIFY (errno == ERANGE); ++ ++ for (int i = 0; i < sizeof (buf); i++) ++ if (buf[i] != 'A') ++ { ++ printf ("buf[%d] = %02x\n", i, (unsigned int) buf[i]); ++ support_record_failure (); ++ } ++ ++ TEST_VERIFY_EXIT (send (sock, "a", 1, MSG_NOSIGNAL) == 1); ++ xclose (sock); ++ TEST_VERIFY_EXIT (xwaitpid (child_pid, NULL, 0) == child_pid); ++ ++ return 0; ++} ++ ++#define CLEANUP_HANDLER do_cleanup ++#include +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 3cbe88b..1b25cb6 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 45 +Release: 46 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -164,6 +164,13 @@ Patch76: CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch Patch77: sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch Patch78: CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch Patch79: support-Add-check-for-TID-zero-in-support_wait_for_t.patch +Patch80: support-Add-helpers-to-create-paths-longer-than-PATH.patch +Patch81: stdlib-Sort-tests-in-Makefile.patch +Patch82: stdlib-Fix-formatting-of-tests-list-in-Makefile.patch +Patch83: realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch +Patch84: tst-realpath-toolong-Fix-hurd-build.patch +Patch85: getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch +Patch86: Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1367,14 +1374,17 @@ fi %endif %changelog -* Fri Jan 21 Yang Yanchao - 2.34-45 +* Tue Jan 25 2022 Qingqing Li - 2.34-46 +- fix CVE-2021-3998 and CVE-2021-3999 + +* Fri Jan 21 2022 Yang Yanchao - 2.34-45 - disable check-installed-headers-c and check-installed-headers-cxx and delete glibc-benchtest to improve build speed -* Fri Jan 21 Qingqing Li - 2.34-44 +* Fri Jan 21 2022 Qingqing Li - 2.34-44 - support: Add check for TID zero in support_wait_for_thread_exit -* Tue Jan 18 Qingqing Li - 2.34-43 +* Tue Jan 18 2022 Qingqing Li - 2.34-43 - fix CVE-2022-23218 and CVE-2022-23219 * Tue Jan 11 2022 Yang Yanchao - 2.34-42 diff --git a/realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch b/realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch new file mode 100644 index 0000000..c802dd9 --- /dev/null +++ b/realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch @@ -0,0 +1,138 @@ +From f7a79879c0b2bef0dadd6caaaeeb0d26423e04e5 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Thu, 13 Jan 2022 11:28:36 +0530 +Subject: [PATCH] realpath: Set errno to ENAMETOOLONG for result larger than + PATH_MAX [BZ #28770] + +realpath returns an allocated string when the result exceeds PATH_MAX, +which is unexpected when its second argument is not NULL. This results +in the second argument (resolved) being uninitialized and also results +in a memory leak since the caller expects resolved to be the same as the +returned value. + +Return NULL and set errno to ENAMETOOLONG if the result exceeds +PATH_MAX. This fixes [BZ #28770], which is CVE-2021-3998. + +Reviewed-by: Adhemerval Zanella +Signed-off-by: Siddhesh Poyarekar +(cherry picked from commit ee8d5e33adb284601c00c94687bc907e10aec9bb) +--- + NEWS | 6 +++++ + stdlib/Makefile | 1 + + stdlib/canonicalize.c | 12 +++++++++-- + stdlib/tst-realpath-toolong.c | 49 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 65 insertions(+), 2 deletions(-) + create mode 100644 stdlib/tst-realpath-toolong.c + +diff --git a/NEWS b/NEWS +index 711420cb..db50b2af 100644 +--- a/NEWS ++++ b/NEWS +@@ -17,8 +17,14 @@ Security related changes: + CVE-2022-23218: Passing an overlong file name to the svcunix_create + legacy function could result in a stack-based buffer overflow. + ++ CVE-2021-3998: Passing a path longer than PATH_MAX to the realpath ++ function could result in a memory leak and potential access of ++ uninitialized memory. Reported by Qualys. ++ + The following bugs are resolved with this release: + ++ [12889] nptl: Fix race between pthread_kill and thread exit ++ [19193] nptl: pthread_kill, pthread_cancel should not fail after exit + [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" + + +diff --git a/stdlib/Makefile b/stdlib/Makefile +index 9bb5c221..a4ac30d1 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -109,6 +109,7 @@ tests := \ + tst-random \ + tst-random2 \ + tst-realpath \ ++ tst-realpath-toolong \ + tst-secure-getenv \ + tst-setcontext \ + tst-setcontext2 \ +diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c +index 698f9ede..7a23a51b 100644 +--- a/stdlib/canonicalize.c ++++ b/stdlib/canonicalize.c +@@ -400,8 +400,16 @@ realpath_stk (const char *name, char *resolved, + + error: + *dest++ = '\0'; +- if (resolved != NULL && dest - rname <= get_path_max ()) +- rname = strcpy (resolved, rname); ++ if (resolved != NULL) ++ { ++ if (dest - rname <= get_path_max ()) ++ rname = strcpy (resolved, rname); ++ else ++ { ++ failed = true; ++ __set_errno (ENAMETOOLONG); ++ } ++ } + + error_nomem: + scratch_buffer_free (&extra_buffer); +diff --git a/stdlib/tst-realpath-toolong.c b/stdlib/tst-realpath-toolong.c +new file mode 100644 +index 00000000..8bed7724 +--- /dev/null ++++ b/stdlib/tst-realpath-toolong.c +@@ -0,0 +1,49 @@ ++/* Verify that realpath returns NULL with ENAMETOOLONG if the result exceeds ++ NAME_MAX. ++ Copyright The GNU Toolchain Authors. ++ 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 ++#include ++#include ++#include ++ ++#define BASENAME "tst-realpath-toolong." ++ ++int ++do_test (void) ++{ ++ char *base = support_create_and_chdir_toolong_temp_directory (BASENAME); ++ ++ char buf[PATH_MAX + 1]; ++ const char *res = realpath (".", buf); ++ ++ /* canonicalize.c states that if the real path is >= PATH_MAX, then ++ realpath returns NULL and sets ENAMETOOLONG. */ ++ TEST_VERIFY (res == NULL); ++ TEST_VERIFY (errno == ENAMETOOLONG); ++ ++ free (base); ++ return 0; ++} ++ ++#include +-- +2.27.0 + diff --git a/stdlib-Fix-formatting-of-tests-list-in-Makefile.patch b/stdlib-Fix-formatting-of-tests-list-in-Makefile.patch new file mode 100644 index 0000000..db49888 --- /dev/null +++ b/stdlib-Fix-formatting-of-tests-list-in-Makefile.patch @@ -0,0 +1,178 @@ +From 73c362840c4efde45125a6c27bf41726397f4038 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Thu, 13 Jan 2022 18:50:55 +0530 +Subject: [PATCH] stdlib: Fix formatting of tests list in Makefile + +Signed-off-by: Siddhesh Poyarekar +Reviewed-by: Florian Weimer +(cherry picked from commit f9dab1b5f23d0fb008a56c7c6c8919adb49d3611) +--- + stdlib/Makefile | 152 ++++++++++++++++++++++++++++---------------------------- + 1 file changed, 77 insertions(+), 75 deletions(-) + +diff --git a/stdlib/Makefile b/stdlib/Makefile +index 6a1c358..9bb5c22 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -65,81 +65,83 @@ aux = grouping groupingwc tens_in_limb + static-only-routines = atexit at_quick_exit + + test-srcs := tst-fmtmsg +-tests := bug-fmtmsg1 \ +- bug-getcontext \ +- bug-strtod \ +- bug-strtod2 \ +- test-a64l \ +- test-at_quick_exit-race \ +- test-atexit-race \ +- test-bz22786 \ +- test-canon \ +- test-canon2 \ +- test-cxa_atexit-race \ +- test-cxa_atexit-race2 \ +- test-dlclose-exit-race \ +- test-on_exit-race \ +- testdiv \ +- testmb \ +- testmb2 \ +- testrand \ +- testsort \ +- tst-at_quick_exit \ +- tst-atexit \ +- tst-atof1 \ +- tst-atof2 \ +- tst-bsearch \ +- tst-bz20544 \ +- tst-canon-bz26341 \ +- tst-cxa_atexit \ +- tst-environ \ +- tst-getrandom \ +- tst-limits \ +- tst-makecontext \ +- tst-makecontext-align \ +- tst-makecontext2 \ +- tst-makecontext3 \ +- tst-on_exit \ +- tst-qsort \ +- tst-qsort2 \ +- tst-quick_exit \ +- tst-rand48 \ +- tst-rand48-2 \ +- tst-random \ +- tst-random2 \ +- tst-realpath \ +- tst-secure-getenv \ +- tst-setcontext \ +- tst-setcontext2 \ +- tst-setcontext3 \ +- tst-setcontext4 \ +- tst-setcontext5 \ +- tst-setcontext6 \ +- tst-setcontext7 \ +- tst-setcontext8 \ +- tst-setcontext9 \ +- tst-strfmon_l \ +- tst-strfrom \ +- tst-strfrom-locale \ +- tst-strtod \ +- tst-strtod-nan-locale \ +- tst-strtod-nan-sign \ +- tst-strtod-overflow \ +- tst-strtod-round \ +- tst-strtod-underflow \ +- tst-strtod2 \ +- tst-strtod5 \ +- tst-strtod6 \ +- tst-strtol \ +- tst-strtol-locale \ +- tst-strtoll \ +- tst-swapcontext1 \ +- tst-thread-quick_exit \ +- tst-tininess \ +- tst-unsetenv1 \ +- tst-width \ +- tst-width-stdint \ +- tst-xpg-basename ++tests := \ ++ bug-fmtmsg1 \ ++ bug-getcontext \ ++ bug-strtod \ ++ bug-strtod2 \ ++ test-a64l \ ++ test-at_quick_exit-race \ ++ test-atexit-race \ ++ test-bz22786 \ ++ test-canon \ ++ test-canon2 \ ++ test-cxa_atexit-race \ ++ test-cxa_atexit-race2 \ ++ test-dlclose-exit-race \ ++ test-on_exit-race \ ++ testdiv \ ++ testmb \ ++ testmb2 \ ++ testrand \ ++ testsort \ ++ tst-at_quick_exit \ ++ tst-atexit \ ++ tst-atof1 \ ++ tst-atof2 \ ++ tst-bsearch \ ++ tst-bz20544 \ ++ tst-canon-bz26341 \ ++ tst-cxa_atexit \ ++ tst-environ \ ++ tst-getrandom \ ++ tst-limits \ ++ tst-makecontext \ ++ tst-makecontext-align \ ++ tst-makecontext2 \ ++ tst-makecontext3 \ ++ tst-on_exit \ ++ tst-qsort \ ++ tst-qsort2 \ ++ tst-quick_exit \ ++ tst-rand48 \ ++ tst-rand48-2 \ ++ tst-random \ ++ tst-random2 \ ++ tst-realpath \ ++ tst-secure-getenv \ ++ tst-setcontext \ ++ tst-setcontext2 \ ++ tst-setcontext3 \ ++ tst-setcontext4 \ ++ tst-setcontext5 \ ++ tst-setcontext6 \ ++ tst-setcontext7 \ ++ tst-setcontext8 \ ++ tst-setcontext9 \ ++ tst-strfmon_l \ ++ tst-strfrom \ ++ tst-strfrom-locale \ ++ tst-strtod \ ++ tst-strtod-nan-locale \ ++ tst-strtod-nan-sign \ ++ tst-strtod-overflow \ ++ tst-strtod-round \ ++ tst-strtod-underflow \ ++ tst-strtod2 \ ++ tst-strtod5 \ ++ tst-strtod6 \ ++ tst-strtol \ ++ tst-strtol-locale \ ++ tst-strtoll \ ++ tst-swapcontext1 \ ++ tst-thread-quick_exit \ ++ tst-tininess \ ++ tst-unsetenv1 \ ++ tst-width \ ++ tst-width-stdint \ ++ tst-xpg-basename \ ++# tests + + tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ + tst-tls-atexit tst-tls-atexit-nodelete +-- +1.8.3.1 + diff --git a/stdlib-Sort-tests-in-Makefile.patch b/stdlib-Sort-tests-in-Makefile.patch new file mode 100644 index 0000000..2e1cdf1 --- /dev/null +++ b/stdlib-Sort-tests-in-Makefile.patch @@ -0,0 +1,126 @@ +From 269eb9d930546ce57e83b56c44c430f154684a23 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Thu, 13 Jan 2022 10:34:37 +0530 +Subject: [PATCH] stdlib: Sort tests in Makefile + +Put one test per line and sort them. + +Signed-off-by: Siddhesh Poyarekar +(cherry picked from commit 5b766603efa727c236a5f0cdcf09b71ff60b7584) +--- + stdlib/Makefile | 99 +++++++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 75 insertions(+), 24 deletions(-) + +diff --git a/stdlib/Makefile b/stdlib/Makefile +index 7c15549..6a1c358 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -65,30 +65,81 @@ aux = grouping groupingwc tens_in_limb + static-only-routines = atexit at_quick_exit + + test-srcs := tst-fmtmsg +-tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ +- test-canon test-canon2 tst-strtoll tst-environ \ +- tst-xpg-basename tst-random tst-random2 tst-bsearch \ +- tst-limits tst-rand48 bug-strtod tst-setcontext \ +- tst-setcontext2 test-a64l tst-qsort testmb2 \ +- bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \ +- tst-rand48-2 tst-makecontext tst-strtod5 \ +- tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \ +- tst-makecontext3 bug-getcontext bug-fmtmsg1 \ +- tst-secure-getenv tst-strtod-overflow tst-strtod-round \ +- tst-tininess tst-strtod-underflow tst-setcontext3 \ +- tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l \ +- tst-quick_exit tst-thread-quick_exit tst-width \ +- tst-width-stdint tst-strfrom tst-strfrom-locale \ +- tst-getrandom tst-atexit tst-at_quick_exit \ +- tst-cxa_atexit tst-on_exit test-atexit-race \ +- test-at_quick_exit-race test-cxa_atexit-race \ +- test-cxa_atexit-race2 \ +- test-on_exit-race test-dlclose-exit-race \ +- tst-makecontext-align test-bz22786 tst-strtod-nan-sign \ +- tst-swapcontext1 tst-setcontext4 tst-setcontext5 \ +- tst-setcontext6 tst-setcontext7 tst-setcontext8 \ +- tst-setcontext9 tst-bz20544 tst-canon-bz26341 \ +- tst-realpath ++tests := bug-fmtmsg1 \ ++ bug-getcontext \ ++ bug-strtod \ ++ bug-strtod2 \ ++ test-a64l \ ++ test-at_quick_exit-race \ ++ test-atexit-race \ ++ test-bz22786 \ ++ test-canon \ ++ test-canon2 \ ++ test-cxa_atexit-race \ ++ test-cxa_atexit-race2 \ ++ test-dlclose-exit-race \ ++ test-on_exit-race \ ++ testdiv \ ++ testmb \ ++ testmb2 \ ++ testrand \ ++ testsort \ ++ tst-at_quick_exit \ ++ tst-atexit \ ++ tst-atof1 \ ++ tst-atof2 \ ++ tst-bsearch \ ++ tst-bz20544 \ ++ tst-canon-bz26341 \ ++ tst-cxa_atexit \ ++ tst-environ \ ++ tst-getrandom \ ++ tst-limits \ ++ tst-makecontext \ ++ tst-makecontext-align \ ++ tst-makecontext2 \ ++ tst-makecontext3 \ ++ tst-on_exit \ ++ tst-qsort \ ++ tst-qsort2 \ ++ tst-quick_exit \ ++ tst-rand48 \ ++ tst-rand48-2 \ ++ tst-random \ ++ tst-random2 \ ++ tst-realpath \ ++ tst-secure-getenv \ ++ tst-setcontext \ ++ tst-setcontext2 \ ++ tst-setcontext3 \ ++ tst-setcontext4 \ ++ tst-setcontext5 \ ++ tst-setcontext6 \ ++ tst-setcontext7 \ ++ tst-setcontext8 \ ++ tst-setcontext9 \ ++ tst-strfmon_l \ ++ tst-strfrom \ ++ tst-strfrom-locale \ ++ tst-strtod \ ++ tst-strtod-nan-locale \ ++ tst-strtod-nan-sign \ ++ tst-strtod-overflow \ ++ tst-strtod-round \ ++ tst-strtod-underflow \ ++ tst-strtod2 \ ++ tst-strtod5 \ ++ tst-strtod6 \ ++ tst-strtol \ ++ tst-strtol-locale \ ++ tst-strtoll \ ++ tst-swapcontext1 \ ++ tst-thread-quick_exit \ ++ tst-tininess \ ++ tst-unsetenv1 \ ++ tst-width \ ++ tst-width-stdint \ ++ tst-xpg-basename + + tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ + tst-tls-atexit tst-tls-atexit-nodelete +-- +1.8.3.1 + diff --git a/support-Add-helpers-to-create-paths-longer-than-PATH.patch b/support-Add-helpers-to-create-paths-longer-than-PATH.patch new file mode 100644 index 0000000..4d4e737 --- /dev/null +++ b/support-Add-helpers-to-create-paths-longer-than-PATH.patch @@ -0,0 +1,282 @@ +From 062ff490c1467059f6cd64bb9c3d85f6cc6cf97a Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Tue, 18 Jan 2022 13:29:36 +0530 +Subject: [PATCH] support: Add helpers to create paths longer than PATH_MAX + +Add new helpers support_create_and_chdir_toolong_temp_directory and +support_chdir_toolong_temp_directory to create and descend into +directory trees longer than PATH_MAX. + +Reviewed-by: Adhemerval Zanella +Signed-off-by: Siddhesh Poyarekar +(cherry picked from commit fb7bff12e81c677a6622f724edd4d4987dd9d971) +--- + support/temp_file.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++---- + support/temp_file.h | 9 +++ + 2 files changed, 160 insertions(+), 10 deletions(-) + +diff --git a/support/temp_file.c b/support/temp_file.c +index c6df641..e41128c 100644 +--- a/support/temp_file.c ++++ b/support/temp_file.c +@@ -1,5 +1,6 @@ + /* Temporary file handling for tests. +- Copyright (C) 1998-2021 Free Software Foundation, Inc. ++ Copyright (C) 1998-2022 Free Software Foundation, Inc. ++ Copyright The GNU Tools Authors. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -20,15 +21,17 @@ + some 32-bit platforms. */ + #define _FILE_OFFSET_BITS 64 + ++#include + #include + #include + #include + ++#include + #include + #include + #include + #include +-#include ++#include + + /* List of temporary files. */ + static struct temp_name_list +@@ -36,14 +39,20 @@ static struct temp_name_list + struct temp_name_list *next; + char *name; + pid_t owner; ++ bool toolong; + } *temp_name_list; + + /* Location of the temporary files. Set by the test skeleton via + support_set_test_dir. The string is not be freed. */ + static const char *test_dir = _PATH_TMP; + +-void +-add_temp_file (const char *name) ++/* Name of subdirectories in a too long temporary directory tree. */ ++static char toolong_subdir[NAME_MAX + 1]; ++static bool toolong_initialized; ++static size_t toolong_path_max; ++ ++static void ++add_temp_file_internal (const char *name, bool toolong) + { + struct temp_name_list *newp + = (struct temp_name_list *) xcalloc (sizeof (*newp), 1); +@@ -53,12 +62,19 @@ add_temp_file (const char *name) + newp->name = newname; + newp->next = temp_name_list; + newp->owner = getpid (); ++ newp->toolong = toolong; + temp_name_list = newp; + } + else + free (newp); + } + ++void ++add_temp_file (const char *name) ++{ ++ add_temp_file_internal (name, false); ++} ++ + int + create_temp_file_in_dir (const char *base, const char *dir, char **filename) + { +@@ -90,8 +106,8 @@ create_temp_file (const char *base, char **filename) + return create_temp_file_in_dir (base, test_dir, filename); + } + +-char * +-support_create_temp_directory (const char *base) ++static char * ++create_temp_directory_internal (const char *base, bool toolong) + { + char *path = xasprintf ("%s/%sXXXXXX", test_dir, base); + if (mkdtemp (path) == NULL) +@@ -99,16 +115,132 @@ support_create_temp_directory (const char *base) + printf ("error: mkdtemp (\"%s\"): %m", path); + exit (1); + } +- add_temp_file (path); ++ add_temp_file_internal (path, toolong); + return path; + } + +-/* Helper functions called by the test skeleton follow. */ ++char * ++support_create_temp_directory (const char *base) ++{ ++ return create_temp_directory_internal (base, false); ++} ++ ++static void ++ensure_toolong_initialized (void) ++{ ++ if (!toolong_initialized) ++ FAIL_EXIT1 ("uninitialized toolong directory tree\n"); ++} ++ ++static void ++initialize_toolong (const char *base) ++{ ++ long name_max = pathconf (base, _PC_NAME_MAX); ++ name_max = (name_max < 0 ? 64 ++ : (name_max < sizeof (toolong_subdir) ? name_max ++ : sizeof (toolong_subdir) - 1)); ++ ++ long path_max = pathconf (base, _PC_PATH_MAX); ++ path_max = (path_max < 0 ? 1024 ++ : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX); ++ ++ /* Sanity check to ensure that the test does not create temporary directories ++ in different filesystems because this API doesn't support it. */ ++ if (toolong_initialized) ++ { ++ if (name_max != strlen (toolong_subdir)) ++ FAIL_UNSUPPORTED ("name_max: Temporary directories in different" ++ " filesystems not supported yet\n"); ++ if (path_max != toolong_path_max) ++ FAIL_UNSUPPORTED ("path_max: Temporary directories in different" ++ " filesystems not supported yet\n"); ++ return; ++ } ++ ++ toolong_path_max = path_max; ++ ++ size_t len = name_max; ++ memset (toolong_subdir, 'X', len); ++ toolong_initialized = true; ++} ++ ++char * ++support_create_and_chdir_toolong_temp_directory (const char *basename) ++{ ++ char *base = create_temp_directory_internal (basename, true); ++ xchdir (base); ++ ++ initialize_toolong (base); ++ ++ size_t sz = strlen (toolong_subdir); ++ ++ /* Create directories and descend into them so that the final path is larger ++ than PATH_MAX. */ ++ for (size_t i = 0; i <= toolong_path_max / sz; i++) ++ { ++ int ret = mkdir (toolong_subdir, S_IRWXU); ++ if (ret != 0 && errno == ENAMETOOLONG) ++ FAIL_UNSUPPORTED ("Filesystem does not support creating too long " ++ "directory trees\n"); ++ else if (ret != 0) ++ FAIL_EXIT1 ("Failed to create directory tree: %m\n"); ++ xchdir (toolong_subdir); ++ } ++ return base; ++} + + void +-support_set_test_dir (const char *path) ++support_chdir_toolong_temp_directory (const char *base) + { +- test_dir = path; ++ ensure_toolong_initialized (); ++ ++ xchdir (base); ++ ++ size_t sz = strlen (toolong_subdir); ++ for (size_t i = 0; i <= toolong_path_max / sz; i++) ++ xchdir (toolong_subdir); ++} ++ ++/* Helper functions called by the test skeleton follow. */ ++ ++static void ++remove_toolong_subdirs (const char *base) ++{ ++ ensure_toolong_initialized (); ++ ++ if (chdir (base) != 0) ++ { ++ printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n", ++ base); ++ return; ++ } ++ ++ /* Descend. */ ++ int levels = 0; ++ size_t sz = strlen (toolong_subdir); ++ for (levels = 0; levels <= toolong_path_max / sz; levels++) ++ if (chdir (toolong_subdir) != 0) ++ { ++ printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n", ++ toolong_subdir); ++ break; ++ } ++ ++ /* Ascend and remove. */ ++ while (--levels >= 0) ++ { ++ if (chdir ("..") != 0) ++ { ++ printf ("warning: toolong cleanup failed: chdir (\"..\"): %m\n"); ++ return; ++ } ++ if (remove (toolong_subdir) != 0) ++ { ++ printf ("warning: could not remove subdirectory: %s: %m\n", ++ toolong_subdir); ++ return; ++ } ++ } + } + + void +@@ -123,6 +255,9 @@ support_delete_temp_files (void) + around, to prevent PID reuse.) */ + if (temp_name_list->owner == pid) + { ++ if (temp_name_list->toolong) ++ remove_toolong_subdirs (temp_name_list->name); ++ + if (remove (temp_name_list->name) != 0) + printf ("warning: could not remove temporary file: %s: %m\n", + temp_name_list->name); +@@ -147,3 +282,9 @@ support_print_temp_files (FILE *f) + fprintf (f, ")\n"); + } + } ++ ++void ++support_set_test_dir (const char *path) ++{ ++ test_dir = path; ++} +diff --git a/support/temp_file.h b/support/temp_file.h +index f3a7fb6..a22964c 100644 +--- a/support/temp_file.h ++++ b/support/temp_file.h +@@ -44,6 +44,15 @@ int create_temp_file_in_dir (const char *base, const char *dir, + returns. The caller should free this string. */ + char *support_create_temp_directory (const char *base); + ++/* Create a temporary directory tree that is longer than PATH_MAX and schedule ++ it for deletion. BASENAME is used as a prefix for the unique directory ++ name, which the function returns. The caller should free this string. */ ++char *support_create_and_chdir_toolong_temp_directory (const char *basename); ++ ++/* Change into the innermost directory of the directory tree BASE, which was ++ created using support_create_and_chdir_toolong_temp_directory. */ ++void support_chdir_toolong_temp_directory (const char *base); ++ + __END_DECLS + + #endif /* SUPPORT_TEMP_FILE_H */ +-- +1.8.3.1 + diff --git a/tst-realpath-toolong-Fix-hurd-build.patch b/tst-realpath-toolong-Fix-hurd-build.patch new file mode 100644 index 0000000..6445782 --- /dev/null +++ b/tst-realpath-toolong-Fix-hurd-build.patch @@ -0,0 +1,31 @@ +From 8c8a71c85f2ed5cc90d08d82ce645513fc907cb6 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Mon, 24 Jan 2022 10:57:09 +0530 +Subject: [PATCH] tst-realpath-toolong: Fix hurd build + +Define PATH_MAX to a constant if it isn't already defined, like in hurd. + +Signed-off-by: Siddhesh Poyarekar +(cherry picked from commit 976db046bc3a3738f69255ae00b0a09b8e77fd9c) +--- + stdlib/tst-realpath-toolong.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/stdlib/tst-realpath-toolong.c b/stdlib/tst-realpath-toolong.c +index 8bed772..4388890 100644 +--- a/stdlib/tst-realpath-toolong.c ++++ b/stdlib/tst-realpath-toolong.c +@@ -29,6 +29,10 @@ + + #define BASENAME "tst-realpath-toolong." + ++#ifndef PATH_MAX ++# define PATH_MAX 1024 ++#endif ++ + int + do_test (void) + { +-- +1.8.3.1 + -- Gitee From 6b774ad599c53c53f276c7f0755449ac18b5a857 Mon Sep 17 00:00:00 2001 From: f00467700 Date: Tue, 25 Jan 2022 21:59:48 +0800 Subject: [PATCH 46/70] Disable debuginfod in printer tests [BZ #28757] i386: Remove broken CAN_USE_REGISTER_ASM_EBP (bug 28771) x86: use default cache size if it cannot be determined [BZ #28784] --- ...debuginfod-in-printer-tests-BZ-28757.patch | 57 +++ glibc.spec | 10 +- ...en-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch | 463 ++++++++++++++++++ ...cache-size-if-it-cannot-be-determine.patch | 61 +++ 4 files changed, 590 insertions(+), 1 deletion(-) create mode 100644 Disable-debuginfod-in-printer-tests-BZ-28757.patch create mode 100644 i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch create mode 100644 x86-use-default-cache-size-if-it-cannot-be-determine.patch diff --git a/Disable-debuginfod-in-printer-tests-BZ-28757.patch b/Disable-debuginfod-in-printer-tests-BZ-28757.patch new file mode 100644 index 0000000..a701f43 --- /dev/null +++ b/Disable-debuginfod-in-printer-tests-BZ-28757.patch @@ -0,0 +1,57 @@ +From 7de501f9418bf099e7104b63b0e4423257981b14 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Sun, 9 Jan 2022 09:06:15 -0800 +Subject: [PATCH] Disable debuginfod in printer tests [BZ #28757] + +With gdb-11.1-6.fc35.x86_64, I got + +FAIL: nptl/test-cond-printers +FAIL: nptl/test-condattr-printers +FAIL: nptl/test-mutex-printers +FAIL: nptl/test-mutexattr-printers +FAIL: nptl/test-rwlock-printers +FAIL: nptl/test-rwlockattr-printers + +$ cat nptl/test-condattr-printers.out +Error: Response does not match the expected pattern. +Command: start +Expected pattern: main +Response: Temporary breakpoint 1 at 0x11d5: file test-condattr-printers.c, line 43. +Starting program: /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/nptl/test-condattr-printers + +This GDB supports auto-downloading debuginfo from the following URLs: +https://debuginfod.fedoraproject.org/ +Enable debuginfod for this session? (y or [n]) + +Disable debuginfod to avoid GDB messages. This fixes BZ #28757. + +Reviewed-by: Florian Weimer +--- + scripts/test_printers_common.py | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/scripts/test_printers_common.py b/scripts/test_printers_common.py +index 6406e3bac7..38121697bc 100644 +--- a/scripts/test_printers_common.py ++++ b/scripts/test_printers_common.py +@@ -161,6 +161,17 @@ def init_test(test_bin, printer_files, printer_names): + printer files. + """ + ++ # Disable debuginfod to avoid GDB messages like: ++ # ++ # This GDB supports auto-downloading debuginfo from the following URLs: ++ # https://debuginfod.fedoraproject.org/ ++ # Enable debuginfod for this session? (y or [n]) ++ # ++ try: ++ test('set debuginfod enabled off') ++ except Exception: ++ pass ++ + # Load all the pretty printer files. We're assuming these are safe. + for printer_file in printer_files: + test('source {0}'.format(printer_file)) +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 1b25cb6..eb533f7 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 46 +Release: 47 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -171,6 +171,9 @@ Patch83: realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch Patch84: tst-realpath-toolong-Fix-hurd-build.patch Patch85: getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch Patch86: Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch +Patch87: Disable-debuginfod-in-printer-tests-BZ-28757.patch +Patch88: i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch +Patch89: x86-use-default-cache-size-if-it-cannot-be-determine.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1374,6 +1377,11 @@ fi %endif %changelog +* Tue Jan 25 2022 Chuang Fang - 2.34-47 +- Disable debuginfod in printer tests [BZ #28757] +- i386: Remove broken CAN_USE_REGISTER_ASM_EBP (bug 28771) +- x86: use default cache size if it cannot be determined [BZ #28784] + * Tue Jan 25 2022 Qingqing Li - 2.34-46 - fix CVE-2021-3998 and CVE-2021-3999 diff --git a/i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch b/i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch new file mode 100644 index 0000000..181b177 --- /dev/null +++ b/i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch @@ -0,0 +1,463 @@ +From 2fe2af88abd13ae5636881da2e26f461ecb7dfb5 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 13 Jan 2022 14:59:29 +0100 +Subject: [PATCH] i386: Remove broken CAN_USE_REGISTER_ASM_EBP (bug 28771) + +The configure check for CAN_USE_REGISTER_ASM_EBP tried to compile a +simple function that uses %ebp as an inline assembly operand. If +compilation failed, CAN_USE_REGISTER_ASM_EBP was set 0, which +eventually had these consequences: + +(1) %ebx was avoided as an inline assembly operand, with an + assembler macro hack to avoid unnecessary register moves. +(2) %ebp was avoided as an inline assembly operand, using an + out-of-line syscall function for 6-argument system calls. + +(1) is no longer needed for any GCC version that is supported for +building glibc. %ebx can be used directly as a register operand. +Therefore, this commit removes the %ebx avoidance completely. This +avoids the assembler macro hack, which turns out to be incompatible +with the current Systemtap probe macros (which switch to .altmacro +unconditionally). + +(2) is still needed in many build configurations. The existing +configure check cannot really capture that because the simple function +succeeds to compile, while the full glibc build still fails. +Therefore, this commit removes the check, the CAN_USE_REGISTER_ASM_EBP +macro, and uses the out-of-line syscall function for 6-argument system +calls unconditionally. + +Reviewed-by: H.J. Lu +(cherry picked from commit a78e6a10d0b50d0ca80309775980fc99944b1727) +--- + NEWS | 1 + + config.h.in | 4 - + sysdeps/unix/sysv/linux/i386/configure | 39 ---- + sysdeps/unix/sysv/linux/i386/configure.ac | 17 -- + sysdeps/unix/sysv/linux/i386/sysdep.h | 222 +++------------------- + 5 files changed, 28 insertions(+), 255 deletions(-) + +diff --git a/NEWS b/NEWS +index 5c253a4392..759a80b1b5 100644 +--- a/NEWS ++++ b/NEWS +@@ -30,6 +30,7 @@ The following bugs are resolved with this release: + AMD64 cpus + [28091] network: ns_name_skip may return 0 for domain names without + terminator ++ [28771] %ebx optimization macros are incompatible with .altmacro + + + Version 2.33 +diff --git a/config.h.in b/config.h.in +index 8b45a3a61d..37207df94f 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -283,10 +283,6 @@ + /* Define if static PIE is enabled. */ + #define ENABLE_STATIC_PIE 0 + +-/* Some compiler options may now allow to use ebp in __asm__ (used mainly +- in i386 6 argument syscall issue). */ +-#define CAN_USE_REGISTER_ASM_EBP 0 +- + /* The default value of x86 CET control. */ + #define DEFAULT_DL_X86_CET_CONTROL cet_elf_property + +diff --git a/sysdeps/unix/sysv/linux/i386/configure b/sysdeps/unix/sysv/linux/i386/configure +index 0327590486..f119e62fc3 100644 +--- a/sysdeps/unix/sysv/linux/i386/configure ++++ b/sysdeps/unix/sysv/linux/i386/configure +@@ -1,44 +1,5 @@ + # This file is generated from configure.ac by Autoconf. DO NOT EDIT! + # Local configure fragment for sysdeps/unix/sysv/linux/i386. + +-# Check if CFLAGS allows compiler to use ebp register in inline assembly. +- +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler flags allows ebp in inline assembly" >&5 +-$as_echo_n "checking if compiler flags allows ebp in inline assembly... " >&6; } +-if ${libc_cv_can_use_register_asm_ebp+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +-cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +- void foo (int i) +- { +- register int reg asm ("ebp") = i; +- asm ("# %0" : : "r" (reg)); +- } +-int +-main () +-{ +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_compile "$LINENO"; then : +- libc_cv_can_use_register_asm_ebp=yes +-else +- libc_cv_can_use_register_asm_ebp=no +-fi +-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_can_use_register_asm_ebp" >&5 +-$as_echo "$libc_cv_can_use_register_asm_ebp" >&6; } +-if test $libc_cv_can_use_register_asm_ebp = yes; then +- $as_echo "#define CAN_USE_REGISTER_ASM_EBP 1" >>confdefs.h +- +-fi +- + libc_cv_gcc_unwind_find_fde=yes + ldd_rewrite_script=sysdeps/unix/sysv/linux/ldd-rewrite.sed +diff --git a/sysdeps/unix/sysv/linux/i386/configure.ac b/sysdeps/unix/sysv/linux/i386/configure.ac +index 9e980784bb..64ab2cc2c8 100644 +--- a/sysdeps/unix/sysv/linux/i386/configure.ac ++++ b/sysdeps/unix/sysv/linux/i386/configure.ac +@@ -1,22 +1,5 @@ + GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + # Local configure fragment for sysdeps/unix/sysv/linux/i386. + +-# Check if CFLAGS allows compiler to use ebp register in inline assembly. +-AC_CACHE_CHECK([if compiler flags allows ebp in inline assembly], +- libc_cv_can_use_register_asm_ebp, [ +-AC_COMPILE_IFELSE( +- [AC_LANG_PROGRAM([ +- void foo (int i) +- { +- register int reg asm ("ebp") = i; +- asm ("# %0" : : "r" (reg)); +- }])], +- [libc_cv_can_use_register_asm_ebp=yes], +- [libc_cv_can_use_register_asm_ebp=no]) +-]) +-if test $libc_cv_can_use_register_asm_ebp = yes; then +- AC_DEFINE(CAN_USE_REGISTER_ASM_EBP) +-fi +- + libc_cv_gcc_unwind_find_fde=yes + ldd_rewrite_script=sysdeps/unix/sysv/linux/ldd-rewrite.sed +diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h +index 8a9911b7ac..39d6a3c134 100644 +--- a/sysdeps/unix/sysv/linux/i386/sysdep.h ++++ b/sysdeps/unix/sysv/linux/i386/sysdep.h +@@ -43,15 +43,6 @@ + # endif + #endif + +-/* Since GCC 5 and above can properly spill %ebx with PIC when needed, +- we can inline syscalls with 6 arguments if GCC 5 or above is used +- to compile glibc. Disable GCC 5 optimization when compiling for +- profiling or when -fno-omit-frame-pointer is used since asm ("ebp") +- can't be used to put the 6th argument in %ebp for syscall. */ +-#if !defined PROF && CAN_USE_REGISTER_ASM_EBP +-# define OPTIMIZE_FOR_GCC_5 +-#endif +- + #ifdef __ASSEMBLER__ + + /* Linux uses a negative return value to indicate syscall errors, +@@ -239,36 +230,6 @@ + extern int __syscall_error (int) + attribute_hidden __attribute__ ((__regparm__ (1))); + +-#ifndef OPTIMIZE_FOR_GCC_5 +-/* We need some help from the assembler to generate optimal code. We +- define some macros here which later will be used. */ +-asm (".L__X'%ebx = 1\n\t" +- ".L__X'%ecx = 2\n\t" +- ".L__X'%edx = 2\n\t" +- ".L__X'%eax = 3\n\t" +- ".L__X'%esi = 3\n\t" +- ".L__X'%edi = 3\n\t" +- ".L__X'%ebp = 3\n\t" +- ".L__X'%esp = 3\n\t" +- ".macro bpushl name reg\n\t" +- ".if 1 - \\name\n\t" +- ".if 2 - \\name\n\t" +- "error\n\t" +- ".else\n\t" +- "xchgl \\reg, %ebx\n\t" +- ".endif\n\t" +- ".endif\n\t" +- ".endm\n\t" +- ".macro bpopl name reg\n\t" +- ".if 1 - \\name\n\t" +- ".if 2 - \\name\n\t" +- "error\n\t" +- ".else\n\t" +- "xchgl \\reg, %ebx\n\t" +- ".endif\n\t" +- ".endif\n\t" +- ".endm\n\t"); +- + /* Six-argument syscalls use an out-of-line helper, because an inline + asm using all registers apart from %esp cannot work reliably and + the assembler does not support describing an asm that saves and +@@ -279,7 +240,6 @@ struct libc_do_syscall_args + { + int ebx, edi, ebp; + }; +-#endif + + # define VDSO_NAME "LINUX_2.6" + # define VDSO_HASH 61765110 +@@ -332,14 +292,8 @@ struct libc_do_syscall_args + + /* Each object using 6-argument inline syscalls must include a + definition of __libc_do_syscall. */ +-#ifdef OPTIMIZE_FOR_GCC_5 +-# define INTERNAL_SYSCALL_MAIN_6(name, args...) \ +- INTERNAL_SYSCALL_MAIN_INLINE(name, 6, args) +-# define INTERNAL_SYSCALL_MAIN_NCS_6(name, args...) \ +- INTERNAL_SYSCALL_MAIN_NCS(name, 6, args) +-#else /* GCC 5 */ +-# define INTERNAL_SYSCALL_MAIN_6(name, arg1, arg2, arg3, \ +- arg4, arg5, arg6) \ ++#define INTERNAL_SYSCALL_MAIN_6(name, arg1, arg2, arg3, \ ++ arg4, arg5, arg6) \ + struct libc_do_syscall_args _xv = \ + { \ + (int) (arg1), \ +@@ -352,8 +306,8 @@ struct libc_do_syscall_args + : "=a" (resultvar) \ + : "i" (__NR_##name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \ + : "memory", "cc") +-# define INTERNAL_SYSCALL_MAIN_NCS_6(name, arg1, arg2, arg3, \ +- arg4, arg5, arg6) \ ++#define INTERNAL_SYSCALL_MAIN_NCS_6(name, arg1, arg2, arg3, \ ++ arg4, arg5, arg6) \ + struct libc_do_syscall_args _xv = \ + { \ + (int) (arg1), \ +@@ -366,7 +320,6 @@ struct libc_do_syscall_args + : "=a" (resultvar) \ + : "a" (name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \ + : "memory", "cc") +-#endif /* GCC 5 */ + + #define INTERNAL_SYSCALL(name, nr, args...) \ + ({ \ +@@ -380,193 +333,72 @@ struct libc_do_syscall_args + (int) resultvar; }) + + #if I386_USE_SYSENTER +-# ifdef OPTIMIZE_FOR_GCC_5 +-# ifdef PIC +-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ ++# ifdef PIC ++# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ + LOADREGS_##nr(args) \ + asm volatile ( \ + "call *%%gs:%P2" \ + : "=a" (resultvar) \ + : "a" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo)) \ + ASMARGS_##nr(args) : "memory", "cc") +-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ ++# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ + LOADREGS_##nr(args) \ + asm volatile ( \ + "call *%%gs:%P2" \ + : "=a" (resultvar) \ + : "a" (name), "i" (offsetof (tcbhead_t, sysinfo)) \ + ASMARGS_##nr(args) : "memory", "cc") +-# else +-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ ++# else /* I386_USE_SYSENTER && !PIC */ ++# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ + LOADREGS_##nr(args) \ + asm volatile ( \ + "call *_dl_sysinfo" \ + : "=a" (resultvar) \ + : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc") +-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ ++# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ + LOADREGS_##nr(args) \ + asm volatile ( \ + "call *_dl_sysinfo" \ + : "=a" (resultvar) \ + : "a" (name) ASMARGS_##nr(args) : "memory", "cc") +-# endif +-# else /* GCC 5 */ +-# ifdef PIC +-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ +- EXTRAVAR_##nr \ +- asm volatile ( \ +- LOADARGS_##nr \ +- "movl %1, %%eax\n\t" \ +- "call *%%gs:%P2\n\t" \ +- RESTOREARGS_##nr \ +- : "=a" (resultvar) \ +- : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo)) \ +- ASMFMT_##nr(args) : "memory", "cc") +-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ +- EXTRAVAR_##nr \ +- asm volatile ( \ +- LOADARGS_##nr \ +- "call *%%gs:%P2\n\t" \ +- RESTOREARGS_##nr \ +- : "=a" (resultvar) \ +- : "0" (name), "i" (offsetof (tcbhead_t, sysinfo)) \ +- ASMFMT_##nr(args) : "memory", "cc") +-# else +-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ +- EXTRAVAR_##nr \ +- asm volatile ( \ +- LOADARGS_##nr \ +- "movl %1, %%eax\n\t" \ +- "call *_dl_sysinfo\n\t" \ +- RESTOREARGS_##nr \ +- : "=a" (resultvar) \ +- : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc") +-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ +- EXTRAVAR_##nr \ +- asm volatile ( \ +- LOADARGS_##nr \ +- "call *_dl_sysinfo\n\t" \ +- RESTOREARGS_##nr \ +- : "=a" (resultvar) \ +- : "0" (name) ASMFMT_##nr(args) : "memory", "cc") +-# endif +-# endif /* GCC 5 */ +-#else +-# ifdef OPTIMIZE_FOR_GCC_5 +-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ ++# endif /* I386_USE_SYSENTER && !PIC */ ++#else /* !I386_USE_SYSENTER */ ++# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ + LOADREGS_##nr(args) \ + asm volatile ( \ + "int $0x80" \ + : "=a" (resultvar) \ + : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc") +-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ ++# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ + LOADREGS_##nr(args) \ + asm volatile ( \ + "int $0x80" \ + : "=a" (resultvar) \ + : "a" (name) ASMARGS_##nr(args) : "memory", "cc") +-# else /* GCC 5 */ +-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \ +- EXTRAVAR_##nr \ +- asm volatile ( \ +- LOADARGS_##nr \ +- "movl %1, %%eax\n\t" \ +- "int $0x80\n\t" \ +- RESTOREARGS_##nr \ +- : "=a" (resultvar) \ +- : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc") +-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \ +- EXTRAVAR_##nr \ +- asm volatile ( \ +- LOADARGS_##nr \ +- "int $0x80\n\t" \ +- RESTOREARGS_##nr \ +- : "=a" (resultvar) \ +- : "0" (name) ASMFMT_##nr(args) : "memory", "cc") +-# endif /* GCC 5 */ +-#endif +- +-#define LOADARGS_0 +-#ifdef __PIC__ +-# if I386_USE_SYSENTER && defined PIC +-# define LOADARGS_1 \ +- "bpushl .L__X'%k3, %k3\n\t" +-# define LOADARGS_5 \ +- "movl %%ebx, %4\n\t" \ +- "movl %3, %%ebx\n\t" +-# else +-# define LOADARGS_1 \ +- "bpushl .L__X'%k2, %k2\n\t" +-# define LOADARGS_5 \ +- "movl %%ebx, %3\n\t" \ +- "movl %2, %%ebx\n\t" +-# endif +-# define LOADARGS_2 LOADARGS_1 +-# define LOADARGS_3 \ +- "xchgl %%ebx, %%edi\n\t" +-# define LOADARGS_4 LOADARGS_3 +-#else +-# define LOADARGS_1 +-# define LOADARGS_2 +-# define LOADARGS_3 +-# define LOADARGS_4 +-# define LOADARGS_5 +-#endif +- +-#define RESTOREARGS_0 +-#ifdef __PIC__ +-# if I386_USE_SYSENTER && defined PIC +-# define RESTOREARGS_1 \ +- "bpopl .L__X'%k3, %k3\n\t" +-# define RESTOREARGS_5 \ +- "movl %4, %%ebx" +-# else +-# define RESTOREARGS_1 \ +- "bpopl .L__X'%k2, %k2\n\t" +-# define RESTOREARGS_5 \ +- "movl %3, %%ebx" +-# endif +-# define RESTOREARGS_2 RESTOREARGS_1 +-# define RESTOREARGS_3 \ +- "xchgl %%edi, %%ebx\n\t" +-# define RESTOREARGS_4 RESTOREARGS_3 +-#else +-# define RESTOREARGS_1 +-# define RESTOREARGS_2 +-# define RESTOREARGS_3 +-# define RESTOREARGS_4 +-# define RESTOREARGS_5 +-#endif ++#endif /* !I386_USE_SYSENTER */ + +-#ifdef OPTIMIZE_FOR_GCC_5 +-# define LOADREGS_0() +-# define ASMARGS_0() +-# define LOADREGS_1(arg1) \ ++#define LOADREGS_0() ++#define ASMARGS_0() ++#define LOADREGS_1(arg1) \ + LOADREGS_0 () +-# define ASMARGS_1(arg1) \ ++#define ASMARGS_1(arg1) \ + ASMARGS_0 (), "b" ((unsigned int) (arg1)) +-# define LOADREGS_2(arg1, arg2) \ ++#define LOADREGS_2(arg1, arg2) \ + LOADREGS_1 (arg1) +-# define ASMARGS_2(arg1, arg2) \ ++#define ASMARGS_2(arg1, arg2) \ + ASMARGS_1 (arg1), "c" ((unsigned int) (arg2)) +-# define LOADREGS_3(arg1, arg2, arg3) \ ++#define LOADREGS_3(arg1, arg2, arg3) \ + LOADREGS_2 (arg1, arg2) +-# define ASMARGS_3(arg1, arg2, arg3) \ ++#define ASMARGS_3(arg1, arg2, arg3) \ + ASMARGS_2 (arg1, arg2), "d" ((unsigned int) (arg3)) +-# define LOADREGS_4(arg1, arg2, arg3, arg4) \ ++#define LOADREGS_4(arg1, arg2, arg3, arg4) \ + LOADREGS_3 (arg1, arg2, arg3) +-# define ASMARGS_4(arg1, arg2, arg3, arg4) \ ++#define ASMARGS_4(arg1, arg2, arg3, arg4) \ + ASMARGS_3 (arg1, arg2, arg3), "S" ((unsigned int) (arg4)) +-# define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \ ++#define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \ + LOADREGS_4 (arg1, arg2, arg3, arg4) +-# define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \ ++#define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \ + ASMARGS_4 (arg1, arg2, arg3, arg4), "D" ((unsigned int) (arg5)) +-# define LOADREGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \ +- register unsigned int _a6 asm ("ebp") = (unsigned int) (arg6); \ +- LOADREGS_5 (arg1, arg2, arg3, arg4, arg5) +-# define ASMARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \ +- ASMARGS_5 (arg1, arg2, arg3, arg4, arg5), "r" (_a6) +-#endif /* GCC 5 */ + + #define ASMFMT_0() + #ifdef __PIC__ +-- +2.27.0 + diff --git a/x86-use-default-cache-size-if-it-cannot-be-determine.patch b/x86-use-default-cache-size-if-it-cannot-be-determine.patch new file mode 100644 index 0000000..7eeae68 --- /dev/null +++ b/x86-use-default-cache-size-if-it-cannot-be-determine.patch @@ -0,0 +1,61 @@ +From c242fcce06e3102ca663b2f992611d0bda4f2668 Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Mon, 17 Jan 2022 19:41:40 +0100 +Subject: [PATCH] x86: use default cache size if it cannot be determined [BZ + #28784] + +In some cases (e.g QEMU, non-Intel/AMD CPU) the cache information can +not be retrieved and the corresponding values are set to 0. + +Commit 2d651eb9265d ("x86: Move x86 processor cache info to +cpu_features") changed the behaviour in such case by defining the +__x86_shared_cache_size and __x86_data_cache_size variables to 0 instead +of using the default values. This cause an issue with the i686 SSE2 +optimized bzero/routine which assumes that the cache size is at least +128 bytes, and otherwise tries to zero/set the whole address space minus +128 bytes. + +Fix that by restoring the original code to only update +__x86_shared_cache_size and __x86_data_cache_size variables if the +corresponding cache sizes are not zero. + +Fixes bug 28784 +Fixes commit 2d651eb9265d + +Reviewed-by: H.J. Lu +--- + sysdeps/x86/cacheinfo.h | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/sysdeps/x86/cacheinfo.h b/sysdeps/x86/cacheinfo.h +index 4f91a1e98d..65132a9d19 100644 +--- a/sysdeps/x86/cacheinfo.h ++++ b/sysdeps/x86/cacheinfo.h +@@ -61,14 +61,20 @@ init_cacheinfo (void) + long int data = cpu_features->data_cache_size; + /* Round data cache size to multiple of 256 bytes. */ + data = data & ~255L; +- __x86_data_cache_size_half = data / 2; +- __x86_data_cache_size = data; ++ if (data > 0) ++ { ++ __x86_data_cache_size_half = data / 2; ++ __x86_data_cache_size = data; ++ } + + long int shared = cpu_features->shared_cache_size; + /* Round shared cache size to multiple of 256 bytes. */ + shared = shared & ~255L; +- __x86_shared_cache_size_half = shared / 2; +- __x86_shared_cache_size = shared; ++ if (shared > 0) ++ { ++ __x86_shared_cache_size_half = shared / 2; ++ __x86_shared_cache_size = shared; ++ } + + __x86_shared_non_temporal_threshold + = cpu_features->non_temporal_threshold; +-- +2.27.0 + -- Gitee From ebae52d7734a9544bd9574fb23db38e96c65e389 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Fri, 28 Jan 2022 10:08:24 +0800 Subject: [PATCH 47/70] Fix __wcsncmp_evex and __wcsncmp_avx2 [BZ #28755] (cherry picked from commit 4035b008a59eb8f5b2701940f4fe8a1969c0fed9) --- glibc.spec | 8 +++- ...sncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch | 40 +++++++++++++++++++ ...sncmp_evex-in-strcmp-evex.S-BZ-28755.patch | 40 +++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch create mode 100644 x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch diff --git a/glibc.spec b/glibc.spec index eb533f7..31e3bdb 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 47 +Release: 48 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -174,6 +174,8 @@ Patch86: Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch Patch87: Disable-debuginfod-in-printer-tests-BZ-28757.patch Patch88: i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch Patch89: x86-use-default-cache-size-if-it-cannot-be-determine.patch +Patch90: x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch +Patch91: x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1377,6 +1379,10 @@ fi %endif %changelog +* Fri Jan 28 2022 Qingqing Li - 2.34-48 +- Fix __wcsncmp_evex in strcmp-evex.S [BZ #28755] +- Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ #28755] + * Tue Jan 25 2022 Chuang Fang - 2.34-47 - Disable debuginfod in printer tests [BZ #28757] - i386: Remove broken CAN_USE_REGISTER_ASM_EBP (bug 28771) diff --git a/x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch b/x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch new file mode 100644 index 0000000..7b8597b --- /dev/null +++ b/x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch @@ -0,0 +1,40 @@ +From ddf0992cf57a93200e0c782e2a94d0733a5a0b87 Mon Sep 17 00:00:00 2001 +From: Noah Goldstein +Date: Sun, 9 Jan 2022 16:02:21 -0600 +Subject: [PATCH] x86: Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ# 28755] + +Fixes [BZ# 28755] for wcsncmp by redirecting length >= 2^56 to +__wcscmp_avx2. For x86_64 this covers the entire address range so any +length larger could not possibly be used to bound `s1` or `s2`. + +test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass. + +Signed-off-by: Noah Goldstein +--- + sysdeps/x86_64/multiarch/strcmp-avx2.S | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S +index a45f9d2..9c73b58 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S +@@ -87,6 +87,16 @@ ENTRY (STRCMP) + je L(char0) + jb L(zero) + # ifdef USE_AS_WCSCMP ++# ifndef __ILP32__ ++ movq %rdx, %rcx ++ /* Check if length could overflow when multiplied by ++ sizeof(wchar_t). Checking top 8 bits will cover all potential ++ overflow cases as well as redirect cases where its impossible to ++ length to bound a valid memory region. In these cases just use ++ 'wcscmp'. */ ++ shrq $56, %rcx ++ jnz __wcscmp_avx2 ++# endif + /* Convert units: from wide to byte char. */ + shl $2, %RDX_LP + # endif +-- +1.8.3.1 + diff --git a/x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch b/x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch new file mode 100644 index 0000000..2b5227e --- /dev/null +++ b/x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch @@ -0,0 +1,40 @@ +From 7e08db3359c86c94918feb33a1182cd0ff3bb10b Mon Sep 17 00:00:00 2001 +From: Noah Goldstein +Date: Sun, 9 Jan 2022 16:02:28 -0600 +Subject: [PATCH] x86: Fix __wcsncmp_evex in strcmp-evex.S [BZ# 28755] + +Fixes [BZ# 28755] for wcsncmp by redirecting length >= 2^56 to +__wcscmp_evex. For x86_64 this covers the entire address range so any +length larger could not possibly be used to bound `s1` or `s2`. + +test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass. + +Signed-off-by: Noah Goldstein +--- + sysdeps/x86_64/multiarch/strcmp-evex.S | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/sysdeps/x86_64/multiarch/strcmp-evex.S b/sysdeps/x86_64/multiarch/strcmp-evex.S +index 1d971f3..0cd939d 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-evex.S ++++ b/sysdeps/x86_64/multiarch/strcmp-evex.S +@@ -104,6 +104,16 @@ ENTRY (STRCMP) + je L(char0) + jb L(zero) + # ifdef USE_AS_WCSCMP ++# ifndef __ILP32__ ++ movq %rdx, %rcx ++ /* Check if length could overflow when multiplied by ++ sizeof(wchar_t). Checking top 8 bits will cover all potential ++ overflow cases as well as redirect cases where its impossible to ++ length to bound a valid memory region. In these cases just use ++ 'wcscmp'. */ ++ shrq $56, %rcx ++ jnz __wcscmp_evex ++# endif + /* Convert units: from wide to byte char. */ + shl $2, %RDX_LP + # endif +-- +1.8.3.1 + -- Gitee From f7cd45c1c8e103331ca48c859cf9412e905092c3 Mon Sep 17 00:00:00 2001 From: Lv Ying Date: Thu, 27 Jan 2022 19:57:42 -0800 Subject: [PATCH 48/70] fix CVE-2019-1010023 Signed-off-by: Lv Ying (cherry picked from commit 3c52b74faf765a574e6abc492c212655b4b45cfe) --- fix-CVE-2019-1010023.patch | 66 ++++++++++++++++++++++++++++++++++++++ glibc.spec | 6 +++- 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 fix-CVE-2019-1010023.patch diff --git a/fix-CVE-2019-1010023.patch b/fix-CVE-2019-1010023.patch new file mode 100644 index 0000000..efa322e --- /dev/null +++ b/fix-CVE-2019-1010023.patch @@ -0,0 +1,66 @@ +From fe1ffef2eec9c6634a1e9af951eb68f0f5614470 Mon Sep 17 00:00:00 2001 +From: xujing +Date: Thu, 2 Dec 2021 11:41:46 +0800 +Subject: [PATCH] glibc: fix CVE-2019-1010023 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +| PT_LOAD +| +| […] Loadable segment entries in the program header table appear in +| ascending order, sorted on the p_vaddr member. + +http://www.sco.com/developers/gabi/latest/ch5.pheader.html + +Some check needed to fix vulnerability in load commands mapping reported by + +https://sourceware.org/bugzilla/show_bug.cgi?id=22851 + +Signed-off-by: lvying +Signed-off-by: xujing +--- + elf/dl-map-segments.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h +index 084076a2..a41ae73b 100644 +--- a/elf/dl-map-segments.h ++++ b/elf/dl-map-segments.h +@@ -33,6 +33,7 @@ _dl_map_segments (struct link_map *l, int fd, + struct link_map *loader) + { + const struct loadcmd *c = loadcmds; ++ ElfW(Addr) l_map_end_aligned; + + if (__glibc_likely (type == ET_DYN)) + { +@@ -61,6 +62,8 @@ _dl_map_segments (struct link_map *l, int fd, + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + + l->l_map_end = l->l_map_start + maplength; ++ l_map_end_aligned = ((l->l_map_end + GLRO(dl_pagesize) - 1) ++ & ~(GLRO(dl_pagesize) - 1)); + l->l_addr = l->l_map_start - c->mapstart; + + if (has_holes) +@@ -85,10 +88,16 @@ _dl_map_segments (struct link_map *l, int fd, + /* Remember which part of the address space this object uses. */ + l->l_map_start = c->mapstart + l->l_addr; + l->l_map_end = l->l_map_start + maplength; ++ l_map_end_aligned = ((l->l_map_end + GLRO(dl_pagesize) - 1) ++ & ~(GLRO(dl_pagesize) - 1)); + l->l_contiguous = !has_holes; + + while (c < &loadcmds[nloadcmds]) + { ++ if ((l->l_addr + c->mapend) > l_map_end_aligned || ++ (l->l_addr + c->mapstart) < l->l_map_start) ++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; ++ + if (c->mapend > c->mapstart + /* Map the segment contents from the file. */ + && (__mmap ((void *) (l->l_addr + c->mapstart), +-- +2.23.0 + diff --git a/glibc.spec b/glibc.spec index 31e3bdb..cdd07b9 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 48 +Release: 49 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -176,6 +176,7 @@ Patch88: i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch Patch89: x86-use-default-cache-size-if-it-cannot-be-determine.patch Patch90: x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch Patch91: x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch +Patch92: fix-CVE-2019-1010023.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1379,6 +1380,9 @@ fi %endif %changelog +* Fri Jan 28 2022 Lv Ying - 2.34-49 +- fix CVE-2019-1010023 + * Fri Jan 28 2022 Qingqing Li - 2.34-48 - Fix __wcsncmp_evex in strcmp-evex.S [BZ #28755] - Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ #28755] -- Gitee From facbb7dec1abd1ffe4a4ad84e8821568f280dce1 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Thu, 27 Jan 2022 17:45:39 +0800 Subject: [PATCH 49/70] Reconstruct the Debug Package Generation Mode: The default debuginfo management mechanism is not deleted. Instead, Use the default macro of RPM. /usr/lib/rpm/openEuler/macros defines: """ %install% {?_Enable Debug Package:% {?Build subdirectory:% {debug package}\ %%Install\ %{nil} """ There are two changes: 1. The source files in /usr/src are correctly packed into the debugging source. 2. The debugging file contains the glibc version number. The CI detects the file change. However, I think this is caused by the CI. Signed-off-by: Yang Yanchao (cherry picked from commit 962ab381cb348507eef59878a6ce56b4203b59ce) --- glibc.spec | 112 +++++------------------------------------------------ 1 file changed, 9 insertions(+), 103 deletions(-) diff --git a/glibc.spec b/glibc.spec index cdd07b9..f0c4718 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 49 +Release: 50 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -437,39 +437,6 @@ Obsoletes: %{name}-utils = 2.28 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 ############################################################################## @@ -696,14 +663,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 debug copies of unstripped static libraries -%if 0%{?_enable_debug_packages} -mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_libdir} -cp -a $RPM_BUILD_ROOT%{_libdir}/*.a \ - $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_libdir}/ -rm -f $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_libdir}/*_p.a -%endif - # Remove any zoneinfo files; they are maintained by tzdata. rm -rf $RPM_BUILD_ROOT%{_prefix}/share/zoneinfo @@ -787,7 +746,6 @@ touch nss-devel.filelist touch libnsl.filelist touch debugutils.filelist touch benchtests.filelist -touch debuginfo.filelist %if %{with compat_2_17} touch compat-2.17.filelist %endif @@ -956,59 +914,6 @@ echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.f echo "%{_libdir}/libpthread-2.17.so" >> compat-2.17.filelist %endif -%if 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 -%if %{with compat_2_17} - -l compat-2.17.filelist \ -%endif - " -%endif - -if command -v find-debuginfo >/dev/null ; then - find_debuginfo=find-debuginfo -else - find_debuginfo=/usr/lib/rpm/find-debuginfo.sh -fi - -$find_debuginfo $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 # 0%{?_enable_debug_packages} ############################################################################## # Run the glibc testsuite ############################################################################## @@ -1359,13 +1264,6 @@ fi %files -f benchtests.filelist benchtests %endif -%if 0%{?_enable_debug_packages} -%files -f debuginfo.filelist debuginfo - -%files debugsource -%endif - - %files help #Doc of glibc package %doc README NEWS INSTALL elf/rtld-debugger-interface.txt @@ -1380,6 +1278,14 @@ fi %endif %changelog +* Fri Jan 28 2022 Yang Yanchao - 2.34-50 +- The default debuginfo management mechanism is deleted. + Instead, Use the default macro of RPM. + There are two changes: + 1. The source files in /usr/src are + correctly packed into the glibc-debugsource. + 2. The debugging file contains the glibc version number. + * Fri Jan 28 2022 Lv Ying - 2.34-49 - fix CVE-2019-1010023 -- Gitee From c0d8fe0932100293f076320da714b2195b3e0d35 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 7 Feb 2022 15:36:59 +0800 Subject: [PATCH 50/70] Pass the actual number of bytes returned by the kernel. Fixes: 33099d72e41c ("linux: Simplify get_nprocs") (cherry picked from commit fbc7ff5e1a4c70a4cbcbbafdc055e114c0414931) --- glibc.spec | 9 ++++-- ...cs_sched-do-not-feed-CPU_COUNT_S-wit.patch | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch diff --git a/glibc.spec b/glibc.spec index f0c4718..e868416 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 50 +Release: 51 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -176,7 +176,7 @@ Patch88: i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch Patch89: x86-use-default-cache-size-if-it-cannot-be-determine.patch Patch90: x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch Patch91: x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch -Patch92: fix-CVE-2019-1010023.patch +Patch92: linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -190,6 +190,7 @@ Patch9008: 0007-add-lowlevellock_2_17_c.patch Patch9009: 0008-add-pause_nocancel_2_17.patch Patch9010: 0009-add-unwind-with-longjmp.patch Patch9011: delete-check-installed-headers-c-and-check-installed.patch +Patch9012: fix-CVE-2019-1010023.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1278,6 +1279,10 @@ fi %endif %changelog +* Mon Feb 7 2022 Qingqing Li - 2.34-51 +- Pass the actual number of bytes returned by the kernel. + Fixes: 33099d72e41c ("linux: Simplify get_nprocs") + * Fri Jan 28 2022 Yang Yanchao - 2.34-50 - The default debuginfo management mechanism is deleted. Instead, Use the default macro of RPM. diff --git a/linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch b/linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch new file mode 100644 index 0000000..0bf8f6d --- /dev/null +++ b/linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch @@ -0,0 +1,30 @@ +From 97ba273b505763325efd802dc3a9562dbba79579 Mon Sep 17 00:00:00 2001 +From: Gleb Fotengauer-Malinovskiy +Date: Tue, 1 Feb 2022 22:39:02 +0000 +Subject: [PATCH] linux: __get_nprocs_sched: do not feed CPU_COUNT_S with + garbage [BZ #28850] + +Pass the actual number of bytes returned by the kernel. + +Fixes: 33099d72e41c ("linux: Simplify get_nprocs") +Reviewed-by: Dmitry V. Levin +--- + sysdeps/unix/sysv/linux/getsysstats.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c +index 4798cc3..c98c8ce 100644 +--- a/sysdeps/unix/sysv/linux/getsysstats.c ++++ b/sysdeps/unix/sysv/linux/getsysstats.c +@@ -44,7 +44,7 @@ __get_nprocs_sched (void) + int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size, + cpu_bits); + if (r > 0) +- return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits); ++ return CPU_COUNT_S (r, (cpu_set_t*) cpu_bits); + else if (r == -EINVAL) + /* The input buffer is still not enough to store the number of cpus. This + is an arbitrary values assuming such systems should be rare and there +-- +1.8.3.1 + -- Gitee From d1531ed325fed6389722abe2c1a1508fc250c3c7 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Mon, 7 Feb 2022 19:40:28 +0800 Subject: [PATCH 51/70] fix misc/tst-glibcsyscalls failed due to kernel reserve some syscalls --- ...calls-due-to-kernel-reserved-some-sy.patch | 55 +++++++++++++++++++ glibc.spec | 6 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch diff --git a/fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch b/fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch new file mode 100644 index 0000000..2a635da --- /dev/null +++ b/fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch @@ -0,0 +1,55 @@ +From 34d9611a38eceba7adf7270d0318629b4a325f56 Mon Sep 17 00:00:00 2001 +From: Qingqing Li +Date: Mon, 7 Feb 2022 20:37:25 +0800 +Subject: [PATCH] fix tst-glibcsyscalls due to kernel reserved some syscalls +kernel has resolved kabi_reserved441 ~ kabi_reserved456, and this will cause +misc/tst-glibcsyscalls failed, errors are like below: + +[ 1241s] =====FAIL: misc/tst-glibcsyscalls.out===== +[ 1241s] info: glibc syscall 'mount_setattr' not known to kernel +[ 1241s] info: glibc syscall 'epoll_pwait2' not known to kernel +[ 1241s] info: glibc syscall 'landlock_add_rule' not known to kernel +[ 1241s] info: glibc syscall 'landlock_restrict_self' not known to kernel +[ 1241s] info: glibc syscall 'landlock_create_ruleset' not known to kernel +[ 1241s] error: kernel syscall 'kabi_reserved454' (454) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved442' (442) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved448' (448) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved447' (447) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved450' (450) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved456' (456) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved441' (441) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved443' (443) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved449' (449) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved455' (455) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved444' (444) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved452' (452) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved453' (453) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved445' (445) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved451' (451) not known to glibc +[ 1241s] error: kernel syscall 'kabi_reserved446' (446) not known to glibc + +--- + sysdeps/unix/sysv/linux/tst-glibcsyscalls.py | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/tst-glibcsyscalls.py b/sysdeps/unix/sysv/linux/tst-glibcsyscalls.py +index 4a00bbab..d2d74c9c 100644 +--- a/sysdeps/unix/sysv/linux/tst-glibcsyscalls.py ++++ b/sysdeps/unix/sysv/linux/tst-glibcsyscalls.py +@@ -67,9 +67,10 @@ def main(): + # superset of the kernel system call set. + if glibc_names.kernel_version >= kernel_version: + for name in kernel_constants.keys() - glibc_constants.keys(): +- print("error: kernel syscall {!r} ({}) not known to glibc" +- .format(name, kernel_constants[name])) +- errors = 1 ++ if 'kabi_reserved' not in name: ++ print("error: kernel syscall {!r} ({}) not known to glibc" ++ .format(name, kernel_constants[name])) ++ errors = 1 + else: + for name in kernel_constants.keys() - glibc_constants.keys(): + print("warning: kernel syscall {!r} ({}) not known to glibc" +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index e868416..285c06c 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 51 +Release: 52 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -191,6 +191,7 @@ Patch9009: 0008-add-pause_nocancel_2_17.patch Patch9010: 0009-add-unwind-with-longjmp.patch Patch9011: delete-check-installed-headers-c-and-check-installed.patch Patch9012: fix-CVE-2019-1010023.patch +Patch9013: fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1279,6 +1280,9 @@ fi %endif %changelog +* Mon Feb 7 2022 Qingqing Li - 2.34-52 +- fix misc/tst-glibcsyscalls failed due to kernel reserve some syscalls + * Mon Feb 7 2022 Qingqing Li - 2.34-51 - Pass the actual number of bytes returned by the kernel. Fixes: 33099d72e41c ("linux: Simplify get_nprocs") -- Gitee From 5bb3b84187fa32da4ed7ae60824e7e4cdc7a18c9 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Tue, 8 Feb 2022 12:29:22 +0800 Subject: [PATCH 52/70] backport patches from upstream 2.34 branch --- ...BI-omission-missing-GLIBC_2.34-in-dy.patch | 399 +++++++++++++ ...ate-64-bit-timestamps-for-64-bit-tim.patch | 498 ++++++++++++++++ ...a-comment-after-trailing-backslashes.patch | 49 ++ ...low-and-sort-most-variable-assignmen.patch | 544 +++++++++++++++++ elf-Sort-tests-and-modules-names.patch | 546 ++++++++++++++++++ glibc.spec | 20 +- ...ary-64-bit-time-timestamp-conversion.patch | 457 +++++++++++++++ ...ng-__convert_scm_timestamps-BZ-28860.patch | 37 ++ ...-Do-not-use-AF_NETLINK-in-__opensock.patch | 40 ++ ...d-support_socket_so_timestamp_time64.patch | 103 ++++ ...tamp-compat.c-Check-__TIMESIZE-BZ-28.patch | 29 + ...ist-more-Intel-CPUs-for-TSX-BZ-27398.patch | 67 +++ ...EATURE_PRESENT-to-check-HLE-BZ-27398.patch | 29 + 13 files changed, 2817 insertions(+), 1 deletion(-) create mode 100644 Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch create mode 100644 Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch create mode 100644 elf-Add-a-comment-after-trailing-backslashes.patch create mode 100644 elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch create mode 100644 elf-Sort-tests-and-modules-names.patch create mode 100644 linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch create mode 100644 linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch create mode 100644 socket-Do-not-use-AF_NETLINK-in-__opensock.patch create mode 100644 support-Add-support_socket_so_timestamp_time64.patch create mode 100644 tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch create mode 100644 x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch create mode 100644 x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch diff --git a/Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch b/Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch new file mode 100644 index 0000000..bc38a37 --- /dev/null +++ b/Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch @@ -0,0 +1,399 @@ +From 948ebc098ed3cd928ea10997f990115e7770bda3 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 27 Jan 2022 16:03:58 +0100 +Subject: [PATCH] Fix glibc 2.34 ABI omission (missing GLIBC_2.34 in dynamic + loader) + +The glibc 2.34 release really should have added a GLIBC_2.34 +symbol to the dynamic loader. With it, we could move functions such +as dlopen or pthread_key_create that work on process-global state +into the dynamic loader (once we have fixed a longstanding issue +with static linking). Without the GLIBC_2.34 symbol, yet another +new symbol version would be needed because old glibc will fail to +load binaries due to the missing symbol version in ld.so that newly +linked programs will require. + +Reviewed-by: H.J. Lu +(cherry picked from commit af121ae3e7cd12628c91ecfc46a9d65313a6e972) +--- + elf/Makefile | 1 + + elf/Versions | 3 ++ + elf/dl-compat.c | 32 +++++++++++++++++++ + sysdeps/mach/hurd/i386/ld.abilist | 1 + + sysdeps/unix/sysv/linux/aarch64/ld.abilist | 1 + + sysdeps/unix/sysv/linux/alpha/ld.abilist | 1 + + sysdeps/unix/sysv/linux/arc/ld.abilist | 1 + + sysdeps/unix/sysv/linux/arm/be/ld.abilist | 1 + + sysdeps/unix/sysv/linux/arm/le/ld.abilist | 1 + + sysdeps/unix/sysv/linux/csky/ld.abilist | 1 + + sysdeps/unix/sysv/linux/hppa/ld.abilist | 1 + + sysdeps/unix/sysv/linux/i386/ld.abilist | 1 + + sysdeps/unix/sysv/linux/ia64/ld.abilist | 1 + + .../unix/sysv/linux/m68k/coldfire/ld.abilist | 1 + + .../unix/sysv/linux/m68k/m680x0/ld.abilist | 1 + + sysdeps/unix/sysv/linux/microblaze/ld.abilist | 1 + + .../unix/sysv/linux/mips/mips32/ld.abilist | 1 + + .../sysv/linux/mips/mips64/n32/ld.abilist | 1 + + .../sysv/linux/mips/mips64/n64/ld.abilist | 1 + + sysdeps/unix/sysv/linux/nios2/ld.abilist | 1 + + .../sysv/linux/powerpc/powerpc32/ld.abilist | 1 + + .../linux/powerpc/powerpc64/be/ld.abilist | 1 + + .../linux/powerpc/powerpc64/le/ld.abilist | 1 + + sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist | 1 + + sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist | 1 + + .../unix/sysv/linux/s390/s390-32/ld.abilist | 1 + + .../unix/sysv/linux/s390/s390-64/ld.abilist | 1 + + sysdeps/unix/sysv/linux/sh/be/ld.abilist | 1 + + sysdeps/unix/sysv/linux/sh/le/ld.abilist | 1 + + .../unix/sysv/linux/sparc/sparc32/ld.abilist | 1 + + .../unix/sysv/linux/sparc/sparc64/ld.abilist | 1 + + sysdeps/unix/sysv/linux/x86_64/64/ld.abilist | 1 + + sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist | 1 + + 33 files changed, 66 insertions(+) + create mode 100644 elf/dl-compat.c + +diff --git a/elf/Makefile b/elf/Makefile +index f930e04e27..af4ccb978c 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -115,6 +115,7 @@ elide-routines.os = \ + # interpreter and operating independent of libc. + rtld-routines = \ + $(all-dl-routines) \ ++ dl-compat \ + dl-conflict \ + dl-diagnostics \ + dl-diagnostics-cpu \ +diff --git a/elf/Versions b/elf/Versions +index 775aab62af..2af210b8f7 100644 +--- a/elf/Versions ++++ b/elf/Versions +@@ -48,6 +48,9 @@ ld { + # stack canary + __stack_chk_guard; + } ++ GLIBC_2.34 { ++ __rtld_version_placeholder; ++ } + GLIBC_PRIVATE { + # Those are in the dynamic linker, but used by libc.so. + __libc_enable_secure; +diff --git a/elf/dl-compat.c b/elf/dl-compat.c +new file mode 100644 +index 0000000000..cc560c5159 +--- /dev/null ++++ b/elf/dl-compat.c +@@ -0,0 +1,32 @@ ++/* Placeholder compatibility symbols. ++ Copyright (C) 2022 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 ++ ++/* GLIBC_2.34 placeholder for future symbol moves. */ ++ ++void ++attribute_compat_text_section ++__attribute_used__ ++__rtld_version_placeholder_1 (void) ++{ ++} ++ ++compat_symbol (ld, __rtld_version_placeholder_1, ++ __rtld_version_placeholder, GLIBC_2_34); +diff --git a/sysdeps/mach/hurd/i386/ld.abilist b/sysdeps/mach/hurd/i386/ld.abilist +index 7e20c5e7ce..ebba31f770 100644 +--- a/sysdeps/mach/hurd/i386/ld.abilist ++++ b/sysdeps/mach/hurd/i386/ld.abilist +@@ -16,3 +16,4 @@ GLIBC_2.2.6 _r_debug D 0x14 + GLIBC_2.2.6 abort F + GLIBC_2.3 ___tls_get_addr F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist +index 80b2fe6725..b7196a80e2 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist +@@ -3,3 +3,4 @@ GLIBC_2.17 __stack_chk_guard D 0x8 + GLIBC_2.17 __tls_get_addr F + GLIBC_2.17 _dl_mcount F + GLIBC_2.17 _r_debug D 0x28 ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist +index 98a03f611f..13f7fc74af 100644 +--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist ++++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist +@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x28 + GLIBC_2.1 __libc_stack_end D 0x8 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __stack_chk_guard D 0x8 +diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/ld.abilist +index 048f17c848..7284383a6b 100644 +--- a/sysdeps/unix/sysv/linux/arc/ld.abilist ++++ b/sysdeps/unix/sysv/linux/arc/ld.abilist +@@ -3,3 +3,4 @@ GLIBC_2.32 __stack_chk_guard D 0x4 + GLIBC_2.32 __tls_get_addr F + GLIBC_2.32 _dl_mcount F + GLIBC_2.32 _r_debug D 0x14 ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/arm/be/ld.abilist b/sysdeps/unix/sysv/linux/arm/be/ld.abilist +index cc8825c3bc..7987bbae11 100644 +--- a/sysdeps/unix/sysv/linux/arm/be/ld.abilist ++++ b/sysdeps/unix/sysv/linux/arm/be/ld.abilist +@@ -1,3 +1,4 @@ ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __libc_stack_end D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 + GLIBC_2.4 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/arm/le/ld.abilist b/sysdeps/unix/sysv/linux/arm/le/ld.abilist +index cc8825c3bc..7987bbae11 100644 +--- a/sysdeps/unix/sysv/linux/arm/le/ld.abilist ++++ b/sysdeps/unix/sysv/linux/arm/le/ld.abilist +@@ -1,3 +1,4 @@ ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __libc_stack_end D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 + GLIBC_2.4 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/csky/ld.abilist b/sysdeps/unix/sysv/linux/csky/ld.abilist +index 564ac09737..4939b20631 100644 +--- a/sysdeps/unix/sysv/linux/csky/ld.abilist ++++ b/sysdeps/unix/sysv/linux/csky/ld.abilist +@@ -3,3 +3,4 @@ GLIBC_2.29 __stack_chk_guard D 0x4 + GLIBC_2.29 __tls_get_addr F + GLIBC_2.29 _dl_mcount F + GLIBC_2.29 _r_debug D 0x14 ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/hppa/ld.abilist b/sysdeps/unix/sysv/linux/hppa/ld.abilist +index d155a59843..7cc9ebd792 100644 +--- a/sysdeps/unix/sysv/linux/hppa/ld.abilist ++++ b/sysdeps/unix/sysv/linux/hppa/ld.abilist +@@ -2,4 +2,5 @@ GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x14 + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist +index 0478e22071..e8d187b14d 100644 +--- a/sysdeps/unix/sysv/linux/i386/ld.abilist ++++ b/sysdeps/unix/sysv/linux/i386/ld.abilist +@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 ___tls_get_addr F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist +index 33f91199bf..be5122650a 100644 +--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist +@@ -2,3 +2,4 @@ GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist +index cc8825c3bc..7987bbae11 100644 +--- a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist +@@ -1,3 +1,4 @@ ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __libc_stack_end D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 + GLIBC_2.4 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist +index 3ba474c27f..4f2854edf7 100644 +--- a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist +@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x14 + GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/microblaze/ld.abilist b/sysdeps/unix/sysv/linux/microblaze/ld.abilist +index a4933c3541..9f0fdeca38 100644 +--- a/sysdeps/unix/sysv/linux/microblaze/ld.abilist ++++ b/sysdeps/unix/sysv/linux/microblaze/ld.abilist +@@ -3,3 +3,4 @@ GLIBC_2.18 __stack_chk_guard D 0x4 + GLIBC_2.18 __tls_get_addr F + GLIBC_2.18 _dl_mcount F + GLIBC_2.18 _r_debug D 0x14 ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist +index be09641a48..f750067d5c 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist +@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x14 + GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist +index be09641a48..f750067d5c 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist +@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x14 + GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist +index 1ea36e13f2..2fba6a9b6e 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist +@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x28 + GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __stack_chk_guard D 0x8 +diff --git a/sysdeps/unix/sysv/linux/nios2/ld.abilist b/sysdeps/unix/sysv/linux/nios2/ld.abilist +index 52178802dd..57dfad5a53 100644 +--- a/sysdeps/unix/sysv/linux/nios2/ld.abilist ++++ b/sysdeps/unix/sysv/linux/nios2/ld.abilist +@@ -3,3 +3,4 @@ GLIBC_2.21 __stack_chk_guard D 0x4 + GLIBC_2.21 __tls_get_addr F + GLIBC_2.21 _dl_mcount F + GLIBC_2.21 _r_debug D 0x14 ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist +index 4bbfba7a61..e896607392 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist +@@ -4,3 +4,4 @@ GLIBC_2.1 _dl_mcount F + GLIBC_2.22 __tls_get_addr_opt F + GLIBC_2.23 __parse_hwcap_and_convert_at_platform F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist +index 283fb4510b..ce0bc63959 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist +@@ -4,3 +4,4 @@ GLIBC_2.3 __libc_stack_end D 0x8 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.3 _dl_mcount F + GLIBC_2.3 _r_debug D 0x28 ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist +index b1f313c7cd..65b22674d2 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist +@@ -4,3 +4,4 @@ GLIBC_2.17 _dl_mcount F + GLIBC_2.17 _r_debug D 0x28 + GLIBC_2.22 __tls_get_addr_opt F + GLIBC_2.23 __parse_hwcap_and_convert_at_platform F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist +index 94ca64c43d..5ad4c81d12 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist +@@ -3,3 +3,4 @@ GLIBC_2.33 __stack_chk_guard D 0x4 + GLIBC_2.33 __tls_get_addr F + GLIBC_2.33 _dl_mcount F + GLIBC_2.33 _r_debug D 0x14 ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist +index 845f356c3c..479efdea9b 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist +@@ -3,3 +3,4 @@ GLIBC_2.27 __stack_chk_guard D 0x8 + GLIBC_2.27 __tls_get_addr F + GLIBC_2.27 _dl_mcount F + GLIBC_2.27 _r_debug D 0x28 ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist +index b56f005beb..d5ecb636bb 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist +@@ -2,3 +2,4 @@ GLIBC_2.0 _r_debug D 0x14 + GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_offset F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist +index 6f788a086d..62a5e1d99a 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist +@@ -2,3 +2,4 @@ GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_offset F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/sh/be/ld.abilist b/sysdeps/unix/sysv/linux/sh/be/ld.abilist +index d155a59843..7cc9ebd792 100644 +--- a/sysdeps/unix/sysv/linux/sh/be/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sh/be/ld.abilist +@@ -2,4 +2,5 @@ GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x14 + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sh/le/ld.abilist b/sysdeps/unix/sysv/linux/sh/le/ld.abilist +index d155a59843..7cc9ebd792 100644 +--- a/sysdeps/unix/sysv/linux/sh/le/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sh/le/ld.abilist +@@ -2,4 +2,5 @@ GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x14 + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist +index 0c6610e3c2..2e60543498 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist +@@ -2,3 +2,4 @@ GLIBC_2.0 _r_debug D 0x14 + GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist +index 33f91199bf..be5122650a 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist +@@ -2,3 +2,4 @@ GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist +index d3cdf7611e..afddaec57c 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist +@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8 + GLIBC_2.2.5 _dl_mcount F + GLIBC_2.2.5 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F ++GLIBC_2.34 __rtld_version_placeholder F +diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist +index c70bccf782..defc488d13 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist +@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4 + GLIBC_2.16 __tls_get_addr F + GLIBC_2.16 _dl_mcount F + GLIBC_2.16 _r_debug D 0x14 ++GLIBC_2.34 __rtld_version_placeholder F +-- +2.27.0 + diff --git a/Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch b/Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch new file mode 100644 index 0000000..45655a6 --- /dev/null +++ b/Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch @@ -0,0 +1,498 @@ +From 489d0b8b32548bc569cd3067aebf98b030720753 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Thu, 27 Jan 2022 16:45:18 -0300 +Subject: [PATCH] Linux: Only generate 64 bit timestamps for 64 bit time_t + recvmsg/recvmmsg + +The timestamps created by __convert_scm_timestamps only make sense for +64 bit time_t programs, 32 bit time_t programs will ignore 64 bit time_t +timestamps since SO_TIMESTAMP will be defined to old values (either by +glibc or kernel headers). + +Worse, if the buffer is not suffice MSG_CTRUNC is set to indicate it +(which breaks some programs [1]). + +This patch makes only 64 bit time_t recvmsg and recvmmsg to call +__convert_scm_timestamps. Also, the assumption to called it is changed +from __ASSUME_TIME64_SYSCALLS to __TIMESIZE != 64 since the setsockopt +might be called by libraries built without __TIME_BITS=64. The +MSG_CTRUNC is only set for the 64 bit symbols, it should happen only +if 64 bit time_t programs run older kernels. + +Checked on x86_64-linux-gnu and i686-linux-gnu. + +[1] https://github.com/systemd/systemd/pull/20567 + +Reviewed-by: Florian Weimer + +(cherry picked from commit 948ce73b31fdb0860bcec4b8e62b14e88234f98a) +--- + include/sys/socket.h | 10 +- + sysdeps/unix/sysv/linux/Makefile | 10 +- + sysdeps/unix/sysv/linux/recvmmsg.c | 36 ++- + sysdeps/unix/sysv/linux/recvmsg.c | 34 ++- + .../tst-socket-timestamp-compat-time64.c | 1 + + .../sysv/linux/tst-socket-timestamp-compat.c | 265 ++++++++++++++++++ + 6 files changed, 330 insertions(+), 26 deletions(-) + create mode 100644 sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c + create mode 100644 sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c + +diff --git a/include/sys/socket.h b/include/sys/socket.h +index a1d749f9fa..6e4cf5077f 100644 +--- a/include/sys/socket.h ++++ b/include/sys/socket.h +@@ -98,15 +98,21 @@ extern int __sendmmsg (int __fd, struct mmsghdr *__vmessages, + libc_hidden_proto (__sendmmsg) + #endif + +-/* Receive a message as described by MESSAGE from socket FD. +- Returns the number of bytes read or -1 for errors. */ + extern ssize_t __libc_recvmsg (int __fd, struct msghdr *__message, + int __flags); + extern ssize_t __recvmsg (int __fd, struct msghdr *__message, + int __flags) attribute_hidden; + #if __TIMESIZE == 64 ++# define __libc_recvmsg64 __libc_recvmsg ++# define __recvmsg64 __recvmsg + # define __recvmmsg64 __recvmmsg + #else ++extern ssize_t __libc_recvmsg64 (int __fd, struct msghdr *__message, ++ int __flags); ++extern ssize_t __recvmsg64 (int __fd, struct msghdr *__message, ++ int __flags); ++/* Receive a message as described by MESSAGE from socket FD. ++ Returns the number of bytes read or -1 for errors. */ + extern int __recvmmsg64 (int __fd, struct mmsghdr *vmessages, + unsigned int vlen, int flags, + struct __timespec64 *timeout); +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 964f641ef9..c34774806f 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -262,8 +262,14 @@ sysdep_routines += cmsg_nxthdr + CFLAGS-recvmmsg.c = -fexceptions -fasynchronous-unwind-tables + CFLAGS-sendmmsg.c = -fexceptions -fasynchronous-unwind-tables + +-tests += tst-socket-timestamp +-tests-time64 += tst-socket-timestamp-time64 ++tests += \ ++ tst-socket-timestamp \ ++ tst-socket-timestamp-compat \ ++ # tests ++tests-time64 += \ ++ tst-socket-timestamp-time64 \ ++ tst-socket-timestamp-compat-time64 ++ # tests-time64 + + tests-special += $(objpfx)tst-socket-consts.out + $(objpfx)tst-socket-consts.out: ../sysdeps/unix/sysv/linux/tst-socket-consts.py +diff --git a/sysdeps/unix/sysv/linux/recvmmsg.c b/sysdeps/unix/sysv/linux/recvmmsg.c +index 5cd107ffa9..fca9f6582d 100644 +--- a/sysdeps/unix/sysv/linux/recvmmsg.c ++++ b/sysdeps/unix/sysv/linux/recvmmsg.c +@@ -20,9 +20,9 @@ + #include + #include + +-int +-__recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, +- struct __timespec64 *timeout) ++static int ++recvmmsg_syscall (int fd, struct mmsghdr *vmessages, unsigned int vlen, ++ int flags, struct __timespec64 *timeout) + { + #ifndef __NR_recvmmsg_time64 + # define __NR_recvmmsg_time64 __NR_recvmmsg +@@ -45,12 +45,6 @@ __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, + pts32 = &ts32; + } + +- socklen_t csize[IOV_MAX]; +- if (vlen > IOV_MAX) +- vlen = IOV_MAX; +- for (int i = 0; i < vlen; i++) +- csize[i] = vmessages[i].msg_hdr.msg_controllen; +- + # ifdef __ASSUME_RECVMMSG_SYSCALL + r = SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32); + # else +@@ -60,11 +54,31 @@ __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, + { + if (timeout != NULL) + *timeout = valid_timespec_to_timespec64 (ts32); ++ } ++#endif ++ return r; ++} ++ ++int ++__recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, ++ struct __timespec64 *timeout) ++{ ++#if __TIMESIZE != 64 ++ socklen_t csize[IOV_MAX]; ++ if (vlen > IOV_MAX) ++ vlen = IOV_MAX; ++ for (int i = 0; i < vlen; i++) ++ csize[i] = vmessages[i].msg_hdr.msg_controllen; ++#endif + ++ int r = recvmmsg_syscall (fd, vmessages, vlen, flags, timeout); ++#if __TIMESIZE != 64 ++ if (r > 0) ++ { + for (int i=0; i < r; i++) + __convert_scm_timestamps (&vmessages[i].msg_hdr, csize[i]); + } +-#endif /* __ASSUME_TIME64_SYSCALLS */ ++#endif + return r; + } + #if __TIMESIZE != 64 +@@ -80,7 +94,7 @@ __recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, + ts64 = valid_timespec_to_timespec64 (*timeout); + pts64 = &ts64; + } +- int r = __recvmmsg64 (fd, vmessages, vlen, flags, pts64); ++ int r = recvmmsg_syscall (fd, vmessages, vlen, flags, pts64); + if (r >= 0 && timeout != NULL) + /* The remanining timeout will be always less the input TIMEOUT. */ + *timeout = valid_timespec64_to_timespec (ts64); +diff --git a/sysdeps/unix/sysv/linux/recvmsg.c b/sysdeps/unix/sysv/linux/recvmsg.c +index 07212f7c86..c4b4704fd6 100644 +--- a/sysdeps/unix/sysv/linux/recvmsg.c ++++ b/sysdeps/unix/sysv/linux/recvmsg.c +@@ -20,29 +20,41 @@ + #include + #include + ++static int ++__recvmsg_syscall (int fd, struct msghdr *msg, int flags) ++{ ++#ifdef __ASSUME_RECVMSG_SYSCALL ++ return SYSCALL_CANCEL (recvmsg, fd, msg, flags); ++#else ++ return SOCKETCALL_CANCEL (recvmsg, fd, msg, flags); ++#endif ++} ++ + ssize_t +-__libc_recvmsg (int fd, struct msghdr *msg, int flags) ++__libc_recvmsg64 (int fd, struct msghdr *msg, int flags) + { + ssize_t r; +-#ifndef __ASSUME_TIME64_SYSCALLS ++#if __TIMESIZE != 64 + socklen_t orig_controllen = msg != NULL ? msg->msg_controllen : 0; + #endif + +-#ifdef __ASSUME_RECVMSG_SYSCALL +- r = SYSCALL_CANCEL (recvmsg, fd, msg, flags); +-#else +- r = SOCKETCALL_CANCEL (recvmsg, fd, msg, flags); +-#endif ++ r = __recvmsg_syscall (fd, msg, flags); + +-#ifndef __ASSUME_TIME64_SYSCALLS ++#if __TIMESIZE != 64 + if (r >= 0 && orig_controllen != 0) + __convert_scm_timestamps (msg, orig_controllen); + #endif + + return r; + } +-weak_alias (__libc_recvmsg, recvmsg) +-weak_alias (__libc_recvmsg, __recvmsg) + #if __TIMESIZE != 64 +-weak_alias (__recvmsg, __recvmsg64) ++weak_alias (__libc_recvmsg64, __recvmsg64) ++ ++ssize_t ++__libc_recvmsg (int fd, struct msghdr *msg, int flags) ++{ ++ return __recvmsg_syscall (fd, msg, flags); ++} + #endif ++weak_alias (__libc_recvmsg, recvmsg) ++weak_alias (__libc_recvmsg, __recvmsg) +diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c +new file mode 100644 +index 0000000000..96a0bef0bf +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c +@@ -0,0 +1 @@ ++#include "tst-socket-timestamp-compat.c" +diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c +new file mode 100644 +index 0000000000..de261dae5a +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c +@@ -0,0 +1,265 @@ ++/* Check recvmsg/recvmmsg 64-bit timestamp support. ++ Copyright (C) 2022 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 ++ ++/* AF_INET socket and address used to receive data. */ ++static int srv; ++static struct sockaddr_in srv_addr; ++ ++static int ++do_sendto (const struct sockaddr_in *addr, int payload) ++{ ++ int s = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); ++ xconnect (s, (const struct sockaddr *) addr, sizeof (*addr)); ++ ++ xsendto (s, &payload, sizeof (payload), 0, (const struct sockaddr *) addr, ++ sizeof (*addr)); ++ ++ xclose (s); ++ ++ return 0; ++} ++ ++static void ++do_recvmsg_ancillary (bool use_multi_call, struct mmsghdr *mmhdr, ++ void *msgbuf, size_t msgbuflen, int exp_payload) ++{ ++ int payload; ++ struct iovec iov = ++ { ++ .iov_base = &payload, ++ .iov_len = sizeof (payload) ++ }; ++ mmhdr->msg_hdr.msg_name = NULL; ++ mmhdr->msg_hdr.msg_iov = &iov; ++ mmhdr->msg_hdr.msg_iovlen = 1; ++ mmhdr->msg_hdr.msg_control = msgbuf; ++ mmhdr->msg_hdr.msg_controllen = msgbuflen; ++ ++ int r; ++ if (use_multi_call) ++ { ++ r = recvmmsg (srv, mmhdr, 1, 0, NULL); ++ if (r >= 0) ++ r = mmhdr->msg_len; ++ } ++ else ++ r = recvmsg (srv, &mmhdr->msg_hdr, 0); ++ TEST_COMPARE (r, sizeof (int)); ++ TEST_COMPARE (payload, exp_payload); ++} ++ ++/* Check if recvmsg create the additional 64 bit timestamp if only 32 bit ++ is enabled for 64 bit recvmsg symbol. */ ++static void ++do_test_large_buffer (bool mc) ++{ ++ struct mmsghdr mmhdr = { 0 }; ++ /* It should be large enought for either timeval/timespec and the ++ 64 time type as well. */ ++ ++ union ++ { ++ struct cmsghdr cmsghdr; ++ char msgbuf[512]; ++ } control; ++ ++ /* Enable 32 bit timeval precision and check if no 64 bit timeval stamp ++ is created. */ ++ { ++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP_OLD, &(int){1}, ++ sizeof (int)); ++ TEST_VERIFY_EXIT (r != -1); ++ ++ do_sendto (&srv_addr, 42); ++ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42); ++ ++ bool found_timestamp = false; ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET) ++ continue; ++ ++ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMP_NEW) ++ found_timestamp = true; ++ else ++ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMP_NEW); ++ } ++ ++ TEST_COMPARE (found_timestamp, sizeof (time_t) > 4); ++ } ++ ++ /* Same as before, but for timespec. */ ++ { ++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS_OLD, &(int){1}, ++ sizeof (int)); ++ TEST_VERIFY_EXIT (r != -1); ++ ++ do_sendto (&srv_addr, 42); ++ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42); ++ ++ bool found_timestamp = false; ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET) ++ continue; ++ ++ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMPNS_NEW) ++ found_timestamp = true; ++ else ++ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMPNS_NEW); ++ } ++ ++ TEST_COMPARE (found_timestamp, sizeof (time_t) > 4); ++ } ++} ++ ++/* Check if recvmsg does not create the additional 64 bit timestamp if ++ only 32 bit timestamp is enabled if the ancillary buffer is not large ++ enought. Also checks if MSG_CTRUNC is set iff for 64 bit recvmsg ++ symbol. */ ++static void ++do_test_small_buffer (bool mc) ++{ ++ struct mmsghdr mmhdr = { 0 }; ++ ++ /* Enable 32 bit timeval precision and check if no 64 bit timeval stamp ++ is created. */ ++ { ++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP_OLD, &(int){1}, ++ sizeof (int)); ++ TEST_VERIFY_EXIT (r != -1); ++ ++ union ++ { ++ struct cmsghdr cmsghdr; ++ char msgbuf[CMSG_SPACE (sizeof (struct timeval))]; ++ } control; ++ ++ do_sendto (&srv_addr, 42); ++ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42); ++ ++ bool found_timestamp = false; ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET) ++ continue; ++ ++ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMP_NEW) ++ found_timestamp = true; ++ else ++ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMP_NEW); ++ } ++ ++ if (sizeof (time_t) > 4) ++ { ++ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC)); ++ TEST_COMPARE (found_timestamp, 0); ++ } ++ else ++ { ++ TEST_VERIFY (!(mmhdr.msg_hdr.msg_flags & MSG_CTRUNC)); ++ TEST_COMPARE (found_timestamp, 0); ++ } ++ } ++ ++ /* Same as before, but for timespec. */ ++ { ++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS_OLD, &(int){1}, ++ sizeof (int)); ++ TEST_VERIFY_EXIT (r != -1); ++ ++ union ++ { ++ struct cmsghdr cmsghdr; ++ char msgbuf[CMSG_SPACE (sizeof (struct timespec))]; ++ } control; ++ ++ do_sendto (&srv_addr, 42); ++ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42); ++ ++ bool found_timestamp = false; ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET) ++ continue; ++ ++ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMPNS_NEW) ++ found_timestamp = true; ++ else ++ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMPNS_NEW); ++ } ++ ++ if (sizeof (time_t) > 4) ++ { ++ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC)); ++ TEST_COMPARE (found_timestamp, 0); ++ } ++ else ++ { ++ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC) == 0); ++ TEST_COMPARE (found_timestamp, 0); ++ } ++ } ++} ++ ++static int ++do_test (void) ++{ ++ /* This test only make sense for ABIs that support 32 bit time_t socket ++ timestampss. */ ++ if (sizeof (time_t) > 4 && __WORDSIZE == 64) ++ return 0; ++ ++ srv = xsocket (AF_INET, SOCK_DGRAM, 0); ++ srv_addr = (struct sockaddr_in) { ++ .sin_family = AF_INET, ++ .sin_addr = {.s_addr = htonl (INADDR_LOOPBACK) }, ++ }; ++ xbind (srv, (struct sockaddr *) &srv_addr, sizeof (srv_addr)); ++ { ++ socklen_t sa_len = sizeof (srv_addr); ++ xgetsockname (srv, (struct sockaddr *) &srv_addr, &sa_len); ++ TEST_VERIFY (sa_len == sizeof (srv_addr)); ++ } ++ ++ /* Check recvmsg; */ ++ do_test_large_buffer (false); ++ do_test_small_buffer (false); ++ /* Check recvmmsg. */ ++ do_test_large_buffer (true); ++ do_test_small_buffer (true); ++ ++ return 0; ++} ++ ++#include +-- +2.27.0 + diff --git a/elf-Add-a-comment-after-trailing-backslashes.patch b/elf-Add-a-comment-after-trailing-backslashes.patch new file mode 100644 index 0000000..101371e --- /dev/null +++ b/elf-Add-a-comment-after-trailing-backslashes.patch @@ -0,0 +1,49 @@ +From 511b244cc55074dc7f8476c39598d5d00811963e Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Tue, 4 Jan 2022 06:58:34 -0800 +Subject: [PATCH] elf: Add a comment after trailing backslashes + +(cherry picked from commit f4f70c2895e3d325188a42c10eb7bb4335be6773) +--- + elf/Makefile | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/elf/Makefile b/elf/Makefile +index ec1cd49bb3..5859d47fc7 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -318,6 +318,7 @@ tests-cxx = \ + tst-nodelete \ + tst-unique3 \ + tst-unique4 \ ++# tests-cxx + + tests += $(if $(CXX),$(tests-cxx)) + tests-internal += loadtest unload unload2 circleload1 \ +@@ -582,6 +583,7 @@ modules-names = \ + vismod1 \ + vismod2 \ + vismod3 \ ++# modules-names + + modules-names-cxx = \ + tst-dlopen-nodelete-reloc-mod1 \ +@@ -607,6 +609,7 @@ modules-names-cxx = \ + tst-unique3lib \ + tst-unique3lib2 \ + tst-unique4lib \ ++# modules-names-cxx + + modules-names += \ + $(if $(CXX),$(modules-names-cxx)) \ +@@ -616,6 +619,7 @@ modules-names += \ + $(tst-tls-many-dynamic-modules-dep-bad) \ + $(tlsmod17a-modules) \ + $(tlsmod18a-modules) \ ++# modules-names + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +-- +2.27.0 + diff --git a/elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch b/elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch new file mode 100644 index 0000000..1d1f790 --- /dev/null +++ b/elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch @@ -0,0 +1,544 @@ +From de6cdd68753ed126a3ecf105d98e8c0ee8cb6ec4 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 14 Jan 2022 20:16:05 +0100 +Subject: [PATCH] elf/Makefile: Reflow and sort most variable assignments + +Reviewed-by: H.J. Lu +(cherry picked from commit 7de01e60c200c431d3469deb784da8fd4508fc15) +--- + elf/Makefile | 386 +++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 294 insertions(+), 92 deletions(-) + +diff --git a/elf/Makefile b/elf/Makefile +index 5859d47fc7..f930e04e27 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -21,21 +21,62 @@ subdir := elf + + include ../Makeconfig + +-headers = elf.h bits/elfclass.h link.h bits/link.h +-routines = $(all-dl-routines) dl-support dl-iteratephdr \ +- dl-addr dl-addr-obj enbl-secure dl-profstub \ +- dl-origin dl-libc dl-sym dl-sysdep dl-error \ +- dl-reloc-static-pie libc_early_init rtld_static_init ++headers = \ ++ bits/elfclass.h \ ++ bits/link.h \ ++ elf.h \ ++ link.h \ ++ # headers ++ ++routines = \ ++ $(all-dl-routines) \ ++ dl-addr \ ++ dl-addr-obj \ ++ dl-error \ ++ dl-iteratephdr \ ++ dl-libc \ ++ dl-origin \ ++ dl-profstub \ ++ dl-reloc-static-pie \ ++ dl-support \ ++ dl-sym \ ++ dl-sysdep \ ++ enbl-secure \ ++ libc_early_init \ ++ rtld_static_init \ ++ # routines + + # The core dynamic linking functions are in libc for the static and + # profiled libraries. +-dl-routines = $(addprefix dl-,load lookup object reloc deps \ +- runtime init fini debug misc \ +- version profile tls origin scope \ +- execstack open close trampoline \ +- exception sort-maps lookup-direct \ +- call-libc-early-init write \ +- thread_gscope_wait tls_init_tp) ++dl-routines = \ ++ dl-call-libc-early-init \ ++ dl-close \ ++ dl-debug \ ++ dl-deps \ ++ dl-exception \ ++ dl-execstack \ ++ dl-fini \ ++ dl-init \ ++ dl-load \ ++ dl-lookup \ ++ dl-lookup-direct \ ++ dl-misc \ ++ dl-object \ ++ dl-open \ ++ dl-origin \ ++ dl-profile \ ++ dl-reloc \ ++ dl-runtime \ ++ dl-scope \ ++ dl-sort-maps \ ++ dl-thread_gscope_wait \ ++ dl-tls \ ++ dl-tls_init_tp \ ++ dl-trampoline \ ++ dl-version \ ++ dl-write \ ++ # dl-routines ++ + ifeq (yes,$(use-ldconfig)) + dl-routines += dl-cache + endif +@@ -58,16 +99,38 @@ endif + + all-dl-routines = $(dl-routines) $(sysdep-dl-routines) + # But they are absent from the shared libc, because that code is in ld.so. +-elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ +- dl-sysdep dl-exception dl-reloc-static-pie \ +- thread_gscope_wait rtld_static_init ++elide-routines.os = \ ++ $(all-dl-routines) \ ++ dl-exception \ ++ dl-origin \ ++ dl-reloc-static-pie \ ++ dl-support \ ++ dl-sysdep \ ++ enbl-secure \ ++ rtld_static_init \ ++ thread_gscope_wait \ ++ # elide-routines.os + + # ld.so uses those routines, plus some special stuff for being the program + # interpreter and operating independent of libc. +-rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ +- dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \ +- dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu \ +- dl-mutex ++rtld-routines = \ ++ $(all-dl-routines) \ ++ dl-conflict \ ++ dl-diagnostics \ ++ dl-diagnostics-cpu \ ++ dl-diagnostics-kernel \ ++ dl-environ \ ++ dl-error-minimal \ ++ dl-hwcaps \ ++ dl-hwcaps-subdirs \ ++ dl-hwcaps_split \ ++ dl-minimal \ ++ dl-mutex \ ++ dl-sysdep \ ++ dl-usage \ ++ rtld \ ++ # rtld-routines ++ + all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) + + CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables +@@ -102,8 +165,16 @@ ld-map = $(common-objpfx)ld.map + endif + + ifeq (yes,$(build-shared)) +-extra-objs = $(all-rtld-routines:%=%.os) sofini.os interp.os +-generated += librtld.os dl-allobjs.os ld.so ldd ++extra-objs = \ ++ $(all-rtld-routines:%=%.os) \ ++ sofini.os \ ++ interp.os \ ++ # extra-objs ++generated += \ ++ dl-allobjs.os \ ++ ld.so ldd \ ++ librtld.os \ ++ # generated + install-others = $(inst_rtlddir)/$(rtld-installed-name) + install-bin-script = ldd + endif +@@ -121,8 +192,15 @@ others-static += ldconfig + others += ldconfig + install-rootsbin += ldconfig + +-ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs \ +- stringtable ++ldconfig-modules := \ ++ cache \ ++ chroot_canon \ ++ readlib \ ++ static-stubs \ ++ stringtable \ ++ xmalloc \ ++ xstrdup \ ++ # ldconfig-modules + extra-objs += $(ldconfig-modules:=.o) + others-extras = $(ldconfig-modules) + endif +@@ -156,23 +234,35 @@ $(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force) + $(do-install-program) + endif + +-tests-static-normal := tst-array1-static tst-array5-static \ +- tst-dl-iter-static \ +- tst-tlsalign-static tst-tlsalign-extern-static \ +- tst-linkall-static tst-env-setuid tst-env-setuid-tunables \ +- tst-single_threaded-static tst-single_threaded-pthread-static \ +- tst-dst-static tst-getauxval-static +- +-tests-static-internal := tst-tls1-static \ +- tst-ptrguard1-static tst-stackguard1-static \ +- tst-tls1-static-non-pie ++tests-static-normal := \ ++ tst-array1-static \ ++ tst-array5-static \ ++ tst-dl-iter-static \ ++ tst-dst-static \ ++ tst-env-setuid \ ++ tst-env-setuid-tunables \ ++ tst-getauxval-static \ ++ tst-linkall-static \ ++ tst-single_threaded-pthread-static \ ++ tst-single_threaded-static \ ++ tst-tlsalign-extern-static \ ++ tst-tlsalign-static \ ++ # tests-static-normal ++ ++tests-static-internal := \ ++ tst-ptrguard1-static \ ++ tst-stackguard1-static \ ++ tst-tls1-static \ ++ tst-tls1-static-non-pie \ ++ # tests-static-internal + + CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o + tst-tls1-static-non-pie-no-pie = yes + + tests-container := \ +- tst-ldconfig-bad-aux-cache \ +- tst-ldconfig-ld_so_conf-update ++ tst-ldconfig-bad-aux-cache \ ++ tst-ldconfig-ld_so_conf-update \ ++ # tests-container + + ifeq (no,$(build-hardcoded-path-in-tests)) + # This is an ld.so.cache test, and RPATH/RUNPATH in the executable +@@ -180,14 +271,31 @@ ifeq (no,$(build-hardcoded-path-in-tests)) + tests-container += tst-glibc-hwcaps-prepend-cache + endif + +-tests := tst-tls9 tst-leaks1 \ +- tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ +- tst-auxv tst-stringtable +-tests-internal := tst-tls1 $(tests-static-internal) ++tests := \ ++ tst-array1 \ ++ tst-array2 \ ++ tst-array3 \ ++ tst-array4 \ ++ tst-array5 \ ++ tst-auxv \ ++ tst-leaks1 \ ++ tst-stringtable \ ++ tst-tls9 \ ++ # tests ++ ++tests-internal := \ ++ $(tests-static-internal) \ ++ tst-tls1 \ ++ # tests-internal ++ + tests-static := $(tests-static-normal) $(tests-static-internal) + + ifeq (yes,$(build-shared)) +-tests-static += tst-tls9-static tst-single_threaded-static-dlopen ++tests-static += \ ++ tst-single_threaded-static-dlopen \ ++ tst-tls9-static \ ++ # tests-static ++ + static-dlopen-environment = \ + LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)dlfcn + tst-tls9-static-ENV = $(static-dlopen-environment) +@@ -312,33 +421,65 @@ tests += \ + unload6 \ + unload7 \ + unload8 \ +-# reldep9 ++ # tests + tests-cxx = \ + tst-dlopen-nodelete-reloc \ + tst-nodelete \ + tst-unique3 \ + tst-unique4 \ +-# tests-cxx ++ # tests-cxx + + tests += $(if $(CXX),$(tests-cxx)) +-tests-internal += loadtest unload unload2 circleload1 \ +- neededtest neededtest2 neededtest3 neededtest4 \ +- tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ +- tst-ptrguard1 tst-stackguard1 \ +- tst-create_format1 tst-tls-surplus tst-dl-hwcaps_split +-tests-container += tst-pldd tst-dlopen-tlsmodid-container \ +- tst-dlopen-self-container tst-preload-pthread-libc +-test-srcs = tst-pathopt ++tests-internal += \ ++ circleload1 \ ++ loadtest \ ++ neededtest \ ++ neededtest2 \ ++ neededtest3 \ ++ neededtest4 \ ++ tst-create_format1 \ ++ tst-dl-hwcaps_split \ ++ tst-dlmopen2 \ ++ tst-ptrguard1 \ ++ tst-stackguard1 \ ++ tst-tls-surplus \ ++ tst-tls3 \ ++ tst-tls6 \ ++ tst-tls7 \ ++ tst-tls8 \ ++ unload \ ++ unload2 \ ++ # tests-internal ++ ++tests-container += \ ++ tst-dlopen-self-container \ ++ tst-dlopen-tlsmodid-container \ ++ tst-pldd \ ++ tst-preload-pthread-libc \ ++ # tests-container ++ ++test-srcs = \ ++ tst-pathopt \ ++ # tests-srcs ++ + selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null) ++ + ifneq ($(selinux-enabled),1) +-tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog ++tests-execstack-yes = \ ++ tst-execstack \ ++ tst-execstack-needed \ ++ tst-execstack-prog \ ++ # tests-execstack-yes + endif + endif + tests += $(tests-execstack-$(have-z-execstack)) + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)tst-leaks1-mem.out \ +- $(objpfx)noload-mem.out \ +- $(objpfx)tst-ldconfig-X.out $(objpfx)tst-rtld-help.out ++tests-special += \ ++ $(objpfx)noload-mem.out \ ++ $(objpfx)tst-ldconfig-X.out \ ++ $(objpfx)tst-leaks1-mem.out \ ++ $(objpfx)tst-rtld-help.out \ ++ # tests-special + endif + tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +@@ -355,9 +496,16 @@ tst-tls-many-dynamic-modules-dep = \ + tst-tls-many-dynamic-modules-dep-bad-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + tst-tls-many-dynamic-modules-dep-bad = \ + $(foreach n,$(tst-tls-many-dynamic-modules-dep-bad-suffixes),tst-tls-manydynamic$(n)mod-dep-bad) +-extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \ +- tst-tlsalign-vars.o +-test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars ++extra-test-objs += \ ++ $(tlsmod17a-modules:=.os) \ ++ $(tlsmod18a-modules:=.os) \ ++ tst-tlsalign-vars.o \ ++ # extra-test-objs ++test-extras += \ ++ tst-tlsalign-vars \ ++ tst-tlsmod17a \ ++ tst-tlsmod18a \ ++ # test-extras + modules-names = \ + circlemod1 \ + circlemod1a \ +@@ -609,17 +757,17 @@ modules-names-cxx = \ + tst-unique3lib \ + tst-unique3lib2 \ + tst-unique4lib \ +-# modules-names-cxx ++ # modules-names-cxx + + modules-names += \ + $(if $(CXX),$(modules-names-cxx)) \ + $(modules-execstack-$(have-z-execstack)) \ ++ $(tlsmod17a-modules) \ ++ $(tlsmod18a-modules) \ + $(tst-tls-many-dynamic-modules) \ + $(tst-tls-many-dynamic-modules-dep) \ + $(tst-tls-many-dynamic-modules-dep-bad) \ +- $(tlsmod17a-modules) \ +- $(tlsmod18a-modules) \ +-# modules-names ++ # modules-names + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -668,35 +816,70 @@ modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod + tests += $(tests-static) + + ifeq (yes,$(have-ifunc)) +-tests-ifuncstatic := ifuncmain1static ifuncmain1picstatic \ +- ifuncmain2static ifuncmain2picstatic \ +- ifuncmain4static ifuncmain4picstatic \ +- ifuncmain5static ifuncmain5picstatic \ +- ifuncmain7static ifuncmain7picstatic ++tests-ifuncstatic := \ ++ ifuncmain1static \ ++ ifuncmain1picstatic \ ++ ifuncmain2static \ ++ ifuncmain2picstatic \ ++ ifuncmain4static \ ++ ifuncmain4picstatic \ ++ ifuncmain5static \ ++ ifuncmain5picstatic \ ++ ifuncmain7static \ ++ ifuncmain7picstatic \ ++ # tests-ifuncstatic + ifeq (yes,$(have-gcc-ifunc)) + tests-ifuncstatic += ifuncmain9static ifuncmain9picstatic + endif + tests-static += $(tests-ifuncstatic) + tests-internal += $(tests-ifuncstatic) + ifeq (yes,$(build-shared)) +-tests += tst-ifunc-fault-lazy tst-ifunc-fault-bindnow ++tests += \ ++ tst-ifunc-fault-bindnow \ ++ tst-ifunc-fault-lazy \ ++ # tests + # Note: sysdeps/x86_64/ifuncmain8.c uses ifuncmain8. + tests-internal += \ +- ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \ +- ifuncmain1staticpic \ +- ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 \ +- ifuncmain5 ifuncmain5pic ifuncmain5staticpic \ +- ifuncmain7 ifuncmain7pic ++ ifuncmain1 \ ++ ifuncmain1pic \ ++ ifuncmain1staticpic \ ++ ifuncmain1vis \ ++ ifuncmain1vispic \ ++ ifuncmain2 \ ++ ifuncmain2pic \ ++ ifuncmain3 \ ++ ifuncmain4 \ ++ ifuncmain5 \ ++ ifuncmain5pic \ ++ ifuncmain5staticpic \ ++ ifuncmain7 \ ++ ifuncmain7pic \ ++ # tests-internal + ifeq (yes,$(have-gcc-ifunc)) +-tests-internal += ifuncmain9 ifuncmain9pic ++tests-internal += \ ++ ifuncmain9 \ ++ ifuncmain9pic \ ++ # tests-internal + endif +-ifunc-test-modules = ifuncdep1 ifuncdep1pic ifuncdep2 ifuncdep2pic \ +- ifuncdep5 ifuncdep5pic ++ifunc-test-modules = \ ++ ifuncdep1 \ ++ ifuncdep1pic \ ++ ifuncdep2 \ ++ ifuncdep2pic \ ++ ifuncdep5 \ ++ ifuncdep5pic \ ++ # ifunc-test-modules + extra-test-objs += $(ifunc-test-modules:=.o) + test-internal-extras += $(ifunc-test-modules) + ifeq (yes,$(have-fpie)) +-ifunc-pie-tests = ifuncmain1pie ifuncmain1vispie ifuncmain1staticpie \ +- ifuncmain5pie ifuncmain6pie ifuncmain7pie ++ifunc-pie-tests = \ ++ ifuncmain1pie \ ++ ifuncmain1staticpie \ ++ ifuncmain1vispie \ ++ ifuncmain5pie \ ++ ifuncmain6pie \ ++ ifuncmain7pie \ ++ # ifunc-pie-tests + ifeq (yes,$(have-gcc-ifunc)) + ifunc-pie-tests += ifuncmain9pie + endif +@@ -706,30 +889,50 @@ endif + tests-internal += $(ifunc-pie-tests) + tests-pie += $(ifunc-pie-tests) + endif +-modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6 ++modules-names += \ ++ ifuncmod1 \ ++ ifuncmod3 \ ++ ifuncmod5 \ ++ ifuncmod6 \ ++ # module-names + endif + endif + + ifeq (yes,$(build-shared)) + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \ +- $(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out \ +- $(objpfx)tst-rtld-help.out ++tests-special += \ ++ $(objpfx)argv0test.out \ ++ $(objpfx)tst-pathopt.out \ ++ $(objpfx)tst-rtld-help.out \ ++ $(objpfx)tst-rtld-load-self.out \ ++ $(objpfx)tst-rtld-preload.out \ ++ # tests-special + endif +-tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \ +- $(objpfx)check-wx-segment.out \ +- $(objpfx)check-localplt.out $(objpfx)check-initfini.out ++tests-special += \ ++ $(objpfx)check-execstack.out \ ++ $(objpfx)check-initfini.out \ ++ $(objpfx)check-localplt.out \ ++ $(objpfx)check-textrel.out \ ++ $(objpfx)check-wx-segment.out \ ++ # tests-special + endif + + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \ +- $(objpfx)tst-array1-static-cmp.out \ +- $(objpfx)tst-array2-cmp.out $(objpfx)tst-array3-cmp.out \ +- $(objpfx)tst-array4-cmp.out $(objpfx)tst-array5-cmp.out \ +- $(objpfx)tst-array5-static-cmp.out $(objpfx)order2-cmp.out \ +- $(objpfx)tst-initorder-cmp.out \ +- $(objpfx)tst-initorder2-cmp.out $(objpfx)tst-unused-dep.out \ +- $(objpfx)tst-unused-dep-cmp.out ++tests-special += \ ++ $(objpfx)order-cmp.out \ ++ $(objpfx)order2-cmp.out \ ++ $(objpfx)tst-array1-cmp.out \ ++ $(objpfx)tst-array1-static-cmp.out \ ++ $(objpfx)tst-array2-cmp.out \ ++ $(objpfx)tst-array3-cmp.out \ ++ $(objpfx)tst-array4-cmp.out \ ++ $(objpfx)tst-array5-cmp.out \ ++ $(objpfx)tst-array5-static-cmp.out \ ++ $(objpfx)tst-initorder-cmp.out \ ++ $(objpfx)tst-initorder2-cmp.out \ ++ $(objpfx)tst-unused-dep-cmp.out \ ++ $(objpfx)tst-unused-dep.out \ ++ # tests-special + endif + + check-abi: $(objpfx)check-abi-ld.out +@@ -811,6 +1014,7 @@ rtld-stubbed-symbols = \ + free \ + malloc \ + realloc \ ++ # rtld-stubbed-symbols + + ifeq ($(have-ssp),yes) + # rtld is not built with the stack protector, so these references will +-- +2.27.0 + diff --git a/elf-Sort-tests-and-modules-names.patch b/elf-Sort-tests-and-modules-names.patch new file mode 100644 index 0000000..49bab1d --- /dev/null +++ b/elf-Sort-tests-and-modules-names.patch @@ -0,0 +1,546 @@ +From 31186e2cb74b2403726060276512c39cc89a1478 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Mon, 13 Dec 2021 09:43:52 -0800 +Subject: [PATCH] elf: Sort tests and modules-names + +Sort tests and modules-names to reduce future conflicts. + +(cherry picked from commit 28713c06129f8f64f88c423266e6ff2880216509) +--- + elf/Makefile | 512 ++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 385 insertions(+), 127 deletions(-) + +diff --git a/elf/Makefile b/elf/Makefile +index 118d579c42..ec1cd49bb3 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -193,39 +193,133 @@ static-dlopen-environment = \ + tst-tls9-static-ENV = $(static-dlopen-environment) + tst-single_threaded-static-dlopen-ENV = $(static-dlopen-environment) + +-tests += restest1 preloadtest loadfail multiload origtest resolvfail \ +- constload1 order noload filter \ +- reldep reldep2 reldep3 reldep4 nodelete nodelete2 \ +- nodlopen nodlopen2 lateglobal initfirst global \ +- restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ +- tst-tls4 tst-tls5 \ +- tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \ +- tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \ +- tst-align tst-align2 \ +- tst-dlmodcount tst-dlopenrpath tst-deep1 \ +- tst-dlmopen1 tst-dlmopen3 \ +- unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ +- tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ +- tst-addr1 tst-thrlock \ +- tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \ +- tst-nodelete tst-dlopen-nodelete-reloc) \ +- tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ +- tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ +- tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ +- tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ +- tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ +- 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-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \ +- tst-audit14 tst-audit15 tst-audit16 tst-audit17 \ +- tst-single_threaded tst-single_threaded-pthread \ +- tst-tls-ie tst-tls-ie-dlmopen argv0test \ +- tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ +- tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \ +- tst-dl-is_dso tst-ro-dynamic ++tests += \ ++ argv0test \ ++ constload1 \ ++ dblload \ ++ dblunload \ ++ filter \ ++ global \ ++ initfirst \ ++ lateglobal \ ++ loadfail \ ++ multiload \ ++ next \ ++ nodelete \ ++ nodelete2 \ ++ nodlopen \ ++ nodlopen2 \ ++ noload \ ++ order \ ++ order2 \ ++ origtest \ ++ preloadtest \ ++ reldep \ ++ reldep2 \ ++ reldep3 \ ++ reldep4 \ ++ reldep5 \ ++ reldep6 \ ++ reldep7 \ ++ reldep8 \ ++ resolvfail \ ++ restest1 \ ++ restest2 \ ++ tst-absolute-sym \ ++ tst-absolute-zero \ ++ tst-addr1 \ ++ tst-align \ ++ tst-align2 \ ++ tst-audit1 \ ++ tst-audit2 \ ++ tst-audit8 \ ++ tst-audit9 \ ++ tst-audit11 \ ++ tst-audit12 \ ++ tst-audit13 \ ++ tst-audit14 \ ++ tst-audit15 \ ++ tst-audit16 \ ++ tst-audit17 \ ++ tst-auditmany \ ++ tst-auxobj \ ++ tst-auxobj-dlopen \ ++ tst-big-note \ ++ tst-debug1 \ ++ tst-deep1 \ ++ tst-dl-is_dso \ ++ tst-dlmodcount \ ++ tst-dlmopen1 \ ++ tst-dlmopen3 \ ++ tst-dlmopen-dlerror \ ++ tst-dlmopen-gethostbyname \ ++ tst-dlopenfail \ ++ tst-dlopenfail-2 \ ++ tst-dlopenrpath \ ++ tst-dlopen-self \ ++ tst-dlopen-tlsmodid \ ++ tst-dlsym-error \ ++ tst-filterobj \ ++ tst-filterobj-dlopen \ ++ tst-glibc-hwcaps \ ++ tst-glibc-hwcaps-mask \ ++ tst-glibc-hwcaps-prepend \ ++ tst-global1 \ ++ tst-initfinilazyfail \ ++ tst-initorder \ ++ tst-initorder2 \ ++ tst-latepthread \ ++ tst-main1 \ ++ tst-nodelete2 \ ++ tst-nodelete-dlclose \ ++ tst-nodelete-opened \ ++ tst-noload \ ++ tst-null-argv \ ++ tst-relsort1 \ ++ tst-ro-dynamic \ ++ tst-single_threaded \ ++ tst-single_threaded-pthread \ ++ tst-sonamemove-dlopen \ ++ tst-sonamemove-link \ ++ tst-thrlock \ ++ tst-tls10 \ ++ tst-tls11 \ ++ tst-tls12 \ ++ tst-tls13 \ ++ tst-tls14 \ ++ tst-tls15 \ ++ tst-tls16 \ ++ tst-tls17 \ ++ tst-tls18 \ ++ tst-tls19 \ ++ tst-tls20 \ ++ tst-tls21 \ ++ tst-tls4 \ ++ tst-tls5 \ ++ tst-tlsalign \ ++ tst-tlsalign-extern \ ++ tst-tls-dlinfo \ ++ tst-tls-ie \ ++ tst-tls-ie-dlmopen \ ++ tst-tls-manydynamic \ ++ tst-unique1 \ ++ tst-unique2 \ ++ tst-unwind-ctor \ ++ tst-unwind-main \ ++ unload3 \ ++ unload4 \ ++ unload5 \ ++ unload6 \ ++ unload7 \ ++ unload8 \ + # reldep9 ++tests-cxx = \ ++ tst-dlopen-nodelete-reloc \ ++ tst-nodelete \ ++ tst-unique3 \ ++ tst-unique4 \ ++ ++tests += $(if $(CXX),$(tests-cxx)) + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ + tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ +@@ -263,101 +357,265 @@ tst-tls-many-dynamic-modules-dep-bad = \ + extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \ + tst-tlsalign-vars.o + test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars +-modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ +- testobj1_1 failobj constload2 constload3 unloadmod \ +- dep1 dep2 dep3 dep4 vismod1 vismod2 vismod3 \ +- nodelmod1 nodelmod2 nodelmod3 nodelmod4 \ +- nodel2mod1 nodel2mod2 nodel2mod3 \ +- nodlopenmod nodlopenmod2 filtmod1 filtmod2 \ +- reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \ +- reldep4mod1 reldep4mod2 reldep4mod3 reldep4mod4 \ +- neededobj1 neededobj2 neededobj3 neededobj4 \ +- neededobj5 neededobj6 firstobj globalmod1 \ +- unload2mod unload2dep ltglobmod1 ltglobmod2 pathoptobj \ +- dblloadmod1 dblloadmod2 dblloadmod3 reldepmod5 reldepmod6 \ +- reldep6mod0 reldep6mod1 reldep6mod2 reldep6mod3 reldep6mod4 \ +- reldep7mod1 reldep7mod2 \ +- tst-tlsmod1 tst-tlsmod2 tst-tlsmod3 tst-tlsmod4 \ +- tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \ +- tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \ +- tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \ +- tst-tlsmod15a tst-tlsmod15b tst-tlsmod16a tst-tlsmod16b \ +- $(tlsmod17a-modules) tst-tlsmod17b $(tlsmod18a-modules) \ +- tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \ +- circlemod1 circlemod1a circlemod2 circlemod2a \ +- circlemod3 circlemod3a \ +- reldep8mod1 reldep8mod2 reldep8mod3 \ +- reldep9mod1 reldep9mod2 reldep9mod3 \ +- tst-alignmod tst-alignmod2 \ +- $(modules-execstack-$(have-z-execstack)) \ +- tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \ +- tst-dlmopen1mod tst-auditmod1 \ +- unload3mod1 unload3mod2 unload3mod3 unload3mod4 \ +- unload4mod1 unload4mod2 unload4mod3 unload4mod4 \ +- unload6mod1 unload6mod2 unload6mod3 \ +- unload7mod1 unload7mod2 \ +- unload8mod1 unload8mod1x unload8mod2 unload8mod3 \ +- order2mod1 order2mod2 order2mod3 order2mod4 \ +- tst-unique1mod1 tst-unique1mod2 \ +- tst-unique2mod1 tst-unique2mod2 \ +- tst-auditmod9a tst-auditmod9b \ +- $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ +- tst-nodelete-uniquemod tst-nodelete-rtldmod \ +- tst-nodelete-zmod \ +- tst-dlopen-nodelete-reloc-mod1 \ +- tst-dlopen-nodelete-reloc-mod2 \ +- tst-dlopen-nodelete-reloc-mod3 \ +- tst-dlopen-nodelete-reloc-mod4 \ +- tst-dlopen-nodelete-reloc-mod5 \ +- tst-dlopen-nodelete-reloc-mod6 \ +- tst-dlopen-nodelete-reloc-mod7 \ +- tst-dlopen-nodelete-reloc-mod8 \ +- tst-dlopen-nodelete-reloc-mod9 \ +- tst-dlopen-nodelete-reloc-mod10 \ +- tst-dlopen-nodelete-reloc-mod11 \ +- tst-dlopen-nodelete-reloc-mod12 \ +- tst-dlopen-nodelete-reloc-mod13 \ +- tst-dlopen-nodelete-reloc-mod14 \ +- tst-dlopen-nodelete-reloc-mod15 \ +- tst-dlopen-nodelete-reloc-mod16 \ +- tst-dlopen-nodelete-reloc-mod17) \ +- tst-initordera1 tst-initorderb1 \ +- tst-initordera2 tst-initorderb2 \ +- tst-initordera3 tst-initordera4 \ +- tst-initorder2a tst-initorder2b tst-initorder2c \ +- tst-initorder2d \ +- tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \ +- tst-array5dep tst-null-argv-lib \ +- tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \ +- tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ +- tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \ +- tst-latepthreadmod $(tst-tls-many-dynamic-modules) \ +- $(tst-tls-many-dynamic-modules-dep) \ +- $(tst-tls-many-dynamic-modules-dep-bad) \ +- tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \ +- tst-main1mod tst-absolute-sym-lib \ +- tst-absolute-zero-lib tst-big-note-lib tst-unwind-ctor-lib \ +- tst-audit13mod1 tst-sonamemove-linkmod1 \ +- tst-sonamemove-runmod1 tst-sonamemove-runmod2 \ +- tst-auditmanymod1 tst-auditmanymod2 tst-auditmanymod3 \ +- tst-auditmanymod4 tst-auditmanymod5 tst-auditmanymod6 \ +- tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \ +- tst-initlazyfailmod tst-finilazyfailmod \ +- tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ +- tst-dlopenfailmod3 tst-dlopenfailnodelmod tst-ldconfig-ld-mod \ +- tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee \ +- tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 \ +- tst-single_threaded-mod1 tst-single_threaded-mod2 \ +- tst-single_threaded-mod3 tst-single_threaded-mod4 \ +- 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 libmarkermod1-1 libmarkermod1-2 libmarkermod1-3 \ +- libmarkermod2-1 libmarkermod2-2 \ +- libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \ +- libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ +- tst-tls20mod-bad tst-tls21mod tst-dlmopen-dlerror-mod \ +- tst-auxvalmod \ +- tst-dlmopen-gethostbyname-mod tst-ro-dynamic-mod \ ++modules-names = \ ++ circlemod1 \ ++ circlemod1a \ ++ circlemod2 \ ++ circlemod2a \ ++ circlemod3 \ ++ circlemod3a \ ++ constload2 \ ++ constload3 \ ++ dblloadmod1 \ ++ dblloadmod2 \ ++ dblloadmod3 \ ++ dep1 \ ++ dep2 \ ++ dep3 \ ++ dep4 \ ++ failobj \ ++ filtmod1 \ ++ filtmod2 \ ++ firstobj \ ++ globalmod1 \ ++ libmarkermod1-1 \ ++ libmarkermod1-2 \ ++ libmarkermod1-3 \ ++ libmarkermod2-1 \ ++ libmarkermod2-2 \ ++ libmarkermod3-1 \ ++ libmarkermod3-2 \ ++ libmarkermod3-3 \ ++ libmarkermod4-1 \ ++ libmarkermod4-2 \ ++ libmarkermod4-3 \ ++ libmarkermod4-4 \ ++ ltglobmod1 \ ++ ltglobmod2 \ ++ neededobj1 \ ++ neededobj2 \ ++ neededobj3 \ ++ neededobj4 \ ++ neededobj5 \ ++ neededobj6 \ ++ nextmod1 \ ++ nextmod2 \ ++ nodel2mod1 \ ++ nodel2mod2 \ ++ nodel2mod3 \ ++ nodelmod1 \ ++ nodelmod2 \ ++ nodelmod3 \ ++ nodelmod4 \ ++ nodlopenmod \ ++ nodlopenmod2 \ ++ order2mod1 \ ++ order2mod2 \ ++ order2mod3 \ ++ order2mod4 \ ++ pathoptobj \ ++ reldep4mod1 \ ++ reldep4mod2 \ ++ reldep4mod3 \ ++ reldep4mod4 \ ++ reldep6mod0 \ ++ reldep6mod1 \ ++ reldep6mod2 \ ++ reldep6mod3 \ ++ reldep6mod4 \ ++ reldep7mod1 \ ++ reldep7mod2 \ ++ reldep8mod1 \ ++ reldep8mod2 \ ++ reldep8mod3 \ ++ reldep9mod1 \ ++ reldep9mod2 \ ++ reldep9mod3 \ ++ reldepmod1 \ ++ reldepmod2 \ ++ reldepmod3 \ ++ reldepmod4 \ ++ reldepmod5 \ ++ reldepmod6 \ ++ testobj1 \ ++ testobj1_1 \ ++ testobj2 \ ++ testobj3 \ ++ testobj4 \ ++ testobj5 \ ++ testobj6 \ ++ tst-absolute-sym-lib \ ++ tst-absolute-zero-lib \ ++ tst-alignmod \ ++ tst-alignmod2 \ ++ tst-array2dep \ ++ tst-array5dep \ ++ tst-audit11mod1 \ ++ tst-audit11mod2 \ ++ tst-audit12mod1 \ ++ tst-audit12mod2 \ ++ tst-audit12mod3 \ ++ tst-audit13mod1 \ ++ tst-auditlogmod-1 \ ++ tst-auditlogmod-2 \ ++ tst-auditlogmod-3 \ ++ tst-auditmanymod1 \ ++ tst-auditmanymod2 \ ++ tst-auditmanymod3 \ ++ tst-auditmanymod4 \ ++ tst-auditmanymod5 \ ++ tst-auditmanymod6 \ ++ tst-auditmanymod7 \ ++ tst-auditmanymod8 \ ++ tst-auditmanymod9 \ ++ tst-auditmod1 \ ++ tst-auditmod9a \ ++ tst-auditmod9b \ ++ tst-auditmod11 \ ++ tst-auditmod12 \ ++ tst-auxvalmod \ ++ tst-big-note-lib \ ++ tst-deep1mod1 \ ++ tst-deep1mod2 \ ++ tst-deep1mod3 \ ++ tst-dlmopen1mod \ ++ tst-dlmopen-dlerror-mod \ ++ tst-dlmopen-gethostbyname-mod \ ++ tst-dlopenfaillinkmod \ ++ tst-dlopenfailmod1 \ ++ tst-dlopenfailmod2 \ ++ tst-dlopenfailmod3 \ ++ tst-dlopenfailnodelmod \ ++ tst-dlopenrpathmod \ ++ tst-filterobj-aux \ ++ tst-filterobj-filtee \ ++ tst-filterobj-flt \ ++ tst-finilazyfailmod \ ++ tst-initlazyfailmod \ ++ tst-initorder2a \ ++ tst-initorder2b \ ++ tst-initorder2c \ ++ tst-initorder2d \ ++ tst-initordera1 \ ++ tst-initordera2 \ ++ tst-initordera3 \ ++ tst-initordera4 \ ++ tst-initorderb1 \ ++ tst-initorderb2 \ ++ tst-latepthreadmod \ ++ tst-ldconfig-ld-mod \ ++ tst-main1mod \ ++ tst-nodelete2mod \ ++ tst-nodelete-dlclose-dso \ ++ tst-nodelete-dlclose-plugin \ ++ tst-nodelete-opened-lib \ ++ tst-null-argv-lib \ ++ tst-relsort1mod1 \ ++ tst-relsort1mod2 \ ++ tst-ro-dynamic-mod \ ++ tst-single_threaded-mod1 \ ++ tst-single_threaded-mod2 \ ++ tst-single_threaded-mod3 \ ++ tst-single_threaded-mod4 \ ++ tst-sonamemove-linkmod1 \ ++ tst-sonamemove-runmod1 \ ++ tst-sonamemove-runmod2 \ ++ tst-tls19mod1 \ ++ tst-tls19mod2 \ ++ tst-tls19mod3 \ ++ tst-tls20mod-bad \ ++ tst-tls21mod \ ++ tst-tlsalign-lib \ ++ tst-tls-ie-mod0 \ ++ tst-tls-ie-mod1 \ ++ tst-tls-ie-mod2 \ ++ tst-tls-ie-mod3 \ ++ tst-tls-ie-mod4 \ ++ tst-tls-ie-mod5 \ ++ tst-tls-ie-mod6 \ ++ tst-tlsmod1 \ ++ tst-tlsmod10 \ ++ tst-tlsmod11 \ ++ tst-tlsmod12 \ ++ tst-tlsmod13 \ ++ tst-tlsmod13a \ ++ tst-tlsmod14a \ ++ tst-tlsmod14b \ ++ tst-tlsmod15a \ ++ tst-tlsmod15b \ ++ tst-tlsmod16a \ ++ tst-tlsmod16b \ ++ tst-tlsmod17b \ ++ tst-tlsmod2 \ ++ tst-tlsmod3 \ ++ tst-tlsmod4 \ ++ tst-tlsmod5 \ ++ tst-tlsmod6 \ ++ tst-tlsmod7 \ ++ tst-tlsmod8 \ ++ tst-tlsmod9 \ ++ tst-unique1mod1 \ ++ tst-unique1mod2 \ ++ tst-unique2mod1 \ ++ tst-unique2mod2 \ ++ tst-unwind-ctor-lib \ ++ unload2dep \ ++ unload2mod \ ++ unload3mod1 \ ++ unload3mod2 \ ++ unload3mod3 \ ++ unload3mod4 \ ++ unload4mod1 \ ++ unload4mod2 \ ++ unload4mod3 \ ++ unload4mod4 \ ++ unload6mod1 \ ++ unload6mod2 \ ++ unload6mod3 \ ++ unload7mod1 \ ++ unload7mod2 \ ++ unload8mod1 \ ++ unload8mod1x \ ++ unload8mod2 \ ++ unload8mod3 \ ++ unloadmod \ ++ vismod1 \ ++ vismod2 \ ++ vismod3 \ ++ ++modules-names-cxx = \ ++ tst-dlopen-nodelete-reloc-mod1 \ ++ tst-dlopen-nodelete-reloc-mod10 \ ++ tst-dlopen-nodelete-reloc-mod11 \ ++ tst-dlopen-nodelete-reloc-mod12 \ ++ tst-dlopen-nodelete-reloc-mod13 \ ++ tst-dlopen-nodelete-reloc-mod14 \ ++ tst-dlopen-nodelete-reloc-mod15 \ ++ tst-dlopen-nodelete-reloc-mod16 \ ++ tst-dlopen-nodelete-reloc-mod17 \ ++ tst-dlopen-nodelete-reloc-mod2 \ ++ tst-dlopen-nodelete-reloc-mod3 \ ++ tst-dlopen-nodelete-reloc-mod4 \ ++ tst-dlopen-nodelete-reloc-mod5 \ ++ tst-dlopen-nodelete-reloc-mod6 \ ++ tst-dlopen-nodelete-reloc-mod7 \ ++ tst-dlopen-nodelete-reloc-mod8 \ ++ tst-dlopen-nodelete-reloc-mod9 \ ++ tst-nodelete-rtldmod \ ++ tst-nodelete-uniquemod \ ++ tst-nodelete-zmod \ ++ tst-unique3lib \ ++ tst-unique3lib2 \ ++ tst-unique4lib \ ++ ++modules-names += \ ++ $(if $(CXX),$(modules-names-cxx)) \ ++ $(modules-execstack-$(have-z-execstack)) \ ++ $(tst-tls-many-dynamic-modules) \ ++ $(tst-tls-many-dynamic-modules-dep) \ ++ $(tst-tls-many-dynamic-modules-dep-bad) \ ++ $(tlsmod17a-modules) \ ++ $(tlsmod18a-modules) \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 285c06c..93fedf4 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 52 +Release: 53 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -177,6 +177,18 @@ Patch89: x86-use-default-cache-size-if-it-cannot-be-determine.patch Patch90: x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch Patch91: x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch Patch92: linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch +Patch93: elf-Sort-tests-and-modules-names.patch +Patch94: elf-Add-a-comment-after-trailing-backslashes.patch +Patch95: elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch +Patch96: Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch +Patch97: x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch +Patch98: x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch +Patch99: support-Add-support_socket_so_timestamp_time64.patch +Patch100: linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch +Patch101: Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch +Patch102: socket-Do-not-use-AF_NETLINK-in-__opensock.patch +Patch103: tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch +Patch104: linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1280,6 +1292,12 @@ fi %endif %changelog +* Tue Feb 8 2022 Qingqing Li - 2.34-53 +- elf: fix glibc 2.34 ABI omission +- x86: black list more intel cpus for TSX [BZ #27398] +- recvmsg/recvmmsg: fix ancillary 64-bit time timestamp comversion [BZ #28349, BZ #28350] +- socket: do not use AF_NETLINK in __opensock + * Mon Feb 7 2022 Qingqing Li - 2.34-52 - fix misc/tst-glibcsyscalls failed due to kernel reserve some syscalls diff --git a/linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch b/linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch new file mode 100644 index 0000000..a4bf1ed --- /dev/null +++ b/linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch @@ -0,0 +1,457 @@ +From e098446037da532d4a250efac9a813bc22f3669f Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 24 Jan 2022 08:55:53 -0300 +Subject: [PATCH] linux: Fix ancillary 64-bit time timestamp conversion (BZ + #28349, BZ#28350) + +The __convert_scm_timestamps only updates the control message last +pointer for SOL_SOCKET type, so if the message control buffer contains +multiple ancillary message types the converted timestamp one might +overwrite a valid message. + +The test checks if the extra ancillary space is correctly handled +by recvmsg/recvmmsg, where if there is no extra space for the 64-bit +time_t converted message the control buffer should be marked with +MSG_TRUNC. It also check if recvmsg/recvmmsg handle correctly multiple +ancillary data. + +Checked on x86_64-linux and on i686-linux-gnu on both 5.11 and +4.15 kernel. + +Co-authored-by: Fabian Vogt + +Reviewed-by: Florian Weimer + +(cherry picked from commit 8fba672472ae0055387e9315fc2eddfa6775ca79) +--- + NEWS | 3 + + sysdeps/unix/sysv/linux/Makefile | 3 + + .../unix/sysv/linux/convert_scm_timestamps.c | 14 +- + .../sysv/linux/tst-socket-timestamp-time64.c | 1 + + .../unix/sysv/linux/tst-socket-timestamp.c | 336 ++++++++++++++++++ + 5 files changed, 351 insertions(+), 6 deletions(-) + create mode 100644 sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c + create mode 100644 sysdeps/unix/sysv/linux/tst-socket-timestamp.c + +diff --git a/NEWS b/NEWS +index db50b2af..e5225e9f 100644 +--- a/NEWS ++++ b/NEWS +@@ -26,6 +26,9 @@ The following bugs are resolved with this release: + [12889] nptl: Fix race between pthread_kill and thread exit + [19193] nptl: pthread_kill, pthread_cancel should not fail after exit + [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" ++ [28349] libc: Segfault for ping -R on qemux86 caused by recvmsg() ++ [28350] libc: ping receives SIGABRT on lib32-qemux86-64 caused by ++ recvmsg() + + + Version 2.34 +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 76ad0636..3399c874 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -262,6 +262,9 @@ sysdep_routines += cmsg_nxthdr + CFLAGS-recvmmsg.c = -fexceptions -fasynchronous-unwind-tables + CFLAGS-sendmmsg.c = -fexceptions -fasynchronous-unwind-tables + ++tests += tst-socket-timestamp ++tests-time64 += tst-socket-timestamp-time64 ++ + tests-special += $(objpfx)tst-socket-consts.out + $(objpfx)tst-socket-consts.out: ../sysdeps/unix/sysv/linux/tst-socket-consts.py + PYTHONPATH=../scripts \ +diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c +index 00c934c4..5d3c4199 100644 +--- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c ++++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c +@@ -54,6 +54,8 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize) + cmsg != NULL; + cmsg = CMSG_NXTHDR (msg, cmsg)) + { ++ last = cmsg; ++ + if (cmsg->cmsg_level != SOL_SOCKET) + continue; + +@@ -75,11 +77,9 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize) + tvts[1] = tmp[1]; + break; + } +- +- last = cmsg; + } + +- if (last == NULL || type == 0) ++ if (type == 0) + return; + + if (CMSG_SPACE (sizeof tvts) > msgsize - msg->msg_controllen) +@@ -88,10 +88,12 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize) + return; + } + ++ /* Zero memory for the new cmsghdr, so reading cmsg_len field ++ by CMSG_NXTHDR does not trigger UB. */ ++ memset (msg->msg_control + msg->msg_controllen, 0, ++ CMSG_SPACE (sizeof tvts)); + msg->msg_controllen += CMSG_SPACE (sizeof tvts); +- cmsg = CMSG_NXTHDR(msg, last); +- if (cmsg == NULL) +- return; ++ cmsg = CMSG_NXTHDR (msg, last); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = type; + cmsg->cmsg_len = CMSG_LEN (sizeof tvts); +diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c +new file mode 100644 +index 00000000..ae424c2a +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c +@@ -0,0 +1 @@ ++#include "tst-socket-timestamp.c" +diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp.c +new file mode 100644 +index 00000000..9c2e76f7 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp.c +@@ -0,0 +1,336 @@ ++/* Check recvmsg/recvmmsg 64-bit timestamp support. ++ Copyright (C) 2022 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Some extra space added for ancillary data, it might be used to convert ++ 32-bit timestamp to 64-bit for _TIME_BITS=64. */ ++enum { slack_max_size = 64 }; ++static const int slack[] = { 0, 4, 8, 16, 32, slack_max_size }; ++ ++static bool support_64_timestamp; ++/* AF_INET socket and address used to receive data. */ ++static int srv; ++static struct sockaddr_in srv_addr; ++ ++static int ++do_sendto (const struct sockaddr_in *addr, int nmsgs) ++{ ++ int s = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); ++ xconnect (s, (const struct sockaddr *) addr, sizeof (*addr)); ++ ++ for (int i = 0; i < nmsgs; i++) ++ xsendto (s, &i, sizeof (i), 0, (const struct sockaddr *) addr, ++ sizeof (*addr)); ++ ++ xclose (s); ++ ++ return 0; ++} ++ ++static void ++do_recvmsg_slack_ancillary (bool use_multi_call, int s, void *cmsg, ++ size_t slack, size_t tsize, int exp_payload) ++{ ++ int payload; ++ struct iovec iov = ++ { ++ .iov_base = &payload, ++ .iov_len = sizeof (payload) ++ }; ++ size_t msg_controllen = CMSG_SPACE (tsize) + slack; ++ char *msg_control = cmsg - msg_controllen; ++ memset (msg_control, 0x55, msg_controllen); ++ struct mmsghdr mmhdr = ++ { ++ .msg_hdr = ++ { ++ .msg_name = NULL, ++ .msg_namelen = 0, ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ .msg_control = msg_control, ++ .msg_controllen = msg_controllen ++ }, ++ }; ++ ++ int r; ++ if (use_multi_call) ++ { ++ r = recvmmsg (s, &mmhdr, 1, 0, NULL); ++ if (r >= 0) ++ r = mmhdr.msg_len; ++ } ++ else ++ r = recvmsg (s, &mmhdr.msg_hdr, 0); ++ TEST_COMPARE (r, sizeof (int)); ++ TEST_COMPARE (payload, exp_payload); ++ ++ if (cmsg == NULL) ++ return; ++ ++ /* A timestamp is expected if 32-bit timestamp are used (support in every ++ configuration) or if underlying kernel support 64-bit timestamps. ++ Otherwise recvmsg will need extra space do add the 64-bit timestamp. */ ++ bool exp_timestamp; ++ if (sizeof (time_t) == 4 || support_64_timestamp) ++ exp_timestamp = true; ++ else ++ exp_timestamp = slack >= CMSG_SPACE (tsize); ++ ++ bool timestamp = false; ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET) ++ continue; ++ if (cmsg->cmsg_type == SCM_TIMESTAMP ++ && cmsg->cmsg_len == CMSG_LEN (sizeof (struct timeval))) ++ { ++ struct timeval tv; ++ memcpy (&tv, CMSG_DATA (cmsg), sizeof (tv)); ++ if (test_verbose) ++ printf ("SCM_TIMESTAMP: {%jd, %jd}\n", (intmax_t)tv.tv_sec, ++ (intmax_t)tv.tv_usec); ++ timestamp = true; ++ } ++ else if (cmsg->cmsg_type == SCM_TIMESTAMPNS ++ && cmsg->cmsg_len == CMSG_LEN (sizeof (struct timespec))) ++ { ++ struct timespec ts; ++ memcpy (&ts, CMSG_DATA (cmsg), sizeof (ts)); ++ if (test_verbose) ++ printf ("SCM_TIMESTAMPNS: {%jd, %jd}\n", (intmax_t)ts.tv_sec, ++ (intmax_t)ts.tv_nsec); ++ timestamp = true; ++ } ++ } ++ ++ TEST_COMPARE (timestamp, exp_timestamp); ++} ++ ++/* Check if the extra ancillary space is correctly handled by recvmsg and ++ recvmmsg with different extra space for the ancillaty buffer. */ ++static void ++do_test_slack_space (void) ++{ ++ /* Setup the ancillary data buffer with an extra page with PROT_NONE to ++ check the possible timestamp conversion on some systems. */ ++ struct support_next_to_fault nf = ++ support_next_to_fault_allocate (slack_max_size); ++ void *msgbuf = nf.buffer + slack_max_size; ++ ++ /* Enable the timestamp using struct timeval precision. */ ++ { ++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP, &(int){1}, ++ sizeof (int)); ++ TEST_VERIFY_EXIT (r != -1); ++ } ++ /* Check recvmsg. */ ++ do_sendto (&srv_addr, array_length (slack)); ++ for (int s = 0; s < array_length (slack); s++) ++ { ++ memset (nf.buffer, 0x55, nf.length); ++ do_recvmsg_slack_ancillary (false, srv, msgbuf, slack[s], ++ sizeof (struct timeval), s); ++ } ++ /* Check recvmmsg. */ ++ do_sendto (&srv_addr, array_length (slack)); ++ for (int s = 0; s < array_length (slack); s++) ++ { ++ memset (nf.buffer, 0x55, nf.length); ++ do_recvmsg_slack_ancillary (true, srv, msgbuf, slack[s], ++ sizeof (struct timeval), s); ++ } ++ ++ /* Now enable timestamp using a higher precision, it overwrites the previous ++ precision. */ ++ { ++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS, &(int){1}, ++ sizeof (int)); ++ TEST_VERIFY_EXIT (r != -1); ++ } ++ /* Check recvmsg. */ ++ do_sendto (&srv_addr, array_length (slack)); ++ for (int s = 0; s < array_length (slack); s++) ++ do_recvmsg_slack_ancillary (false, srv, msgbuf, slack[s], ++ sizeof (struct timespec), s); ++ /* Check recvmmsg. */ ++ do_sendto (&srv_addr, array_length (slack)); ++ for (int s = 0; s < array_length (slack); s++) ++ do_recvmsg_slack_ancillary (true, srv, msgbuf, slack[s], ++ sizeof (struct timespec), s); ++ ++ support_next_to_fault_free (&nf); ++} ++ ++/* Check if the converted 64-bit timestamp is correctly appended when there ++ are multiple ancillary messages. */ ++static void ++do_recvmsg_multiple_ancillary (bool use_multi_call, int s, void *cmsg, ++ size_t cmsgsize, int exp_msg) ++{ ++ int msg; ++ struct iovec iov = ++ { ++ .iov_base = &msg, ++ .iov_len = sizeof (msg) ++ }; ++ size_t msgs = cmsgsize; ++ struct mmsghdr mmhdr = ++ { ++ .msg_hdr = ++ { ++ .msg_name = NULL, ++ .msg_namelen = 0, ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ .msg_controllen = msgs, ++ .msg_control = cmsg, ++ }, ++ }; ++ ++ int r; ++ if (use_multi_call) ++ { ++ r = recvmmsg (s, &mmhdr, 1, 0, NULL); ++ if (r >= 0) ++ r = mmhdr.msg_len; ++ } ++ else ++ r = recvmsg (s, &mmhdr.msg_hdr, 0); ++ TEST_COMPARE (r, sizeof (int)); ++ TEST_COMPARE (msg, exp_msg); ++ ++ if (cmsg == NULL) ++ return; ++ ++ bool timestamp = false; ++ bool origdstaddr = false; ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg)) ++ { ++ if (cmsg->cmsg_level == SOL_IP ++ && cmsg->cmsg_type == IP_ORIGDSTADDR ++ && cmsg->cmsg_len >= CMSG_LEN (sizeof (struct sockaddr_in))) ++ { ++ struct sockaddr_in sa; ++ memcpy (&sa, CMSG_DATA (cmsg), sizeof (sa)); ++ if (test_verbose) ++ { ++ char str[INET_ADDRSTRLEN]; ++ inet_ntop (AF_INET, &sa.sin_addr, str, INET_ADDRSTRLEN); ++ printf ("IP_ORIGDSTADDR: %s:%d\n", str, ntohs (sa.sin_port)); ++ } ++ origdstaddr = sa.sin_addr.s_addr == srv_addr.sin_addr.s_addr ++ && sa.sin_port == srv_addr.sin_port; ++ } ++ if (cmsg->cmsg_level == SOL_SOCKET ++ && cmsg->cmsg_type == SCM_TIMESTAMP ++ && cmsg->cmsg_len >= CMSG_LEN (sizeof (struct timeval))) ++ { ++ struct timeval tv; ++ memcpy (&tv, CMSG_DATA (cmsg), sizeof (tv)); ++ if (test_verbose) ++ printf ("SCM_TIMESTAMP: {%jd, %jd}\n", (intmax_t)tv.tv_sec, ++ (intmax_t)tv.tv_usec); ++ timestamp = true; ++ } ++ } ++ ++ TEST_COMPARE (timestamp, true); ++ TEST_COMPARE (origdstaddr, true); ++} ++ ++static void ++do_test_multiple_ancillary (void) ++{ ++ { ++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP, &(int){1}, ++ sizeof (int)); ++ TEST_VERIFY_EXIT (r != -1); ++ } ++ { ++ int r = setsockopt (srv, IPPROTO_IP, IP_RECVORIGDSTADDR, &(int){1}, ++ sizeof (int)); ++ TEST_VERIFY_EXIT (r != -1); ++ } ++ ++ /* Enougth data for default SO_TIMESTAMP, the IP_RECVORIGDSTADDR, and the ++ extra 64-bit SO_TIMESTAMP. */ ++ enum { msgbuflen = CMSG_SPACE (2 * sizeof (uint64_t)) ++ + CMSG_SPACE (sizeof (struct sockaddr_in)) ++ + CMSG_SPACE (2 * sizeof (uint64_t)) }; ++ char msgbuf[msgbuflen]; ++ ++ enum { nmsgs = 8 }; ++ /* Check recvmsg. */ ++ do_sendto (&srv_addr, nmsgs); ++ for (int s = 0; s < nmsgs; s++) ++ do_recvmsg_multiple_ancillary (false, srv, msgbuf, msgbuflen, s); ++ /* Check recvmmsg. */ ++ do_sendto (&srv_addr, nmsgs); ++ for (int s = 0; s < nmsgs; s++) ++ do_recvmsg_multiple_ancillary (true, srv, msgbuf, msgbuflen, s); ++} ++ ++static int ++do_test (void) ++{ ++ srv = xsocket (AF_INET, SOCK_DGRAM, 0); ++ srv_addr = (struct sockaddr_in) { ++ .sin_family = AF_INET, ++ .sin_addr = {.s_addr = htonl (INADDR_LOOPBACK) }, ++ }; ++ xbind (srv, (struct sockaddr *) &srv_addr, sizeof (srv_addr)); ++ { ++ socklen_t sa_len = sizeof (srv_addr); ++ xgetsockname (srv, (struct sockaddr *) &srv_addr, &sa_len); ++ TEST_VERIFY (sa_len == sizeof (srv_addr)); ++ } ++ ++ TEST_COMPARE (recvmsg (-1, NULL, 0), -1); ++ TEST_COMPARE (errno, EBADF); ++ TEST_COMPARE (recvmmsg (-1, NULL, 0, 0, NULL), -1); ++ TEST_COMPARE (errno, EBADF); ++ ++ /* If underlying kernel does not support */ ++ support_64_timestamp = support_socket_so_timestamp_time64 (srv); ++ ++ do_test_slack_space (); ++ do_test_multiple_ancillary (); ++ ++ xclose (srv); ++ ++ return 0; ++} ++ ++#include +-- +2.27.0 + diff --git a/linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch b/linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch new file mode 100644 index 0000000..bcfed33 --- /dev/null +++ b/linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch @@ -0,0 +1,37 @@ +From 0351c75c5f94134fcec0e778e8cf86d149f8bbfb Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Thu, 3 Feb 2022 16:52:52 -0300 +Subject: [PATCH] linux: Fix missing __convert_scm_timestamps (BZ #28860) + +Commit 948ce73b31 made recvmsg/recvmmsg to always call +__convert_scm_timestamps for 64 bit time_t symbol, so adjust it to +always build it for __TIMESIZE != 64. + +It fixes build for architecture with 32 bit time_t support when +configured with minimum kernel of 5.1. + +(cherry-picked from 798d716df71fb23dc89d1d5dba1fc26a1b5c0024) +--- + sysdeps/unix/sysv/linux/convert_scm_timestamps.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c +index 5d3c4199e0..953ce97bd2 100644 +--- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c ++++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c +@@ -16,9 +16,10 @@ + License along with the GNU C Library; if not, see + . */ + +-#include ++#include ++#include + +-#ifndef __ASSUME_TIME64_SYSCALLS ++#if __TIMESIZE != 64 + # include + # include + # include +-- +2.27.0 + diff --git a/socket-Do-not-use-AF_NETLINK-in-__opensock.patch b/socket-Do-not-use-AF_NETLINK-in-__opensock.patch new file mode 100644 index 0000000..d78b010 --- /dev/null +++ b/socket-Do-not-use-AF_NETLINK-in-__opensock.patch @@ -0,0 +1,40 @@ +From 6eaf10cbb78d22eae7999d9de55f6b93999e0860 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 22 Nov 2021 14:41:14 +0100 +Subject: [PATCH] socket: Do not use AF_NETLINK in __opensock + +It is not possible to use interface ioctls with netlink sockets +on all Linux kernels. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 3d981795cd00cc9b73c3ee5087c308361acd62e5) +--- + socket/opensock.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/socket/opensock.c b/socket/opensock.c +index ff94d27a61..3e35821f91 100644 +--- a/socket/opensock.c ++++ b/socket/opensock.c +@@ -24,17 +24,10 @@ + int + __opensock (void) + { +- /* SOCK_DGRAM is supported by all address families. (Netlink does +- not support SOCK_STREAM.) */ ++ /* SOCK_DGRAM is supported by all address families. */ + int type = SOCK_DGRAM | SOCK_CLOEXEC; + int fd; + +-#ifdef AF_NETLINK +- fd = __socket (AF_NETLINK, type, 0); +- if (fd >= 0) +- return fd; +-#endif +- + fd = __socket (AF_UNIX, type, 0); + if (fd >= 0) + return fd; +-- +2.27.0 + diff --git a/support-Add-support_socket_so_timestamp_time64.patch b/support-Add-support_socket_so_timestamp_time64.patch new file mode 100644 index 0000000..e6f9922 --- /dev/null +++ b/support-Add-support_socket_so_timestamp_time64.patch @@ -0,0 +1,103 @@ +From e09e7b1492b2d5c2f68ddf81f8f58e093dd4df6d Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 13 Dec 2021 11:36:42 -0300 +Subject: [PATCH] support: Add support_socket_so_timestamp_time64 + +Check if the socket support 64-bit network packages timestamps +(SO_TIMESTAMP and SO_TIMESTAMPNS). This will be used on recvmsg +and recvmmsg tests to check if the timestamp should be generated. + +Reviewed-by: Florian Weimer + +(cherry picked from 38bc0f4e78934aab455b31af05cefcbf3c22bece) +--- + support/Makefile | 1 + + support/support.h | 4 ++ + support/support_socket_so_timestamp_time64.c | 48 ++++++++++++++++++++ + 3 files changed, 53 insertions(+) + create mode 100644 support/support_socket_so_timestamp_time64.c + +diff --git a/support/Makefile b/support/Makefile +index 2a0731796f..724ae6d712 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -78,6 +78,7 @@ libsupport-routines = \ + support_set_small_thread_stack_size \ + support_shared_allocate \ + support_small_stack_thread_attribute \ ++ support_socket_so_timestamp_time64 \ + support_stat_nanoseconds \ + support_subprocess \ + support_test_compare_blob \ +diff --git a/support/support.h b/support/support.h +index c219e0d9d1..309be85b09 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -164,6 +164,10 @@ extern bool support_select_modifies_timeout (void); + tv_usec larger than 1000000. */ + extern bool support_select_normalizes_timeout (void); + ++/* Return true if socket FD supports 64-bit timestamps with the SOL_SOCKET ++ and SO_TIMESTAMP/SO_TIMESTAMPNS. */ ++extern bool support_socket_so_timestamp_time64 (int fd); ++ + /* Create a timer that trigger after SEC seconds and NSEC nanoseconds. If + REPEAT is true the timer will repeat indefinitely. If CALLBACK is not + NULL, the function will be called when the timer expires; otherwise a +diff --git a/support/support_socket_so_timestamp_time64.c b/support/support_socket_so_timestamp_time64.c +new file mode 100644 +index 0000000000..54bf3f4272 +--- /dev/null ++++ b/support/support_socket_so_timestamp_time64.c +@@ -0,0 +1,48 @@ ++/* Return whether socket supports 64-bit timestamps. ++ Copyright (C) 2022 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 ++#ifdef __linux__ ++# include ++#endif ++ ++bool ++support_socket_so_timestamp_time64 (int fd) ++{ ++#ifdef __linux__ ++# if __LINUX_KERNEL_VERSION >= 0x050100 \ ++ || __WORDSIZE == 64 \ ++ || (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64) ++ return true; ++# else ++ int level = SOL_SOCKET; ++ int optname = COMPAT_SO_TIMESTAMP_NEW; ++ int optval; ++ socklen_t len = sizeof (optval); ++ ++ int r = syscall (__NR_getsockopt, fd, level, optname, &optval, &len); ++ return r != -1; ++# endif ++#else ++ return false; ++#endif ++} +-- +2.27.0 + diff --git a/tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch b/tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch new file mode 100644 index 0000000..eeab0ad --- /dev/null +++ b/tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch @@ -0,0 +1,29 @@ +From 008003dc6e83439c5e04a744b7fd8197df19096e Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Sat, 29 Jan 2022 05:22:31 -0800 +Subject: [PATCH] tst-socket-timestamp-compat.c: Check __TIMESIZE [BZ #28837] + +time_t size is defined by __TIMESIZE, not __WORDSIZE. Check __TIMESIZE, +instead of __WORDSIZE, for time_t size. This fixes BZ #28837. + +(cherry pick from commit 77a602ebb0769e7ccc5f9f8e06f7fffe66f69dfc) +--- + sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c +index de261dae5a..0ff1a214e6 100644 +--- a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c ++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c +@@ -237,7 +237,7 @@ do_test (void) + { + /* This test only make sense for ABIs that support 32 bit time_t socket + timestampss. */ +- if (sizeof (time_t) > 4 && __WORDSIZE == 64) ++ if (sizeof (time_t) > 4 && __TIMESIZE == 64) + return 0; + + srv = xsocket (AF_INET, SOCK_DGRAM, 0); +-- +2.27.0 + diff --git a/x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch b/x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch new file mode 100644 index 0000000..67704e0 --- /dev/null +++ b/x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch @@ -0,0 +1,67 @@ +From b952c25dc7adf0684c53ad72d1d667da0348c929 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Fri, 14 Jan 2022 14:48:01 -0800 +Subject: [PATCH] x86: Black list more Intel CPUs for TSX [BZ #27398] + +Disable TSX and enable RTM_ALWAYS_ABORT for Intel CPUs listed in: + +https://www.intel.com/content/www/us/en/support/articles/000059422/processors.html + +This fixes BZ #27398. + +Reviewed-by: Noah Goldstein +(cherry picked from commit 1e000d3d33211d5a954300e2a69b90f93f18a1a1) +--- + sysdeps/x86/cpu-features.c | 34 +++++++++++++++++++++++++++++++--- + 1 file changed, 31 insertions(+), 3 deletions(-) + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 645bba6314..de4e3c3b72 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -507,11 +507,39 @@ init_cpu_features (struct cpu_features *cpu_features) + break; + } + +- /* Disable TSX on some Haswell processors to avoid TSX on kernels that +- weren't updated with the latest microcode package (which disables +- broken feature by default). */ ++ /* Disable TSX on some processors to avoid TSX on kernels that ++ weren't updated with the latest microcode package (which ++ disables broken feature by default). */ + switch (model) + { ++ case 0x55: ++ if (stepping <= 5) ++ goto disable_tsx; ++ break; ++ case 0x8e: ++ /* NB: Although the errata documents that for model == 0x8e, ++ only 0xb stepping or lower are impacted, the intention of ++ the errata was to disable TSX on all client processors on ++ all steppings. Include 0xc stepping which is an Intel ++ Core i7-8665U, a client mobile processor. */ ++ case 0x9e: ++ if (stepping > 0xc) ++ break; ++ /* Fall through. */ ++ case 0x4e: ++ case 0x5e: ++ { ++ /* Disable Intel TSX and enable RTM_ALWAYS_ABORT for ++ processors listed in: ++ ++https://www.intel.com/content/www/us/en/support/articles/000059422/processors.html ++ */ ++disable_tsx: ++ CPU_FEATURE_UNSET (cpu_features, HLE); ++ CPU_FEATURE_UNSET (cpu_features, RTM); ++ CPU_FEATURE_SET (cpu_features, RTM_ALWAYS_ABORT); ++ } ++ break; + case 0x3f: + /* Xeon E7 v3 with stepping >= 4 has working TSX. */ + if (stepping >= 4) +-- +2.27.0 + diff --git a/x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch b/x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch new file mode 100644 index 0000000..ecd4a42 --- /dev/null +++ b/x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch @@ -0,0 +1,29 @@ +From aa601d024424c40ae9a69b0c4e394a70ea0570c8 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Mon, 24 Jan 2022 19:33:43 -0800 +Subject: [PATCH] x86: Use CHECK_FEATURE_PRESENT to check HLE [BZ #27398] + +HLE is disabled on blacklisted CPUs. Use CHECK_FEATURE_PRESENT, instead +of CHECK_FEATURE_ACTIVE, to check HLE. + +(cherry picked from commit 501246c5e2dfcc278f0ebbdb72345cdd239521c7) +--- + sysdeps/x86/tst-cpu-features-supports.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c +index 9d76e6bd3f..faa5091b78 100644 +--- a/sysdeps/x86/tst-cpu-features-supports.c ++++ b/sysdeps/x86/tst-cpu-features-supports.c +@@ -130,7 +130,7 @@ do_test (int argc, char **argv) + fails += CHECK_FEATURE_ACTIVE (gfni, GFNI); + #endif + #if __GNUC_PREREQ (11, 0) +- fails += CHECK_FEATURE_ACTIVE (hle, HLE); ++ fails += CHECK_FEATURE_PRESENT (hle, HLE); + fails += CHECK_FEATURE_PRESENT (ibt, IBT); + fails += CHECK_FEATURE_ACTIVE (lahf_lm, LAHF64_SAHF64); + fails += CHECK_FEATURE_PRESENT (lm, LM); +-- +2.27.0 + -- Gitee From 1b7bed85e9cb17df982aaf4a914cd0e8ad4e4040 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 8 Feb 2022 15:42:22 +0800 Subject: [PATCH 53/70] disable rt/tst-cpuclock2 which often fails in CI. Signed-off-by: Yang Yanchao --- glibc.spec | 5 ++++- testsuite_whitelist.aarch64 | 4 ++++ testsuite_whitelist.x86_64 | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/glibc.spec b/glibc.spec index 93fedf4..0912a4f 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 53 +Release: 54 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -1292,6 +1292,9 @@ fi %endif %changelog +* Tue Feb 8 2022 Yang Yanchao - 2.34-54 +- disable rt/tst-cpuclock2 which often fails in CI. + * Tue Feb 8 2022 Qingqing Li - 2.34-53 - elf: fix glibc 2.34 ABI omission - x86: black list more intel cpus for TSX [BZ #27398] diff --git a/testsuite_whitelist.aarch64 b/testsuite_whitelist.aarch64 index 3e99a3d..bb0b3fa 100644 --- a/testsuite_whitelist.aarch64 +++ b/testsuite_whitelist.aarch64 @@ -109,3 +109,7 @@ nss/tst-nss-files-hosts-long # The test case fails due to OBS machine restrictions which can be passed locally. elf/tst-debug1 + +# This test case often fails in CI which is the high-pressure environment. +# No better solution is available. This test case is shielded. +rt/tst-cpuclock2 diff --git a/testsuite_whitelist.x86_64 b/testsuite_whitelist.x86_64 index 342591b..8a74a6f 100644 --- a/testsuite_whitelist.x86_64 +++ b/testsuite_whitelist.x86_64 @@ -110,3 +110,7 @@ elf/check-cet # Add the tst-nss-files-hosts-long.root/etc/hosts of glibc to # the /etc/hosts directory of the system, and then run sucess nss/tst-nss-files-hosts-long + +# This test case often fails in CI which is the high-pressure environment. +# No better solution is available. This test case is shielded. +rt/tst-cpuclock2 -- Gitee From 0e1ffabe6f90bd78a7182edfda6b55613cf6e9a9 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Wed, 9 Feb 2022 12:15:48 +0800 Subject: [PATCH 54/70] linux: fix accurarcy of get_nprocs and get_nprocs_conf [BZ #28865] --- glibc.spec | 6 +- ...cy-of-get_nprocs-and-get_nprocs_conf.patch | 212 ++++++++++++++++++ 2 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch diff --git a/glibc.spec b/glibc.spec index 0912a4f..437470c 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 54 +Release: 55 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -189,6 +189,7 @@ Patch101: Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch Patch102: socket-Do-not-use-AF_NETLINK-in-__opensock.patch Patch103: tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch Patch104: linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch +Patch105: linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1292,6 +1293,9 @@ fi %endif %changelog +* Wed Feb 9 2022 Qingqing Li - 2.34-55 +- linux: fix accurarcy of get_nprocs and get_nprocs_conf [BZ #28865] + * Tue Feb 8 2022 Yang Yanchao - 2.34-54 - disable rt/tst-cpuclock2 which often fails in CI. diff --git a/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch b/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch new file mode 100644 index 0000000..d16fa75 --- /dev/null +++ b/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch @@ -0,0 +1,212 @@ +From 007e054d786be340699c634e3a3b30ab1fde1a7a Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Sat, 5 Feb 2022 08:00:00 +0000 +Subject: [PATCH] linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ + #28865] + +get_nprocs() and get_nprocs_conf() use various methods to obtain an +accurate number of processors. Re-introduce __get_nprocs_sched() as +a source of information, and fix the order in which these methods are +used to return the most accurate information. The primary source of +information used in both functions remains unchanged. + +This also changes __get_nprocs_sched() error return value from 2 to 0, +but all its users are already prepared to handle that. + +Old fallback order: + get_nprocs: + /sys/devices/system/cpu/online -> /proc/stat -> 2 + get_nprocs_conf: + /sys/devices/system/cpu/ -> /proc/stat -> 2 + +New fallback order: + get_nprocs: + /sys/devices/system/cpu/online -> /proc/stat -> sched_getaffinity -> 2 + get_nprocs_conf: + /sys/devices/system/cpu/ -> /proc/stat -> sched_getaffinity -> 2 + +Fixes: 342298278e ("linux: Revert the use of sched_getaffinity on get_nproc") +Closes: BZ #28865 +Reviewed-by: Adhemerval Zanella + +(cherry picked from commit e1d32b836410767270a3adf1f82b1a47e6e4cd51) +--- + NEWS | 2 + + sysdeps/unix/sysv/linux/getsysstats.c | 94 ++++++++++++++++++--------- + 2 files changed, 65 insertions(+), 31 deletions(-) + +diff --git a/NEWS b/NEWS +index 87c9517e1a..aef051122e 100644 +--- a/NEWS ++++ b/NEWS +@@ -29,6 +29,8 @@ The following bugs are resolved with this release: + [28349] libc: Segfault for ping -R on qemux86 caused by recvmsg() + [28350] libc: ping receives SIGABRT on lib32-qemux86-64 caused by + recvmsg() ++ [28865] linux: _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN are inaccurate ++ without /sys and /proc + + + Version 2.34 +diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c +index 7babd947aa..327802b14c 100644 +--- a/sysdeps/unix/sysv/linux/getsysstats.c ++++ b/sysdeps/unix/sysv/linux/getsysstats.c +@@ -51,9 +51,8 @@ __get_nprocs_sched (void) + is an arbitrary values assuming such systems should be rare and there + is no offline cpus. */ + return max_num_cpus; +- /* Some other error. 2 is conservative (not a uniprocessor system, so +- atomics are needed). */ +- return 2; ++ /* Some other error. */ ++ return 0; + } + + static char * +@@ -109,22 +108,19 @@ next_line (int fd, char *const buffer, char **cp, char **re, + } + + static int +-get_nproc_stat (char *buffer, size_t buffer_size) ++get_nproc_stat (void) + { ++ enum { buffer_size = 1024 }; ++ char buffer[buffer_size]; + char *buffer_end = buffer + buffer_size; + char *cp = buffer_end; + char *re = buffer_end; +- +- /* Default to an SMP system in case we cannot obtain an accurate +- number. */ +- int result = 2; ++ int result = 0; + + const int flags = O_RDONLY | O_CLOEXEC; + int fd = __open_nocancel ("/proc/stat", flags); + if (fd != -1) + { +- result = 0; +- + char *l; + while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) + /* The current format of /proc/stat has all the cpu* entries +@@ -140,8 +136,8 @@ get_nproc_stat (char *buffer, size_t buffer_size) + return result; + } + +-int +-__get_nprocs (void) ++static int ++get_nprocs_cpu_online (void) + { + enum { buffer_size = 1024 }; + char buffer[buffer_size]; +@@ -180,7 +176,8 @@ __get_nprocs (void) + } + } + +- result += m - n + 1; ++ if (m >= n) ++ result += m - n + 1; + + l = endp; + if (l < re && *l == ',') +@@ -189,28 +186,18 @@ __get_nprocs (void) + while (l < re && *l != '\n'); + + __close_nocancel_nostatus (fd); +- +- if (result > 0) +- return result; + } + +- return get_nproc_stat (buffer, buffer_size); ++ return result; + } +-libc_hidden_def (__get_nprocs) +-weak_alias (__get_nprocs, get_nprocs) +- + +-/* On some architectures it is possible to distinguish between configured +- and active cpus. */ +-int +-__get_nprocs_conf (void) ++static int ++get_nprocs_cpu (void) + { +- /* Try to use the sysfs filesystem. It has actual information about +- online processors. */ ++ int count = 0; + DIR *dir = __opendir ("/sys/devices/system/cpu"); + if (dir != NULL) + { +- int count = 0; + struct dirent64 *d; + + while ((d = __readdir64 (dir)) != NULL) +@@ -225,12 +212,57 @@ __get_nprocs_conf (void) + + __closedir (dir); + +- return count; + } ++ return count; ++} + +- enum { buffer_size = 1024 }; +- char buffer[buffer_size]; +- return get_nproc_stat (buffer, buffer_size); ++static int ++get_nprocs_fallback (void) ++{ ++ int result; ++ ++ /* Try /proc/stat first. */ ++ result = get_nproc_stat (); ++ if (result != 0) ++ return result; ++ ++ /* Try sched_getaffinity. */ ++ result = __get_nprocs_sched (); ++ if (result != 0) ++ return result; ++ ++ /* We failed to obtain an accurate number. Be conservative: return ++ the smallest number meaning that this is not a uniprocessor system, ++ so atomics are needed. */ ++ return 2; ++} ++ ++int ++__get_nprocs (void) ++{ ++ /* Try /sys/devices/system/cpu/online first. */ ++ int result = get_nprocs_cpu_online (); ++ if (result != 0) ++ return result; ++ ++ /* Fall back to /proc/stat and sched_getaffinity. */ ++ return get_nprocs_fallback (); ++} ++libc_hidden_def (__get_nprocs) ++weak_alias (__get_nprocs, get_nprocs) ++ ++/* On some architectures it is possible to distinguish between configured ++ and active cpus. */ ++int ++__get_nprocs_conf (void) ++{ ++ /* Try /sys/devices/system/cpu/ first. */ ++ int result = get_nprocs_cpu (); ++ if (result != 0) ++ return result; ++ ++ /* Fall back to /proc/stat and sched_getaffinity. */ ++ return get_nprocs_fallback (); + } + libc_hidden_def (__get_nprocs_conf) + weak_alias (__get_nprocs_conf, get_nprocs_conf) +-- +2.27.0 + -- Gitee From 223e18c1a6244b0edf6170d9ee34e7afe8654990 Mon Sep 17 00:00:00 2001 From: shirely16 Date: Thu, 10 Feb 2022 19:55:09 +0800 Subject: [PATCH 55/70] remove nscd (cherry picked from commit b3377d2da5dc73eca67e2ac15399fc51fff19699) --- glibc-1070416.patch | 38 ------------------- glibc.spec | 91 +++++---------------------------------------- nscd.conf | 1 - 3 files changed, 10 insertions(+), 120 deletions(-) delete mode 100644 glibc-1070416.patch delete mode 100644 nscd.conf diff --git a/glibc-1070416.patch b/glibc-1070416.patch deleted file mode 100644 index 0975e0f..0000000 --- a/glibc-1070416.patch +++ /dev/null @@ -1,38 +0,0 @@ -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.spec b/glibc.spec index 437470c..a17ad05 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,13 +66,12 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 55 +Release: 56 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ Source0: https://ftp.gnu.org/gnu/glibc/%{name}-%{version}.tar.xz -Source1: nscd.conf Source2: nsswitch.conf Source3: bench.mk Source4: glibc-bench-compare @@ -84,7 +83,6 @@ Source7: replace_same_file_to_hard_link.py Source8: testsuite_whitelist.%{_target_cpu} %endif -Patch0: glibc-1070416.patch Patch1: glibc-c-utf8-locale.patch Patch2: backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch Patch3: backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch @@ -206,6 +204,7 @@ Patch9011: delete-check-installed-headers-c-and-check-installed.patch Patch9012: fix-CVE-2019-1010023.patch Patch9013: fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch +Obsoletes: nscd < 2.35 Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) BuildRequires: audit-libs-devel >= 1.1.3, sed >= 3.95, libcap-devel, gettext @@ -364,24 +363,6 @@ The glibc-devel package contains the object files necessary for developing programs which use the standard C libraries. Besides, it contains the headers. Thus, it is necessory to install glibc-devel if you ned develop programs. -############################################################################## -# glibc "nscd" sub-package -############################################################################## -%package -n nscd -Summary: Name caching service daemon. -Requires: %{name} = %{version}-%{release} -%if %{without bootstrap} -Requires: libselinux >= 1.17.10-1 -%endif -Requires: audit-libs >= 1.1.3 -Requires(pre): shadow-utils, coreutils -Requires: systemd -Requires(postun): shadow-utils - -%description -n nscd -The nscd package is able to daemon caches name service lookups and improve -the performance with LDAP. - ############################################################################## # nss modules sub-package ############################################################################## @@ -566,7 +547,8 @@ pushd $builddir %if 0%{rpm_version_ge_412} --disable-crypt \ %endif - || + --disable-build-nscd \ + --disable-nscd || { cat config.log; false; } make %{?_smp_mflags} -O -r %{glibc_make_flags} @@ -658,20 +640,11 @@ install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/etc/nsswitch.conf install -p -m 755 build-%{target}/nptl/libpthread-2.17.so $RPM_BUILD_ROOT%{_libdir} %endif -# This is for ncsd - in glibc 2.2 -install -m 644 nscd/nscd.conf $RPM_BUILD_ROOT/etc -mkdir -p $RPM_BUILD_ROOT%{_tmpfilesdir} -install -m 644 %{SOURCE1} %{buildroot}%{_tmpfilesdir} -mkdir -p $RPM_BUILD_ROOT/lib/systemd/system -install -m 644 nscd/nscd.service nscd/nscd.socket $RPM_BUILD_ROOT/lib/systemd/system - # Include ld.so.conf echo 'include ld.so.conf.d/*.conf' > $RPM_BUILD_ROOT/etc/ld.so.conf truncate -s 0 $RPM_BUILD_ROOT/etc/ld.so.cache chmod 644 $RPM_BUILD_ROOT/etc/ld.so.conf mkdir -p $RPM_BUILD_ROOT/etc/ld.so.conf.d -mkdir -p $RPM_BUILD_ROOT/etc/sysconfig -truncate -s 0 $RPM_BUILD_ROOT/etc/sysconfig/nscd truncate -s 0 $RPM_BUILD_ROOT/etc/gai.conf # Include %{_libdir}/gconv/gconv-modules.cache @@ -723,10 +696,6 @@ popd rm -f $RPM_BUILD_ROOT%{_infodir}/dir %endif -mkdir -p $RPM_BUILD_ROOT/var/{db,run}/nscd -touch $RPM_BUILD_ROOT/var/{db,run}/nscd/{passwd,group,hosts,services} -touch $RPM_BUILD_ROOT/var/run/nscd/{socket,nscd.pid} - mkdir -p $RPM_BUILD_ROOT%{_libdir} mv -f $RPM_BUILD_ROOT/%{_lib}/lib{pcprofile,memusage}.so \ $RPM_BUILD_ROOT%{_libdir} @@ -755,7 +724,6 @@ 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 @@ -809,7 +777,6 @@ cat master.filelist \ -e '%{_libdir}/lib.*\.a' \ -e '%{_libdir}/.*\.o' \ -e '%{_libdir}/lib.*\.so' \ - -e 'nscd' \ -e '%{_prefix}/bin' \ -e '%{_prefix}/lib/locale' \ -e '%{_prefix}/sbin/[^i]' \ @@ -836,8 +803,7 @@ echo '%{_libdir}/libpcprofile.so' >> glibc.filelist ############################################################################## grep '%{_prefix}/bin' master.filelist > common.filelist grep '%{_prefix}/sbin' master.filelist \ - | grep -v '%{_prefix}/sbin/iconvconfig' \ - | grep -v 'nscd' >> common.filelist + | grep -v '%{_prefix}/sbin/iconvconfig' >> common.filelist grep '%{_prefix}/share' master.filelist \ | grep -v \ @@ -869,11 +835,6 @@ grep '%{_libdir}/lib.*\.a' < master.filelist \ >> devel.filelist -############################################################################## -# glibc "nscd" sub-package -############################################################################## -echo '%{_prefix}/sbin/nscd' > nscd.filelist - ############################################################################## # nss modules sub-package ############################################################################## @@ -1179,24 +1140,6 @@ if [ -L %{_prefix}/include/scsi ] ; then rm -f %{_prefix}/include/scsi fi -%pre -n nscd -getent group nscd >/dev/null || /usr/sbin/groupadd -g 28 -r nscd -getent passwd nscd >/dev/null || - /usr/sbin/useradd -M -o -r -d / -s /sbin/nologin \ - -c "NSCD Daemon" -u 28 -g nscd nscd - -%post -n nscd -%systemd_post nscd.service - -%preun -n nscd -%systemd_preun nscd.service - -%postun -n nscd -if test $1 = 0; then - /usr/sbin/userdel nscd > /dev/null 2>&1 || : -fi -%systemd_postun_with_restart nscd.service - ############################################################################## # Files list ############################################################################## @@ -1246,25 +1189,6 @@ fi %files -f devel.filelist devel -%files -f nscd.filelist -n nscd -%config(noreplace) /etc/nscd.conf -%dir %attr(0755,root,root) /var/run/nscd -%dir %attr(0755,root,root) /var/db/nscd -/lib/systemd/system/nscd.service -/lib/systemd/system/nscd.socket -%{_tmpfilesdir}/nscd.conf -%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/nscd.pid -%attr(0666,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/socket -%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/passwd -%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/group -%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/hosts -%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/services -%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/passwd -%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/group -%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/hosts -%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/services -%ghost %config(missingok,noreplace) /etc/sysconfig/nscd - %files -f nss_modules.filelist -n nss_modules /var/db/Makefile @@ -1293,6 +1217,11 @@ fi %endif %changelog +* Thu Feb 10 2022 jiangheng - 2.34-56 +- remove nscd; the functionality nscd currently provides can be + achieved by using systemd-resolved for DNS caching and the sssd + daemon for everything else + * Wed Feb 9 2022 Qingqing Li - 2.34-55 - linux: fix accurarcy of get_nprocs and get_nprocs_conf [BZ #28865] diff --git a/nscd.conf b/nscd.conf deleted file mode 100644 index 8a24a78..0000000 --- a/nscd.conf +++ /dev/null @@ -1 +0,0 @@ -d /run/nscd 0755 root root -- Gitee From 31a81545289cb9952a49d1c3e2cab82ee68875e9 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Tue, 22 Feb 2022 15:20:56 +0800 Subject: [PATCH 56/70] tzselect: use region to instead of country for extract timezone selection --- glibc.spec | 6 +- ...stead-of-country-for-extract-timezon.patch | 152 ++++++++++++++++++ 2 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 use-region-to-instead-of-country-for-extract-timezon.patch diff --git a/glibc.spec b/glibc.spec index a17ad05..82ef002 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 56 +Release: 57 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -203,6 +203,7 @@ Patch9010: 0009-add-unwind-with-longjmp.patch Patch9011: delete-check-installed-headers-c-and-check-installed.patch Patch9012: fix-CVE-2019-1010023.patch Patch9013: fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch +Patch9014: use-region-to-instead-of-country-for-extract-timezon.patch Obsoletes: nscd < 2.35 Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1217,6 +1218,9 @@ fi %endif %changelog +* Tue Feb 22 2022 Qingqing Li - 2.34-57 +- tzselect: use region to instead of country for extract timezone selection. + * Thu Feb 10 2022 jiangheng - 2.34-56 - remove nscd; the functionality nscd currently provides can be achieved by using systemd-resolved for DNS caching and the sssd diff --git a/use-region-to-instead-of-country-for-extract-timezon.patch b/use-region-to-instead-of-country-for-extract-timezon.patch new file mode 100644 index 0000000..7e8eb07 --- /dev/null +++ b/use-region-to-instead-of-country-for-extract-timezon.patch @@ -0,0 +1,152 @@ +From 1c20cf491471a4a70f103a9d052fcca993eaa341 Mon Sep 17 00:00:00 2001 +From: Qingqing Li +Date: Tue, 22 Feb 2022 15:00:55 +0800 +Subject: [PATCH] use region to instead of country for extract timezone + selection. +Co-authored-by: liusirui +--- + timezone/tzselect.ksh | 97 +++++++++---------------------------------- + 1 file changed, 20 insertions(+), 77 deletions(-) + +diff --git a/timezone/tzselect.ksh b/timezone/tzselect.ksh +index 18fce27e..414bfa2a 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,38 @@ 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.27.0 + -- Gitee From 14ed19693b3e817bf4f4a9197fd82b6681c2ba6f Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Wed, 23 Feb 2022 10:47:47 +0800 Subject: [PATCH 57/70] - The release of glibc.src.rpm in OpenEuler is not based on the architecture. Developers only have glibc.src.rpm in the ARM, so add all testsuite_whitelist in glibc.src.rpm. Signed-off-by: Yang Yanchao --- glibc.spec | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/glibc.spec b/glibc.spec index 82ef002..a20e3f7 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 57 +Release: 58 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -80,7 +80,8 @@ Source6: LicenseList Source7: replace_same_file_to_hard_link.py %if %{with testsuite} -Source8: testsuite_whitelist.%{_target_cpu} +Source8: testsuite_whitelist.aarch64 +Source9: testsuite_whitelist.x86_64 %endif Patch1: glibc-c-utf8-locale.patch @@ -928,7 +929,7 @@ fi grep -v ^PASS: tests.sum | grep -v ^UNSUPPORTED > rpmbuild.tests.sum.not-passing || true # Delete the testsuite from the whitelist -cp %{SOURCE8} testsuite_whitelist +cp $RPM_SOURCE_DIR/testsuite_whitelist.%{_target_cpu} testsuite_whitelist omit_testsuite testsuite_whitelist rm -rf testsuite_whitelist @@ -1218,6 +1219,10 @@ fi %endif %changelog +* Wed Feb 23 2022 Yang Yanchao - 2.34-58 +- The release of glibc.src.rpm in OpenEuler is not based on the architecture. + Developers only have glibc.src.rpm in the ARM, so add all testsuite_whitelist in glibc.src.rpm. + * Tue Feb 22 2022 Qingqing Li - 2.34-57 - tzselect: use region to instead of country for extract timezone selection. -- Gitee From 03b9b275269e525a8b8c66414417b1193ea4c208 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Wed, 23 Feb 2022 15:34:35 +0800 Subject: [PATCH 58/70] strcmp: delete align for loop_aligned In Kunpeng-920, the performance of strcmp deteriorates only when the 16 to 23 characters are different.Or the string is only 16-23 characters.That shows 2 misses per iteration which means this is a branch predictor issue indeed. In the preceding scenario, strcmp performance is 300% worse than expected. Fortunately, this problem can be solved by modifying the alignment of the functions. Signed-off-by: Yang Yanchao --- glibc.spec | 6 +++- strcmp-delete-align-for-loop_aligned.patch | 32 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 strcmp-delete-align-for-loop_aligned.patch diff --git a/glibc.spec b/glibc.spec index a20e3f7..9775f96 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 58 +Release: 59 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -205,6 +205,7 @@ Patch9011: delete-check-installed-headers-c-and-check-installed.patch Patch9012: fix-CVE-2019-1010023.patch Patch9013: fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch Patch9014: use-region-to-instead-of-country-for-extract-timezon.patch +Patch9015: strcmp-delete-align-for-loop_aligned.patch Obsoletes: nscd < 2.35 Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1219,6 +1220,9 @@ fi %endif %changelog +* Wed Feb 23 2022 Yang Yanchao - 2.34-59 +- strcmp: delete align for loop_aligned + * Wed Feb 23 2022 Yang Yanchao - 2.34-58 - The release of glibc.src.rpm in OpenEuler is not based on the architecture. Developers only have glibc.src.rpm in the ARM, so add all testsuite_whitelist in glibc.src.rpm. diff --git a/strcmp-delete-align-for-loop_aligned.patch b/strcmp-delete-align-for-loop_aligned.patch new file mode 100644 index 0000000..cf5b15a --- /dev/null +++ b/strcmp-delete-align-for-loop_aligned.patch @@ -0,0 +1,32 @@ +From 9bbffed83b93f633b272368fc536a4f24e9942e6 Mon Sep 17 00:00:00 2001 +From: Yang Yanchao +Date: Mon, 21 Feb 2022 14:25:25 +0800 +Subject: [PATCH] strcmp: delete align for loop_aligned + +In Kunpeng-920, the performance of strcmp deteriorates only +when the 16 to 23 characters are different.Or the string is +only 16-23 characters.That shows 2 misses per iteration which +means this is a branch predictor issue indeed. +In the preceding scenario, strcmp performance is 300% worse than expected. + +Fortunately, this problem can be solved by modifying the alignment of the functions. +--- + sysdeps/aarch64/strcmp.S | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/sysdeps/aarch64/strcmp.S b/sysdeps/aarch64/strcmp.S +index f225d718..7a048b66 100644 +--- a/sysdeps/aarch64/strcmp.S ++++ b/sysdeps/aarch64/strcmp.S +@@ -71,8 +71,6 @@ ENTRY(strcmp) + b.ne L(misaligned8) + cbnz tmp, L(mutual_align) + +- .p2align 4 +- + L(loop_aligned): + ldr data2, [src1, off2] + ldr data1, [src1], 8 +-- +2.33.0 + -- Gitee From 6b2193619972e95fba241638e1bb676969cf343b Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Thu, 24 Feb 2022 11:18:39 +0800 Subject: [PATCH 59/70] Only in the CI environment, the build is interrupted due to test case failure. Signed-off-by: Yang Yanchao --- glibc.spec | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/glibc.spec b/glibc.spec index 9775f96..32e8f7e 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 59 +Release: 60 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -949,7 +949,9 @@ if test -s rpmbuild.tests.sum.not-passing ; then fi done done - 2.34-60 +- Only in the CI environment, the build is interrupted due to test case failure. + * Wed Feb 23 2022 Yang Yanchao - 2.34-59 - strcmp: delete align for loop_aligned -- Gitee From 9042da8301adbdbea607cd0dbd4c26500a363fb5 Mon Sep 17 00:00:00 2001 From: qinyu Date: Tue, 1 Mar 2022 09:33:17 +0800 Subject: [PATCH 60/70] glibc: add supposrt for rseq add rseq support Signed-off-by: qinyu (cherry picked from commit db74864101252bb75250782ca32e47d1b1545c1f) --- glibc.spec | 14 +- ...inux-Use-ptrdiff_t-for-__rseq_offset.patch | 197 +++ ...-Use-rseq-to-accelerate-sched_getcpu.patch | 48 + ...thread.rseq-tunable-to-control-rseq-.patch | 292 +++++ ...d-public-rseq-symbols-and-sys-rseq.h.patch | 692 ++++++++++ rseq-nptl-Add-rseq-registration.patch | 1165 +++++++++++++++++ ...pointer.h-for-defining-__thread_poin.patch | 141 ++ ...ptl-Introduce-THREAD_GETMEM_VOLATILE.patch | 56 + ...e-tcb-access.h-for-THREAD_-accessors.patch | 935 +++++++++++++ ...e-after-registration-on-main-thread-.patch | 44 + 10 files changed, 3583 insertions(+), 1 deletion(-) create mode 100644 rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch create mode 100644 rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch create mode 100644 rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch create mode 100644 rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch create mode 100644 rseq-nptl-Add-rseq-registration.patch create mode 100644 rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch create mode 100644 rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch create mode 100644 rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch create mode 100644 rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch diff --git a/glibc.spec b/glibc.spec index 32e8f7e..114a83f 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 60 +Release: 61 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -189,6 +189,15 @@ Patch102: socket-Do-not-use-AF_NETLINK-in-__opensock.patch Patch103: tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch Patch104: linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch Patch105: linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch +Patch106: rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch +Patch107: rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch +Patch108: rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch +Patch109: rseq-nptl-Add-rseq-registration.patch +Patch110: rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch +Patch111: rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch +Patch112: rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch +Patch113: rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch +Patch114: rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1222,6 +1231,9 @@ fi %endif %changelog +* Fri Feb 25 2022 qinyu - 2.34-61 +- add rseq support + * Thu Feb 24 2022 Yang Yanchao - 2.34-60 - Only in the CI environment, the build is interrupted due to test case failure. diff --git a/rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch b/rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch new file mode 100644 index 0000000..1485892 --- /dev/null +++ b/rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch @@ -0,0 +1,197 @@ +From 6cb5cc084432eba1f2215ec7c9816b748c32182a Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 2 Feb 2022 22:37:20 +0100 +Subject: [PATCH 9/9] Linux: Use ptrdiff_t for __rseq_offset + +This matches the data size initial-exec relocations use on most +targets. + +Reviewed-by: Mathieu Desnoyers +Reviewed-by: Carlos O'Donell +--- + manual/threads.texi | 2 +- + sysdeps/nptl/dl-tls_init_tp.c | 4 ++-- + sysdeps/unix/sysv/linux/aarch64/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/alpha/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/ia64/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist | 2 +- + sysdeps/unix/sysv/linux/sys/rseq.h | 3 ++- + sysdeps/unix/sysv/linux/x86_64/64/ld.abilist | 2 +- + 13 files changed, 15 insertions(+), 14 deletions(-) + +diff --git a/manual/threads.texi b/manual/threads.texi +index ab44a92c..4b9fc946 100644 +--- a/manual/threads.texi ++++ b/manual/threads.texi +@@ -1004,7 +1004,7 @@ The manual for the @code{rseq} system call can be found + at @uref{https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2}. + @end deftp + +-@deftypevar {int} __rseq_offset ++@deftypevar {ptrdiff_t} __rseq_offset + @standards{Linux, sys/rseq.h} + This variable contains the offset between the thread pointer (as defined + by @code{__builtin_thread_pointer} or the thread pointer register for +diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c +index 4a73927f..86e87c7d 100644 +--- a/sysdeps/nptl/dl-tls_init_tp.c ++++ b/sysdeps/nptl/dl-tls_init_tp.c +@@ -46,7 +46,7 @@ rtld_mutex_dummy (pthread_mutex_t *lock) + + const unsigned int __rseq_flags; + const unsigned int __rseq_size attribute_relro; +-const int __rseq_offset attribute_relro; ++const ptrdiff_t __rseq_offset attribute_relro; + + void + __tls_pre_init_tp (void) +@@ -119,7 +119,7 @@ __tls_init_tp (void) + all targets support __thread_pointer, so set __rseq_offset only + if thre rseq registration may have happened because RSEQ_SIG is + defined. */ +- extern int offset __asm__ ("__rseq_offset"); ++ extern ptrdiff_t offset __asm__ ("__rseq_offset"); + offset = (char *) &pd->rseq_area - (char *) __thread_pointer (); + #endif + } +diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist +index bf4d4f9b..5151c078 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist +@@ -5,5 +5,5 @@ GLIBC_2.17 _dl_mcount F + GLIBC_2.17 _r_debug D 0x28 + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist +index a23325a5..3e296c54 100644 +--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist ++++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist +@@ -4,6 +4,6 @@ GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x8 +diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist +index 8ccb5be9..5471b24d 100644 +--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist +@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist +index 37a47ebc..f26e594a 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist +@@ -4,6 +4,6 @@ GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x8 +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist +index da24dc7f..21f472e6 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist +@@ -6,5 +6,5 @@ GLIBC_2.3 _dl_mcount F + GLIBC_2.3 _r_debug D 0x28 + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist +index b9ae89ae..9c9c4045 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist +@@ -6,5 +6,5 @@ GLIBC_2.22 __tls_get_addr_opt F + GLIBC_2.23 __parse_hwcap_and_convert_at_platform F + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist +index 48431c91..a7758a0e 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist +@@ -5,5 +5,5 @@ GLIBC_2.27 _dl_mcount F + GLIBC_2.27 _r_debug D 0x28 + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist +index 117d1430..78d07160 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist +@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_offset F + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist +index 8ccb5be9..5471b24d 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist +@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h +index 1215b5d0..791ed831 100644 +--- a/sysdeps/unix/sysv/linux/sys/rseq.h ++++ b/sysdeps/unix/sysv/linux/sys/rseq.h +@@ -21,6 +21,7 @@ + /* Architecture-specific rseq signature. */ + #include + ++#include + #include + #include + #include +@@ -172,7 +173,7 @@ struct rseq + #endif /* __GLIBC_HAVE_KERNEL_RSEQ */ + + /* Offset from the thread pointer to the rseq area. */ +-extern const int __rseq_offset; ++extern const ptrdiff_t __rseq_offset; + + /* Size of the registered rseq area. 0 if the registration was + unsuccessful. */ +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist +index ae622bdf..5a8bd322 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist +@@ -4,5 +4,5 @@ GLIBC_2.2.5 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F + GLIBC_2.35 __rseq_flags D 0x4 +-GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_offset D 0x8 + GLIBC_2.35 __rseq_size D 0x4 +-- +2.23.0 + diff --git a/rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch b/rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch new file mode 100644 index 0000000..3e7548c --- /dev/null +++ b/rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch @@ -0,0 +1,48 @@ +From 00bae0eb5212a1ec4e8b4b90294937903628e7ce Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 9 Dec 2021 09:49:32 +0100 +Subject: [PATCH 5/9] Linux: Use rseq to accelerate sched_getcpu + +Co-Authored-By: Mathieu Desnoyers +Reviewed-by: Szabolcs Nagy +--- + sysdeps/unix/sysv/linux/sched_getcpu.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/sched_getcpu.c b/sysdeps/unix/sysv/linux/sched_getcpu.c +index c41e986f..6f78edae 100644 +--- a/sysdeps/unix/sysv/linux/sched_getcpu.c ++++ b/sysdeps/unix/sysv/linux/sched_getcpu.c +@@ -20,8 +20,8 @@ + #include + #include + +-int +-sched_getcpu (void) ++static int ++vsyscall_sched_getcpu (void) + { + unsigned int cpu; + int r = -1; +@@ -32,3 +32,18 @@ sched_getcpu (void) + #endif + return r == -1 ? r : cpu; + } ++ ++#ifdef RSEQ_SIG ++int ++sched_getcpu (void) ++{ ++ int cpu_id = THREAD_GETMEM_VOLATILE (THREAD_SELF, rseq_area.cpu_id); ++ return __glibc_likely (cpu_id >= 0) ? cpu_id : vsyscall_sched_getcpu (); ++} ++#else /* RSEQ_SIG */ ++int ++sched_getcpu (void) ++{ ++ return vsyscall_sched_getcpu (); ++} ++#endif /* RSEQ_SIG */ +-- +2.23.0 + diff --git a/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch b/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch new file mode 100644 index 0000000..6fb0aa6 --- /dev/null +++ b/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch @@ -0,0 +1,292 @@ +From ff1e1631665651ceb8b4b226ec725140c7420e8c Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 9 Dec 2021 09:49:32 +0100 +Subject: [PATCH 6/9] nptl: Add glibc.pthread.rseq tunable to control rseq + registration + +This tunable allows applications to register the rseq area instead +of glibc. + +Reviewed-by: Szabolcs Nagy +Reviewed-by: Siddhesh Poyarekar +--- + manual/tunables.texi | 10 +++ + nptl/pthread_create.c | 10 ++- + sysdeps/nptl/dl-tls_init_tp.c | 11 ++- + sysdeps/nptl/dl-tunables.list | 6 ++ + sysdeps/nptl/internaltypes.h | 1 + + sysdeps/unix/sysv/linux/Makefile | 8 ++ + sysdeps/unix/sysv/linux/rseq-internal.h | 19 +++-- + sysdeps/unix/sysv/linux/tst-rseq-disable.c | 89 ++++++++++++++++++++++ + 8 files changed, 145 insertions(+), 9 deletions(-) + create mode 100644 sysdeps/unix/sysv/linux/tst-rseq-disable.c + +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 658547c6..1f5c4102 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -413,6 +413,16 @@ The value is measured in bytes. The default is @samp{41943040} + (fourty mibibytes). + @end deftp + ++@deftp Tunable glibc.pthread.rseq ++The @code{glibc.pthread.rseq} tunable can be set to @samp{0}, to disable ++restartable sequences support in @theglibc{}. This enables applications ++to perform direct restartable sequence registration with the kernel. ++The default is @samp{1}, which means that @theglibc{} performs ++registration on behalf of the application. ++ ++Restartable sequences are a Linux-specific extension. ++@end deftp ++ + @node Hardware Capability Tunables + @section Hardware Capability Tunables + @cindex hardware capability tunables +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index d2b40924..f405fa35 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -369,7 +369,10 @@ start_thread (void *arg) + __ctype_init (); + + /* Register rseq TLS to the kernel. */ +- rseq_register_current_thread (pd); ++ { ++ bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ; ++ rseq_register_current_thread (pd, do_rseq); ++ } + + #ifndef __ASSUME_SET_ROBUST_LIST + if (__nptl_set_robust_list_avail) +@@ -678,6 +681,11 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, + pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) + | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))); + ++ /* Inherit rseq registration state. Without seccomp filters, rseq ++ registration will either always fail or always succeed. */ ++ if ((int) THREAD_GETMEM_VOLATILE (self, rseq_area.cpu_id) >= 0) ++ pd->flags |= ATTR_FLAG_DO_RSEQ; ++ + /* Initialize the field for the ID of the thread which is waiting + for us. This is a self-reference in case the thread is created + detached. */ +diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c +index fedb876f..b39dfbff 100644 +--- a/sysdeps/nptl/dl-tls_init_tp.c ++++ b/sysdeps/nptl/dl-tls_init_tp.c +@@ -23,6 +23,9 @@ + #include + #include + ++#define TUNABLE_NAMESPACE pthread ++#include ++ + #ifndef __ASSUME_SET_ROBUST_LIST + bool __nptl_set_robust_list_avail; + rtld_hidden_data_def (__nptl_set_robust_list_avail) +@@ -92,7 +95,13 @@ __tls_init_tp (void) + } + } + +- rseq_register_current_thread (pd); ++ { ++ bool do_rseq = true; ++#if HAVE_TUNABLES ++ do_rseq = TUNABLE_GET (rseq, int, NULL); ++#endif ++ rseq_register_current_thread (pd, do_rseq); ++ } + + /* Set initial thread's stack block from 0 up to __libc_stack_end. + It will be bigger than it actually is, but for unwind.c/pt-longjmp.c +diff --git a/sysdeps/nptl/dl-tunables.list b/sysdeps/nptl/dl-tunables.list +index ac5d0532..d24f4be0 100644 +--- a/sysdeps/nptl/dl-tunables.list ++++ b/sysdeps/nptl/dl-tunables.list +@@ -27,5 +27,11 @@ glibc { + type: SIZE_T + default: 41943040 + } ++ rseq { ++ type: INT_32 ++ minval: 0 ++ maxval: 1 ++ default: 1 ++ } + } + } +diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h +index 50a2ad19..8205c6d1 100644 +--- a/sysdeps/nptl/internaltypes.h ++++ b/sysdeps/nptl/internaltypes.h +@@ -49,6 +49,7 @@ struct pthread_attr + #define ATTR_FLAG_OLDATTR 0x0010 + #define ATTR_FLAG_SCHED_SET 0x0020 + #define ATTR_FLAG_POLICY_SET 0x0040 ++#define ATTR_FLAG_DO_RSEQ 0x0080 + + /* Used to allocate a pthread_attr_t object which is also accessed + internally. */ +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index f103a964..0657f400 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -135,6 +135,12 @@ tests-internal += \ + tst-sigcontext-get_pc \ + # tests-internal + ++ifneq (no,$(have-tunables)) ++tests-internal += \ ++ tst-rseq-disable \ ++ # tests-internal $(have-tunables) ++endif ++ + tests-time64 += \ + tst-adjtimex-time64 \ + tst-clock_adjtime-time64 \ +@@ -226,6 +232,8 @@ $(objpfx)tst-mman-consts.out: ../sysdeps/unix/sysv/linux/tst-mman-consts.py + < /dev/null > $@ 2>&1; $(evaluate-test) + $(objpfx)tst-mman-consts.out: $(sysdeps-linux-python-deps) + ++tst-rseq-disable-ENV = GLIBC_TUNABLES=glibc.pthread.rseq=0 ++ + endif # $(subdir) == misc + + ifeq ($(subdir),time) +diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h +index 909f5478..15bc7ffd 100644 +--- a/sysdeps/unix/sysv/linux/rseq-internal.h ++++ b/sysdeps/unix/sysv/linux/rseq-internal.h +@@ -21,22 +21,27 @@ + #include + #include + #include ++#include + #include + #include + + #ifdef RSEQ_SIG + static inline void +-rseq_register_current_thread (struct pthread *self) ++rseq_register_current_thread (struct pthread *self, bool do_rseq) + { +- int ret = INTERNAL_SYSCALL_CALL (rseq, +- &self->rseq_area, sizeof (self->rseq_area), +- 0, RSEQ_SIG); +- if (INTERNAL_SYSCALL_ERROR_P (ret)) +- THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++ if (do_rseq) ++ { ++ int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area, ++ sizeof (self->rseq_area), ++ 0, RSEQ_SIG); ++ if (!INTERNAL_SYSCALL_ERROR_P (ret)) ++ return; ++ } ++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); + } + #else /* RSEQ_SIG */ + static inline void +-rseq_register_current_thread (struct pthread *self) ++rseq_register_current_thread (struct pthread *self, bool do_rseq) + { + THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); + } +diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c +new file mode 100644 +index 00000000..000e3518 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c +@@ -0,0 +1,89 @@ ++/* Test disabling of rseq registration via tunable. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 ++ ++#ifdef RSEQ_SIG ++ ++/* Check that rseq can be registered and has not been taken by glibc. */ ++static void ++check_rseq_disabled (void) ++{ ++ struct pthread *pd = THREAD_SELF; ++ TEST_COMPARE ((int) pd->rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++ ++ int ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area), ++ 0, RSEQ_SIG); ++ if (ret == 0) ++ { ++ ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area), ++ RSEQ_FLAG_UNREGISTER, RSEQ_SIG); ++ TEST_COMPARE (ret, 0); ++ pd->rseq_area.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED; ++ } ++ else ++ { ++ TEST_VERIFY (errno != -EINVAL); ++ TEST_VERIFY (errno != -EBUSY); ++ } ++} ++ ++static void * ++thread_func (void *ignored) ++{ ++ check_rseq_disabled (); ++ return NULL; ++} ++ ++static void ++proc_func (void *ignored) ++{ ++ check_rseq_disabled (); ++} ++ ++static int ++do_test (void) ++{ ++ puts ("info: checking main thread"); ++ check_rseq_disabled (); ++ ++ puts ("info: checking main thread (2)"); ++ check_rseq_disabled (); ++ ++ puts ("info: checking new thread"); ++ xpthread_join (xpthread_create (NULL, thread_func, NULL)); ++ ++ puts ("info: checking subprocess"); ++ support_isolate_in_subprocess (proc_func, NULL); ++ ++ return 0; ++} ++#else /* !RSEQ_SIG */ ++static int ++do_test (void) ++{ ++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test"); ++} ++#endif ++ ++#include +-- +2.23.0 + diff --git a/rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch b/rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch new file mode 100644 index 0000000..f4311c5 --- /dev/null +++ b/rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch @@ -0,0 +1,692 @@ +From e3291e074ff67a8cc2630ab6175976f875d61a14 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 17 Feb 2022 14:56:12 +0800 +Subject: [PATCH 7/9] nptl: Add public rseq symbols and + +The relationship between the thread pointer and the rseq area +is made explicit. The constant offset can be used by JIT compilers +to optimize rseq access (e.g., for really fast sched_getcpu). + +Extensibility is provided through __rseq_size and __rseq_flags. +(In the future, the kernel could request a different rseq size +via the auxiliary vector.) + +Co-Authored-By: Mathieu Desnoyers +Reviewed-by: Szabolcs Nagy +----- +conflicts: + context conflicts +--- + NEWS | 11 +++ + manual/threads.texi | 81 +++++++++++++++++++ + sysdeps/nptl/dl-tls_init_tp.c | 23 +++++- + sysdeps/unix/sysv/linux/Makefile | 3 +- + sysdeps/unix/sysv/linux/Versions | 5 ++ + sysdeps/unix/sysv/linux/aarch64/ld.abilist | 3 + + sysdeps/unix/sysv/linux/alpha/ld.abilist | 3 + + sysdeps/unix/sysv/linux/arc/ld.abilist | 3 + + sysdeps/unix/sysv/linux/arm/be/ld.abilist | 3 + + sysdeps/unix/sysv/linux/arm/le/ld.abilist | 3 + + sysdeps/unix/sysv/linux/csky/ld.abilist | 3 + + sysdeps/unix/sysv/linux/hppa/ld.abilist | 3 + + sysdeps/unix/sysv/linux/i386/ld.abilist | 3 + + sysdeps/unix/sysv/linux/ia64/ld.abilist | 3 + + .../unix/sysv/linux/m68k/coldfire/ld.abilist | 3 + + .../unix/sysv/linux/m68k/m680x0/ld.abilist | 3 + + sysdeps/unix/sysv/linux/microblaze/ld.abilist | 3 + + .../unix/sysv/linux/mips/mips32/ld.abilist | 3 + + .../sysv/linux/mips/mips64/n32/ld.abilist | 3 + + .../sysv/linux/mips/mips64/n64/ld.abilist | 3 + + sysdeps/unix/sysv/linux/nios2/ld.abilist | 3 + + .../sysv/linux/powerpc/powerpc32/ld.abilist | 3 + + .../linux/powerpc/powerpc64/be/ld.abilist | 3 + + .../linux/powerpc/powerpc64/le/ld.abilist | 3 + + sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist | 3 + + sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist | 3 + + sysdeps/unix/sysv/linux/rseq-internal.h | 8 +- + .../unix/sysv/linux/s390/s390-32/ld.abilist | 3 + + .../unix/sysv/linux/s390/s390-64/ld.abilist | 3 + + sysdeps/unix/sysv/linux/sh/be/ld.abilist | 3 + + sysdeps/unix/sysv/linux/sh/le/ld.abilist | 3 + + .../unix/sysv/linux/sparc/sparc32/ld.abilist | 3 + + .../unix/sysv/linux/sparc/sparc64/ld.abilist | 3 + + sysdeps/unix/sysv/linux/sys/rseq.h | 10 +++ + sysdeps/unix/sysv/linux/tst-rseq-disable.c | 6 ++ + sysdeps/unix/sysv/linux/tst-rseq.c | 8 ++ + sysdeps/unix/sysv/linux/x86_64/64/ld.abilist | 3 + + sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist | 3 + + 38 files changed, 237 insertions(+), 5 deletions(-) + +diff --git a/NEWS b/NEWS +index ffae154a..1b0ee549 100644 +--- a/NEWS ++++ b/NEWS +@@ -129,6 +129,17 @@ Major new features: + than or equal to a given integer. This function is a GNU extension, + although Solaris also provides a similar function. + ++* Support for automatically registering threads with the Linux rseq ++ system call has been added. This system call is implemented starting ++ from Linux 4.18. The Restartable Sequences ABI accelerates user-space ++ operations on per-cpu data. It allows user-space to perform updates ++ on per-cpu data without requiring heavy-weight atomic operations. ++ Automatically registering threads allows all libraries, including ++ libc, to make immediate use of the rseq support by using the ++ documented ABI, via the __rseq_flags, __rseq_offset, and __rseq_size ++ variables. The GNU C Library manual has details on integration of ++ Restartable Sequences. ++ + Deprecated and removed features, and other changes affecting compatibility: + + * The function pthread_mutex_consistent_np has been deprecated; programs +diff --git a/manual/threads.texi b/manual/threads.texi +index 06b6b277..ab44a92c 100644 +--- a/manual/threads.texi ++++ b/manual/threads.texi +@@ -629,6 +629,8 @@ the standard. + * Waiting with Explicit Clocks:: Functions for waiting with an + explicit clock specification. + * Single-Threaded:: Detecting single-threaded execution. ++* Restartable Sequences:: Linux-specific restartable sequences ++ integration. + @end menu + + @node Default Thread Attributes +@@ -958,6 +960,85 @@ application-created thread because future versions of @theglibc{} may + create background threads after the first thread has been created, and + the application has no way of knowning that these threads are present. + ++@node Restartable Sequences ++@subsubsection Restartable Sequences ++ ++This section describes restartable sequences integration for ++@theglibc{}. This functionality is only available on Linux. ++ ++@deftp {Data Type} {struct rseq} ++@standards{Linux, sys/rseq.h} ++The type of the restartable sequences area. Future versions ++of Linux may add additional fields to the end of this structure. ++ ++ ++Users need to obtain the address of the restartable sequences area using ++the thread pointer and the @code{__rseq_offset} variable, described ++below. ++ ++One use of the restartable sequences area is to read the current CPU ++number from its @code{cpu_id} field, as an inline version of ++@code{sched_getcpu}. @Theglibc{} sets the @code{cpu_id} field to ++@code{RSEQ_CPU_ID_REGISTRATION_FAILED} if registration failed or was ++explicitly disabled. ++ ++Furthermore, users can store the address of a @code{struct rseq_cs} ++object into the @code{rseq_cs} field of @code{struct rseq}, thus ++informing the kernel that the thread enters a restartable sequence ++critical section. This pointer and the code areas it itself points to ++must not be left pointing to memory areas which are freed or re-used. ++Several approaches can guarantee this. If the application or library ++can guarantee that the memory used to hold the @code{struct rseq_cs} and ++the code areas it refers to are never freed or re-used, no special ++action must be taken. Else, before that memory is re-used of freed, the ++application is responsible for setting the @code{rseq_cs} field to ++@code{NULL} in each thread's restartable sequence area to guarantee that ++it does not leak dangling references. Because the application does not ++typically have knowledge of libraries' use of restartable sequences, it ++is recommended that libraries using restartable sequences which may end ++up freeing or re-using their memory set the @code{rseq_cs} field to ++@code{NULL} before returning from library functions which use ++restartable sequences. ++ ++The manual for the @code{rseq} system call can be found ++at @uref{https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2}. ++@end deftp ++ ++@deftypevar {int} __rseq_offset ++@standards{Linux, sys/rseq.h} ++This variable contains the offset between the thread pointer (as defined ++by @code{__builtin_thread_pointer} or the thread pointer register for ++the architecture) and the restartable sequences area. This value is the ++same for all threads in the process. If the restartable sequences area ++is located at a lower address than the location to which the thread ++pointer points, the value is negative. ++@end deftypevar ++ ++@deftypevar {unsigned int} __rseq_size ++@standards{Linux, sys/rseq.h} ++This variable is either zero (if restartable sequence registration ++failed or has been disabled) or the size of the restartable sequence ++registration. This can be different from the size of @code{struct rseq} ++if the kernel has extended the size of the registration. If ++registration is successful, @code{__rseq_size} is at least 32 (the ++initial size of @code{struct rseq}). ++@end deftypevar ++ ++@deftypevar {unsigned int} __rseq_flags ++@standards{Linux, sys/rseq.h} ++The flags used during restartable sequence registration with the kernel. ++Currently zero. ++@end deftypevar ++ ++@deftypevr Macro int RSEQ_SIG ++@standards{Linux, sys/rseq.h} ++Each supported architecture provides a @code{RSEQ_SIG} macro in ++@file{sys/rseq.h} which contains a signature. That signature is ++expected to be present in the code before each restartable sequences ++abort handler. Failure to provide the expected signature may terminate ++the process with a segmentation fault. ++@end deftypevr ++ + @c FIXME these are undocumented: + @c pthread_atfork + @c pthread_attr_destroy +diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c +index b39dfbff..4a73927f 100644 +--- a/sysdeps/nptl/dl-tls_init_tp.c ++++ b/sysdeps/nptl/dl-tls_init_tp.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #define TUNABLE_NAMESPACE pthread + #include +@@ -43,6 +44,10 @@ rtld_mutex_dummy (pthread_mutex_t *lock) + } + #endif + ++const unsigned int __rseq_flags; ++const unsigned int __rseq_size attribute_relro; ++const int __rseq_offset attribute_relro; ++ + void + __tls_pre_init_tp (void) + { +@@ -100,7 +105,23 @@ __tls_init_tp (void) + #if HAVE_TUNABLES + do_rseq = TUNABLE_GET (rseq, int, NULL); + #endif +- rseq_register_current_thread (pd, do_rseq); ++ if (rseq_register_current_thread (pd, do_rseq)) ++ { ++ /* We need a writable view of the variables. They are in ++ .data.relro and are not yet write-protected. */ ++ extern unsigned int size __asm__ ("__rseq_size"); ++ size = sizeof (pd->rseq_area); ++ } ++ ++#ifdef RSEQ_SIG ++ /* This should be a compile-time constant, but the current ++ infrastructure makes it difficult to determine its value. Not ++ all targets support __thread_pointer, so set __rseq_offset only ++ if thre rseq registration may have happened because RSEQ_SIG is ++ defined. */ ++ extern int offset __asm__ ("__rseq_offset"); ++ offset = (char *) &pd->rseq_area - (char *) __thread_pointer (); ++#endif + } + + /* Set initial thread's stack block from 0 up to __libc_stack_end. +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 0657f400..856a9d58 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -110,7 +110,8 @@ sysdep_headers += sys/mount.h sys/acct.h \ + bits/types/struct_semid64_ds_helper.h \ + bits/types/struct_shmid64_ds.h \ + bits/types/struct_shmid64_ds_helper.h \ +- bits/pthread_stack_min.h bits/pthread_stack_min-dynamic.h ++ bits/pthread_stack_min.h bits/pthread_stack_min-dynamic.h \ ++ sys/rseq.h bits/rseq.h + + tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \ + tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \ +diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions +index 26452f3f..3f8809a1 100644 +--- a/sysdeps/unix/sysv/linux/Versions ++++ b/sysdeps/unix/sysv/linux/Versions +@@ -316,6 +316,11 @@ librt { + } + + ld { ++ GLIBC_2.35 { ++ __rseq_flags; ++ __rseq_offset; ++ __rseq_size; ++ } + GLIBC_PRIVATE { + __nptl_change_stack_perm; + } +diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist +index b7196a80..bf4d4f9b 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist +@@ -4,3 +4,6 @@ GLIBC_2.17 __tls_get_addr F + GLIBC_2.17 _dl_mcount F + GLIBC_2.17 _r_debug D 0x28 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist +index 13f7fc74..a23325a5 100644 +--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist ++++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist +@@ -3,4 +3,7 @@ GLIBC_2.1 __libc_stack_end D 0x8 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x8 +diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/ld.abilist +index 7284383a..55f0c2ab 100644 +--- a/sysdeps/unix/sysv/linux/arc/ld.abilist ++++ b/sysdeps/unix/sysv/linux/arc/ld.abilist +@@ -4,3 +4,6 @@ GLIBC_2.32 __tls_get_addr F + GLIBC_2.32 _dl_mcount F + GLIBC_2.32 _r_debug D 0x14 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/arm/be/ld.abilist b/sysdeps/unix/sysv/linux/arm/be/ld.abilist +index 7987bbae..f1da2c63 100644 +--- a/sysdeps/unix/sysv/linux/arm/be/ld.abilist ++++ b/sysdeps/unix/sysv/linux/arm/be/ld.abilist +@@ -1,4 +1,7 @@ + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __libc_stack_end D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 + GLIBC_2.4 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/arm/le/ld.abilist b/sysdeps/unix/sysv/linux/arm/le/ld.abilist +index 7987bbae..f1da2c63 100644 +--- a/sysdeps/unix/sysv/linux/arm/le/ld.abilist ++++ b/sysdeps/unix/sysv/linux/arm/le/ld.abilist +@@ -1,4 +1,7 @@ + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __libc_stack_end D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 + GLIBC_2.4 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/csky/ld.abilist b/sysdeps/unix/sysv/linux/csky/ld.abilist +index 4939b206..7f482276 100644 +--- a/sysdeps/unix/sysv/linux/csky/ld.abilist ++++ b/sysdeps/unix/sysv/linux/csky/ld.abilist +@@ -4,3 +4,6 @@ GLIBC_2.29 __tls_get_addr F + GLIBC_2.29 _dl_mcount F + GLIBC_2.29 _r_debug D 0x14 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/hppa/ld.abilist b/sysdeps/unix/sysv/linux/hppa/ld.abilist +index 7cc9ebd7..7f5527fb 100644 +--- a/sysdeps/unix/sysv/linux/hppa/ld.abilist ++++ b/sysdeps/unix/sysv/linux/hppa/ld.abilist +@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x14 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist +index e8d187b1..9c4a45d8 100644 +--- a/sysdeps/unix/sysv/linux/i386/ld.abilist ++++ b/sysdeps/unix/sysv/linux/i386/ld.abilist +@@ -4,3 +4,6 @@ GLIBC_2.1 _dl_mcount F + GLIBC_2.3 ___tls_get_addr F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist +index be512265..8ccb5be9 100644 +--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist +@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist +index 7987bbae..f1da2c63 100644 +--- a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist +@@ -1,4 +1,7 @@ + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __libc_stack_end D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 + GLIBC_2.4 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist +index 4f2854ed..dadbf852 100644 +--- a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist +@@ -3,4 +3,7 @@ GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/microblaze/ld.abilist b/sysdeps/unix/sysv/linux/microblaze/ld.abilist +index 9f0fdeca..89a0b7e4 100644 +--- a/sysdeps/unix/sysv/linux/microblaze/ld.abilist ++++ b/sysdeps/unix/sysv/linux/microblaze/ld.abilist +@@ -4,3 +4,6 @@ GLIBC_2.18 __tls_get_addr F + GLIBC_2.18 _dl_mcount F + GLIBC_2.18 _r_debug D 0x14 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist +index f750067d..e304d1bb 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist +@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist +index f750067d..e304d1bb 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist +@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist +index 2fba6a9b..37a47ebc 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist +@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x8 +diff --git a/sysdeps/unix/sysv/linux/nios2/ld.abilist b/sysdeps/unix/sysv/linux/nios2/ld.abilist +index 57dfad5a..811ae9da 100644 +--- a/sysdeps/unix/sysv/linux/nios2/ld.abilist ++++ b/sysdeps/unix/sysv/linux/nios2/ld.abilist +@@ -4,3 +4,6 @@ GLIBC_2.21 __tls_get_addr F + GLIBC_2.21 _dl_mcount F + GLIBC_2.21 _r_debug D 0x14 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist +index e8966073..5a68aeb9 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist +@@ -5,3 +5,6 @@ GLIBC_2.22 __tls_get_addr_opt F + GLIBC_2.23 __parse_hwcap_and_convert_at_platform F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist +index ce0bc639..da24dc7f 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist +@@ -5,3 +5,6 @@ GLIBC_2.3 __tls_get_addr F + GLIBC_2.3 _dl_mcount F + GLIBC_2.3 _r_debug D 0x28 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist +index 65b22674..b9ae89ae 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist +@@ -5,3 +5,6 @@ GLIBC_2.17 _r_debug D 0x28 + GLIBC_2.22 __tls_get_addr_opt F + GLIBC_2.23 __parse_hwcap_and_convert_at_platform F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist +index 5ad4c81d..06836887 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist +@@ -4,3 +4,6 @@ GLIBC_2.33 __tls_get_addr F + GLIBC_2.33 _dl_mcount F + GLIBC_2.33 _r_debug D 0x14 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist +index 479efdea..48431c91 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist +@@ -4,3 +4,6 @@ GLIBC_2.27 __tls_get_addr F + GLIBC_2.27 _dl_mcount F + GLIBC_2.27 _r_debug D 0x28 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h +index 15bc7ffd..9e8f99fd 100644 +--- a/sysdeps/unix/sysv/linux/rseq-internal.h ++++ b/sysdeps/unix/sysv/linux/rseq-internal.h +@@ -26,7 +26,7 @@ + #include + + #ifdef RSEQ_SIG +-static inline void ++static inline bool + rseq_register_current_thread (struct pthread *self, bool do_rseq) + { + if (do_rseq) +@@ -35,15 +35,17 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq) + sizeof (self->rseq_area), + 0, RSEQ_SIG); + if (!INTERNAL_SYSCALL_ERROR_P (ret)) +- return; ++ return true; + } + THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++ return false; + } + #else /* RSEQ_SIG */ +-static inline void ++static inline bool + rseq_register_current_thread (struct pthread *self, bool do_rseq) + { + THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++ return false; + } + #endif /* RSEQ_SIG */ + +diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist +index d5ecb636..c1528839 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist +@@ -3,3 +3,6 @@ GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_offset F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist +index 62a5e1d9..117d1430 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist +@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_offset F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sh/be/ld.abilist b/sysdeps/unix/sysv/linux/sh/be/ld.abilist +index 7cc9ebd7..7f5527fb 100644 +--- a/sysdeps/unix/sysv/linux/sh/be/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sh/be/ld.abilist +@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x14 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sh/le/ld.abilist b/sysdeps/unix/sysv/linux/sh/le/ld.abilist +index 7cc9ebd7..7f5527fb 100644 +--- a/sysdeps/unix/sysv/linux/sh/le/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sh/le/ld.abilist +@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x14 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist +index 2e605434..3aac73f3 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist +@@ -3,3 +3,6 @@ GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist +index be512265..8ccb5be9 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist +@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h +index c8edff50..1215b5d0 100644 +--- a/sysdeps/unix/sysv/linux/sys/rseq.h ++++ b/sysdeps/unix/sysv/linux/sys/rseq.h +@@ -171,4 +171,14 @@ struct rseq + + #endif /* __GLIBC_HAVE_KERNEL_RSEQ */ + ++/* Offset from the thread pointer to the rseq area. */ ++extern const int __rseq_offset; ++ ++/* Size of the registered rseq area. 0 if the registration was ++ unsuccessful. */ ++extern const unsigned int __rseq_size; ++ ++/* Flags used during rseq registration. */ ++extern const unsigned int __rseq_flags; ++ + #endif /* sys/rseq.h */ +diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c +index 000e3518..6d73f77e 100644 +--- a/sysdeps/unix/sysv/linux/tst-rseq-disable.c ++++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + + #ifdef RSEQ_SIG +@@ -30,6 +31,11 @@ static void + check_rseq_disabled (void) + { + struct pthread *pd = THREAD_SELF; ++ ++ TEST_COMPARE (__rseq_flags, 0); ++ TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset ++ == (char *) &pd->rseq_area); ++ TEST_COMPARE (__rseq_size, 0); + TEST_COMPARE ((int) pd->rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); + + int ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area), +diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c +index 926376b6..572c1116 100644 +--- a/sysdeps/unix/sysv/linux/tst-rseq.c ++++ b/sysdeps/unix/sysv/linux/tst-rseq.c +@@ -29,12 +29,20 @@ + # include + # include + # include ++# include ++# include + # include "tst-rseq.h" + + static void + do_rseq_main_test (void) + { ++ struct pthread *pd = THREAD_SELF; ++ + TEST_VERIFY_EXIT (rseq_thread_registered ()); ++ TEST_COMPARE (__rseq_flags, 0); ++ TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset ++ == (char *) &pd->rseq_area); ++ TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area)); + } + + static void +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist +index afddaec5..ae622bdf 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist +@@ -3,3 +3,6 @@ GLIBC_2.2.5 _dl_mcount F + GLIBC_2.2.5 _r_debug D 0x28 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist +index defc488d..e17496d1 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist +@@ -3,3 +3,6 @@ GLIBC_2.16 __tls_get_addr F + GLIBC_2.16 _dl_mcount F + GLIBC_2.16 _r_debug D 0x14 + GLIBC_2.34 __rtld_version_placeholder F ++GLIBC_2.35 __rseq_flags D 0x4 ++GLIBC_2.35 __rseq_offset D 0x4 ++GLIBC_2.35 __rseq_size D 0x4 +-- +2.23.0 + diff --git a/rseq-nptl-Add-rseq-registration.patch b/rseq-nptl-Add-rseq-registration.patch new file mode 100644 index 0000000..1f76ab3 --- /dev/null +++ b/rseq-nptl-Add-rseq-registration.patch @@ -0,0 +1,1165 @@ +From 9394ca7ec895e284fcb7f5d7839feeb517acc249 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 21 Jan 2022 22:23:58 -0500 +Subject: [PATCH 4/9] nptl: Add rseq registration + +The rseq area is placed directly into struct pthread. rseq +registration failure is not treated as an error, so it is possible +that threads run with inconsistent registration status. + + is not yet installed as a public header. + +Co-Authored-By: Mathieu Desnoyers +Reviewed-by: Szabolcs Nagy +Reviewed-by: Siddhesh Poyarekar +------ +conflicts: + context conflict +--- + nptl/descr.h | 4 + + nptl/pthread_create.c | 13 + + sysdeps/nptl/dl-tls_init_tp.c | 8 +- + sysdeps/unix/sysv/linux/Makefile | 9 +- + sysdeps/unix/sysv/linux/aarch64/bits/rseq.h | 43 ++++ + sysdeps/unix/sysv/linux/arm/bits/rseq.h | 83 +++++++ + sysdeps/unix/sysv/linux/bits/rseq.h | 29 +++ + sysdeps/unix/sysv/linux/mips/bits/rseq.h | 62 +++++ + sysdeps/unix/sysv/linux/powerpc/bits/rseq.h | 37 +++ + sysdeps/unix/sysv/linux/rseq-internal.h | 45 ++++ + sysdeps/unix/sysv/linux/s390/bits/rseq.h | 37 +++ + sysdeps/unix/sysv/linux/sys/rseq.h | 174 +++++++++++++ + sysdeps/unix/sysv/linux/tst-rseq-nptl.c | 260 ++++++++++++++++++++ + sysdeps/unix/sysv/linux/tst-rseq.c | 64 +++++ + sysdeps/unix/sysv/linux/tst-rseq.h | 57 +++++ + sysdeps/unix/sysv/linux/x86/bits/rseq.h | 30 +++ + 16 files changed, 952 insertions(+), 3 deletions(-) + create mode 100644 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h + create mode 100644 sysdeps/unix/sysv/linux/arm/bits/rseq.h + create mode 100644 sysdeps/unix/sysv/linux/bits/rseq.h + create mode 100644 sysdeps/unix/sysv/linux/mips/bits/rseq.h + create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h + create mode 100644 sysdeps/unix/sysv/linux/rseq-internal.h + create mode 100644 sysdeps/unix/sysv/linux/s390/bits/rseq.h + create mode 100644 sysdeps/unix/sysv/linux/sys/rseq.h + create mode 100644 sysdeps/unix/sysv/linux/tst-rseq-nptl.c + create mode 100644 sysdeps/unix/sysv/linux/tst-rseq.c + create mode 100644 sysdeps/unix/sysv/linux/tst-rseq.h + create mode 100644 sysdeps/unix/sysv/linux/x86/bits/rseq.h + +diff --git a/nptl/descr.h b/nptl/descr.h +index 4de84138..79362661 100644 +--- a/nptl/descr.h ++++ b/nptl/descr.h +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + #ifndef TCB_ALIGNMENT + # define TCB_ALIGNMENT sizeof (double) +@@ -405,6 +406,9 @@ struct pthread + /* Used on strsignal. */ + struct tls_internal_t tls_state; + ++ /* rseq area registered with the kernel. */ ++ struct rseq rseq_area; ++ + /* This member must be last. */ + char end_padding[]; + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index 3db0c9fd..d2b40924 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include "libioP.h" + #include + #include +@@ -367,6 +368,9 @@ start_thread (void *arg) + /* Initialize pointers to locale data. */ + __ctype_init (); + ++ /* Register rseq TLS to the kernel. */ ++ rseq_register_current_thread (pd); ++ + #ifndef __ASSUME_SET_ROBUST_LIST + if (__nptl_set_robust_list_avail) + #endif +@@ -572,6 +576,15 @@ out: + process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID + flag. The 'tid' field in the TCB will be set to zero. + ++ rseq TLS is still registered at this point. Rely on implicit ++ unregistration performed by the kernel on thread teardown. This is not a ++ problem because the rseq TLS lives on the stack, and the stack outlives ++ the thread. If TCB allocation is ever changed, additional steps may be ++ required, such as performing explicit rseq unregistration before ++ reclaiming the rseq TLS area memory. It is NOT sufficient to block ++ signals because the kernel may write to the rseq area even without ++ signals. ++ + The exit code is zero since in case all threads exit by calling + 'pthread_exit' the exit status must be 0 (zero). */ + while (1) +diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c +index ca494dd3..fedb876f 100644 +--- a/sysdeps/nptl/dl-tls_init_tp.c ++++ b/sysdeps/nptl/dl-tls_init_tp.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #ifndef __ASSUME_SET_ROBUST_LIST + bool __nptl_set_robust_list_avail; +@@ -57,11 +58,12 @@ __tls_pre_init_tp (void) + void + __tls_init_tp (void) + { ++ struct pthread *pd = THREAD_SELF; ++ + /* Set up thread stack list management. */ +- list_add (&THREAD_SELF->list, &GL (dl_stack_user)); ++ list_add (&pd->list, &GL (dl_stack_user)); + + /* Early initialization of the TCB. */ +- struct pthread *pd = THREAD_SELF; + pd->tid = INTERNAL_SYSCALL_CALL (set_tid_address, &pd->tid); + THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]); + THREAD_SETMEM (pd, user_stack, true); +@@ -90,6 +92,8 @@ __tls_init_tp (void) + } + } + ++ rseq_register_current_thread (pd); ++ + /* Set initial thread's stack block from 0 up to __libc_stack_end. + It will be bigger than it actually is, but for unwind.c/pt-longjmp.c + purposes this is good enough. */ +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index c3477480..f103a964 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -130,7 +130,10 @@ ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes) + tests += tst-ofdlocks-compat + endif + +-tests-internal += tst-sigcontext-get_pc ++tests-internal += \ ++ tst-rseq \ ++ tst-sigcontext-get_pc \ ++ # tests-internal + + tests-time64 += \ + tst-adjtimex-time64 \ +@@ -370,4 +373,8 @@ endif + + ifeq ($(subdir),nptl) + tests += tst-align-clone tst-getpid1 ++ ++# tst-rseq-nptl is an internal test because it requires a definition of ++# __NR_rseq from the internal system call list. ++tests-internal += tst-rseq-nptl + endif +diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h b/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h +new file mode 100644 +index 00000000..9ba92725 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h +@@ -0,0 +1,43 @@ ++/* Restartable Sequences Linux aarch64 architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ aarch64 -mbig-endian generates mixed endianness code vs data: ++ little-endian code and big-endian data. Ensure the RSEQ_SIG signature ++ matches code endianness. */ ++ ++#define RSEQ_SIG_CODE 0xd428bc00 /* BRK #0x45E0. */ ++ ++#ifdef __AARCH64EB__ ++# define RSEQ_SIG_DATA 0x00bc28d4 /* BRK #0x45E0. */ ++#else ++# define RSEQ_SIG_DATA RSEQ_SIG_CODE ++#endif ++ ++#define RSEQ_SIG RSEQ_SIG_DATA +diff --git a/sysdeps/unix/sysv/linux/arm/bits/rseq.h b/sysdeps/unix/sysv/linux/arm/bits/rseq.h +new file mode 100644 +index 00000000..0542b26f +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/arm/bits/rseq.h +@@ -0,0 +1,83 @@ ++/* Restartable Sequences Linux arm architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* ++ RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ - ARM little endian ++ ++ RSEQ_SIG uses the udf A32 instruction with an uncommon immediate operand ++ value 0x5de3. This traps if user-space reaches this instruction by mistake, ++ and the uncommon operand ensures the kernel does not move the instruction ++ pointer to attacker-controlled code on rseq abort. ++ ++ The instruction pattern in the A32 instruction set is: ++ ++ e7f5def3 udf #24035 ; 0x5de3 ++ ++ This translates to the following instruction pattern in the T16 instruction ++ set: ++ ++ little endian: ++ def3 udf #243 ; 0xf3 ++ e7f5 b.n <7f5> ++ ++ - ARMv6+ big endian (BE8): ++ ++ ARMv6+ -mbig-endian generates mixed endianness code vs data: little-endian ++ code and big-endian data. The data value of the signature needs to have its ++ byte order reversed to generate the trap instruction: ++ ++ Data: 0xf3def5e7 ++ ++ Translates to this A32 instruction pattern: ++ ++ e7f5def3 udf #24035 ; 0x5de3 ++ ++ Translates to this T16 instruction pattern: ++ ++ def3 udf #243 ; 0xf3 ++ e7f5 b.n <7f5> ++ ++ - Prior to ARMv6 big endian (BE32): ++ ++ Prior to ARMv6, -mbig-endian generates big-endian code and data ++ (which match), so the endianness of the data representation of the ++ signature should not be reversed. However, the choice between BE32 ++ and BE8 is done by the linker, so we cannot know whether code and ++ data endianness will be mixed before the linker is invoked. So rather ++ than try to play tricks with the linker, the rseq signature is simply ++ data (not a trap instruction) prior to ARMv6 on big endian. This is ++ why the signature is expressed as data (.word) rather than as ++ instruction (.inst) in assembler. */ ++ ++#ifdef __ARMEB__ ++# define RSEQ_SIG 0xf3def5e7 /* udf #24035 ; 0x5de3 (ARMv6+) */ ++#else ++# define RSEQ_SIG 0xe7f5def3 /* udf #24035 ; 0x5de3 */ ++#endif +diff --git a/sysdeps/unix/sysv/linux/bits/rseq.h b/sysdeps/unix/sysv/linux/bits/rseq.h +new file mode 100644 +index 00000000..46cf5d1c +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/bits/rseq.h +@@ -0,0 +1,29 @@ ++/* Restartable Sequences architecture header. Stub version. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. */ +diff --git a/sysdeps/unix/sysv/linux/mips/bits/rseq.h b/sysdeps/unix/sysv/linux/mips/bits/rseq.h +new file mode 100644 +index 00000000..a9defee5 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/mips/bits/rseq.h +@@ -0,0 +1,62 @@ ++/* Restartable Sequences Linux mips architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ RSEQ_SIG uses the break instruction. The instruction pattern is: ++ ++ On MIPS: ++ 0350000d break 0x350 ++ ++ On nanoMIPS: ++ 00100350 break 0x350 ++ ++ On microMIPS: ++ 0000d407 break 0x350 ++ ++ For nanoMIPS32 and microMIPS, the instruction stream is encoded as ++ 16-bit halfwords, so the signature halfwords need to be swapped ++ accordingly for little-endian. */ ++ ++#if defined (__nanomips__) ++# ifdef __MIPSEL__ ++# define RSEQ_SIG 0x03500010 ++# else ++# define RSEQ_SIG 0x00100350 ++# endif ++#elif defined (__mips_micromips) ++# ifdef __MIPSEL__ ++# define RSEQ_SIG 0xd4070000 ++# else ++# define RSEQ_SIG 0x0000d407 ++# endif ++#elif defined (__mips__) ++# define RSEQ_SIG 0x0350000d ++#else ++/* Unknown MIPS architecture. */ ++#endif +diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h b/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h +new file mode 100644 +index 00000000..05b3cf7b +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h +@@ -0,0 +1,37 @@ ++/* Restartable Sequences Linux powerpc architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ RSEQ_SIG uses the following trap instruction: ++ ++ powerpc-be: 0f e5 00 0b twui r5,11 ++ powerpc64-le: 0b 00 e5 0f twui r5,11 ++ powerpc64-be: 0f e5 00 0b twui r5,11 */ ++ ++#define RSEQ_SIG 0x0fe5000b +diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h +new file mode 100644 +index 00000000..909f5478 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/rseq-internal.h +@@ -0,0 +1,45 @@ ++/* Restartable Sequences internal API. Linux implementation. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 RSEQ_INTERNAL_H ++#define RSEQ_INTERNAL_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef RSEQ_SIG ++static inline void ++rseq_register_current_thread (struct pthread *self) ++{ ++ int ret = INTERNAL_SYSCALL_CALL (rseq, ++ &self->rseq_area, sizeof (self->rseq_area), ++ 0, RSEQ_SIG); ++ if (INTERNAL_SYSCALL_ERROR_P (ret)) ++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++} ++#else /* RSEQ_SIG */ ++static inline void ++rseq_register_current_thread (struct pthread *self) ++{ ++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++} ++#endif /* RSEQ_SIG */ ++ ++#endif /* rseq-internal.h */ +diff --git a/sysdeps/unix/sysv/linux/s390/bits/rseq.h b/sysdeps/unix/sysv/linux/s390/bits/rseq.h +new file mode 100644 +index 00000000..3030e38f +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/s390/bits/rseq.h +@@ -0,0 +1,37 @@ ++/* Restartable Sequences Linux s390 architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ RSEQ_SIG uses the trap4 instruction. As Linux does not make use of the ++ access-register mode nor the linkage stack this instruction will always ++ cause a special-operation exception (the trap-enabled bit in the DUCT ++ is and will stay 0). The instruction pattern is ++ b2 ff 0f ff trap4 4095(%r0) */ ++ ++#define RSEQ_SIG 0xB2FF0FFF +diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h +new file mode 100644 +index 00000000..c8edff50 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/sys/rseq.h +@@ -0,0 +1,174 @@ ++/* Restartable Sequences exported symbols. Linux header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 _SYS_RSEQ_H ++#define _SYS_RSEQ_H 1 ++ ++/* Architecture-specific rseq signature. */ ++#include ++ ++#include ++#include ++#include ++ ++#ifdef __has_include ++# if __has_include ("linux/rseq.h") ++# define __GLIBC_HAVE_KERNEL_RSEQ ++# endif ++#else ++# include ++# if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 18, 0) ++# define __GLIBC_HAVE_KERNEL_RSEQ ++# endif ++#endif ++ ++#ifdef __GLIBC_HAVE_KERNEL_RSEQ ++/* We use the structures declarations from the kernel headers. */ ++# include ++#else /* __GLIBC_HAVE_KERNEL_RSEQ */ ++/* We use a copy of the include/uapi/linux/rseq.h kernel header. */ ++ ++enum rseq_cpu_id_state ++ { ++ RSEQ_CPU_ID_UNINITIALIZED = -1, ++ RSEQ_CPU_ID_REGISTRATION_FAILED = -2, ++ }; ++ ++enum rseq_flags ++ { ++ RSEQ_FLAG_UNREGISTER = (1 << 0), ++ }; ++ ++enum rseq_cs_flags_bit ++ { ++ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0, ++ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1, ++ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2, ++ }; ++ ++enum rseq_cs_flags ++ { ++ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT = ++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT), ++ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL = ++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT), ++ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE = ++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT), ++ }; ++ ++/* struct rseq_cs is aligned on 32 bytes to ensure it is always ++ contained within a single cache-line. It is usually declared as ++ link-time constant data. */ ++struct rseq_cs ++ { ++ /* Version of this structure. */ ++ uint32_t version; ++ /* enum rseq_cs_flags. */ ++ uint32_t flags; ++ uint64_t start_ip; ++ /* Offset from start_ip. */ ++ uint64_t post_commit_offset; ++ uint64_t abort_ip; ++ } __attribute__ ((__aligned__ (32))); ++ ++/* struct rseq is aligned on 32 bytes to ensure it is always ++ contained within a single cache-line. ++ ++ A single struct rseq per thread is allowed. */ ++struct rseq ++ { ++ /* Restartable sequences cpu_id_start field. Updated by the ++ kernel. Read by user-space with single-copy atomicity ++ semantics. This field should only be read by the thread which ++ registered this data structure. Aligned on 32-bit. Always ++ contains a value in the range of possible CPUs, although the ++ value may not be the actual current CPU (e.g. if rseq is not ++ initialized). This CPU number value should always be compared ++ against the value of the cpu_id field before performing a rseq ++ commit or returning a value read from a data structure indexed ++ using the cpu_id_start value. */ ++ uint32_t cpu_id_start; ++ /* Restartable sequences cpu_id field. Updated by the kernel. ++ Read by user-space with single-copy atomicity semantics. This ++ field should only be read by the thread which registered this ++ data structure. Aligned on 32-bit. Values ++ RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED ++ have a special semantic: the former means "rseq uninitialized", ++ and latter means "rseq initialization failed". This value is ++ meant to be read within rseq critical sections and compared ++ with the cpu_id_start value previously read, before performing ++ the commit instruction, or read and compared with the ++ cpu_id_start value before returning a value loaded from a data ++ structure indexed using the cpu_id_start value. */ ++ uint32_t cpu_id; ++ /* Restartable sequences rseq_cs field. ++ ++ Contains NULL when no critical section is active for the current ++ thread, or holds a pointer to the currently active struct rseq_cs. ++ ++ Updated by user-space, which sets the address of the currently ++ active rseq_cs at the beginning of assembly instruction sequence ++ block, and set to NULL by the kernel when it restarts an assembly ++ instruction sequence block, as well as when the kernel detects that ++ it is preempting or delivering a signal outside of the range ++ targeted by the rseq_cs. Also needs to be set to NULL by user-space ++ before reclaiming memory that contains the targeted struct rseq_cs. ++ ++ Read and set by the kernel. Set by user-space with single-copy ++ atomicity semantics. This field should only be updated by the ++ thread which registered this data structure. Aligned on 64-bit. */ ++ union ++ { ++ uint64_t ptr64; ++# ifdef __LP64__ ++ uint64_t ptr; ++# else /* __LP64__ */ ++ struct ++ { ++#if __BYTE_ORDER == __BIG_ENDIAN ++ uint32_t padding; /* Initialized to zero. */ ++ uint32_t ptr32; ++# else /* LITTLE */ ++ uint32_t ptr32; ++ uint32_t padding; /* Initialized to zero. */ ++# endif /* ENDIAN */ ++ } ptr; ++# endif /* __LP64__ */ ++ } rseq_cs; ++ ++ /* Restartable sequences flags field. ++ ++ This field should only be updated by the thread which ++ registered this data structure. Read by the kernel. ++ Mainly used for single-stepping through rseq critical sections ++ with debuggers. ++ ++ - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT ++ Inhibit instruction sequence block restart on preemption ++ for this thread. ++ - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL ++ Inhibit instruction sequence block restart on signal ++ delivery for this thread. ++ - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE ++ Inhibit instruction sequence block restart on migration for ++ this thread. */ ++ uint32_t flags; ++ } __attribute__ ((__aligned__ (32))); ++ ++#endif /* __GLIBC_HAVE_KERNEL_RSEQ */ ++ ++#endif /* sys/rseq.h */ +diff --git a/sysdeps/unix/sysv/linux/tst-rseq-nptl.c b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c +new file mode 100644 +index 00000000..d31d9444 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c +@@ -0,0 +1,260 @@ ++/* Restartable Sequences NPTL test. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 ++ . */ ++ ++/* These tests validate that rseq is registered from various execution ++ contexts (main thread, destructor, other threads, other threads created ++ from destructor, forked process (without exec), pthread_atfork handlers, ++ pthread setspecific destructors, signal handlers, atexit handlers). ++ ++ See the Linux kernel selftests for extensive rseq stress-tests. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef RSEQ_SIG ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include "tst-rseq.h" ++ ++static pthread_key_t rseq_test_key; ++ ++static void ++atfork_prepare (void) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in pthread atfork prepare\n"); ++ support_record_failure (); ++ } ++} ++ ++static void ++atfork_parent (void) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in pthread atfork parent\n"); ++ support_record_failure (); ++ } ++} ++ ++static void ++atfork_child (void) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in pthread atfork child\n"); ++ support_record_failure (); ++ } ++} ++ ++static void ++rseq_key_destructor (void *arg) ++{ ++ /* Cannot use deferred failure reporting after main returns. */ ++ if (!rseq_thread_registered ()) ++ FAIL_EXIT1 ("rseq not registered in pthread key destructor"); ++} ++ ++static void ++atexit_handler (void) ++{ ++ /* Cannot use deferred failure reporting after main returns. */ ++ if (!rseq_thread_registered ()) ++ FAIL_EXIT1 ("rseq not registered in atexit handler"); ++} ++ ++/* Used to avoid -Werror=stringop-overread warning with ++ pthread_setspecific and GCC 11. */ ++static char one = 1; ++ ++static void ++do_rseq_main_test (void) ++{ ++ TEST_COMPARE (atexit (atexit_handler), 0); ++ rseq_test_key = xpthread_key_create (rseq_key_destructor); ++ TEST_COMPARE (pthread_atfork (atfork_prepare, atfork_parent, atfork_child), 0); ++ xraise (SIGUSR1); ++ TEST_COMPARE (pthread_setspecific (rseq_test_key, &one), 0); ++ TEST_VERIFY_EXIT (rseq_thread_registered ()); ++} ++ ++static void ++cancel_routine (void *arg) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in cancel routine\n"); ++ support_record_failure (); ++ } ++} ++ ++static pthread_barrier_t cancel_thread_barrier; ++static pthread_cond_t cancel_thread_cond = PTHREAD_COND_INITIALIZER; ++static pthread_mutex_t cancel_thread_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++static void ++test_cancel_thread (void) ++{ ++ pthread_cleanup_push (cancel_routine, NULL); ++ (void) xpthread_barrier_wait (&cancel_thread_barrier); ++ /* Wait forever until cancellation. */ ++ xpthread_cond_wait (&cancel_thread_cond, &cancel_thread_mutex); ++ pthread_cleanup_pop (0); ++} ++ ++static void * ++thread_function (void * arg) ++{ ++ int i = (int) (intptr_t) arg; ++ ++ xraise (SIGUSR1); ++ if (i == 0) ++ test_cancel_thread (); ++ TEST_COMPARE (pthread_setspecific (rseq_test_key, &one), 0); ++ return rseq_thread_registered () ? NULL : (void *) 1l; ++} ++ ++static void ++sighandler (int sig) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in signal handler\n"); ++ support_record_failure (); ++ } ++} ++ ++static void ++setup_signals (void) ++{ ++ struct sigaction sa; ++ ++ sigemptyset (&sa.sa_mask); ++ sigaddset (&sa.sa_mask, SIGUSR1); ++ sa.sa_flags = 0; ++ sa.sa_handler = sighandler; ++ xsigaction (SIGUSR1, &sa, NULL); ++} ++ ++static int ++do_rseq_threads_test (int nr_threads) ++{ ++ pthread_t th[nr_threads]; ++ int i; ++ int result = 0; ++ ++ xpthread_barrier_init (&cancel_thread_barrier, NULL, 2); ++ ++ for (i = 0; i < nr_threads; ++i) ++ th[i] = xpthread_create (NULL, thread_function, ++ (void *) (intptr_t) i); ++ ++ (void) xpthread_barrier_wait (&cancel_thread_barrier); ++ ++ xpthread_cancel (th[0]); ++ ++ for (i = 0; i < nr_threads; ++i) ++ { ++ void *v; ++ ++ v = xpthread_join (th[i]); ++ if (i != 0 && v != NULL) ++ { ++ printf ("error: join %d successful, but child failed\n", i); ++ result = 1; ++ } ++ else if (i == 0 && v == NULL) ++ { ++ printf ("error: join %d successful, child did not fail as expected\n", i); ++ result = 1; ++ } ++ } ++ ++ xpthread_barrier_destroy (&cancel_thread_barrier); ++ ++ return result; ++} ++ ++static void ++subprocess_callback (void *closure) ++{ ++ do_rseq_main_test (); ++} ++ ++static void ++do_rseq_fork_test (void) ++{ ++ support_isolate_in_subprocess (subprocess_callback, NULL); ++} ++ ++static int ++do_rseq_test (void) ++{ ++ int t[] = { 1, 2, 6, 5, 4, 3, 50 }; ++ int i, result = 0; ++ ++ if (!rseq_available ()) ++ FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test"); ++ setup_signals (); ++ xraise (SIGUSR1); ++ do_rseq_main_test (); ++ for (i = 0; i < array_length (t); i++) ++ if (do_rseq_threads_test (t[i])) ++ result = 1; ++ do_rseq_fork_test (); ++ return result; ++} ++ ++static void __attribute__ ((destructor)) ++do_rseq_destructor_test (void) ++{ ++ /* Cannot use deferred failure reporting after main returns. */ ++ if (do_rseq_test ()) ++ FAIL_EXIT1 ("rseq not registered within destructor"); ++ xpthread_key_delete (rseq_test_key); ++} ++ ++#else /* RSEQ_SIG */ ++static int ++do_rseq_test (void) ++{ ++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test"); ++ return 0; ++} ++#endif /* RSEQ_SIG */ ++ ++static int ++do_test (void) ++{ ++ return do_rseq_test (); ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c +new file mode 100644 +index 00000000..926376b6 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-rseq.c +@@ -0,0 +1,64 @@ ++/* Restartable Sequences single-threaded tests. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 ++ . */ ++ ++/* These tests validate that rseq is registered from main in an executable ++ not linked against libpthread. */ ++ ++#include ++#include ++#include ++#include ++ ++#ifdef RSEQ_SIG ++# include ++# include ++# include ++# include ++# include ++# include "tst-rseq.h" ++ ++static void ++do_rseq_main_test (void) ++{ ++ TEST_VERIFY_EXIT (rseq_thread_registered ()); ++} ++ ++static void ++do_rseq_test (void) ++{ ++ if (!rseq_available ()) ++ { ++ FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test"); ++ } ++ do_rseq_main_test (); ++} ++#else /* RSEQ_SIG */ ++static void ++do_rseq_test (void) ++{ ++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test"); ++} ++#endif /* RSEQ_SIG */ ++ ++static int ++do_test (void) ++{ ++ do_rseq_test (); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/tst-rseq.h b/sysdeps/unix/sysv/linux/tst-rseq.h +new file mode 100644 +index 00000000..a476c316 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-rseq.h +@@ -0,0 +1,57 @@ ++/* Restartable Sequences tests header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 ++ ++static inline bool ++rseq_thread_registered (void) ++{ ++ return THREAD_GETMEM_VOLATILE (THREAD_SELF, rseq_area.cpu_id) >= 0; ++} ++ ++static inline int ++sys_rseq (struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig) ++{ ++ return syscall (__NR_rseq, rseq_abi, rseq_len, flags, sig); ++} ++ ++static inline bool ++rseq_available (void) ++{ ++ int rc; ++ ++ rc = sys_rseq (NULL, 0, 0, 0); ++ if (rc != -1) ++ FAIL_EXIT1 ("Unexpected rseq return value %d", rc); ++ switch (errno) ++ { ++ case ENOSYS: ++ return false; ++ case EINVAL: ++ /* rseq is implemented, but detected an invalid rseq_len parameter. */ ++ return true; ++ default: ++ FAIL_EXIT1 ("Unexpected rseq error %s", strerror (errno)); ++ } ++} +diff --git a/sysdeps/unix/sysv/linux/x86/bits/rseq.h b/sysdeps/unix/sysv/linux/x86/bits/rseq.h +new file mode 100644 +index 00000000..9fc909e7 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/x86/bits/rseq.h +@@ -0,0 +1,30 @@ ++/* Restartable Sequences Linux x86 architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ 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 _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ RSEQ_SIG is used with the following reserved undefined instructions, which ++ trap in user-space: ++ ++ x86-32: 0f b9 3d 53 30 05 53 ud1 0x53053053,%edi ++ x86-64: 0f b9 3d 53 30 05 53 ud1 0x53053053(%rip),%edi */ ++ ++#define RSEQ_SIG 0x53053053 +-- +2.23.0 + diff --git a/rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch b/rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch new file mode 100644 index 0000000..39c25a0 --- /dev/null +++ b/rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch @@ -0,0 +1,141 @@ +From c773e8d7fb0c7a97290bd889ba984411a1952e9e Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 9 Dec 2021 09:49:32 +0100 +Subject: [PATCH 1/9] nptl: Add for defining + __thread_pointer + + already contains a definition that is quite similar, +but it is not consistent across architectures. + +Only architectures for which rseq support is added are covered. + +Reviewed-by: Szabolcs Nagy +--- + sysdeps/nptl/thread_pointer.h | 28 ++++++++++++++++++++ + sysdeps/powerpc/nptl/thread_pointer.h | 33 +++++++++++++++++++++++ + sysdeps/x86/nptl/thread_pointer.h | 38 +++++++++++++++++++++++++++ + 3 files changed, 99 insertions(+) + create mode 100644 sysdeps/nptl/thread_pointer.h + create mode 100644 sysdeps/powerpc/nptl/thread_pointer.h + create mode 100644 sysdeps/x86/nptl/thread_pointer.h + +diff --git a/sysdeps/nptl/thread_pointer.h b/sysdeps/nptl/thread_pointer.h +new file mode 100644 +index 00000000..92f2f309 +--- /dev/null ++++ b/sysdeps/nptl/thread_pointer.h +@@ -0,0 +1,28 @@ ++/* __thread_pointer definition. Generic version. ++ Copyright (C) 2021 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 _SYS_THREAD_POINTER_H ++#define _SYS_THREAD_POINTER_H ++ ++static inline void * ++__thread_pointer (void) ++{ ++ return __builtin_thread_pointer (); ++} ++ ++#endif /* _SYS_THREAD_POINTER_H */ +diff --git a/sysdeps/powerpc/nptl/thread_pointer.h b/sysdeps/powerpc/nptl/thread_pointer.h +new file mode 100644 +index 00000000..8fd5ba67 +--- /dev/null ++++ b/sysdeps/powerpc/nptl/thread_pointer.h +@@ -0,0 +1,33 @@ ++/* __thread_pointer definition. powerpc version. ++ Copyright (C) 2021 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 _SYS_THREAD_POINTER_H ++#define _SYS_THREAD_POINTER_H ++ ++static inline void * ++__thread_pointer (void) ++{ ++#ifdef __powerpc64__ ++ register void *__result asm ("r13"); ++#else ++ register void *__result asm ("r2"); ++#endif ++ return __result; ++} ++ ++#endif /* _SYS_THREAD_POINTER_H */ +diff --git a/sysdeps/x86/nptl/thread_pointer.h b/sysdeps/x86/nptl/thread_pointer.h +new file mode 100644 +index 00000000..6b71b6f7 +--- /dev/null ++++ b/sysdeps/x86/nptl/thread_pointer.h +@@ -0,0 +1,38 @@ ++/* __thread_pointer definition. x86 version. ++ Copyright (C) 2021 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 _SYS_THREAD_POINTER_H ++#define _SYS_THREAD_POINTER_H ++ ++static inline void * ++__thread_pointer (void) ++{ ++#if __GNUC_PREREQ (11, 1) ++ return __builtin_thread_pointer (); ++#else ++ void *__result; ++# ifdef __x86_64__ ++ __asm__ ("mov %%fs:0, %0" : "=r" (__result)); ++# else ++ __asm__ ("mov %%gs:0, %0" : "=r" (__result)); ++# endif ++ return __result; ++#endif /* !GCC 11 */ ++} ++ ++#endif /* _SYS_THREAD_POINTER_H */ +-- +2.23.0 + diff --git a/rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch b/rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch new file mode 100644 index 0000000..4ad2329 --- /dev/null +++ b/rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch @@ -0,0 +1,56 @@ +From 6a8628eca8c8b22ccfd1422f2eb27bb665cfd660 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 9 Dec 2021 09:49:32 +0100 +Subject: [PATCH 3/9] nptl: Introduce THREAD_GETMEM_VOLATILE + +This will be needed for rseq TCB access. + +Reviewed-by: Szabolcs Nagy +--- + sysdeps/i386/nptl/tcb-access.h | 2 ++ + sysdeps/nptl/tcb-access.h | 2 ++ + sysdeps/x86_64/nptl/tcb-access.h | 2 ++ + 3 files changed, 6 insertions(+) + +diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h +index 6c6d561e..5ddd8322 100644 +--- a/sysdeps/i386/nptl/tcb-access.h ++++ b/sysdeps/i386/nptl/tcb-access.h +@@ -41,6 +41,8 @@ + } \ + __value; }) + ++/* THREAD_GETMEM already forces a read. */ ++#define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member) + + /* Same as THREAD_GETMEM, but the member offset can be non-constant. */ + #define THREAD_GETMEM_NC(descr, member, idx) \ +diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h +index b4137b8a..bbe20b72 100644 +--- a/sysdeps/nptl/tcb-access.h ++++ b/sysdeps/nptl/tcb-access.h +@@ -22,6 +22,8 @@ + + #define THREAD_GETMEM(descr, member) \ + descr->member ++#define THREAD_GETMEM_VOLATILE(descr, member) \ ++ (*(volatile __typeof (descr->member) *)&descr->member) + #define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] + #define THREAD_SETMEM(descr, member, value) \ +diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h +index 18848a72..e4d2d07a 100644 +--- a/sysdeps/x86_64/nptl/tcb-access.h ++++ b/sysdeps/x86_64/nptl/tcb-access.h +@@ -39,6 +39,8 @@ + } \ + __value; }) + ++/* THREAD_GETMEM already forces a read. */ ++#define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member) + + /* Same as THREAD_GETMEM, but the member offset can be non-constant. */ + # define THREAD_GETMEM_NC(descr, member, idx) \ +-- +2.23.0 + diff --git a/rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch b/rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch new file mode 100644 index 0000000..0d54119 --- /dev/null +++ b/rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch @@ -0,0 +1,935 @@ +From da3869963c4039b583d011e5612c2546efe90ed3 Mon Sep 17 00:00:00 2001 +From: qinyu +Date: Fri, 25 Feb 2022 10:55:45 +0800 +Subject: [PATCH 2/9] nptl: Introduce for THREAD_* accessors + +These are common between most architectures. Only the x86 targets +are outliers. + +Reviewed-by: Szabolcs Nagy +------ +conflicts: + context conflicts +--- + sysdeps/aarch64/nptl/tls.h | 10 +-- + sysdeps/alpha/nptl/tls.h | 10 +-- + sysdeps/arc/nptl/tls.h | 10 +-- + sysdeps/arm/nptl/tls.h | 10 +-- + sysdeps/csky/nptl/tls.h | 10 +-- + sysdeps/hppa/nptl/tls.h | 10 +-- + sysdeps/i386/nptl/tcb-access.h | 123 +++++++++++++++++++++++++++++ + sysdeps/i386/nptl/tls.h | 108 +------------------------ + sysdeps/ia64/nptl/tls.h | 10 +-- + sysdeps/m68k/nptl/tls.h | 10 +-- + sysdeps/microblaze/nptl/tls.h | 15 +--- + sysdeps/mips/nptl/tls.h | 9 +-- + sysdeps/nios2/nptl/tls.h | 10 +-- + sysdeps/nptl/tcb-access.h | 30 +++++++ + sysdeps/powerpc/nptl/tls.h | 15 +--- + sysdeps/riscv/nptl/tls.h | 9 +-- + sysdeps/s390/nptl/tls.h | 10 +-- + sysdeps/sh/nptl/tls.h | 14 +--- + sysdeps/sparc/nptl/tls.h | 10 +-- + sysdeps/x86_64/nptl/tcb-access.h | 130 +++++++++++++++++++++++++++++++ + sysdeps/x86_64/nptl/tls.h | 114 +-------------------------- + 21 files changed, 301 insertions(+), 376 deletions(-) + create mode 100644 sysdeps/i386/nptl/tcb-access.h + create mode 100644 sysdeps/nptl/tcb-access.h + create mode 100644 sysdeps/x86_64/nptl/tcb-access.h + +diff --git a/sysdeps/aarch64/nptl/tls.h b/sysdeps/aarch64/nptl/tls.h +index 6e896207..cd9abb5d 100644 +--- a/sysdeps/aarch64/nptl/tls.h ++++ b/sysdeps/aarch64/nptl/tls.h +@@ -98,15 +98,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (64, sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + # define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/alpha/nptl/tls.h b/sysdeps/alpha/nptl/tls.h +index 4dbccc52..5f4843b2 100644 +--- a/sysdeps/alpha/nptl/tls.h ++++ b/sysdeps/alpha/nptl/tls.h +@@ -92,15 +92,7 @@ typedef struct + # define DB_THREAD_SELF \ + REGISTER (64, 64, 32 * 8, -sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + #define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/arc/nptl/tls.h b/sysdeps/arc/nptl/tls.h +index 95300fdd..d9ada2f3 100644 +--- a/sysdeps/arc/nptl/tls.h ++++ b/sysdeps/arc/nptl/tls.h +@@ -100,15 +100,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + #define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/arm/nptl/tls.h b/sysdeps/arm/nptl/tls.h +index 1bd11307..354aae33 100644 +--- a/sysdeps/arm/nptl/tls.h ++++ b/sysdeps/arm/nptl/tls.h +@@ -89,15 +89,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + #define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/csky/nptl/tls.h b/sysdeps/csky/nptl/tls.h +index 7a234041..f3fa3fcb 100644 +--- a/sysdeps/csky/nptl/tls.h ++++ b/sysdeps/csky/nptl/tls.h +@@ -116,15 +116,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + # define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/hppa/nptl/tls.h b/sysdeps/hppa/nptl/tls.h +index 857003a7..f0e274c4 100644 +--- a/sysdeps/hppa/nptl/tls.h ++++ b/sysdeps/hppa/nptl/tls.h +@@ -107,15 +107,7 @@ typedef struct + # define DB_THREAD_SELF \ + REGISTER (32, 32, 53 * 4, -sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + static inline struct pthread *__get_cr27(void) + { +diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h +new file mode 100644 +index 00000000..6c6d561e +--- /dev/null ++++ b/sysdeps/i386/nptl/tcb-access.h +@@ -0,0 +1,123 @@ ++/* THREAD_* accessors. i386 version. ++ Copyright (C) 2002-2021 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 ++ . */ ++ ++/* Read member of the thread descriptor directly. */ ++#define THREAD_GETMEM(descr, member) \ ++ ({ __typeof (descr->member) __value; \ ++ _Static_assert (sizeof (__value) == 1 \ ++ || sizeof (__value) == 4 \ ++ || sizeof (__value) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (__value) == 1) \ ++ asm volatile ("movb %%gs:%P2,%b0" \ ++ : "=q" (__value) \ ++ : "0" (0), "i" (offsetof (struct pthread, member))); \ ++ else if (sizeof (__value) == 4) \ ++ asm volatile ("movl %%gs:%P1,%0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member))); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movl %%gs:%P1,%%eax\n\t" \ ++ "movl %%gs:%P2,%%edx" \ ++ : "=A" (__value) \ ++ : "i" (offsetof (struct pthread, member)), \ ++ "i" (offsetof (struct pthread, member) + 4)); \ ++ } \ ++ __value; }) ++ ++ ++/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ ++#define THREAD_GETMEM_NC(descr, member, idx) \ ++ ({ __typeof (descr->member[0]) __value; \ ++ _Static_assert (sizeof (__value) == 1 \ ++ || sizeof (__value) == 4 \ ++ || sizeof (__value) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (__value) == 1) \ ++ asm volatile ("movb %%gs:%P2(%3),%b0" \ ++ : "=q" (__value) \ ++ : "0" (0), "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else if (sizeof (__value) == 4) \ ++ asm volatile ("movl %%gs:%P1(,%2,4),%0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \ ++ "movl %%gs:4+%P1(,%2,8),%%edx" \ ++ : "=&A" (__value) \ ++ : "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ } \ ++ __value; }) ++ ++ ++ ++/* Set member of the thread descriptor directly. */ ++#define THREAD_SETMEM(descr, member, value) \ ++ ({ \ ++ _Static_assert (sizeof (descr->member) == 1 \ ++ || sizeof (descr->member) == 4 \ ++ || sizeof (descr->member) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (descr->member) == 1) \ ++ asm volatile ("movb %b0,%%gs:%P1" : \ ++ : "iq" (value), \ ++ "i" (offsetof (struct pthread, member))); \ ++ else if (sizeof (descr->member) == 4) \ ++ asm volatile ("movl %0,%%gs:%P1" : \ ++ : "ir" (value), \ ++ "i" (offsetof (struct pthread, member))); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movl %%eax,%%gs:%P1\n\t" \ ++ "movl %%edx,%%gs:%P2" : \ ++ : "A" ((uint64_t) cast_to_integer (value)), \ ++ "i" (offsetof (struct pthread, member)), \ ++ "i" (offsetof (struct pthread, member) + 4)); \ ++ }}) ++ ++ ++/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ ++#define THREAD_SETMEM_NC(descr, member, idx, value) \ ++ ({ \ ++ _Static_assert (sizeof (descr->member[0]) == 1 \ ++ || sizeof (descr->member[0]) == 4 \ ++ || sizeof (descr->member[0]) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (descr->member[0]) == 1) \ ++ asm volatile ("movb %b0,%%gs:%P1(%2)" : \ ++ : "iq" (value), \ ++ "i" (offsetof (struct pthread, member)), \ ++ "r" (idx)); \ ++ else if (sizeof (descr->member[0]) == 4) \ ++ asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \ ++ : "ir" (value), \ ++ "i" (offsetof (struct pthread, member)), \ ++ "r" (idx)); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \ ++ "movl %%edx,%%gs:4+%P1(,%2,8)" : \ ++ : "A" ((uint64_t) cast_to_integer (value)), \ ++ "i" (offsetof (struct pthread, member)), \ ++ "r" (idx)); \ ++ }}) +diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h +index 86ee1ef3..111c9ee5 100644 +--- a/sysdeps/i386/nptl/tls.h ++++ b/sysdeps/i386/nptl/tls.h +@@ -250,113 +250,7 @@ tls_fill_user_desc (union user_desc_init *desc, + REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \ + REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */ + +- +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) \ +- ({ __typeof (descr->member) __value; \ +- _Static_assert (sizeof (__value) == 1 \ +- || sizeof (__value) == 4 \ +- || sizeof (__value) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (__value) == 1) \ +- asm volatile ("movb %%gs:%P2,%b0" \ +- : "=q" (__value) \ +- : "0" (0), "i" (offsetof (struct pthread, member))); \ +- else if (sizeof (__value) == 4) \ +- asm volatile ("movl %%gs:%P1,%0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member))); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movl %%gs:%P1,%%eax\n\t" \ +- "movl %%gs:%P2,%%edx" \ +- : "=A" (__value) \ +- : "i" (offsetof (struct pthread, member)), \ +- "i" (offsetof (struct pthread, member) + 4)); \ +- } \ +- __value; }) +- +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- ({ __typeof (descr->member[0]) __value; \ +- _Static_assert (sizeof (__value) == 1 \ +- || sizeof (__value) == 4 \ +- || sizeof (__value) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (__value) == 1) \ +- asm volatile ("movb %%gs:%P2(%3),%b0" \ +- : "=q" (__value) \ +- : "0" (0), "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else if (sizeof (__value) == 4) \ +- asm volatile ("movl %%gs:%P1(,%2,4),%0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \ +- "movl %%gs:4+%P1(,%2,8),%%edx" \ +- : "=&A" (__value) \ +- : "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- } \ +- __value; }) +- +- +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- ({ \ +- _Static_assert (sizeof (descr->member) == 1 \ +- || sizeof (descr->member) == 4 \ +- || sizeof (descr->member) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (descr->member) == 1) \ +- asm volatile ("movb %b0,%%gs:%P1" : \ +- : "iq" (value), \ +- "i" (offsetof (struct pthread, member))); \ +- else if (sizeof (descr->member) == 4) \ +- asm volatile ("movl %0,%%gs:%P1" : \ +- : "ir" (value), \ +- "i" (offsetof (struct pthread, member))); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movl %%eax,%%gs:%P1\n\t" \ +- "movl %%edx,%%gs:%P2" : \ +- : "A" ((uint64_t) cast_to_integer (value)), \ +- "i" (offsetof (struct pthread, member)), \ +- "i" (offsetof (struct pthread, member) + 4)); \ +- }}) +- +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- ({ \ +- _Static_assert (sizeof (descr->member[0]) == 1 \ +- || sizeof (descr->member[0]) == 4 \ +- || sizeof (descr->member[0]) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (descr->member[0]) == 1) \ +- asm volatile ("movb %b0,%%gs:%P1(%2)" : \ +- : "iq" (value), \ +- "i" (offsetof (struct pthread, member)), \ +- "r" (idx)); \ +- else if (sizeof (descr->member[0]) == 4) \ +- asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \ +- : "ir" (value), \ +- "i" (offsetof (struct pthread, member)), \ +- "r" (idx)); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \ +- "movl %%edx,%%gs:4+%P1(,%2,8)" : \ +- : "A" ((uint64_t) cast_to_integer (value)), \ +- "i" (offsetof (struct pthread, member)), \ +- "r" (idx)); \ +- }}) +- ++# include + + /* Set the stack guard field in TCB head. */ + #define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/ia64/nptl/tls.h b/sysdeps/ia64/nptl/tls.h +index 66d9bf31..26fe555c 100644 +--- a/sysdeps/ia64/nptl/tls.h ++++ b/sysdeps/ia64/nptl/tls.h +@@ -128,15 +128,7 @@ register struct pthread *__thread_self __asm__("r13"); + /* Magic for libthread_db to know how to do THREAD_SELF. */ + # define DB_THREAD_SELF REGISTER (64, 64, 13 * 8, -TLS_PRE_TCB_SIZE) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Set the stack guard field in TCB head. */ + #define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/m68k/nptl/tls.h b/sysdeps/m68k/nptl/tls.h +index cfcd6d2b..9f562c38 100644 +--- a/sysdeps/m68k/nptl/tls.h ++++ b/sysdeps/m68k/nptl/tls.h +@@ -118,15 +118,7 @@ extern void * __m68k_read_tp (void); + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* l_tls_offset == 0 is perfectly valid on M68K, so we have to use some + different value to mean unset l_tls_offset. */ +diff --git a/sysdeps/microblaze/nptl/tls.h b/sysdeps/microblaze/nptl/tls.h +index c93d90b1..bfa6efa7 100644 +--- a/sysdeps/microblaze/nptl/tls.h ++++ b/sysdeps/microblaze/nptl/tls.h +@@ -100,20 +100,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) (descr->member) +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- (descr->member[idx]) +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- (descr->member = (value)) +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- (descr->member[idx] = (value)) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + # define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h +index c09f4907..ef99aa64 100644 +--- a/sysdeps/mips/nptl/tls.h ++++ b/sysdeps/mips/nptl/tls.h +@@ -144,14 +144,7 @@ typedef struct + CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + + /* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some + different value to mean unset l_tls_offset. */ +diff --git a/sysdeps/nios2/nptl/tls.h b/sysdeps/nios2/nptl/tls.h +index 02a05b4e..7110cfcc 100644 +--- a/sysdeps/nios2/nptl/tls.h ++++ b/sysdeps/nios2/nptl/tls.h +@@ -112,15 +112,7 @@ register struct pthread *__thread_self __asm__("r23"); + # define DB_THREAD_SELF \ + REGISTER (32, 32, 23 * 4, -TLS_PRE_TCB_SIZE - TLS_TCB_OFFSET) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + # define THREAD_GET_POINTER_GUARD() \ + (((tcbhead_t *) (READ_THREAD_POINTER () \ +diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h +new file mode 100644 +index 00000000..b4137b8a +--- /dev/null ++++ b/sysdeps/nptl/tcb-access.h +@@ -0,0 +1,30 @@ ++/* THREAD_* accessors. Generic version based on struct pthread pointers. ++ Copyright (C) 2002-2021 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 ++ . */ ++ ++/* Note: These are for accessing the TCB of the *current* thread. ++ descr can be disregarded on some targets as an optimization. See ++ i386 for an example. */ ++ ++#define THREAD_GETMEM(descr, member) \ ++ descr->member ++#define THREAD_GETMEM_NC(descr, member, idx) \ ++ descr->member[idx] ++#define THREAD_SETMEM(descr, member, value) \ ++ descr->member = (value) ++#define THREAD_SETMEM_NC(descr, member, idx, value) \ ++ descr->member[idx] = (value) +diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h +index 6c779b66..110d085d 100644 +--- a/sysdeps/powerpc/nptl/tls.h ++++ b/sysdeps/powerpc/nptl/tls.h +@@ -176,20 +176,7 @@ typedef struct + REGISTER (64, 64, PT_THREAD_POINTER * 8, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member) +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- ((void)(descr), (THREAD_SELF)->member[idx]) +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- ((void)(descr), (THREAD_SELF)->member = (value)) +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- ((void)(descr), (THREAD_SELF)->member[idx] = (value)) ++# include + + /* Set the stack guard field in TCB head. */ + # define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/riscv/nptl/tls.h b/sysdeps/riscv/nptl/tls.h +index 5350bcc0..bdc0a3a6 100644 +--- a/sysdeps/riscv/nptl/tls.h ++++ b/sysdeps/riscv/nptl/tls.h +@@ -105,14 +105,7 @@ typedef struct + REGISTER (64, 64, 4 * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + + /* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* l_tls_offset == 0 is perfectly valid, so we have to use some different + value to mean unset l_tls_offset. */ +diff --git a/sysdeps/s390/nptl/tls.h b/sysdeps/s390/nptl/tls.h +index efb52515..2cdd18eb 100644 +--- a/sysdeps/s390/nptl/tls.h ++++ b/sysdeps/s390/nptl/tls.h +@@ -135,15 +135,7 @@ typedef struct + # define DB_THREAD_SELF REGISTER (32, 32, 18 * 4, 0) \ + REGISTER (64, __WORDSIZE, 18 * 8, 0) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Set the stack guard field in TCB head. */ + #define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/sh/nptl/tls.h b/sysdeps/sh/nptl/tls.h +index ac3c9a9e..39064002 100644 +--- a/sysdeps/sh/nptl/tls.h ++++ b/sysdeps/sh/nptl/tls.h +@@ -113,19 +113,7 @@ typedef struct + # define DB_THREAD_SELF \ + REGISTER (32, 32, REG_GBR * 4, -sizeof (struct pthread)) + +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) (descr->member) +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) (descr->member[idx]) +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + #define THREAD_GET_POINTER_GUARD() \ + ({ tcbhead_t *__tcbp; \ +diff --git a/sysdeps/sparc/nptl/tls.h b/sysdeps/sparc/nptl/tls.h +index dd1eb82a..376d7299 100644 +--- a/sysdeps/sparc/nptl/tls.h ++++ b/sysdeps/sparc/nptl/tls.h +@@ -112,15 +112,7 @@ register struct pthread *__thread_self __asm__("%g7"); + REGISTER (32, 32, 10 * 4, 0) \ + REGISTER (64, __WORDSIZE, (6 * 8) + (__WORDSIZE==64?0:4), 0) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Set the stack guard field in TCB head. */ + #define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h +new file mode 100644 +index 00000000..18848a72 +--- /dev/null ++++ b/sysdeps/x86_64/nptl/tcb-access.h +@@ -0,0 +1,130 @@ ++/* THREAD_* accessors. x86_64 version. ++ Copyright (C) 2002-2021 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 ++ . */ ++ ++/* Read member of the thread descriptor directly. */ ++# define THREAD_GETMEM(descr, member) \ ++ ({ __typeof (descr->member) __value; \ ++ _Static_assert (sizeof (__value) == 1 \ ++ || sizeof (__value) == 4 \ ++ || sizeof (__value) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (__value) == 1) \ ++ asm volatile ("movb %%fs:%P2,%b0" \ ++ : "=q" (__value) \ ++ : "0" (0), "i" (offsetof (struct pthread, member))); \ ++ else if (sizeof (__value) == 4) \ ++ asm volatile ("movl %%fs:%P1,%0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member))); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movq %%fs:%P1,%q0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member))); \ ++ } \ ++ __value; }) ++ ++ ++/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ ++# define THREAD_GETMEM_NC(descr, member, idx) \ ++ ({ __typeof (descr->member[0]) __value; \ ++ _Static_assert (sizeof (__value) == 1 \ ++ || sizeof (__value) == 4 \ ++ || sizeof (__value) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (__value) == 1) \ ++ asm volatile ("movb %%fs:%P2(%q3),%b0" \ ++ : "=q" (__value) \ ++ : "0" (0), "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else if (sizeof (__value) == 4) \ ++ asm volatile ("movl %%fs:%P1(,%q2,4),%0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member[0])), "r" (idx));\ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ } \ ++ __value; }) ++ ++ ++/* Loading addresses of objects on x86-64 needs to be treated special ++ when generating PIC code. */ ++#ifdef __pic__ ++# define IMM_MODE "nr" ++#else ++# define IMM_MODE "ir" ++#endif ++ ++ ++/* Set member of the thread descriptor directly. */ ++# define THREAD_SETMEM(descr, member, value) \ ++ ({ \ ++ _Static_assert (sizeof (descr->member) == 1 \ ++ || sizeof (descr->member) == 4 \ ++ || sizeof (descr->member) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (descr->member) == 1) \ ++ asm volatile ("movb %b0,%%fs:%P1" : \ ++ : "iq" (value), \ ++ "i" (offsetof (struct pthread, member))); \ ++ else if (sizeof (descr->member) == 4) \ ++ asm volatile ("movl %0,%%fs:%P1" : \ ++ : IMM_MODE (value), \ ++ "i" (offsetof (struct pthread, member))); \ ++ else /* 8 */ \ ++ { \ ++ /* Since movq takes a signed 32-bit immediate or a register source \ ++ operand, use "er" constraint for 32-bit signed integer constant \ ++ or register. */ \ ++ asm volatile ("movq %q0,%%fs:%P1" : \ ++ : "er" ((uint64_t) cast_to_integer (value)), \ ++ "i" (offsetof (struct pthread, member))); \ ++ }}) ++ ++ ++/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ ++# define THREAD_SETMEM_NC(descr, member, idx, value) \ ++ ({ \ ++ _Static_assert (sizeof (descr->member[0]) == 1 \ ++ || sizeof (descr->member[0]) == 4 \ ++ || sizeof (descr->member[0]) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (descr->member[0]) == 1) \ ++ asm volatile ("movb %b0,%%fs:%P1(%q2)" : \ ++ : "iq" (value), \ ++ "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else if (sizeof (descr->member[0]) == 4) \ ++ asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \ ++ : IMM_MODE (value), \ ++ "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else /* 8 */ \ ++ { \ ++ /* Since movq takes a signed 32-bit immediate or a register source \ ++ operand, use "er" constraint for 32-bit signed integer constant \ ++ or register. */ \ ++ asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ ++ : "er" ((uint64_t) cast_to_integer (value)), \ ++ "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ }}) +diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h +index a78c4f4d..3af1836e 100644 +--- a/sysdeps/x86_64/nptl/tls.h ++++ b/sysdeps/x86_64/nptl/tls.h +@@ -195,119 +195,7 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, + # define DB_THREAD_SELF_INCLUDE /* For the FS constant. */ + # define DB_THREAD_SELF CONST_THREAD_AREA (64, FS) + +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) \ +- ({ __typeof (descr->member) __value; \ +- _Static_assert (sizeof (__value) == 1 \ +- || sizeof (__value) == 4 \ +- || sizeof (__value) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (__value) == 1) \ +- asm volatile ("movb %%fs:%P2,%b0" \ +- : "=q" (__value) \ +- : "0" (0), "i" (offsetof (struct pthread, member))); \ +- else if (sizeof (__value) == 4) \ +- asm volatile ("movl %%fs:%P1,%0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member))); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movq %%fs:%P1,%q0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member))); \ +- } \ +- __value; }) +- +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- ({ __typeof (descr->member[0]) __value; \ +- _Static_assert (sizeof (__value) == 1 \ +- || sizeof (__value) == 4 \ +- || sizeof (__value) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (__value) == 1) \ +- asm volatile ("movb %%fs:%P2(%q3),%b0" \ +- : "=q" (__value) \ +- : "0" (0), "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else if (sizeof (__value) == 4) \ +- asm volatile ("movl %%fs:%P1(,%q2,4),%0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member[0])), "r" (idx));\ +- else /* 8 */ \ +- { \ +- asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- } \ +- __value; }) +- +- +-/* Loading addresses of objects on x86-64 needs to be treated special +- when generating PIC code. */ +-#ifdef __pic__ +-# define IMM_MODE "nr" +-#else +-# define IMM_MODE "ir" +-#endif +- +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- ({ \ +- _Static_assert (sizeof (descr->member) == 1 \ +- || sizeof (descr->member) == 4 \ +- || sizeof (descr->member) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (descr->member) == 1) \ +- asm volatile ("movb %b0,%%fs:%P1" : \ +- : "iq" (value), \ +- "i" (offsetof (struct pthread, member))); \ +- else if (sizeof (descr->member) == 4) \ +- asm volatile ("movl %0,%%fs:%P1" : \ +- : IMM_MODE (value), \ +- "i" (offsetof (struct pthread, member))); \ +- else /* 8 */ \ +- { \ +- /* Since movq takes a signed 32-bit immediate or a register source \ +- operand, use "er" constraint for 32-bit signed integer constant \ +- or register. */ \ +- asm volatile ("movq %q0,%%fs:%P1" : \ +- : "er" ((uint64_t) cast_to_integer (value)), \ +- "i" (offsetof (struct pthread, member))); \ +- }}) +- +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- ({ \ +- _Static_assert (sizeof (descr->member[0]) == 1 \ +- || sizeof (descr->member[0]) == 4 \ +- || sizeof (descr->member[0]) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (descr->member[0]) == 1) \ +- asm volatile ("movb %b0,%%fs:%P1(%q2)" : \ +- : "iq" (value), \ +- "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else if (sizeof (descr->member[0]) == 4) \ +- asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \ +- : IMM_MODE (value), \ +- "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else /* 8 */ \ +- { \ +- /* Since movq takes a signed 32-bit immediate or a register source \ +- operand, use "er" constraint for 32-bit signed integer constant \ +- or register. */ \ +- asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ +- : "er" ((uint64_t) cast_to_integer (value)), \ +- "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- }}) +- ++# include + + /* Set the stack guard field in TCB head. */ + # define THREAD_SET_STACK_GUARD(value) \ +-- +2.23.0 + diff --git a/rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch b/rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch new file mode 100644 index 0000000..7fd271a --- /dev/null +++ b/rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch @@ -0,0 +1,44 @@ +From 210967ce32172eb7356747ed0b655e1fc37d0c57 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 9 Dec 2021 09:49:32 +0100 +Subject: [PATCH 8/9] nptl: rseq failure after registration on main thread is + fatal + +This simplifies the application programming model. + +Browser sandboxes have already been fixed: + + Sandbox is incompatible with rseq registration + + + Allow rseq in the Linux sandboxes. r=gcp + + + Sandbox needs to support rseq system call + + + Linux sandbox: Allow rseq(2) + + +Reviewed-by: Szabolcs Nagy +--- + nptl/pthread_create.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index f405fa35..109c5e3d 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -371,7 +371,8 @@ start_thread (void *arg) + /* Register rseq TLS to the kernel. */ + { + bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ; +- rseq_register_current_thread (pd, do_rseq); ++ if (!rseq_register_current_thread (pd, do_rseq) && do_rseq) ++ __libc_fatal ("Fatal glibc error: rseq registration failed\n"); + } + + #ifndef __ASSUME_SET_ROBUST_LIST +-- +2.23.0 + -- Gitee From 6293129cfee5c816177fe357feb85b2eb4f60605 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Tue, 1 Mar 2022 15:21:08 +0800 Subject: [PATCH 61/70] remove shared library's RPATH/RUNPATH for security --- glibc.spec | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/glibc.spec b/glibc.spec index 114a83f..58eae2a 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 61 +Release: 62 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -902,6 +902,63 @@ echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.f echo "%{_libdir}/libpthread-2.17.so" >> compat-2.17.filelist %endif +reliantlib="" + +function findReliantLib() +{ + local library=$1 + reliantlib=$(readelf -d $library | grep "(NEEDED)" | awk -F "Shared library" '{print $2}')$reliantlib +} + +# remove gconv rpath/runpath +function removeLoadPath() +{ + local file=$1 + local rpathInfo=$(chrpath -l $file | grep "RPATH=") + local runpathInfo=$(chrpath -l $file | grep "RUNPATH=") + + local currPath="" + if [ x"$rpathInfo" != x"" ]; then + currPath=$(echo $rpathInfo | awk -F "RPATH=" '{print $2}') + fi + + if [ x"$runpathInfo" != x"" ]; then + currPath=$(echo $runpathInfo | awk -F "RUNPATH=" '{print $2}') + fi + + if [ x"$currPath" == x"\$ORIGIN" ]; then + chrpath -d $file + + findReliantLib $file + fi +} + +set +e + +# find and remove RPATH/RUNPATH +for file in $(find $RPM_BUILD_ROOT%{_libdir}/gconv/ -name "*.so" -exec file {} ';' | grep "\" | awk -F ':' '{print $1}') +do + removeLoadPath $file +done + +function createSoftLink() +{ + # pick up the dynamic libraries and create softlink for them + local tmplib=$(echo $reliantlib | sed 's/://g' | sed 's/ //g' | sed 's/\[//g' | sed 's/]/\n/g' | sort | uniq) + + for temp in $tmplib + do + if [ -f "$RPM_BUILD_ROOT%{_libdir}/gconv/$temp" ]; then + ln -sf %{_libdir}/gconv/$temp $RPM_BUILD_ROOT%{_libdir}/$temp + echo %{_libdir}/$temp >> glibc.filelist + fi + done +} + +# create soft link for the reliant libraries +createSoftLink +set -e + ############################################################################## # Run the glibc testsuite ############################################################################## @@ -1231,6 +1288,9 @@ fi %endif %changelog +* Tue Mar 1 2022 Qingqing Li - 2.34-62 +- remove shared library's RPATH/RUNPATH for security + * Fri Feb 25 2022 qinyu - 2.34-61 - add rseq support -- Gitee From 4dddc721893ec27859ab23de6e40db1c890a35a0 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 1 Mar 2022 17:08:00 +0800 Subject: [PATCH 62/70] glibc:Merge testsuite_whitelist.aarch64 and testsuite_whitelist.x86_64 to testsuite_whitelist. Signed-off-by: Yang Yanchao --- glibc.spec | 20 +-- ...te_whitelist.x86_64 => testsuite_whitelist | 25 ++-- testsuite_whitelist.aarch64 | 115 ------------------ 3 files changed, 27 insertions(+), 133 deletions(-) rename testsuite_whitelist.x86_64 => testsuite_whitelist (84%) delete mode 100644 testsuite_whitelist.aarch64 diff --git a/glibc.spec b/glibc.spec index 58eae2a..a76444c 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 62 +Release: 63 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -80,8 +80,7 @@ Source6: LicenseList Source7: replace_same_file_to_hard_link.py %if %{with testsuite} -Source8: testsuite_whitelist.aarch64 -Source9: testsuite_whitelist.x86_64 +Source8: testsuite_whitelist %endif Patch1: glibc-c-utf8-locale.patch @@ -966,14 +965,11 @@ set -e %if %{with testsuite} omit_testsuite() { - whitelist=$1 - sed -i '/^#/d' $whitelist - sed -i '/^[\s]*$/d' $whitelist while read testsuite; do testsuite_escape=$(echo "$testsuite" | \ sed 's/\([.+?^$\/\\|()\[]\|\]\)/\\\0/g') sed -i "/${testsuite_escape}/d" rpmbuild.tests.sum.not-passing - done < "$whitelist" + done } # Increase timeouts @@ -996,9 +992,10 @@ fi grep -v ^PASS: tests.sum | grep -v ^UNSUPPORTED > rpmbuild.tests.sum.not-passing || true # Delete the testsuite from the whitelist -cp $RPM_SOURCE_DIR/testsuite_whitelist.%{_target_cpu} testsuite_whitelist -omit_testsuite testsuite_whitelist -rm -rf testsuite_whitelist +cat %{SOURCE8} | \ + grep -v "^$\|^#" | \ + awk -F':' '{if($2 == "" || $2 ~ /'%{_target_cpu}'/ ) {print $1}}' |\ + omit_testsuite set +x if test -s rpmbuild.tests.sum.not-passing ; then @@ -1288,6 +1285,9 @@ fi %endif %changelog +* Tue Mar 1 2022 Yang Yanchao - 2.34-63 +- Merge testsuite_whitelist.aarch64 and testsuite_whitelist.x86_64 to testsuite_whitelist. + * Tue Mar 1 2022 Qingqing Li - 2.34-62 - remove shared library's RPATH/RUNPATH for security diff --git a/testsuite_whitelist.x86_64 b/testsuite_whitelist similarity index 84% rename from testsuite_whitelist.x86_64 rename to testsuite_whitelist index 8a74a6f..024457e 100644 --- a/testsuite_whitelist.x86_64 +++ b/testsuite_whitelist @@ -1,3 +1,9 @@ +# USAGE: +# If it's a generic error: +# testsuite +# If the test case fails on part of the architecture: +# testsuite:arch1,arch2 + # These test cases failed due to gcc_secure conform/ISO/setjmp.h/conform conform/ISO/stdlib.h/conform @@ -57,7 +63,7 @@ elf/circleload1 elf/constload1 elf/dblload elf/dblunload -elf/ifuncmain6pie +elf/ifuncmain6pie:x86_64 elf/lateglobal elf/reldep6 elf/resolvfail @@ -83,34 +89,37 @@ conform/XOPEN2K8/ndbm.h/linknamespace conform/XPG42/ndbm.h/conform conform/XPG42/ndbm.h/linknamespace -# Test whether the date/time is correct under different -# language libraries, use case problems, and see that +# Test whether the date/time is correct under different +# language libraries, use case problems, and see that # the compiled language library itself has no errors # https://sourceware.org/bugzilla/show_bug.cgi?id=23164 localedata/tst-langinfo-newlocale-static -# The use case itself passed but because +# The use case itself passed but because # test-xfail-tst-protected1a/test-xfail-tst-protected1b was added elf/tst-protected1a elf/tst-protected1b -# the test case is due to check whether a macro is defined -# in the header files. As GLIBC evolves, the position of the +# the test case is due to check whether a macro is defined +# in the header files. As GLIBC evolves, the position of the # macro changes, causing the use case to fail posix/annexc -# Check whether sys/mman.h is consistent with linux/mman.h. +# Check whether sys/mman.h is consistent with linux/mman.h. # kernel has a self-developed macro that does not require glibc adaptation # https://gitee.com/src-openeuler/kernel/issues/I4BZ9T?from=project-issue misc/tst-mman-consts # It need to build GliBC on a platform that supports CET -elf/check-cet +elf/check-cet:x86_64 # Add the tst-nss-files-hosts-long.root/etc/hosts of glibc to # the /etc/hosts directory of the system, and then run sucess nss/tst-nss-files-hosts-long +# The test case fails due to OBS machine restrictions which can be passed locally. +elf/tst-debug1:aarch64 + # This test case often fails in CI which is the high-pressure environment. # No better solution is available. This test case is shielded. rt/tst-cpuclock2 diff --git a/testsuite_whitelist.aarch64 b/testsuite_whitelist.aarch64 deleted file mode 100644 index bb0b3fa..0000000 --- a/testsuite_whitelist.aarch64 +++ /dev/null @@ -1,115 +0,0 @@ -# These test cases failed due to gcc_secure -conform/ISO/setjmp.h/conform -conform/ISO/stdlib.h/conform -conform/ISO/stdlib.h/linknamespace -conform/ISO/string.h/conform -conform/ISO11/setjmp.h/conform -conform/ISO11/stdio.h/conform -conform/ISO11/stdlib.h/conform -conform/ISO11/stdlib.h/linknamespace -conform/ISO11/string.h/conform -conform/ISO11/wchar.h/conform -conform/ISO99/setjmp.h/conform -conform/ISO99/stdio.h/conform -conform/ISO99/stdlib.h/conform -conform/ISO99/stdlib.h/linknamespace -conform/ISO99/string.h/conform -conform/ISO99/wchar.h/conform -conform/POSIX/stdlib.h/conform -conform/POSIX/stdlib.h/linknamespace -conform/POSIX/string.h/conform -conform/POSIX2008/fcntl.h/conform -conform/POSIX2008/mqueue.h/conform -conform/POSIX2008/stdio.h/conform -conform/POSIX2008/stdlib.h/conform -conform/POSIX2008/stdlib.h/linknamespace -conform/POSIX2008/wchar.h/conform -conform/UNIX98/stdlib.h/conform -conform/UNIX98/string.h/conform -conform/UNIX98/unistd.h/conform -conform/UNIX98/unistd.h/linknamespace -conform/UNIX98/wchar.h/conform -conform/XOPEN2K/fcntl.h/conform -conform/XOPEN2K/mqueue.h/conform -conform/XOPEN2K/stdio.h/conform -conform/XOPEN2K/stdlib.h/conform -conform/XOPEN2K/string.h/conform -conform/XOPEN2K/syslog.h/conform -conform/XOPEN2K/unistd.h/conform -conform/XOPEN2K/unistd.h/linknamespace -conform/XOPEN2K/wchar.h/conform -conform/XOPEN2K8/fcntl.h/conform -conform/XOPEN2K8/mqueue.h/conform -conform/XOPEN2K8/stdio.h/conform -conform/XOPEN2K8/stdlib.h/conform -conform/XOPEN2K8/syslog.h/conform -conform/XOPEN2K8/unistd.h/conform -conform/XOPEN2K8/unistd.h/linknamespace -conform/XOPEN2K8/wchar.h/conform -conform/XPG4/stdlib.h/conform -conform/XPG4/stdlib.h/linknamespace -conform/XPG4/string.h/conform -conform/XPG4/unistd.h/conform -conform/XPG42/stdlib.h/conform -conform/XPG42/string.h/conform -conform/XPG42/unistd.h/conform -elf/circleload1 -elf/constload1 -elf/dblload -elf/dblunload -elf/lateglobal -elf/reldep6 -elf/resolvfail -elf/tst-global1 -elf/tst-tls20 -nptl/tst-execstack - -# GCC no longer implements -conform/UNIX98/varargs.h/conform -conform/UNIX98/varargs.h/linknamespace -conform/XPG4/varargs.h/conform -conform/XPG4/varargs.h/linknamespace -conform/XPG42/varargs.h/conform -conform/XPG42/varargs.h/linknamespace - -# These cases depend on gdbm-devel -conform/UNIX98/ndbm.h/conform -conform/UNIX98/ndbm.h/linknamespace -conform/XOPEN2K/ndbm.h/conform -conform/XOPEN2K/ndbm.h/linknamespace -conform/XOPEN2K8/ndbm.h/conform -conform/XOPEN2K8/ndbm.h/linknamespace -conform/XPG42/ndbm.h/conform -conform/XPG42/ndbm.h/linknamespace - -# Test whether the date/time is correct under different -# language libraries, use case problems, and see that -# the compiled language library itself has no errors -# https://sourceware.org/bugzilla/show_bug.cgi?id=23164 -localedata/tst-langinfo-newlocale-static - -# The use case itself passed but because -# test-xfail-tst-protected1a/test-xfail-tst-protected1b was added -elf/tst-protected1a -elf/tst-protected1b - -# the test case is due to check whether a macro is defined -# in the header files. As GLIBC evolves, the position of the -# macro changes, causing the use case to fail -posix/annexc - -# Check whether sys/mman.h is consistent with linux/mman.h. -# kernel has a self-developed macro that does not require glibc adaptation -# https://gitee.com/src-openeuler/kernel/issues/I4BZ9T?from=project-issue -misc/tst-mman-consts - -# Add the tst-nss-files-hosts-long.root/etc/hosts of glibc to -# the /etc/hosts directory of the system, and then run sucess -nss/tst-nss-files-hosts-long - -# The test case fails due to OBS machine restrictions which can be passed locally. -elf/tst-debug1 - -# This test case often fails in CI which is the high-pressure environment. -# No better solution is available. This test case is shielded. -rt/tst-cpuclock2 -- Gitee From c06b87ef7b74954d8fc0e29b214f64fc5c8b5952 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Wed, 2 Mar 2022 15:22:56 +0800 Subject: [PATCH 63/70] x86: strncmp-avx2-rtm and wcsncmp-avx2-rtm fallback on non-rtm variants when avoiding overflow. [BZ #28896] --- glibc.spec | 9 +- ...-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch | 132 ++++++++++++++++ ...E-to-make-it-a-string-in-tst-strncmp.patch | 37 +++++ ...RTM-in-the-wcsncmp-overflow-case-BZ-.patch | 147 ++++++++++++++++++ 4 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch create mode 100644 x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch create mode 100644 x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch diff --git a/glibc.spec b/glibc.spec index a76444c..c12d667 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 63 +Release: 64 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -197,6 +197,9 @@ Patch111: rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch Patch112: rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch Patch113: rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch Patch114: rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch +Patch115: x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch +Patch116: x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch +Patch117: x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1285,6 +1288,10 @@ fi %endif %changelog +* Wed Mar 2 2022 Qingqing Li - 2.34-64 +- x86: strncmp-avx2-rtm and wcsncmp-avx2-rtm fallback on + non-rtm variants when avoiding overflow. [BZ #28896] + * Tue Mar 1 2022 Yang Yanchao - 2.34-63 - Merge testsuite_whitelist.aarch64 and testsuite_whitelist.x86_64 to testsuite_whitelist. diff --git a/x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch b/x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch new file mode 100644 index 0000000..6bfbc68 --- /dev/null +++ b/x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch @@ -0,0 +1,132 @@ +From 38e0d2479413ccdbc02b4c9e9e246eca31e956c9 Mon Sep 17 00:00:00 2001 +From: Noah Goldstein +Date: Tue, 15 Feb 2022 08:18:15 -0600 +Subject: [PATCH] x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ + #28896] + +In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would +call strcmp-avx2 and wcscmp-avx2 respectively. This would have +not checks around vzeroupper and would trigger spurious +aborts. This commit fixes that. + +test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on +AVX2 machines with and without RTM. + +Co-authored-by: H.J. Lu + +(cherry picked from commit c6272098323153db373f2986c67786ea8c85f1cf) +--- + sysdeps/x86/Makefile | 2 +- + sysdeps/x86/tst-strncmp-rtm.c | 17 ++++++++++++++++- + sysdeps/x86_64/multiarch/strcmp-avx2.S | 2 +- + sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S | 1 + + sysdeps/x86_64/multiarch/strncmp-avx2.S | 1 + + sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S | 2 +- + sysdeps/x86_64/multiarch/wcsncmp-avx2.S | 2 +- + 7 files changed, 22 insertions(+), 5 deletions(-) + +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index 5ee06f9473..6c3e08a3d7 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -104,7 +104,7 @@ CFLAGS-tst-memset-rtm.c += -mrtm + CFLAGS-tst-strchr-rtm.c += -mrtm + CFLAGS-tst-strcpy-rtm.c += -mrtm + CFLAGS-tst-strlen-rtm.c += -mrtm +-CFLAGS-tst-strncmp-rtm.c += -mrtm ++CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error + CFLAGS-tst-strrchr-rtm.c += -mrtm + endif + +diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c +index 236ad951b5..4d0004b58a 100644 +--- a/sysdeps/x86/tst-strncmp-rtm.c ++++ b/sysdeps/x86/tst-strncmp-rtm.c +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + + #define LOOP 3000 +@@ -45,8 +46,22 @@ function (void) + return 1; + } + ++__attribute__ ((noinline, noclone)) ++static int ++function_overflow (void) ++{ ++ if (strncmp (string1, string2, SIZE_MAX) == 0) ++ return 0; ++ else ++ return 1; ++} ++ + static int + do_test (void) + { +- return do_test_1 ("strncmp", LOOP, prepare, function); ++ int status = do_test_1 ("strncmp", LOOP, prepare, function); ++ if (status != EXIT_SUCCESS) ++ return status; ++ status = do_test_1 ("strncmp", LOOP, prepare, function_overflow); ++ return status; + } +diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S +index 3dfcb1bf80..fa70c994fc 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S +@@ -95,7 +95,7 @@ ENTRY (STRCMP) + length to bound a valid memory region. In these cases just use + 'wcscmp'. */ + shrq $56, %rcx +- jnz __wcscmp_avx2 ++ jnz OVERFLOW_STRCMP + # endif + /* Convert units: from wide to byte char. */ + shl $2, %RDX_LP +diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S +index 37d1224bb9..68bad365ba 100644 +--- a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S ++++ b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S +@@ -1,3 +1,4 @@ + #define STRCMP __strncmp_avx2_rtm + #define USE_AS_STRNCMP 1 ++#define OVERFLOW_STRCMP __strcmp_avx2_rtm + #include "strcmp-avx2-rtm.S" +diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2.S b/sysdeps/x86_64/multiarch/strncmp-avx2.S +index 1678bcc235..f138e9f1fd 100644 +--- a/sysdeps/x86_64/multiarch/strncmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/strncmp-avx2.S +@@ -1,3 +1,4 @@ + #define STRCMP __strncmp_avx2 + #define USE_AS_STRNCMP 1 ++#define OVERFLOW_STRCMP __strcmp_avx2 + #include "strcmp-avx2.S" +diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S +index 4e88c70cc6..f467582cbe 100644 +--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S ++++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S +@@ -1,5 +1,5 @@ + #define STRCMP __wcsncmp_avx2_rtm + #define USE_AS_STRNCMP 1 + #define USE_AS_WCSCMP 1 +- ++#define OVERFLOW_STRCMP __wcscmp_avx2_rtm + #include "strcmp-avx2-rtm.S" +diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S +index 4fa1de4d3f..e9ede522b8 100644 +--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S +@@ -1,5 +1,5 @@ + #define STRCMP __wcsncmp_avx2 + #define USE_AS_STRNCMP 1 + #define USE_AS_WCSCMP 1 +- ++#define OVERFLOW_STRCMP __wcscmp_avx2 + #include "strcmp-avx2.S" +-- +2.27.0 + diff --git a/x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch b/x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch new file mode 100644 index 0000000..2b231d1 --- /dev/null +++ b/x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch @@ -0,0 +1,37 @@ +From 15b00d2af0e56dcc8c244a36d6872d301b0c7185 Mon Sep 17 00:00:00 2001 +From: Noah Goldstein +Date: Fri, 18 Feb 2022 17:00:25 -0600 +Subject: [PATCH] x86: Fix TEST_NAME to make it a string in tst-strncmp-rtm.c + +Previously TEST_NAME was passing a function pointer. This didn't fail +because of the -Wno-error flag (to allow for overflow sizes passed +to strncmp/wcsncmp) + +Reviewed-by: H.J. Lu +(cherry picked from commit b98d0bbf747f39770e0caba7e984ce9f8f900330) +--- + sysdeps/x86/tst-strncmp-rtm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c +index 4e9f094f39..aef9866cf2 100644 +--- a/sysdeps/x86/tst-strncmp-rtm.c ++++ b/sysdeps/x86/tst-strncmp-rtm.c +@@ -23,12 +23,12 @@ + # define CHAR wchar_t + # define MEMSET wmemset + # define STRNCMP wcsncmp +-# define TEST_NAME wcsncmp ++# define TEST_NAME "wcsncmp" + #else /* !WIDE */ + # define CHAR char + # define MEMSET memset + # define STRNCMP strncmp +-# define TEST_NAME strncmp ++# define TEST_NAME "strncmp" + #endif /* !WIDE */ + + +-- +2.27.0 + diff --git a/x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch b/x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch new file mode 100644 index 0000000..6d7469b --- /dev/null +++ b/x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch @@ -0,0 +1,147 @@ +From d093b677c36ef4b360bf30483b68b95d9f0ad1d2 Mon Sep 17 00:00:00 2001 +From: Noah Goldstein +Date: Fri, 18 Feb 2022 14:19:15 -0600 +Subject: [PATCH] x86: Test wcscmp RTM in the wcsncmp overflow case [BZ #28896] + +In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would +call strcmp-avx2 and wcscmp-avx2 respectively. This would have +not checks around vzeroupper and would trigger spurious +aborts. This commit fixes that. + +test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on +AVX2 machines with and without RTM. +Reviewed-by: H.J. Lu + +(cherry picked from commit 7835d611af0854e69a0c71e3806f8fe379282d6f) +--- + sysdeps/x86/Makefile | 5 ++++- + sysdeps/x86/tst-strncmp-rtm.c | 32 +++++++++++++++++++++++--------- + sysdeps/x86/tst-wcsncmp-rtm.c | 21 +++++++++++++++++++++ + 3 files changed, 48 insertions(+), 10 deletions(-) + create mode 100644 sysdeps/x86/tst-wcsncmp-rtm.c + +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index 6c3e08a3d7..d7fe68609f 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -94,7 +94,9 @@ tests += \ + tst-strcpy-rtm \ + tst-strlen-rtm \ + tst-strncmp-rtm \ +- tst-strrchr-rtm ++ tst-strrchr-rtm \ ++ tst-wcsncmp-rtm \ ++# tests + + CFLAGS-tst-memchr-rtm.c += -mrtm + CFLAGS-tst-memcmp-rtm.c += -mrtm +@@ -106,6 +108,7 @@ CFLAGS-tst-strcpy-rtm.c += -mrtm + CFLAGS-tst-strlen-rtm.c += -mrtm + CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error + CFLAGS-tst-strrchr-rtm.c += -mrtm ++CFLAGS-tst-wcsncmp-rtm.c += -mrtm -Wno-error + endif + + ifneq ($(enable-cet),no) +diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c +index 4d0004b58a..4e9f094f39 100644 +--- a/sysdeps/x86/tst-strncmp-rtm.c ++++ b/sysdeps/x86/tst-strncmp-rtm.c +@@ -19,18 +19,32 @@ + #include + #include + ++#ifdef WIDE ++# define CHAR wchar_t ++# define MEMSET wmemset ++# define STRNCMP wcsncmp ++# define TEST_NAME wcsncmp ++#else /* !WIDE */ ++# define CHAR char ++# define MEMSET memset ++# define STRNCMP strncmp ++# define TEST_NAME strncmp ++#endif /* !WIDE */ ++ ++ ++ + #define LOOP 3000 + #define STRING_SIZE 1024 +-char string1[STRING_SIZE]; +-char string2[STRING_SIZE]; ++CHAR string1[STRING_SIZE]; ++CHAR string2[STRING_SIZE]; + + __attribute__ ((noinline, noclone)) + static int + prepare (void) + { +- memset (string1, 'a', STRING_SIZE - 1); +- memset (string2, 'a', STRING_SIZE - 1); +- if (strncmp (string1, string2, STRING_SIZE) == 0) ++ MEMSET (string1, 'a', STRING_SIZE - 1); ++ MEMSET (string2, 'a', STRING_SIZE - 1); ++ if (STRNCMP (string1, string2, STRING_SIZE) == 0) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +@@ -40,7 +54,7 @@ __attribute__ ((noinline, noclone)) + static int + function (void) + { +- if (strncmp (string1, string2, STRING_SIZE) == 0) ++ if (STRNCMP (string1, string2, STRING_SIZE) == 0) + return 0; + else + return 1; +@@ -50,7 +64,7 @@ __attribute__ ((noinline, noclone)) + static int + function_overflow (void) + { +- if (strncmp (string1, string2, SIZE_MAX) == 0) ++ if (STRNCMP (string1, string2, SIZE_MAX) == 0) + return 0; + else + return 1; +@@ -59,9 +73,9 @@ function_overflow (void) + static int + do_test (void) + { +- int status = do_test_1 ("strncmp", LOOP, prepare, function); ++ int status = do_test_1 (TEST_NAME, LOOP, prepare, function); + if (status != EXIT_SUCCESS) + return status; +- status = do_test_1 ("strncmp", LOOP, prepare, function_overflow); ++ status = do_test_1 (TEST_NAME, LOOP, prepare, function_overflow); + return status; + } +diff --git a/sysdeps/x86/tst-wcsncmp-rtm.c b/sysdeps/x86/tst-wcsncmp-rtm.c +new file mode 100644 +index 0000000000..bad3b86378 +--- /dev/null ++++ b/sysdeps/x86/tst-wcsncmp-rtm.c +@@ -0,0 +1,21 @@ ++/* Test case for wcsncmp inside a transactionally executing RTM region. ++ Copyright (C) 2022 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 ++ . */ ++ ++#define WIDE 1 ++#include ++#include "tst-strncmp-rtm.c" +-- +2.27.0 + -- Gitee From e3cb56ed65a0407c7450a81c6dc3a60b6fcf8907 Mon Sep 17 00:00:00 2001 From: liqingqing_1229 Date: Thu, 3 Mar 2022 10:26:53 +0800 Subject: [PATCH 64/70] add chrpath to BuildRequires to make 'remove shared library's RPATH/RUNPATH' to take effect --- glibc.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/glibc.spec b/glibc.spec index c12d667..035acb4 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 64 +Release: 65 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -224,7 +224,7 @@ Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) BuildRequires: audit-libs-devel >= 1.1.3, sed >= 3.95, libcap-devel, gettext BuildRequires: procps-ng, util-linux, gawk, systemtap-sdt-devel, systemd, python3 BuildRequires: make >= 4.0, bison >= 2.7, binutils >= 2.30-17, gcc >= 7.2.1-6 -BuildRequires: m4 gcc_secure +BuildRequires: m4 gcc_secure chrpath %if %{without bootstrap} BuildRequires: gd-devel libpng-devel zlib-devel @@ -1288,6 +1288,10 @@ fi %endif %changelog +* Thu Mar 3 2022 Qingqing Li - 2.34-65 +- add chrpath to BuildRequires to make + 'remove shared library's RPATH/RUNPATH' to take effect + * Wed Mar 2 2022 Qingqing Li - 2.34-64 - x86: strncmp-avx2-rtm and wcsncmp-avx2-rtm fallback on non-rtm variants when avoiding overflow. [BZ #28896] -- Gitee From 32473005217f961a244180b766da64d3bf4972c2 Mon Sep 17 00:00:00 2001 From: Yunfeng Ye Date: Thu, 3 Mar 2022 04:32:31 -0500 Subject: [PATCH 65/70] glibc: Add PTRACE_GET_RSEQ_CONFIGURATION Linux 5.13 adds a PTRACE_GET_RSEQ_CONFIGURATION constant, with an associated ptrace_rseq_configuration structure. Add this constant to the various sys/ptrace.h headers in glibc, with the structure in bits/ptrace-shared.h (named struct __ptrace_rseq_configuration in glibc, as with other such structures). --- ...SEQ_CONFIGURATION-from-Linux-5.13-to.patch | 216 ++++++++++++++++++ glibc.spec | 6 +- 2 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch diff --git a/Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch b/Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch new file mode 100644 index 0000000..a11a56e --- /dev/null +++ b/Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch @@ -0,0 +1,216 @@ +From 98149b16d645e9644a8e9b3d1f4b7932b9b193c5 Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Mon, 9 Aug 2021 16:51:38 +0000 +Subject: [PATCH] Add PTRACE_GET_RSEQ_CONFIGURATION from Linux 5.13 to + sys/ptrace.h + +Linux 5.13 adds a PTRACE_GET_RSEQ_CONFIGURATION constant, with an +associated ptrace_rseq_configuration structure. + +Add this constant to the various sys/ptrace.h headers in glibc, with +the structure in bits/ptrace-shared.h (named struct +__ptrace_rseq_configuration in glibc, as with other such structures). + +Tested for x86_64, and with build-many-glibcs.py. + +--- + sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h | 7 ++++++- + sysdeps/unix/sysv/linux/arm/sys/ptrace.h | 6 +++++- + sysdeps/unix/sysv/linux/bits/ptrace-shared.h | 10 ++++++++++ + sysdeps/unix/sysv/linux/ia64/sys/ptrace.h | 6 +++++- + sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h | 7 ++++++- + sysdeps/unix/sysv/linux/s390/sys/ptrace.h | 5 +++++ + sysdeps/unix/sysv/linux/sparc/sys/ptrace.h | 6 +++++- + sysdeps/unix/sysv/linux/sys/ptrace.h | 6 +++++- + sysdeps/unix/sysv/linux/x86/sys/ptrace.h | 6 +++++- + 9 files changed, 52 insertions(+), 7 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h +index af8193cbe7b2..1fae1dce9c6a 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h +@@ -58,6 +58,7 @@ __BEGIN_DECLS + #undef PTRACE_SECCOMP_GET_FILTER + #undef PTRACE_SECCOMP_GET_METADATA + #undef PTRACE_GET_SYSCALL_INFO ++#undef PTRACE_GET_RSEQ_CONFIGURATION + + /* Type of the REQUEST argument to `ptrace.' */ + enum __ptrace_request +@@ -190,8 +191,12 @@ enum __ptrace_request + #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA + + /* Get information about system call. */ +- PTRACE_GET_SYSCALL_INFO = 0x420e ++ PTRACE_GET_SYSCALL_INFO = 0x420e, + #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO ++ ++ /* Get rseq configuration information. */ ++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f ++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION + }; + + +diff --git a/sysdeps/unix/sysv/linux/arm/sys/ptrace.h b/sysdeps/unix/sysv/linux/arm/sys/ptrace.h +index cdb1f159a7c1..2e3843664855 100644 +--- a/sysdeps/unix/sysv/linux/arm/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/arm/sys/ptrace.h +@@ -200,8 +200,12 @@ enum __ptrace_request + #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA + + /* Get information about system call. */ +- PTRACE_GET_SYSCALL_INFO = 0x420e ++ PTRACE_GET_SYSCALL_INFO = 0x420e, + #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO ++ ++ /* Get rseq configuration information. */ ++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f ++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION + }; + + +diff --git a/sysdeps/unix/sysv/linux/bits/ptrace-shared.h b/sysdeps/unix/sysv/linux/bits/ptrace-shared.h +index 7d40634da55e..7e95ca7082e9 100644 +--- a/sysdeps/unix/sysv/linux/bits/ptrace-shared.h ++++ b/sysdeps/unix/sysv/linux/bits/ptrace-shared.h +@@ -120,6 +120,16 @@ struct __ptrace_syscall_info + }; + }; + ++/* Results of PTRACE_GET_RSEQ_CONFIGURATION. */ ++struct __ptrace_rseq_configuration ++{ ++ __uint64_t rseq_abi_pointer; ++ __uint32_t rseq_abi_size; ++ __uint32_t signature; ++ __uint32_t flags; ++ __uint32_t pad; ++}; ++ + /* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be +diff --git a/sysdeps/unix/sysv/linux/ia64/sys/ptrace.h b/sysdeps/unix/sysv/linux/ia64/sys/ptrace.h +index bea975bb9e3d..536a0cafbd1b 100644 +--- a/sysdeps/unix/sysv/linux/ia64/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/ia64/sys/ptrace.h +@@ -153,8 +153,12 @@ enum __ptrace_request + #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA + + /* Get information about system call. */ +- PTRACE_GET_SYSCALL_INFO = 0x420e ++ PTRACE_GET_SYSCALL_INFO = 0x420e, + #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO ++ ++ /* Get rseq configuration information. */ ++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f ++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION + }; + + +diff --git a/sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h b/sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h +index 032c91e81791..fb599af6da64 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h +@@ -36,6 +36,7 @@ __BEGIN_DECLS + # undef PTRACE_GETREGS + # undef PTRACE_GETREGS64 + # undef PTRACE_GETREGSET ++# undef PTRACE_GET_RSEQ_CONFIGURATION + # undef PTRACE_GETSIGINFO + # undef PTRACE_GETSIGMASK + # undef PTRACE_GET_SYSCALL_INFO +@@ -260,8 +261,12 @@ enum __ptrace_request + #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA + + /* Get information about system call. */ +- PTRACE_GET_SYSCALL_INFO = 0x420e ++ PTRACE_GET_SYSCALL_INFO = 0x420e, + #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO ++ ++ /* Get rseq configuration information. */ ++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f ++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION + }; + + +diff --git a/sysdeps/unix/sysv/linux/s390/sys/ptrace.h b/sysdeps/unix/sysv/linux/s390/sys/ptrace.h +index 4f3c65726f61..3ddd2e426789 100644 +--- a/sysdeps/unix/sysv/linux/s390/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/s390/sys/ptrace.h +@@ -86,6 +86,7 @@ __BEGIN_DECLS + # undef PTRACE_SYSCALL_INFO_ENTRY + # undef PTRACE_SYSCALL_INFO_EXIT + # undef PTRACE_SYSCALL_INFO_SECCOMP ++# undef PTRACE_GET_RSEQ_CONFIGURATION + #endif + /* Type of the REQUEST argument to `ptrace.' */ + enum __ptrace_request +@@ -217,6 +218,10 @@ enum __ptrace_request + PTRACE_GET_SYSCALL_INFO = 0x420e, + #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO + ++ /* Get rseq configuration information. */ ++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f, ++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION ++ + PTRACE_PEEKUSR_AREA = 0x5000, + #define PTRACE_PEEKUSR_AREA PTRACE_PEEKUSR_AREA + +diff --git a/sysdeps/unix/sysv/linux/sparc/sys/ptrace.h b/sysdeps/unix/sysv/linux/sparc/sys/ptrace.h +index 3f6150028487..773b4379249c 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/sparc/sys/ptrace.h +@@ -221,8 +221,12 @@ enum __ptrace_request + #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA + + /* Get information about system call. */ +- PTRACE_GET_SYSCALL_INFO = 0x420e ++ PTRACE_GET_SYSCALL_INFO = 0x420e, + #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO ++ ++ /* Get rseq configuration information. */ ++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f ++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION + }; + + +diff --git a/sysdeps/unix/sysv/linux/sys/ptrace.h b/sysdeps/unix/sysv/linux/sys/ptrace.h +index dc76e97ea72a..404fc3ddb7b5 100644 +--- a/sysdeps/unix/sysv/linux/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/sys/ptrace.h +@@ -170,8 +170,12 @@ enum __ptrace_request + #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA + + /* Get information about system call. */ +- PTRACE_GET_SYSCALL_INFO = 0x420e ++ PTRACE_GET_SYSCALL_INFO = 0x420e, + #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO ++ ++ /* Get rseq configuration information. */ ++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f ++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION + }; + + +diff --git a/sysdeps/unix/sysv/linux/x86/sys/ptrace.h b/sysdeps/unix/sysv/linux/x86/sys/ptrace.h +index 8501cc22ed7b..7202a09eefd3 100644 +--- a/sysdeps/unix/sysv/linux/x86/sys/ptrace.h ++++ b/sysdeps/unix/sysv/linux/x86/sys/ptrace.h +@@ -190,8 +190,12 @@ enum __ptrace_request + #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA + + /* Get information about system call. */ +- PTRACE_GET_SYSCALL_INFO = 0x420e ++ PTRACE_GET_SYSCALL_INFO = 0x420e, + #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO ++ ++ /* Get rseq configuration information. */ ++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f ++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION + }; + + +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 035acb4..2456ef4 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 65 +Release: 66 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -200,6 +200,7 @@ Patch114: rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch Patch115: x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch Patch116: x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch Patch117: x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch +Patch118: Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1288,6 +1289,9 @@ fi %endif %changelog +* Thu Mar 3 2022 Yunfeng Ye - 2.34-66 +- add PTRACE_GET_RSEQ_CONFIGURATION + * Thu Mar 3 2022 Qingqing Li - 2.34-65 - add chrpath to BuildRequires to make 'remove shared library's RPATH/RUNPATH' to take effect -- Gitee From 2c4eaeba9b98ff746a55da49f1831b82b8f04c78 Mon Sep 17 00:00:00 2001 From: qinyu Date: Thu, 3 Mar 2022 20:24:30 +0800 Subject: [PATCH 66/70] glibc: disable rseq feature by default with tunable disable rseq feature by default with tunable Signed-off-by: qinyu --- glibc.spec | 5 ++++- ...d-glibc.pthread.rseq-tunable-to-control-rseq-.patch | 10 +++++++++- testsuite_whitelist | 4 ++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/glibc.spec b/glibc.spec index 2456ef4..a433944 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 66 +Release: 67 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -1289,6 +1289,9 @@ fi %endif %changelog +* Thu Mar 3 2022 qinyu - 2.34-67 +- disable rseq by default with tunable + * Thu Mar 3 2022 Yunfeng Ye - 2.34-66 - add PTRACE_GET_RSEQ_CONFIGURATION diff --git a/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch b/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch index 6fb0aa6..8e5675d 100644 --- a/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch +++ b/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch @@ -9,6 +9,14 @@ of glibc. Reviewed-by: Szabolcs Nagy Reviewed-by: Siddhesh Poyarekar +----- +change: +Since rseq is a big feature and have changed code behavior quite a lot, +disable rseq by default to reduce potential conflicts. + +sysdeps/nptl/dl-tunables.list: + default: 1 -> default: 0 + --- manual/tunables.texi | 10 +++ nptl/pthread_create.c | 10 ++- @@ -111,7 +119,7 @@ index ac5d0532..d24f4be0 100644 + type: INT_32 + minval: 0 + maxval: 1 -+ default: 1 ++ default: 0 + } } } diff --git a/testsuite_whitelist b/testsuite_whitelist index 024457e..b99f3d5 100644 --- a/testsuite_whitelist +++ b/testsuite_whitelist @@ -123,3 +123,7 @@ elf/tst-debug1:aarch64 # This test case often fails in CI which is the high-pressure environment. # No better solution is available. This test case is shielded. rt/tst-cpuclock2 + +# These testcase fails because rseq is disabled by default +misc/tst-rseq-nptl +misc/tst-rseq -- Gitee From 5793040e7a771cee0eee9774cf76b8b7c6c71e04 Mon Sep 17 00:00:00 2001 From: Lv Ying Date: Tue, 25 Jan 2022 12:23:40 +0000 Subject: [PATCH 67/70] elf: dynamic linker load lib use hugepage This patch provides environment variables HUGEPAGE_PROBE and LD_HUGEPAGE_LIB to enable load shared object use hugepage. Signed-off-by: Lv Ying Reviewed-by: zhoukang --- ...er-load-shared-object-use-hugepage-a.patch | 1179 +++++++++++++++++ ...stcase-for-ld.so-load-shared-object-.patch | 1177 ++++++++++++++++ ...ecial-mmap-for-hugepage-to-get-symbo.patch | 69 + glibc.spec | 8 +- 4 files changed, 2432 insertions(+), 1 deletion(-) create mode 100644 0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch create mode 100644 0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch create mode 100644 0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch diff --git a/0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch b/0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch new file mode 100644 index 0000000..3a561e1 --- /dev/null +++ b/0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch @@ -0,0 +1,1179 @@ +From 28a9a4123b8a7494c0b5e70fd943fa7aa4f64fe8 Mon Sep 17 00:00:00 2001 +From: Lv Ying +Date: Mon, 7 Mar 2022 03:28:33 +0000 +Subject: [PATCH 1/3] elf: dynamic linker load shared object use hugepage as + much as possible + +This patch provides environment variables HUGEPAGE_PROBE and LD_HUGEPAGE_LIB +to enable load shared object use hugepage. + +When load shared object, ld.so first to map text PT_LOAD segment into 2MB +hugepage area. And then, load the neighbor PT_LOAD segment use 2MB hugepage +as much as possible. This means: +* PT_LOAD segment's mapstart_va is 2MB aligned, howerver its maplenth is + less than 2MB, fallback to 4KB page +* PT_LOAD segment's mapstart_va is 2MB aligned, and its maplenth is larger + than 2MB, the first 2MB aligned area use 2MB hugepage, the end area (if it exists) use 4KB area +* PT_LOAD segment's mapstart_va is not 2MB aligned, alignup this address + to 2MB aligned address mapstart_align, if its maplenth is less than + mapstart_align - mapstart_va, or maplenth - (mapstart_align - mapstart_va), fallback to 4KB hugepage +* PT_LOAD segment's mapstart_va is not 2MB aligned, maplenth - (mapstart_align - mapstart_va) + is still larger than 2MB, first map (mapstart_align - mapstart_va) as 4KB page + then map 2MB aligned area as hugepage, the end area (if it exists) use 4KB area +--- + config.h.in | 2 + + configure | 20 ++ + configure.ac | 11 + + elf/Makefile | 8 + + elf/dl-environ.c | 11 + + elf/dl-load.c | 38 +++ + elf/dl-load.h | 16 + + elf/dl-map-segments-hugepage.h | 593 +++++++++++++++++++++++++++++++++ + elf/elf.h | 2 + + elf/hugepageedit.c | 169 ++++++++++ + elf/rtld.c | 64 ++++ + sysdeps/generic/ldsodefs.h | 6 +- + 12 files changed, 939 insertions(+), 1 deletion(-) + create mode 100644 elf/dl-map-segments-hugepage.h + create mode 100644 elf/hugepageedit.c + +diff --git a/config.h.in b/config.h.in +index db6402cd..13101496 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -277,6 +277,8 @@ + /* Define if static PIE is supported. */ + #undef SUPPORT_STATIC_PIE + ++#undef HUGEPAGE_SHARED_LIB ++ + /* Define if static PIE is enabled. */ + #define ENABLE_STATIC_PIE 0 + +diff --git a/configure b/configure +index 7272fbf6..43993923 100755 +--- a/configure ++++ b/configure +@@ -670,6 +670,7 @@ stack_protector + libc_cv_ssp + libc_cv_with_fp + base_machine ++enable_hugepage_shared_library + have_tunables + build_pt_chown + build_nscd +@@ -791,6 +792,7 @@ enable_pt_chown + enable_tunables + enable_mathvec + enable_cet ++enable_hugepage_shared_library + enable_scv + with_cpu + ' +@@ -1464,6 +1466,9 @@ Optional Features: + depends on architecture] + --enable-cet enable Intel Control-flow Enforcement Technology + (CET), x86 only ++ --enable-hugepage-shared-library ++ enable shared library use huge page to decrease TLB ++ miss, x86_64 aarch64 only + --disable-scv syscalls will not use scv instruction, even if the + kernel supports it, powerpc only + +@@ -3830,6 +3835,21 @@ if test "$use_scv" != "no"; then : + + fi + ++# Check whether --enable-hugepage-shared-library was given. ++if test "${enable_hugepage_shared_library+set}" = set; then : ++ enableval=$enable_hugepage_shared_library; enable_hugepage_shared_library=$enableval ++else ++ enable_hugepage_shared_library=no ++fi ++ ++ ++config_vars="$config_vars ++enable-hugepage-shared-library = $enable_hugepage_shared_library" ++if test "$enable_hugepage_shared_library" = yes; then ++ $as_echo "#define HUGEPAGE_SHARED_LIB 1" >>confdefs.h ++ ++fi ++ + # We keep the original values in `$config_*' and never modify them, so we + # can write them unchanged into config.make. Everything else uses + # $machine, $vendor, and $os, and changes them whenever convenient. +diff --git a/configure.ac b/configure.ac +index af47cd51..27a48338 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -478,6 +478,17 @@ AC_ARG_ENABLE([scv], + + AS_IF([[test "$use_scv" != "no"]],[AC_DEFINE(USE_PPC_SCV)]) + ++AC_ARG_ENABLE([hugepage-shared-library], ++ AC_HELP_STRING([--enable-hugepage-shared-library], ++ [enable shared library use huge page to decrease TLB miss, x86_64 aarch64 only]), ++ [enable_hugepage_shared_library=$enableval], ++ [enable_hugepage_shared_library=no]) ++ ++LIBC_CONFIG_VAR([enable-hugepage-shared-library], [$enable_hugepage_shared_library]) ++if test "$enable_hugepage_shared_library" = yes; then ++ AC_DEFINE(HUGEPAGE_SHARED_LIB) ++fi ++ + # We keep the original values in `$config_*' and never modify them, so we + # can write them unchanged into config.make. Everything else uses + # $machine, $vendor, and $os, and changes them whenever convenient. +diff --git a/elf/Makefile b/elf/Makefile +index 48bb4703..1574574d 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -207,6 +207,14 @@ others-extras = $(ldconfig-modules) + endif + endif + ++ifeq (yes,$(enable-hugepage-shared-library)) ++others += hugepageedit ++others-pie += hugepageedit ++install-bin += hugepageedit ++ ++$(objpfx)hugepageedit: $(objpfx)hugepageedit.o ++endif ++ + # To find xmalloc.c and xstrdup.c + vpath %.c ../locale/programs + +diff --git a/elf/dl-environ.c b/elf/dl-environ.c +index 31c1c09f..ac70c9ab 100644 +--- a/elf/dl-environ.c ++++ b/elf/dl-environ.c +@@ -31,6 +31,17 @@ _dl_next_ld_env_entry (char ***position) + + while (*current != NULL) + { ++#ifdef HUGEPAGE_SHARED_LIB ++ #define LEN_HUGEPAGE_PROBE (sizeof("HUGEPAGE_PROBE") - 1) ++ if (memcmp (*current, "HUGEPAGE_PROBE", LEN_HUGEPAGE_PROBE) == 0) ++ { ++ result = *current; ++ ++ /* Save current position for next visit. */ ++ *position = ++current; ++ break; ++ } ++#endif + if (__builtin_expect ((*current)[0] == 'L', 0) + && (*current)[1] == 'D' && (*current)[2] == '_') + { +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 0976977f..57d5754e 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -73,6 +73,9 @@ struct filebuf + #include + #include + #include ++#ifdef HUGEPAGE_SHARED_LIB ++#include ++#endif + + #include + #if BYTE_ORDER == BIG_ENDIAN +@@ -1131,6 +1134,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + size_t nloadcmds = 0; + bool has_holes = false; + bool empty_dynamic = false; ++#ifdef HUGEPAGE_SHARED_LIB ++ bool use_hugepage = false; ++#endif + + /* The struct is initialized to zero so this is not necessary: + l->l_ld = 0; +@@ -1188,6 +1194,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + if (nloadcmds > 1 && c[-1].mapend != c->mapstart) + has_holes = true; + ++#ifdef HUGEPAGE_SHARED_LIB ++ if (ph->p_flags & PF_HUGEPAGE) ++ use_hugepage = true; ++#endif ++ + /* Optimize a common case. */ + #if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7 + c->prot = (PF_TO_PROT +@@ -1278,12 +1289,39 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + /* Length of the sections to be loaded. */ + maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart; + ++#ifdef HUGEPAGE_SHARED_LIB ++#define ERRSTRING_BUF_LEN 1024 ++ int hp_errcode = 0; ++ char hp_buf[ERRSTRING_BUF_LEN]; ++ if ((GLRO(dl_debug_mask) & DL_HUGEPAGE_LIB_LARGE_IN_FLAG) || ++ ((GLRO(dl_debug_mask) & DL_HUGEPAGE_PROBE_FLAG) && use_hugepage)) ++ { ++ errstring = _dl_map_segments_largein (l, fd, header, type, loadcmds, nloadcmds, ++ maplength, has_holes); ++ if (__glibc_unlikely (errstring != NULL)) ++ { ++ hp_errcode = errno; ++ /* __strerror_r will set hp_buf last character '\0', hp_buf will not overflow */ ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf ("_dl_map_segments_largein: %s, %s\n", errstring, ++ hp_errcode ? __strerror_r (hp_errcode, hp_buf, sizeof hp_buf) : ""); ++ goto fallback; ++ } ++ } ++ else ++ { ++ fallback: ++ errstring = _dl_map_segments (l, fd, header, type, loadcmds, nloadcmds, ++ maplength, has_holes, loader); ++ } ++#else + /* Now process the load commands and map segments into memory. + This is responsible for filling in: + l_map_start, l_map_end, l_addr, l_contiguous, l_text_end, l_phdr + */ + errstring = _dl_map_segments (l, fd, header, type, loadcmds, nloadcmds, + maplength, has_holes, loader); ++#endif + if (__glibc_unlikely (errstring != NULL)) + { + /* Mappings can be in an inconsistent state: avoid unmap. */ +diff --git a/elf/dl-load.h b/elf/dl-load.h +index e329d49a..d3f69466 100644 +--- a/elf/dl-load.h ++++ b/elf/dl-load.h +@@ -131,5 +131,21 @@ static const char *_dl_map_segments (struct link_map *l, int fd, + #define DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL \ + N_("cannot map zero-fill pages") + ++#ifdef HUGEPAGE_SHARED_LIB ++#define DL_MAP_SEGMENTS_ERROR_TYPE \ ++ N_("cannot map Non shared object file in hugepage") ++#define DL_MAP_SEGMENTS_ERROR_READ_SEGMENT \ ++ N_("failed to read shared object file") ++#define DL_MAP_SEGMENTS_ERROR_ARRANGE \ ++ N_("shared object's PT_LOAD segment in wrong arrange") ++#define DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL \ ++ N_("failed to mmap shared object's hole part of PT_LOAD") ++#define DL_MAP_RESERVED_HUGEPAGE_AREA_ERROR \ ++ N_("failed to map reserved 2MB contiguous hugepage va space") ++#define DL_FIND_EXEC_SEGMENT_ERROR \ ++ N_("fail to find exec prot segment") ++#define DL_MAP_SEGMENT_ERROR_EXTRA_SIZE \ ++ N_("wrong segment extra size") ++#endif + + #endif /* dl-load.h */ +diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h +new file mode 100644 +index 00000000..cd7b6d79 +--- /dev/null ++++ b/elf/dl-map-segments-hugepage.h +@@ -0,0 +1,593 @@ ++/* Map a shared object's segments into hugepage. Generic version. ++ Copyright (C) 1995-2021 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 ++ ++#define SHFIT_2MB 21 ++#define SIZE_2MB 0x200000 ++#define MASK_2MB 0x1FFFFF ++#define THRESHOLD 16 ++ ++/* ++ * Find the first PT_LOAD segment with execute permission ++ */ ++static __always_inline const struct loadcmd * ++_find_exec_segment(const struct loadcmd loadcmds[], size_t nloadcmds) ++{ ++ const struct loadcmd *c = loadcmds; ++ ++ while (c < &loadcmds[nloadcmds]) ++ { ++ if (c->prot & PROT_EXEC) ++ return c; ++ c++; ++ } ++ return NULL; ++} ++ ++static __always_inline void * ++__mmap_reserved_area(const struct loadcmd loadcmds[], size_t nloadcmds, ++ size_t *maparealen) ++{ ++ const struct loadcmd * c = loadcmds; ++ *maparealen = 0; ++ ++ while (c < &loadcmds[nloadcmds]) ++ { ++ *maparealen += ALIGN_UP((c->mapend > c->allocend ? c->mapend : c->allocend), SIZE_2MB) - ++ ALIGN_DOWN(c->mapstart, SIZE_2MB); ++ c++; ++ } ++ ++ /* ++ * Get 2MB aligned contiguous va space ++ * This va space can not be munmap in case of multi thread dlopen concurrently ++ */ ++ void *map_area_start = __mmap(0, *maparealen, PROT_NONE, ++ MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT), -1, 0); ++ if (__glibc_unlikely (map_area_start == MAP_FAILED)) ++ return MAP_FAILED; ++ ++ /* ++ * Remap 2MB aligned contiguous va space into 4KB contiguous va space ++ * to avoid the tedious work of splitting hugepage into 4KB page ++ */ ++ if (__glibc_unlikely(__mmap(map_area_start, *maparealen, PROT_NONE, ++ MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) ++ == MAP_FAILED)) ++ { ++ goto unmap_reserved_area; ++ } ++ return map_area_start; ++ ++unmap_reserved_area: ++ __munmap(map_area_start, *maparealen); ++ return MAP_FAILED; ++} ++ ++static __always_inline size_t ++_get_relro_len(struct link_map *l, const struct loadcmd *c) ++{ ++ size_t relro_len = 0; ++ if (c->mapstart == ALIGN_DOWN (l->l_relro_addr, GLRO(dl_pagesize))) ++ { ++ relro_len = ALIGN_DOWN(l->l_relro_addr + l->l_relro_size, GLRO(dl_pagesize)) - ++ ALIGN_DOWN(l->l_relro_addr, GLRO(dl_pagesize)); ++ } ++ return relro_len; ++} ++ ++/* ++ * the alignment stands for the size of page which is to be cleared to zero ++ */ ++static __always_inline const char * ++_zero_tail_page(const struct loadcmd *c, ElfW(Addr) zero, ElfW(Addr) zeropage, ++ size_t alignment) ++{ ++ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0)) ++ { ++ /* Dag nab it. */ ++ if (__mprotect ((caddr_t) ALIGN_DOWN(zero, alignment), alignment, ++ c->prot|PROT_WRITE) < 0) ++ return DL_MAP_SEGMENTS_ERROR_MPROTECT; ++ } ++ memset ((void *) zero, '\0', zeropage - zero); ++ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0)) ++ __mprotect ((caddr_t) ALIGN_DOWN(zero, alignment), alignment, c->prot); ++ return NULL; ++} ++ ++static __always_inline const char * ++_mmap_remain_zero_page(ElfW(Addr) zeropage, ElfW(Addr) zeroend, int prot) ++{ ++ ElfW(Addr) hp_start = ALIGN_UP(zeropage, SIZE_2MB); ++ size_t len = 0, mod = 0; ++ caddr_t mapat; ++ ++ if (zeroend > hp_start && zeroend - hp_start >= SIZE_2MB) ++ { ++ len = zeroend - hp_start; ++ mod = len % SIZE_2MB; ++ } ++ else ++ hp_start = 0; ++ ++ if (hp_start == 0) ++ { ++ mapat = __mmap((caddr_t) zeropage, zeroend - zeropage, prot, ++ MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0); ++ if (__glibc_unlikely (mapat == MAP_FAILED)) ++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; ++ return NULL; ++ } ++ ++ if (hp_start - zeropage > 0) ++ { ++ mapat = __mmap((caddr_t) zeropage, hp_start - zeropage, ++ prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0); ++ if (__glibc_unlikely (mapat == MAP_FAILED)) ++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; ++ } ++ ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t\t\t=> mmap anonymous hugepage: [%lx-%lx)\n", hp_start, hp_start + len - mod); ++ mapat = __mmap((caddr_t) hp_start, len - mod, prot, ++ MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT), ++ -1, 0); ++ if (__glibc_unlikely (mapat == MAP_FAILED)) ++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; ++ ++ if (mod > 0) ++ { ++ mapat =__mmap((caddr_t)(hp_start + len - mod), mod, prot, ++ MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0); ++ if (__glibc_unlikely (mapat == MAP_FAILED)) ++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; ++ } ++ ++ return NULL; ++} ++ ++/* ++ * memsz_len records the remain memsiz part ++ */ ++static __always_inline const char * ++_mmap_segment_memsz(struct link_map *l, const struct loadcmd * c, ++ ElfW(Addr) mapstart, size_t extra_len, size_t *memsz_len) ++{ ++ const char * errstring = NULL; ++ ++ /* Extra zero pages should appear at the end of this segment, ++ after the data mapped from the file. */ ++ ElfW(Addr) zero, zeroend, zeropage; ++ ++ zero = mapstart + c->dataend - c->mapstart; ++ zeroend = mapstart + c->allocend - c->mapstart; ++ zeropage = ALIGN_UP(zero, GLRO(dl_pagesize)); ++ size_t alignment = GLRO(dl_pagesize); ++ *memsz_len = 0; ++ ++ /* ++ * no matter what the extra space consists of: ++ * 1. all the extra space is initialized data area (MemSiz > FileSiz) ++ * 2. initialized data area and hole ++ * 3. all the extra space is hole (MemSiz == FileSiz) ++ * ++ * the extra space just needs to be set zero, for the initialized data area, it's ++ * initialized to zero; for the hole area, it's initialized to invalid instruction ++ */ ++ if (extra_len > 0) ++ { ++ if (__glibc_unlikely(zeropage == ALIGN_UP(zero, SIZE_2MB) || ++ zeropage + extra_len != ALIGN_UP(zero, SIZE_2MB))) ++ return DL_MAP_SEGMENT_ERROR_EXTRA_SIZE; ++ ++ zeropage = ALIGN_UP(zero, SIZE_2MB); ++ alignment = SIZE_2MB; ++ } ++ else ++ { ++ /* ++ * extra_len = 0, _mmap_segment_filesz just mmap segment's FileSiz part, ++ * here, it needs to zero tail page [FileSiz end, tail page end) part ++ */ ++ if (c->allocend <= c->dataend) ++ return NULL; ++ ++ if (ALIGN_UP(zero, GLRO(dl_pagesize)) == ALIGN_UP(zero, SIZE_2MB) && ++ (zeropage - (mapstart + _get_relro_len(l, c)) >= SIZE_2MB)) ++ { ++ alignment = SIZE_2MB; ++ } ++ ++ if (zeroend < zeropage) ++ zeropage = zeroend; ++ } ++ ++ if (zeropage > zero) ++ { ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t\tzero tail page [%lx-%lx) which contains hole area length: 0x%lx\n", ++ zero, zeropage, zeropage > ALIGN_UP(zero, GLRO(dl_pagesize)) ? ++ zeropage - ALIGN_UP(zero, GLRO(dl_pagesize)) : 0); ++ errstring = _zero_tail_page(c, zero, zeropage, alignment); ++ if (errstring != NULL) ++ return errstring; ++ } ++ ++ if (zeroend > zeropage) ++ { ++ *memsz_len = ALIGN_UP(zeroend, GLRO(dl_pagesize)) - zeropage; ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t\tzero remain page [%lx-%lx)\n", zeropage, zeroend); ++ errstring = _mmap_remain_zero_page(zeropage, zeroend, c->prot); ++ } ++ return errstring; ++} ++ ++/* ++ * mmap as fixed addr, if the middle part is 2MB aligned, ++ * this part should be mmaped in 2MB aligned, else in 4KB aligned ++ * 2MB hugepage area should be set with correct permissions, no need to remap ++ */ ++static __always_inline const char * ++_mmap_segment_filesz(struct link_map *l, const struct loadcmd *c, ElfW(Addr) mapstart, ++ size_t extra_len, int fd) ++{ ++ void *map_addr = 0; ++ ++ size_t relro_len = _get_relro_len(l, c); ++ if (relro_len > 0) ++ { ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t\tmmap relro: [%lx-%lx)\n", mapstart, mapstart + relro_len); ++ /* ++ * relro part must be mapped as normal page size to avoid ++ * _dl_protect_relro failure ++ */ ++ map_addr = __mmap((void *)mapstart, relro_len, c->prot, ++ MAP_PRIVATE|MAP_FIXED|MAP_FILE, ++ fd, c->mapoff); ++ if (__glibc_unlikely (map_addr == MAP_FAILED)) ++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; ++ ++ mapstart += relro_len; ++ } ++ ++ size_t prev_map_len = ALIGN_UP(mapstart, SIZE_2MB) - mapstart; ++ size_t len = (c->mapend + extra_len) - (c->mapstart + relro_len); ++ if (len <= prev_map_len || len - prev_map_len < SIZE_2MB) ++ { ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t\tmmap all: [%lx-%lx), which includes prev_map_len(0x%lx)\n", ++ mapstart, mapstart + len, prev_map_len); ++ mapstart = (ElfW(Addr))__mmap((void *)mapstart, len, c->prot, ++ MAP_PRIVATE|MAP_FIXED|MAP_FILE, ++ fd, c->mapoff + relro_len); ++ if (__glibc_unlikely ((void *)mapstart == MAP_FAILED)) ++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; ++ return NULL; ++ } ++ ++ if (prev_map_len > 0) ++ { ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t\tmmap prev_map_len: [%lx-%lx)\n", ++ mapstart, mapstart + prev_map_len); ++ mapstart = (ElfW(Addr))__mmap((void *)mapstart, prev_map_len, c->prot, ++ MAP_PRIVATE|MAP_FIXED|MAP_FILE, ++ fd, c->mapoff + relro_len); ++ if (__glibc_unlikely ((void *)mapstart == MAP_FAILED)) ++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; ++ ++ map_addr = map_addr == 0 ? (void *)mapstart : map_addr; ++ mapstart += prev_map_len; ++ len -= prev_map_len; ++ } ++ ++ size_t mod = len % SIZE_2MB; ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t\tmmap hugepage: [%lx-%lx)\n", mapstart, mapstart + len - mod); ++ mapstart = (ElfW(Addr))__mmap((void *)mapstart, len - mod, c->prot, ++ MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT), ++ -1, 0); ++ if (__glibc_unlikely ((void *)mapstart == MAP_FAILED)) ++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; ++ ++ if ((c->prot & PROT_WRITE) == 0 && __mprotect((void *)mapstart, len - mod, c->prot | PROT_WRITE) < 0) ++ { ++ return DL_MAP_SEGMENTS_ERROR_MPROTECT; ++ } ++ ++ /* Read the segment contents from the file. */ ++ size_t file_len = (size_t)(c->dataend - c->mapstart) <= prev_map_len + relro_len ? 0 : ++ (size_t)(c->dataend - c->mapstart) - prev_map_len - relro_len; ++ if (file_len > 0) ++ { ++ lseek(fd, c->mapoff + relro_len + prev_map_len, SEEK_SET); ++ if ( __read(fd, (void *)mapstart, file_len < len - mod ? file_len : len - mod) < 0) ++ return DL_MAP_SEGMENTS_ERROR_READ_SEGMENT; ++ } ++ ++ if ((c->prot & PROT_WRITE) == 0 && __mprotect((void *)mapstart, len - mod, c->prot) < 0) ++ { ++ return DL_MAP_SEGMENTS_ERROR_MPROTECT; ++ } ++ ++ map_addr = map_addr == 0 ? (void *)mapstart : map_addr; ++ mapstart += len - mod; ++ ++ if (__glibc_unlikely (extra_len > 0 && mod > 0)) ++ return DL_MAP_SEGMENT_ERROR_EXTRA_SIZE; ++ ++ if (mod > 0 && __glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t\tmmap tail part: [%lx-%lx)\n", mapstart, mapstart + mod); ++ if (mod > 0 && __mmap((void *)mapstart, mod, c->prot, ++ MAP_PRIVATE|MAP_FIXED|MAP_FILE, ++ fd, c->mapoff + relro_len + prev_map_len + len - mod) ++ == MAP_FAILED) ++ { ++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; ++ } ++ return NULL; ++} ++ ++/* ++ * mmap segment filesz tail part only covers the very first part of hugepage, ++ * if the size of this tail part reach the threshold, map the tail part in hugepage ++ * ++ * The tail part must be calculated by mapend, because this is file mmaping, ++ * if tail part is calculated by allocend, it will mmap invalid data in file ++ * s: mapstart mp: mapend ac: allocend ++ * 1. [s, mp) can not cover the tail hugepage start, mp, s, ac are all in same hugepage, no extra space ++ * s mp ac ++ * | | | ++ * |--------|--------| ++ * ++ * 2. [s, mp) can not cover the tail hugepage start, ac is in the behind hugepage, no extra space ++ * s mp ac ++ * | | | ++ * |--------|--------|--------| ++ * ++ * 3. [s, mp) covers the tail hugepage start, mp and the ac in the same hugepage, ++ * if (ac - ALIGN_DOWN(mp, SIZE_2MB) < threshold, no extra space; else extra space ++ * [mp, ALIGN_UP(mp, SIZE_2MB) which contains initialized data area and hole ++ * if ac == mp, the extra space only contains hole ++ * s1 s2 mp ac ++ * | | | | ++ * |--------|--------|--------| ++ * ++ * 4. [s, mp) covers the tail hugepage start, ac is in the behind hugepage, ++ * the extra space is [mp, ALIGN_UP(mp, SIZE_2MB) which only contains initialized data area ++ * s1 s2 mp ac ++ * | | | | ++ * |--------|--------|--------|--------|--------| ++ * ++ * 5. if mp is 2MB aligned, no matter [s, mp) covers the tail hugepage start or not, ++ * no extra area ++ * s1 s2 s3 mp ac ++ * | | | | | ++ * |--------|--------|--------|--------|--------| ++ * ++ * there are a few points to note: ++ * 1. the extra part shold not overlap with the next segment ++ * 2. PT_LOAD segment which contains relro section should update mapstart ++ */ ++static __always_inline size_t ++_extra_mmap(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmds, ++ const struct loadcmd *c, ElfW(Addr) mapstart) ++{ ++ ElfW(Addr) mapend = mapstart + (c->mapend - c->mapstart); ++ ElfW(Addr) hugepage = ALIGN_DOWN(mapend, SIZE_2MB); ++ size_t relro_len = _get_relro_len(l, c); ++ mapstart += relro_len; ++ ++ /* ++ * 1. mapend is 2MB aligned ++ * 2. [mapstart, mapend) does not cover the tail hugepage start ++ */ ++ if (mapend == ALIGN_UP(mapend, SIZE_2MB) || mapstart > hugepage) ++ return 0; ++ ++ /* the initialized data area end in the tail hugepage */ ++ ElfW(Addr) end = (mapstart - relro_len) + ALIGN_UP(c->allocend - c->mapstart, GLRO(dl_pagesize)) >= ++ ALIGN_UP(mapend, SIZE_2MB) ? ALIGN_UP(mapend, SIZE_2MB) : ++ (mapstart - relro_len) + ALIGN_UP(c->allocend - c->mapstart, GLRO(dl_pagesize)); ++ ++ size_t extra_len = ALIGN_UP(mapend, SIZE_2MB) - mapend; ++ if ((end - hugepage < THRESHOLD * GLRO(dl_pagesize)) || ((c < loadcmds + (nloadcmds - 1)) && ++ (ALIGN_UP(mapend, SIZE_2MB) > (mapstart - relro_len) + c[1].mapstart - c->mapstart))) ++ { ++ extra_len = 0; ++ } ++ ++ return extra_len; ++} ++ ++/* ++ * PT_LOAD segment is described by p_filesz and p_memsz. ++ * The bytes from the file are mapped to the beginning of the memory segment. ++ * If the segment’s memory size (p_memsz) is larger than the file size (p_filesz), ++ * the extra bytes are defined to hold the value 0 and to follow the segment’s ++ * initialized area ++ */ ++static __always_inline const char * ++_mmap_segment(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmds, ++ const struct loadcmd *c, ElfW(Addr) mapstart, int fd, size_t *mapseglen) ++{ ++ const char * errstring = NULL; ++ size_t extra_len = _extra_mmap(l, loadcmds, nloadcmds, c, mapstart); ++ size_t memsz_len = 0; ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t%s(0x%lx): extra_len = 0x%lx\n\t{\n", __func__, ++ (unsigned long)c, extra_len); ++ ++ errstring = _mmap_segment_filesz(l, c, mapstart, extra_len, fd); ++ if (__glibc_unlikely (errstring != NULL)) ++ return errstring; ++ errstring = _mmap_segment_memsz(l, c, mapstart, extra_len, &memsz_len); ++ if (__glibc_unlikely (errstring != NULL)) ++ return errstring; ++ ++ *mapseglen = c->mapend - c->mapstart + extra_len + memsz_len; ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\t} => mapseglen = 0x%lx, memsz_len = 0x%lx\n", *mapseglen, memsz_len); ++ return NULL; ++} ++ ++static __always_inline void * ++_mmap_hole(const struct loadcmd *current, const struct loadcmd *next, ++ ElfW(Addr) mapstart, size_t mapseglen, int fd) ++{ ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("\tmmap hole area:[%lx-%lx)\n", mapstart + mapseglen, ++ mapstart + (next->mapstart - current->mapstart)); ++ return __mmap((void *)(mapstart + mapseglen), ++ next->mapstart - (current->mapstart + mapseglen), ++ PROT_NONE, MAP_FILE|MAP_PRIVATE|MAP_FIXED, ++ fd, current->mapoff + mapseglen); ++} ++ ++static __always_inline const char * ++_dl_map_segments_largein (struct link_map *l, int fd, ++ const ElfW(Ehdr) *header, int type, ++ const struct loadcmd loadcmds[], size_t nloadcmds, ++ const size_t maplength, bool has_holes) ++{ ++ if (__glibc_unlikely (type != ET_DYN)) ++ return DL_MAP_SEGMENTS_ERROR_TYPE; ++ ++ const char *errstring = NULL; ++ const struct loadcmd *text = _find_exec_segment(loadcmds, nloadcmds); ++ if (__glibc_unlikely (text == NULL)) ++ return DL_FIND_EXEC_SEGMENT_ERROR; ++ ++ size_t maparealen; ++ void *map_area_start = __mmap_reserved_area(loadcmds, nloadcmds, &maparealen); ++ if (__glibc_unlikely (map_area_start == MAP_FAILED)) ++ return DL_MAP_RESERVED_HUGEPAGE_AREA_ERROR; ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("reserved area:[%lx-%lx)\n", ++ (unsigned long)map_area_start, (unsigned long)map_area_start + maparealen); ++ ++ /* First to mmap text segment */ ++ const struct loadcmd * c = loadcmds; ++ ElfW(Addr) text_addr = ALIGN_UP((ElfW(Addr))map_area_start + (text->mapstart - c->mapstart), SIZE_2MB); ++ size_t mapseglen; ++ errstring = _mmap_segment(l, loadcmds, nloadcmds, text, text_addr, fd, &mapseglen); ++ if (__glibc_unlikely(errstring != NULL)) ++ goto unmap_reserved_area; ++ ++ const struct loadcmd *prev = text; ++ c = text + 1; ++ ElfW(Addr) map_addr = text_addr; ++ while (c < &loadcmds[nloadcmds]) ++ { ++ if (prev->mapstart + mapseglen > c->mapstart || c->mapstart < prev->mapstart) ++ { ++ errstring = DL_MAP_SEGMENTS_ERROR_ARRANGE; ++ goto unmap_reserved_area; ++ } ++ ++ if (prev->mapstart + mapseglen < c->mapstart && ++ _mmap_hole(prev, c, map_addr, mapseglen, fd) == MAP_FAILED) ++ { ++ errstring = DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL; ++ goto unmap_reserved_area; ++ } ++ ++ map_addr += c->mapstart - prev->mapstart; ++ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd, &mapseglen); ++ if (__glibc_unlikely(errstring != NULL)) ++ goto unmap_reserved_area; ++ prev = c; ++ ++c; ++ } ++ ElfW(Addr) l_map_end = map_addr + mapseglen; ++ ++ /* search for the first segment */ ++ prev = text; ++ c = text - 1; ++ map_addr = text_addr; ++ while (c >= loadcmds) ++ { ++ if (prev->mapstart < c->mapstart) ++ { ++ errstring = DL_MAP_SEGMENTS_ERROR_ARRANGE; ++ goto unmap_reserved_area; ++ } ++ ++ map_addr -= prev->mapstart - c->mapstart; ++ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd, &mapseglen); ++ if (__glibc_unlikely(errstring != NULL)) ++ goto unmap_reserved_area; ++ ++ if (c->mapstart + mapseglen > prev->mapstart) ++ { ++ errstring = DL_MAP_SEGMENTS_ERROR_ARRANGE; ++ goto unmap_reserved_area; ++ } ++ ++ if (c->mapstart + mapseglen < prev->mapstart && ++ _mmap_hole(c, prev, map_addr, mapseglen, fd) == MAP_FAILED) ++ { ++ errstring = DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL; ++ goto unmap_reserved_area; ++ } ++ prev = c; ++ --c; ++ } ++ ++ ++c; ++ l->l_map_start = map_addr; ++ l->l_map_end = l->l_map_start + maplength; ++ l->l_addr = l->l_map_start - c->mapstart; ++ l->l_contiguous = 1; ++ ++ c = loadcmds; ++ while (c < &loadcmds[nloadcmds]) ++ { ++ _dl_postprocess_loadcmd (l, header, c); ++ ++c; ++ } ++ ++ if (l->l_map_start > (ElfW(Addr))map_area_start) ++ { ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("__munmap [%lx-%lx)\n", (ElfW(Addr))map_area_start, l->l_map_start); ++ __munmap(map_area_start, l->l_map_start - (ElfW(Addr))map_area_start); ++ } ++ ++ /* ++ * l->l_map_end is caculated by maplength, l_map_end may end with extra space ++ * use l->l_map_end may munmap extra space part ++ */ ++ if ((ElfW(Addr))map_area_start + maparealen > l_map_end) ++ { ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf("__munmap [%lx-%lx)\n", l_map_end, (ElfW(Addr))map_area_start + maparealen); ++ __munmap((void *)l_map_end, (ElfW(Addr))map_area_start + maparealen - l_map_end); ++ } ++ ++ return NULL; ++ ++unmap_reserved_area: ++ __munmap(map_area_start, maparealen); ++ ++ return errstring; ++} +diff --git a/elf/elf.h b/elf/elf.h +index 4738dfa2..c5315d1b 100644 +--- a/elf/elf.h ++++ b/elf/elf.h +@@ -730,6 +730,8 @@ typedef struct + + /* Legal values for p_flags (segment flags). */ + ++/* libhugetlbfs's hugeedit use 0x00100000, here use another */ ++#define PF_HUGEPAGE (0x01000000) + #define PF_X (1 << 0) /* Segment is executable */ + #define PF_W (1 << 1) /* Segment is writable */ + #define PF_R (1 << 2) /* Segment is readable */ +diff --git a/elf/hugepageedit.c b/elf/hugepageedit.c +new file mode 100644 +index 00000000..14a91a4b +--- /dev/null ++++ b/elf/hugepageedit.c +@@ -0,0 +1,169 @@ ++/* Mark ELF object ELF header hugepage flag Generic version. ++ Copyright (C) 2021-2021 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 ++#include ++#include ++#include ++#include ++ ++/* reference kernel load_elf_phdrs program header table size constraint */ ++#define ELF_MIN_ALIGN 4096 ++#define TOOL_NAME "hugepageedit" ++ ++int check_ptr(void *ptr, void *start, size_t len) ++{ ++ if (ptr < start || ptr > start + len) ++ return -1; ++ return 0; ++} ++ ++void print_usage(void) ++{ ++ fprintf(stderr, "%s [-x] [-d] \n" \ ++ "\tdefault mark all PT_LOAD segment PF_HUGEPAGE flag\n" \ ++ "\t-x option only mark executable PT_LOAD segment PF_HUGEPAGE flag\n" \ ++ "\t-d option delete all the PT_LOAD segment PF_HUGEPAGE flag\n", TOOL_NAME); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int exit_status = -1; ++ int i, opt, delete = 0, exec_only = 0; ++ while ((opt = getopt(argc, argv, "dx")) != -1) ++ { ++ switch (opt) ++ { ++ case 'd': ++ delete = 1; ++ break; ++ case 'x': ++ exec_only = 1; ++ break; ++ default: ++ print_usage(); ++ return 0; ++ } ++ } ++ ++ if (delete && exec_only) ++ { ++ fprintf(stderr, "can not specify -x and -d option at the same time\n"); ++ return -1; ++ } ++ ++ if (optind >= argc) ++ { ++ fprintf(stderr, "Expected argument after options\n"); ++ return -1; ++ } ++ ++ int fd = open(argv[optind], O_RDWR); ++ if (fd < 0) ++ { ++ perror("open"); ++ return -1; ++ } ++ ++ struct stat statbuf; ++ if (fstat(fd, &statbuf) != 0) ++ { ++ perror("fstat"); ++ goto close_fd; ++ } ++ ++ /* this ensures file is large enough to hold ELF header */ ++ if (statbuf.st_size < sizeof (ElfW(Ehdr))) ++ { ++ fprintf(stderr, "file is not large enough to hold ELF header\n"); ++ goto close_fd; ++ } ++ ++ void *ehdr = mmap(NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); ++ if (ehdr == MAP_FAILED) ++ { ++ perror("mmap"); ++ goto close_fd; ++ } ++ ++ if (memcmp(((ElfW(Ehdr) *) ehdr)->e_ident, ELFMAG, SELFMAG) != 0) ++ { ++ fprintf(stderr, "file is not ELF format\n"); ++ goto unmap; ++ } ++ ++ if (((ElfW(Ehdr) *)ehdr)->e_phentsize != sizeof(ElfW(Phdr))) ++ { ++ fprintf(stderr, "ELF header's e_phentsize mismatch ElfW(Phdr) size\n"); ++ goto unmap; ++ } ++ ++ unsigned int size = ((ElfW(Ehdr) *)ehdr)->e_phnum * sizeof(ElfW(Phdr)); ++ if (size == 0 || size > ELF_MIN_ALIGN) ++ { ++ fprintf(stderr, "The program header table size specified by ELF header is abnormal: %u\n", size); ++ goto unmap; ++ } ++ ++ void *ephdr_s = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff; ++ void *ephdr_e = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff + size; ++ ++ if (check_ptr(ephdr_s, ehdr, statbuf.st_size) || ++ check_ptr(ephdr_e, ehdr, statbuf.st_size)) ++ { ++ fprintf(stderr, "ELF porgram header table is not fully mmaped\n"); ++ goto unmap; ++ } ++ ++ ElfW(Phdr) *phdr = (ElfW(Phdr) *)ephdr_s; ++ /* ++ * Here, mark hugepage flag in ELF header e_ident padding bytes won't work. ++ * elf/dl-load.c open_verify will check if shared object ELF header e_ident ++ * padding bytes match expected[EI_NIDENT] byte array which padding bytes ++ * should be zero. If it mismatches, ld.so will exit abnormally ++ */ ++ for (i = 0; i < ((ElfW(Ehdr) *)ehdr)->e_phnum; i++) ++ { ++ if (phdr[i].p_type == PT_LOAD) ++ { ++ if (delete) ++ { ++ phdr[i].p_flags &= ~PF_HUGEPAGE; ++ } ++ else ++ { ++ if (exec_only && !(phdr[i].p_flags & PF_X)) ++ continue; ++ phdr[i].p_flags |= PF_HUGEPAGE; ++ } ++ } ++ } ++ exit_status = 0; ++ ++unmap: ++ munmap(ehdr, statbuf.st_size); ++ ++close_fd: ++ close(fd); ++ ++ return exit_status; ++} +diff --git a/elf/rtld.c b/elf/rtld.c +index 8268849a..491ef6b1 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2502,6 +2502,40 @@ dl_main (const ElfW(Phdr) *phdr, + /* Once we return, _dl_sysdep_start will invoke + the DT_INIT functions and then *USER_ENTRY. */ + } ++ ++#ifdef HUGEPAGE_SHARED_LIB ++/* prase the hugepage use strategy of loading shared object */ ++static void ++process_dl_hugepage (const char *dl_hugepage) ++{ ++ static const struct ++ { ++ uint64_t option; ++ int flag; ++ } hpopts[] = ++ { ++ {DL_HUGEPAGE_LARGE_IN, DL_HUGEPAGE_LIB_LARGE_IN_FLAG}, ++ }; ++#define nhpopts (sizeof (hpopts) / sizeof (hpopts[0])) ++ ++ if (dl_hugepage == NULL) ++ return; ++ ++ char *endptr; ++ uint64_t val = _dl_strtoul (dl_hugepage, &endptr); ++ /* Invalid digit in input string */ ++ if (*endptr != '\0') ++ return; ++ ++ for (size_t cnt = 0; cnt < nhpopts; ++cnt) ++ if (val == hpopts[cnt].option) ++ { ++ GLRO(dl_debug_mask) |= hpopts[cnt].flag; ++ break; ++ } ++} ++#endif ++ + + /* This is a little helper function for resolving symbols while + tracing the binary. */ +@@ -2637,6 +2671,9 @@ process_envvars (struct dl_main_state *state) + char **runp = _environ; + char *envline; + char *debug_output = NULL; ++#ifdef HUGEPAGE_SHARED_LIB ++ bool hugepage_lib_env = false; ++#endif + + /* This is the default place for profiling data file. */ + GLRO(dl_profile_output) +@@ -2751,6 +2788,16 @@ process_envvars (struct dl_main_state *state) + GLRO(dl_dynamic_weak) = 1; + break; + ++#ifdef HUGEPAGE_SHARED_LIB ++ if (memcmp (envline, "HUGEPAGE_LIB", 12) == 0 && envline[13] != '\0') ++ { ++ hugepage_lib_env = true; ++ process_dl_hugepage(&envline[13]); ++ } ++#endif ++ ++ break; ++ + case 13: + /* We might have some extra environment variable with length 13 + to handle. */ +@@ -2771,6 +2818,13 @@ process_envvars (struct dl_main_state *state) + && memcmp (envline, "PROFILE_OUTPUT", 14) == 0 + && envline[15] != '\0') + GLRO(dl_profile_output) = &envline[15]; ++ ++#ifdef HUGEPAGE_SHARED_LIB ++ if (memcmp (envline, "HUGEPAGE_PROBE", 14) == 0 && ++ envline[15] != '\0') ++ GLRO(dl_debug_mask) |= DL_HUGEPAGE_PROBE_FLAG; ++#endif ++ + break; + + case 16: +@@ -2800,6 +2854,16 @@ process_envvars (struct dl_main_state *state) + } + } + ++#ifdef HUGEPAGE_SHARED_LIB ++ /* LIB_HUGEPAGE_LIB and HUGEPAGE_PROBE are both set. use LIB_HUGEPAGE_LIB */ ++ if ((GLRO(dl_debug_mask) & DL_HUGEPAGE_PROBE_FLAG) && hugepage_lib_env) ++ { ++ GLRO(dl_debug_mask) &= ~DL_HUGEPAGE_PROBE_FLAG; ++ } ++ /* unsetenv LD_HUGEPAGE_LIB, child process should not get this env */ ++ unsetenv("LD_HUGEPAGE_LIB"); ++#endif ++ + /* Extra security for SUID binaries. Remove all dangerous environment + variables. */ + if (__builtin_expect (__libc_enable_secure, 0)) +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index fcbbf697..03cab4c4 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -549,7 +549,11 @@ struct rtld_global_ro + /* These two are used only internally. */ + #define DL_DEBUG_HELP (1 << 10) + #define DL_DEBUG_PRELINK (1 << 11) +- ++#ifdef HUGEPAGE_SHARED_LIB ++#define DL_HUGEPAGE_PROBE_FLAG (1 << 31) ++#define DL_HUGEPAGE_LIB_LARGE_IN_FLAG (1 << 30) ++#define DL_HUGEPAGE_LARGE_IN 1 ++#endif + /* OS version. */ + EXTERN unsigned int _dl_osversion; + /* Platform name. */ +-- +2.31.1 + diff --git a/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch b/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch new file mode 100644 index 0000000..9442241 --- /dev/null +++ b/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch @@ -0,0 +1,1177 @@ +From 74c980c56a1ae533c3cd25f572f83c0c1def6a30 Mon Sep 17 00:00:00 2001 +From: Lv Ying +Date: Tue, 25 Jan 2022 09:25:35 +0000 +Subject: [PATCH 2/3] elf/ld.so: add testcase for ld.so load shared object use + hugepage feature + +1. testcase for hugepageedit +2. testcase for feature env +3. testcase for feature fallback +4. testcase for hugepage mmap consistency witch process occupancy +5. testcase for dlopen use hugepage +--- + config.make.in | 1 + + configure | 24 ++++++- + configure.ac | 3 + + elf/Makefile | 61 +++++++++++++++++ + elf/hugepageedit.c | 69 +++---------------- + elf/tst-check-hugepage.sh | 72 ++++++++++++++++++++ + elf/tst-dl-hugepage.sh | 70 +++++++++++++++++++ + elf/tst-dl-use-hugepage.c | 54 +++++++++++++++ + elf/tst-get-ephdr.h | 96 ++++++++++++++++++++++++++ + elf/tst-hugepageedit1.sh | 85 +++++++++++++++++++++++ + elf/tst-ld-hugepage-env.sh | 108 ++++++++++++++++++++++++++++++ + elf/tst-ld-hugepage-fallback.sh | 66 ++++++++++++++++++ + elf/tst-ld-hugepage-mmap-smaps.sh | 49 ++++++++++++++ + elf/tst-ld-hugepage.h | 7 ++ + elf/tst-ld-hugepagemod.c | 19 ++++++ + elf/tst-update-ehdr.c | 58 ++++++++++++++++ + elf/tst-update-phdr.c | 93 +++++++++++++++++++++++++ + elf/tst-use-hugepage.c | 15 +++++ + 18 files changed, 889 insertions(+), 61 deletions(-) + create mode 100644 elf/tst-check-hugepage.sh + create mode 100644 elf/tst-dl-hugepage.sh + create mode 100644 elf/tst-dl-use-hugepage.c + create mode 100644 elf/tst-get-ephdr.h + create mode 100644 elf/tst-hugepageedit1.sh + create mode 100644 elf/tst-ld-hugepage-env.sh + create mode 100644 elf/tst-ld-hugepage-fallback.sh + create mode 100644 elf/tst-ld-hugepage-mmap-smaps.sh + create mode 100644 elf/tst-ld-hugepage.h + create mode 100644 elf/tst-ld-hugepagemod.c + create mode 100644 elf/tst-update-ehdr.c + create mode 100644 elf/tst-update-phdr.c + create mode 100644 elf/tst-use-hugepage.c + +diff --git a/config.make.in b/config.make.in +index cbf59114..0105cc8e 100644 +--- a/config.make.in ++++ b/config.make.in +@@ -76,6 +76,7 @@ use-default-link = @use_default_link@ + have-cxx-thread_local = @libc_cv_cxx_thread_local@ + have-loop-to-function = @libc_cv_cc_loop_to_function@ + have-textrel_ifunc = @libc_cv_textrel_ifunc@ ++have-hugetlb-dir = @have_hugetlb_dir@ + + multi-arch = @multi_arch@ + +diff --git a/configure b/configure +index 43993923..be2277b1 100755 +--- a/configure ++++ b/configure +@@ -670,7 +670,7 @@ stack_protector + libc_cv_ssp + libc_cv_with_fp + base_machine +-enable_hugepage_shared_library ++have_hugetlb_dir + have_tunables + build_pt_chown + build_nscd +@@ -3848,6 +3848,28 @@ enable-hugepage-shared-library = $enable_hugepage_shared_library" + if test "$enable_hugepage_shared_library" = yes; then + $as_echo "#define HUGEPAGE_SHARED_LIB 1" >>confdefs.h + ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /sys/devices/system/node/node0/hugepages/hugepages-2048kB/" >&5 ++$as_echo_n "checking for /sys/devices/system/node/node0/hugepages/hugepages-2048kB/... " >&6; } ++if ${ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ test "$cross_compiling" = yes && ++ as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 ++if test -r "/sys/devices/system/node/node0/hugepages/hugepages-2048kB/"; then ++ ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_=yes ++else ++ ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_=no ++fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" >&5 ++$as_echo "$ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" >&6; } ++if test "x$ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" = xyes; then : ++ have_hugetlb_dir=yes ++else ++ have_hugetlb_dir=no ++fi ++ ++ + fi + + # We keep the original values in `$config_*' and never modify them, so we +diff --git a/configure.ac b/configure.ac +index 27a48338..fa34af26 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -487,6 +487,9 @@ AC_ARG_ENABLE([hugepage-shared-library], + LIBC_CONFIG_VAR([enable-hugepage-shared-library], [$enable_hugepage_shared_library]) + if test "$enable_hugepage_shared_library" = yes; then + AC_DEFINE(HUGEPAGE_SHARED_LIB) ++ AC_CHECK_FILE(/sys/devices/system/node/node0/hugepages/hugepages-2048kB/, ++ have_hugetlb_dir=yes, have_hugetlb_dir=no) ++ AC_SUBST(have_hugetlb_dir) + fi + + # We keep the original values in `$config_*' and never modify them, so we +diff --git a/elf/Makefile b/elf/Makefile +index 1574574d..0fb2be3b 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -213,6 +213,12 @@ others-pie += hugepageedit + install-bin += hugepageedit + + $(objpfx)hugepageedit: $(objpfx)hugepageedit.o ++ ++ifeq ($(run-built-tests),yes) ++tests-special += $(objpfx)tst-hugepageedit1.out $(objpfx)tst-ld-hugepage-env.out \ ++ $(objpfx)tst-ld-hugepage-fallback.out $(objpfx)tst-ld-hugepage-mmap-smaps.out \ ++ $(objpfx)tst-dl-hugepage.out ++endif + endif + + # To find xmalloc.c and xstrdup.c +@@ -788,6 +794,13 @@ $(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so + tst-gnu2-tls1mod.so-no-z-defs = yes + CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2 + endif ++ifeq (yes,$(enable-hugepage-shared-library)) ++ld-hugepagemod-suffixes = 1 2 3 4 5 ++ld-hugepagemod-modules = $(addprefix tst-ld-hugepagemod, $(ld-hugepagemod-suffixes)) ++tst-usehugepage = $(addprefix tst-use-hugepage, $(ld-hugepagemod-suffixes)) ++modules-names += $(ld-hugepagemod-modules) ++test-srcs += tst-update-ehdr tst-update-phdr tst-dl-use-hugepage $(tst-usehugepage) ++endif + ifeq (yes,$(have-protected-data)) + modules-names += tst-protected1moda tst-protected1modb + tests += tst-protected1a tst-protected1b +@@ -2015,6 +2028,54 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig + '$(run-program-env)' > $@; \ + $(evaluate-test) + ++ifeq (yes,$(enable-hugepage-shared-library)) ++CFLAGS-tst-ld-hugepagemod.c += -DOBJDIR=\"$(elf-objpfx)\" ++$(objpfx)tst-ld-hugepage-bin.o : ++ dd if=/dev/zero of=$@ count=4 bs=2MB ++$(patsubst %,$(objpfx)%.os,$(ld-hugepagemod-modules)): $(objpfx)tst-ld-hugepagemod%.os: tst-ld-hugepagemod.c $(objpfx)tst-ld-hugepage-bin.o ++ $(compile-command.c) -DN=$* ++$(patsubst %,$(objpfx)%.o,$(tst-usehugepage)): $(objpfx)tst-use-hugepage%.o: tst-use-hugepage.c ++ $(compile-command.c) ++$(patsubst tst-use-hugepage%,$(objpfx)tst-use-hugepage%,$(tst-usehugepage)): $(objpfx)tst-use-hugepage% : \ ++ $(objpfx)tst-use-hugepage%.o $(objpfx)tst-ld-hugepagemod%.so $(objpfx)ld.so ++$(objpfx)tst-dl-use-hugepage: $(libdl) ++ ++ifeq ($(have-hugetlb-dir),yes) ++$(objpfx)tst-hugepageedit1.out: tst-hugepageedit1.sh tst-check-hugepage.sh \ ++ $(objpfx)tst-update-ehdr $(objpfx)tst-use-hugepage1 $(objpfx)tst-ld-hugepagemod1.so ++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \ ++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \ ++ $(evaluate-test) ++ ++$(objpfx)tst-ld-hugepage-env.out: tst-ld-hugepage-env.sh tst-check-hugepage.sh \ ++ $(objpfx)tst-use-hugepage2 $(objpfx)tst-ld-hugepagemod2.so ++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \ ++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \ ++ $(evaluate-test) ++ ++$(objpfx)tst-ld-hugepage-fallback.out: tst-ld-hugepage-fallback.sh tst-check-hugepage.sh \ ++ $(objpfx)tst-update-phdr $(objpfx)tst-use-hugepage3 $(objpfx)tst-ld-hugepagemod3.so ++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \ ++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \ ++ $(evaluate-test) ++ ++$(objpfx)tst-ld-hugepage-mmap-smaps.out: tst-ld-hugepage-mmap-smaps.sh tst-check-hugepage.sh \ ++ $(objpfx)tst-use-hugepage4 $(objpfx)tst-ld-hugepagemod4.so ++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \ ++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \ ++ $(evaluate-test) ++ ++$(objpfx)tst-dl-hugepage.out: tst-dl-hugepage.sh tst-check-hugepage.sh \ ++ $(objpfx)tst-dl-use-hugepage $(objpfx)tst-ld-hugepagemod5.so ++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \ ++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \ ++ $(evaluate-test) ++else ++tests-unsupported += tst-hugepageedit1.out tst-ld-hugepage-env.out tst-ld-hugepage-fallback.out \ ++ tst-ld-hugepage-mmap-smaps.out tst-dl-hugepage.out ++endif ++endif ++ + # Test static linking of all the libraries we can possibly link + # together. Note that in some configurations this may be less than the + # complete list of libraries we build but we try to maxmimize this list. +diff --git a/elf/hugepageedit.c b/elf/hugepageedit.c +index 14a91a4b..ab4247ad 100644 +--- a/elf/hugepageedit.c ++++ b/elf/hugepageedit.c +@@ -25,18 +25,10 @@ + #include + #include + #include ++#include "tst-get-ephdr.h" + +-/* reference kernel load_elf_phdrs program header table size constraint */ +-#define ELF_MIN_ALIGN 4096 + #define TOOL_NAME "hugepageedit" + +-int check_ptr(void *ptr, void *start, size_t len) +-{ +- if (ptr < start || ptr > start + len) +- return -1; +- return 0; +-} +- + void print_usage(void) + { + fprintf(stderr, "%s [-x] [-d] \n" \ +@@ -47,6 +39,7 @@ void print_usage(void) + + int main(int argc, char *argv[]) + { ++ size_t length; + int exit_status = -1; + int i, opt, delete = 0, exec_only = 0; + while ((opt = getopt(argc, argv, "dx")) != -1) +@@ -84,57 +77,13 @@ int main(int argc, char *argv[]) + return -1; + } + +- struct stat statbuf; +- if (fstat(fd, &statbuf) != 0) +- { +- perror("fstat"); +- goto close_fd; +- } +- +- /* this ensures file is large enough to hold ELF header */ +- if (statbuf.st_size < sizeof (ElfW(Ehdr))) +- { +- fprintf(stderr, "file is not large enough to hold ELF header\n"); +- goto close_fd; +- } +- +- void *ehdr = mmap(NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); +- if (ehdr == MAP_FAILED) +- { +- perror("mmap"); +- goto close_fd; +- } +- +- if (memcmp(((ElfW(Ehdr) *) ehdr)->e_ident, ELFMAG, SELFMAG) != 0) +- { +- fprintf(stderr, "file is not ELF format\n"); +- goto unmap; +- } +- +- if (((ElfW(Ehdr) *)ehdr)->e_phentsize != sizeof(ElfW(Phdr))) +- { +- fprintf(stderr, "ELF header's e_phentsize mismatch ElfW(Phdr) size\n"); +- goto unmap; +- } +- +- unsigned int size = ((ElfW(Ehdr) *)ehdr)->e_phnum * sizeof(ElfW(Phdr)); +- if (size == 0 || size > ELF_MIN_ALIGN) +- { +- fprintf(stderr, "The program header table size specified by ELF header is abnormal: %u\n", size); +- goto unmap; +- } +- +- void *ephdr_s = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff; +- void *ephdr_e = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff + size; +- +- if (check_ptr(ephdr_s, ehdr, statbuf.st_size) || +- check_ptr(ephdr_e, ehdr, statbuf.st_size)) +- { +- fprintf(stderr, "ELF porgram header table is not fully mmaped\n"); +- goto unmap; +- } ++ void *ehdr = get_ehdr(fd, &length); ++ if (ehdr == NULL) ++ goto close_fd; + +- ElfW(Phdr) *phdr = (ElfW(Phdr) *)ephdr_s; ++ ElfW(Phdr) *phdr = (ElfW(Phdr) *)get_phdr(ehdr, length); ++ if (phdr == NULL) ++ goto unmap; + /* + * Here, mark hugepage flag in ELF header e_ident padding bytes won't work. + * elf/dl-load.c open_verify will check if shared object ELF header e_ident +@@ -160,7 +109,7 @@ int main(int argc, char *argv[]) + exit_status = 0; + + unmap: +- munmap(ehdr, statbuf.st_size); ++ munmap(ehdr, length); + + close_fd: + close(fd); +diff --git a/elf/tst-check-hugepage.sh b/elf/tst-check-hugepage.sh +new file mode 100644 +index 00000000..0cdebe2a +--- /dev/null ++++ b/elf/tst-check-hugepage.sh +@@ -0,0 +1,72 @@ ++#!/bin/sh ++# check whether ld.so use hugepage when loading shared object and whether ++# there are exceptions when using hugepage ++# Copyright (C) 2021-2021 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 ++# . ++ ++check_hugepage_mmap () { ++ log=$1 ++ ++ cat $log | egrep "reserved area|_dl_map_segments_largein:" > /dev/null && return 0 ++ return 1 ++} ++ ++check_hugepage_mmap_success () { ++ log=$1 ++ ++ # check whether the log contains fallback log ++ cat $log | grep "_dl_map_segments_largein:" > /dev/null && return 1 ++ check_hugepage_mmap $log || return 1 ++ left=$(cat $log | grep _mmap_segment | wc -l) ++ right=$(cat $log | grep "} => mapseglen" | wc -l) ++ if [ $left -eq $right ]; then ++ return 0 ++ else ++ return 1 ++ fi ++} ++ ++check_hugepage_fallback () { ++ log=$1 ++ ++ cat $log | grep "_dl_map_segments_largein:" > /dev/null && return 0 ++ return 1 ++} ++ ++# return 0: mmap hugepage correctly ++# return 1: Non-hugepage mmap ++# return 2: mmap hugepage wrongly ++check_hugepage_mmap_detail () { ++ log=$1 ++ ++ # check whether the log contains hugepage mmap ++ areas=$(cat $log | grep "mmap hugepage:" | awk '{print $4}' | cut -d '[' -f2 | cut -d ')' -f1) ++ if test -z "$areas"; then ++ return 1 ++ else ++ for area in $areas; do ++ num=$(grep "mmap hugepage: \[$area)" $log | wc -l) ++ num=$(( $num * 2)) ++ total_num=$(grep $area $log | wc -l) ++ if [ $num -ne $total_num ]; then ++ return 2 ++ fi ++ grep -A21 $area $log | tail -22 ++ done ++ return 0 ++ fi ++} +diff --git a/elf/tst-dl-hugepage.sh b/elf/tst-dl-hugepage.sh +new file mode 100644 +index 00000000..f67e552f +--- /dev/null ++++ b/elf/tst-dl-hugepage.sh +@@ -0,0 +1,70 @@ ++#!/bin/sh ++# Test that ld.so can handle dlopen call ++# Copyright (C) 2021-2021 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 ++# . ++ ++set -ex ++echo "source $4" ++source $4 ++ ++common_objpfx=$1 ++test_wrapper=$2 ++test_wrapper_env=$3 ++result=0 ++ ++excption_handle () ++{ ++ echo "ld.so hugepage feature is not behaving as expected, return $1" ++ result=1 ++} ++ ++check_global_var () ++{ ++ log=$1 ++ ++ for i in $(seq 1 2); do ++ cat $log | grep "In huge_func, huge_global = $i" > /dev/null|| return -1 ++ done ++ return 0 ++} ++ ++testroot="${common_objpfx}elf/dl-hugepage-directory" ++ ++rm -rf "$testroot" ++mkdir -p $testroot ++ ++echo '# reseve 200 2MB hugepage' ++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1 ++ ++echo '# Test LD_HUGEPAGE_LIB=1 whether ld.so mmap hugepage is consistent with the actual process occupancy' ++${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-dl-use-hugepage ${common_objpfx}elf/tst-ld-hugepagemod5.so > ${testroot}/log1 2>&1 ++check_hugepage_mmap_detail ${testroot}/log1 && rc=0 || rc=$? ++#check_global_var ${testroot}/log1 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle $rc ++ ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod5.so || exit 1 ++ ++echo '# Test HUGEPAGE_PROBE=1 whether ld.so mmap hugepage is consistent with the actual process occupancy' ++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-dl-use-hugepage ${common_objpfx}elf/tst-ld-hugepagemod5.so > ${testroot}/log2 2>&1 ++check_hugepage_mmap_detail ${testroot}/log2 && rc=0 || rc=$? ++#check_global_var ${testroot}/log2 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle $rc ++ ++exit $result +diff --git a/elf/tst-dl-use-hugepage.c b/elf/tst-dl-use-hugepage.c +new file mode 100644 +index 00000000..cd7c6f29 +--- /dev/null ++++ b/elf/tst-dl-use-hugepage.c +@@ -0,0 +1,54 @@ ++#include ++#include ++#include ++#include ++#include "tst-ld-hugepage.h" ++ ++#define DL_ERR_HANDLE(s) \ ++do { \ ++ fprintf(stderr, "%s: %s\n", s, dlerror()); \ ++ exit(EXIT_FAILURE); \ ++} while(0) ++ ++static void dl_flag_test(char *libname, int flags, int val) ++{ ++ int *global; ++ char *error; ++ void (*funcp)(void); ++ char command[100]; ++ sprintf(command, "cat /proc/%d/smaps", getpid()); ++ ++ void *handle = dlopen(libname, flags); ++ if (handle == NULL) ++ DL_ERR_HANDLE("dlopen"); ++ ++ (void) dlerror(); ++ ++ *(void **)(&global) = dlsym(handle, "huge_global"); ++ error = dlerror(); ++ if (error != NULL) ++ DL_ERR_HANDLE("dlsym"); ++ ++ (void) dlerror(); ++ *(void **)(&funcp) = dlsym(handle, "huge_func"); ++ error = dlerror(); ++ if (error != NULL) ++ DL_ERR_HANDLE("dlsym"); ++ ++ *global = val; ++ (*funcp)(); ++ system(command); ++ dlclose(handle); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ if (argc != 2) ++ { ++ fprintf(stderr, "shared object should be a parameter\n"); ++ exit(EXIT_FAILURE); ++ } ++ dl_flag_test(argv[1], RTLD_LAZY, 1); ++ dl_flag_test(argv[1], RTLD_NOW, 2); ++ return 0; ++} +diff --git a/elf/tst-get-ephdr.h b/elf/tst-get-ephdr.h +new file mode 100644 +index 00000000..109af265 +--- /dev/null ++++ b/elf/tst-get-ephdr.h +@@ -0,0 +1,96 @@ ++/* mmap ELF file return ELF header and get mmap length ++ Copyright (C) 1995-2021 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 ++ ++/* reference kernel load_elf_phdrs program header table size constraint */ ++#define ELF_MIN_ALIGN 4096 ++ ++static __always_inline void *get_ehdr(int fd, size_t *len) ++{ ++ struct stat statbuf; ++ *len = 0; ++ if (fstat(fd, &statbuf) != 0) ++ { ++ perror("fstat"); ++ return NULL; ++ } ++ ++ /* this ensures file is large enough to hold ELF header */ ++ if (statbuf.st_size < sizeof (ElfW(Ehdr))) ++ { ++ fprintf(stderr, "file is not large enough to hold ELF header\n"); ++ return NULL; ++ } ++ ++ void *ehdr = mmap(NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); ++ if (ehdr == MAP_FAILED) ++ { ++ perror("mmap"); ++ return NULL; ++ } ++ ++ if (memcmp(((ElfW(Ehdr) *) ehdr)->e_ident, ELFMAG, SELFMAG) != 0) ++ { ++ fprintf(stderr, "file is not ELF format\n"); ++ munmap(ehdr, statbuf.st_size); ++ ehdr = NULL; ++ } ++ ++ *len = statbuf.st_size; ++ return ehdr; ++} ++ ++static __always_inline int check_ptr(void *ptr, void *start, size_t len) ++{ ++ if (ptr < start || ptr > start + len) ++ return -1; ++ return 0; ++} ++ ++static __always_inline void *get_phdr(void *ehdr, size_t length) ++{ ++ if (((ElfW(Ehdr) *)ehdr)->e_phentsize != sizeof(ElfW(Phdr))) ++ { ++ fprintf(stderr, "ELF header's e_phentsize mismatch ElfW(Phdr) size\n"); ++ return NULL; ++ } ++ ++ unsigned int size = ((ElfW(Ehdr) *)ehdr)->e_phnum * sizeof(ElfW(Phdr)); ++ if (size == 0 || size > ELF_MIN_ALIGN) ++ { ++ fprintf(stderr, "The program header table size specified by ELF header is abnormal: %u\n", size); ++ return NULL; ++ } ++ ++ void *ephdr_s = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff; ++ void *ephdr_e = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff + size; ++ ++ if (check_ptr(ephdr_s, ehdr, length) || ++ check_ptr(ephdr_e, ehdr, length)) ++ { ++ fprintf(stderr, "ELF porgram header table is not fully mmaped\n"); ++ return NULL; ++ } ++ ++ return ephdr_s; ++} +diff --git a/elf/tst-hugepageedit1.sh b/elf/tst-hugepageedit1.sh +new file mode 100644 +index 00000000..ee43c279 +--- /dev/null ++++ b/elf/tst-hugepageedit1.sh +@@ -0,0 +1,85 @@ ++#!/bin/sh ++# Test that hugepageedit can handle abnormal files reasonably ++# Copyright (C) 2021-2021 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 ++# . ++ ++set -ex ++echo "source $4" ++source $4 ++ ++common_objpfx=$1 ++test_wrapper=$2 ++test_wrapper_env=$3 ++result=0 ++ ++excption_handle () ++{ ++ echo "hugepageedit and ls.so use hugepage feature is not beahving expected" ++ result=1 ++} ++ ++testroot="${common_objpfx}elf/hugepageedit-test-directory" ++ ++rm -rf "$testroot" ++mkdir -p $testroot ++cp ${common_objpfx}elf/tst-use-hugepage1 $testroot/tst-use-hugepage1 ++ ++echo '# reseve 200 2MB hugepage' ++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1 ++ ++echo '# Test no option hugepageedit' ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1 ++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log1 2>&1 ++check_hugepage_mmap_success ${testroot}/log1 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++echo '# Test hugepageedit -d option' ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1 ++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log2 2>&1 ++check_hugepage_mmap ${testroot}/log2 && rc=1 || rc=0 ++test $rc -eq 0 || excption_handle ++ ++echo '# Test hugepageedit -x option' ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit -x ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1 ++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log3 2>&1 ++check_hugepage_mmap_success ${testroot}/log3 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++echo '# Test Non-ELF file' ++dd if=/dev/urandom of=${testroot}/test.file count=1024 bs=1024 ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/test.file 2>&1 && result=1 ++ ++echo '# Test ELF phnum is 0' ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/tst-update-ehdr ${testroot}/tst-use-hugepage1 0 2>&1 || result=1 ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/tst-use-hugepage1 2>&1 && result=1 ++ ++echo '# Test ELF phnum is 0xFFFF' ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/tst-update-ehdr ${testroot}/tst-use-hugepage1 65535 2>&1 || result=1 ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/tst-use-hugepage1 2>&1 && result=1 ++ ++exit $result +diff --git a/elf/tst-ld-hugepage-env.sh b/elf/tst-ld-hugepage-env.sh +new file mode 100644 +index 00000000..e16ada67 +--- /dev/null ++++ b/elf/tst-ld-hugepage-env.sh +@@ -0,0 +1,108 @@ ++#!/bin/sh ++# Test that ld.so can handle different env input ++# Copyright (C) 2021-2021 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 ++# . ++ ++set -ex ++echo "source $4" ++source $4 ++ ++common_objpfx=$1 ++test_wrapper=$2 ++test_wrapper_env=$3 ++result=0 ++ ++excption_handle () ++{ ++ echo "ld.so hugepage feature is not behaving as expected" ++ result=1 ++} ++ ++testroot="${common_objpfx}elf/ld-hugepage-env-directory" ++ ++rm -rf "$testroot" ++mkdir -p $testroot ++ ++echo '# reseve 200 2MB hugepage' ++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1 ++ ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod2.so || exit 1 ++ ++echo '# Test HUGEPAGE_PROBE env set 1 and shared object is not hugepageedited' ++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log1 2>&1 ++check_hugepage_mmap ${testroot}/log1 && rc=1 || rc=0 ++test $rc -eq 0 || excption_handle ++ ++echo '# Test LD_HUGEPAGE_LIB env set 1 and shared object is not hugepageedited' ++${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log2 2>&1 ++check_hugepage_mmap_success ${testroot}/log2 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++echo '# Test LD_HUGEPAGE_LIB env set 100 and shared object is not hugepageedited' ++${test_wrapper_env} LD_HUGEPAGE_LIB=100 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log3 2>&1 ++check_hugepage_mmap ${testroot}/log3 && rc=1 || rc=0 ++test $rc -eq 0 || excption_handle ++ ++echo '# Test LD_HUGEPAGE_LIB env set -8 and shared object is not hugepageedited' ++${test_wrapper_env} LD_HUGEPAGE_LIB=-8 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log4 2>&1 ++check_hugepage_mmap ${testroot}/log4 && rc=1 || rc=0 ++test $rc -eq 0 || excption_handle ++ ++echo '# Test LD_HUGEPAGE_LIB env set aa#_bb and shared object is not hugepageedited' ++${test_wrapper_env} LD_HUGEPAGE_LIB=aa#_bb LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log5 2>&1 ++check_hugepage_mmap ${testroot}/log5 && rc=1 || rc=0 ++test $rc -eq 0 || excption_handle ++ ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod2.so || exit 1 ++echo '# Test HUGEPAGE_PROBE env set 2 and shared object is hugepageedited' ++${test_wrapper_env} HUGEPAGE_PROBE=2 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log6 2>&1 ++check_hugepage_mmap_success ${testroot}/log6 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++echo '# Test HUGEPAGE_PROBE env set -2 and shared object is hugepageedited' ++${test_wrapper_env} HUGEPAGE_PROBE=-2 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log7 2>&1 ++check_hugepage_mmap_success ${testroot}/log7 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++echo '# Test HUGEPAGE_PROBE env set 0 and shared object is hugepageedited' ++${test_wrapper_env} HUGEPAGE_PROBE=0 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log8 2>&1 ++check_hugepage_mmap_success ${testroot}/log8 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++echo '# Test HUGEPAGE_PROBE env set 3.14 and shared object is hugepageedited' ++${test_wrapper_env} HUGEPAGE_PROBE=3.14 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log9 2>&1 ++check_hugepage_mmap_success ${testroot}/log9 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++echo '# Test HUGEPAGE_PROBE env set #aabb and shared object is hugepageedited' ++${test_wrapper_env} HUGEPAGE_PROBE=#aabb LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log10 2>&1 ++check_hugepage_mmap_success ${testroot}/log10 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++exit $result +diff --git a/elf/tst-ld-hugepage-fallback.sh b/elf/tst-ld-hugepage-fallback.sh +new file mode 100644 +index 00000000..0c616633 +--- /dev/null ++++ b/elf/tst-ld-hugepage-fallback.sh +@@ -0,0 +1,66 @@ ++#!/bin/sh ++# Test that ld.so can fallback to original shared object load process when ++# exception happens ++# Copyright (C) 2021-2021 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 ++# . ++ ++echo "source $4" ++source $4 ++ ++common_objpfx=$1 ++test_wrapper=$2 ++test_wrapper_env=$3 ++result=0 ++ ++excption_handle () ++{ ++ echo "ld.so hugepage feature should fallback this time" ++ result=1 ++} ++ ++testroot="${common_objpfx}elf/ld-hugepage-fallback" ++ ++rm -rf "$testroot" ++mkdir -p $testroot ++ ++echo '# reseve 200 2MB hugepage' ++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1 ++ ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1 ++ ++echo '# tst-update-phdr make shared object previous PT_LOAD segment vma > next' ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/tst-update-phdr ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1 ++ ++echo '# Test LD_HUGEPAGE_LIB env set 1 and shared object is not hugepageedited' ++${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage3 > ${testroot}/log1 2>&1 ++check_hugepage_fallback ${testroot}/log1 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++echo '# hugepageedit shared object' ++${test_wrapper_env} \ ++${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1 ++ ++echo '# Test HUGEPAGE_PROBE env set 1 and shared object is hugepageedited' ++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage3 > ${testroot}/log2 2>&1 ++check_hugepage_fallback ${testroot}/log2 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle ++ ++exit $result +diff --git a/elf/tst-ld-hugepage-mmap-smaps.sh b/elf/tst-ld-hugepage-mmap-smaps.sh +new file mode 100644 +index 00000000..b817ab53 +--- /dev/null ++++ b/elf/tst-ld-hugepage-mmap-smaps.sh +@@ -0,0 +1,49 @@ ++#!/bin/sh ++# Test that ld.so mmapping hugepage is consistent with the actual process occupancy ++# Copyright (C) 2021-2021 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 ++# . ++ ++set -ex ++echo "source $4" ++source $4 ++ ++common_objpfx=$1 ++test_wrapper=$2 ++test_wrapper_env=$3 ++result=0 ++ ++excption_handle () ++{ ++ echo "ld.so mmap hugepage is not consistent with the actual process occupancy, return $1" ++ result=1 ++} ++ ++testroot="${common_objpfx}elf/ld-hugepage-mmap-smaps" ++ ++rm -rf "$testroot" ++mkdir -p $testroot ++ ++echo '# reseve 200 2MB hugepage' ++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1 ++ ++echo '# Test LD_HUGEPAGE_LIB=1 whether ld.so mmap hugepage is consistent with the actual process occupancy' ++${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \ ++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage4 > ${testroot}/log1 2>&1 ++check_hugepage_mmap_detail ${testroot}/log1 && rc=0 || rc=$? ++test $rc -eq 0 || excption_handle $rc ++ ++exit $result +diff --git a/elf/tst-ld-hugepage.h b/elf/tst-ld-hugepage.h +new file mode 100644 +index 00000000..30e938da +--- /dev/null ++++ b/elf/tst-ld-hugepage.h +@@ -0,0 +1,7 @@ ++#ifndef TST_HUGEPAGE_H ++#define TST_HUGEPAGE_H ++ ++extern void huge_func(void); ++extern int huge_global; ++ ++#endif +diff --git a/elf/tst-ld-hugepagemod.c b/elf/tst-ld-hugepagemod.c +new file mode 100644 +index 00000000..70c42e5a +--- /dev/null ++++ b/elf/tst-ld-hugepagemod.c +@@ -0,0 +1,19 @@ ++#include ++ ++#define BIN_PATH OBJDIR"/tst-ld-hugepage-bin.o" ++ ++int huge_global; ++ ++asm (".section .rodata\n\t" \ ++ ".globl vvvdso_start, vvvdso_end\n" \ ++ ".balign 4096\n" \ ++ "vvvdso_start:\n\t" \ ++ ".incbin " "\""BIN_PATH"\"" "\n\t" \ ++ ".balign 4096\n" \ ++ "vvvdso_end:\n\t" \ ++ ".previous"); ++ ++void huge_func(void) ++{ ++ printf("In huge_func, huge_global = %d\n", huge_global); ++} +diff --git a/elf/tst-update-ehdr.c b/elf/tst-update-ehdr.c +new file mode 100644 +index 00000000..6d653aa0 +--- /dev/null ++++ b/elf/tst-update-ehdr.c +@@ -0,0 +1,58 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-get-ephdr.h" ++ ++#define TOOL_NAME "tst-update-ehdr" ++ ++void print_usage(void) ++{ ++ fprintf(stderr, "%s \n", TOOL_NAME); ++} ++ ++int main(int argc, char **argv) ++{ ++ size_t length; ++ int exit_status = EXIT_FAILURE; ++ ++ if (argc != 3) ++ { ++ print_usage(); ++ exit(EXIT_FAILURE); ++ } ++ ++ int fd = open(argv[1], O_RDWR); ++ if (fd < 0) ++ { ++ perror("open"); ++ exit(EXIT_FAILURE); ++ } ++ ++ void *ehdr = get_ehdr(fd, &length); ++ if (ehdr == NULL) ++ goto close_fd; ++ ++ char *endptr; ++ unsigned long val = strtoul(argv[2], &endptr, 10); ++ if ((errno == ERANGE && val == ULONG_MAX) || (errno != 0 && val == 0)) ++ { ++ perror("strtoul"); ++ goto unmap; ++ } ++ ++ ((ElfW(Ehdr) *)ehdr)->e_phnum = val; ++ exit_status = EXIT_SUCCESS; ++ ++unmap: ++ munmap(ehdr, length); ++ ++close_fd: ++ close(fd); ++ ++ exit(exit_status); ++} +diff --git a/elf/tst-update-phdr.c b/elf/tst-update-phdr.c +new file mode 100644 +index 00000000..bd3e30eb +--- /dev/null ++++ b/elf/tst-update-phdr.c +@@ -0,0 +1,93 @@ ++/* construct exception PT_LOAD segment VMA ++ make previous PT_LOAD vma > next PT_LOAD vma ++ Copyright (C) 2021-2021 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 ++#include ++#include ++#include ++#include ++#include "tst-get-ephdr.h" ++ ++#define TOOL_NAME "tst-update-phdr" ++#define PAGE_SIZE 0x1000 ++ ++void print_usage(void) ++{ ++ fprintf(stderr, "%s \n", TOOL_NAME); ++} ++ ++int main(int argc, char **argv) ++{ ++ size_t length; ++ int exit_status = EXIT_FAILURE; ++ int i; ++ if (argc != 2) ++ { ++ print_usage(); ++ exit(EXIT_FAILURE); ++ } ++ ++ int fd = open(argv[1], O_RDWR); ++ if (fd < 0) ++ { ++ perror("open"); ++ exit(EXIT_FAILURE); ++ } ++ ++ void *ehdr = get_ehdr(fd, &length); ++ if (ehdr == NULL) ++ goto close_fd; ++ ++ ElfW(Phdr) *phdr = (ElfW(Phdr) *)get_phdr(ehdr, length); ++ if (phdr == NULL) ++ goto unmap; ++ ++ ElfW(Phdr) *prev =NULL, *next = NULL; ++ for (i = 0; i < ((ElfW(Ehdr) *)ehdr)->e_phnum; i++) ++ { ++ if (prev != NULL && next != NULL) ++ break; ++ if (phdr[i].p_type == PT_LOAD) ++ { ++ if (prev == NULL) ++ prev = &phdr[i]; ++ else ++ next = &phdr[i]; ++ } ++ } ++ if (prev != NULL && next != NULL) ++ { ++ prev->p_vaddr = next->p_vaddr + PAGE_SIZE; ++ exit_status = EXIT_SUCCESS; ++ } ++ else ++ fprintf(stderr, "There are no PT_LOADs in %s\n", argv[1]); ++ ++unmap: ++ munmap(ehdr, length); ++ ++close_fd: ++ close(fd); ++ ++ exit(exit_status); ++} +diff --git a/elf/tst-use-hugepage.c b/elf/tst-use-hugepage.c +new file mode 100644 +index 00000000..938e0afc +--- /dev/null ++++ b/elf/tst-use-hugepage.c +@@ -0,0 +1,15 @@ ++#include ++#include ++#include ++#include "tst-ld-hugepage.h" ++ ++int main(void) ++{ ++ char command[100]; ++ sprintf(command, "cat /proc/%d/smaps", getpid()); ++ system(command); ++ huge_func(); ++ huge_global = 1; ++ huge_func(); ++ return 0; ++} +-- +2.31.1 + diff --git a/0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch b/0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch new file mode 100644 index 0000000..8b67e66 --- /dev/null +++ b/0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch @@ -0,0 +1,69 @@ +From 49986b3674d002c43fa09e6b777555bdc772018b Mon Sep 17 00:00:00 2001 +From: Lv Ying +Date: Tue, 25 Jan 2022 09:29:32 +0000 +Subject: [PATCH 3/3] elf/ld.so: use special mmap for hugepage to get symbols + +use special mmap for hugepage to get symbols in hugepage area for debug +purpose; kernel need to support file mmap hugepage; +--- + elf/dl-load.h | 2 -- + elf/dl-map-segments-hugepage.h | 25 +++---------------------- + 2 files changed, 3 insertions(+), 24 deletions(-) + +diff --git a/elf/dl-load.h b/elf/dl-load.h +index d3f69466..fcf91a47 100644 +--- a/elf/dl-load.h ++++ b/elf/dl-load.h +@@ -134,8 +134,6 @@ static const char *_dl_map_segments (struct link_map *l, int fd, + #ifdef HUGEPAGE_SHARED_LIB + #define DL_MAP_SEGMENTS_ERROR_TYPE \ + N_("cannot map Non shared object file in hugepage") +-#define DL_MAP_SEGMENTS_ERROR_READ_SEGMENT \ +- N_("failed to read shared object file") + #define DL_MAP_SEGMENTS_ERROR_ARRANGE \ + N_("shared object's PT_LOAD segment in wrong arrange") + #define DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL \ +diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h +index cd7b6d79..37788ef9 100644 +--- a/elf/dl-map-segments-hugepage.h ++++ b/elf/dl-map-segments-hugepage.h +@@ -302,33 +302,14 @@ _mmap_segment_filesz(struct link_map *l, const struct loadcmd *c, ElfW(Addr) map + + size_t mod = len % SIZE_2MB; + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) +- _dl_debug_printf("\t\tmmap hugepage: [%lx-%lx)\n", mapstart, mapstart + len - mod); ++ _dl_debug_printf("\t\tmmap hugepage: [%lx-%lx), mapoff = %lx\n", mapstart, ++ mapstart + len - mod, c->mapoff + relro_len + prev_map_len); + mapstart = (ElfW(Addr))__mmap((void *)mapstart, len - mod, c->prot, + MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT), +- -1, 0); ++ fd, c->mapoff + relro_len + prev_map_len); + if (__glibc_unlikely ((void *)mapstart == MAP_FAILED)) + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + +- if ((c->prot & PROT_WRITE) == 0 && __mprotect((void *)mapstart, len - mod, c->prot | PROT_WRITE) < 0) +- { +- return DL_MAP_SEGMENTS_ERROR_MPROTECT; +- } +- +- /* Read the segment contents from the file. */ +- size_t file_len = (size_t)(c->dataend - c->mapstart) <= prev_map_len + relro_len ? 0 : +- (size_t)(c->dataend - c->mapstart) - prev_map_len - relro_len; +- if (file_len > 0) +- { +- lseek(fd, c->mapoff + relro_len + prev_map_len, SEEK_SET); +- if ( __read(fd, (void *)mapstart, file_len < len - mod ? file_len : len - mod) < 0) +- return DL_MAP_SEGMENTS_ERROR_READ_SEGMENT; +- } +- +- if ((c->prot & PROT_WRITE) == 0 && __mprotect((void *)mapstart, len - mod, c->prot) < 0) +- { +- return DL_MAP_SEGMENTS_ERROR_MPROTECT; +- } +- + map_addr = map_addr == 0 ? (void *)mapstart : map_addr; + mapstart += len - mod; + +-- +2.31.1 + diff --git a/glibc.spec b/glibc.spec index a433944..3369c9e 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 67 +Release: 68 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -218,6 +218,9 @@ Patch9012: fix-CVE-2019-1010023.patch Patch9013: fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch Patch9014: use-region-to-instead-of-country-for-extract-timezon.patch Patch9015: strcmp-delete-align-for-loop_aligned.patch +Patch9016: 0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch +Patch9017: 0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch +Patch9018: 0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch Obsoletes: nscd < 2.35 Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1289,6 +1292,9 @@ fi %endif %changelog +* Sat Mar 5 2022 zhoukang - 2.34-68 +- add dynamic linker load lib use hugepage + * Thu Mar 3 2022 qinyu - 2.34-67 - disable rseq by default with tunable -- Gitee From 972793895157bcfd9b3099b2a8d0c9cf54a36039 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Sat, 12 Mar 2022 15:50:55 +0800 Subject: [PATCH 68/70] malloc: use __get_nprocs replace __get_nprocs_sched. Signed-off-by: Yang Yanchao --- glibc.spec | 6 ++++- ...et_nprocs-replace-__get_nprocs_sched.patch | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch diff --git a/glibc.spec b/glibc.spec index 3369c9e..25f6572 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 68 +Release: 69 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -221,6 +221,7 @@ Patch9015: strcmp-delete-align-for-loop_aligned.patch Patch9016: 0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch Patch9017: 0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch Patch9018: 0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch +Patch9019: malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch Obsoletes: nscd < 2.35 Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1292,6 +1293,9 @@ fi %endif %changelog +* Sat Mar 12 2022 Yang Yanchao - 2.34-69 +- malloc: use __get_nprocs replace __get_nprocs_sched. + * Sat Mar 5 2022 zhoukang - 2.34-68 - add dynamic linker load lib use hugepage diff --git a/malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch b/malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch new file mode 100644 index 0000000..d5aa111 --- /dev/null +++ b/malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch @@ -0,0 +1,25 @@ +From f5545d74d6dc4d5036bee6a91cda14a51e2a0676 Mon Sep 17 00:00:00 2001 +From: Yang Yanchao +Date: Sat, 12 Mar 2022 15:30:17 +0800 +Subject: [PATCH] malloc: use __get_nprocs replace __get_nprocs_sched. + +--- + malloc/arena.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/malloc/arena.c b/malloc/arena.c +index f1f0af86..66748463 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -879,7 +879,7 @@ arena_get2 (size_t size, mstate avoid_arena) + narenas_limit = mp_.arena_max; + else if (narenas > mp_.arena_test) + { +- int n = __get_nprocs_sched (); ++ int n = __get_nprocs (); + + if (n >= 1) + narenas_limit = NARENAS_FROM_NCORES (n); +-- +2.33.0 + -- Gitee From 780caed580517889c570932e1d6d3c65fd3bae85 Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 15 Mar 2022 16:11:51 +0800 Subject: [PATCH 69/70] malloc: Improve Huge Page support backport the following seven patches malloc: Add madvise support for Transparent Huge Pages malloc: Add THP/madvise support for sbrk malloc: Move mmap logic to its own function malloc: Add Huge Page support for mmap malloc: Add Huge Page support to arenas malloc: Move MORECORE fallback mmap to sysmalloc_mmap_fallback malloc: Enable huge page support on main arena Signed-off-by: Yang Yanchao --- glibc.spec | 18 +- ...se-support-for-Transparent-Huge-Page.patch | 532 ++++++++++++++++++ ...loc-Add-THP-madvise-support-for-sbrk.patch | 111 ++++ ...-Move-mmap-logic-to-its-own-function.patch | 205 +++++++ ...alloc-Add-Huge-Page-support-for-mmap.patch | 476 ++++++++++++++++ ...lloc-Add-Huge-Page-support-to-arenas.patch | 338 +++++++++++ ...CORE-fallback-mmap-to-sysmalloc_mmap.patch | 119 ++++ ...able-huge-page-support-on-main-arena.patch | 86 +++ 8 files changed, 1884 insertions(+), 1 deletion(-) create mode 100644 malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch create mode 100644 malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch create mode 100644 malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch create mode 100644 malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch create mode 100644 malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch create mode 100644 malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch create mode 100644 malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch diff --git a/glibc.spec b/glibc.spec index 25f6572..70d41bb 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 69 +Release: 70 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -201,6 +201,13 @@ Patch115: x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch Patch116: x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch Patch117: x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch Patch118: Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch +Patch119: malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch +Patch120: malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch +Patch121: malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch +Patch122: malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch +Patch123: malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch +Patch124: malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch +Patch125: malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch @@ -1293,6 +1300,15 @@ fi %endif %changelog +* Tue Mar 15 2022 Yang Yanchao - 2.34-70 +- malloc: Add madvise support for Transparent Huge Pages +- malloc: Add THP/madvise support for sbrk +- malloc: Move mmap logic to its own function +- malloc: Add Huge Page support for mmap +- malloc: Add Huge Page support to arenas +- malloc: Move MORECORE fallback mmap to sysmalloc_mmap_fallback +- malloc: Enable huge page support on main arena + * Sat Mar 12 2022 Yang Yanchao - 2.34-69 - malloc: use __get_nprocs replace __get_nprocs_sched. diff --git a/malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch b/malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch new file mode 100644 index 0000000..1fc292a --- /dev/null +++ b/malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch @@ -0,0 +1,532 @@ +From 5f6d8d97c69748180f0031dfa385aff75062c4d5 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Fri, 13 Aug 2021 08:36:29 -0300 +Subject: [PATCH 1/7] malloc: Add madvise support for Transparent Huge Pages + +Linux Transparent Huge Pages (THP) current supports three different +states: 'never', 'madvise', and 'always'. The 'never' is +self-explanatory and 'always' will enable THP for all anonymous +pages. However, 'madvise' is still the default for some system and +for such case THP will be only used if the memory range is explicity +advertise by the program through a madvise(MADV_HUGEPAGE) call. + +To enable it a new tunable is provided, 'glibc.malloc.hugetlb', +where setting to a value diffent than 0 enables the madvise call. + +This patch issues the madvise(MADV_HUGEPAGE) call after a successful +mmap() call at sysmalloc() with sizes larger than the default huge +page size. The madvise() call is disable is system does not support +THP or if it has the mode set to "never" and on Linux only support +one page size for THP, even if the architecture supports multiple +sizes. + +To test is a new rule is added tests-malloc-hugetlb1, which run the +addes tests with the required GLIBC_TUNABLE setting. + +Checked on x86_64-linux-gnu. + +Reviewed-by: DJ Delorie +--- + NEWS | 5 ++ + Rules | 19 ++++++ + elf/dl-tunables.list | 5 ++ + elf/tst-rtld-list-tunables.exp | 1 + + malloc/Makefile | 16 +++++ + malloc/arena.c | 5 ++ + malloc/malloc-internal.h | 1 + + malloc/malloc.c | 47 ++++++++++++++ + manual/tunables.texi | 10 +++ + sysdeps/generic/Makefile | 8 +++ + sysdeps/generic/malloc-hugepages.c | 31 +++++++++ + sysdeps/generic/malloc-hugepages.h | 37 +++++++++++ + sysdeps/unix/sysv/linux/malloc-hugepages.c | 74 ++++++++++++++++++++++ + 13 files changed, 259 insertions(+) + create mode 100644 sysdeps/generic/malloc-hugepages.c + create mode 100644 sysdeps/generic/malloc-hugepages.h + create mode 100644 sysdeps/unix/sysv/linux/malloc-hugepages.c + +diff --git a/NEWS b/NEWS +index 2532565d77..3b94dd209c 100644 +--- a/NEWS ++++ b/NEWS +@@ -92,6 +92,11 @@ Major new features: + variables. The GNU C Library manual has details on integration of + Restartable Sequences. + ++* On Linux, a new tunable, glibc.malloc.hugetlb, can be used to ++ make malloc issue madvise plus MADV_HUGEPAGE on mmap and sbrk calls. ++ Setting this might improve performance with Transparent Huge Pages madvise ++ mode depending of the workload. ++ + Deprecated and removed features, and other changes affecting compatibility: + + * The function pthread_mutex_consistent_np has been deprecated; programs +diff --git a/Rules b/Rules +index b1137afe71..5f5d9ba4cc 100644 +--- a/Rules ++++ b/Rules +@@ -157,6 +157,7 @@ tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \ + $(tests-container:%=$(objpfx)%.out) \ + $(tests-mcheck:%=$(objpfx)%-mcheck.out) \ + $(tests-malloc-check:%=$(objpfx)%-malloc-check.out) \ ++ $(tests-malloc-hugetlb1:%=$(objpfx)%-malloc-hugetlb1.out) \ + $(tests-special) $(tests-printers-out) + xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special) + endif +@@ -168,6 +169,7 @@ tests-expected = + else + tests-expected = $(tests) $(tests-internal) $(tests-printers) \ + $(tests-container) $(tests-malloc-check:%=%-malloc-check) \ ++ $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1) \ + $(tests-mcheck:%=%-mcheck) + endif + tests: +@@ -196,6 +198,7 @@ binaries-pie-notests = + endif + binaries-mcheck-tests = $(tests-mcheck:%=%-mcheck) + binaries-malloc-check-tests = $(tests-malloc-check:%=%-malloc-check) ++binaries-malloc-hugetlb1-tests = $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1) + else + binaries-all-notests = + binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs) +@@ -207,6 +210,7 @@ binaries-pie-tests = + binaries-pie-notests = + binaries-mcheck-tests = + binaries-malloc-check-tests = ++binaries-malloc-hugetlb1-tests = + endif + + binaries-pie = $(binaries-pie-tests) $(binaries-pie-notests) +@@ -247,6 +251,14 @@ $(addprefix $(objpfx),$(binaries-malloc-check-tests)): %-malloc-check: %.o \ + $(+link-tests) + endif + ++ifneq "$(strip $(binaries-malloc-hugetlb1-tests))" "" ++$(addprefix $(objpfx),$(binaries-malloc-hugetlb1-tests)): %-malloc-hugetlb1: %.o \ ++ $(link-extra-libs-tests) \ ++ $(sort $(filter $(common-objpfx)lib%,$(link-libc))) \ ++ $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit) ++ $(+link-tests) ++endif ++ + ifneq "$(strip $(binaries-pie-tests))" "" + $(addprefix $(objpfx),$(binaries-pie-tests)): %: %.o \ + $(link-extra-libs-tests) \ +@@ -284,6 +296,13 @@ $(1)-malloc-check-ENV = MALLOC_CHECK_=3 \ + endef + $(foreach t,$(tests-malloc-check),$(eval $(call malloc-check-ENVS,$(t)))) + ++# All malloc-hugetlb1 tests will be run with GLIBC_TUNABLES=glibc.malloc.hugetlb=1 ++define malloc-hugetlb1-ENVS ++$(1)-malloc-hugetlb1-ENV += GLIBC_TUNABLES=glibc.malloc.hugetlb=1 ++endef ++$(foreach t,$(tests-malloc-hugetlb1),$(eval $(call malloc-hugetlb1-ENVS,$(t)))) ++ ++ + # mcheck tests need the debug DSO to support -lmcheck. + define mcheck-ENVS + $(1)-mcheck-ENV = LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so +diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list +index ffcd7f18d4..d1fd3f3e91 100644 +--- a/elf/dl-tunables.list ++++ b/elf/dl-tunables.list +@@ -92,6 +92,11 @@ glibc { + minval: 0 + security_level: SXID_IGNORE + } ++ hugetlb { ++ type: INT_32 ++ minval: 0 ++ maxval: 1 ++ } + } + cpu { + hwcap_mask { +diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp +index 44e4834cfb..d8e363f2c5 100644 +--- a/elf/tst-rtld-list-tunables.exp ++++ b/elf/tst-rtld-list-tunables.exp +@@ -1,6 +1,7 @@ + glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0x[f]+) + glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0x[f]+) + glibc.malloc.check: 0 (min: 0, max: 3) ++glibc.malloc.hugetlb: 0 (min: 0, max: 1) + glibc.malloc.mmap_max: 0 (min: 0, max: 2147483647) + glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0x[f]+) +diff --git a/malloc/Makefile b/malloc/Makefile +index 63cd7c0734..0137595e17 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -78,6 +78,22 @@ tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \ + tests-malloc-check = $(filter-out $(tests-exclude-malloc-check) \ + $(tests-static),$(tests)) + ++# Run all testes with GLIBC_TUNABLES=glibc.malloc.hugetlb=1 that check the ++# Transparent Huge Pages support. We need exclude some tests that define ++# the ENV vars. ++tests-exclude-hugetlb1 = \ ++ tst-compathooks-off \ ++ tst-compathooks-on \ ++ tst-interpose-nothread \ ++ tst-interpose-thread \ ++ tst-interpose-static-nothread \ ++ tst-interpose-static-thread \ ++ tst-malloc-usable \ ++ tst-malloc-usable-tunables \ ++ tst-mallocstate ++tests-malloc-hugetlb1 = \ ++ $(filter-out $(tests-exclude-hugetlb1), $(tests)) ++ + # -lmcheck needs __malloc_initialize_hook, which was deprecated in 2.24. + ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes) + # Tests that don't play well with mcheck. They are either bugs in mcheck or +diff --git a/malloc/arena.c b/malloc/arena.c +index 78ef4cf18c..cd00c7bef4 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -230,6 +230,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t) + TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t) + #endif + TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t) ++TUNABLE_CALLBACK_FNDECL (set_hugetlb, int32_t) + #else + /* Initialization routine. */ + #include +@@ -330,6 +331,7 @@ ptmalloc_init (void) + TUNABLE_CALLBACK (set_tcache_unsorted_limit)); + # endif + TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast)); ++ TUNABLE_GET (hugetlb, int32_t, TUNABLE_CALLBACK (set_hugetlb)); + #else + if (__glibc_likely (_environ != NULL)) + { +@@ -508,6 +510,9 @@ new_heap (size_t size, size_t top_pad) + __munmap (p2, HEAP_MAX_SIZE); + return 0; + } ++ ++ madvise_thp (p2, size); ++ + h = (heap_info *) p2; + h->size = size; + h->mprotect_size = size; +diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h +index 0c7b5a183c..7493e34d86 100644 +--- a/malloc/malloc-internal.h ++++ b/malloc/malloc-internal.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + /* Called in the parent process before a fork. */ + void __malloc_fork_lock_parent (void) attribute_hidden; +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 095d97a3be..c75841b841 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -1880,6 +1880,11 @@ struct malloc_par + INTERNAL_SIZE_T arena_test; + INTERNAL_SIZE_T arena_max; + ++#if HAVE_TUNABLES ++ /* Transparent Large Page support. */ ++ INTERNAL_SIZE_T thp_pagesize; ++#endif ++ + /* Memory map support */ + int n_mmaps; + int n_mmaps_max; +@@ -2008,6 +2013,20 @@ free_perturb (char *p, size_t n) + + #include + ++/* ----------- Routines dealing with transparent huge pages ----------- */ ++ ++static inline void ++madvise_thp (void *p, INTERNAL_SIZE_T size) ++{ ++#if HAVE_TUNABLES && defined (MADV_HUGEPAGE) ++ /* Do not consider areas smaller than a huge page or if the tunable is ++ not active. */ ++ if (mp_.thp_pagesize == 0 || size < mp_.thp_pagesize) ++ return; ++ __madvise (p, size, MADV_HUGEPAGE); ++#endif ++} ++ + /* ------------------- Support for multiple arenas -------------------- */ + #include "arena.c" + +@@ -2445,6 +2464,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + + if (mm != MAP_FAILED) + { ++ madvise_thp (mm, size); ++ + /* + The offset to the start of the mmapped region is stored + in the prev_size field of the chunk. This allows us to adjust +@@ -2606,6 +2627,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + if (size > 0) + { + brk = (char *) (MORECORE (size)); ++ if (brk != (char *) (MORECORE_FAILURE)) ++ madvise_thp (brk, size); + LIBC_PROBE (memory_sbrk_more, 2, brk, size); + } + +@@ -2637,6 +2660,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + + if (mbrk != MAP_FAILED) + { ++ madvise_thp (mbrk, size); ++ + /* We do not need, and cannot use, another sbrk call to find end */ + brk = mbrk; + snd_brk = brk + size; +@@ -2748,6 +2773,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + correction = 0; + snd_brk = (char *) (MORECORE (0)); + } ++ else ++ madvise_thp (snd_brk, correction); + } + + /* handle non-contiguous cases */ +@@ -2988,6 +3015,8 @@ mremap_chunk (mchunkptr p, size_t new_size) + if (cp == MAP_FAILED) + return 0; + ++ madvise_thp (cp, new_size); ++ + p = (mchunkptr) (cp + offset); + + assert (aligned_OK (chunk2mem (p))); +@@ -5316,6 +5345,24 @@ do_set_mxfast (size_t value) + return 0; + } + ++#if HAVE_TUNABLES ++static __always_inline int ++do_set_hugetlb (int32_t value) ++{ ++ if (value == 1) ++ { ++ enum malloc_thp_mode_t thp_mode = __malloc_thp_mode (); ++ /* ++ Only enable THP madvise usage if system does support it and ++ has 'madvise' mode. Otherwise the madvise() call is wasteful. ++ */ ++ if (thp_mode == malloc_thp_mode_madvise) ++ mp_.thp_pagesize = __malloc_default_thp_pagesize (); ++ } ++ return 0; ++} ++#endif ++ + int + __libc_mallopt (int param_number, int value) + { +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 28ff502990..9ca6e3f603 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -270,6 +270,16 @@ pointer, so add 4 on 32-bit systems or 8 on 64-bit systems to the size + passed to @code{malloc} for the largest bin size to enable. + @end deftp + ++@deftp Tunable glibc.malloc.hugetlb ++This tunable controls the usage of Huge Pages on @code{malloc} calls. The ++default value is @code{0}, which disables any additional support on ++@code{malloc}. ++ ++Setting its value to @code{1} enables the use of @code{madvise} with ++@code{MADV_HUGEPAGE} after memory allocation with @code{mmap}. It is enabled ++only if the system supports Transparent Huge Page (currently only on Linux). ++@end deftp ++ + @node Dynamic Linking Tunables + @section Dynamic Linking Tunables + @cindex dynamic linking tunables +diff --git a/sysdeps/generic/Makefile b/sysdeps/generic/Makefile +index a209e85cc4..8eef83c94d 100644 +--- a/sysdeps/generic/Makefile ++++ b/sysdeps/generic/Makefile +@@ -27,3 +27,11 @@ sysdep_routines += framestate unwind-pe + shared-only-routines += framestate unwind-pe + endif + endif ++ ++ifeq ($(subdir),malloc) ++sysdep_malloc_debug_routines += malloc-hugepages ++endif ++ ++ifeq ($(subdir),misc) ++sysdep_routines += malloc-hugepages ++endif +diff --git a/sysdeps/generic/malloc-hugepages.c b/sysdeps/generic/malloc-hugepages.c +new file mode 100644 +index 0000000000..8fb459a263 +--- /dev/null ++++ b/sysdeps/generic/malloc-hugepages.c +@@ -0,0 +1,31 @@ ++/* Huge Page support. Generic implementation. ++ Copyright (C) 2021 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; see the file COPYING.LIB. If ++ not, see . */ ++ ++#include ++ ++unsigned long int ++__malloc_default_thp_pagesize (void) ++{ ++ return 0; ++} ++ ++enum malloc_thp_mode_t ++__malloc_thp_mode (void) ++{ ++ return malloc_thp_mode_not_supported; ++} +diff --git a/sysdeps/generic/malloc-hugepages.h b/sysdeps/generic/malloc-hugepages.h +new file mode 100644 +index 0000000000..f5a442e328 +--- /dev/null ++++ b/sysdeps/generic/malloc-hugepages.h +@@ -0,0 +1,37 @@ ++/* Malloc huge page support. Generic implementation. ++ Copyright (C) 2021 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; see the file COPYING.LIB. If ++ not, see . */ ++ ++#ifndef _MALLOC_HUGEPAGES_H ++#define _MALLOC_HUGEPAGES_H ++ ++#include ++ ++/* Return the default transparent huge page size. */ ++unsigned long int __malloc_default_thp_pagesize (void) attribute_hidden; ++ ++enum malloc_thp_mode_t ++{ ++ malloc_thp_mode_always, ++ malloc_thp_mode_madvise, ++ malloc_thp_mode_never, ++ malloc_thp_mode_not_supported ++}; ++ ++enum malloc_thp_mode_t __malloc_thp_mode (void) attribute_hidden; ++ ++#endif /* _MALLOC_HUGEPAGES_H */ +diff --git a/sysdeps/unix/sysv/linux/malloc-hugepages.c b/sysdeps/unix/sysv/linux/malloc-hugepages.c +new file mode 100644 +index 0000000000..7497e07260 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/malloc-hugepages.c +@@ -0,0 +1,74 @@ ++/* Huge Page support. Linux implementation. ++ Copyright (C) 2021 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; see the file COPYING.LIB. If ++ not, see . */ ++ ++#include ++#include ++#include ++ ++unsigned long int ++__malloc_default_thp_pagesize (void) ++{ ++ int fd = __open64_nocancel ( ++ "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY); ++ if (fd == -1) ++ return 0; ++ ++ char str[INT_BUFSIZE_BOUND (unsigned long int)]; ++ ssize_t s = __read_nocancel (fd, str, sizeof (str)); ++ __close_nocancel (fd); ++ if (s < 0) ++ return 0; ++ ++ unsigned long int r = 0; ++ for (ssize_t i = 0; i < s; i++) ++ { ++ if (str[i] == '\n') ++ break; ++ r *= 10; ++ r += str[i] - '0'; ++ } ++ return r; ++} ++ ++enum malloc_thp_mode_t ++__malloc_thp_mode (void) ++{ ++ int fd = __open64_nocancel ("/sys/kernel/mm/transparent_hugepage/enabled", ++ O_RDONLY); ++ if (fd == -1) ++ return malloc_thp_mode_not_supported; ++ ++ static const char mode_always[] = "[always] madvise never\n"; ++ static const char mode_madvise[] = "always [madvise] never\n"; ++ static const char mode_never[] = "always madvise [never]\n"; ++ ++ char str[sizeof(mode_always)]; ++ ssize_t s = __read_nocancel (fd, str, sizeof (str)); ++ __close_nocancel (fd); ++ ++ if (s == sizeof (mode_always) - 1) ++ { ++ if (strcmp (str, mode_always) == 0) ++ return malloc_thp_mode_always; ++ else if (strcmp (str, mode_madvise) == 0) ++ return malloc_thp_mode_madvise; ++ else if (strcmp (str, mode_never) == 0) ++ return malloc_thp_mode_never; ++ } ++ return malloc_thp_mode_not_supported; ++} +-- +2.33.0 + diff --git a/malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch b/malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch new file mode 100644 index 0000000..58f2abf --- /dev/null +++ b/malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch @@ -0,0 +1,111 @@ +From 7478c9959ae409f7b3d63146943575d6ee745352 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Fri, 13 Aug 2021 10:06:04 -0300 +Subject: [PATCH 2/7] malloc: Add THP/madvise support for sbrk + +To increase effectiveness with Transparent Huge Page with madvise, the +large page size is use instead page size for sbrk increment for the +main arena. + +Checked on x86_64-linux-gnu. + +Reviewed-by: DJ Delorie +--- + include/libc-pointer-arith.h | 8 ++++++++ + malloc/malloc.c | 34 +++++++++++++++++++++++++++++----- + 2 files changed, 37 insertions(+), 5 deletions(-) + +diff --git a/include/libc-pointer-arith.h b/include/libc-pointer-arith.h +index 04ba537617..55dccc10ac 100644 +--- a/include/libc-pointer-arith.h ++++ b/include/libc-pointer-arith.h +@@ -60,4 +60,12 @@ + #define PTR_ALIGN_UP(base, size) \ + ((__typeof__ (base)) ALIGN_UP ((uintptr_t) (base), (size))) + ++/* Check if BASE is aligned on SIZE */ ++#define PTR_IS_ALIGNED(base, size) \ ++ ((((uintptr_t) (base)) & (size - 1)) == 0) ++ ++/* Returns the ptrdiff_t diference between P1 and P2. */ ++#define PTR_DIFF(p1, p2) \ ++ ((ptrdiff_t)((uintptr_t)(p1) - (uintptr_t)(p2))) ++ + #endif +diff --git a/malloc/malloc.c b/malloc/malloc.c +index c75841b841..57db4dd9a5 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2023,6 +2023,16 @@ madvise_thp (void *p, INTERNAL_SIZE_T size) + not active. */ + if (mp_.thp_pagesize == 0 || size < mp_.thp_pagesize) + return; ++ ++ /* Linux requires the input address to be page-aligned, and unaligned ++ inputs happens only for initial data segment. */ ++ if (__glibc_unlikely (!PTR_IS_ALIGNED (p, GLRO (dl_pagesize)))) ++ { ++ void *q = PTR_ALIGN_DOWN (p, GLRO (dl_pagesize)); ++ size += PTR_DIFF (p, q); ++ p = q; ++ } ++ + __madvise (p, size, MADV_HUGEPAGE); + #endif + } +@@ -2609,14 +2619,25 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + size -= old_size; + + /* +- Round to a multiple of page size. ++ Round to a multiple of page size or huge page size. + If MORECORE is not contiguous, this ensures that we only call it + with whole-page arguments. And if MORECORE is contiguous and + this is not first time through, this preserves page-alignment of + previous calls. Otherwise, we correct to page-align below. + */ + +- size = ALIGN_UP (size, pagesize); ++#if HAVE_TUNABLES && defined (MADV_HUGEPAGE) ++ /* Defined in brk.c. */ ++ extern void *__curbrk; ++ if (__glibc_unlikely (mp_.thp_pagesize != 0)) ++ { ++ uintptr_t top = ALIGN_UP ((uintptr_t) __curbrk + size, ++ mp_.thp_pagesize); ++ size = top - (uintptr_t) __curbrk; ++ } ++ else ++#endif ++ size = ALIGN_UP (size, GLRO(dl_pagesize)); + + /* + Don't try to call MORECORE if argument is so big as to appear +@@ -2899,10 +2920,8 @@ systrim (size_t pad, mstate av) + long released; /* Amount actually released */ + char *current_brk; /* address returned by pre-check sbrk call */ + char *new_brk; /* address returned by post-check sbrk call */ +- size_t pagesize; + long top_area; + +- pagesize = GLRO (dl_pagesize); + top_size = chunksize (av->top); + + top_area = top_size - MINSIZE - 1; +@@ -2910,7 +2929,12 @@ systrim (size_t pad, mstate av) + return 0; + + /* Release in pagesize units and round down to the nearest page. */ +- extra = ALIGN_DOWN(top_area - pad, pagesize); ++#if HAVE_TUNABLES && defined (MADV_HUGEPAGE) ++ if (__glibc_unlikely (mp_.thp_pagesize != 0)) ++ extra = ALIGN_DOWN (top_area - pad, mp_.thp_pagesize); ++ else ++#endif ++ extra = ALIGN_DOWN (top_area - pad, GLRO(dl_pagesize)); + + if (extra == 0) + return 0; +-- +2.33.0 + diff --git a/malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch b/malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch new file mode 100644 index 0000000..5b1768b --- /dev/null +++ b/malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch @@ -0,0 +1,205 @@ +From 6cc3ccc67e0dda654fc839377af2818a296f0007 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 16 Aug 2021 11:14:20 -0300 +Subject: [PATCH 3/7] malloc: Move mmap logic to its own function + +So it can be used with different pagesize and flags. + +Reviewed-by: DJ Delorie +--- + malloc/malloc.c | 164 ++++++++++++++++++++++++++---------------------- + 1 file changed, 88 insertions(+), 76 deletions(-) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 57db4dd9a5..6b6ec53db1 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2412,6 +2412,85 @@ do_check_malloc_state (mstate av) + be extended or replaced. + */ + ++static void * ++sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av) ++{ ++ long int size; ++ ++ /* ++ Round up size to nearest page. For mmapped chunks, the overhead is one ++ SIZE_SZ unit larger than for normal chunks, because there is no ++ following chunk whose prev_size field could be used. ++ ++ See the front_misalign handling below, for glibc there is no need for ++ further alignments unless we have have high alignment. ++ */ ++ if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ) ++ size = ALIGN_UP (nb + SIZE_SZ, pagesize); ++ else ++ size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize); ++ ++ /* Don't try if size wraps around 0. */ ++ if ((unsigned long) (size) <= (unsigned long) (nb)) ++ return MAP_FAILED; ++ ++ char *mm = (char *) MMAP (0, size, ++ mtag_mmap_flags | PROT_READ | PROT_WRITE, ++ extra_flags); ++ if (mm == MAP_FAILED) ++ return mm; ++ ++ madvise_thp (mm, size); ++ ++ /* ++ The offset to the start of the mmapped region is stored in the prev_size ++ field of the chunk. This allows us to adjust returned start address to ++ meet alignment requirements here and in memalign(), and still be able to ++ compute proper address argument for later munmap in free() and realloc(). ++ */ ++ ++ INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */ ++ ++ if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ) ++ { ++ /* For glibc, chunk2mem increases the address by CHUNK_HDR_SZ and ++ MALLOC_ALIGN_MASK is CHUNK_HDR_SZ-1. Each mmap'ed area is page ++ aligned and therefore definitely MALLOC_ALIGN_MASK-aligned. */ ++ assert (((INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK) == 0); ++ front_misalign = 0; ++ } ++ else ++ front_misalign = (INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK; ++ ++ mchunkptr p; /* the allocated/returned chunk */ ++ ++ if (front_misalign > 0) ++ { ++ ptrdiff_t correction = MALLOC_ALIGNMENT - front_misalign; ++ p = (mchunkptr) (mm + correction); ++ set_prev_size (p, correction); ++ set_head (p, (size - correction) | IS_MMAPPED); ++ } ++ else ++ { ++ p = (mchunkptr) mm; ++ set_prev_size (p, 0); ++ set_head (p, size | IS_MMAPPED); ++ } ++ ++ /* update statistics */ ++ int new = atomic_exchange_and_add (&mp_.n_mmaps, 1) + 1; ++ atomic_max (&mp_.max_n_mmaps, new); ++ ++ unsigned long sum; ++ sum = atomic_exchange_and_add (&mp_.mmapped_mem, size) + size; ++ atomic_max (&mp_.max_mmapped_mem, sum); ++ ++ check_chunk (av, p); ++ ++ return chunk2mem (p); ++} ++ + static void * + sysmalloc (INTERNAL_SIZE_T nb, mstate av) + { +@@ -2449,81 +2528,10 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold) + && (mp_.n_mmaps < mp_.n_mmaps_max))) + { +- char *mm; /* return value from mmap call*/ +- +- try_mmap: +- /* +- Round up size to nearest page. For mmapped chunks, the overhead +- is one SIZE_SZ unit larger than for normal chunks, because there +- is no following chunk whose prev_size field could be used. +- +- See the front_misalign handling below, for glibc there is no +- need for further alignments unless we have have high alignment. +- */ +- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ) +- size = ALIGN_UP (nb + SIZE_SZ, pagesize); +- else +- size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize); ++ char *mm = sysmalloc_mmap (nb, pagesize, 0, av); ++ if (mm != MAP_FAILED) ++ return mm; + tried_mmap = true; +- +- /* Don't try if size wraps around 0 */ +- if ((unsigned long) (size) > (unsigned long) (nb)) +- { +- mm = (char *) (MMAP (0, size, +- mtag_mmap_flags | PROT_READ | PROT_WRITE, 0)); +- +- if (mm != MAP_FAILED) +- { +- madvise_thp (mm, size); +- +- /* +- The offset to the start of the mmapped region is stored +- in the prev_size field of the chunk. This allows us to adjust +- returned start address to meet alignment requirements here +- and in memalign(), and still be able to compute proper +- address argument for later munmap in free() and realloc(). +- */ +- +- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ) +- { +- /* For glibc, chunk2mem increases the address by +- CHUNK_HDR_SZ and MALLOC_ALIGN_MASK is +- CHUNK_HDR_SZ-1. Each mmap'ed area is page +- aligned and therefore definitely +- MALLOC_ALIGN_MASK-aligned. */ +- assert (((INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK) == 0); +- front_misalign = 0; +- } +- else +- front_misalign = (INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK; +- if (front_misalign > 0) +- { +- correction = MALLOC_ALIGNMENT - front_misalign; +- p = (mchunkptr) (mm + correction); +- set_prev_size (p, correction); +- set_head (p, (size - correction) | IS_MMAPPED); +- } +- else +- { +- p = (mchunkptr) mm; +- set_prev_size (p, 0); +- set_head (p, size | IS_MMAPPED); +- } +- +- /* update statistics */ +- +- int new = atomic_exchange_and_add (&mp_.n_mmaps, 1) + 1; +- atomic_max (&mp_.max_n_mmaps, new); +- +- unsigned long sum; +- sum = atomic_exchange_and_add (&mp_.mmapped_mem, size) + size; +- atomic_max (&mp_.max_mmapped_mem, sum); +- +- check_chunk (av, p); +- +- return chunk2mem (p); +- } +- } + } + + /* There are no usable arenas and mmap also failed. */ +@@ -2600,8 +2608,12 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + } + } + else if (!tried_mmap) +- /* We can at least try to use to mmap memory. */ +- goto try_mmap; ++ { ++ /* We can at least try to use to mmap memory. */ ++ char *mm = sysmalloc_mmap (nb, pagesize, 0, av); ++ if (mm != MAP_FAILED) ++ return mm; ++ } + } + else /* av == main_arena */ + +-- +2.33.0 + diff --git a/malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch b/malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch new file mode 100644 index 0000000..1969a1f --- /dev/null +++ b/malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch @@ -0,0 +1,476 @@ +From 98d5fcb8d099a1a868e032c89891c395a2f365c5 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 16 Aug 2021 15:08:27 -0300 +Subject: [PATCH 4/7] malloc: Add Huge Page support for mmap + +With the morecore hook removed, there is not easy way to provide huge +pages support on with glibc allocator without resorting to transparent +huge pages. And some users and programs do prefer to use the huge pages +directly instead of THP for multiple reasons: no splitting, re-merging +by the VM, no TLB shootdowns for running processes, fast allocation +from the reserve pool, no competition with the rest of the processes +unlike THP, no swapping all, etc. + +This patch extends the 'glibc.malloc.hugetlb' tunable: the value +'2' means to use huge pages directly with the system default size, +while a positive value means and specific page size that is matched +against the supported ones by the system. + +Currently only memory allocated on sysmalloc() is handled, the arenas +still uses the default system page size. + +To test is a new rule is added tests-malloc-hugetlb2, which run the +addes tests with the required GLIBC_TUNABLE setting. On systems without +a reserved huge pages pool, is just stress the mmap(MAP_HUGETLB) +allocation failure. To improve test coverage it is required to create +a pool with some allocated pages. + +Checked on x86_64-linux-gnu. + +Reviewed-by: DJ Delorie +--- + NEWS | 8 +- + Rules | 17 +++ + elf/dl-tunables.list | 3 +- + elf/tst-rtld-list-tunables.exp | 2 +- + malloc/Makefile | 8 +- + malloc/arena.c | 4 +- + malloc/malloc.c | 31 ++++- + manual/tunables.texi | 7 ++ + sysdeps/generic/malloc-hugepages.c | 8 ++ + sysdeps/generic/malloc-hugepages.h | 7 ++ + sysdeps/unix/sysv/linux/malloc-hugepages.c | 127 +++++++++++++++++++++ + 11 files changed, 207 insertions(+), 15 deletions(-) + +diff --git a/NEWS b/NEWS +index 3b94dd209c..c7200cd4e8 100644 +--- a/NEWS ++++ b/NEWS +@@ -93,9 +93,11 @@ Major new features: + Restartable Sequences. + + * On Linux, a new tunable, glibc.malloc.hugetlb, can be used to +- make malloc issue madvise plus MADV_HUGEPAGE on mmap and sbrk calls. +- Setting this might improve performance with Transparent Huge Pages madvise +- mode depending of the workload. ++ either make malloc issue madvise plus MADV_HUGEPAGE on mmap and sbrk ++ or to use huge pages directly with mmap calls with the MAP_HUGETLB ++ flags). The former can improve performance when Transparent Huge Pages ++ is set to 'madvise' mode while the latter uses the system reserved ++ huge pages. + + Deprecated and removed features, and other changes affecting compatibility: + +diff --git a/Rules b/Rules +index 5f5d9ba4cc..be34982daa 100644 +--- a/Rules ++++ b/Rules +@@ -158,6 +158,7 @@ tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \ + $(tests-mcheck:%=$(objpfx)%-mcheck.out) \ + $(tests-malloc-check:%=$(objpfx)%-malloc-check.out) \ + $(tests-malloc-hugetlb1:%=$(objpfx)%-malloc-hugetlb1.out) \ ++ $(tests-malloc-hugetlb2:%=$(objpfx)%-malloc-hugetlb2.out) \ + $(tests-special) $(tests-printers-out) + xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special) + endif +@@ -170,6 +171,7 @@ else + tests-expected = $(tests) $(tests-internal) $(tests-printers) \ + $(tests-container) $(tests-malloc-check:%=%-malloc-check) \ + $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1) \ ++ $(tests-malloc-hugetlb2:%=%-malloc-hugetlb2) \ + $(tests-mcheck:%=%-mcheck) + endif + tests: +@@ -199,6 +201,7 @@ endif + binaries-mcheck-tests = $(tests-mcheck:%=%-mcheck) + binaries-malloc-check-tests = $(tests-malloc-check:%=%-malloc-check) + binaries-malloc-hugetlb1-tests = $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1) ++binaries-malloc-hugetlb2-tests = $(tests-malloc-hugetlb2:%=%-malloc-hugetlb2) + else + binaries-all-notests = + binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs) +@@ -211,6 +214,7 @@ binaries-pie-notests = + binaries-mcheck-tests = + binaries-malloc-check-tests = + binaries-malloc-hugetlb1-tests = ++binaries-malloc-hugetlb2-tests = + endif + + binaries-pie = $(binaries-pie-tests) $(binaries-pie-notests) +@@ -259,6 +263,14 @@ $(addprefix $(objpfx),$(binaries-malloc-hugetlb1-tests)): %-malloc-hugetlb1: %.o + $(+link-tests) + endif + ++ifneq "$(strip $(binaries-malloc-hugetlb2-tests))" "" ++$(addprefix $(objpfx),$(binaries-malloc-hugetlb2-tests)): %-malloc-hugetlb2: %.o \ ++ $(link-extra-libs-tests) \ ++ $(sort $(filter $(common-objpfx)lib%,$(link-libc))) \ ++ $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit) ++ $(+link-tests) ++endif ++ + ifneq "$(strip $(binaries-pie-tests))" "" + $(addprefix $(objpfx),$(binaries-pie-tests)): %: %.o \ + $(link-extra-libs-tests) \ +@@ -302,6 +314,11 @@ $(1)-malloc-hugetlb1-ENV += GLIBC_TUNABLES=glibc.malloc.hugetlb=1 + endef + $(foreach t,$(tests-malloc-hugetlb1),$(eval $(call malloc-hugetlb1-ENVS,$(t)))) + ++# All malloc-hugetlb2 tests will be run with GLIBC_TUNABLE=glibc.malloc.hugetlb=2 ++define malloc-hugetlb2-ENVS ++$(1)-malloc-hugetlb2-ENV += GLIBC_TUNABLES=glibc.malloc.hugetlb=2 ++endef ++$(foreach t,$(tests-malloc-hugetlb2),$(eval $(call malloc-hugetlb2-ENVS,$(t)))) + + # mcheck tests need the debug DSO to support -lmcheck. + define mcheck-ENVS +diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list +index d1fd3f3e91..845d521a43 100644 +--- a/elf/dl-tunables.list ++++ b/elf/dl-tunables.list +@@ -93,9 +93,8 @@ glibc { + security_level: SXID_IGNORE + } + hugetlb { +- type: INT_32 ++ type: SIZE_T + minval: 0 +- maxval: 1 + } + } + cpu { +diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp +index d8e363f2c5..cdfdb56a94 100644 +--- a/elf/tst-rtld-list-tunables.exp ++++ b/elf/tst-rtld-list-tunables.exp +@@ -1,7 +1,7 @@ + glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0x[f]+) + glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0x[f]+) + glibc.malloc.check: 0 (min: 0, max: 3) +-glibc.malloc.hugetlb: 0 (min: 0, max: 1) ++glibc.malloc.hugetlb: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.mmap_max: 0 (min: 0, max: 2147483647) + glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0x[f]+) +diff --git a/malloc/Makefile b/malloc/Makefile +index 0137595e17..e9a6666d22 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -78,9 +78,9 @@ tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \ + tests-malloc-check = $(filter-out $(tests-exclude-malloc-check) \ + $(tests-static),$(tests)) + +-# Run all testes with GLIBC_TUNABLES=glibc.malloc.hugetlb=1 that check the +-# Transparent Huge Pages support. We need exclude some tests that define +-# the ENV vars. ++# Run all tests with GLIBC_TUNABLES=glibc.malloc.hugetlb={1,2} which check ++# the Transparent Huge Pages support (1) or automatic huge page support (2). ++# We need exclude some tests that define the ENV vars. + tests-exclude-hugetlb1 = \ + tst-compathooks-off \ + tst-compathooks-on \ +@@ -93,6 +93,8 @@ tests-exclude-hugetlb1 = \ + tst-mallocstate + tests-malloc-hugetlb1 = \ + $(filter-out $(tests-exclude-hugetlb1), $(tests)) ++tests-malloc-hugetlb2 = \ ++ $(filter-out $(tests-exclude-hugetlb1), $(tests)) + + # -lmcheck needs __malloc_initialize_hook, which was deprecated in 2.24. + ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes) +diff --git a/malloc/arena.c b/malloc/arena.c +index cd00c7bef4..9a6e1af2bd 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -230,7 +230,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t) + TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t) + #endif + TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t) +-TUNABLE_CALLBACK_FNDECL (set_hugetlb, int32_t) ++TUNABLE_CALLBACK_FNDECL (set_hugetlb, size_t) + #else + /* Initialization routine. */ + #include +@@ -331,7 +331,7 @@ ptmalloc_init (void) + TUNABLE_CALLBACK (set_tcache_unsorted_limit)); + # endif + TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast)); +- TUNABLE_GET (hugetlb, int32_t, TUNABLE_CALLBACK (set_hugetlb)); ++ TUNABLE_GET (hugetlb, size_t, TUNABLE_CALLBACK (set_hugetlb)); + #else + if (__glibc_likely (_environ != NULL)) + { +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 6b6ec53db1..75efdc2ee7 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -1883,6 +1883,10 @@ struct malloc_par + #if HAVE_TUNABLES + /* Transparent Large Page support. */ + INTERNAL_SIZE_T thp_pagesize; ++ /* A value different than 0 means to align mmap allocation to hp_pagesize ++ add hp_flags on flags. */ ++ INTERNAL_SIZE_T hp_pagesize; ++ int hp_flags; + #endif + + /* Memory map support */ +@@ -2440,7 +2444,10 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av) + if (mm == MAP_FAILED) + return mm; + +- madvise_thp (mm, size); ++#ifdef MAP_HUGETLB ++ if (!(extra_flags & MAP_HUGETLB)) ++ madvise_thp (mm, size); ++#endif + + /* + The offset to the start of the mmapped region is stored in the prev_size +@@ -2528,7 +2535,18 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold) + && (mp_.n_mmaps < mp_.n_mmaps_max))) + { +- char *mm = sysmalloc_mmap (nb, pagesize, 0, av); ++ char *mm; ++#if HAVE_TUNABLES ++ if (mp_.hp_pagesize > 0 && nb >= mp_.hp_pagesize) ++ { ++ /* There is no need to isse the THP madvise call if Huge Pages are ++ used directly. */ ++ mm = sysmalloc_mmap (nb, mp_.hp_pagesize, mp_.hp_flags, av); ++ if (mm != MAP_FAILED) ++ return mm; ++ } ++#endif ++ mm = sysmalloc_mmap (nb, pagesize, 0, av); + if (mm != MAP_FAILED) + return mm; + tried_mmap = true; +@@ -2609,7 +2627,9 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + } + else if (!tried_mmap) + { +- /* We can at least try to use to mmap memory. */ ++ /* We can at least try to use to mmap memory. If new_heap fails ++ it is unlikely that trying to allocate huge pages will ++ succeed. */ + char *mm = sysmalloc_mmap (nb, pagesize, 0, av); + if (mm != MAP_FAILED) + return mm; +@@ -5383,7 +5403,7 @@ do_set_mxfast (size_t value) + + #if HAVE_TUNABLES + static __always_inline int +-do_set_hugetlb (int32_t value) ++do_set_hugetlb (size_t value) + { + if (value == 1) + { +@@ -5395,6 +5415,9 @@ do_set_hugetlb (int32_t value) + if (thp_mode == malloc_thp_mode_madvise) + mp_.thp_pagesize = __malloc_default_thp_pagesize (); + } ++ else if (value >= 2) ++ __malloc_hugepage_config (value == 2 ? 0 : value, &mp_.hp_pagesize, ++ &mp_.hp_flags); + return 0; + } + #endif +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 9ca6e3f603..58a47b2e9b 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -278,6 +278,13 @@ default value is @code{0}, which disables any additional support on + Setting its value to @code{1} enables the use of @code{madvise} with + @code{MADV_HUGEPAGE} after memory allocation with @code{mmap}. It is enabled + only if the system supports Transparent Huge Page (currently only on Linux). ++ ++Setting its value to @code{2} enables the use of Huge Page directly with ++@code{mmap} with the use of @code{MAP_HUGETLB} flag. The huge page size ++to use will be the default one provided by the system. A value larger than ++@code{2} specifies huge page size, which will be matched against the system ++supported ones. If provided value is invalid, @code{MAP_HUGETLB} will not ++be used. + @end deftp + + @node Dynamic Linking Tunables +diff --git a/sysdeps/generic/malloc-hugepages.c b/sysdeps/generic/malloc-hugepages.c +index 8fb459a263..946284a33c 100644 +--- a/sysdeps/generic/malloc-hugepages.c ++++ b/sysdeps/generic/malloc-hugepages.c +@@ -29,3 +29,11 @@ __malloc_thp_mode (void) + { + return malloc_thp_mode_not_supported; + } ++ ++/* Return the default transparent huge page size. */ ++void ++__malloc_hugepage_config (size_t requested, size_t *pagesize, int *flags) ++{ ++ *pagesize = 0; ++ *flags = 0; ++} +diff --git a/sysdeps/generic/malloc-hugepages.h b/sysdeps/generic/malloc-hugepages.h +index f5a442e328..75cda3796a 100644 +--- a/sysdeps/generic/malloc-hugepages.h ++++ b/sysdeps/generic/malloc-hugepages.h +@@ -34,4 +34,11 @@ enum malloc_thp_mode_t + + enum malloc_thp_mode_t __malloc_thp_mode (void) attribute_hidden; + ++/* Return the supported huge page size from the REQUESTED sizes on PAGESIZE ++ along with the required extra mmap flags on FLAGS, Requesting the value ++ of 0 returns the default huge page size, otherwise the value will be ++ matched against the sizes supported by the system. */ ++void __malloc_hugepage_config (size_t requested, size_t *pagesize, int *flags) ++ attribute_hidden; ++ + #endif /* _MALLOC_HUGEPAGES_H */ +diff --git a/sysdeps/unix/sysv/linux/malloc-hugepages.c b/sysdeps/unix/sysv/linux/malloc-hugepages.c +index 7497e07260..0e05291d61 100644 +--- a/sysdeps/unix/sysv/linux/malloc-hugepages.c ++++ b/sysdeps/unix/sysv/linux/malloc-hugepages.c +@@ -17,8 +17,10 @@ + not, see . */ + + #include ++#include + #include + #include ++#include + + unsigned long int + __malloc_default_thp_pagesize (void) +@@ -72,3 +74,128 @@ __malloc_thp_mode (void) + } + return malloc_thp_mode_not_supported; + } ++ ++static size_t ++malloc_default_hugepage_size (void) ++{ ++ int fd = __open64_nocancel ("/proc/meminfo", O_RDONLY); ++ if (fd == -1) ++ return 0; ++ ++ size_t hpsize = 0; ++ ++ char buf[512]; ++ off64_t off = 0; ++ while (1) ++ { ++ ssize_t r = __pread64_nocancel (fd, buf, sizeof (buf) - 1, off); ++ if (r < 0) ++ break; ++ buf[r] = '\0'; ++ ++ /* If the tag is not found, read the last line again. */ ++ const char *s = strstr (buf, "Hugepagesize:"); ++ if (s == NULL) ++ { ++ char *nl = strrchr (buf, '\n'); ++ if (nl == NULL) ++ break; ++ off += (nl + 1) - buf; ++ continue; ++ } ++ ++ /* The default huge page size is in the form: ++ Hugepagesize: NUMBER kB */ ++ s += sizeof ("Hugepagesize: ") - 1; ++ for (int i = 0; (s[i] >= '0' && s[i] <= '9') || s[i] == ' '; i++) ++ { ++ if (s[i] == ' ') ++ continue; ++ hpsize *= 10; ++ hpsize += s[i] - '0'; ++ } ++ hpsize *= 1024; ++ break; ++ } ++ ++ __close_nocancel (fd); ++ ++ return hpsize; ++} ++ ++static inline int ++hugepage_flags (size_t pagesize) ++{ ++ return MAP_HUGETLB | (__builtin_ctzll (pagesize) << MAP_HUGE_SHIFT); ++} ++ ++void ++__malloc_hugepage_config (size_t requested, size_t *pagesize, int *flags) ++{ ++ *pagesize = 0; ++ *flags = 0; ++ ++ if (requested == 0) ++ { ++ *pagesize = malloc_default_hugepage_size (); ++ if (*pagesize != 0) ++ *flags = hugepage_flags (*pagesize); ++ return; ++ } ++ ++ /* Each entry represents a supported huge page in the form of: ++ hugepages-kB. */ ++ int dirfd = __open64_nocancel ("/sys/kernel/mm/hugepages", ++ O_RDONLY | O_DIRECTORY, 0); ++ if (dirfd == -1) ++ return; ++ ++ char buffer[1024]; ++ while (true) ++ { ++#if !IS_IN(libc) ++# define __getdents64 getdents64 ++#endif ++ ssize_t ret = __getdents64 (dirfd, buffer, sizeof (buffer)); ++ if (ret == -1) ++ break; ++ else if (ret == 0) ++ break; ++ ++ bool found = false; ++ char *begin = buffer, *end = buffer + ret; ++ while (begin != end) ++ { ++ unsigned short int d_reclen; ++ memcpy (&d_reclen, begin + offsetof (struct dirent64, d_reclen), ++ sizeof (d_reclen)); ++ const char *dname = begin + offsetof (struct dirent64, d_name); ++ begin += d_reclen; ++ ++ if (dname[0] == '.' ++ || strncmp (dname, "hugepages-", sizeof ("hugepages-") - 1) != 0) ++ continue; ++ ++ size_t hpsize = 0; ++ const char *sizestr = dname + sizeof ("hugepages-") - 1; ++ for (int i = 0; sizestr[i] >= '0' && sizestr[i] <= '9'; i++) ++ { ++ hpsize *= 10; ++ hpsize += sizestr[i] - '0'; ++ } ++ hpsize *= 1024; ++ ++ if (hpsize == requested) ++ { ++ *pagesize = hpsize; ++ *flags = hugepage_flags (*pagesize); ++ found = true; ++ break; ++ } ++ } ++ if (found) ++ break; ++ } ++ ++ __close_nocancel (dirfd); ++} +-- +2.33.0 + diff --git a/malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch b/malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch new file mode 100644 index 0000000..f759588 --- /dev/null +++ b/malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch @@ -0,0 +1,338 @@ +From c1beb51d08d3d7ec935b0a2419b4c6fad91d1969 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Fri, 20 Aug 2021 13:22:35 -0300 +Subject: [PATCH 5/7] malloc: Add Huge Page support to arenas + +It is enabled as default for glibc.malloc.hugetlb set to 2 or higher. +It also uses a non configurable minimum value and maximum value, +currently set respectively to 1 and 4 selected huge page size. + +The arena allocation with huge pages does not use MAP_NORESERVE. As +indicate by kernel internal documentation [1], the flag might trigger +a SIGBUS on soft page faults if at memory access there is no left +pages in the pool. + +On systems without a reserved huge pages pool, is just stress the +mmap(MAP_HUGETLB) allocation failure. To improve test coverage it is +required to create a pool with some allocated pages. + +Checked on x86_64-linux-gnu with no reserved pages, 10 reserved pages +(which trigger mmap(MAP_HUGETBL) failures) and with 256 reserved pages +(which does not trigger mmap(MAP_HUGETLB) failures). + +[1] https://www.kernel.org/doc/html/v4.18/vm/hugetlbfs_reserv.html#resv-map-modifications + +Reviewed-by: DJ Delorie +--- + malloc/Makefile | 7 ++- + malloc/arena.c | 134 +++++++++++++++++++++++++++++++++--------------- + malloc/malloc.c | 2 +- + 3 files changed, 99 insertions(+), 44 deletions(-) + +diff --git a/malloc/Makefile b/malloc/Makefile +index e9a6666d22..451eb84612 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -91,10 +91,15 @@ tests-exclude-hugetlb1 = \ + tst-malloc-usable \ + tst-malloc-usable-tunables \ + tst-mallocstate ++# The tst-free-errno relies on the used malloc page size to mmap an ++# overlapping region. ++tests-exclude-hugetlb2 = \ ++ $(tests-exclude-hugetlb1) \ ++ tst-free-errno + tests-malloc-hugetlb1 = \ + $(filter-out $(tests-exclude-hugetlb1), $(tests)) + tests-malloc-hugetlb2 = \ +- $(filter-out $(tests-exclude-hugetlb1), $(tests)) ++ $(filter-out $(tests-exclude-hugetlb2), $(tests)) + + # -lmcheck needs __malloc_initialize_hook, which was deprecated in 2.24. + ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes) +diff --git a/malloc/arena.c b/malloc/arena.c +index 9a6e1af2bd..e1852f8597 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -41,6 +41,29 @@ + mmap threshold, so that requests with a size just below that + threshold can be fulfilled without creating too many heaps. */ + ++/* When huge pages are used to create new arenas, the maximum and minumum ++ size are based on the runtime defined huge page size. */ ++ ++static inline size_t ++heap_min_size (void) ++{ ++#if HAVE_TUNABLES ++ return mp_.hp_pagesize == 0 ? HEAP_MIN_SIZE : mp_.hp_pagesize; ++#else ++ return HEAP_MIN_SIZE; ++#endif ++} ++ ++static inline size_t ++heap_max_size (void) ++{ ++#if HAVE_TUNABLES ++ return mp_.hp_pagesize == 0 ? HEAP_MAX_SIZE : mp_.hp_pagesize * 4; ++#else ++ return HEAP_MAX_SIZE; ++#endif ++} ++ + /***************************************************************************/ + + #define top(ar_ptr) ((ar_ptr)->top) +@@ -56,10 +79,11 @@ typedef struct _heap_info + size_t size; /* Current size in bytes. */ + size_t mprotect_size; /* Size in bytes that has been mprotected + PROT_READ|PROT_WRITE. */ ++ size_t pagesize; /* Page size used when allocating the arena. */ + /* Make sure the following data is properly aligned, particularly + that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of + MALLOC_ALIGNMENT. */ +- char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK]; ++ char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK]; + } heap_info; + + /* Get a compile-time error if the heap_info padding is not correct +@@ -125,10 +149,18 @@ static bool __malloc_initialized = false; + + /* find the heap and corresponding arena for a given ptr */ + +-#define heap_for_ptr(ptr) \ +- ((heap_info *) ((unsigned long) (ptr) & ~(HEAP_MAX_SIZE - 1))) +-#define arena_for_chunk(ptr) \ +- (chunk_main_arena (ptr) ? &main_arena : heap_for_ptr (ptr)->ar_ptr) ++static inline heap_info * ++heap_for_ptr (void *ptr) ++{ ++ size_t max_size = heap_max_size (); ++ return PTR_ALIGN_DOWN (ptr, max_size); ++} ++ ++static inline struct malloc_state * ++arena_for_chunk (mchunkptr ptr) ++{ ++ return chunk_main_arena (ptr) ? &main_arena : heap_for_ptr (ptr)->ar_ptr; ++} + + + /**************************************************************************/ +@@ -443,71 +475,72 @@ static char *aligned_heap_area; + of the page size. */ + + static heap_info * +-new_heap (size_t size, size_t top_pad) ++alloc_new_heap (size_t size, size_t top_pad, size_t pagesize, ++ int mmap_flags) + { +- size_t pagesize = GLRO (dl_pagesize); + char *p1, *p2; + unsigned long ul; + heap_info *h; ++ size_t min_size = heap_min_size (); ++ size_t max_size = heap_max_size (); + +- if (size + top_pad < HEAP_MIN_SIZE) +- size = HEAP_MIN_SIZE; +- else if (size + top_pad <= HEAP_MAX_SIZE) ++ if (size + top_pad < min_size) ++ size = min_size; ++ else if (size + top_pad <= max_size) + size += top_pad; +- else if (size > HEAP_MAX_SIZE) ++ else if (size > max_size) + return 0; + else +- size = HEAP_MAX_SIZE; ++ size = max_size; + size = ALIGN_UP (size, pagesize); + +- /* A memory region aligned to a multiple of HEAP_MAX_SIZE is needed. ++ /* A memory region aligned to a multiple of max_size is needed. + No swap space needs to be reserved for the following large + mapping (on Linux, this is the case for all non-writable mappings + anyway). */ + p2 = MAP_FAILED; + if (aligned_heap_area) + { +- p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE, +- MAP_NORESERVE); ++ p2 = (char *) MMAP (aligned_heap_area, max_size, PROT_NONE, mmap_flags); + aligned_heap_area = NULL; +- if (p2 != MAP_FAILED && ((unsigned long) p2 & (HEAP_MAX_SIZE - 1))) ++ if (p2 != MAP_FAILED && ((unsigned long) p2 & (max_size - 1))) + { +- __munmap (p2, HEAP_MAX_SIZE); ++ __munmap (p2, max_size); + p2 = MAP_FAILED; + } + } + if (p2 == MAP_FAILED) + { +- p1 = (char *) MMAP (0, HEAP_MAX_SIZE << 1, PROT_NONE, MAP_NORESERVE); ++ p1 = (char *) MMAP (0, max_size << 1, PROT_NONE, mmap_flags); + if (p1 != MAP_FAILED) + { +- p2 = (char *) (((unsigned long) p1 + (HEAP_MAX_SIZE - 1)) +- & ~(HEAP_MAX_SIZE - 1)); ++ p2 = (char *) (((unsigned long) p1 + (max_size - 1)) ++ & ~(max_size - 1)); + ul = p2 - p1; + if (ul) + __munmap (p1, ul); + else +- aligned_heap_area = p2 + HEAP_MAX_SIZE; +- __munmap (p2 + HEAP_MAX_SIZE, HEAP_MAX_SIZE - ul); ++ aligned_heap_area = p2 + max_size; ++ __munmap (p2 + max_size, max_size - ul); + } + else + { +- /* Try to take the chance that an allocation of only HEAP_MAX_SIZE ++ /* Try to take the chance that an allocation of only max_size + is already aligned. */ +- p2 = (char *) MMAP (0, HEAP_MAX_SIZE, PROT_NONE, MAP_NORESERVE); ++ p2 = (char *) MMAP (0, max_size, PROT_NONE, mmap_flags); + if (p2 == MAP_FAILED) + return 0; + +- if ((unsigned long) p2 & (HEAP_MAX_SIZE - 1)) ++ if ((unsigned long) p2 & (max_size - 1)) + { +- __munmap (p2, HEAP_MAX_SIZE); ++ __munmap (p2, max_size); + return 0; + } + } + } + if (__mprotect (p2, size, mtag_mmap_flags | PROT_READ | PROT_WRITE) != 0) + { +- __munmap (p2, HEAP_MAX_SIZE); ++ __munmap (p2, max_size); + return 0; + } + +@@ -516,22 +549,42 @@ new_heap (size_t size, size_t top_pad) + h = (heap_info *) p2; + h->size = size; + h->mprotect_size = size; ++ h->pagesize = pagesize; + LIBC_PROBE (memory_heap_new, 2, h, h->size); + return h; + } + ++static heap_info * ++new_heap (size_t size, size_t top_pad) ++{ ++#if HAVE_TUNABLES ++ if (__glibc_unlikely (mp_.hp_pagesize != 0)) ++ { ++ /* MAP_NORESERVE is not used for huge pages because some kernel may ++ not reserve the mmap region and a subsequent access may trigger ++ a SIGBUS if there is no free pages in the pool. */ ++ heap_info *h = alloc_new_heap (size, top_pad, mp_.hp_pagesize, ++ mp_.hp_flags); ++ if (h != NULL) ++ return h; ++ } ++#endif ++ return alloc_new_heap (size, top_pad, GLRO (dl_pagesize), MAP_NORESERVE); ++} ++ + /* Grow a heap. size is automatically rounded up to a + multiple of the page size. */ + + static int + grow_heap (heap_info *h, long diff) + { +- size_t pagesize = GLRO (dl_pagesize); ++ size_t pagesize = h->pagesize; ++ size_t max_size = heap_max_size (); + long new_size; + + diff = ALIGN_UP (diff, pagesize); + new_size = (long) h->size + diff; +- if ((unsigned long) new_size > (unsigned long) HEAP_MAX_SIZE) ++ if ((unsigned long) new_size > (unsigned long) max_size) + return -1; + + if ((unsigned long) new_size > h->mprotect_size) +@@ -581,21 +634,14 @@ shrink_heap (heap_info *h, long diff) + + /* Delete a heap. */ + +-#define delete_heap(heap) \ +- do { \ +- if ((char *) (heap) + HEAP_MAX_SIZE == aligned_heap_area) \ +- aligned_heap_area = NULL; \ +- __munmap ((char *) (heap), HEAP_MAX_SIZE); \ +- } while (0) +- + static int + heap_trim (heap_info *heap, size_t pad) + { + mstate ar_ptr = heap->ar_ptr; +- unsigned long pagesz = GLRO (dl_pagesize); + mchunkptr top_chunk = top (ar_ptr), p; + heap_info *prev_heap; + long new_size, top_size, top_area, extra, prev_size, misalign; ++ size_t max_size = heap_max_size (); + + /* Can this heap go away completely? */ + while (top_chunk == chunk_at_offset (heap, sizeof (*heap))) +@@ -612,19 +658,23 @@ heap_trim (heap_info *heap, size_t pad) + assert (new_size > 0 && new_size < (long) (2 * MINSIZE)); + if (!prev_inuse (p)) + new_size += prev_size (p); +- assert (new_size > 0 && new_size < HEAP_MAX_SIZE); +- if (new_size + (HEAP_MAX_SIZE - prev_heap->size) < pad + MINSIZE + pagesz) ++ assert (new_size > 0 && new_size < max_size); ++ if (new_size + (max_size - prev_heap->size) < pad + MINSIZE ++ + heap->pagesize) + break; + ar_ptr->system_mem -= heap->size; + LIBC_PROBE (memory_heap_free, 2, heap, heap->size); +- delete_heap (heap); ++ if ((char *) heap + max_size == aligned_heap_area) ++ aligned_heap_area = NULL; ++ __munmap (heap, max_size); + heap = prev_heap; + if (!prev_inuse (p)) /* consolidate backward */ + { + p = prev_chunk (p); + unlink_chunk (ar_ptr, p); + } +- assert (((unsigned long) ((char *) p + new_size) & (pagesz - 1)) == 0); ++ assert (((unsigned long) ((char *) p + new_size) & (heap->pagesize - 1)) ++ == 0); + assert (((char *) p + new_size) == ((char *) heap + heap->size)); + top (ar_ptr) = top_chunk = p; + set_head (top_chunk, new_size | PREV_INUSE); +@@ -644,7 +694,7 @@ heap_trim (heap_info *heap, size_t pad) + return 0; + + /* Release in pagesize units and round down to the nearest page. */ +- extra = ALIGN_DOWN(top_area - pad, pagesz); ++ extra = ALIGN_DOWN(top_area - pad, heap->pagesize); + if (extra == 0) + return 0; + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 75efdc2ee7..1698d45d1e 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -5302,7 +5302,7 @@ static __always_inline int + do_set_mmap_threshold (size_t value) + { + /* Forbid setting the threshold too high. */ +- if (value <= HEAP_MAX_SIZE / 2) ++ if (value <= heap_max_size () / 2) + { + LIBC_PROBE (memory_mallopt_mmap_threshold, 3, value, mp_.mmap_threshold, + mp_.no_dyn_threshold); +-- +2.33.0 + diff --git a/malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch b/malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch new file mode 100644 index 0000000..afc5650 --- /dev/null +++ b/malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch @@ -0,0 +1,119 @@ +From 0849eed45daabf30a02c153695041597d6d43b2d Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 30 Aug 2021 10:56:55 -0300 +Subject: [PATCH 6/7] malloc: Move MORECORE fallback mmap to + sysmalloc_mmap_fallback + +So it can be used on hugepage code as well. + +Reviewed-by: DJ Delorie +--- + malloc/malloc.c | 85 ++++++++++++++++++++++++++++++------------------- + 1 file changed, 53 insertions(+), 32 deletions(-) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 1698d45d1e..32050be4cc 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2498,6 +2498,51 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av) + return chunk2mem (p); + } + ++/* ++ Allocate memory using mmap() based on S and NB requested size, aligning to ++ PAGESIZE if required. The EXTRA_FLAGS is used on mmap() call. If the call ++ succeedes S is updated with the allocated size. This is used as a fallback ++ if MORECORE fails. ++ */ ++static void * ++sysmalloc_mmap_fallback (long int *s, INTERNAL_SIZE_T nb, ++ INTERNAL_SIZE_T old_size, size_t minsize, ++ size_t pagesize, int extra_flags, mstate av) ++{ ++ long int size = *s; ++ ++ /* Cannot merge with old top, so add its size back in */ ++ if (contiguous (av)) ++ size = ALIGN_UP (size + old_size, pagesize); ++ ++ /* If we are relying on mmap as backup, then use larger units */ ++ if ((unsigned long) (size) < minsize) ++ size = minsize; ++ ++ /* Don't try if size wraps around 0 */ ++ if ((unsigned long) (size) <= (unsigned long) (nb)) ++ return MORECORE_FAILURE; ++ ++ char *mbrk = (char *) (MMAP (0, size, ++ mtag_mmap_flags | PROT_READ | PROT_WRITE, ++ extra_flags)); ++ if (mbrk == MAP_FAILED) ++ return MAP_FAILED; ++ ++#ifdef MAP_HUGETLB ++ if (!(extra_flags & MAP_HUGETLB)) ++ madvise_thp (mbrk, size); ++#endif ++ ++ /* Record that we no longer have a contiguous sbrk region. After the first ++ time mmap is used as backup, we do not ever rely on contiguous space ++ since this could incorrectly bridge regions. */ ++ set_noncontiguous (av); ++ ++ *s = size; ++ return mbrk; ++} ++ + static void * + sysmalloc (INTERNAL_SIZE_T nb, mstate av) + { +@@ -2696,38 +2741,14 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + segregated mmap region. + */ + +- /* Cannot merge with old top, so add its size back in */ +- if (contiguous (av)) +- size = ALIGN_UP (size + old_size, pagesize); +- +- /* If we are relying on mmap as backup, then use larger units */ +- if ((unsigned long) (size) < (unsigned long) (MMAP_AS_MORECORE_SIZE)) +- size = MMAP_AS_MORECORE_SIZE; +- +- /* Don't try if size wraps around 0 */ +- if ((unsigned long) (size) > (unsigned long) (nb)) +- { +- char *mbrk = (char *) (MMAP (0, size, +- mtag_mmap_flags | PROT_READ | PROT_WRITE, +- 0)); +- +- if (mbrk != MAP_FAILED) +- { +- madvise_thp (mbrk, size); +- +- /* We do not need, and cannot use, another sbrk call to find end */ +- brk = mbrk; +- snd_brk = brk + size; +- +- /* +- Record that we no longer have a contiguous sbrk region. +- After the first time mmap is used as backup, we do not +- ever rely on contiguous space since this could incorrectly +- bridge regions. +- */ +- set_noncontiguous (av); +- } +- } ++ char *mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, pagesize, ++ MMAP_AS_MORECORE_SIZE, 0, av); ++ if (mbrk != MAP_FAILED) ++ { ++ /* We do not need, and cannot use, another sbrk call to find end */ ++ brk = mbrk; ++ snd_brk = brk + size; ++ } + } + + if (brk != (char *) (MORECORE_FAILURE)) +-- +2.33.0 + diff --git a/malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch b/malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch new file mode 100644 index 0000000..fa5c9db --- /dev/null +++ b/malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch @@ -0,0 +1,86 @@ +From 0f982c182760bd7689769ee7590df592d0a132c0 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 30 Aug 2021 14:01:00 -0300 +Subject: [PATCH 7/7] malloc: Enable huge page support on main arena + +This patch adds support huge page support on main arena allocation, +enable with tunable glibc.malloc.hugetlb=2. The patch essentially +disable the __glibc_morecore() sbrk() call (similar when memory +tag does when sbrk() call does not support it) and fallback to +default page size if the memory allocation fails. + +Checked on x86_64-linux-gnu. + +Reviewed-by: DJ Delorie +--- + malloc/arena.c | 4 ++++ + malloc/malloc.c | 12 ++++++++++-- + malloc/morecore.c | 4 ---- + 3 files changed, 14 insertions(+), 6 deletions(-) + +diff --git a/malloc/arena.c b/malloc/arena.c +index e1852f8597..3ed4ef3f05 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -364,6 +364,10 @@ ptmalloc_init (void) + # endif + TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast)); + TUNABLE_GET (hugetlb, size_t, TUNABLE_CALLBACK (set_hugetlb)); ++ if (mp_.hp_pagesize > 0) ++ /* Force mmap for main arena instead of sbrk, so hugepages are explicitly ++ used. */ ++ __always_fail_morecore = true; + #else + if (__glibc_likely (_environ != NULL)) + { +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 32050be4cc..b67f2c84ee 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2741,8 +2741,16 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + segregated mmap region. + */ + +- char *mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, pagesize, +- MMAP_AS_MORECORE_SIZE, 0, av); ++ char *mbrk = MAP_FAILED; ++#if HAVE_TUNABLES ++ if (mp_.hp_pagesize > 0) ++ mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, ++ mp_.hp_pagesize, mp_.hp_pagesize, ++ mp_.hp_flags, av); ++#endif ++ if (mbrk == MAP_FAILED) ++ mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, pagesize, ++ MMAP_AS_MORECORE_SIZE, 0, av); + if (mbrk != MAP_FAILED) + { + /* We do not need, and cannot use, another sbrk call to find end */ +diff --git a/malloc/morecore.c b/malloc/morecore.c +index 8168ef158c..004cd3ead4 100644 +--- a/malloc/morecore.c ++++ b/malloc/morecore.c +@@ -15,9 +15,7 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined(SHARED) || defined(USE_MTAG) + static bool __always_fail_morecore = false; +-#endif + + /* Allocate INCREMENT more bytes of data space, + and return the start of data space, or NULL on errors. +@@ -25,10 +23,8 @@ static bool __always_fail_morecore = false; + void * + __glibc_morecore (ptrdiff_t increment) + { +-#if defined(SHARED) || defined(USE_MTAG) + if (__always_fail_morecore) + return NULL; +-#endif + + void *result = (void *) __sbrk (increment); + if (result == (void *) -1) +-- +2.33.0 + -- Gitee From 74dd0680dc4a4c0df30154dfd1dcf3a83187eb8c Mon Sep 17 00:00:00 2001 From: Yang Yanchao Date: Tue, 29 Mar 2022 19:12:17 +0800 Subject: [PATCH 70/70] mv libc.info.gz* to the package glibc-help Signed-off-by: Yang Yanchao --- glibc.spec | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/glibc.spec b/glibc.spec index 70d41bb..ba43603 100644 --- a/glibc.spec +++ b/glibc.spec @@ -66,7 +66,7 @@ ############################################################################## Name: glibc Version: 2.34 -Release: 70 +Release: 71 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -365,7 +365,6 @@ it from the "local-archive". Summary: The devel for %{name} Requires: %{name} = %{version}-%{release} Requires: libgcc%{_isa} -Requires(pre): info Requires(pre): kernel-headers Requires(pre): coreutils Requires: kernel-headers >= 3.2 @@ -468,7 +467,7 @@ Buildarch: noarch Requires: man info %description help -This package provides al doc and man files of %{name} +This package provides all doc,man and info files of %{name} ############################################################################## # glibc compat-2.17 sub-package @@ -755,6 +754,7 @@ touch nss-devel.filelist touch libnsl.filelist touch debugutils.filelist touch benchtests.filelist +touch help.filelist %if %{with compat_2_17} touch compat-2.17.filelist %endif @@ -842,7 +842,7 @@ grep '%{_prefix}/share' master.filelist \ # glibc "devel" sub-package ############################################################################### %if %{with docs} -grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > devel.filelist +grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > help.filelist %endif grep '%{_libdir}/lib.*\.a' master.filelist \ @@ -1286,7 +1286,7 @@ fi %files -f benchtests.filelist benchtests %endif -%files help +%files -f help.filelist help #Doc of glibc package %doc README NEWS INSTALL elf/rtld-debugger-interface.txt #Doc of common sub-package @@ -1300,6 +1300,9 @@ fi %endif %changelog +* Tue Mar 29 2022 Yang Yanchao - 2.34-71 +- mv libc.info.gz* to the package glibc-help + * Tue Mar 15 2022 Yang Yanchao - 2.34-70 - malloc: Add madvise support for Transparent Huge Pages - malloc: Add THP/madvise support for sbrk -- Gitee