GIT update of https://sourceware.org/git/glibc.git/release/2.39/master from glibc-2.39
GIT update of https://sourceware.org/git/glibc.git/release/2.39/master from glibc-2.39
Gbp-Pq: Name git-updates.diff
--- /dev/null
+For the GNU C Library Security Advisories, see the git master branch:
+https://sourceware.org/git/?p=glibc.git;a=tree;f=advisories;hb=HEAD
# before the expansion of LDLIBS-* variables).
# Tests use -Wl,-rpath instead of -Wl,-rpath-link for
-# build-hardcoded-path-in-tests.
+# build-hardcoded-path-in-tests. Add -Wl,--disable-new-dtags to force
+# DT_RPATH instead of DT_RUNPATH which only applies to DT_NEEDED entries
+# in the executable and doesn't applies to DT_NEEDED entries in shared
+# libraries which are loaded via DT_NEEDED entries in the executable.
ifeq (yes,$(build-hardcoded-path-in-tests))
-link-libc-tests-rpath-link = $(link-libc-rpath)
-link-test-modules-rpath-link = $(link-libc-rpath)
+link-libc-tests-rpath-link = $(link-libc-rpath) -Wl,--disable-new-dtags
+link-test-modules-rpath-link = $(link-libc-rpath) -Wl,--disable-new-dtags
else
link-libc-tests-rpath-link = $(link-libc-rpath-link)
link-test-modules-rpath-link =
$(SHELL) $< "$(PYTHON)" `pwd` > $@ ; \
$(evaluate-test)
+# Link libc.a as a whole to verify that it does not contain multiple
+# definitions of any symbols.
+tests-special += $(objpfx)link-static-libc.out
+$(objpfx)link-static-libc.out:
+ $(LINK.o) $(whole-archive) -r $(objpfx)libc.a -o /dev/null > $@ 2>&1; \
+ $(evaluate-test)
+
# Print test summary for tests in $1 .sum file;
# $2 is optional test identifier.
# Fail if there are unexpected failures in the test results.
Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
using `glibc' in the "product" field.
\f
+Version 2.39.1
+
+Deprecated and removed features, and other changes affecting compatibility:
+
+* __rseq_size now denotes the size of the active rseq area (20 bytes
+ initially), not the size of struct rseq (32 bytes initially).
+
+Security related changes:
+
+The following CVEs were fixed in this release:
+
+ GLIBC-SA-2024-0004:
+ ISO-2022-CN-EXT: fix out-of-bound writes when writing escape
+ sequence (CVE-2024-2961)
+
+ GLIBC-SA-2024-0005:
+ nscd: Stack-based buffer overflow in netgroup cache (CVE-2024-33599)
+
+ GLIBC-SA-2024-0006:
+ nscd: Null pointer crash after notfound response (CVE-2024-33600)
+
+ GLIBC-SA-2024-0007:
+ nscd: netgroup cache may terminate daemon on memory allocation
+ failure (CVE-2024-33601)
+
+ GLIBC-SA-2024-0008:
+ nscd: netgroup cache assumes NSS callback uses in-buffer strings
+ (CVE-2024-33602)
+
+The following bugs are resolved with this release:
+
+ [19622] network: Support aliasing with struct sockaddr
+ [30701] time: getutxent misbehaves on 32-bit x86 when _TIME_BITS=64
+ [30994] REP MOVSB performance suffers from page aliasing on Zen 4
+ [31339] libc: arm32 loader crash after cleanup in 2.36
+ [31325] mips: clone3 is wrong for o32
+ [31335] math: Compile glibc with -march=x86-64-v3 should disable FMA4
+ multi-arch version
+ [31402] libc: clone (NULL, NULL, ...) clobbers %r7 register on
+ s390{,x}
+ [31479] libc: Missing #include <sys/rseq.h> in sched_getcpu.c may
+ result in a loss of rseq acceleration
+ [31316] build: Fails test misc/tst-dirname "Didn't expect signal from
+ child: got `Illegal instruction'" on non SSE CPUs
+ [31371] x86-64: APX and Tile registers aren't preserved in ld.so
+ trampoline
+ [31372] dynamic-link: _dl_tlsdesc_dynamic doesn't preserve all caller-
+ saved registers
+ [31429] build: Glibc failed to build with -march=x86-64-v3
+ [31501] dynamic-link: _dl_tlsdesc_dynamic_xsavec may clobber %rbx
+ [31612] libc: arc4random fails to fallback to /dev/urandom if
+ getrandom is not present
+ [31640] dynamic-link: POWER10 ld.so crashes in
+ elf_machine_load_address with GCC 14
+ [31676] Configuring with CC="gcc -march=x86-64-v3"
+ --with-rtld-early-cflags=-march=x86-64 results in linker failure
+ [31677] nscd: nscd: netgroup cache: invalid memcpy under low
+ memory/storage conditions
+ [31678] nscd: nscd: Null pointer dereferences after failed netgroup
+ cache insertion
+ [31679] nscd: nscd: netgroup cache may terminate daemon on memory
+ allocation failure
+ [31680] nscd: nscd: netgroup cache assumes NSS callback uses in-buffer
+ strings
+ [31686] dynamic-link: Stack-based buffer overflow in
+ parse_tunables_string
+ [31695] libc: pidfd_spawn/pidfd_spawnp leak an fd if clone3 succeeds
+ [31719] dynamic-link: --enable-hardcoded-path-in-tests doesn't work
+ with -Wl,--enable-new-dtags
+ [31782] Test build failure with recent GCC trunk
+ (x86/tst-cpu-features-supports.c:69:3: error: parameter to builtin
+ not valid: avx5124fmaps)
+ [31798] pidfd_getpid.c is miscompiled by GCC 6.4
+ [31867] build: "CPU ISA level is lower than required" on SSE2-free
+ CPUs
+ [31883] build: ISA level support configure check relies on bashism /
+ is otherwise broken for arithmetic
+ [31965] rseq extension mechanism does not work as intended
+\f
Version 2.39
Major new features:
+++ /dev/null
-printf: incorrect output for integers with thousands separator and width field
-
-When the printf family of functions is called with a format specifier
-that uses an <apostrophe> (enable grouping) and a minimum width
-specifier, the resulting output could be larger than reasonably expected
-by a caller that computed a tight bound on the buffer size. The
-resulting larger than expected output could result in a buffer overflow
-in the printf family of functions.
-
-CVE-Id: CVE-2023-25139
-Public-Date: 2023-02-02
-Vulnerable-Commit: e88b9f0e5cc50cab57a299dc7efe1a4eb385161d (2.37)
-Fix-Commit: c980549cc6a1c03c23cc2fe3e7b0fe626a0364b0 (2.38)
-Fix-Commit: 07b9521fc6369d000216b96562ff7c0ed32a16c4 (2.37-4)
+++ /dev/null
-getaddrinfo: Stack read overflow in no-aaaa mode
-
-If the system is configured in no-aaaa mode via /etc/resolv.conf,
-getaddrinfo is called for the AF_UNSPEC address family, and a DNS
-response is received over TCP that is larger than 2048 bytes,
-getaddrinfo may potentially disclose stack contents via the returned
-address data, or crash.
-
-CVE-Id: CVE-2023-4527
-Public-Date: 2023-09-12
-Vulnerable-Commit: f282cdbe7f436c75864e5640a409a10485e9abb2 (2.36)
-Fix-Commit: bd77dd7e73e3530203be1c52c8a29d08270cb25d (2.39)
-Fix-Commit: 4ea972b7edd7e36610e8cde18bf7a8149d7bac4f (2.36-113)
-Fix-Commit: b7529346025a130fee483d42178b5c118da971bb (2.37-38)
-Fix-Commit: b25508dd774b617f99419bdc3cf2ace4560cd2d6 (2.38-19)
+++ /dev/null
-getaddrinfo: Potential use-after-free
-
-When an NSS plugin only implements the _gethostbyname2_r and
-_getcanonname_r callbacks, getaddrinfo could use memory that was freed
-during buffer resizing, potentially causing a crash or read or write to
-arbitrary memory.
-
-CVE-Id: CVE-2023-4806
-Public-Date: 2023-09-12
-Fix-Commit: 973fe93a5675c42798b2161c6f29c01b0e243994 (2.39)
-Fix-Commit: e09ee267c03e3150c2c9ba28625ab130705a485e (2.34-420)
-Fix-Commit: e3ccb230a961b4797510e6a1f5f21fd9021853e7 (2.35-270)
-Fix-Commit: a9728f798ec7f05454c95637ee6581afaa9b487d (2.36-115)
-Fix-Commit: 6529a7466c935f36e9006b854d6f4e1d4876f942 (2.37-39)
-Fix-Commit: 00ae4f10b504bc4564e9f22f00907093f1ab9338 (2.38-20)
+++ /dev/null
-tunables: local privilege escalation through buffer overflow
-
-If a tunable of the form NAME=NAME=VAL is passed in the environment of a
-setuid program and NAME is valid, it may result in a buffer overflow,
-which could be exploited to achieve escalated privileges. This flaw was
-introduced in glibc 2.34.
-
-CVE-Id: CVE-2023-4911
-Public-Date: 2023-10-03
-Vulnerable-Commit: 2ed18c5b534d9e92fc006202a5af0df6b72e7aca (2.34)
-Fix-Commit: 1056e5b4c3f2d90ed2b4a55f96add28da2f4c8fa (2.39)
-Fix-Commit: dcc367f148bc92e7f3778a125f7a416b093964d9 (2.34-423)
-Fix-Commit: c84018a05aec80f5ee6f682db0da1130b0196aef (2.35-274)
-Fix-Commit: 22955ad85186ee05834e47e665056148ca07699c (2.36-118)
-Fix-Commit: b4e23c75aea756b4bddc4abcf27a1c6dca8b6bd3 (2.37-45)
-Fix-Commit: 750a45a783906a19591fb8ff6b7841470f1f5701 (2.38-27)
+++ /dev/null
-getaddrinfo: DoS due to memory leak
-
-The fix for CVE-2023-4806 introduced a memory leak when an application
-calls getaddrinfo for AF_INET6 with AI_CANONNAME, AI_ALL and AI_V4MAPPED
-flags set.
-
-CVE-Id: CVE-2023-5156
-Public-Date: 2023-09-25
-Vulnerable-Commit: e09ee267c03e3150c2c9ba28625ab130705a485e (2.34-420)
-Vulnerable-Commit: e3ccb230a961b4797510e6a1f5f21fd9021853e7 (2.35-270)
-Vulnerable-Commit: a9728f798ec7f05454c95637ee6581afaa9b487d (2.36-115)
-Vulnerable-Commit: 6529a7466c935f36e9006b854d6f4e1d4876f942 (2.37-39)
-Vulnerable-Commit: 00ae4f10b504bc4564e9f22f00907093f1ab9338 (2.38-20)
-Fix-Commit: 8006457ab7e1cd556b919f477348a96fe88f2e49 (2.34-421)
-Fix-Commit: 17092c0311f954e6f3c010f73ce3a78c24ac279a (2.35-272)
-Fix-Commit: 856bac55f98dc840e7c27cfa82262b933385de90 (2.36-116)
-Fix-Commit: 4473d1b87d04b25cdd0e0354814eeaa421328268 (2.37-42)
-Fix-Commit: 5ee59ca371b99984232d7584fe2b1a758b4421d3 (2.38-24)
+++ /dev/null
-syslog: Heap buffer overflow in __vsyslog_internal
-
-__vsyslog_internal did not handle a case where printing a SYSLOG_HEADER
-containing a long program name failed to update the required buffer
-size, leading to the allocation and overflow of a too-small buffer on
-the heap.
-
-CVE-Id: CVE-2023-6246
-Public-Date: 2024-01-30
-Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
-Fix-Commit: 6bd0e4efcc78f3c0115e5ea9739a1642807450da (2.39)
-Fix-Commit: 23514c72b780f3da097ecf33a793b7ba9c2070d2 (2.38-42)
-Fix-Commit: 97a4292aa4a2642e251472b878d0ec4c46a0e59a (2.37-57)
-Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
-Fix-Commit: d1a83b6767f68b3cb5b4b4ea2617254acd040c82 (2.36-126)
+++ /dev/null
-syslog: Heap buffer overflow in __vsyslog_internal
-
-__vsyslog_internal used the return value of snprintf/vsnprintf to
-calculate buffer sizes for memory allocation. If these functions (for
-any reason) failed and returned -1, the resulting buffer would be too
-small to hold output.
-
-CVE-Id: CVE-2023-6779
-Public-Date: 2024-01-30
-Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
-Fix-Commit: 7e5a0c286da33159d47d0122007aac016f3e02cd (2.39)
-Fix-Commit: d0338312aace5bbfef85e03055e1212dd0e49578 (2.38-43)
-Fix-Commit: 67062eccd9a65d7fda9976a56aeaaf6c25a80214 (2.37-58)
-Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
-Fix-Commit: 2bc9d7c002bdac38b5c2a3f11b78e309d7765b83 (2.36-127)
+++ /dev/null
-syslog: Integer overflow in __vsyslog_internal
-
-__vsyslog_internal calculated a buffer size by adding two integers, but
-did not first check if the addition would overflow.
-
-CVE-Id: CVE-2023-6780
-Public-Date: 2024-01-30
-Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
-Fix-Commit: ddf542da94caf97ff43cc2875c88749880b7259b (2.39)
-Fix-Commit: d37c2b20a4787463d192b32041c3406c2bd91de0 (2.38-44)
-Fix-Commit: 2b58cba076e912961ceaa5fa58588e4b10f791c0 (2.37-59)
-Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
-Fix-Commit: b9b7d6a27aa0632f334352fa400771115b3c69b7 (2.36-128)
+++ /dev/null
-GNU C Library Security Advisory Format
-======================================
-
-Security advisories in this directory follow a simple git commit log
-format, with a heading and free-format description augmented with tags
-to allow parsing key information. References to code changes are
-specific to the glibc repository and follow a specific format:
-
- Tag-name: <commit-ref> (release-version)
-
-The <commit-ref> indicates a specific commit in the repository. The
-release-version indicates the publicly consumable release in which this
-commit is known to exist. The release-version is derived from the
-git-describe format, (i.e. stripped out from glibc-2.34.NNN-gxxxx) and
-is of the form 2.34-NNN. If the -NNN suffix is absent, it means that
-the change is in that release tarball, otherwise the change is on the
-release/2.YY/master branch and not in any released tarball.
-
-The following tags are currently being used:
-
-CVE-Id:
-This is the CVE-Id assigned under the CVE Program
-(https://www.cve.org/).
-
-Public-Date:
-The date this issue became publicly known.
-
-Vulnerable-Commit:
-The commit that introduced this vulnerability. There could be multiple
-entries, one for each release branch in the glibc repository; the
-release-version portion of this tag should tell you which branch this is
-on.
-
-Fix-Commit:
-The commit that fixed this vulnerability. There could be multiple
-entries for each release branch in the glibc repository, indicating that
-all of those commits contributed to fixing that issue in each of those
-branches.
-
-Adding an Advisory
-------------------
-
-An advisory for a CVE needs to be added on the master branch in two steps:
-
-1. Add the text of the advisory without any Fix-Commit tags along with
- the fix for the CVE. Add the Vulnerable-Commit tag, if applicable.
- The advisories directory does not exist in release branches, so keep
- the advisory text commit distinct from the code changes, to ease
- backports. Ask for the GLIBC-SA advisory number from the security
- team.
-
-2. Finish all backports on release branches and then back on the msater
- branch, add all commit refs to the advisory using the Fix-Commit
- tags. Don't bother adding the release-version subscript since the
- next step will overwrite it.
-
-3. Run the process-advisories.sh script in the scripts directory on the
- advisory:
-
- scripts/process-advisories.sh update GLIBC-SA-YYYY-NNNN
-
- (replace YYYY-NNNN with the actual advisory number).
-
-4. Verify the updated advisory and push the result.
-
-Getting a NEWS snippet from advisories
---------------------------------------
-
-Run:
-
- scripts/process-advisories.sh news
-
-and copy the content into the NEWS file.
#include <bits/sockaddr.h>
/* Structure describing a generic socket address. */
-struct sockaddr
+struct __attribute_struct_may_alias__ sockaddr
{
__SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
#define _SS_PADSIZE \
(_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype))
-struct sockaddr_storage
+struct __attribute_struct_may_alias__ sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
char __ss_padding[_SS_PADSIZE];
#define __WORDSIZE32_PTRDIFF_LONG
/* Set to 1 in order to force time types to be 32 bits instead of 64 bits in
- struct lastlog and struct utmp{,x} on 64-bit ports. This may be done in
+ struct lastlog and struct utmp{,x}. This may be done in
order to make 64-bit ports compatible with 32-bit ports. Set to 0 for
- 64-bit ports where the time types are 64-bits or for any 32-bit ports. */
+ 64-bit ports where the time types are 64-bits and new 32-bit ports
+ where time_t is 64 bits, and there is no companion architecture with
+ 32-bit time_t. */
#define __WORDSIZE_TIME64_COMPAT32
/* LOONGARCH floating-point ABI for ld.so. */
#undef LOONGARCH_ABI_FRLEN
+/* Define whether ARM used hard-float and support VFPvX-D32. */
+#undef HAVE_ARM_PCS_VFP_D32
+
/* Linux specific: minimum supported kernel version. */
#undef __LINUX_KERNEL_VERSION
/* Define if x86 ISA level should be included in shared libraries. */
#undef INCLUDE_X86_ISA_LEVEL
+/* The x86 ISA level. 1 for baseline. Undefined on non-x86. */
+#undef MINIMUM_X86_ISA_LEVEL
+
/* Define if -msahf is enabled by default on x86. */
#undef HAVE_X86_LAHF_SAHF
libc_cv_cc_loop_to_function
libc_cv_cc_submachine
libc_cv_cc_nofma
-libc_cv_mtls_dialect_gnu2
+libc_cv_mtls_descriptor
libc_cv_has_glob_dat
libc_cv_fpie
libc_cv_z_execstack
# whether to use such directories.
with_fp_cond=1
+# A preconfigure script may define another name to TLS descriptor variant
+mtls_descriptor=gnu2
+
if frags=`ls -d $srcdir/sysdeps/*/preconfigure 2> /dev/null`
then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysdeps preconfigure fragments" >&5
printf "%s\n" "$libc_cv_has_glob_dat" >&6; }
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -mtls-dialect=gnu2" >&5
-printf %s "checking for -mtls-dialect=gnu2... " >&6; }
-if test ${libc_cv_mtls_dialect_gnu2+y}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tls descriptor support" >&5
+printf %s "checking for tls descriptor support... " >&6; }
+if test ${libc_cv_mtls_descriptor+y}
then :
printf %s "(cached) " >&6
else $as_nop
i = 10;
}
EOF
-if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=gnu2 -nostdlib -nostartfiles
- conftest.c -o conftest 1>&5'
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=$mtls_descriptor -nostdlib -nostartfiles
+ -shared conftest.c -o conftest 1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
- libc_cv_mtls_dialect_gnu2=yes
+ libc_cv_mtls_descriptor=$mtls_descriptor
else
- libc_cv_mtls_dialect_gnu2=no
+ libc_cv_mtls_descriptor=no
fi
rm -f conftest*
fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mtls_dialect_gnu2" >&5
-printf "%s\n" "$libc_cv_mtls_dialect_gnu2" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mtls_descriptor" >&5
+printf "%s\n" "$libc_cv_mtls_descriptor" >&6; }
config_vars="$config_vars
-have-mtls-dialect-gnu2 = $libc_cv_mtls_dialect_gnu2"
+have-mtls-descriptor = $libc_cv_mtls_descriptor"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if -Wno-ignored-attributes is required for aliases" >&5
printf %s "checking if -Wno-ignored-attributes is required for aliases... " >&6; }
# whether to use such directories.
with_fp_cond=1
+# A preconfigure script may define another name to TLS descriptor variant
+mtls_descriptor=gnu2
+
dnl Let sysdeps/*/preconfigure act here.
LIBC_PRECONFIGURE([$srcdir], [for sysdeps])
rm -f conftest*])
AC_SUBST(libc_cv_has_glob_dat)
-AC_CACHE_CHECK([for -mtls-dialect=gnu2], libc_cv_mtls_dialect_gnu2,
+AC_CACHE_CHECK([for tls descriptor support], libc_cv_mtls_descriptor,
[dnl
cat > conftest.c <<EOF
__thread int i;
i = 10;
}
EOF
-if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=gnu2 -nostdlib -nostartfiles
- conftest.c -o conftest 1>&AS_MESSAGE_LOG_FD])
+if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=$mtls_descriptor -nostdlib -nostartfiles
+ -shared conftest.c -o conftest 1>&AS_MESSAGE_LOG_FD])
then
- libc_cv_mtls_dialect_gnu2=yes
+ libc_cv_mtls_descriptor=$mtls_descriptor
else
- libc_cv_mtls_dialect_gnu2=no
+ libc_cv_mtls_descriptor=no
fi
rm -f conftest*])
-AC_SUBST(libc_cv_mtls_dialect_gnu2)
-LIBC_CONFIG_VAR([have-mtls-dialect-gnu2], [$libc_cv_mtls_dialect_gnu2])
+AC_SUBST(libc_cv_mtls_descriptor)
+LIBC_CONFIG_VAR([have-mtls-descriptor], [$libc_cv_mtls_descriptor])
dnl clang emits an warning for a double alias redirection, to warn the
dnl original symbol is sed even when weak definition overrides it.
CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines))
# Add the requested compiler flags to the early startup code.
+CFLAGS-dl-misc.os += $(rtld-early-cflags)
CFLAGS-dl-printf.os += $(rtld-early-cflags)
CFLAGS-dl-setup_hash.os += $(rtld-early-cflags)
CFLAGS-dl-sysdep.os += $(rtld-early-cflags)
tst-glibc-hwcaps-prepend \
tst-global1 \
tst-global2 \
+ tst-gnu2-tls2 \
tst-initfinilazyfail \
tst-initorder \
tst-initorder2 \
tst-filterobj-flt \
tst-finilazyfailmod \
tst-globalmod2 \
+ tst-gnu2-tls2mod0 \
+ tst-gnu2-tls2mod1 \
+ tst-gnu2-tls2mod2 \
tst-initlazyfailmod \
tst-initorder2a \
tst-initorder2b \
# For +depfiles in Makerules.
extra-test-objs += tst-auditmod17.os
-ifeq (yes,$(have-mtls-dialect-gnu2))
+ifneq (no,$(have-mtls-descriptor))
tests += tst-gnu2-tls1
modules-names += tst-gnu2-tls1mod
$(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 # $(have-mtls-dialect-gnu2)
+CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=$(have-mtls-descriptor)
+endif # $(have-mtls-descriptor)
ifeq (yes,$(have-protected-data))
modules-names += tst-protected1moda tst-protected1modb
$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
$(objpfx)tst-audit-tlsdesc-mod2.so \
$(shared-thread-library)
-ifeq (yes,$(have-mtls-dialect-gnu2))
+ifneq (no,$(have-mtls-descriptor))
# The test is valid for all TLS types, but we want to exercise GNU2
# TLS if possible.
-CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2
-CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2
+CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=$(have-mtls-descriptor)
endif
$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
$(objpfx)tst-tlsgap-mod0.so \
$(objpfx)tst-tlsgap-mod1.so \
$(objpfx)tst-tlsgap-mod2.so
-ifeq (yes,$(have-mtls-dialect-gnu2))
-CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=gnu2
-CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
-CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
+
+$(objpfx)tst-gnu2-tls2: $(shared-thread-library)
+$(objpfx)tst-gnu2-tls2.out: \
+ $(objpfx)tst-gnu2-tls2mod0.so \
+ $(objpfx)tst-gnu2-tls2mod1.so \
+ $(objpfx)tst-gnu2-tls2mod2.so
+
+ifneq (no,$(have-mtls-descriptor))
+CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-gnu2-tls2mod0.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-gnu2-tls2mod1.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-gnu2-tls2mod2.c += -mtls-dialect=$(have-mtls-descriptor)
endif
_dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap));
_dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT);
_dl_diagnostics_print_labeled_value ("dl_hwcap2", GLRO (dl_hwcap2));
+ _dl_diagnostics_print_labeled_value ("dl_hwcap3", GLRO (dl_hwcap3));
+ _dl_diagnostics_print_labeled_value ("dl_hwcap4", GLRO (dl_hwcap4));
_dl_diagnostics_print_labeled_string
("dl_hwcaps_subdirs", _dl_hwcaps_subdirs);
_dl_diagnostics_print_labeled_value
size_t _dl_phnum;
uint64_t _dl_hwcap;
uint64_t _dl_hwcap2;
+uint64_t _dl_hwcap3;
+uint64_t _dl_hwcap4;
enum dso_sort_algorithm _dl_dso_sort_algo;
dtv entry free it. Note: this is not AS-safe. */
/* XXX Ideally we will at some point create a memory
pool. */
- free (dtv[modid].pointer.to_free);
+ /* Avoid calling free on a null pointer. Some mallocs
+ incorrectly use dynamic TLS, and depending on how the
+ free function was compiled, it could call
+ __tls_get_addr before the null pointer check in the
+ free implementation. Checking here papers over at
+ least some dynamic TLS usage by interposed mallocs. */
+ if (dtv[modid].pointer.to_free != NULL)
+ free (dtv[modid].pointer.to_free);
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
dtv[modid].pointer.to_free = NULL;
#include <ldsodefs.h>
#include <array_length.h>
#include <dl-minimal-malloc.h>
+#include <dl-symbol-redir-ifunc.h>
#define TUNABLES_INTERNAL 1
#include "dl-tunables.h"
{
tunables[ntunables++] =
(struct tunable_toset_t) { cur, value, p - value };
+
break;
}
}
static void
parse_tunables (const char *valstring)
{
- struct tunable_toset_t tunables[tunables_list_size];
- int ntunables = parse_tunables_string (valstring, tunables);
- if (ntunables == -1)
+ struct tunable_toset_t tunables[tunables_list_size] = { 0 };
+ if (parse_tunables_string (valstring, tunables) == -1)
{
_dl_error_printf (
"WARNING: ld.so: invalid GLIBC_TUNABLES `%s': ignored.\n", valstring);
return;
}
- for (int i = 0; i < ntunables; i++)
- if (!tunable_initialize (tunables[i].t, tunables[i].value,
- tunables[i].len))
- _dl_error_printf ("WARNING: ld.so: invalid GLIBC_TUNABLES value `%.*s' "
- "for option `%s': ignored.\n",
- (int) tunables[i].len,
- tunables[i].value,
- tunables[i].t->name);
+ for (int i = 0; i < tunables_list_size; i++)
+ {
+ if (tunables[i].t == NULL)
+ continue;
+
+ if (!tunable_initialize (tunables[i].t, tunables[i].value,
+ tunables[i].len))
+ _dl_error_printf ("WARNING: ld.so: invalid GLIBC_TUNABLES value `%.*s' "
+ "for option `%s': ignored.\n",
+ (int) tunables[i].len,
+ tunables[i].value,
+ tunables[i].t->name);
+ }
}
/* Initialize the tunables list from the environment. For now we only use the
#define AT_RSEQ_FEATURE_SIZE 27 /* rseq supported feature size. */
#define AT_RSEQ_ALIGN 28 /* rseq allocation alignment. */
+/* More machine-dependent hints about processor capabilities. */
+#define AT_HWCAP3 29 /* extension of AT_HWCAP. */
+#define AT_HWCAP4 30 /* extension of AT_HWCAP. */
+
#define AT_EXECFN 31 /* Filename of executable. */
/* Pointer to the global system page used for system calls and other
--- /dev/null
+/* Test TLSDESC relocation.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <support/xdlfcn.h>
+#include <support/xthread.h>
+#include <support/check.h>
+#include <support/test-driver.h>
+#include "tst-gnu2-tls2.h"
+
+#ifndef IS_SUPPORTED
+# define IS_SUPPORTED() true
+#endif
+
+/* An architecture can define it to clobber caller-saved registers in
+ malloc below to verify that the implicit TLSDESC call won't change
+ caller-saved registers. */
+#ifndef PREPARE_MALLOC
+# define PREPARE_MALLOC()
+#endif
+
+extern void * __libc_malloc (size_t);
+
+size_t malloc_counter = 0;
+
+void *
+malloc (size_t n)
+{
+ PREPARE_MALLOC ();
+ malloc_counter++;
+ return __libc_malloc (n);
+}
+
+static void *mod[3];
+#ifndef MOD
+# define MOD(i) "tst-gnu2-tls2mod" #i ".so"
+#endif
+static const char *modname[3] = { MOD(0), MOD(1), MOD(2) };
+#undef MOD
+
+static void
+open_mod (int i)
+{
+ mod[i] = xdlopen (modname[i], RTLD_LAZY);
+ printf ("open %s\n", modname[i]);
+}
+
+static void
+close_mod (int i)
+{
+ xdlclose (mod[i]);
+ mod[i] = NULL;
+ printf ("close %s\n", modname[i]);
+}
+
+static void
+access_mod (int i, const char *sym)
+{
+ struct tls var = { -1, -1, -1, -1 };
+ struct tls *(*f) (struct tls *) = xdlsym (mod[i], sym);
+ /* Check that our malloc is called. */
+ malloc_counter = 0;
+ struct tls *p = f (&var);
+ TEST_VERIFY (malloc_counter != 0);
+ printf ("access %s: %s() = %p\n", modname[i], sym, p);
+ TEST_VERIFY_EXIT (memcmp (p, &var, sizeof (var)) == 0);
+ ++(p->a);
+}
+
+static void *
+start (void *arg)
+{
+ /* The DTV generation is at the last dlopen of mod0 and the
+ entry for mod1 is NULL. */
+
+ open_mod (1); /* Reuse modid of mod1. Uses dynamic TLS. */
+
+ /* Force the slow path in GNU2 TLS descriptor call. */
+ access_mod (1, "apply_tls");
+
+ return arg;
+}
+
+static int
+do_test (void)
+{
+ if (!IS_SUPPORTED ())
+ return EXIT_UNSUPPORTED;
+
+ open_mod (0);
+ open_mod (1);
+ open_mod (2);
+ close_mod (0);
+ close_mod (1); /* Create modid gap at mod1. */
+ open_mod (0); /* Reuse modid of mod0, bump generation count. */
+
+ /* Create a thread where DTV of mod1 is NULL. */
+ pthread_t t = xpthread_create (NULL, start, NULL);
+ xpthread_join (t);
+ return 0;
+}
+
+#include <support/test-driver.c>
--- /dev/null
+/* Test TLSDESC relocation.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+
+struct tls
+{
+ int64_t a, b, c, d;
+};
+
+extern struct tls *apply_tls (struct tls *);
+
+/* An architecture can define them to verify that clobber caller-saved
+ registers aren't changed by the implicit TLSDESC call. */
+#ifndef INIT_TLSDESC_CALL
+# define INIT_TLSDESC_CALL()
+#endif
+
+#ifndef BEFORE_TLSDESC_CALL
+# define BEFORE_TLSDESC_CALL()
+#endif
+
+#ifndef AFTER_TLSDESC_CALL
+# define AFTER_TLSDESC_CALL()
+#endif
--- /dev/null
+/* DSO used by tst-gnu2-tls2.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <tst-gnu2-tls2.h>
+
+__thread struct tls tls_var0 __attribute__ ((visibility ("hidden")));
+
+struct tls *
+apply_tls (struct tls *p)
+{
+ INIT_TLSDESC_CALL ();
+ BEFORE_TLSDESC_CALL ();
+ tls_var0 = *p;
+ struct tls *ret = &tls_var0;
+ AFTER_TLSDESC_CALL ();
+ return ret;
+}
--- /dev/null
+/* DSO used by tst-gnu2-tls2.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <tst-gnu2-tls2.h>
+
+__thread struct tls tls_var1[100] __attribute__ ((visibility ("hidden")));
+
+struct tls *
+apply_tls (struct tls *p)
+{
+ INIT_TLSDESC_CALL ();
+ BEFORE_TLSDESC_CALL ();
+ tls_var1[1] = *p;
+ struct tls *ret = &tls_var1[1];
+ AFTER_TLSDESC_CALL ();
+ return ret;
+}
--- /dev/null
+/* DSO used by tst-gnu2-tls2.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <tst-gnu2-tls2.h>
+
+__thread struct tls tls_var2 __attribute__ ((visibility ("hidden")));
+
+struct tls *
+apply_tls (struct tls *p)
+{
+ INIT_TLSDESC_CALL ();
+ BEFORE_TLSDESC_CALL ();
+ tls_var2 = *p;
+ struct tls *ret = &tls_var2;
+ AFTER_TLSDESC_CALL ();
+ return ret;
+}
<https://www.gnu.org/licenses/>. */
#include <array_length.h>
+/* The test uses the tunable_list size, which is only exported for
+ ld.so. This will result in a copy of tunable_list, which is ununsed by
+ the test itself. */
+#define TUNABLES_INTERNAL 1
#include <dl-tunables.h>
#include <getopt.h>
#include <intprops.h>
#include <stdlib.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
+#include <support/support.h>
static int restart;
#define CMDLINE_OPTIONS \
{ "restart", no_argument, &restart, 1 },
-static const struct test_t
+static struct test_t
{
const char *name;
const char *value;
0,
0,
},
+ /* Also check for repeated tunables with a count larger than the total number
+ of tunables. */
+ {
+ "GLIBC_TUNABLES",
+ NULL,
+ 2,
+ 0,
+ 0,
+ },
+ {
+ "GLIBC_TUNABLES",
+ NULL,
+ 1,
+ 0,
+ 0,
+ },
+ {
+ "GLIBC_TUNABLES",
+ NULL,
+ 0,
+ 0,
+ 0,
+ },
};
static int
spargv[i] = NULL;
}
+ /* Create a tunable line with the duplicate values with a total number
+ larger than the different number of tunables. */
+ {
+ enum { tunables_list_size = array_length (tunable_list) };
+ const char *value = "";
+ for (int i = 0; i < tunables_list_size; i++)
+ value = xasprintf ("%sglibc.malloc.check=2%c",
+ value,
+ i == (tunables_list_size - 1) ? '\0' : ':');
+ tests[33].value = value;
+ }
+ /* Same as before, but the last tunable values is differen than the
+ rest. */
+ {
+ enum { tunables_list_size = array_length (tunable_list) };
+ const char *value = "";
+ for (int i = 0; i < tunables_list_size - 1; i++)
+ value = xasprintf ("%sglibc.malloc.check=2:", value);
+ value = xasprintf ("%sglibc.malloc.check=1", value);
+ tests[34].value = value;
+ }
+ /* Same as before, but with an invalid last entry. */
+ {
+ enum { tunables_list_size = array_length (tunable_list) };
+ const char *value = "";
+ for (int i = 0; i < tunables_list_size - 1; i++)
+ value = xasprintf ("%sglibc.malloc.check=2:", value);
+ value = xasprintf ("%sglibc.malloc.check=1=1", value);
+ tests[35].value = value;
+ }
+
for (int i = 0; i < array_length (tests); i++)
{
snprintf (nteststr, sizeof nteststr, "%d", i);
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-iconv15
+ bug-iconv13 bug-iconv14 bug-iconv15 \
+ tst-iconv-iso-2022-cn-ext
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
$(addprefix $(objpfx),$(modules.so))
$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
+$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ $(addprefix $(objpfx),$(modules.so))
$(objpfx)iconv-test.out: run-iconv-test.sh \
$(addprefix $(objpfx), $(gconv-modules)) \
{ \
const char *escseq; \
\
+ if (outptr + 4 > outend) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
+ \
assert (used == CNS11643_2_set); /* XXX */ \
escseq = "*H"; \
*outptr++ = ESC; \
{ \
const char *escseq; \
\
+ if (outptr + 4 > outend) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
+ \
assert ((used >> 5) >= 3 && (used >> 5) <= 7); \
escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \
*outptr++ = ESC; \
--- /dev/null
+/* Verify ISO-2022-CN-EXT does not write out of the bounds.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <errno.h>
+#include <iconv.h>
+#include <sys/mman.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/support.h>
+
+/* The test sets up a two memory page buffer with the second page marked
+ PROT_NONE to trigger a fault if the conversion writes beyond the exact
+ expected amount. Then we carry out various conversions and precisely
+ place the start of the output buffer in order to trigger a SIGSEGV if the
+ process writes anywhere between 1 and page sized bytes more (only one
+ PROT_NONE page is setup as a canary) than expected. These tests exercise
+ all three of the cases in ISO-2022-CN-EXT where the converter must switch
+ character sets and may run out of buffer space while doing the
+ operation. */
+
+static int
+do_test (void)
+{
+ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
+
+ char *ntf;
+ size_t ntfsize;
+ char *outbufbase;
+ {
+ int pgz = getpagesize ();
+ TEST_VERIFY_EXIT (pgz > 0);
+ ntfsize = 2 * pgz;
+
+ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
+ | MAP_ANONYMOUS, -1);
+ xmprotect (ntf + pgz, pgz, PROT_NONE);
+
+ outbufbase = ntf + pgz;
+ }
+
+ /* Check if SOdesignation escape sequence does not trigger an OOB write. */
+ {
+ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
+
+ for (int i = 0; i < 9; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ /* Same as before for SS2designation. */
+ {
+ char inbuf[] = "ã´½ \xe3\xb4\xbd";
+
+ for (int i = 0; i < 14; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ /* Same as before for SS3designation. */
+ {
+ char inbuf[] = "劄 \xe5\x8a\x84";
+
+ for (int i = 0; i < 14; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
+
+ xmunmap (ntf, ntfsize);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
/* Structure describing an Internet socket address. */
-struct sockaddr_in
+struct __attribute_struct_may_alias__ sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port; /* Port number. */
- sizeof (struct in_addr)];
};
-#if !__USE_KERNEL_IPV6_DEFS
+#if __USE_KERNEL_IPV6_DEFS
+struct __attribute_struct_may_alias__ sockaddr_in6;
+#else
/* Ditto, for IPv6. */
-struct sockaddr_in6
+struct __attribute_struct_may_alias__ sockaddr_in6
{
__SOCKADDR_COMMON (sin6_);
in_port_t sin6_port; /* Transport layer port # */
#ifdef __USE_GNU
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
extern int __REDIRECT (__ppoll64_alias, (struct pollfd *__fds, nfds_t __nfds,
const struct timespec *__timeout,
const __sigset_t *__ss), __ppoll64);
This function is a cancellation point and therefore not marked with
__THROW. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
# ifndef __USE_FILE_OFFSET64
extern int fcntl (int __fd, int __cmd, ...);
# else
# ifdef __USE_LARGEFILE64
extern int fcntl64 (int __fd, int __cmd, ...);
# endif
-#else /* __USE_TIME_BITS64 */
+#else /* __USE_TIME64_REDIRECTS */
# ifdef __REDIRECT
extern int __REDIRECT_NTH (fcntl, (int __fd, int __request, ...),
__fcntl_time64);
int fts_set (FTS *, FTSENT *, int) __THROW;
#else
# ifdef __REDIRECT
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
FTSENT *__REDIRECT (fts_children, (FTS *, int), fts64_children);
int __REDIRECT (fts_close, (FTS *), fts64_close);
FTS *__REDIRECT (fts_open, (char * const *, int,
__fts64_set_time64);
# endif
# else
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
# define fts_children fts64_children
# define fts_close fts64_close
# define fts_open fts64_open
# endif
#endif
#ifdef __USE_LARGEFILE64
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
FTSENT64 *fts64_children (FTS64 *, int);
int fts64_close (FTS64 *);
FTS64 *fts64_open (char * const *, int,
__nonnull ((1, 2));
#else
# ifdef __REDIRECT
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int __REDIRECT (ftw, (const char *__dir, __ftw_func_t __func,
int __descriptors), ftw64) __nonnull ((1, 2));
# else
__nonnull ((1, 2));
# endif
# else
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
# define ftw ftw64
# else
# define ftw __ftw64_time64
# endif
#endif
#ifdef __USE_LARGEFILE64
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int ftw64 (const char *__dir, __ftw64_func_t __func,
int __descriptors) __nonnull ((1, 2));
# else
int __flag) __nonnull ((1, 2));
# else
# ifdef __REDIRECT
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int __REDIRECT (nftw, (const char *__dir, __nftw_func_t __func,
int __descriptors, int __flag), nftw64)
__nonnull ((1, 2));
__nonnull ((1, 2));
# endif
# else
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
# define nftw nftw64
# else
# define nftw __nftw64_time64
# endif
# endif
# ifdef __USE_LARGEFILE64
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int nftw64 (const char *__dir, __nftw64_func_t __func,
int __descriptors, int __flag) __nonnull ((1, 2));
# else
const __sigset_t *__ss)
__fortified_attr_access (__write_only__, 1, 2);
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# ifdef __REDIRECT
extern int __REDIRECT (ppoll, (struct pollfd *__fds, nfds_t __nfds,
const struct timespec *__timeout,
that file descriptor FD is open on and put them in BUF. */
extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull ((2));
#else
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
struct stat *__restrict __buf),
# endif
#endif
#ifdef __USE_LARGEFILE64
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int stat64 (const char *__restrict __file,
struct stat64 *__restrict __buf) __THROW __nonnull ((1, 2));
extern int fstat64 (int __fd, struct stat64 *__buf) __THROW __nonnull ((2));
struct stat *__restrict __buf, int __flag)
__THROW __nonnull ((2, 3));
# else
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (fstatat, (int __fd, const char *__restrict __file,
struct stat *__restrict __buf,
# endif
# ifdef __USE_LARGEFILE64
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int fstatat64 (int __fd, const char *__restrict __file,
struct stat64 *__restrict __buf, int __flag)
__THROW __nonnull ((2, 3));
extern int lstat (const char *__restrict __file,
struct stat *__restrict __buf) __THROW __nonnull ((1, 2));
# else
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (lstat,
(const char *__restrict __file,
# endif
# endif
# ifdef __USE_LARGEFILE64
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int lstat64 (const char *__restrict __file,
struct stat64 *__restrict __buf)
__THROW __nonnull ((1, 2));
#endif
\f
#ifdef __USE_ATFILE
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Set file access and modification times relative to directory file
descriptor. */
extern int utimensat (int __fd, const char *__path,
#endif
#ifdef __USE_XOPEN2K8
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Set file access and modification times of the file associated with FD. */
extern int futimens (int __fd, const struct timespec __times[2]) __THROW;
/* Structure describing file times. */
struct utimbuf
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
__time64_t actime; /* Access time. */
__time64_t modtime; /* Modification time. */
#else
/* Set the access and modification times of FILE to those given in
*FILE_TIMES. If FILE_TIMES is NULL, set them to the current time. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int utime (const char *__file,
const struct utimbuf *__file_times)
__THROW __nonnull ((1));
country_num 232
country_car "ER"
% country_isbn unknown, Need ISO 2108
-# https://en.wikipedia.org/wiki/Saho_language has "Saaho" as the endonym but CLDR has "Saho"
+% https://en.wikipedia.org/wiki/Saho_language has "Saaho" as the endonym but CLDR has "Saho"
lang_name "Saho"
lang_ab ""
lang_term "ssy"
vpath %.c programs
tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
- tst-pututxline-lockfail tst-pututxline-cache
+ tst-pututxline-lockfail tst-pututxline-cache tst-utmp-size tst-utmp-size-64
+
+CFLAGS-tst-utmp-size-64.c += -D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64
# Empty compatibility library for old binaries.
extra-libs := libutil
--- /dev/null
+/* The on-disk layout must not change in time64 mode. */
+#include "tst-utmp-size.c"
--- /dev/null
+/* Check expected sizes of struct utmp, struct utmpx, struct lastlog.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <utmp.h>
+#include <utmpx.h>
+#include <utmp-size.h>
+
+static int
+do_test (void)
+{
+ _Static_assert (sizeof (struct utmp) == UTMP_SIZE, "struct utmp size");
+ _Static_assert (sizeof (struct utmpx) == UTMP_SIZE, "struct utmpx size");
+ _Static_assert (sizeof (struct lastlog) == LASTLOG_SIZE,
+ "struct lastlog size");
+ return 0;
+}
+
+#include <support/test-driver.c>
dist-headers := malloc.h
headers := $(dist-headers) obstack.h mcheck.h
-tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
- tst-malloc-check tst-mallocfork tst-trim1 \
- tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
- tst-pvalloc tst-pvalloc-fortify tst-memalign tst-mallopt \
- tst-malloc-backtrace tst-malloc-thread-exit \
- tst-malloc-thread-fail tst-malloc-fork-deadlock \
- tst-mallocfork2 \
- tst-mallocfork3 \
- tst-interpose-nothread \
- tst-interpose-thread \
- tst-alloc_buffer \
- tst-free-errno \
- tst-malloc-tcache-leak \
- tst-malloc_info tst-mallinfo2 \
- tst-malloc-too-large \
- tst-malloc-stats-cancellation \
- tst-tcfree1 tst-tcfree2 tst-tcfree3 \
- tst-safe-linking \
- tst-mallocalign1 \
- tst-memalign-2 \
- tst-memalign-3 \
- tst-aligned-alloc
+tests := \
+ mallocbug \
+ tst-aligned-alloc \
+ tst-aligned-alloc-random \
+ tst-alloc_buffer \
+ tst-calloc \
+ tst-free-errno \
+ tst-interpose-nothread \
+ tst-interpose-thread \
+ tst-malloc \
+ tst-malloc-alternate-path \
+ tst-malloc-backtrace \
+ tst-malloc-check \
+ tst-malloc-fork-deadlock \
+ tst-malloc-random \
+ tst-malloc-stats-cancellation \
+ tst-malloc-tcache-leak \
+ tst-malloc-thread-exit \
+ tst-malloc-thread-fail \
+ tst-malloc-too-large \
+ tst-malloc-usable \
+ tst-malloc_info tst-mallinfo2 \
+ tst-mallocalign1 \
+ tst-mallocfork \
+ tst-mallocfork2 \
+ tst-mallocfork3 \
+ tst-mallopt \
+ tst-memalign \
+ tst-memalign-2 \
+ tst-memalign-3 \
+ tst-obstack \
+ tst-posix_memalign \
+ tst-pvalloc \
+ tst-pvalloc-fortify \
+ tst-realloc \
+ tst-reallocarray \
+ tst-safe-linking \
+ tst-tcfree1 tst-tcfree2 tst-tcfree3 \
+ tst-trim1 \
+ tst-valloc \
+# tests
tests-static := \
- tst-interpose-static-nothread \
- tst-interpose-static-thread \
- tst-aligned-alloc-static
+ tst-aligned-alloc-static \
+ tst-interpose-static-nothread \
+ tst-interpose-static-thread \
+# tests-static
# Test for the malloc_set_state symbol removed in glibc 2.25.
ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes)
-tests += tst-mallocstate tst-compathooks-off tst-compathooks-on
+tests += \
+ tst-compathooks-off \
+ tst-compathooks-on \
+ tst-mallocstate \
+# tests
endif
tests-internal := tst-scratch_buffer
# The dynarray framework is only available inside glibc.
tests-internal += \
- tst-dynarray \
- tst-dynarray-fail \
- tst-dynarray-at-fail \
+ tst-dynarray \
+ tst-dynarray-at-fail \
+ tst-dynarray-fail \
+# tests-internal
-tests += tst-malloc-usable-tunables tst-mxfast
+tests += \
+ tst-malloc-usable-tunables \
+ tst-mxfast \
+# tests
tests += $(tests-static)
test-srcs = tst-mtrace
# These tests either are run with MALLOC_CHECK_=3 by default or do not work
# with MALLOC_CHECK_=3 because they expect a specific failure.
-tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \
- tst-mxfast tst-safe-linking \
- tst-compathooks-off tst-compathooks-on tst-memalign-2 tst-memalign-3 \
- tst-mallocfork2 \
- tst-mallocfork3 \
- tst-malloc-tcache-leak
+tests-exclude-malloc-check = \
+ tst-compathooks-off \
+ tst-compathooks-on \
+ tst-malloc-check \
+ tst-malloc-tcache-leak \
+ tst-malloc-usable \
+ tst-mallocfork2 \
+ tst-mallocfork3 \
+ tst-memalign-2 \
+ tst-memalign-3 \
+ tst-mxfast \
+ tst-safe-linking \
+# tests-exclude-malloc-check
# Run all tests with MALLOC_CHECK_=3
tests-malloc-check = $(filter-out $(tests-exclude-malloc-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 \
- tst-interpose-nothread \
- tst-interpose-thread \
- tst-interpose-static-nothread \
- tst-interpose-static-thread \
- tst-malloc-usable \
- tst-malloc-usable-tunables \
- tst-mallocstate \
- tst-malloc-tcache-leak \
- tst-mallocfork2 \
- tst-mallocfork3
+ tst-compathooks-off \
+ tst-compathooks-on \
+ tst-interpose-nothread \
+ tst-interpose-static-nothread \
+ tst-interpose-static-thread \
+ tst-interpose-thread \
+ tst-malloc-tcache-leak \
+ tst-malloc-usable \
+ tst-malloc-usable-tunables \
+ tst-mallocfork2 \
+ tst-mallocfork3 \
+ tst-mallocstate \
+# tests-exclude-hugetlb1
# The tst-free-errno relies on the used malloc page size to mmap an
# overlapping region.
tests-exclude-hugetlb2 = \
# Tests that don't play well with mcheck. They are either bugs in mcheck or
# the tests expect specific internal behavior that is changed due to linking to
# libmcheck.a.
-tests-exclude-mcheck = tst-mallocstate \
- tst-safe-linking \
- tst-malloc-backtrace \
- tst-malloc-fork-deadlock \
- tst-malloc-stats-cancellation \
- tst-malloc-tcache-leak \
- tst-malloc-thread-exit \
- tst-malloc-thread-fail \
- tst-malloc-usable-tunables \
- tst-malloc_info \
- tst-compathooks-off tst-compathooks-on \
- tst-memalign-2 \
- tst-memalign-3 \
- tst-mxfast \
- tst-mallocfork2 \
- tst-mallocfork3
+tests-exclude-mcheck = \
+ tst-compathooks-off \
+ tst-compathooks-on \
+ tst-malloc-backtrace \
+ tst-malloc-fork-deadlock \
+ tst-malloc-stats-cancellation \
+ tst-malloc-tcache-leak \
+ tst-malloc-thread-exit \
+ tst-malloc-thread-fail \
+ tst-malloc-usable-tunables \
+ tst-malloc_info \
+ tst-mallocfork2 \
+ tst-mallocfork3 \
+ tst-mallocstate \
+ tst-memalign-2 \
+ tst-memalign-3 \
+ tst-mxfast \
+ tst-safe-linking \
+# tests-exclude-mcheck
tests-mcheck = $(filter-out $(tests-exclude-mcheck) $(tests-static), $(tests))
endif
# Helper objects for some tests.
extra-test-objs += \
+ tst-aligned_alloc-lib.so \
tst-interpose-aux-nothread.o \
tst-interpose-aux-thread.o \
+# extra-test-objs
test-extras = \
tst-interpose-aux-nothread \
tst-interpose-aux-thread \
+# test-extras
+
+modules-names = \
+ tst-aligned_alloc-lib
libmemusage-routines = memusage
libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
# libc_malloc_debug.so.
$(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so
$(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so
+
+$(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
+$(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
+
+tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
start_sp = __thread_stack_pointer ();
uintptr_t sp = __thread_stack_pointer ();
-#ifdef _STACK_GROWS_UP
+#if _STACK_GROWS_UP
/* This can happen in threads where we didn't catch the thread's
stack early enough. */
if (__glibc_unlikely (sp < start_sp))
--- /dev/null
+/* Test for randomized malloc that calls aligned_alloc
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <support/check.h>
+#include <time.h>
+
+static int
+do_test (void)
+{
+ void *p1;
+ int i;
+
+ srandom (time (NULL));
+
+ for (i = 0; i < 1024; i++)
+ {
+ size_t size = random () & 0xffff;
+
+ p1 = malloc (size);
+ TEST_VERIFY (p1 != NULL);
+ }
+
+ return 0;
+}
+
+
+#include <support/test-driver.c>
--- /dev/null
+/* Module used for improved aligned_alloc testing.
+ Copyright (C) 2024 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
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General 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 <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <libc-symbols.h>
+#include <stdlib.h>
+
+extern void *__libc_malloc (size_t size);
+extern void *__libc_calloc (size_t n, size_t size);
+
+int aligned_alloc_count = 0;
+int libc_malloc_count = 0;
+int libc_calloc_count = 0;
+
+/* Get a random alignment value. Biased towards the smaller values. Must be
+ a power of 2. */
+static size_t get_random_alignment (void)
+{
+ size_t aligns[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384
+ };
+
+ return aligns[random () % array_length (aligns)];
+}
+
+static void *get_random_alloc (size_t size)
+{
+ void *retval;
+ size_t align;
+
+ switch (random() % 3)
+ {
+ case 1:
+ align = get_random_alignment ();
+ retval = aligned_alloc (align, size);
+ aligned_alloc_count++;
+ break;
+ case 2:
+ retval = __libc_calloc (1, size);
+ libc_calloc_count++;
+ break;
+ default:
+ retval = __libc_malloc (size);
+ libc_malloc_count++;
+ break;
+ }
+
+ return retval;
+}
+
+
+void * __random_malloc (size_t size)
+{
+ return get_random_alloc (size);
+}
+strong_alias (__random_malloc, malloc)
--- /dev/null
+/* Test that malloc uses mmap when sbrk or brk fails.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This test sets up an obstruction to ensure that brk/sbrk fails to
+ grow the heap, then verifies that malloc uses mmap for allocations
+ instead. */
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <libc-pointer-arith.h>
+#include <support/check.h>
+#include <stddef.h>
+#include <stdalign.h>
+
+#define LARGE_SIZE (10 * (1 << 20)) // 10 MB
+static long page_size;
+
+static int
+do_test (void)
+{
+ /* Get current program break. */
+ void *current_brk = sbrk (0);
+
+ page_size = sysconf (_SC_PAGESIZE);
+
+ /* Round up to the next page boundary. */
+ void *next_page_boundary = PTR_ALIGN_UP (current_brk, page_size);
+
+ /* Place a mapping using mmap at the next page boundary. */
+ void *obstruction_addr
+ = mmap (next_page_boundary, page_size, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+
+ /* Check if memory obstruction is set up correctly. */
+ TEST_VERIFY_EXIT (obstruction_addr == next_page_boundary);
+
+ /* Try to extend the heap beyond the obstruction using sbrk */
+ int *ptr = sbrk (page_size);
+ TEST_VERIFY_EXIT (ptr == (void *) -1);
+
+ /* Attempt multiple small allocations using malloc. */
+ for (size_t i = 0; i < page_size / alignof (max_align_t); i++)
+ {
+ TEST_VERIFY (malloc (alignof (max_align_t)));
+ }
+
+ /* Attempt to allocate a large block of memory using malloc. */
+ TEST_VERIFY_EXIT (malloc (LARGE_SIZE) != NULL);
+
+ /* Check if malloc changed current program break. */
+ TEST_VERIFY_EXIT (current_brk == sbrk (0));
+
+ return 0;
+}
+
+#include <support/test-driver.c>
--- /dev/null
+/* Test malloc with random calls to aligned_alloc and calloc.
+
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-malloc.c"
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
+#include <stdlib.h>
#include <libc-diag.h>
+#include <time.h>
static int errors = 0;
void *p, *q;
int save;
+ srandom (time (NULL));
+
errno = 0;
DIAG_PUSH_NEEDS_COMMENT;
# define __attribute_returns_twice__ /* Ignore. */
#endif
+/* Mark struct types as aliasable. Restricted to compilers that
+ support forward declarations of structs in the presence of the
+ attribute. */
+#if __GNUC_PREREQ (7, 1) || defined __clang__
+# define __attribute_struct_may_alias__ __attribute__ ((__may_alias__))
+#else
+# define __attribute_struct_may_alias__
+#endif
+
#endif /* sys/cdefs.h */
/* Perform the I/O control operation specified by REQUEST on FD.
One argument may follow; its presence and type depend on REQUEST.
Return value depends on REQUEST. Usually -1 indicates error. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;
#else
# ifdef __REDIRECT
This function is a cancellation point and therefore not marked with
__THROW. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int select (int __nfds, fd_set *__restrict __readfds,
fd_set *__restrict __writefds,
fd_set *__restrict __exceptfds,
This function is a cancellation point and therefore not marked with
__THROW. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pselect (int __nfds, fd_set *__restrict __readfds,
fd_set *__restrict __writefds,
fd_set *__restrict __exceptfds,
#ifndef RWF_APPEND
# define RWF_APPEND 0
#endif
+#ifndef RWF_NOAPPEND
+# define RWF_NOAPPEND 0
+#endif
#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \
- | RWF_APPEND)
+ | RWF_APPEND | RWF_NOAPPEND)
/* Generic uio_lim.h does not define IOV_MAX. */
#ifndef IOV_MAX
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <scratch_buffer.h>
#include "../nss/netgroup.h"
#include "nscd.h"
char strdata[0];
};
+/* Send a notfound response to FD. Always returns -1 to indicate an
+ ephemeral error. */
+static time_t
+send_notfound (int fd)
+{
+ if (fd != -1)
+ TEMP_FAILURE_RETRY (send (fd, ¬found, sizeof (notfound), MSG_NOSIGNAL));
+ return -1;
+}
+
/* Sends a notfound message and prepares a notfound dataset to write to the
cache. Returns true if there was enough memory to allocate the dataset and
returns the dataset in DATASETP, total bytes to write in TOTALP and the
total = sizeof (notfound);
timeout = time (NULL) + db->negtimeout;
- if (fd != -1)
- TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL));
+ send_notfound (fd);
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
/* If we cannot permanently store the result, so be it. */
return cacheable;
}
+struct addgetnetgrentX_scratch
+{
+ /* This is the result that the caller should use. It can be NULL,
+ point into buffer, or it can be in the cache. */
+ struct dataset *dataset;
+
+ struct scratch_buffer buffer;
+
+ /* Used internally in addgetnetgrentX as a staging area. */
+ struct scratch_buffer tmp;
+
+ /* Number of bytes in buffer that are actually used. */
+ size_t buffer_used;
+};
+
+static void
+addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
+{
+ scratch->dataset = NULL;
+ scratch_buffer_init (&scratch->buffer);
+ scratch_buffer_init (&scratch->tmp);
+
+ /* Reserve space for the header. */
+ scratch->buffer_used = sizeof (struct dataset);
+ static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
+ "initial buffer space");
+ memset (scratch->tmp.data, 0, sizeof (struct dataset));
+}
+
+static void
+addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
+{
+ scratch_buffer_free (&scratch->buffer);
+ scratch_buffer_free (&scratch->tmp);
+}
+
+/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH
+ could not be resized, otherwise a pointer to the copy. */
+static char *
+addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
+ const char *s, size_t length)
+{
+ while (true)
+ {
+ size_t remaining = scratch->buffer.length - scratch->buffer_used;
+ if (remaining >= length)
+ break;
+ if (!scratch_buffer_grow_preserve (&scratch->buffer))
+ return NULL;
+ }
+ char *copy = scratch->buffer.data + scratch->buffer_used;
+ memcpy (copy, s, length);
+ scratch->buffer_used += length;
+ return copy;
+}
+
+/* Copy S into SCRATCH, including its null terminator. Returns false
+ if SCRATCH could not be resized. */
+static bool
+addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
+{
+ if (s == NULL)
+ s = "";
+ return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
+}
+
+/* Caller must initialize and free *SCRATCH. If the return value is
+ negative, this function has sent a notfound response. */
static time_t
addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
const char *key, uid_t uid, struct hashentry *he,
- struct datahead *dh, struct dataset **resultp,
- void **tofreep)
+ struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
{
if (__glibc_unlikely (debug_level > 0))
{
char *key_copy = NULL;
struct __netgrent data;
- size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
- size_t buffilled = sizeof (*dataset);
- char *buffer = NULL;
size_t nentries = 0;
size_t group_len = strlen (key) + 1;
struct name_list *first_needed
= alloca (sizeof (struct name_list) + group_len);
- *tofreep = NULL;
if (netgroup_database == NULL
&& !__nss_database_get (nss_database_netgroup, &netgroup_database))
/* No such service. */
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
&key_copy);
- goto writeout;
+ goto maybe_cache_add;
}
memset (&data, '\0', sizeof (data));
- buffer = xmalloc (buflen);
- *tofreep = buffer;
first_needed->next = first_needed;
memcpy (first_needed->name, key, group_len);
data.needed_groups = first_needed;
while (1)
{
int e;
- status = getfct.f (&data, buffer + buffilled,
- buflen - buffilled - req->key_len, &e);
+ status = getfct.f (&data, scratch->tmp.data,
+ scratch->tmp.length, &e);
if (status == NSS_STATUS_SUCCESS)
{
if (data.type == triple_val)
const char *nhost = data.val.triple.host;
const char *nuser = data.val.triple.user;
const char *ndomain = data.val.triple.domain;
-
- size_t hostlen = strlen (nhost ?: "") + 1;
- size_t userlen = strlen (nuser ?: "") + 1;
- size_t domainlen = strlen (ndomain ?: "") + 1;
-
- if (nhost == NULL || nuser == NULL || ndomain == NULL
- || nhost > nuser || nuser > ndomain)
- {
- const char *last = nhost;
- if (last == NULL
- || (nuser != NULL && nuser > last))
- last = nuser;
- if (last == NULL
- || (ndomain != NULL && ndomain > last))
- last = ndomain;
-
- size_t bufused
- = (last == NULL
- ? buffilled
- : last + strlen (last) + 1 - buffer);
-
- /* We have to make temporary copies. */
- size_t needed = hostlen + userlen + domainlen;
-
- if (buflen - req->key_len - bufused < needed)
- {
- buflen += MAX (buflen, 2 * needed);
- /* Save offset in the old buffer. We don't
- bother with the NULL check here since
- we'll do that later anyway. */
- size_t nhostdiff = nhost - buffer;
- size_t nuserdiff = nuser - buffer;
- size_t ndomaindiff = ndomain - buffer;
-
- char *newbuf = xrealloc (buffer, buflen);
- /* Fix up the triplet pointers into the new
- buffer. */
- nhost = (nhost ? newbuf + nhostdiff
- : NULL);
- nuser = (nuser ? newbuf + nuserdiff
- : NULL);
- ndomain = (ndomain ? newbuf + ndomaindiff
- : NULL);
- *tofreep = buffer = newbuf;
- }
-
- nhost = memcpy (buffer + bufused,
- nhost ?: "", hostlen);
- nuser = memcpy ((char *) nhost + hostlen,
- nuser ?: "", userlen);
- ndomain = memcpy ((char *) nuser + userlen,
- ndomain ?: "", domainlen);
- }
-
- char *wp = buffer + buffilled;
- wp = memmove (wp, nhost ?: "", hostlen);
- wp += hostlen;
- wp = memmove (wp, nuser ?: "", userlen);
- wp += userlen;
- wp = memmove (wp, ndomain ?: "", domainlen);
- wp += domainlen;
- buffilled = wp - buffer;
+ if (!(addgetnetgrentX_append (scratch, nhost)
+ && addgetnetgrentX_append (scratch, nuser)
+ && addgetnetgrentX_append (scratch, ndomain)))
+ return send_notfound (fd);
++nentries;
}
else
}
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
{
- buflen *= 2;
- *tofreep = buffer = xrealloc (buffer, buflen);
+ if (!scratch_buffer_grow (&scratch->tmp))
+ return send_notfound (fd);
}
else if (status == NSS_STATUS_RETURN
|| status == NSS_STATUS_NOTFOUND
{
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
&key_copy);
- goto writeout;
+ goto maybe_cache_add;
}
- total = buffilled;
+ /* Capture the result size without the key appended. */
+ total = scratch->buffer_used;
+
+ /* Make a copy of the key. The scratch buffer must not move after
+ this point. */
+ key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
+ if (key_copy == NULL)
+ return send_notfound (fd);
/* Fill in the dataset. */
- dataset = (struct dataset *) buffer;
+ dataset = scratch->buffer.data;
timeout = datahead_init_pos (&dataset->head, total + req->key_len,
total - offsetof (struct dataset, resp),
he == NULL ? 0 : dh->nreloads + 1,
dataset->resp.version = NSCD_VERSION;
dataset->resp.found = 1;
dataset->resp.nresults = nentries;
- dataset->resp.result_len = buffilled - sizeof (*dataset);
-
- assert (buflen - buffilled >= req->key_len);
- key_copy = memcpy (buffer + buffilled, key, req->key_len);
- buffilled += req->key_len;
+ dataset->resp.result_len = total - sizeof (*dataset);
/* Now we can determine whether on refill we have to create a new
record or not. */
if (__glibc_likely (newp != NULL))
{
/* Adjust pointer into the memory block. */
- key_copy = (char *) newp + (key_copy - buffer);
+ key_copy = (char *) newp + (key_copy - (char *) dataset);
dataset = memcpy (newp, dataset, total + req->key_len);
cacheable = true;
}
if (he == NULL && fd != -1)
- {
- /* We write the dataset before inserting it to the database
- since while inserting this thread might block and so would
- unnecessarily let the receiver wait. */
- writeout:
+ /* We write the dataset before inserting it to the database since
+ while inserting this thread might block and so would
+ unnecessarily let the receiver wait. */
writeall (fd, &dataset->resp, dataset->head.recsize);
- }
+ maybe_cache_add:
if (cacheable)
{
/* If necessary, we also propagate the data to disk. */
}
out:
- *resultp = dataset;
+ scratch->dataset = dataset;
return timeout;
}
if (user != NULL)
key = strchr (key, '\0') + 1;
const char *domain = *key++ ? key : NULL;
+ struct addgetnetgrentX_scratch scratch;
+
+ addgetnetgrentX_scratch_init (&scratch);
if (__glibc_unlikely (debug_level > 0))
{
group, group_len,
db, uid);
time_t timeout;
- void *tofree;
if (result != NULL)
- {
- timeout = result->head.timeout;
- tofree = NULL;
- }
+ timeout = result->head.timeout;
else
{
request_header req_get =
.key_len = group_len
};
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
- &result, &tofree);
+ &scratch);
+ result = scratch.dataset;
+ if (timeout < 0)
+ goto out;
}
struct indataset
= (struct indataset *) mempool_alloc (db,
sizeof (*dataset) + req->key_len,
1);
- struct indataset dataset_mem;
bool cacheable = true;
if (__glibc_unlikely (dataset == NULL))
{
cacheable = false;
- dataset = &dataset_mem;
+ /* The alloca is safe because nscd_run_worker verfies that
+ key_len is not larger than MAXKEYLEN. */
+ dataset = alloca (sizeof (*dataset) + req->key_len);
}
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
sizeof (innetgroup_response_header),
- he == NULL ? 0 : dh->nreloads + 1, result->head.ttl);
+ he == NULL ? 0 : dh->nreloads + 1,
+ result == NULL ? db->negtimeout : result->head.ttl);
/* Set the notfound status and timeout based on the result from
getnetgrent. */
- dataset->head.notfound = result->head.notfound;
+ dataset->head.notfound = result == NULL || result->head.notfound;
dataset->head.timeout = timeout;
dataset->resp.version = NSCD_VERSION;
- dataset->resp.found = result->resp.found;
+ dataset->resp.found = result != NULL && result->resp.found;
/* Until we find a matching entry the result is 0. */
dataset->resp.result = 0;
goto out;
}
- if (he == NULL)
+ /* addgetnetgrentX may have already sent a notfound response. Do
+ not send another one. */
+ if (he == NULL && dataset->resp.found)
{
/* We write the dataset before inserting it to the database
since while inserting this thread might block and so would
}
out:
- free (tofree);
+ addgetnetgrentX_scratch_free (&scratch);
return timeout;
}
const char *key, uid_t uid, struct hashentry *he,
struct datahead *dh)
{
- struct dataset *ignore;
- void *tofree;
- time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
- &ignore, &tofree);
- free (tofree);
+ struct addgetnetgrentX_scratch scratch;
+ addgetnetgrentX_scratch_init (&scratch);
+ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
+ addgetnetgrentX_scratch_free (&scratch);
+ if (timeout < 0)
+ timeout = 0;
return timeout;
}
.key_len = he->len
};
- return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
+ time_t timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
+ he, dh);
+ if (timeout < 0)
+ timeout = 0;
+ return timeout;
}
/* Free storage allocated in PGLOB by a previous `glob' call. */
extern void globfree (glob_t *__pglob) __THROW;
#else
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
extern int __REDIRECT_NTHNL (glob, (const char *__restrict __pattern,
int __flags,
int (*__errfunc) (const char *, int),
#endif
#ifdef __USE_LARGEFILE64
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
extern int __REDIRECT_NTHNL (glob64, (const char *__restrict __pattern,
int __flags,
int (*__errfunc) (const char *, int),
extern int sched_get_priority_min (int __algorithm) __THROW;
/* Get the SCHED_RR interval for the named process. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW;
#else
# ifdef __REDIRECT_NTH
nil, store information about the child's resource usage there. If the
WUNTRACED bit is set in OPTIONS, return status for stopped children;
otherwise don't. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern __pid_t wait3 (int *__stat_loc, int __options,
struct rusage * __usage) __THROWNL;
# else
#endif
#ifdef __USE_MISC
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* PID is like waitpid. Other args are like wait3. */
extern __pid_t wait4 (__pid_t __pid, int *__stat_loc, int __options,
struct rusage *__usage) __THROWNL;
#include <stdio.h>
#include <support/check.h>
+#include <support/descriptors.h>
#include <tst-spawn.h>
int
char * const args[] = { 0 };
PID_T_TYPE pid = -1;
- int ret = POSIX_SPAWN (&pid, program, 0, 0, args, environ);
- if (ret != ENOENT)
- {
- errno = ret;
- FAIL_EXIT1 ("posix_spawn: %m");
- }
-
- /* POSIX states the value returned on pid variable in case of an error
- is not specified. GLIBC will update the value iff the child
- execution is successful. */
- if (pid != -1)
- FAIL_EXIT1 ("posix_spawn returned pid != -1 (%i)", (int) pid);
-
- /* Check if no child is actually created. */
- TEST_COMPARE (WAITID (P_ALL, 0, NULL, WEXITED), -1);
- TEST_COMPARE (errno, ECHILD);
-
- /* Same as before, but with posix_spawnp. */
- char *args2[] = { (char*) program, 0 };
-
- ret = POSIX_SPAWNP (&pid, args2[0], 0, 0, args2, environ);
- if (ret != ENOENT)
- {
- errno = ret;
- FAIL_EXIT1 ("posix_spawnp: %m");
- }
-
- if (pid != -1)
- FAIL_EXIT1 ("posix_spawnp returned pid != -1 (%i)", (int) pid);
-
- TEST_COMPARE (WAITID (P_ALL, 0, NULL, WEXITED), -1);
- TEST_COMPARE (errno, ECHILD);
+ {
+ struct support_descriptors *descrs = support_descriptors_list ();
+
+ int ret = POSIX_SPAWN (&pid, program, 0, 0, args, environ);
+ if (ret != ENOENT)
+ {
+ errno = ret;
+ FAIL_EXIT1 ("posix_spawn: %m");
+ }
+
+ /* POSIX states the value returned on pid variable in case of an error
+ is not specified. GLIBC will update the value iff the child
+ execution is successful. */
+ if (pid != -1)
+ FAIL_EXIT1 ("posix_spawn returned pid != -1 (%i)", (int) pid);
+
+ /* Check if no child is actually created. */
+ TEST_COMPARE (WAITID (P_ALL, 0, NULL, WEXITED), -1);
+ TEST_COMPARE (errno, ECHILD);
+
+ /* Also check if there is no leak descriptors. */
+ support_descriptors_check (descrs);
+ support_descriptors_free (descrs);
+ }
+
+ {
+ /* Same as before, but with posix_spawnp. */
+ char *args2[] = { (char*) program, 0 };
+
+ struct support_descriptors *descrs = support_descriptors_list ();
+
+ int ret = POSIX_SPAWNP (&pid, args2[0], 0, 0, args2, environ);
+ if (ret != ENOENT)
+ {
+ errno = ret;
+ FAIL_EXIT1 ("posix_spawnp: %m");
+ }
+
+ if (pid != -1)
+ FAIL_EXIT1 ("posix_spawnp returned pid != -1 (%i)", (int) pid);
+
+ TEST_COMPARE (WAITID (P_ALL, 0, NULL, WEXITED), -1);
+ TEST_COMPARE (errno, ECHILD);
+
+ support_descriptors_check (descrs);
+ support_descriptors_free (descrs);
+ }
return 0;
}
extern int gai_suspend (const struct gaicb *const __list[], int __ent,
const struct timespec *__timeout);
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# if defined(__REDIRECT)
extern int __REDIRECT (gai_suspend, (const struct gaicb *const __list[],
int __ent,
and put it in *USAGE. Returns 0 for success, -1 for failure. */
extern int getrusage (__rusage_who_t __who, struct rusage *__usage) __THROW;
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# if defined(__REDIRECT_NTH)
extern int __REDIRECT_NTH (getrusage, (__rusage_who_t __who,
struct rusage *__usage),
extern int __REDIRECT_NTH (aio_cancel,
(int __fildes, struct aiocb *__aiocbp),
aio_cancel64);
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
extern int __REDIRECT_NTH (aio_suspend,
(const struct aiocb *const __list[], int __nent,
const struct timespec *__restrict __timeout),
# define aio_error aio_error64
# define aio_return aio_return64
# define aio_cancel aio_cancel64
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# define aio_suspend __aio_suspend_time64
# else
# define aio_suspend aio_suspend64
unsigned int __msg_prio) __nonnull ((2));
#ifdef __USE_XOPEN2K
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Receive the oldest from highest priority messages in message queue
MQDES, stop waiting if ABS_TIMEOUT expires. */
extern ssize_t mq_timedreceive (mqd_t __mqdes, char *__restrict __msg_ptr,
}
FILENAME != lastfile {
- if (lastfile && jmprel_offset == 0 && rela_offset == 0 && rel_offset == 0) {
+ if (lastfile && jmprel_offset == 0 && rela_offset == 0 && rel_offset == 0 \
+ && relr_offset == 0) {
print FILENAME ": *** failed to find expected output (readelf -WSdr)";
result = 2;
}
jmprel_offset = 0;
rela_offset = 0;
rel_offset = 0;
+ relr_offset = 0;
pltrelsz = -1;
delete section_offset_by_address;
}
}
}
+# No need to handle DT_RELR (all packed relocations are relative).
+
in_relocs { next }
$1 == "Relocation" && $2 == "section" && $5 == "offset" {
}
next
}
+
+$2 == "(RELR)" {
+ relr_addr = strtonum($3);
+ if (relr_addr in section_offset_by_address) {
+ relr_offset = section_offset_by_address[relr_addr];
+ } else {
+ print FILENAME ": *** DT_RELR does not match any section's address";
+ result = 2;
+ }
+}
END { exit(result) }
This function is a cancellation point and therefore not marked with
__THROW. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int sigtimedwait (const sigset_t *__restrict __set,
siginfo_t *__restrict __info,
const struct timespec *__restrict __timeout)
tst-accept4 \
tst-cmsg_cloexec \
tst-cmsghdr \
+ tst-connect \
tst-sockopt \
# tests
This function is a cancellation point and therefore not marked with
__THROW. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern ssize_t sendmsg (int __fd, const struct msghdr *__message,
int __flags);
#else
This function is a cancellation point and therefore not marked with
__THROW. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int sendmmsg (int __fd, struct mmsghdr *__vmessages,
unsigned int __vlen, int __flags);
# else
unsigned int __vlen, int __flags);
# define sendmmsg __sendmmsg64
# endif
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
#endif /* __USE_GNU */
/* Receive a message as described by MESSAGE from socket FD.
This function is a cancellation point and therefore not marked with
__THROW. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags);
#else
# ifdef __REDIRECT
This function is a cancellation point and therefore not marked with
__THROW. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int recvmmsg (int __fd, struct mmsghdr *__vmessages,
unsigned int __vlen, int __flags,
struct timespec *__tmo);
/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL
into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's
actual length. Returns 0 on success, -1 for errors. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int getsockopt (int __fd, int __level, int __optname,
void *__restrict __optval,
socklen_t *__restrict __optlen) __THROW;
/* Set socket FD's option OPTNAME at protocol level LEVEL
to *OPTVAL (which is OPTLEN bytes long).
Returns 0 on success, -1 for errors. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int setsockopt (int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen) __THROW;
#else
__BEGIN_DECLS
/* Structure describing the address of an AF_LOCAL (aka AF_UNIX) socket. */
-struct sockaddr_un
+struct __attribute_struct_may_alias__ sockaddr_un
{
__SOCKADDR_COMMON (sun_);
char sun_path[108]; /* Path name. */
--- /dev/null
+/* Test the connect function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <support/check.h>
+#include <support/xsocket.h>
+#include <support/xunistd.h>
+#include <sys/socket.h>
+#include <stdio.h>
+
+static struct sockaddr_in server_address;
+
+int
+open_socket_inet_tcp (void)
+{
+ int fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fd < 0)
+ {
+ if (errno == EAFNOSUPPORT)
+ FAIL_UNSUPPORTED ("The host does not support IPv4");
+ else
+ FAIL_EXIT1 ("socket (AF_INET, SOCK_STREAM, IPPROTO_TCP): %m\n");
+ }
+ return fd;
+}
+
+static pid_t
+start_server (void)
+{
+ server_address.sin_family = AF_INET;
+ server_address.sin_port = 0;
+ server_address.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ int server_sock = open_socket_inet_tcp ();
+
+ xbind (server_sock, (struct sockaddr *) &server_address,
+ sizeof (server_address));
+
+ socklen_t sa_len = sizeof (server_address);
+ xgetsockname (server_sock, (struct sockaddr *) &server_address, &sa_len);
+ xlisten (server_sock, 5);
+
+ pid_t my_pid = xfork ();
+ if (my_pid > 0)
+ {
+ xclose (server_sock);
+ return my_pid;
+ }
+
+ struct sockaddr_in client_address;
+ socklen_t ca_len = sizeof (server_address);
+ int client_sock = xaccept (server_sock, (struct sockaddr *) &client_address,
+ &ca_len);
+ printf ("socket accepted %d\n", client_sock);
+
+ _exit (0);
+}
+
+static int
+do_test (void)
+{
+ pid_t serv_pid;
+ struct sockaddr_in peer;
+ socklen_t peer_len;
+
+ serv_pid = start_server ();
+ int client_sock = open_socket_inet_tcp ();
+ xconnect (client_sock, (const struct sockaddr *) &server_address,
+ sizeof (server_address));
+
+ /* A second connect with same arguments should fail with EISCONN. */
+ int result = connect (client_sock,
+ (const struct sockaddr *) &server_address,
+ sizeof (server_address));
+ if (result == 0 || errno != EISCONN)
+ FAIL_EXIT1 ("Second connect (%d), should fail with EISCONN: %m",
+ client_sock);
+
+ peer_len = sizeof (peer);
+ xgetpeername (client_sock, (struct sockaddr *) &peer, &peer_len);
+ TEST_COMPARE (peer_len, sizeof (peer));
+ TEST_COMPARE (peer.sin_port, server_address.sin_port);
+ TEST_COMPARE_BLOB (&peer.sin_addr, sizeof (peer.sin_addr),
+ &server_address.sin_addr,
+ sizeof (server_address.sin_addr));
+
+ int status;
+ xwaitpid (serv_pid, &status, 0);
+ TEST_COMPARE (status, 0);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
tst-setcontext10 \
tst-setcontext11 \
tst-stdbit-Wconversion \
+ tst-stdbit-builtins \
tst-stdc_bit_ceil \
tst-stdc_bit_floor \
tst-stdc_bit_width \
n -= l;
continue; /* Interrupted by a signal; keep going. */
}
- else if (l == -ENOSYS)
+ else if (l < 0 && errno == ENOSYS)
break; /* No syscall, so fallback to /dev/urandom. */
arc4random_getrandom_failure ();
}
__extension__
extern unsigned int stdc_leading_zeros_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_leading_zeros(x) \
+#if __glibc_has_builtin (__builtin_stdc_leading_zeros)
+# define stdc_leading_zeros(x) (__builtin_stdc_leading_zeros (x))
+#else
+# define stdc_leading_zeros(x) \
(stdc_leading_zeros_ull (x) \
- (unsigned int) (8 * (sizeof (0ULL) - sizeof (x))))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_leading_ones_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_leading_ones(x) \
+#if __glibc_has_builtin (__builtin_stdc_leading_ones)
+# define stdc_leading_ones(x) (__builtin_stdc_leading_ones (x))
+#else
+# define stdc_leading_ones(x) \
(stdc_leading_ones_ull ((unsigned long long int) (x) \
<< 8 * (sizeof (0ULL) - sizeof (x))))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_trailing_zeros_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_trailing_zeros(x) \
+#if __glibc_has_builtin (__builtin_stdc_trailing_zeros)
+# define stdc_trailing_zeros(x) (__builtin_stdc_trailing_zeros (x))
+#else
+# define stdc_trailing_zeros(x) \
(sizeof (x) == 8 ? stdc_trailing_zeros_ull (x) \
: sizeof (x) == 4 ? stdc_trailing_zeros_ui (x) \
: sizeof (x) == 2 ? stdc_trailing_zeros_us (__pacify_uint16 (x)) \
: stdc_trailing_zeros_uc (__pacify_uint8 (x)))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_trailing_ones_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_trailing_ones(x) (stdc_trailing_ones_ull (x))
+#if __glibc_has_builtin (__builtin_stdc_trailing_ones)
+# define stdc_trailing_ones(x) (__builtin_stdc_trailing_ones (x))
+#else
+# define stdc_trailing_ones(x) (stdc_trailing_ones_ull (x))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_first_leading_zero_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_first_leading_zero(x) \
+#if __glibc_has_builtin (__builtin_stdc_first_leading_zero)
+# define stdc_first_leading_zero(x) (__builtin_stdc_first_leading_zero (x))
+#else
+# define stdc_first_leading_zero(x) \
(sizeof (x) == 8 ? stdc_first_leading_zero_ull (x) \
: sizeof (x) == 4 ? stdc_first_leading_zero_ui (x) \
: sizeof (x) == 2 ? stdc_first_leading_zero_us (__pacify_uint16 (x)) \
: stdc_first_leading_zero_uc (__pacify_uint8 (x)))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_first_leading_one_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_first_leading_one(x) \
+#if __glibc_has_builtin (__builtin_stdc_first_leading_one)
+# define stdc_first_leading_one(x) (__builtin_stdc_first_leading_one (x))
+#else
+# define stdc_first_leading_one(x) \
(sizeof (x) == 8 ? stdc_first_leading_one_ull (x) \
: sizeof (x) == 4 ? stdc_first_leading_one_ui (x) \
: sizeof (x) == 2 ? stdc_first_leading_one_us (__pacify_uint16 (x)) \
: stdc_first_leading_one_uc (__pacify_uint8 (x)))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_first_trailing_zero_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_first_trailing_zero(x) \
+#if __glibc_has_builtin (__builtin_stdc_first_trailing_zero)
+# define stdc_first_trailing_zero(x) (__builtin_stdc_first_trailing_zero (x))
+#else
+# define stdc_first_trailing_zero(x) \
(sizeof (x) == 8 ? stdc_first_trailing_zero_ull (x) \
: sizeof (x) == 4 ? stdc_first_trailing_zero_ui (x) \
: sizeof (x) == 2 ? stdc_first_trailing_zero_us (__pacify_uint16 (x)) \
: stdc_first_trailing_zero_uc (__pacify_uint8 (x)))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_first_trailing_one_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_first_trailing_one(x) \
+#if __glibc_has_builtin (__builtin_stdc_first_trailing_one)
+# define stdc_first_trailing_one(x) (__builtin_stdc_first_trailing_one (x))
+#else
+# define stdc_first_trailing_one(x) \
(sizeof (x) == 8 ? stdc_first_trailing_one_ull (x) \
: sizeof (x) == 4 ? stdc_first_trailing_one_ui (x) \
: sizeof (x) == 2 ? stdc_first_trailing_one_us (__pacify_uint16 (x)) \
: stdc_first_trailing_one_uc (__pacify_uint8 (x)))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_count_zeros_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_count_zeros(x) \
+#if __glibc_has_builtin (__builtin_stdc_count_zeros)
+# define stdc_count_zeros(x) (__builtin_stdc_count_zeros (x))
+#else
+# define stdc_count_zeros(x) \
(stdc_count_zeros_ull (x) \
- (unsigned int) (8 * (sizeof (0ULL) - sizeof (x))))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_popcountll)
static __always_inline unsigned int
__extension__
extern unsigned int stdc_count_ones_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_count_ones(x) (stdc_count_ones_ull (x))
+#if __glibc_has_builtin (__builtin_stdc_count_ones)
+# define stdc_count_ones(x) (__builtin_stdc_count_ones (x))
+#else
+# define stdc_count_ones(x) (stdc_count_ones_ull (x))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_popcountll)
static __always_inline unsigned int
__extension__
extern bool stdc_has_single_bit_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_has_single_bit(x) \
+#if __glibc_has_builtin (__builtin_stdc_has_single_bit)
+# define stdc_has_single_bit(x) (__builtin_stdc_has_single_bit (x))
+#else
+# define stdc_has_single_bit(x) \
((bool) (sizeof (x) <= sizeof (unsigned int) \
? stdc_has_single_bit_ui (x) \
: stdc_has_single_bit_ull (x)))
+#endif
static __always_inline bool
__hsb64_inline (uint64_t __x)
__extension__
extern unsigned int stdc_bit_width_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_bit_width(x) (stdc_bit_width_ull (x))
+#if __glibc_has_builtin (__builtin_stdc_bit_width)
+# define stdc_bit_width(x) (__builtin_stdc_bit_width (x))
+#else
+# define stdc_bit_width(x) (stdc_bit_width_ull (x))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
static __always_inline unsigned int
__extension__
extern unsigned long long int stdc_bit_floor_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_bit_floor(x) ((__typeof (x)) stdc_bit_floor_ull (x))
+#if __glibc_has_builtin (__builtin_stdc_bit_floor)
+# define stdc_bit_floor(x) (__builtin_stdc_bit_floor (x))
+#else
+# define stdc_bit_floor(x) ((__typeof (x)) stdc_bit_floor_ull (x))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
static __always_inline uint64_t
__extension__
extern unsigned long long int stdc_bit_ceil_ull (unsigned long long int __x)
__THROW __attribute_const__;
-#define stdc_bit_ceil(x) ((__typeof (x)) stdc_bit_ceil_ull (x))
+#if __glibc_has_builtin (__builtin_stdc_bit_ceil)
+# define stdc_bit_ceil(x) (__builtin_stdc_bit_ceil (x))
+#else
+# define stdc_bit_ceil(x) ((__typeof (x)) stdc_bit_ceil_ull (x))
+#endif
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
static __always_inline uint64_t
--- /dev/null
+/* Test <stdbit.h> type-generic macros with compiler __builtin_stdc_* support.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdbit.h>
+#include <limits.h>
+#include <support/check.h>
+
+#if __glibc_has_builtin (__builtin_stdc_leading_zeros) \
+ && __glibc_has_builtin (__builtin_stdc_leading_ones) \
+ && __glibc_has_builtin (__builtin_stdc_trailing_zeros) \
+ && __glibc_has_builtin (__builtin_stdc_trailing_ones) \
+ && __glibc_has_builtin (__builtin_stdc_first_leading_zero) \
+ && __glibc_has_builtin (__builtin_stdc_first_leading_one) \
+ && __glibc_has_builtin (__builtin_stdc_first_trailing_zero) \
+ && __glibc_has_builtin (__builtin_stdc_first_trailing_one) \
+ && __glibc_has_builtin (__builtin_stdc_count_zeros) \
+ && __glibc_has_builtin (__builtin_stdc_count_ones) \
+ && __glibc_has_builtin (__builtin_stdc_has_single_bit) \
+ && __glibc_has_builtin (__builtin_stdc_bit_width) \
+ && __glibc_has_builtin (__builtin_stdc_bit_floor) \
+ && __glibc_has_builtin (__builtin_stdc_bit_ceil)
+
+# if !defined (BITINT_MAXWIDTH) && defined (__BITINT_MAXWIDTH__)
+# define BITINT_MAXWIDTH __BITINT_MAXWIDTH__
+# endif
+
+typedef unsigned char uc;
+typedef unsigned short us;
+typedef unsigned int ui;
+typedef unsigned long int ul;
+typedef unsigned long long int ull;
+
+# define expr_has_type(e, t) _Generic (e, default : 0, t : 1)
+
+static int
+do_test (void)
+{
+ TEST_COMPARE (stdc_leading_zeros ((uc) 0), CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_leading_zeros ((us) 0), sizeof (short) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_leading_zeros (0U), sizeof (int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros (0U), ui), 1);
+ TEST_COMPARE (stdc_leading_zeros (0UL), sizeof (long int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros (0UL), ui), 1);
+ TEST_COMPARE (stdc_leading_zeros (0ULL), sizeof (long long int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros (0ULL), ui), 1);
+ TEST_COMPARE (stdc_leading_zeros ((uc) ~0U), 0);
+ TEST_COMPARE (stdc_leading_zeros ((us) ~0U), 0);
+ TEST_COMPARE (stdc_leading_zeros (~0U), 0);
+ TEST_COMPARE (stdc_leading_zeros (~0UL), 0);
+ TEST_COMPARE (stdc_leading_zeros (~0ULL), 0);
+ TEST_COMPARE (stdc_leading_zeros ((uc) 3), CHAR_BIT - 2);
+ TEST_COMPARE (stdc_leading_zeros ((us) 9), sizeof (short) * CHAR_BIT - 4);
+ TEST_COMPARE (stdc_leading_zeros (34U), sizeof (int) * CHAR_BIT - 6);
+ TEST_COMPARE (stdc_leading_zeros (130UL), sizeof (long int) * CHAR_BIT - 8);
+ TEST_COMPARE (stdc_leading_zeros (512ULL),
+ sizeof (long long int) * CHAR_BIT - 10);
+ TEST_COMPARE (stdc_leading_ones ((uc) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_leading_ones ((us) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_leading_ones (0U), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones (0U), ui), 1);
+ TEST_COMPARE (stdc_leading_ones (0UL), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones (0UL), ui), 1);
+ TEST_COMPARE (stdc_leading_ones (0ULL), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones (0ULL), ui), 1);
+ TEST_COMPARE (stdc_leading_ones ((uc) ~0U), CHAR_BIT);
+ TEST_COMPARE (stdc_leading_ones ((us) ~0U), sizeof (short) * CHAR_BIT);
+ TEST_COMPARE (stdc_leading_ones (~0U), sizeof (int) * CHAR_BIT);
+ TEST_COMPARE (stdc_leading_ones (~0UL), sizeof (long int) * CHAR_BIT);
+ TEST_COMPARE (stdc_leading_ones (~0ULL), sizeof (long long int) * CHAR_BIT);
+ TEST_COMPARE (stdc_leading_ones ((uc) ~3), CHAR_BIT - 2);
+ TEST_COMPARE (stdc_leading_ones ((us) ~9), sizeof (short) * CHAR_BIT - 4);
+ TEST_COMPARE (stdc_leading_ones (~34U), sizeof (int) * CHAR_BIT - 6);
+ TEST_COMPARE (stdc_leading_ones (~130UL), sizeof (long int) * CHAR_BIT - 8);
+ TEST_COMPARE (stdc_leading_ones (~512ULL),
+ sizeof (long long int) * CHAR_BIT - 10);
+ TEST_COMPARE (stdc_trailing_zeros ((uc) 0), CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros ((us) 0), sizeof (short) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros (0U), sizeof (int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros (0U), ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros (0UL), sizeof (long int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros (0UL), ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros (0ULL), sizeof (long long int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros (0ULL), ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros ((uc) ~0U), 0);
+ TEST_COMPARE (stdc_trailing_zeros ((us) ~0U), 0);
+ TEST_COMPARE (stdc_trailing_zeros (~0U), 0);
+ TEST_COMPARE (stdc_trailing_zeros (~0UL), 0);
+ TEST_COMPARE (stdc_trailing_zeros (~0ULL), 0);
+ TEST_COMPARE (stdc_trailing_zeros ((uc) 2), 1);
+ TEST_COMPARE (stdc_trailing_zeros ((us) 24), 3);
+ TEST_COMPARE (stdc_trailing_zeros (32U), 5);
+ TEST_COMPARE (stdc_trailing_zeros (128UL), 7);
+ TEST_COMPARE (stdc_trailing_zeros (512ULL), 9);
+ TEST_COMPARE (stdc_trailing_ones ((uc) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_trailing_ones ((us) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_trailing_ones (0U), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones (0U), ui), 1);
+ TEST_COMPARE (stdc_trailing_ones (0UL), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones (0UL), ui), 1);
+ TEST_COMPARE (stdc_trailing_ones (0ULL), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones (0ULL), ui), 1);
+ TEST_COMPARE (stdc_trailing_ones ((uc) ~0U), CHAR_BIT);
+ TEST_COMPARE (stdc_trailing_ones ((us) ~0U), sizeof (short) * CHAR_BIT);
+ TEST_COMPARE (stdc_trailing_ones (~0U), sizeof (int) * CHAR_BIT);
+ TEST_COMPARE (stdc_trailing_ones (~0UL), sizeof (long int) * CHAR_BIT);
+ TEST_COMPARE (stdc_trailing_ones (~0ULL), sizeof (long long int) * CHAR_BIT);
+ TEST_COMPARE (stdc_trailing_ones ((uc) 5), 1);
+ TEST_COMPARE (stdc_trailing_ones ((us) 15), 4);
+ TEST_COMPARE (stdc_trailing_ones (127U), 7);
+ TEST_COMPARE (stdc_trailing_ones (511UL), 9);
+ TEST_COMPARE (stdc_trailing_ones (~0ULL >> 2),
+ sizeof (long long int) * CHAR_BIT - 2);
+ TEST_COMPARE (stdc_first_leading_zero ((uc) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero ((us) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero (0U), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero (0U), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero (0UL), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero (0UL), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero (0ULL), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero (0ULL), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero ((uc) ~0U), 0);
+ TEST_COMPARE (stdc_first_leading_zero ((us) ~0U), 0);
+ TEST_COMPARE (stdc_first_leading_zero (~0U), 0);
+ TEST_COMPARE (stdc_first_leading_zero (~0UL), 0);
+ TEST_COMPARE (stdc_first_leading_zero (~0ULL), 0);
+ TEST_COMPARE (stdc_first_leading_zero ((uc) ~3U), CHAR_BIT - 1);
+ TEST_COMPARE (stdc_first_leading_zero ((us) ~15U),
+ sizeof (short) * CHAR_BIT - 3);
+ TEST_COMPARE (stdc_first_leading_zero (~63U), sizeof (int) * CHAR_BIT - 5);
+ TEST_COMPARE (stdc_first_leading_zero (~255UL),
+ sizeof (long int) * CHAR_BIT - 7);
+ TEST_COMPARE (stdc_first_leading_zero (~1023ULL),
+ sizeof (long long int) * CHAR_BIT - 9);
+ TEST_COMPARE (stdc_first_leading_one ((uc) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one ((us) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one (0U), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one (0U), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one (0UL), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one (0UL), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one (0ULL), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one (0ULL), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one ((uc) ~0U), 1);
+ TEST_COMPARE (stdc_first_leading_one ((us) ~0U), 1);
+ TEST_COMPARE (stdc_first_leading_one (~0U), 1);
+ TEST_COMPARE (stdc_first_leading_one (~0UL), 1);
+ TEST_COMPARE (stdc_first_leading_one (~0ULL), 1);
+ TEST_COMPARE (stdc_first_leading_one ((uc) 3), CHAR_BIT - 1);
+ TEST_COMPARE (stdc_first_leading_one ((us) 9),
+ sizeof (short) * CHAR_BIT - 3);
+ TEST_COMPARE (stdc_first_leading_one (34U), sizeof (int) * CHAR_BIT - 5);
+ TEST_COMPARE (stdc_first_leading_one (130UL),
+ sizeof (long int) * CHAR_BIT - 7);
+ TEST_COMPARE (stdc_first_leading_one (512ULL),
+ sizeof (long long int) * CHAR_BIT - 9);
+ TEST_COMPARE (stdc_first_trailing_zero ((uc) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero ((us) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero (0U), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero (0U), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero (0UL), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero (0UL), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero (0ULL), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero (0ULL), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero ((uc) ~0U), 0);
+ TEST_COMPARE (stdc_first_trailing_zero ((us) ~0U), 0);
+ TEST_COMPARE (stdc_first_trailing_zero (~0U), 0);
+ TEST_COMPARE (stdc_first_trailing_zero (~0UL), 0);
+ TEST_COMPARE (stdc_first_trailing_zero (~0ULL), 0);
+ TEST_COMPARE (stdc_first_trailing_zero ((uc) 2), 1);
+ TEST_COMPARE (stdc_first_trailing_zero ((us) 15), 5);
+ TEST_COMPARE (stdc_first_trailing_zero (63U), 7);
+ TEST_COMPARE (stdc_first_trailing_zero (128UL), 1);
+ TEST_COMPARE (stdc_first_trailing_zero (511ULL), 10);
+ TEST_COMPARE (stdc_first_trailing_one ((uc) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one ((us) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one (0U), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one (0U), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one (0UL), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one (0UL), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one (0ULL), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one (0ULL), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one ((uc) ~0U), 1);
+ TEST_COMPARE (stdc_first_trailing_one ((us) ~0U), 1);
+ TEST_COMPARE (stdc_first_trailing_one (~0U), 1);
+ TEST_COMPARE (stdc_first_trailing_one (~0UL), 1);
+ TEST_COMPARE (stdc_first_trailing_one (~0ULL), 1);
+ TEST_COMPARE (stdc_first_trailing_one ((uc) 4), 3);
+ TEST_COMPARE (stdc_first_trailing_one ((us) 96), 6);
+ TEST_COMPARE (stdc_first_trailing_one (127U), 1);
+ TEST_COMPARE (stdc_first_trailing_one (511UL), 1);
+ TEST_COMPARE (stdc_first_trailing_one (~0ULL << 12), 13);
+ TEST_COMPARE (stdc_count_zeros ((uc) 0), CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_count_zeros ((us) 0), sizeof (short) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_count_zeros (0U), sizeof (int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros (0U), ui), 1);
+ TEST_COMPARE (stdc_count_zeros (0UL), sizeof (long int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros (0UL), ui), 1);
+ TEST_COMPARE (stdc_count_zeros (0ULL), sizeof (long long int) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros (0ULL), ui), 1);
+ TEST_COMPARE (stdc_count_zeros ((uc) ~0U), 0);
+ TEST_COMPARE (stdc_count_zeros ((us) ~0U), 0);
+ TEST_COMPARE (stdc_count_zeros (~0U), 0);
+ TEST_COMPARE (stdc_count_zeros (~0UL), 0);
+ TEST_COMPARE (stdc_count_zeros (~0ULL), 0);
+ TEST_COMPARE (stdc_count_zeros ((uc) 1U), CHAR_BIT - 1);
+ TEST_COMPARE (stdc_count_zeros ((us) 42), sizeof (short) * CHAR_BIT - 3);
+ TEST_COMPARE (stdc_count_zeros (291U), sizeof (int) * CHAR_BIT - 4);
+ TEST_COMPARE (stdc_count_zeros (~1315UL), 5);
+ TEST_COMPARE (stdc_count_zeros (3363ULL),
+ sizeof (long long int) * CHAR_BIT - 6);
+ TEST_COMPARE (stdc_count_ones ((uc) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_count_ones ((us) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_count_ones (0U), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones (0U), ui), 1);
+ TEST_COMPARE (stdc_count_ones (0UL), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones (0UL), ui), 1);
+ TEST_COMPARE (stdc_count_ones (0ULL), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones (0ULL), ui), 1);
+ TEST_COMPARE (stdc_count_ones ((uc) ~0U), CHAR_BIT);
+ TEST_COMPARE (stdc_count_ones ((us) ~0U), sizeof (short) * CHAR_BIT);
+ TEST_COMPARE (stdc_count_ones (~0U), sizeof (int) * CHAR_BIT);
+ TEST_COMPARE (stdc_count_ones (~0UL), sizeof (long int) * CHAR_BIT);
+ TEST_COMPARE (stdc_count_ones (~0ULL), sizeof (long long int) * CHAR_BIT);
+ TEST_COMPARE (stdc_count_ones ((uc) ~1U), CHAR_BIT - 1);
+ TEST_COMPARE (stdc_count_ones ((us) ~42), sizeof (short) * CHAR_BIT - 3);
+ TEST_COMPARE (stdc_count_ones (~291U), sizeof (int) * CHAR_BIT - 4);
+ TEST_COMPARE (stdc_count_ones (1315UL), 5);
+ TEST_COMPARE (stdc_count_ones (~3363ULL),
+ sizeof (long long int) * CHAR_BIT - 6);
+ TEST_COMPARE (stdc_has_single_bit ((uc) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit ((uc) 0), _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit ((us) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit ((us) 0), _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit (0U), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit (0U), _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit (0UL), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit (0UL), _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit (0ULL), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit (0ULL), _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit ((uc) 2), 1);
+ TEST_COMPARE (stdc_has_single_bit ((us) 8), 1);
+ TEST_COMPARE (stdc_has_single_bit (32U), 1);
+ TEST_COMPARE (stdc_has_single_bit (128UL), 1);
+ TEST_COMPARE (stdc_has_single_bit (512ULL), 1);
+ TEST_COMPARE (stdc_has_single_bit ((uc) 7), 0);
+ TEST_COMPARE (stdc_has_single_bit ((us) 96), 0);
+ TEST_COMPARE (stdc_has_single_bit (513U), 0);
+ TEST_COMPARE (stdc_has_single_bit (1022UL), 0);
+ TEST_COMPARE (stdc_has_single_bit (12ULL), 0);
+ TEST_COMPARE (stdc_bit_width ((uc) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width ((uc) 0), ui), 1);
+ TEST_COMPARE (stdc_bit_width ((us) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width ((us) 0), ui), 1);
+ TEST_COMPARE (stdc_bit_width (0U), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width (0U), ui), 1);
+ TEST_COMPARE (stdc_bit_width (0UL), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width (0UL), ui), 1);
+ TEST_COMPARE (stdc_bit_width (0ULL), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width (0ULL), ui), 1);
+ TEST_COMPARE (stdc_bit_width ((uc) ~0U), CHAR_BIT);
+ TEST_COMPARE (stdc_bit_width ((us) ~0U), sizeof (short) * CHAR_BIT);
+ TEST_COMPARE (stdc_bit_width (~0U), sizeof (int) * CHAR_BIT);
+ TEST_COMPARE (stdc_bit_width (~0UL), sizeof (long int) * CHAR_BIT);
+ TEST_COMPARE (stdc_bit_width (~0ULL), sizeof (long long int) * CHAR_BIT);
+ TEST_COMPARE (stdc_bit_width ((uc) ((uc) ~0U >> 1)), CHAR_BIT - 1);
+ TEST_COMPARE (stdc_bit_width ((uc) 6), 3);
+ TEST_COMPARE (stdc_bit_width ((us) 12U), 4);
+ TEST_COMPARE (stdc_bit_width ((us) ((us) ~0U >> 5)),
+ sizeof (short) * CHAR_BIT - 5);
+ TEST_COMPARE (stdc_bit_width (137U), 8);
+ TEST_COMPARE (stdc_bit_width (269U), 9);
+ TEST_COMPARE (stdc_bit_width (39UL), 6);
+ TEST_COMPARE (stdc_bit_width (~0UL >> 2), sizeof (long int) * CHAR_BIT - 2);
+ TEST_COMPARE (stdc_bit_width (1023ULL), 10);
+ TEST_COMPARE (stdc_bit_width (1024ULL), 11);
+ TEST_COMPARE (stdc_bit_floor ((uc) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor ((uc) 0), uc), 1);
+ TEST_COMPARE (stdc_bit_floor ((us) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor ((us) 0), us), 1);
+ TEST_COMPARE (stdc_bit_floor (0U), 0U);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor (0U), ui), 1);
+ TEST_COMPARE (stdc_bit_floor (0UL), 0UL);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor (0UL), ul), 1);
+ TEST_COMPARE (stdc_bit_floor (0ULL), 0ULL);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor (0ULL), ull), 1);
+ TEST_COMPARE (stdc_bit_floor ((uc) ~0U), (1U << (CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_floor ((us) ~0U),
+ (1U << (sizeof (short) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_floor (~0U), (1U << (sizeof (int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_floor (~0UL),
+ (1UL << (sizeof (long int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_floor (~0ULL),
+ (1ULL << (sizeof (long long int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_floor ((uc) 4), 4);
+ TEST_COMPARE (stdc_bit_floor ((uc) 7), 4);
+ TEST_COMPARE (stdc_bit_floor ((us) 8U), 8);
+ TEST_COMPARE (stdc_bit_floor ((us) 31U), 16);
+ TEST_COMPARE (stdc_bit_floor (137U), 128U);
+ TEST_COMPARE (stdc_bit_floor (269U), 256U);
+ TEST_COMPARE (stdc_bit_floor (511UL), 256UL);
+ TEST_COMPARE (stdc_bit_floor (512UL), 512UL);
+ TEST_COMPARE (stdc_bit_floor (513UL), 512ULL);
+ TEST_COMPARE (stdc_bit_floor (1024ULL), 1024ULL);
+ TEST_COMPARE (stdc_bit_ceil ((uc) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil ((uc) 0), uc), 1);
+ TEST_COMPARE (stdc_bit_ceil ((us) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil ((us) 0), us), 1);
+ TEST_COMPARE (stdc_bit_ceil (0U), 1U);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil (0U), ui), 1);
+ TEST_COMPARE (stdc_bit_ceil (0UL), 1UL);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil (0UL), ul), 1);
+ TEST_COMPARE (stdc_bit_ceil (0ULL), 1ULL);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil (0ULL), ull), 1);
+ TEST_COMPARE (stdc_bit_ceil ((uc) ~0U), 0);
+ TEST_COMPARE (stdc_bit_ceil ((us) ~0U), 0);
+ TEST_COMPARE (stdc_bit_ceil (~0U), 0U);
+ TEST_COMPARE (stdc_bit_ceil (~0UL), 0UL);
+ TEST_COMPARE (stdc_bit_ceil (~0ULL), 0ULL);
+ TEST_COMPARE (stdc_bit_ceil ((uc) ((uc) ~0U >> 1)), (1U << (CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil ((uc) ((uc) ~0U >> 1)), (1U << (CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil ((us) ((us) ~0U >> 1)),
+ (1U << (sizeof (short) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil ((us) ((us) ~0U >> 1)),
+ (1U << (sizeof (short) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil (~0U >> 1),
+ (1U << (sizeof (int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil (1U << (sizeof (int) * CHAR_BIT - 1)),
+ (1U << (sizeof (int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil (~0UL >> 1),
+ (1UL << (sizeof (long int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil (~0UL >> 1),
+ (1UL << (sizeof (long int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil (1ULL
+ << (sizeof (long long int) * CHAR_BIT - 1)),
+ (1ULL << (sizeof (long long int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil (~0ULL >> 1),
+ (1ULL << (sizeof (long long int) * CHAR_BIT - 1)));
+ TEST_COMPARE (stdc_bit_ceil ((uc) 1), 1);
+ TEST_COMPARE (stdc_bit_ceil ((uc) 2), 2);
+ TEST_COMPARE (stdc_bit_ceil ((us) 3U), 4);
+ TEST_COMPARE (stdc_bit_ceil ((us) 4U), 4);
+ TEST_COMPARE (stdc_bit_ceil (5U), 8U);
+ TEST_COMPARE (stdc_bit_ceil (269U), 512U);
+ TEST_COMPARE (stdc_bit_ceil (511UL), 512UL);
+ TEST_COMPARE (stdc_bit_ceil (512UL), 512UL);
+ TEST_COMPARE (stdc_bit_ceil (513ULL), 1024ULL);
+ TEST_COMPARE (stdc_bit_ceil (1025ULL), 2048ULL);
+# ifdef __SIZEOF_INT128__
+ TEST_COMPARE (stdc_leading_zeros ((unsigned __int128) 0),
+ sizeof (__int128) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros ((unsigned __int128) 0), ui),
+ 1);
+ TEST_COMPARE (stdc_leading_zeros (~(unsigned __int128) 0), 0);
+ TEST_COMPARE (stdc_leading_ones ((unsigned __int128) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones ((unsigned __int128) 0), ui),
+ 1);
+ TEST_COMPARE (stdc_leading_ones (~(unsigned __int128) 0),
+ sizeof (__int128) * CHAR_BIT);
+ TEST_COMPARE (stdc_trailing_zeros ((unsigned __int128) 0),
+ sizeof (__int128) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros ((unsigned __int128) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros (~(unsigned __int128) 0), 0);
+ TEST_COMPARE (stdc_trailing_ones ((unsigned __int128) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones ((unsigned __int128) 0), ui),
+ 1);
+ TEST_COMPARE (stdc_trailing_ones (~(unsigned __int128) 0),
+ sizeof (__int128) * CHAR_BIT);
+ TEST_COMPARE (stdc_first_leading_zero ((unsigned __int128) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero ((unsigned __int128) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero (~(unsigned __int128) 0), 0);
+ TEST_COMPARE (stdc_first_leading_one ((unsigned __int128) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one ((unsigned __int128) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_first_leading_one (~(unsigned __int128) 0), 1);
+ TEST_COMPARE (stdc_first_trailing_zero ((unsigned __int128) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero ((unsigned __int128)
+ 0), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero (~(unsigned __int128) 0), 0);
+ TEST_COMPARE (stdc_first_trailing_one ((unsigned __int128) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one ((unsigned __int128) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one (~(unsigned __int128) 0), 1);
+ TEST_COMPARE (stdc_count_zeros ((unsigned __int128) 0),
+ sizeof (__int128) * CHAR_BIT);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros ((unsigned __int128) 0), ui),
+ 1);
+ TEST_COMPARE (stdc_count_zeros (~(unsigned __int128) 0), 0);
+ TEST_COMPARE (stdc_count_ones ((unsigned __int128) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones ((unsigned __int128) 0), ui),
+ 1);
+ TEST_COMPARE (stdc_count_ones (~(unsigned __int128) 0),
+ sizeof (__int128) * CHAR_BIT);
+ TEST_COMPARE (stdc_has_single_bit ((unsigned __int128) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit ((unsigned __int128) 0),
+ _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit (~(unsigned __int128) 0), 0);
+ TEST_COMPARE (stdc_bit_width ((unsigned __int128) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width ((unsigned __int128) 0), ui), 1);
+ TEST_COMPARE (stdc_bit_width (~(unsigned __int128) 0),
+ sizeof (__int128) * CHAR_BIT);
+ TEST_COMPARE (stdc_bit_floor ((unsigned __int128) 0) != 0, 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor ((unsigned __int128) 0),
+ unsigned __int128), 1);
+ TEST_COMPARE (stdc_bit_floor (~(unsigned __int128) 0)
+ != ((unsigned __int128) 1) << (sizeof (__int128)
+ * CHAR_BIT - 1), 0);
+ TEST_COMPARE (stdc_bit_ceil ((unsigned __int128) 0) != 1, 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil ((unsigned __int128) 0),
+ unsigned __int128), 1);
+ TEST_COMPARE (stdc_bit_ceil ((unsigned __int128) 1) != 1, 0);
+ TEST_COMPARE (stdc_bit_ceil ((~(unsigned __int128) 0) >> 1)
+ != ((unsigned __int128) 1) << (sizeof (__int128)
+ * CHAR_BIT - 1), 0);
+ TEST_COMPARE (stdc_bit_ceil (~(unsigned __int128) 0) != 0, 0);
+# endif
+ uc a = 0;
+ TEST_COMPARE (stdc_bit_width (a++), 0);
+ TEST_COMPARE (a, 1);
+ ull b = 0;
+ TEST_COMPARE (stdc_bit_width (b++), 0);
+ TEST_COMPARE (b, 1);
+ TEST_COMPARE (stdc_bit_floor (a++), 1);
+ TEST_COMPARE (a, 2);
+ TEST_COMPARE (stdc_bit_floor (b++), 1);
+ TEST_COMPARE (b, 2);
+ TEST_COMPARE (stdc_bit_ceil (a++), 2);
+ TEST_COMPARE (a, 3);
+ TEST_COMPARE (stdc_bit_ceil (b++), 2);
+ TEST_COMPARE (b, 3);
+ TEST_COMPARE (stdc_leading_zeros (a++), CHAR_BIT - 2);
+ TEST_COMPARE (a, 4);
+ TEST_COMPARE (stdc_leading_zeros (b++),
+ sizeof (long long int) * CHAR_BIT - 2);
+ TEST_COMPARE (b, 4);
+ TEST_COMPARE (stdc_leading_ones (a++), 0);
+ TEST_COMPARE (a, 5);
+ TEST_COMPARE (stdc_leading_ones (b++), 0);
+ TEST_COMPARE (b, 5);
+ TEST_COMPARE (stdc_trailing_zeros (a++), 0);
+ TEST_COMPARE (a, 6);
+ TEST_COMPARE (stdc_trailing_zeros (b++), 0);
+ TEST_COMPARE (b, 6);
+ TEST_COMPARE (stdc_trailing_ones (a++), 0);
+ TEST_COMPARE (a, 7);
+ TEST_COMPARE (stdc_trailing_ones (b++), 0);
+ TEST_COMPARE (b, 7);
+ TEST_COMPARE (stdc_first_leading_zero (a++), 1);
+ TEST_COMPARE (a, 8);
+ TEST_COMPARE (stdc_first_leading_zero (b++), 1);
+ TEST_COMPARE (b, 8);
+ TEST_COMPARE (stdc_first_leading_one (a++), CHAR_BIT - 3);
+ TEST_COMPARE (a, 9);
+ TEST_COMPARE (stdc_first_leading_one (b++),
+ sizeof (long long int) * CHAR_BIT - 3);
+ TEST_COMPARE (b, 9);
+ TEST_COMPARE (stdc_first_trailing_zero (a++), 2);
+ TEST_COMPARE (a, 10);
+ TEST_COMPARE (stdc_first_trailing_zero (b++), 2);
+ TEST_COMPARE (b, 10);
+ TEST_COMPARE (stdc_first_trailing_one (a++), 2);
+ TEST_COMPARE (a, 11);
+ TEST_COMPARE (stdc_first_trailing_one (b++), 2);
+ TEST_COMPARE (b, 11);
+ TEST_COMPARE (stdc_count_zeros (a++), CHAR_BIT - 3);
+ TEST_COMPARE (a, 12);
+ TEST_COMPARE (stdc_count_zeros (b++),
+ sizeof (long long int) * CHAR_BIT - 3);
+ TEST_COMPARE (b, 12);
+ TEST_COMPARE (stdc_count_ones (a++), 2);
+ TEST_COMPARE (a, 13);
+ TEST_COMPARE (stdc_count_ones (b++), 2);
+ TEST_COMPARE (b, 13);
+ TEST_COMPARE (stdc_has_single_bit (a++), 0);
+ TEST_COMPARE (a, 14);
+ TEST_COMPARE (stdc_has_single_bit (b++), 0);
+ TEST_COMPARE (b, 14);
+# ifdef BITINT_MAXWIDTH
+# if BITINT_MAXWIDTH >= 64
+ TEST_COMPARE (stdc_leading_zeros (0uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros (0uwb), ui), 1);
+ TEST_COMPARE (stdc_leading_zeros (1uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros (1uwb), ui), 1);
+ TEST_COMPARE (stdc_leading_ones (0uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones (0uwb), ui), 1);
+ TEST_COMPARE (stdc_leading_ones (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones (1uwb), ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros (0uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros (0uwb), ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros (1uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros (1uwb), ui), 1);
+ TEST_COMPARE (stdc_trailing_ones (0uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones (0uwb), ui), 1);
+ TEST_COMPARE (stdc_trailing_ones (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones (1uwb), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero (0uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero (0uwb), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero (1uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero (1uwb), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one (0uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one (0uwb), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one (1uwb), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero (0uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero (0uwb), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero (1uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero (1uwb), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one (0uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one (0uwb), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one (1uwb), ui), 1);
+ TEST_COMPARE (stdc_count_zeros (0uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros (0uwb), ui), 1);
+ TEST_COMPARE (stdc_count_zeros (1uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros (1uwb), ui), 1);
+ TEST_COMPARE (stdc_count_ones (0uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones (0uwb), ui), 1);
+ TEST_COMPARE (stdc_count_ones (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_count_ones (1uwb), ui), 1);
+ TEST_COMPARE (stdc_has_single_bit (0uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit (0uwb), _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit (1uwb), _Bool), 1);
+ TEST_COMPARE (stdc_bit_width (0uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width (0uwb), ui), 1);
+ TEST_COMPARE (stdc_bit_width (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_bit_width (1uwb), ui), 1);
+ TEST_COMPARE (stdc_bit_floor (0uwb), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor (0uwb), unsigned _BitInt(1)), 1);
+ TEST_COMPARE (stdc_bit_floor (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor (1uwb), unsigned _BitInt(1)), 1);
+ TEST_COMPARE (stdc_bit_ceil (0uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil (0uwb), unsigned _BitInt(1)), 1);
+ TEST_COMPARE (stdc_bit_ceil (1uwb), 1);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil (1uwb), unsigned _BitInt(1)), 1);
+ unsigned _BitInt(1) c = 0;
+ TEST_COMPARE (stdc_bit_floor (c++), 0);
+ TEST_COMPARE (c, 1);
+ TEST_COMPARE (stdc_bit_floor (c++), 1);
+ TEST_COMPARE (c, 0);
+ TEST_COMPARE (stdc_bit_ceil (c++), 1);
+ TEST_COMPARE (c, 1);
+ TEST_COMPARE (stdc_bit_ceil (c++), 1);
+ TEST_COMPARE (c, 0);
+# endif
+# if BITINT_MAXWIDTH >= 512
+ TEST_COMPARE (stdc_leading_zeros ((unsigned _BitInt(512)) 0), 512);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros ((unsigned _BitInt(512)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_leading_zeros ((unsigned _BitInt(373)) 0), 373);
+ TEST_COMPARE (expr_has_type (stdc_leading_zeros ((unsigned _BitInt(373)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_leading_zeros (~(unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (stdc_leading_zeros (~(unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (stdc_leading_zeros ((unsigned _BitInt(512)) 275), 512 - 9);
+ TEST_COMPARE (stdc_leading_zeros ((unsigned _BitInt(373)) 512), 373 - 10);
+ TEST_COMPARE (stdc_leading_ones ((unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones ((unsigned _BitInt(512)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_leading_ones ((unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_leading_ones ((unsigned _BitInt(373)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_leading_ones (~(unsigned _BitInt(512)) 0), 512);
+ TEST_COMPARE (stdc_leading_ones (~(unsigned _BitInt(373)) 0), 373);
+ TEST_COMPARE (stdc_leading_ones (~(unsigned _BitInt(512)) 275), 512 - 9);
+ TEST_COMPARE (stdc_leading_ones (~(unsigned _BitInt(373)) 512), 373 - 10);
+ TEST_COMPARE (stdc_trailing_zeros ((unsigned _BitInt(512)) 0), 512);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros ((unsigned _BitInt(512)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros ((unsigned _BitInt(373)) 0), 373);
+ TEST_COMPARE (expr_has_type (stdc_trailing_zeros ((unsigned _BitInt(373)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_trailing_zeros (~(unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (stdc_trailing_zeros (~(unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (stdc_trailing_zeros ((unsigned _BitInt(512)) 256), 8);
+ TEST_COMPARE (stdc_trailing_zeros ((unsigned _BitInt(373)) 512), 9);
+ TEST_COMPARE (stdc_trailing_ones ((unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones ((unsigned _BitInt(512)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_trailing_ones ((unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_trailing_ones ((unsigned _BitInt(373)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_trailing_ones (~(unsigned _BitInt(512)) 0), 512);
+ TEST_COMPARE (stdc_trailing_ones (~(unsigned _BitInt(373)) 0), 373);
+ TEST_COMPARE (stdc_trailing_ones ((unsigned _BitInt(512)) 255), 8);
+ TEST_COMPARE (stdc_trailing_ones ((~(unsigned _BitInt(373)) 0) >> 2),
+ 373 - 2);
+ TEST_COMPARE (stdc_first_leading_zero ((unsigned _BitInt(512)) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero ((unsigned _BitInt(512))
+ 0), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero ((unsigned _BitInt(373)) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_zero ((unsigned _BitInt(373))
+ 0), ui), 1);
+ TEST_COMPARE (stdc_first_leading_zero (~(unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (stdc_first_leading_zero (~(unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (stdc_first_leading_zero (~(unsigned _BitInt(512)) 511),
+ 512 - 8);
+ TEST_COMPARE (stdc_first_leading_zero (~(unsigned _BitInt(373)) 1023),
+ 373 - 9);
+ TEST_COMPARE (stdc_first_leading_one ((unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one ((unsigned _BitInt(512))
+ 0), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one ((unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_leading_one ((unsigned _BitInt(373))
+ 0), ui), 1);
+ TEST_COMPARE (stdc_first_leading_one (~(unsigned _BitInt(512)) 0), 1);
+ TEST_COMPARE (stdc_first_leading_one (~(unsigned _BitInt(373)) 0), 1);
+ TEST_COMPARE (stdc_first_leading_one ((unsigned _BitInt(512)) 275), 512 - 8);
+ TEST_COMPARE (stdc_first_leading_one ((unsigned _BitInt(373)) 512), 373 - 9);
+ TEST_COMPARE (stdc_first_trailing_zero ((unsigned _BitInt(512)) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero ((unsigned
+ _BitInt(512)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero ((unsigned _BitInt(373)) 0), 1);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_zero ((unsigned
+ _BitInt(373)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_first_trailing_zero (~(unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (stdc_first_trailing_zero (~(unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (stdc_first_trailing_zero ((unsigned _BitInt(512)) 255), 9);
+ TEST_COMPARE (stdc_first_trailing_zero ((unsigned _BitInt(373)) 511), 10);
+ TEST_COMPARE (stdc_first_trailing_one ((unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one ((unsigned _BitInt(512))
+ 0), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one ((unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_first_trailing_one ((unsigned _BitInt(373))
+ 0), ui), 1);
+ TEST_COMPARE (stdc_first_trailing_one (~(unsigned _BitInt(512)) 0), 1);
+ TEST_COMPARE (stdc_first_trailing_one (~(unsigned _BitInt(373)) 0), 1);
+ TEST_COMPARE (stdc_first_trailing_one (((unsigned _BitInt(512)) 255) << 175),
+ 176);
+ TEST_COMPARE (stdc_first_trailing_one ((~(unsigned _BitInt(373)) 0) << 311),
+ 312);
+ TEST_COMPARE (stdc_count_zeros ((unsigned _BitInt(512)) 0), 512);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros ((unsigned _BitInt(512)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_count_zeros ((unsigned _BitInt(373)) 0), 373);
+ TEST_COMPARE (expr_has_type (stdc_count_zeros ((unsigned _BitInt(373)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_count_zeros (~(unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (stdc_count_zeros (~(unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (stdc_count_zeros ((unsigned _BitInt(512)) 1315), 512 - 5);
+ TEST_COMPARE (stdc_count_zeros ((unsigned _BitInt(373)) 3363), 373 - 6);
+ TEST_COMPARE (stdc_count_ones ((unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones ((unsigned _BitInt(512)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_count_ones ((unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_count_ones ((unsigned _BitInt(373)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_count_ones (~(unsigned _BitInt(512)) 0), 512);
+ TEST_COMPARE (stdc_count_ones (~(unsigned _BitInt(373)) 0), 373);
+ TEST_COMPARE (stdc_count_ones (~(unsigned _BitInt(512)) 1315), 512 - 5);
+ TEST_COMPARE (stdc_count_ones (~(unsigned _BitInt(373)) 3363), 373 - 6);
+ TEST_COMPARE (stdc_has_single_bit ((unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit ((unsigned _BitInt(512)) 0),
+ _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit ((unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_has_single_bit ((unsigned _BitInt(373)) 0),
+ _Bool), 1);
+ TEST_COMPARE (stdc_has_single_bit (~(unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (stdc_has_single_bit (~(unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (stdc_has_single_bit (((unsigned _BitInt(512)) 1022) << 279),
+ 0);
+ TEST_COMPARE (stdc_has_single_bit (((unsigned _BitInt(373)) 12) << 305), 0);
+ TEST_COMPARE (stdc_bit_width ((unsigned _BitInt(512)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width ((unsigned _BitInt(512)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_bit_width ((unsigned _BitInt(373)) 0), 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_width ((unsigned _BitInt(373)) 0),
+ ui), 1);
+ TEST_COMPARE (stdc_bit_width (~(unsigned _BitInt(512)) 0), 512);
+ TEST_COMPARE (stdc_bit_width (~(unsigned _BitInt(373)) 0), 373);
+ TEST_COMPARE (stdc_bit_width (((unsigned _BitInt(512)) 1023) << 405),
+ 405 + 10);
+ TEST_COMPARE (stdc_bit_width (((unsigned _BitInt(373)) 1024) << 242),
+ 242 + 11);
+ TEST_COMPARE (stdc_bit_floor ((unsigned _BitInt(512)) 0) != 0, 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor ((unsigned _BitInt(512)) 0),
+ unsigned _BitInt(512)), 1);
+ TEST_COMPARE (stdc_bit_floor ((unsigned _BitInt(373)) 0) != 0, 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_floor ((unsigned _BitInt(373)) 0),
+ unsigned _BitInt(373)), 1);
+ TEST_COMPARE (stdc_bit_floor (~(unsigned _BitInt(512)) 0)
+ != ((unsigned _BitInt(512)) 1) << (512 - 1), 0);
+ TEST_COMPARE (stdc_bit_floor (~(unsigned _BitInt(373)) 0)
+ != ((unsigned _BitInt(373)) 1) << (373 - 1), 0);
+ TEST_COMPARE (stdc_bit_floor (((unsigned _BitInt(512)) 511) << 405)
+ != (((unsigned _BitInt(512)) 256) << 405), 0);
+ TEST_COMPARE (stdc_bit_floor (((unsigned _BitInt(373)) 512) << 242)
+ != (((unsigned _BitInt(512)) 512) << 242), 0);
+ TEST_COMPARE (stdc_bit_ceil ((unsigned _BitInt(512)) 0) != 1, 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil ((unsigned _BitInt(512)) 0),
+ unsigned _BitInt(512)), 1);
+ TEST_COMPARE (stdc_bit_ceil ((unsigned _BitInt(373)) 0) != 1, 0);
+ TEST_COMPARE (expr_has_type (stdc_bit_ceil ((unsigned _BitInt(373)) 0),
+ unsigned _BitInt(373)), 1);
+ TEST_COMPARE (stdc_bit_ceil (~(unsigned _BitInt(512)) 0) != 0, 0);
+ TEST_COMPARE (stdc_bit_ceil (~(unsigned _BitInt(373)) 0) != 0, 0);
+ TEST_COMPARE (stdc_bit_ceil (((unsigned _BitInt(512)) 1) << (512 - 1))
+ != ((unsigned _BitInt(512)) 1) << (512 - 1), 0);
+ TEST_COMPARE (stdc_bit_ceil ((~(unsigned _BitInt(373)) 0) >> 1)
+ != ((unsigned _BitInt(373)) 1) << (373 - 1), 0);
+ TEST_COMPARE (stdc_bit_ceil (((unsigned _BitInt(512)) 512) << 405)
+ != (((unsigned _BitInt(512)) 512) << 405), 0);
+ TEST_COMPARE (stdc_bit_ceil (((unsigned _BitInt(373)) 513) << 242)
+ != (((unsigned _BitInt(512)) 1024) << 242), 0);
+ TEST_COMPARE (stdc_bit_floor ((unsigned _BitInt(BITINT_MAXWIDTH)) 0) != 0,
+ 0);
+ TEST_COMPARE (stdc_bit_floor (~(unsigned _BitInt(BITINT_MAXWIDTH)) 0)
+ != ((unsigned _BitInt(BITINT_MAXWIDTH)) 1) << (BITINT_MAXWIDTH
+ - 1), 0);
+ TEST_COMPARE (stdc_bit_floor (((unsigned _BitInt(BITINT_MAXWIDTH)) 511)
+ << 405)
+ != (((unsigned _BitInt(BITINT_MAXWIDTH)) 256) << 405), 0);
+ TEST_COMPARE (stdc_bit_floor (((unsigned _BitInt(BITINT_MAXWIDTH)) 512)
+ << 405)
+ != (((unsigned _BitInt(BITINT_MAXWIDTH)) 512) << 405), 0);
+ TEST_COMPARE (stdc_bit_ceil ((unsigned _BitInt(BITINT_MAXWIDTH)) 0) != 1, 0);
+ TEST_COMPARE (stdc_bit_ceil (~(unsigned _BitInt(BITINT_MAXWIDTH)) 0) != 0,
+ 0);
+ TEST_COMPARE (stdc_bit_ceil (((unsigned _BitInt(BITINT_MAXWIDTH)) 1)
+ << (BITINT_MAXWIDTH - 1))
+ != ((unsigned _BitInt(BITINT_MAXWIDTH)) 1) << (BITINT_MAXWIDTH
+ - 1), 0);
+ TEST_COMPARE (stdc_bit_ceil (((unsigned _BitInt(BITINT_MAXWIDTH)) 512)
+ << 405)
+ != (((unsigned _BitInt(BITINT_MAXWIDTH)) 512) << 405), 0);
+ TEST_COMPARE (stdc_bit_ceil (((unsigned _BitInt(BITINT_MAXWIDTH)) 513)
+ << 405)
+ != (((unsigned _BitInt(BITINT_MAXWIDTH)) 1024) << 405), 0);
+# endif
+# endif
+ return 0;
+}
+#else
+static int
+do_test (void)
+{
+ return 0;
+}
+#endif
+
+#include <support/test-driver.c>
{
/* ____longjmp_chk has */
#if 0
-#ifdef _STACK_GROWS_DOWN
+#if _STACK_GROWS_DOWN
#define called_from(this, saved) ((this) < (saved))
#else
#define called_from(this, saved) ((this) > (saved))
/* Arrange stacks for uctx_func1 and uctx_func2 so that called_from
is true when setjmp is called from uctx_func1 and longjmp is called
from uctx_func2. */
-#ifdef _STACK_GROWS_DOWN
+#if _STACK_GROWS_DOWN
# define UCTX_FUNC1_STACK 1
# define UCTX_FUNC2_STACK 0
#else
xfreopen \
xftruncate \
xgetline \
+ xgetpeername \
xgetsockname \
xlisten \
xlseek \
enum { TIMESPEC_HZ = 1000000000 };
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
struct timespec timespec_add (struct timespec, struct timespec)
__attribute__((const));
struct timespec timespec_sub (struct timespec, struct timespec)
--- /dev/null
+/* getpeername with error checking.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/xsocket.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+
+void
+xgetpeername (int fd, struct sockaddr *sa, socklen_t *plen)
+{
+ if (getpeername (fd, sa, plen) != 0)
+ FAIL_EXIT1 ("getpeername (%d): %m", fd);
+}
int xsocket (int, int, int);
void xsetsockopt (int, int, int, const void *, socklen_t);
void xgetsockname (int, struct sockaddr *, socklen_t *);
+void xgetpeername (int, struct sockaddr *, socklen_t *);
void xconnect (int, const struct sockaddr *, socklen_t);
void xbind (int, const struct sockaddr *, socklen_t);
void xlisten (int, int);
/* The following functions call the corresponding libc functions and
terminate the process on error. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
void xclock_gettime (clockid_t clock, struct timespec *ts);
void xclock_settime (clockid_t clock, const struct timespec *ts);
#else
void xpipe (int[2]);
void xdup2 (int, int);
int xopen (const char *path, int flags, mode_t);
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
# ifdef __USE_FILE_OFFSET64
void xstat (const char *path, struct stat *);
void xlstat (const char *path, struct stat *);
printf %s "(cached) " >&6
else $as_nop
cat > conftest.s <<\EOF
- ptrue p0.b
+ .arch armv8.2-a+sve
+ ptrue p0.b
EOF
-if { ac_try='${CC-cc} -c -march=armv8.2-a+sve conftest.s 1>&5'
+if { ac_try='${CC-cc} -c conftest.s 1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
# Check if asm support armv8.2-a+sve
AC_CACHE_CHECK([for SVE support in assembler], [libc_cv_aarch64_sve_asm], [dnl
cat > conftest.s <<\EOF
- ptrue p0.b
+ .arch armv8.2-a+sve
+ ptrue p0.b
EOF
-if AC_TRY_COMMAND(${CC-cc} -c -march=armv8.2-a+sve conftest.s 1>&AS_MESSAGE_LOG_FD); then
+if AC_TRY_COMMAND(${CC-cc} -c conftest.s 1>&AS_MESSAGE_LOG_FD); then
libc_cv_aarch64_sve_asm=yes
else
libc_cv_aarch64_sve_asm=no
/* Currently, the GLIBC memory tagging tunable only defines 8 bits. */
uint8_t mte_state;
bool sve;
+ bool prefer_sve_ifuncs;
bool mops;
};
};
#define AllMask v_u64 (0xffffffffffffffff)
-#define Oneu (0x3ff0000000000000)
-#define Small (0x3e50000000000000) /* 2^-53. */
+#define Oneu 0x3ff0000000000000
+#define Small 0x3e50000000000000 /* 2^-53. */
#if WANT_SIMD_EXCEPT
static float64x2_t VPCS_ATTR NOINLINE
};
#define AllMask v_u64 (0xffffffffffffffff)
-#define One (0x3ff0000000000000)
-#define Small (0x3e50000000000000) /* 2^-12. */
+#define One 0x3ff0000000000000
+#define Small 0x3e50000000000000 /* 2^-12. */
#if WANT_SIMD_EXCEPT
static float64x2_t VPCS_ATTR NOINLINE
.pi_over_2 = 0x1.921fb54442d18p+0,
};
-/* Useful constants. */
-#define SignMask sv_u64 (0x8000000000000000)
-
/* Special cases i.e. 0, infinity, nan (fall back to scalar calls). */
static svfloat64_t NOINLINE
special_case (svfloat64_t y, svfloat64_t x, svfloat64_t ret,
svbool_t cmp_y = zeroinfnan (iy, pg);
svbool_t cmp_xy = svorr_z (pg, cmp_x, cmp_y);
- svuint64_t sign_x = svand_x (pg, ix, SignMask);
- svuint64_t sign_y = svand_x (pg, iy, SignMask);
- svuint64_t sign_xy = sveor_x (pg, sign_x, sign_y);
-
svfloat64_t ax = svabs_x (pg, x);
svfloat64_t ay = svabs_x (pg, y);
+ svuint64_t iax = svreinterpret_u64 (ax);
+ svuint64_t iay = svreinterpret_u64 (ay);
+
+ svuint64_t sign_x = sveor_x (pg, ix, iax);
+ svuint64_t sign_y = sveor_x (pg, iy, iay);
+ svuint64_t sign_xy = sveor_x (pg, sign_x, sign_y);
- svbool_t pred_xlt0 = svcmplt (pg, x, 0.0);
svbool_t pred_aygtax = svcmpgt (pg, ay, ax);
/* Set up z for call to atan. */
svfloat64_t z = svdiv_x (pg, n, d);
/* Work out the correct shift. */
- svfloat64_t shift = svsel (pred_xlt0, sv_f64 (-2.0), sv_f64 (0.0));
- shift = svsel (pred_aygtax, svadd_x (pg, shift, 1.0), shift);
+ svfloat64_t shift = svreinterpret_f64 (svlsr_x (pg, sign_x, 1));
+ shift = svsel (pred_aygtax, sv_f64 (1.0), shift);
+ shift = svreinterpret_f64 (svorr_x (pg, sign_x, svreinterpret_u64 (shift)));
shift = svmul_x (pg, shift, data_ptr->pi_over_2);
/* Use split Estrin scheme for P(z^2) with deg(P)=19. */
ret = svadd_m (pg, ret, shift);
/* Account for the sign of x and y. */
- ret = svreinterpret_f64 (sveor_x (pg, svreinterpret_u64 (ret), sign_xy));
-
if (__glibc_unlikely (svptest_any (pg, cmp_xy)))
- return special_case (y, x, ret, cmp_xy);
-
- return ret;
+ return special_case (
+ y, x,
+ svreinterpret_f64 (sveor_x (pg, svreinterpret_u64 (ret), sign_xy)),
+ cmp_xy);
+ return svreinterpret_f64 (sveor_x (pg, svreinterpret_u64 (ret), sign_xy));
}
.pi_over_2 = 0x1.921fb6p+0f,
};
-#define SignMask sv_u32 (0x80000000)
-
/* Special cases i.e. 0, infinity, nan (fall back to scalar calls). */
-static inline svfloat32_t
+static svfloat32_t NOINLINE
special_case (svfloat32_t y, svfloat32_t x, svfloat32_t ret,
const svbool_t cmp)
{
svbool_t cmp_y = zeroinfnan (iy, pg);
svbool_t cmp_xy = svorr_z (pg, cmp_x, cmp_y);
- svuint32_t sign_x = svand_x (pg, ix, SignMask);
- svuint32_t sign_y = svand_x (pg, iy, SignMask);
- svuint32_t sign_xy = sveor_x (pg, sign_x, sign_y);
-
svfloat32_t ax = svabs_x (pg, x);
svfloat32_t ay = svabs_x (pg, y);
+ svuint32_t iax = svreinterpret_u32 (ax);
+ svuint32_t iay = svreinterpret_u32 (ay);
+
+ svuint32_t sign_x = sveor_x (pg, ix, iax);
+ svuint32_t sign_y = sveor_x (pg, iy, iay);
+ svuint32_t sign_xy = sveor_x (pg, sign_x, sign_y);
- svbool_t pred_xlt0 = svcmplt (pg, x, 0.0);
svbool_t pred_aygtax = svcmpgt (pg, ay, ax);
/* Set up z for call to atan. */
svfloat32_t z = svdiv_x (pg, n, d);
/* Work out the correct shift. */
- svfloat32_t shift = svsel (pred_xlt0, sv_f32 (-2.0), sv_f32 (0.0));
- shift = svsel (pred_aygtax, svadd_x (pg, shift, 1.0), shift);
+ svfloat32_t shift = svreinterpret_f32 (svlsr_x (pg, sign_x, 1));
+ shift = svsel (pred_aygtax, sv_f32 (1.0), shift);
+ shift = svreinterpret_f32 (svorr_x (pg, sign_x, svreinterpret_u32 (shift)));
shift = svmul_x (pg, shift, sv_f32 (data_ptr->pi_over_2));
- /* Use split Estrin scheme for P(z^2) with deg(P)=7. */
+ /* Use pure Estrin scheme for P(z^2) with deg(P)=7. */
svfloat32_t z2 = svmul_x (pg, z, z);
svfloat32_t z4 = svmul_x (pg, z2, z2);
svfloat32_t z8 = svmul_x (pg, z4, z4);
ret = svadd_m (pg, ret, shift);
/* Account for the sign of x and y. */
- ret = svreinterpret_f32 (sveor_x (pg, svreinterpret_u32 (ret), sign_xy));
if (__glibc_unlikely (svptest_any (pg, cmp_xy)))
- return special_case (y, x, ret, cmp_xy);
+ return special_case (
+ y, x,
+ svreinterpret_f32 (sveor_x (pg, svreinterpret_u32 (ret), sign_xy)),
+ cmp_xy);
- return ret;
+ return svreinterpret_f32 (sveor_x (pg, svreinterpret_u32 (ret), sign_xy));
}
special-case handler later. */
r = vbslq_f64 (cmp, v_f64 (1.0), r);
#else
- cmp = vcageq_f64 (d->range_val, x);
- cmp = vceqzq_u64 (cmp); /* cmp = ~cmp. */
+ cmp = vcageq_f64 (x, d->range_val);
r = x;
#endif
special-case handler later. */
r = vbslq_f32 (cmp, v_f32 (1.0f), r);
#else
- cmp = vcageq_f32 (d->range_val, x);
- cmp = vceqzq_u32 (cmp); /* cmp = ~cmp. */
+ cmp = vcageq_f32 (x, d->range_val);
r = x;
#endif
# define BigBound v_u64 (0x4070000000000000) /* asuint64 (0x1p8). */
# define Thres v_u64 (0x2070000000000000) /* BigBound - TinyBound. */
-static inline float64x2_t VPCS_ATTR
+static float64x2_t VPCS_ATTR NOINLINE
special_case (float64x2_t x, float64x2_t y, uint64x2_t cmp)
{
/* If fenv exceptions are to be triggered correctly, fall back to the scalar
# define SpecialBias1 v_u64 (0x7000000000000000) /* 0x1p769. */
# define SpecialBias2 v_u64 (0x3010000000000000) /* 0x1p-254. */
-static float64x2_t VPCS_ATTR NOINLINE
+static inline float64x2_t VPCS_ATTR
special_case (float64x2_t s, float64x2_t y, float64x2_t n,
const struct data *d)
{
static const struct data
{
float32x4_t poly[5];
- float32x4_t shift, log10_2, log2_10_hi, log2_10_lo;
+ float32x4_t log10_2_and_inv, shift;
+
#if !WANT_SIMD_EXCEPT
float32x4_t scale_thresh;
#endif
.poly = { V4 (0x1.26bb16p+1f), V4 (0x1.5350d2p+1f), V4 (0x1.04744ap+1f),
V4 (0x1.2d8176p+0f), V4 (0x1.12b41ap-1f) },
.shift = V4 (0x1.8p23f),
- .log10_2 = V4 (0x1.a934fp+1),
- .log2_10_hi = V4 (0x1.344136p-2),
- .log2_10_lo = V4 (-0x1.ec10cp-27),
+
+ /* Stores constants 1/log10(2), log10(2)_high, log10(2)_low, 0. */
+ .log10_2_and_inv = { 0x1.a934fp+1, 0x1.344136p-2, -0x1.ec10cp-27, 0 },
#if !WANT_SIMD_EXCEPT
.scale_thresh = V4 (ScaleBound)
#endif
#if WANT_SIMD_EXCEPT
/* asuint(x) - TinyBound >= BigBound - TinyBound. */
uint32x4_t cmp = vcgeq_u32 (
- vsubq_u32 (vandq_u32 (vreinterpretq_u32_f32 (x), v_u32 (0x7fffffff)),
- TinyBound),
- Thres);
+ vsubq_u32 (vreinterpretq_u32_f32 (vabsq_f32 (x)), TinyBound), Thres);
float32x4_t xm = x;
/* If any lanes are special, mask them with 1 and retain a copy of x to allow
special case handler to fix special lanes later. This is only necessary if
fenv exceptions are to be triggered correctly. */
if (__glibc_unlikely (v_any_u32 (cmp)))
- x = vbslq_f32 (cmp, v_f32 (1), x);
+ x = v_zerofy_f32 (x, cmp);
#endif
/* exp10(x) = 2^n * 10^r = 2^n * (1 + poly (r)),
with poly(r) in [1/sqrt(2), sqrt(2)] and
x = r + n * log10 (2), with r in [-log10(2)/2, log10(2)/2]. */
- float32x4_t z = vfmaq_f32 (d->shift, x, d->log10_2);
+ float32x4_t z = vfmaq_laneq_f32 (d->shift, x, d->log10_2_and_inv, 0);
float32x4_t n = vsubq_f32 (z, d->shift);
- float32x4_t r = vfmsq_f32 (x, n, d->log2_10_hi);
- r = vfmsq_f32 (r, n, d->log2_10_lo);
+ float32x4_t r = vfmsq_laneq_f32 (x, n, d->log10_2_and_inv, 1);
+ r = vfmsq_laneq_f32 (r, n, d->log10_2_and_inv, 2);
uint32x4_t e = vshlq_n_u32 (vreinterpretq_u32_f32 (z), 23);
float32x4_t scale = vreinterpretq_f32_u32 (vaddq_u32 (e, ExponentBias));
#define IndexMask (N - 1)
#define BigBound 1022.0
#define UOFlowBound 1280.0
+#define TinyBound 0x2000000000000000 /* asuint64(0x1p-511). */
static const struct data
{
#if WANT_SIMD_EXCEPT
-# define TinyBound 0x2000000000000000 /* asuint64(0x1p-511). */
# define Thres 0x2080000000000000 /* asuint64(512.0) - TinyBound. */
/* Call scalar exp2 as a fallback. */
static float64x2_t VPCS_ATTR NOINLINE
-special_case (float64x2_t x)
+special_case (float64x2_t x, float64x2_t y, uint64x2_t is_special)
{
- return v_call_f64 (exp2, x, x, v_u64 (0xffffffffffffffff));
+ return v_call_f64 (exp2, x, y, is_special);
}
#else
# define SpecialBias1 0x7000000000000000 /* 0x1p769. */
# define SpecialBias2 0x3010000000000000 /* 0x1p-254. */
-static float64x2_t VPCS_ATTR
+static inline float64x2_t VPCS_ATTR
special_case (float64x2_t s, float64x2_t y, float64x2_t n,
const struct data *d)
{
#if WANT_SIMD_EXCEPT
uint64x2_t ia = vreinterpretq_u64_f64 (vabsq_f64 (x));
cmp = vcgeq_u64 (vsubq_u64 (ia, v_u64 (TinyBound)), v_u64 (Thres));
- /* If any special case (inf, nan, small and large x) is detected,
- fall back to scalar for all lanes. */
- if (__glibc_unlikely (v_any_u64 (cmp)))
- return special_case (x);
+ /* Mask special lanes and retain a copy of x for passing to special-case
+ handler. */
+ float64x2_t xc = x;
+ x = v_zerofy_f64 (x, cmp);
#else
cmp = vcagtq_f64 (x, d->scale_big_bound);
#endif
float64x2_t y = v_pairwise_poly_3_f64 (r, r2, d->poly);
y = vmulq_f64 (r, y);
-#if !WANT_SIMD_EXCEPT
if (__glibc_unlikely (v_any_u64 (cmp)))
+#if !WANT_SIMD_EXCEPT
return special_case (s, y, n, d);
+#else
+ return special_case (xc, vfmaq_f64 (s, s, y), cmp);
#endif
return vfmaq_f64 (s, s, y);
}
#include "sv_math.h"
#include "poly_sve_f32.h"
+#define Thres 0x1.5d5e2ap+6f
+
static const struct data
{
float poly[5];
.shift = 0x1.903f8p17f,
/* Roughly 87.3. For x < -Thres, the result is subnormal and not handled
correctly by FEXPA. */
- .thres = 0x1.5d5e2ap+6f,
+ .thres = Thres,
};
static svfloat32_t NOINLINE
# define BigBound v_u64 (0x4080000000000000) /* asuint64 (0x1p9). */
# define SpecialBound v_u64 (0x2080000000000000) /* BigBound - TinyBound. */
-static inline float64x2_t VPCS_ATTR
+static float64x2_t VPCS_ATTR NOINLINE
special_case (float64x2_t x, float64x2_t y, uint64x2_t cmp)
{
/* If fenv exceptions are to be triggered correctly, fall back to the scalar
# define SpecialBias1 v_u64 (0x7000000000000000) /* 0x1p769. */
# define SpecialBias2 v_u64 (0x3010000000000000) /* 0x1p-254. */
-static float64x2_t VPCS_ATTR NOINLINE
+static inline float64x2_t VPCS_ATTR
special_case (float64x2_t s, float64x2_t y, float64x2_t n)
{
/* 2^(n/N) may overflow, break it up into s1*s2. */
static const struct data
{
float64x2_t poly[11];
- float64x2_t invln2, ln2_lo, ln2_hi, shift;
+ float64x2_t invln2, ln2, shift;
int64x2_t exponent_bias;
#if WANT_SIMD_EXCEPT
uint64x2_t thresh, tiny_bound;
V2 (0x1.71ddf82db5bb4p-19), V2 (0x1.27e517fc0d54bp-22),
V2 (0x1.af5eedae67435p-26), V2 (0x1.1f143d060a28ap-29) },
.invln2 = V2 (0x1.71547652b82fep0),
- .ln2_hi = V2 (0x1.62e42fefa39efp-1),
- .ln2_lo = V2 (0x1.abc9e3b39803fp-56),
+ .ln2 = { 0x1.62e42fefa39efp-1, 0x1.abc9e3b39803fp-56 },
.shift = V2 (0x1.8p52),
.exponent_bias = V2 (0x3ff0000000000000),
#if WANT_SIMD_EXCEPT
x = v_zerofy_f64 (x, special);
#else
/* Large input, NaNs and Infs. */
- uint64x2_t special = vceqzq_u64 (vcaltq_f64 (x, d->oflow_bound));
+ uint64x2_t special = vcageq_f64 (x, d->oflow_bound);
#endif
/* Reduce argument to smaller range:
where 2^i is exact because i is an integer. */
float64x2_t n = vsubq_f64 (vfmaq_f64 (d->shift, d->invln2, x), d->shift);
int64x2_t i = vcvtq_s64_f64 (n);
- float64x2_t f = vfmsq_f64 (x, n, d->ln2_hi);
- f = vfmsq_f64 (f, n, d->ln2_lo);
+ float64x2_t f = vfmsq_laneq_f64 (x, n, d->ln2, 0);
+ f = vfmsq_laneq_f64 (f, n, d->ln2, 1);
/* Approximate expm1(f) using polynomial.
Taylor expansion for expm1(x) has the form:
static const struct data
{
float32x4_t poly[5];
- float32x4_t invln2, ln2_lo, ln2_hi, shift;
+ float32x4_t invln2_and_ln2;
+ float32x4_t shift;
int32x4_t exponent_bias;
#if WANT_SIMD_EXCEPT
uint32x4_t thresh;
/* Generated using fpminimax with degree=5 in [-log(2)/2, log(2)/2]. */
.poly = { V4 (0x1.fffffep-2), V4 (0x1.5554aep-3), V4 (0x1.555736p-5),
V4 (0x1.12287cp-7), V4 (0x1.6b55a2p-10) },
- .invln2 = V4 (0x1.715476p+0f),
- .ln2_hi = V4 (0x1.62e4p-1f),
- .ln2_lo = V4 (0x1.7f7d1cp-20f),
+ /* Stores constants: invln2, ln2_hi, ln2_lo, 0. */
+ .invln2_and_ln2 = { 0x1.715476p+0f, 0x1.62e4p-1f, 0x1.7f7d1cp-20f, 0 },
.shift = V4 (0x1.8p23f),
.exponent_bias = V4 (0x3f800000),
#if !WANT_SIMD_EXCEPT
x = v_zerofy_f32 (x, special);
#else
/* Handles very large values (+ve and -ve), +/-NaN, +/-Inf. */
- uint32x4_t special = vceqzq_u32 (vcaltq_f32 (x, d->oflow_bound));
+ uint32x4_t special = vcagtq_f32 (x, d->oflow_bound);
#endif
/* Reduce argument to smaller range:
and f = x - i * ln2, then f is in [-ln2/2, ln2/2].
exp(x) - 1 = 2^i * (expm1(f) + 1) - 1
where 2^i is exact because i is an integer. */
- float32x4_t j = vsubq_f32 (vfmaq_f32 (d->shift, d->invln2, x), d->shift);
+ float32x4_t j = vsubq_f32 (
+ vfmaq_laneq_f32 (d->shift, x, d->invln2_and_ln2, 0), d->shift);
int32x4_t i = vcvtq_s32_f32 (j);
- float32x4_t f = vfmsq_f32 (x, j, d->ln2_hi);
- f = vfmsq_f32 (f, j, d->ln2_lo);
+ float32x4_t f = vfmsq_laneq_f32 (x, j, d->invln2_and_ln2, 1);
+ f = vfmsq_laneq_f32 (f, j, d->invln2_and_ln2, 2);
/* Approximate expm1(f) using polynomial.
Taylor expansion for expm1(x) has the form:
uint64_t i1 = (i[1] >> (52 - V_LOG_TABLE_BITS)) & IndexMask;
float64x2_t e0 = vld1q_f64 (&__v_log_data.table[i0].invc);
float64x2_t e1 = vld1q_f64 (&__v_log_data.table[i1].invc);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
e.invc = vuzp1q_f64 (e0, e1);
e.logc = vuzp2q_f64 (e0, e1);
+#else
+ e.invc = vuzp1q_f64 (e1, e0);
+ e.logc = vuzp2q_f64 (e1, e0);
+#endif
return e;
}
r = vbslq_f64 (cmp, vreinterpretq_f64_u64 (cmp), x);
#else
r = x;
- cmp = vcageq_f64 (d->range_val, x);
- cmp = vceqzq_u64 (cmp); /* cmp = ~cmp. */
+ cmp = vcageq_f64 (x, d->range_val);
#endif
/* n = rint(|x|/pi). */
r = vbslq_f32 (cmp, vreinterpretq_f32_u32 (cmp), x);
#else
r = x;
- cmp = vcageq_f32 (d->range_val, x);
- cmp = vceqzq_u32 (cmp); /* cmp = ~cmp. */
+ cmp = vcageq_f32 (x, d->range_val);
#endif
/* n = rint(|x|/pi) */
static const struct data
{
float64x2_t poly[9];
- float64x2_t half_pi_hi, half_pi_lo, two_over_pi, shift;
+ float64x2_t half_pi, two_over_pi, shift;
#if !WANT_SIMD_EXCEPT
float64x2_t range_val;
#endif
V2 (0x1.226e5e5ecdfa3p-7), V2 (0x1.d6c7ddbf87047p-9),
V2 (0x1.7ea75d05b583ep-10), V2 (0x1.289f22964a03cp-11),
V2 (0x1.4e4fd14147622p-12) },
- .half_pi_hi = V2 (0x1.921fb54442d18p0),
- .half_pi_lo = V2 (0x1.1a62633145c07p-54),
+ .half_pi = { 0x1.921fb54442d18p0, 0x1.1a62633145c07p-54 },
.two_over_pi = V2 (0x1.45f306dc9c883p-1),
.shift = V2 (0x1.8p52),
#if !WANT_SIMD_EXCEPT
/* Vector approximation for double-precision tan.
Maximum measured error is 3.48 ULP:
- __v_tan(0x1.4457047ef78d8p+20) got -0x1.f6ccd8ecf7dedp+37
- want -0x1.f6ccd8ecf7deap+37. */
+ _ZGVnN2v_tan(0x1.4457047ef78d8p+20) got -0x1.f6ccd8ecf7dedp+37
+ want -0x1.f6ccd8ecf7deap+37. */
float64x2_t VPCS_ATTR V_NAME_D1 (tan) (float64x2_t x)
{
const struct data *dat = ptr_barrier (&data);
- /* Our argument reduction cannot calculate q with sufficient accuracy for very
- large inputs. Fall back to scalar routine for all lanes if any are too
- large, or Inf/NaN. If fenv exceptions are expected, also fall back for tiny
- input to avoid underflow. */
+ /* Our argument reduction cannot calculate q with sufficient accuracy for
+ very large inputs. Fall back to scalar routine for all lanes if any are
+ too large, or Inf/NaN. If fenv exceptions are expected, also fall back for
+ tiny input to avoid underflow. */
#if WANT_SIMD_EXCEPT
uint64x2_t iax = vreinterpretq_u64_f64 (vabsq_f64 (x));
/* iax - tiny_bound > range_val - tiny_bound. */
/* Use q to reduce x to r in [-pi/4, pi/4], by:
r = x - q * pi/2, in extended precision. */
float64x2_t r = x;
- r = vfmsq_f64 (r, q, dat->half_pi_hi);
- r = vfmsq_f64 (r, q, dat->half_pi_lo);
+ r = vfmsq_laneq_f64 (r, q, dat->half_pi, 0);
+ r = vfmsq_laneq_f64 (r, q, dat->half_pi, 1);
/* Further reduce r to [-pi/8, pi/8], to be reconstructed using double angle
formula. */
r = vmulq_n_f64 (r, 0.5);
and reciprocity around pi/2:
tan(x) = 1 / (tan(pi/2 - x))
to assemble result using change-of-sign and conditional selection of
- numerator/denominator, dependent on odd/even-ness of q (hence quadrant). */
+ numerator/denominator, dependent on odd/even-ness of q (hence quadrant).
+ */
float64x2_t n = vfmaq_f64 (v_f64 (-1), p, p);
float64x2_t d = vaddq_f64 (p, p);
uint64x2_t no_recip = vtstq_u64 (vreinterpretq_u64_s64 (qi), v_u64 (1));
#if !WANT_SIMD_EXCEPT
- uint64x2_t special = vceqzq_u64 (vcaleq_f64 (x, dat->range_val));
+ uint64x2_t special = vcageq_f64 (x, dat->range_val);
if (__glibc_unlikely (v_any_u64 (special)))
return special_case (x);
#endif
static const struct data
{
float32x4_t poly[6];
- float32x4_t neg_half_pi_1, neg_half_pi_2, neg_half_pi_3, two_over_pi, shift;
+ float32x4_t pi_consts;
+ float32x4_t shift;
#if !WANT_SIMD_EXCEPT
float32x4_t range_val;
#endif
/* Coefficients generated using FPMinimax. */
.poly = { V4 (0x1.55555p-2f), V4 (0x1.11166p-3f), V4 (0x1.b88a78p-5f),
V4 (0x1.7b5756p-6f), V4 (0x1.4ef4cep-8f), V4 (0x1.0e1e74p-7f) },
- .neg_half_pi_1 = V4 (-0x1.921fb6p+0f),
- .neg_half_pi_2 = V4 (0x1.777a5cp-25f),
- .neg_half_pi_3 = V4 (0x1.ee59dap-50f),
- .two_over_pi = V4 (0x1.45f306p-1f),
+ /* Stores constants: (-pi/2)_high, (-pi/2)_mid, (-pi/2)_low, and 2/pi. */
+ .pi_consts
+ = { -0x1.921fb6p+0f, 0x1.777a5cp-25f, 0x1.ee59dap-50f, 0x1.45f306p-1f },
.shift = V4 (0x1.8p+23f),
#if !WANT_SIMD_EXCEPT
.range_val = V4 (0x1p15f),
{
float32x4_t z2 = vmulq_f32 (z, z);
#if WANT_SIMD_EXCEPT
- /* Tiny z (<= 0x1p-31) will underflow when calculating z^4. If fp exceptions
- are to be triggered correctly, sidestep this by fixing such lanes to 0. */
+ /* Tiny z (<= 0x1p-31) will underflow when calculating z^4.
+ If fp exceptions are to be triggered correctly,
+ sidestep this by fixing such lanes to 0. */
uint32x4_t will_uflow
- = vcleq_u32 (vreinterpretq_u32_f32 (vabsq_f32 (z)), TinyBound);
+ = vcleq_u32 (vreinterpretq_u32_f32 (vabsq_f32 (z)), TinyBound);
if (__glibc_unlikely (v_any_u32 (will_uflow)))
z2 = vbslq_f32 (will_uflow, v_f32 (0), z2);
#endif
#endif
/* n = rint(x/(pi/2)). */
- float32x4_t q = vfmaq_f32 (d->shift, d->two_over_pi, x);
+ float32x4_t q = vfmaq_laneq_f32 (d->shift, x, d->pi_consts, 3);
float32x4_t n = vsubq_f32 (q, d->shift);
/* Determine if x lives in an interval, where |tan(x)| grows to infinity. */
uint32x4_t pred_alt = vtstq_u32 (vreinterpretq_u32_f32 (q), v_u32 (1));
/* r = x - n * (pi/2) (range reduction into -pi./4 .. pi/4). */
float32x4_t r;
- r = vfmaq_f32 (x, d->neg_half_pi_1, n);
- r = vfmaq_f32 (r, d->neg_half_pi_2, n);
- r = vfmaq_f32 (r, d->neg_half_pi_3, n);
+ r = vfmaq_laneq_f32 (x, n, d->pi_consts, 0);
+ r = vfmaq_laneq_f32 (r, n, d->pi_consts, 1);
+ r = vfmaq_laneq_f32 (r, n, d->pi_consts, 2);
/* If x lives in an interval, where |tan(x)|
- is finite, then use a polynomial approximation of the form
MTE_ENABLED (); \
bool __attribute__((unused)) sve = \
GLRO(dl_aarch64_cpu_features).sve; \
+ bool __attribute__((unused)) prefer_sve_ifuncs = \
+ GLRO(dl_aarch64_cpu_features).prefer_sve_ifuncs; \
bool __attribute__((unused)) mops = \
GLRO(dl_aarch64_cpu_features).mops;
{
if (IS_A64FX (midr))
return __memcpy_a64fx;
- return __memcpy_sve;
+ return prefer_sve_ifuncs ? __memcpy_sve : __memcpy_generic;
}
if (IS_THUNDERX (midr))
{
if (IS_A64FX (midr))
return __memmove_a64fx;
- return __memmove_sve;
+ return prefer_sve_ifuncs ? __memmove_sve : __memmove_generic;
}
if (IS_THUNDERX (midr))
#endif
#include <../memset.S>
+
+#if IS_IN (rtld)
+strong_alias (memset, __memset_generic)
+#endif
aarch64*)
base_machine=aarch64
machine=aarch64
+ mtls_descriptor=desc
;;
esac
--- /dev/null
+/* arc has less padding than other architectures with 64-bit time_t. */
+#define UTMP_SIZE 392
+#define LASTLOG_SIZE 296
lib-noranlib: $(objpfx)libgcc-stubs.a
ifeq ($(build-shared),yes)
-ifeq (yes,$(have-mtls-dialect-gnu2))
+ifneq (no,$(have-mtls-descriptor))
tests += tst-armtlsdescloc tst-armtlsdescextnow tst-armtlsdescextlazy
modules-names += tst-armtlsdesclocmod
modules-names += tst-armtlsdescextlazymod tst-armtlsdescextnowmod
CPPFLAGS-tst-armtlsdescextnowmod.c += -Dstatic=
CPPFLAGS-tst-armtlsdescextlazymod.c += -Dstatic=
-CFLAGS-tst-armtlsdesclocmod.c += -mtls-dialect=gnu2
-CFLAGS-tst-armtlsdescextnowmod.c += -mtls-dialect=gnu2
-CFLAGS-tst-armtlsdescextlazymod.c += -mtls-dialect=gnu2
+CFLAGS-tst-armtlsdesclocmod.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-armtlsdescextnowmod.c += -mtls-dialect=$(have-mtls-descriptor)
+CFLAGS-tst-armtlsdescextlazymod.c += -mtls-dialect=$(have-mtls-descriptor)
LDFLAGS-tst-armtlsdescextnowmod.so += -Wl,-z,now
tst-armtlsdescloc-ENV = LD_BIND_NOW=1
tst-armtlsdescextnow-ENV = LD_BIND_NOW=1
--- /dev/null
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define __WORDSIZE 32
+#define __WORDSIZE_TIME64_COMPAT32 1
+#define __WORDSIZE32_SIZE_ULONG 0
+#define __WORDSIZE32_PTRDIFF_LONG 0
default-abi = soft"
fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether VFP supports 32 registers" >&5
+printf %s "checking whether VFP supports 32 registers... " >&6; }
+if test ${libc_cv_arm_pcs_vfp_d32+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+void foo (void)
+{
+ asm volatile ("vldr d16,=17" : : : "d16");
+}
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ libc_cv_arm_pcs_vfp_d32=yes
+else $as_nop
+ libc_cv_arm_pcs_vfp_d32=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_arm_pcs_vfp_d32" >&5
+printf "%s\n" "$libc_cv_arm_pcs_vfp_d32" >&6; }
+if test "$libc_cv_arm_pcs_vfp_d32" = yes ;
+then
+ printf "%s\n" "#define HAVE_ARM_PCS_VFP_D32 1" >>confdefs.h
+
+fi
+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether PC-relative relocs in movw/movt work properly" >&5
printf %s "checking whether PC-relative relocs in movw/movt work properly... " >&6; }
if test ${libc_cv_arm_pcrel_movw+y}
LIBC_CONFIG_VAR([default-abi], [soft])
fi
+AC_CACHE_CHECK([whether VFP supports 32 registers],
+ libc_cv_arm_pcs_vfp_d32, [
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+void foo (void)
+{
+ asm volatile ("vldr d16,=17" : : : "d16");
+}
+]])],
+ [libc_cv_arm_pcs_vfp_d32=yes],
+ [libc_cv_arm_pcs_vfp_d32=no])])
+if test "$libc_cv_arm_pcs_vfp_d32" = yes ;
+then
+ AC_DEFINE(HAVE_ARM_PCS_VFP_D32)
+fi
+
AC_CACHE_CHECK([whether PC-relative relocs in movw/movt work properly],
libc_cv_arm_pcrel_movw, [
cat > conftest.s <<\EOF
_dl_start_user:\n\
adr r6, .L_GET_GOT\n\
add sl, sl, r6\n\
- ldr r4, [sl, r4]\n\
@ save the entry point in another register\n\
mov r6, r0\n\
@ get the original arg count\n\
#include <sysdep.h>
#include <arm-features.h>
#include <tls.h>
+#include <rtld-global-offsets.h>
#include "tlsdesc.h"
.text
.align 2
_dl_tlsdesc_dynamic:
/* Our calling convention is to clobber r0, r1 and the processor
- flags. All others that are modified must be saved */
- eabi_save ({r2,r3,r4,lr})
- push {r2,r3,r4,lr}
- cfi_adjust_cfa_offset (16)
+ flags. All others that are modified must be saved. r5 is
+ used as the hwcap value to avoid reload after __tls_get_addr
+ call. If required we will save the vector register on the slow
+ path. */
+ eabi_save ({r2,r3,r4,r5,ip,lr})
+ push {r2,r3,r4,r5,ip,lr}
+ cfi_adjust_cfa_offset (24)
cfi_rel_offset (r2,0)
cfi_rel_offset (r3,4)
cfi_rel_offset (r4,8)
- cfi_rel_offset (lr,12)
+ cfi_rel_offset (r5,12)
+ cfi_rel_offset (ip,16)
+ cfi_rel_offset (lr,20)
+
ldr r1, [r0] /* td */
GET_TLS (lr)
mov r4, r0 /* r4 = tp */
rsbne r0, r4, r3
bne 2f
1: mov r0, r1
+
+ /* Load the hwcap to check for vector support. */
+ ldr r2, 3f
+ ldr r1, .Lrtld_global_ro
+0: add r2, pc, r2
+ ldr r2, [r2, r1]
+ ldr r5, [r2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
+
+#ifdef __SOFTFP__
+ tst r5, #HWCAP_ARM_VFP
+ beq .Lno_vfp
+#endif
+
+ /* Store the VFP registers. Don't use VFP instructions directly
+ because this code is used in non-VFP multilibs. */
+#define VFP_STACK_REQ (32*8 + 8)
+ sub sp, sp, VFP_STACK_REQ
+ cfi_adjust_cfa_offset (VFP_STACK_REQ)
+ mov r3, sp
+ .inst 0xeca30b20 /* vstmia r3!, {d0-d15} */
+ tst r5, #HWCAP_ARM_VFPD32
+ beq 4f
+ .inst 0xece30b20 /* vstmia r3!, {d16-d31} */
+ /* Store the floating-point status register. */
+4: .inst 0xeef12a10 /* vmrs r2, fpscr */
+ str r2, [r3]
+.Lno_vfp:
bl __tls_get_addr
rsb r0, r4, r0
+#ifdef __SOFTFP__
+ tst r5, #HWCAP_ARM_VFP
+ beq 2f
+#endif
+ mov r3, sp
+ .inst 0xecb30b20 /* vldmia r3!, {d0-d15} */
+ tst r5, #HWCAP_ARM_VFPD32
+ beq 5f
+ .inst 0xecf30b20 /* vldmia r3!, {d16-d31} */
+ ldr r4, [r3]
+5: .inst 0xeee14a10 /* vmsr fpscr, r4 */
+ add sp, sp, VFP_STACK_REQ
+ cfi_adjust_cfa_offset (-VFP_STACK_REQ)
+
2:
#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
|| defined (ARM_ALWAYS_BX))
- pop {r2,r3,r4, lr}
- cfi_adjust_cfa_offset (-16)
+ pop {r2,r3,r4,r5,ip, lr}
+ cfi_adjust_cfa_offset (-20)
cfi_restore (lr)
+ cfi_restore (ip)
+ cfi_restore (r5)
cfi_restore (r4)
cfi_restore (r3)
cfi_restore (r2)
bx lr
#else
- pop {r2,r3,r4, pc}
+ pop {r2,r3,r4,r5,ip, pc}
#endif
eabi_fnend
cfi_endproc
.size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+
+3: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS
+.Lrtld_global_ro:
+ .long C_SYMBOL_NAME(_rtld_global_ro)(GOT)
#endif /* SHARED */
--- /dev/null
+/* Test TLSDESC relocation. ARM version.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <sys/auxv.h>
+#include <string.h>
+#include <stdlib.h>
+#include <endian.h>
+
+#ifndef __SOFTFP__
+
+# ifdef HAVE_ARM_PCS_VFP_D32
+# define SAVE_VFP_D32 \
+ asm volatile ("vldr d16,=17" : : : "d16"); \
+ asm volatile ("vldr d17,=18" : : : "d17"); \
+ asm volatile ("vldr d18,=19" : : : "d18"); \
+ asm volatile ("vldr d19,=20" : : : "d19"); \
+ asm volatile ("vldr d20,=21" : : : "d20"); \
+ asm volatile ("vldr d21,=22" : : : "d21"); \
+ asm volatile ("vldr d22,=23" : : : "d22"); \
+ asm volatile ("vldr d23,=24" : : : "d23"); \
+ asm volatile ("vldr d24,=25" : : : "d24"); \
+ asm volatile ("vldr d25,=26" : : : "d25"); \
+ asm volatile ("vldr d26,=27" : : : "d26"); \
+ asm volatile ("vldr d27,=28" : : : "d27"); \
+ asm volatile ("vldr d28,=29" : : : "d28"); \
+ asm volatile ("vldr d29,=30" : : : "d29"); \
+ asm volatile ("vldr d30,=31" : : : "d30"); \
+ asm volatile ("vldr d31,=32" : : : "d31");
+# else
+# define SAVE_VFP_D32
+# endif
+
+# define INIT_TLSDESC_CALL() \
+ unsigned long hwcap = getauxval (AT_HWCAP)
+
+/* Set each vector register to a value from 1 to 32 before the TLS access,
+ dump to memory after TLS access, and compare with the expected values. */
+
+# define BEFORE_TLSDESC_CALL() \
+ if (hwcap & HWCAP_ARM_VFP) \
+ { \
+ asm volatile ("vldr d0,=1" : : : "d0"); \
+ asm volatile ("vldr d1,=2" : : : "d1"); \
+ asm volatile ("vldr d2,=3" : : : "d1"); \
+ asm volatile ("vldr d3,=4" : : : "d3"); \
+ asm volatile ("vldr d4,=5" : : : "d4"); \
+ asm volatile ("vldr d5,=6" : : : "d5"); \
+ asm volatile ("vldr d6,=7" : : : "d6"); \
+ asm volatile ("vldr d7,=8" : : : "d7"); \
+ asm volatile ("vldr d8,=9" : : : "d8"); \
+ asm volatile ("vldr d9,=10" : : : "d9"); \
+ asm volatile ("vldr d10,=11" : : : "d10"); \
+ asm volatile ("vldr d11,=12" : : : "d11"); \
+ asm volatile ("vldr d12,=13" : : : "d12"); \
+ asm volatile ("vldr d13,=14" : : : "d13"); \
+ asm volatile ("vldr d14,=15" : : : "d14"); \
+ asm volatile ("vldr d15,=16" : : : "d15"); \
+ } \
+ if (hwcap & HWCAP_ARM_VFPD32) \
+ { \
+ SAVE_VFP_D32 \
+ }
+
+# define VFP_STACK_REQ (16*8)
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define DISP 7
+# else
+# define DISP 0
+# endif
+
+# ifdef HAVE_ARM_PCS_VFP_D32
+# define CHECK_VFP_D32 \
+ char vfp[VFP_STACK_REQ]; \
+ asm volatile ("vstmia %0, {d16-d31}\n" \
+ : \
+ : "r" (vfp) \
+ : "memory"); \
+ \
+ char expected[VFP_STACK_REQ] = { 0 }; \
+ for (int i = 0; i < 16; ++i) \
+ expected[i * 8 + DISP] = i + 17; \
+ \
+ if (memcmp (vfp, expected, VFP_STACK_REQ) != 0) \
+ abort ();
+# else
+# define CHECK_VFP_D32
+# endif
+
+# define AFTER_TLSDESC_CALL() \
+ if (hwcap & HWCAP_ARM_VFP) \
+ { \
+ char vfp[VFP_STACK_REQ]; \
+ asm volatile ("vstmia %0, {d0-d15}\n" \
+ : \
+ : "r" (vfp) \
+ : "memory"); \
+ \
+ char expected[VFP_STACK_REQ] = { 0 }; \
+ for (int i = 0; i < 16; ++i) \
+ expected[i * 8 + DISP] = i + 1; \
+ \
+ if (memcmp (vfp, expected, VFP_STACK_REQ) != 0) \
+ abort (); \
+ } \
+ if (hwcap & HWCAP_ARM_VFPD32) \
+ { \
+ CHECK_VFP_D32 \
+ }
+
+#endif /* __SOFTFP__ */
+
+#include_next <tst-gnu2-tls2.h>
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
--- /dev/null
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define __WORDSIZE 32
+#define __WORDSIZE_TIME64_COMPAT32 1
+#define __WORDSIZE32_SIZE_ULONG 0
+#define __WORDSIZE32_PTRDIFF_LONG 0
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
/* Mask for more hardware capabilities that are available on some
platforms. */
EXTERN uint64_t _dl_hwcap2;
+ EXTERN uint64_t _dl_hwcap3;
+ EXTERN uint64_t _dl_hwcap4;
EXTERN enum dso_sort_algorithm _dl_dso_sort_algo;
--- /dev/null
+/* Expected sizes of utmp-related structures stored in files. 64-bit version.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Expected size, in bytes, of struct utmp and struct utmpx. */
+#define UTMP_SIZE 400
+
+/* Expected size, in bytes, of struct lastlog. */
+#define LASTLOG_SIZE 296
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
{
td->arg = _dl_make_tlsdesc_dynamic
(sym_map, sym->st_value + (ElfW(Word))td->arg);
- td->entry = _dl_tlsdesc_dynamic;
+ td->entry = GLRO(dl_x86_tlsdesc_dynamic);
}
else
# endif
--- /dev/null
+/* Thread-local storage handling in the ELF dynamic linker. i386 version.
+ Copyright (C) 2004-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#undef REGISTER_SAVE_AREA
+
+#if !defined USE_FNSAVE && (STATE_SAVE_ALIGNMENT % 16) != 0
+# error STATE_SAVE_ALIGNMENT must be multiple of 16
+#endif
+
+#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+# ifdef USE_FNSAVE
+# error USE_FNSAVE shouldn't be defined
+# endif
+# ifdef USE_FXSAVE
+/* Use fxsave to save all registers. */
+# define REGISTER_SAVE_AREA 512
+# endif
+#else
+# ifdef USE_FNSAVE
+/* Use fnsave to save x87 FPU stack registers. */
+# define REGISTER_SAVE_AREA 108
+# else
+# ifndef USE_FXSAVE
+# error USE_FXSAVE must be defined
+# endif
+/* Use fxsave to save all registers. Add 12 bytes to align the stack
+ to 16 bytes. */
+# define REGISTER_SAVE_AREA (512 + 12)
+# endif
+#endif
+
+ .hidden _dl_tlsdesc_dynamic
+ .global _dl_tlsdesc_dynamic
+ .type _dl_tlsdesc_dynamic,@function
+
+ /* This function is used for symbols that need dynamic TLS.
+
+ %eax points to the TLS descriptor, such that 0(%eax) points to
+ _dl_tlsdesc_dynamic itself, and 4(%eax) points to a struct
+ tlsdesc_dynamic_arg object. It must return in %eax the offset
+ between the thread pointer and the object denoted by the
+ argument, without clobbering any registers.
+
+ The assembly code that follows is a rendition of the following
+ C code, hand-optimized a little bit.
+
+ptrdiff_t
+__attribute__ ((__regparm__ (1)))
+_dl_tlsdesc_dynamic (struct tlsdesc *tdp)
+{
+ struct tlsdesc_dynamic_arg *td = tdp->arg;
+ dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + DTV_OFFSET);
+ if (__builtin_expect (td->gen_count <= dtv[0].counter
+ && (dtv[td->tlsinfo.ti_module].pointer.val
+ != TLS_DTV_UNALLOCATED),
+ 1))
+ return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset
+ - __thread_pointer;
+
+ return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
+}
+*/
+ cfi_startproc
+ .align 16
+_dl_tlsdesc_dynamic:
+ /* Like all TLS resolvers, preserve call-clobbered registers.
+ We need two scratch regs anyway. */
+ subl $32, %esp
+ cfi_adjust_cfa_offset (32)
+ movl %ecx, 20(%esp)
+ movl %edx, 24(%esp)
+ movl TLSDESC_ARG(%eax), %eax
+ movl %gs:DTV_OFFSET, %edx
+ movl TLSDESC_GEN_COUNT(%eax), %ecx
+ cmpl (%edx), %ecx
+ ja 2f
+ movl TLSDESC_MODID(%eax), %ecx
+ movl (%edx,%ecx,8), %edx
+ cmpl $-1, %edx
+ je 2f
+ movl TLSDESC_MODOFF(%eax), %eax
+ addl %edx, %eax
+1:
+ movl 20(%esp), %ecx
+ subl %gs:0, %eax
+ movl 24(%esp), %edx
+ addl $32, %esp
+ cfi_adjust_cfa_offset (-32)
+ ret
+ .p2align 4,,7
+2:
+ cfi_adjust_cfa_offset (32)
+#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+ movl %ebx, -28(%esp)
+ movl %esp, %ebx
+ cfi_def_cfa_register(%ebx)
+ and $-STATE_SAVE_ALIGNMENT, %esp
+#endif
+#ifdef REGISTER_SAVE_AREA
+ subl $REGISTER_SAVE_AREA, %esp
+# if !DL_RUNTIME_RESOLVE_REALIGN_STACK
+ cfi_adjust_cfa_offset(REGISTER_SAVE_AREA)
+# endif
+#else
+# if !DL_RUNTIME_RESOLVE_REALIGN_STACK
+# error DL_RUNTIME_RESOLVE_REALIGN_STACK must be true
+# endif
+ /* Allocate stack space of the required size to save the state. */
+ LOAD_PIC_REG (cx)
+ subl RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET+XSAVE_STATE_SIZE_OFFSET+_rtld_local_ro@GOTOFF(%ecx), %esp
+#endif
+#ifdef USE_FNSAVE
+ fnsave (%esp)
+#elif defined USE_FXSAVE
+ fxsave (%esp)
+#else
+ /* Save the argument for ___tls_get_addr in EAX. */
+ movl %eax, %ecx
+ movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax
+ xorl %edx, %edx
+ /* Clear the XSAVE Header. */
+# ifdef USE_XSAVE
+ movl %edx, (512)(%esp)
+ movl %edx, (512 + 4 * 1)(%esp)
+ movl %edx, (512 + 4 * 2)(%esp)
+ movl %edx, (512 + 4 * 3)(%esp)
+# endif
+ movl %edx, (512 + 4 * 4)(%esp)
+ movl %edx, (512 + 4 * 5)(%esp)
+ movl %edx, (512 + 4 * 6)(%esp)
+ movl %edx, (512 + 4 * 7)(%esp)
+ movl %edx, (512 + 4 * 8)(%esp)
+ movl %edx, (512 + 4 * 9)(%esp)
+ movl %edx, (512 + 4 * 10)(%esp)
+ movl %edx, (512 + 4 * 11)(%esp)
+ movl %edx, (512 + 4 * 12)(%esp)
+ movl %edx, (512 + 4 * 13)(%esp)
+ movl %edx, (512 + 4 * 14)(%esp)
+ movl %edx, (512 + 4 * 15)(%esp)
+# ifdef USE_XSAVE
+ xsave (%esp)
+# else
+ xsavec (%esp)
+# endif
+ /* Restore the argument for ___tls_get_addr in EAX. */
+ movl %ecx, %eax
+#endif
+ call HIDDEN_JUMPTARGET (___tls_get_addr)
+ /* Get register content back. */
+#ifdef USE_FNSAVE
+ frstor (%esp)
+#elif defined USE_FXSAVE
+ fxrstor (%esp)
+#else
+ /* Save and retore ___tls_get_addr return value stored in EAX. */
+ movl %eax, %ecx
+ movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax
+ xorl %edx, %edx
+ xrstor (%esp)
+ movl %ecx, %eax
+#endif
+#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+ mov %ebx, %esp
+ cfi_def_cfa_register(%esp)
+ movl -28(%esp), %ebx
+ cfi_restore(%ebx)
+#else
+ addl $REGISTER_SAVE_AREA, %esp
+ cfi_adjust_cfa_offset(-REGISTER_SAVE_AREA)
+#endif
+ jmp 1b
+ cfi_endproc
+ .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+
+#undef STATE_SAVE_ALIGNMENT
#include <sysdep.h>
#include <tls.h>
+#include <cpu-features-offsets.h>
+#include <features-offsets.h>
#include "tlsdesc.h"
+#ifndef DL_STACK_ALIGNMENT
+/* Due to GCC bug:
+
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
+
+ __tls_get_addr may be called with 4-byte stack alignment. Although
+ this bug has been fixed in GCC 4.9.4, 5.3 and 6, we can't assume
+ that stack will be always aligned at 16 bytes. */
+# define DL_STACK_ALIGNMENT 4
+#endif
+
+/* True if _dl_tlsdesc_dynamic should align stack for STATE_SAVE or align
+ stack to MINIMUM_ALIGNMENT bytes before calling ___tls_get_addr. */
+#define DL_RUNTIME_RESOLVE_REALIGN_STACK \
+ (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \
+ || MINIMUM_ALIGNMENT > DL_STACK_ALIGNMENT)
+
.text
/* This function is used to compute the TP offset for symbols in
.size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
#ifdef SHARED
- .hidden _dl_tlsdesc_dynamic
- .global _dl_tlsdesc_dynamic
- .type _dl_tlsdesc_dynamic,@function
-
- /* This function is used for symbols that need dynamic TLS.
-
- %eax points to the TLS descriptor, such that 0(%eax) points to
- _dl_tlsdesc_dynamic itself, and 4(%eax) points to a struct
- tlsdesc_dynamic_arg object. It must return in %eax the offset
- between the thread pointer and the object denoted by the
- argument, without clobbering any registers.
-
- The assembly code that follows is a rendition of the following
- C code, hand-optimized a little bit.
-
-ptrdiff_t
-__attribute__ ((__regparm__ (1)))
-_dl_tlsdesc_dynamic (struct tlsdesc *tdp)
-{
- struct tlsdesc_dynamic_arg *td = tdp->arg;
- dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + DTV_OFFSET);
- if (__builtin_expect (td->gen_count <= dtv[0].counter
- && (dtv[td->tlsinfo.ti_module].pointer.val
- != TLS_DTV_UNALLOCATED),
- 1))
- return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset
- - __thread_pointer;
-
- return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
-}
-*/
- cfi_startproc
- .align 16
-_dl_tlsdesc_dynamic:
- /* Like all TLS resolvers, preserve call-clobbered registers.
- We need two scratch regs anyway. */
- subl $28, %esp
- cfi_adjust_cfa_offset (28)
- movl %ecx, 20(%esp)
- movl %edx, 24(%esp)
- movl TLSDESC_ARG(%eax), %eax
- movl %gs:DTV_OFFSET, %edx
- movl TLSDESC_GEN_COUNT(%eax), %ecx
- cmpl (%edx), %ecx
- ja .Lslow
- movl TLSDESC_MODID(%eax), %ecx
- movl (%edx,%ecx,8), %edx
- cmpl $-1, %edx
- je .Lslow
- movl TLSDESC_MODOFF(%eax), %eax
- addl %edx, %eax
-.Lret:
- movl 20(%esp), %ecx
- subl %gs:0, %eax
- movl 24(%esp), %edx
- addl $28, %esp
- cfi_adjust_cfa_offset (-28)
- ret
- .p2align 4,,7
-.Lslow:
- cfi_adjust_cfa_offset (28)
- call HIDDEN_JUMPTARGET (___tls_get_addr)
- jmp .Lret
- cfi_endproc
- .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+# define USE_FNSAVE
+# define MINIMUM_ALIGNMENT 4
+# define STATE_SAVE_ALIGNMENT 4
+# define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_fnsave
+# include "dl-tlsdesc-dynamic.h"
+# undef _dl_tlsdesc_dynamic
+# undef MINIMUM_ALIGNMENT
+# undef USE_FNSAVE
+
+# define MINIMUM_ALIGNMENT 16
+
+# define USE_FXSAVE
+# define STATE_SAVE_ALIGNMENT 16
+# define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_fxsave
+# include "dl-tlsdesc-dynamic.h"
+# undef _dl_tlsdesc_dynamic
+# undef USE_FXSAVE
+
+# define USE_XSAVE
+# define STATE_SAVE_ALIGNMENT 64
+# define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_xsave
+# include "dl-tlsdesc-dynamic.h"
+# undef _dl_tlsdesc_dynamic
+# undef USE_XSAVE
+
+# define USE_XSAVEC
+# define STATE_SAVE_ALIGNMENT 64
+# define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_xsavec
+# include "dl-tlsdesc-dynamic.h"
+# undef _dl_tlsdesc_dynamic
+# undef USE_XSAVEC
#endif /* SHARED */
Function: "hypot":
double: 1
+float: 1
float128: 1
ldouble: 1
/* i386 provides an optimized __ieee754_exp10. */
-#define NO_COMPAT_NEEDED 1
-#include <math/w_exp10_compat.c>
+#ifdef SHARED
+# define NO_COMPAT_NEEDED 1
+# include <math/w_exp10_compat.c>
+#else
+# include <math-type-macros-double.h>
+# include <w_exp10_template.c>
+#endif
# define LIBM_SVID_COMPAT 1
# undef compat_symbol
# define compat_symbol(a, b, c, d)
-#endif
-#include <math/w_fmod_compat.c>
-#ifdef SHARED
+# include <math/w_fmod_compat.c>
libm_alias_double (__fmod_compat, fmod)
+#else
+#include <math-type-macros-double.h>
+#include <w_fmod_template.c>
#endif
# define LIBM_SVID_COMPAT 1
# undef compat_symbol
# define compat_symbol(a, b, c, d)
-#endif
-#include <math/w_fmodf_compat.c>
-#ifdef SHARED
+# include <math/w_fmodf_compat.c>
libm_alias_float (__fmod_compat, fmod)
+#else
+#include <math-type-macros-float.h>
+#include <w_fmod_template.c>
#endif
#define LEN SRC+4
.text
-#if defined PIC && IS_IN (libc)
+#if defined SHARED && IS_IN (libc)
ENTRY (__memcpy_chk)
movl 12(%esp), %eax
cmpl %eax, 16(%esp)
#define SRC DEST+4
#define LEN SRC+4
-#if defined PIC && IS_IN (libc)
+#if defined SHARED && IS_IN (libc)
ENTRY_CHK (__memmove_chk)
movl 12(%esp), %eax
cmpl %eax, 16(%esp)
#define LEN CHR+4
.text
-#if defined PIC && IS_IN (libc)
+#if defined SHARED && IS_IN (libc)
ENTRY_CHK (__memset_chk)
movl 12(%esp), %eax
cmpl %eax, 16(%esp)
#endif
#include "string/memrchr.c"
+strong_alias (__memrchr_ia32, __GI___memrchr)
ret
END (__memrchr_sse2)
-strong_alias (__memrchr_sse2, __GI___memrchr)
#endif
#include "../ldbl-128/s_isnanl.c"
#if !IS_IN (libm)
#include <float128-abi.h>
+#ifdef SHARED
hidden_ver (__isnanf128_impl, __isnanf128)
+#else
+strong_alias (__isnanf128_impl, __isnanf128)
+#endif
_weak_alias (__isnanf128_impl, isnanl)
versioned_symbol (libc, __isnanf128_impl, __isnanf128, GLIBC_2_34);
#if (SHLIB_COMPAT (libc, FLOAT128_VERSION_M, GLIBC_2_34))
#include <math_ldbl_opt.h>
#include <libm-alias-ldouble.h>
-#if IS_IN (libc)
+#if IS_IN (libc) && defined SHARED
# undef libm_alias_ldouble
# define libm_alias_ldouble(from, to)
#endif
#include <sysdeps/ieee754/ldbl-128/s_copysignl.c>
-#if IS_IN (libc)
+#if IS_IN (libc) && defined SHARED
long_double_symbol (libc, __copysignl, copysignl);
#endif
#include <math_ldbl_opt.h>
#include <libm-alias-ldouble.h>
-#if IS_IN (libc)
+#if IS_IN (libc) && defined SHARED
# undef libm_alias_ldouble
# define libm_alias_ldouble(from, to)
#endif
#include <sysdeps/ieee754/ldbl-128/s_frexpl.c>
-#if IS_IN (libc)
+#if IS_IN (libc) && defined SHARED
long_double_symbol (libc, __frexpl, frexpl);
#endif
#include <math_ldbl_opt.h>
#include <libm-alias-ldouble.h>
-#if IS_IN (libc)
+#if IS_IN (libc) && defined SHARED
# undef libm_alias_ldouble
# define libm_alias_ldouble(from, to)
#endif
#include <sysdeps/ieee754/ldbl-128/s_modfl.c>
-#if IS_IN (libc)
+#if IS_IN (libc) && defined SHARED
long_double_symbol (libc, __modfl, modfl);
#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#if IS_IN (libc)
+#if IS_IN (libc) && defined SHARED
# define declare_mgen_alias(f,t)
#endif
#include <math-type-macros-ldouble.h>
#include <s_ldexp_template.c>
-#if IS_IN (libc)
+#if IS_IN (libc) && defined SHARED
long_double_symbol (libc, __ldexpl, ldexpl);
long_double_symbol (libc, __wrap_scalbnl, scalbnl);
#endif
return x;
}
-libm_alias_finite (__ieee754_scalb, __scalb)
+libm_alias_finite (__ieee754_scalbf, __scalbf)
ifeq ($(subdir),string)
sysdep_routines += \
- strlen-aligned \
- strlen-lsx \
- strlen-lasx \
- strnlen-aligned \
- strnlen-lsx \
- strnlen-lasx \
+ memchr-aligned \
+ memchr-lasx \
+ memchr-lsx \
+ memcmp-aligned \
+ memcmp-lasx \
+ memcmp-lsx \
+ memcpy-aligned \
+ memcpy-unaligned \
+ memmove-lasx \
+ memmove-lsx \
+ memmove-unaligned \
+ memrchr-generic \
+ memrchr-lasx \
+ memrchr-lsx \
+ memset-aligned \
+ memset-lasx \
+ memset-lsx \
+ memset-unaligned \
+ rawmemchr-aligned \
+ rawmemchr-lasx \
+ rawmemchr-lsx \
+ stpcpy-aligned \
+ stpcpy-lasx \
+ stpcpy-lsx \
+ stpcpy-unaligned \
strchr-aligned \
- strchr-lsx \
strchr-lasx \
- strrchr-aligned \
- strrchr-lsx \
- strrchr-lasx \
+ strchr-lsx \
strchrnul-aligned \
- strchrnul-lsx \
strchrnul-lasx \
+ strchrnul-lsx \
strcmp-aligned \
strcmp-lsx \
- strncmp-aligned \
- strncmp-lsx \
strcpy-aligned \
- strcpy-unaligned \
- strcpy-lsx \
strcpy-lasx \
- stpcpy-aligned \
- stpcpy-unaligned \
- stpcpy-lsx \
- stpcpy-lasx \
- memcpy-aligned \
- memcpy-unaligned \
- memmove-unaligned \
- memmove-lsx \
- memmove-lasx \
- rawmemchr-aligned \
- rawmemchr-lsx \
- rawmemchr-lasx \
- memchr-aligned \
- memchr-lsx \
- memchr-lasx \
- memrchr-generic \
- memrchr-lsx \
- memrchr-lasx \
- memset-aligned \
- memset-unaligned \
- memset-lsx \
- memset-lasx \
- memcmp-aligned \
- memcmp-lsx \
- memcmp-lasx \
+ strcpy-lsx \
+ strcpy-unaligned \
+ strlen-aligned \
+ strlen-lasx \
+ strlen-lsx \
+ strncmp-aligned \
+ strncmp-lsx \
+ strnlen-aligned \
+ strnlen-lasx \
+ strnlen-lsx \
+ strrchr-aligned \
+ strrchr-lasx \
+ strrchr-lsx \
# sysdep_routines
endif
#ifndef _DL_IFUNC_GENERIC_H
#define _DL_IFUNC_GENERIC_H
+#ifndef SHARED
asm ("memset = __memset_aligned");
+asm ("memcmp = __memcmp_aligned");
+#endif
#endif
--- /dev/null
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define __WORDSIZE 32
+#define __WORDSIZE_TIME64_COMPAT32 1
+#define __WORDSIZE32_SIZE_ULONG 0
+#define __WORDSIZE32_PTRDIFF_LONG 0
/* m68k provides an optimized __ieee754_exp10. */
-#define NO_COMPAT_NEEDED 1
-#include <math/w_exp10_compat.c>
+#ifdef SHARED
+# define NO_COMPAT_NEEDED 1
+# include <math/w_exp10_compat.c>
+#else
+# include <math-type-macros-double.h>
+# include <w_exp10_template.c>
+#endif
# define LIBM_SVID_COMPAT 1
# undef compat_symbol
# define compat_symbol(a, b, c, d)
-#endif
#include <math/w_fmod_compat.c>
-#ifdef SHARED
libm_alias_double (__fmod_compat, fmod)
+#else
+#include <math-type-macros-double.h>
+#include <w_fmod_template.c>
#endif
# define LIBM_SVID_COMPAT 1
# undef compat_symbol
# define compat_symbol(a, b, c, d)
-#endif
-#include <math/w_fmodf_compat.c>
-#ifdef SHARED
+# include <math/w_fmodf_compat.c>
libm_alias_float (__fmod_compat, fmod)
+#else
+#include <math-type-macros-float.h>
+#include <w_fmod_template.c>
#endif
--- /dev/null
+/* m68k has 2-byte alignment. */
+#define UTMP_SIZE 382
+#define LASTLOG_SIZE 292
#include <bits/sockaddr.h>
/* Structure describing a generic socket address. */
-struct sockaddr
+struct __attribute_struct_may_alias__ sockaddr
{
__SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
#define _SS_PADSIZE \
(_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype))
-struct sockaddr_storage
+struct __attribute_struct_may_alias__ sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
char __ss_padding[_SS_PADSIZE];
--- /dev/null
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define __WORDSIZE 32
+#define __WORDSIZE_TIME64_COMPAT32 1
+#define __WORDSIZE32_SIZE_ULONG 0
+#define __WORDSIZE32_PTRDIFF_LONG 0
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
#define __WORDSIZE _MIPS_SZPTR
-#if _MIPS_SIM == _ABI64
-# define __WORDSIZE_TIME64_COMPAT32 1
-#else
-# define __WORDSIZE_TIME64_COMPAT32 0
-#endif
+#define __WORDSIZE_TIME64_COMPAT32 1
#if __WORDSIZE == 32
#define __WORDSIZE32_SIZE_ULONG 0
ldouble: 1
Function: "j0":
-double: 2
+double: 3
float: 9
ldouble: 2
Function: "j0_downward":
-double: 5
+double: 6
float: 9
ldouble: 9
Function: "j0_towardzero":
-double: 6
+double: 7
float: 9
ldouble: 9
ldouble: 8
Function: "log":
+double: 1
float: 1
ldouble: 1
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
--- /dev/null
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define __WORDSIZE 32
+#define __WORDSIZE_TIME64_COMPAT32 1
+#define __WORDSIZE32_SIZE_ULONG 0
+#define __WORDSIZE32_PTRDIFF_LONG 0
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
#endif
const unsigned int __rseq_flags;
-const unsigned int __rseq_size attribute_relro;
-const ptrdiff_t __rseq_offset attribute_relro;
void
__tls_pre_init_tp (void)
bool do_rseq = true;
do_rseq = TUNABLE_GET (rseq, int, NULL);
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);
- }
+ _rseq_size = RSEQ_AREA_SIZE_INITIAL_USED;
#ifdef RSEQ_SIG
/* This should be a compile-time constant, but the current
all targets support __thread_pointer, so set __rseq_offset only
if the rseq registration may have happened because RSEQ_SIG is
defined. */
- extern ptrdiff_t offset __asm__ ("__rseq_offset");
- offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
+ _rseq_offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
#endif
}
the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL. */
extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW;
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* 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.
#ifdef __USE_XOPEN2K
/* Wait until lock becomes available, or specified time passes. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
const struct timespec *__restrict
__abstime) __THROWNL __nonnull ((1, 2));
#endif
#ifdef __USE_GNU
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pthread_mutex_clocklock (pthread_mutex_t *__restrict __mutex,
clockid_t __clockid,
const struct timespec *__restrict
# ifdef __USE_XOPEN2K
/* Try to acquire read lock for RWLOCK or return after specified time. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
const struct timespec *__restrict
__abstime) __THROWNL __nonnull ((1, 2));
# endif
# ifdef __USE_GNU
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pthread_rwlock_clockrdlock (pthread_rwlock_t *__restrict __rwlock,
clockid_t __clockid,
const struct timespec *__restrict
# ifdef __USE_XOPEN2K
/* Try to acquire write lock for RWLOCK or return after specified time. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
const struct timespec *__restrict
__abstime) __THROWNL __nonnull ((1, 2));
# endif
# ifdef __USE_GNU
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pthread_rwlock_clockwrlock (pthread_rwlock_t *__restrict __rwlock,
clockid_t __clockid,
const struct timespec *__restrict
This function is a cancellation point and therefore not marked with
__THROW. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
pthread_mutex_t *__restrict __mutex,
const struct timespec *__restrict __abstime)
This function is a cancellation point and therefore not marked with
__THROW. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int pthread_cond_clockwait (pthread_cond_t *__restrict __cond,
pthread_mutex_t *__restrict __mutex,
__clockid_t __clock_id,
--- /dev/null
+/* or1k has less padding than other architectures with 64-bit time_t. */
+#define UTMP_SIZE 392
+#define LASTLOG_SIZE 296
needed.
*/
+/* The total number of available bits (including those prior to
+ _DL_HWCAP_FIRST). Some of these bits might not be used. */
+#define _DL_HWCAP_COUNT 128
+
#ifndef PROCINFO_CLASS
# define PROCINFO_CLASS
#endif
#if !defined PROCINFO_DECL && defined SHARED
._dl_powerpc_cap_flags
#else
-PROCINFO_CLASS const char _dl_powerpc_cap_flags[64][15]
+PROCINFO_CLASS const char _dl_powerpc_cap_flags[_DL_HWCAP_COUNT][15]
#endif
#ifndef PROCINFO_DECL
= {
#include <ldsodefs.h>
#include <sysdep.h> /* This defines the PPC_FEATURE[2]_* macros. */
-/* The total number of available bits (including those prior to
- _DL_HWCAP_FIRST). Some of these bits might not be used. */
-#define _DL_HWCAP_COUNT 64
+/* Feature masks are all 32-bits in size. */
+#define _DL_HWCAP_SIZE 32
-/* Features started at bit 31 and decremented as new features were added. */
-#define _DL_HWCAP_LAST 31
+/* AT_HWCAP2 feature strings follow the AT_HWCAP feature strings. */
+#define _DL_HWCAP2_OFFSET _DL_HWCAP_SIZE
-/* AT_HWCAP2 features started at bit 31 and decremented as new features were
- added. HWCAP2 feature bits start at bit 0. */
-#define _DL_HWCAP2_LAST 31
+/* AT_HWCAP3 feature strings follow the AT_HWCAP2 feature strings. */
+#define _DL_HWCAP3_OFFSET (_DL_HWCAP2_OFFSET + _DL_HWCAP_SIZE)
+
+/* AT_HWCAP4 feature strings follow the AT_HWCAP3 feature strings. */
+#define _DL_HWCAP4_OFFSET (_DL_HWCAP3_OFFSET + _DL_HWCAP_SIZE)
/* These bits influence library search. */
#define HWCAP_IMPORTANT (PPC_FEATURE_HAS_ALTIVEC \
+ PPC_FEATURE_HAS_DFP)
-#define _DL_PLATFORMS_COUNT 16
+#define _DL_PLATFORMS_COUNT 17
#define _DL_FIRST_PLATFORM 32
/* Mask to filter out platforms. */
#define PPC_PLATFORM_POWER8 13
#define PPC_PLATFORM_POWER9 14
#define PPC_PLATFORM_POWER10 15
+#define PPC_PLATFORM_POWER11 16
static inline const char *
__attribute__ ((unused))
ret = _DL_FIRST_PLATFORM + PPC_PLATFORM_POWER10;
str++;
}
+ else if (str[1] == '1')
+ {
+ ret = _DL_FIRST_PLATFORM + PPC_PLATFORM_POWER11;
+ str++;
+ }
else
return -1;
break;
case AT_HWCAP:
_dl_printf ("AT_HWCAP: ");
- for (int i = 0; i <= _DL_HWCAP_LAST; ++i)
+ for (int i = 0; i < _DL_HWCAP_SIZE; ++i)
if (word & (1 << i))
_dl_printf (" %s", _dl_hwcap_string (i));
break;
case AT_HWCAP2:
{
- unsigned int offset = _DL_HWCAP_LAST + 1;
_dl_printf ("AT_HWCAP2: ");
- /* We have to go through them all because the kernel added the
- AT_HWCAP2 features starting with the high bits. */
- for (int i = 0; i <= _DL_HWCAP2_LAST; ++i)
- if (word & (1 << i))
- _dl_printf (" %s", _dl_hwcap_string (offset + i));
+ /* We have to go through them all because the kernel added the
+ AT_HWCAP2 features starting with the high bits. */
+ for (int i = 0; i < _DL_HWCAP_SIZE; ++i)
+ if (word & (1 << i))
+ _dl_printf (" %s", _dl_hwcap_string (_DL_HWCAP2_OFFSET + i));
+ break;
+ }
+ case AT_HWCAP3:
+ {
+ _dl_printf ("AT_HWCAP3: ");
+
+ /* We have to go through them all because the kernel added the
+ AT_HWCAP3 features starting with the high bits. */
+ for (int i = 0; i < _DL_HWCAP_SIZE; ++i)
+ if (word & (1 << i))
+ _dl_printf (" %s", _dl_hwcap_string (_DL_HWCAP3_OFFSET + i));
+ break;
+ }
+ case AT_HWCAP4:
+ {
+ _dl_printf ("AT_HWCAP4: ");
+
+ /* We have to go through them all because the kernel added the
+ AT_HWCAP4 features starting with the high bits. */
+ for (int i = 0; i <= _DL_HWCAP_SIZE; ++i)
+ if (word & (1 << i))
+ _dl_printf (" %s", _dl_hwcap_string (_DL_HWCAP4_OFFSET + i));
break;
}
case AT_L1I_CACHEGEOMETRY:
__tcb_parse_hwcap_and_convert_at_platform (void)
{
- uint64_t h1, h2;
+ uint64_t h1, h2, h3, h4;
/* Read AT_PLATFORM string from auxv and convert it to a number. */
__tcb.at_platform = _dl_string_platform (GLRO (dl_platform));
/* Read HWCAP and HWCAP2 from auxv. */
h1 = GLRO (dl_hwcap);
h2 = GLRO (dl_hwcap2);
+ h3 = GLRO (dl_hwcap3);
+ h4 = GLRO (dl_hwcap4);
/* hwcap contains only the latest supported ISA, the code checks which is
and fills the previous supported ones. */
else if (h1 & PPC_FEATURE_POWER5)
h1 |= PPC_FEATURE_POWER4;
- uint64_t array_hwcaps[] = { h1, h2 };
+ uint64_t array_hwcaps[] = { h1, h2, h3, h4 };
init_cpu_features (&GLRO(dl_powerpc_cpu_features), array_hwcaps);
/* Consolidate both HWCAP and HWCAP2 into a single doubleword so that
we can read both in a single load later. */
__tcb.hwcap = (h1 << 32) | (h2 & 0xffffffff);
- __tcb.hwcap_extn = 0x0;
+
+ /* Consolidate both HWCAP3 and HWCAP4 into a single doubleword so that
+ we can read both in a single load later. */
+ __tcb.hwcap_extn = (h3 << 32) | (h4 & 0xffffffff);
}
#if IS_IN (rtld)
#if defined __powerpc64__
# define __WORDSIZE 64
-# define __WORDSIZE_TIME64_COMPAT32 1
#else
# define __WORDSIZE 32
-# define __WORDSIZE_TIME64_COMPAT32 0
# define __WORDSIZE32_SIZE_ULONG 0
# define __WORDSIZE32_PTRDIFF_LONG 0
#endif
+#define __WORDSIZE_TIME64_COMPAT32 1
--- /dev/null
+powerpc/powerpc32/power10/fpu
+powerpc/powerpc32/power10
--- /dev/null
+powerpc/powerpc32/power10/fpu/multiarch
--- /dev/null
+powerpc/powerpc32/power10/multiarch
--- /dev/null
+powerpc/powerpc64/be/power10/fpu
+powerpc/powerpc64/be/power10
--- /dev/null
+powerpc/powerpc64/be/power10/fpu
--- /dev/null
+powerpc/powerpc64/be/power10/fpu/multiarch
--- /dev/null
+powerpc/powerpc64/be/power10/multiarch
#if defined __powerpc64__
# define __WORDSIZE 64
-# define __WORDSIZE_TIME64_COMPAT32 1
#else
# define __WORDSIZE 32
-# define __WORDSIZE_TIME64_COMPAT32 0
# define __WORDSIZE32_SIZE_ULONG 0
# define __WORDSIZE32_PTRDIFF_LONG 0
#endif
+#define __WORDSIZE_TIME64_COMPAT32 1
static inline Elf64_Addr
elf_machine_load_address (void) __attribute__ ((const));
+#ifndef __PCREL__
static inline Elf64_Addr
elf_machine_load_address (void)
{
/* Then subtract off the load address offset. */
return runtime_dynamic - elf_machine_load_address() ;
}
+#else /* __PCREL__ */
+/* In PCREL mode, r2 may have been clobbered. Rely on relative
+ relocations instead. */
+
+static inline ElfW(Addr)
+elf_machine_load_address (void)
+{
+ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
+ return (ElfW(Addr)) &__ehdr_start;
+}
+
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
+}
+#endif /* __PCREL__ */
/* The PLT uses Elf64_Rela relocs. */
#define elf_machine_relplt elf_machine_rela
--- /dev/null
+powerpc/powerpc64/le/power10/fpu
+powerpc/powerpc64/le/power10
--- /dev/null
+powerpc/powerpc64/le/power10/fpu
--- /dev/null
+powerpc/powerpc64/le/power10/fpu/multiarch
--- /dev/null
+powerpc/powerpc64/le/power10/multiarch
return 9;
if (strcmp (platform, "power10") == 0)
return 10;
+ if (strcmp (platform, "power11") == 0)
+ return 11;
printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform);
- /* Assume that the new platform supports POWER10. */
- return 10;
+ /* Assume that the new platform supports POWER11. */
+ return 11;
}
static int
;;
- a2|970|power[4-9]|power5x|power6+|power10)
+ a2|970|power[4-9]|power5x|power6+|power10|power11)
submachine=${archcpu}
if test ${libc_cv_cc_submachine+y}
then :
AC_CACHE_VAL(libc_cv_cc_submachine,libc_cv_cc_submachine="")
;;
- a2|970|power[[4-9]]|power5x|power6+|power10)
+ a2|970|power[[4-9]]|power5x|power6+|power10|power11)
submachine=${archcpu}
AC_CACHE_VAL(libc_cv_cc_submachine,libc_cv_cc_submachine="")
;;
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
This function is a cancellation point and therefore not marked with
__THROW. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int sem_timedwait (sem_t *__restrict __sem,
const struct timespec *__restrict __abstime)
__nonnull ((1, 2));
#endif
#ifdef __USE_GNU
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int sem_clockwait (sem_t *__restrict __sem,
clockid_t clock,
const struct timespec *__restrict __abstime)
__TIME_POINT. The current thread may resume if receives a signal. In
that case, if __REMAINING is not NULL, the remaining time is stored in
the object pointed by it. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int thrd_sleep (const struct timespec *__time_point,
struct timespec *__remaining);
#else
/* Block the current thread until the mutex pointed by __MUTEX is unlocked
or time pointed by __TIME_POINT is reached. In case the mutex is unlock,
the current thread will not be blocked. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int mtx_timedlock (mtx_t *__restrict __mutex,
const struct timespec *__restrict __time_point);
#else
/* Block current thread on the condition variable until condition variable
pointed by __COND is signaled or time pointed by __TIME_POINT is
reached. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int cnd_timedwait (cnd_t *__restrict __cond,
mtx_t *__restrict __mutex,
const struct timespec *__restrict __time_point);
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <errno.h>
#include <support/check.h>
#include <support/xstdio.h>
#include <support/xthread.h>
/* Wait indefinitely for cancellation, which only works if asynchronous
cancellation is enabled. */
-#if defined SYS_ppoll || defined SYS_ppoll_time64
-# ifndef SYS_ppoll_time64
-# define SYS_ppoll_time64 SYS_ppoll
+#ifdef SYS_ppoll_time64
+ long int ret = syscall (SYS_ppoll_time64, NULL, 0, NULL, NULL);
+ (void) ret;
+# ifdef SYS_ppoll
+ if (ret == -1 && errno == ENOSYS)
+ syscall (SYS_ppoll, NULL, 0, NULL, NULL);
# endif
- syscall (SYS_ppoll_time64, NULL, 0, NULL, NULL);
#else
+# ifdef SYS_ppoll
+ syscall (SYS_ppoll, NULL, 0, NULL, NULL);
+# else
for (;;);
+# endif
#endif
return 0;
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
sllg %r4,%r4,2 /* Convert character-count to byte-count. */
locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */
- /* Check first character without vector load. */
- lghi %r5,4 /* current_len = 4 bytes. */
- /* Check s1/2[0]. */
- lt %r0,0(%r2)
- l %r1,0(%r3)
- je .Lend_cmp_one_char
- crjne %r0,%r1,.Lend_cmp_one_char
-
+ lghi %r5,0 /* current_len = 0 bytes. */
.Lloop:
vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */
vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */
srl %r4,2 /* And convert it to character-index. */
vlgvf %r0,%v16,0(%r4) /* Load character-values. */
vlgvf %r1,%v17,0(%r4)
-.Lend_cmp_one_char:
cr %r0,%r1
je .Lend_equal
lghi %r2,1
--- /dev/null
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define __WORDSIZE 32
+#define __WORDSIZE_TIME64_COMPAT32 1
+#define __WORDSIZE32_SIZE_ULONG 0
+#define __WORDSIZE32_PTRDIFF_LONG 0
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
/* Determine the wordsize from the preprocessor defines. */
#define __WORDSIZE 32
-#define __WORDSIZE_TIME64_COMPAT32 0
+#define __WORDSIZE_TIME64_COMPAT32 1
#define __WORDSIZE32_SIZE_ULONG 0
#define __WORDSIZE32_PTRDIFF_LONG 0
#if defined __arch64__ || defined __sparcv9
# define __WORDSIZE 64
-# define __WORDSIZE_TIME64_COMPAT32 1
#else
# define __WORDSIZE 32
-# define __WORDSIZE_TIME64_COMPAT32 0
# define __WORDSIZE32_SIZE_ULONG 0
# define __WORDSIZE32_PTRDIFF_LONG 0
#endif
+#define __WORDSIZE_TIME64_COMPAT32 1
#include <string/memset.c>
+#if IS_IN(rtld)
+strong_alias (memset, __memset_ultra1)
+#endif
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
endif
ifeq ($(subdir),elf)
+dl-routines += \
+ dl-rseq-symbols \
+ # dl-routines
+
sysdep-rtld-routines += \
dl-brk \
dl-getcwd \
#include <stdio.h>
#include <stackinfo.h>
-#ifdef _STACK_GROWS_DOWN
+#if _STACK_GROWS_DOWN
#define called_from(this, saved) ((this) < (saved))
#else
#define called_from(this, saved) ((this) > (saved))
#include <sys/auxv.h>
#include <elf/dl-hwcaps.h>
#include <sys/prctl.h>
+#include <sys/utsname.h>
#include <dl-tunables-parse.h>
#define DCZID_DZP_MASK (1 << 4)
return UINT64_MAX;
}
+#if __LINUX_KERNEL_VERSION < 0x060200
+
+/* Return true if we prefer using SVE in string ifuncs. Old kernels disable
+ SVE after every system call which results in unnecessary traps if memcpy
+ uses SVE. This is true for kernels between 4.15.0 and before 6.2.0, except
+ for 5.14.0 which was patched. For these versions return false to avoid using
+ SVE ifuncs.
+ Parse the kernel version into a 24-bit kernel.major.minor value without
+ calling any library functions. If uname() is not supported or if the version
+ format is not recognized, assume the kernel is modern and return true. */
+
+static inline bool
+prefer_sve_ifuncs (void)
+{
+ struct utsname buf;
+ const char *p = &buf.release[0];
+ int kernel = 0;
+ int val;
+
+ if (__uname (&buf) < 0)
+ return true;
+
+ for (int shift = 16; shift >= 0; shift -= 8)
+ {
+ for (val = 0; *p >= '0' && *p <= '9'; p++)
+ val = val * 10 + *p - '0';
+ kernel |= (val & 255) << shift;
+ if (*p++ != '.')
+ break;
+ }
+
+ if (kernel >= 0x060200 || kernel == 0x050e00)
+ return true;
+ if (kernel >= 0x040f00)
+ return false;
+ return true;
+}
+
+#endif
+
static inline void
init_cpu_features (struct cpu_features *cpu_features)
{
/* Check if SVE is supported. */
cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE;
+ cpu_features->prefer_sve_ifuncs = cpu_features->sve;
+
+#if __LINUX_KERNEL_VERSION < 0x060200
+ if (cpu_features->sve)
+ cpu_features->prefer_sve_ifuncs = prefer_sve_ifuncs ();
+#endif
+
/* Check if MOPS is supported. */
cpu_features->mops = GLRO (dl_hwcap2) & HWCAP2_MOPS;
}
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
# else
__ino64_t st_ino; /* File serial number. */
# endif
-#endif /* __USE_TIME_BITS64 */
+#endif /* __USE_TIME64_REDIRECTS */
};
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
unsigned long int st_ctimensec; /* Nsecs of last status change. */
# endif
__ino64_t st_ino; /* File serial number. */
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif
# define SO_TIMESTAMPNS_NEW 64
# define SO_TIMESTAMPING_NEW 65
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# define SO_RCVTIMEO SO_RCVTIMEO_NEW
# define SO_SNDTIMEO SO_SNDTIMEO_NEW
# define SO_TIMESTAMP SO_TIMESTAMP_NEW
#include <bits/sockaddr.h>
/* Structure describing a generic socket address. */
-struct sockaddr
+struct __attribute_struct_may_alias__ sockaddr
{
__SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
#define _SS_PADSIZE \
(_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype))
-struct sockaddr_storage
+struct __attribute_struct_may_alias__ sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
char __ss_padding[_SS_PADSIZE];
/* Tune a POSIX clock. */
extern int clock_adjtime (__clockid_t __clock_id, struct timex *__utx) __THROW __nonnull((2));
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# if defined(__REDIRECT_NTH)
extern int __REDIRECT_NTH (clock_adjtime, (__clockid_t __clock_id,
struct timex *__utx),
struct timex
{
-# if defined __USE_TIME_BITS64 || (__TIMESIZE == 64 && __WORDSIZE == 32)
+# if defined __USE_TIME64_REDIRECTS || (__TIMESIZE == 64 && __WORDSIZE == 32)
unsigned int modes; /* mode selector */
int :32; /* pad */
long long offset; /* time offset (usec) */
The type `struct msg' is opaque. */
struct msqid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_msqid64_ds_helper.h>
#else
struct ipc_perm msg_perm; /* structure describing operation permission */
/* Data structure describing a set of semaphores. */
struct semid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_semid64_ds_helper.h>
#else
struct ipc_perm sem_perm; /* operation permission struct */
/* Data structure describing a shared memory segment. */
struct shmid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_shmid64_ds_helper.h>
#else
struct ipc_perm shm_perm; /* operation permission struct */
#define RWF_SYNC 0x00000004 /* per-IO O_SYNC. */
#define RWF_NOWAIT 0x00000008 /* per-IO nonblocking mode. */
#define RWF_APPEND 0x00000010 /* per-IO O_APPEND. */
+#define RWF_NOAPPEND 0x00000020 /* per-IO negation of O_APPEND */
__END_DECLS
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
GLRO(dl_platform) = (void *) auxv_values[AT_PLATFORM];
GLRO(dl_hwcap) = auxv_values[AT_HWCAP];
GLRO(dl_hwcap2) = auxv_values[AT_HWCAP2];
+ GLRO(dl_hwcap3) = auxv_values[AT_HWCAP3];
+ GLRO(dl_hwcap4) = auxv_values[AT_HWCAP4];
GLRO(dl_clktck) = auxv_values[AT_CLKTCK];
GLRO(dl_fpu_control) = auxv_values[AT_FPUCW];
_dl_random = (void *) auxv_values[AT_RANDOM];
--- /dev/null
+/* Define symbols used by rseq.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+#if __WORDSIZE == 64
+#define RSEQ_OFFSET_SIZE 8
+#else
+#define RSEQ_OFFSET_SIZE 4
+#endif
+
+/* Some targets define a macro to denote the zero register. */
+#undef zero
+
+/* Define 2 symbols: '__rseq_size' is public const and '_rseq_size' (an
+ alias of '__rseq_size') is hidden and writable for internal use by the
+ dynamic linker which will initialize the value both symbols point to
+ before copy relocations take place. */
+
+ .globl __rseq_size
+ .type __rseq_size, %object
+ .size __rseq_size, 4
+ .hidden _rseq_size
+ .globl _rseq_size
+ .type _rseq_size, %object
+ .size _rseq_size, 4
+ .section .data.rel.ro
+ .balign 4
+__rseq_size:
+_rseq_size:
+ .zero 4
+
+/* Define 2 symbols: '__rseq_offset' is public const and '_rseq_offset' (an
+ alias of '__rseq_offset') is hidden and writable for internal use by the
+ dynamic linker which will initialize the value both symbols point to
+ before copy relocations take place. */
+
+ .globl __rseq_offset
+ .type __rseq_offset, %object
+ .size __rseq_offset, RSEQ_OFFSET_SIZE
+ .hidden _rseq_offset
+ .globl _rseq_offset
+ .type _rseq_offset, %object
+ .size _rseq_offset, RSEQ_OFFSET_SIZE
+ .section .data.rel.ro
+ .balign RSEQ_OFFSET_SIZE
+__rseq_offset:
+_rseq_offset:
+ .zero RSEQ_OFFSET_SIZE
#include <sys/utsname.h>
#include <tls.h>
#include <unistd.h>
+#include <dl-symbol-redir-ifunc.h>
#include <dl-machine.h>
#include <dl-hwcap-check.h>
[AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex },
[AT_RANDOM - 2] = { "RANDOM: 0x", hex },
[AT_HWCAP2 - 2] = { "HWCAP2: 0x", hex },
+ [AT_HWCAP3 - 2] = { "HWCAP3: 0x", hex },
+ [AT_HWCAP4 - 2] = { "HWCAP4: 0x", hex },
[AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ: ", dec },
[AT_L1I_CACHESIZE - 2] = { "L1I_CACHESIZE: ", dec },
[AT_L1I_CACHEGEOMETRY - 2] = { "L1I_CACHEGEOMETRY: 0x", hex },
# if _TIME_BITS == 64
# if ! defined (_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
# error "_TIME_BITS=64 is allowed only with _FILE_OFFSET_BITS=64"
-# elif __TIMESIZE == 32
-# define __USE_TIME_BITS64 1
# endif
+# define __USE_TIME_BITS64 1
# elif _TIME_BITS == 32
# if __TIMESIZE > 32
# error "_TIME_BITS=32 is not compatible with __TIMESIZE > 32"
# else
# error Invalid _TIME_BITS value (can only be 32 or 64-bit)
# endif
+#elif __TIMESIZE == 64
+# define __USE_TIME_BITS64 1
+#endif
+
+#if defined __USE_TIME_BITS64 && __TIMESIZE == 32
+# define __USE_TIME64_REDIRECTS 1
#endif
# define SO_TIMESTAMPNS_NEW 0x4039
# define SO_TIMESTAMPING_NEW 0x403A
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# define SO_RCVTIMEO SO_RCVTIMEO_NEW
# define SO_SNDTIMEO SO_SNDTIMEO_NEW
# define SO_TIMESTAMP SO_TIMESTAMP_NEW
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
# else
__ino64_t st_ino; /* File serial number. */
# endif
-#endif /* __USE_TIME_BITS64 */
+#endif /* __USE_TIME64_REDIRECTS */
};
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
unsigned long int st_ctimensec; /* Nsecs of last status change. */
# endif
__ino64_t st_ino; /* File serial number. */
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif
The type `struct msg' is opaque. */
struct msqid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_msqid64_ds_helper.h>
#else
struct ipc_perm msg_perm; /* structure describing operation permission */
/* Data structure describing a set of semaphores. */
struct semid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_semid64_ds_helper.h>
#else
struct ipc_perm sem_perm; /* operation permission struct */
/* Data structure describing a shared memory segment. */
struct shmid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_shmid64_ds_helper.h>
#else
struct ipc_perm shm_perm; /* operation permission struct */
--- /dev/null
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define __WORDSIZE 32
+#define __WORDSIZE_TIME64_COMPAT32 1
+#define __WORDSIZE32_SIZE_ULONG 0
+#define __WORDSIZE32_PTRDIFF_LONG 0
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
# else
__ino64_t st_ino; /* File serial number. */
# endif
-#endif /* __USE_TIME_BITS64 */
+#endif /* __USE_TIME64_REDIRECTS */
};
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
unsigned long int st_ctimensec; /* Nsecs of last status change. */
# endif
__ino64_t st_ino; /* File serial number. */
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif
#ifndef __USE_FILE_OFFSET64
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
# endif
unsigned int __glibc_reserved4;
unsigned int __glibc_reserved5;
-#endif /* __USE_TIME_BITS64 */
+#endif /* __USE_TIME64_REDIRECTS */
};
#else /* __USE_FILE_OFFSET64 */
/* MS: If __USE_FILE_OFFSET64 is setup then struct stat should match stat64
* create one ifdef to separate stats structures. */
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
unsigned long long st_dev; /* Device. */
# endif
unsigned int __glibc_reserved4;
unsigned int __glibc_reserved5;
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif /* __USE_FILE_OFFSET64 */
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
unsigned long long st_dev; /* Device. */
# endif
unsigned int __glibc_reserved4;
unsigned int __glibc_reserved5;
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif
# define SO_TIMESTAMPNS_NEW 64
# define SO_TIMESTAMPING_NEW 65
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# define SO_RCVTIMEO SO_RCVTIMEO_NEW
# define SO_SNDTIMEO SO_SNDTIMEO_NEW
# define SO_TIMESTAMP SO_TIMESTAMP_NEW
/* Structure describing file characteristics. */
struct stat
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
unsigned long int st_dev;
__blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */
# endif
long int st_pad5[14];
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
# ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
unsigned long int st_dev;
long int st_pad3;
__blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */
long int st_pad4[14];
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
# endif /* __USE_LARGEFILE64 */
struct stat
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev;
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev;
unsigned int st_pad3;
__blkcnt64_t st_blocks;
int st_pad4[14];
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif
The type `struct msg' is opaque. */
struct msqid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_msqid64_ds_helper.h>
#else
struct ipc_perm msg_perm; /* structure describing operation permission */
/* Data structure describing a set of semaphores. */
struct semid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_semid64_ds_helper.h>
#else
struct ipc_perm sem_perm; /* operation permission struct */
/* Data structure describing a shared memory segment. */
struct shmid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_shmid64_ds_helper.h>
#else
struct ipc_perm shm_perm; /* operation permission struct */
.text
.set nomips16
-#if _MIPS_SIM == _ABIO32
-# define EXTRA_LOCALS 1
-#else
-# define EXTRA_LOCALS 0
-#endif
#define FRAMESZ ((NARGSAVE*SZREG)+ALSZ)&ALMASK
GPOFF= FRAMESZ-(1*SZREG)
NESTED(__clone3, SZREG, sp)
beqz a0, L(error) /* No NULL cl_args pointer. */
beqz a2, L(error) /* No NULL function pointer. */
+#if _MIPS_SIM == _ABIO32
+ /* Both stack and stack_size on clone_args are defined as uint64_t, and
+ there is no need to handle values larger than to 32 bits for o32. */
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define CL_STACKPOINTER_OFFSET 44
+# define CL_STACKSIZE_OFFSET 52
+# else
+# define CL_STACKPOINTER_OFFSET 40
+# define CL_STACKSIZE_OFFSET 48
+# endif
+
+ /* For o32 we need to setup a minimal stack frame to allow cprestore
+ on __thread_start_clone3. Also there is no guarantee by kABI that
+ $8 will be preserved after syscall execution (so we need to save it
+ on the provided stack). */
+ lw t0, CL_STACKPOINTER_OFFSET(a0) /* Load the stack pointer. */
+ lw t1, CL_STACKSIZE_OFFSET(a0) /* Load the stack_size. */
+ addiu t1, -32 /* Update the stack size. */
+ addu t2, t1, t0 /* Calculate the thread stack. */
+ sw a3, 0(t2) /* Save argument pointer. */
+ sw t1, CL_STACKSIZE_OFFSET(a0) /* Save the new stack size. */
+#else
move $8, a3 /* a3 is set to 0/1 for syscall success/error
while a4/$8 is returned unmodified. */
+#endif
/* Do the system call, the kernel expects:
v0: system call number
/* Restore the arg for user's function. */
move t9, a2 /* Function pointer. */
+#if _MIPS_SIM == _ABIO32
+ PTR_L a0, 0(sp)
+#else
move a0, $8 /* Argument pointer. */
+#endif
/* Call the user's function. */
jal t9
From Linux 2.1 the AF_PACKET interface is preferred and you should
consider using it in place of this one. */
-struct sockaddr_pkt
+struct __attribute_struct_may_alias__ sockaddr_pkt
{
__SOCKADDR_COMMON (spkt_);
unsigned char spkt_device[14];
#include <features.h>
#include <bits/sockaddr.h>
-struct sockaddr_ash
+struct __attribute_struct_may_alias__ sockaddr_ash
{
__SOCKADDR_COMMON (sash_); /* Common data: address family etc. */
int sash_ifindex; /* Interface to use. */
unsigned char net; /* Network number. */
};
-struct sockaddr_ec
+struct __attribute_struct_may_alias__ sockaddr_ec
{
__SOCKADDR_COMMON (sec_);
unsigned char port; /* Port number. */
__BEGIN_DECLS
-struct sockaddr_iucv
+struct __attribute_struct_may_alias__ sockaddr_iucv
{
__SOCKADDR_COMMON (siucv_);
unsigned short siucv_port; /* Reserved */
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
/* Ignore invalid large values. */
if (INT_MULTIPLY_WRAPV (10, n, &n)
- || INT_ADD_WRAPV (n, *l++ - '0', &n))
+ || INT_ADD_WRAPV (n, *l - '0', &n))
return -1;
+
+ l++;
}
/* -1 indicates that the process is terminated. */
# define SO_TIMESTAMPNS_NEW 64
# define SO_TIMESTAMPING_NEW 65
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# define SO_RCVTIMEO SO_RCVTIMEO_NEW
# define SO_SNDTIMEO SO_SNDTIMEO_NEW
# define SO_TIMESTAMP SO_TIMESTAMP_NEW
#if __WORDSIZE == 32
struct stat
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
# endif
unsigned long int __glibc_reserved4;
unsigned long int __glibc_reserved5;
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
# ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
# endif
unsigned long int __glibc_reserved4;
unsigned long int __glibc_reserved5;
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
# endif /* __USE_LARGEFILE64 */
The type `struct msg' is opaque. */
struct msqid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_msqid64_ds_helper.h>
#else
struct ipc_perm msg_perm; /* structure describing operation permission */
/* Data structure describing a set of semaphores. */
struct semid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_semid64_ds_helper.h>
#else
struct ipc_perm sem_perm; /* operation permission struct */
/* Data structure describing a shared memory segment. */
struct shmid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_shmid64_ds_helper.h>
#else
struct ipc_perm shm_perm; /* operation permission struct */
#if defined __powerpc64__
# define __WORDSIZE 64
-# define __WORDSIZE_TIME64_COMPAT32 1
#else
# define __WORDSIZE 32
-# define __WORDSIZE_TIME64_COMPAT32 0
# define __WORDSIZE32_SIZE_ULONG 0
# define __WORDSIZE32_PTRDIFF_LONG 0
#endif
+#define __WORDSIZE_TIME64_COMPAT32 1
which are set by __tcb_parse_hwcap_and_convert_at_platform. */
cpu_features->hwcap = hwcaps[0];
cpu_features->hwcap2 = hwcaps[1];
+ cpu_features->hwcap3 = hwcaps[2];
+ cpu_features->hwcap4 = hwcaps[3];
/* Default is to use aligned memory access on optimized function unless
tunables is enable, since for this case user can explicit disable
unaligned optimizations. */
bool use_cached_memopt;
unsigned long int hwcap;
unsigned long int hwcap2;
+ unsigned long int hwcap3;
+ unsigned long int hwcap4;
};
static const char hwcap_names[] = {
case AT_HWCAP2:
_dl_hwcap2 = (unsigned long int) av->a_un.a_val;
break;
+ case AT_HWCAP3:
+ _dl_hwcap3 = (unsigned long int) av->a_un.a_val;
+ break;
+ case AT_HWCAP4:
+ _dl_hwcap4 = (unsigned long int) av->a_un.a_val;
+ break;
case AT_PLATFORM:
_dl_platform = (void *) av->a_un.a_val;
break;
#include <stdio.h>
#include <sys/rseq.h>
+/* 32 is the initially required value for the area size. The
+ actually used rseq size may be less (20 bytes initially). */
+#define RSEQ_AREA_SIZE_INITIAL 32
+#define RSEQ_AREA_SIZE_INITIAL_USED 20
+
+/* The variables are in .data.relro but are not yet write-protected. */
+extern unsigned int _rseq_size attribute_hidden;
+extern ptrdiff_t _rseq_offset attribute_hidden;
+
#ifdef RSEQ_SIG
static inline bool
rseq_register_current_thread (struct pthread *self, bool do_rseq)
{
if (do_rseq)
{
+ unsigned int size;
+#if IS_IN (rtld)
+ /* Use the hidden symbol in ld.so. */
+ size = _rseq_size;
+#else
+ size = __rseq_size;
+#endif
+ if (size < RSEQ_AREA_SIZE_INITIAL)
+ /* The initial implementation used only 20 bytes out of 32,
+ but still expected size 32. */
+ size = RSEQ_AREA_SIZE_INITIAL;
int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area,
- sizeof (self->rseq_area),
- 0, RSEQ_SIG);
+ size, 0, RSEQ_SIG);
if (!INTERNAL_SYSCALL_ERROR_P (ret))
return true;
}
#else
struct stat
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
# else
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
br %r14
error:
lhi %r2,-EINVAL
+ lm %r6,%r7,24(%r15) /* Load registers. */
j SYSCALL_ERROR_LABEL
PSEUDO_END (__clone)
br %r14
error:
lghi %r2,-EINVAL
+ lmg %r6,%r7,48(%r15) /* Restore registers. */
jg SYSCALL_ERROR_LABEL
PSEUDO_END (__clone)
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 */
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
# else
__ino64_t st_ino; /* File serial number. */
# endif
-#endif /* __USE_TIME_BITS64 */
+#endif /* __USE_TIME64_REDIRECTS */
};
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
unsigned long int st_ctimensec; /* Nsecs of last status change. */
# endif
__ino64_t st_ino; /* File serial number. */
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif
# define SO_TIMESTAMPNS_NEW 0x0042
# define SO_TIMESTAMPING_NEW 0x0043
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# define SO_RCVTIMEO SO_RCVTIMEO_NEW
# define SO_SNDTIMEO SO_SNDTIMEO_NEW
# define SO_TIMESTAMP SO_TIMESTAMP_NEW
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
# endif
unsigned long int __glibc_reserved4;
unsigned long int __glibc_reserved5;
-#endif /* __USE_TIME_BITS64 */
+#endif /* __USE_TIME64_REDIRECTS */
};
#ifdef __USE_LARGEFILE64
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
# endif
unsigned long int __glibc_reserved4;
unsigned long int __glibc_reserved5;
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif
The type `struct msg' is opaque. */
struct msqid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_msqid64_ds_helper.h>
#else
struct ipc_perm msg_perm; /* structure describing operation permission */
/* Data structure describing a set of semaphores. */
struct semid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_semid64_ds_helper.h>
#else
struct ipc_perm sem_perm; /* operation permission struct */
/* Data structure describing a shared memory segment. */
struct shmid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_shmid64_ds_helper.h>
#else
struct ipc_perm shm_perm; /* operation permission struct */
#if defined __arch64__ || defined __sparcv9
# define __WORDSIZE 64
-# define __WORDSIZE_TIME64_COMPAT32 1
#else
# define __WORDSIZE 32
# define __WORDSIZE32_SIZE_ULONG 0
# define __WORDSIZE32_PTRDIFF_LONG 0
-# define __WORDSIZE_TIME64_COMPAT32 0
#endif
+#define __WORDSIZE_TIME64_COMPAT32 1
caller to actually collect it. */
ec = args.err;
if (ec > 0)
- /* There still an unlikely case where the child is cancelled after
- setting args.err, due to a positive error value. Also there is
- possible pid reuse race (where the kernel allocated the same pid
- to an unrelated process). Unfortunately due synchronization
- issues where the kernel might not have the process collected
- the waitpid below can not use WNOHANG. */
- __waitpid (new_pid, NULL, 0);
+ {
+ /* There still an unlikely case where the child is cancelled after
+ setting args.err, due to a positive error value. Also there is
+ possible pid reuse race (where the kernel allocated the same pid
+ to an unrelated process). Unfortunately due synchronization
+ issues where the kernel might not have the process collected
+ the waitpid below can not use WNOHANG. */
+ __waitid (use_pidfd ? P_PIDFD : P_PID,
+ use_pidfd ? args.pidfd : new_pid,
+ NULL,
+ WEXITED);
+ /* For pidfd we need to also close the file descriptor for the case
+ where execve fails. */
+ if (use_pidfd)
+ __close_nocancel_nostatus (args.pidfd);
+ }
}
else
ec = errno;
This function is a cancellation point and therefore not marked with
__THROW. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int epoll_pwait2 (int __epfd, struct epoll_event *__events,
int __maxevents, const struct timespec *__timeout,
const __sigset_t *__ss)
__BEGIN_DECLS
/* Control process execution. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int prctl (int __option, ...) __THROW;
#else
# ifdef __REDIRECT
const struct itimerspec *__utmr,
struct itimerspec *__otmr) __THROW;
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# if defined(__REDIRECT_NTH)
extern int __REDIRECT_NTH (timerfd_settime,
(int __ufd, int __flags,
/* Return the next expiration time of UFD. */
extern int timerfd_gettime (int __ufd, struct itimerspec *__otmr) __THROW;
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# if defined(__REDIRECT_NTH)
extern int __REDIRECT_NTH (timerfd_gettime, (int __ufd,
struct itimerspec *__otmr),
__BEGIN_DECLS
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int adjtimex (struct timex *__ntx) __THROW __nonnull ((1));
extern int ntp_gettimex (struct ntptimeval *__ntv) __THROW __nonnull ((1));
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 2.1 of the License.
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 2.1 of the License.
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-/* BZ #2386 */
+/* BZ #2386, BZ #31402 */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
+#include <stackinfo.h> /* For _STACK_GROWS_{UP,DOWN}. */
+#include <support/check.h>
+
+volatile unsigned v = 0xdeadbeef;
int child_fn(void *arg)
{
}
static int
-do_test (void)
+__attribute__((noinline))
+do_clone (int (*fn)(void *), void *stack)
{
int result;
+ unsigned int a = v;
+ unsigned int b = v;
+ unsigned int c = v;
+ unsigned int d = v;
+ unsigned int e = v;
+ unsigned int f = v;
+ unsigned int g = v;
+ unsigned int h = v;
+ unsigned int i = v;
+ unsigned int j = v;
+ unsigned int k = v;
+ unsigned int l = v;
+ unsigned int m = v;
+ unsigned int n = v;
+ unsigned int o = v;
+
+ result = clone (fn, stack, 0, NULL);
+
+ /* Check that clone does not clobber call-saved registers. */
+ TEST_VERIFY (a == v && b == v && c == v && d == v && e == v && f == v
+ && g == v && h == v && i == v && j == v && k == v && l == v
+ && m == v && n == v && o == v);
+
+ return result;
+}
+
+static void
+__attribute__((noinline))
+do_test_single (int (*fn)(void *), void *stack)
+{
+ printf ("%s (fn=%p, stack=%p)\n", __FUNCTION__, fn, stack);
+ errno = 0;
+
+ int result = do_clone (fn, stack);
+
+ TEST_COMPARE (errno, EINVAL);
+ TEST_COMPARE (result, -1);
+}
- result = clone (child_fn, NULL, 0, NULL);
+static int
+do_test (void)
+{
+ char st[128 * 1024] __attribute__ ((aligned));
+ void *stack = NULL;
+#if _STACK_GROWS_DOWN
+ stack = st + sizeof (st);
+#elif _STACK_GROWS_UP
+ stack = st;
+#else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+#endif
- if (errno != EINVAL || result != -1)
- {
- printf ("FAIL: clone()=%d (wanted -1) errno=%d (wanted %d)\n",
- result, errno, EINVAL);
- return 1;
- }
+ do_test_single (child_fn, NULL);
+ do_test_single (NULL, stack);
+ do_test_single (NULL, NULL);
- puts ("All OK");
return 0;
}
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+#include <support/test-driver.c>
# include <stdlib.h>
# include <string.h>
# include <syscall.h>
+# include <sys/auxv.h>
# include <thread_pointer.h>
# include <tls.h>
# include "tst-rseq.h"
TEST_COMPARE (__rseq_flags, 0);
TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
== (char *) &pd->rseq_area);
- TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area));
+ /* The current implementation only supports the initial size. */
+ TEST_COMPARE (__rseq_size, 20);
}
static void
{
FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
}
+ printf ("info: __rseq_size: %u\n", __rseq_size);
+ printf ("info: __rseq_offset: %td\n", __rseq_offset);
+ printf ("info: __rseq_flags: %u\n", __rseq_flags);
+ printf ("info: getauxval (AT_RSEQ_FEATURE_SIZE): %ld\n",
+ getauxval (AT_RSEQ_FEATURE_SIZE));
+ printf ("info: getauxval (AT_RSEQ_ALIGN): %ld\n", getauxval (AT_RSEQ_ALIGN));
do_rseq_main_test ();
}
#else /* RSEQ_SIG */
struct stat
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
#else
__dev_t st_dev; /* Device. */
__ino64_t st_ino; /* File serial number. */
# endif
# endif
-#endif /* __USE_TIME_BITS64 */
+#endif /* __USE_TIME64_REDIRECTS */
};
#ifdef __USE_LARGEFILE64
/* Note stat64 has the same shape as stat for x86-64. */
struct stat64
{
-# ifdef __USE_TIME_BITS64
+# ifdef __USE_TIME64_REDIRECTS
# include <bits/struct_stat_time64_helper.h>
# else
__dev_t st_dev; /* Device. */
# else
__ino64_t st_ino; /* File serial number. */
# endif
-# endif /* __USE_TIME_BITS64 */
+# endif /* __USE_TIME64_REDIRECTS */
};
#endif
/* Data structure describing a set of semaphores. */
struct semid_ds
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
# include <bits/types/struct_semid64_ds_helper.h>
#else
struct ipc_perm sem_perm; /* operation permission struct */
$(objpfx)libx86-64-isa-level.so: $(objpfx)libx86-64-isa-level-1.so
cp $< $@
endif
+
+ifeq (yes,$(have-mamx-tile))
+tests += \
+ tst-gnu2-tls2-amx \
+# tests
+
+modules-names += \
+ tst-gnu2-tls2-amx-mod0 \
+ tst-gnu2-tls2-amx-mod1 \
+ tst-gnu2-tls2-amx-mod2 \
+# modules-names
+
+$(objpfx)tst-gnu2-tls2-amx: $(shared-thread-library)
+$(objpfx)tst-gnu2-tls2-amx.out: \
+ $(objpfx)tst-gnu2-tls2-amx-mod0.so \
+ $(objpfx)tst-gnu2-tls2-amx-mod1.so \
+ $(objpfx)tst-gnu2-tls2-amx-mod2.so
+$(objpfx)tst-gnu2-tls2-amx-mod0.so: $(libsupport)
+$(objpfx)tst-gnu2-tls2-amx-mod1.so: $(libsupport)
+$(objpfx)tst-gnu2-tls2-amx-mod2.so: $(libsupport)
+
+CFLAGS-tst-gnu2-tls2-amx.c += -mamx-tile
+CFLAGS-tst-gnu2-tls2-amx-mod0.c += -mamx-tile -mtls-dialect=gnu2
+CFLAGS-tst-gnu2-tls2-amx-mod1.c += -mamx-tile -mtls-dialect=gnu2
+CFLAGS-tst-gnu2-tls2-amx-mod2.c += -mamx-tile -mtls-dialect=gnu2
+endif
+
endif # $(subdir) == elf
ifneq ($(enable-cet),no)
# define ARCH_SHSTK_SHSTK 0x1
# define ARCH_SHSTK_WRSS 0x2
#endif
+
+#ifndef ARCH_GET_XCOMP_PERM
+# define ARCH_GET_XCOMP_PERM 0x1022
+# define ARCH_REQ_XCOMP_PERM 0x1023
+#endif
--- /dev/null
+#include "tst-gnu2-tls2-amx.h"
+#include <tst-gnu2-tls2mod0.c>
--- /dev/null
+#include "tst-gnu2-tls2-amx.h"
+#include <tst-gnu2-tls2mod1.c>
--- /dev/null
+#include "tst-gnu2-tls2-amx.h"
+#include <tst-gnu2-tls2mod2.c>
--- /dev/null
+/* Test TLSDESC relocation with AMX.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+#include <asm/prctl.h>
+#include <support/check.h>
+#include "tst-gnu2-tls2-amx.h"
+
+extern int arch_prctl (int, ...);
+
+#define X86_XSTATE_TILECFG_ID 17
+#define X86_XSTATE_TILEDATA_ID 18
+
+/* Initialize tile config. */
+__attribute__ ((noinline, noclone))
+static void
+init_tile_config (__tilecfg *tileinfo)
+{
+ int i;
+ tileinfo->palette_id = 1;
+ tileinfo->start_row = 0;
+
+ tileinfo->colsb[0] = MAX_ROWS;
+ tileinfo->rows[0] = MAX_ROWS;
+
+ for (i = 1; i < 4; ++i)
+ {
+ tileinfo->colsb[i] = MAX_COLS;
+ tileinfo->rows[i] = MAX_ROWS;
+ }
+
+ _tile_loadconfig (tileinfo);
+}
+
+static bool
+enable_amx (void)
+{
+ uint64_t bitmask;
+ if (arch_prctl (ARCH_GET_XCOMP_PERM, &bitmask) != 0)
+ return false;
+
+ if ((bitmask & (1 << X86_XSTATE_TILECFG_ID)) == 0)
+ return false;
+
+ if (arch_prctl (ARCH_REQ_XCOMP_PERM, X86_XSTATE_TILEDATA_ID) != 0)
+ return false;
+
+ /* Load tile configuration. */
+ __tilecfg tile_data = { 0 };
+ init_tile_config (&tile_data);
+
+ return true;
+}
+
+/* An architecture can define it to clobber caller-saved registers in
+ malloc below to verify that the implicit TLSDESC call won't change
+ caller-saved registers. */
+static void
+clear_tile_register (void)
+{
+ _tile_zero (2);
+}
+
+#define MOD(i) "tst-gnu2-tls2-amx-mod" #i ".so"
+#define IS_SUPPORTED() enable_amx ()
+#define PREPARE_MALLOC() clear_tile_register ()
+
+#include <elf/tst-gnu2-tls2.c>
--- /dev/null
+/* Test TLSDESC relocation with AMX.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+#include <string.h>
+#include <x86intrin.h>
+#include <support/check.h>
+
+#define MAX_ROWS 16
+#define MAX_COLS 64
+#define MAX 1024
+#define STRIDE 64
+
+typedef struct __tile_config
+{
+ uint8_t palette_id;
+ uint8_t start_row;
+ uint8_t reserved_0[14];
+ uint16_t colsb[16];
+ uint8_t rows[16];
+} __tilecfg __attribute__ ((aligned (64)));
+
+/* Initialize int8_t buffer */
+static inline void
+init_buffer (int8_t *buf, int8_t value)
+{
+ int rows, colsb, i, j;
+ rows = MAX_ROWS;
+ colsb = MAX_COLS;
+
+ for (i = 0; i < rows; i++)
+ for (j = 0; j < colsb; j++)
+ buf[i * colsb + j] = value;
+}
+
+#define BEFORE_TLSDESC_CALL() \
+ int8_t src[MAX]; \
+ int8_t res[MAX]; \
+ /* Initialize src with data */ \
+ init_buffer (src, 2); \
+ /* Load tile rows from memory. */ \
+ _tile_loadd (2, src, STRIDE);
+
+#define AFTER_TLSDESC_CALL() \
+ /* Store the tile data to memory. */ \
+ _tile_stored (2, res, STRIDE); \
+ _tile_release (); \
+ TEST_VERIFY_EXIT (memcmp (src, res, sizeof (res)) == 0);
ifeq ($(subdir),csu)
-gen-as-const-headers += cpu-features-offsets.sym
+gen-as-const-headers += cpu-features-offsets.sym features-offsets.sym
endif
ifeq ($(subdir),elf)
CFLAGS-get-cpuid-feature-leaf.o += $(no-stack-protector)
tests += \
- tst-get-cpu-features \
- tst-get-cpu-features-static \
tst-cpu-features-cpuinfo \
tst-cpu-features-cpuinfo-static \
tst-cpu-features-supports \
tst-cpu-features-supports-static \
+ tst-get-cpu-features \
+ tst-get-cpu-features-static \
tst-hwcap-tunables \
# tests
tests-static += \
- tst-get-cpu-features-static \
tst-cpu-features-cpuinfo-static \
tst-cpu-features-supports-static \
+ tst-get-cpu-features-static \
# tests-static
ifeq (yes,$(have-ifunc))
ifeq (yes,$(have-gcc-ifunc))
tst-ifunc-isa-2-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-SSE4_2,-AVX,-AVX2,-AVX512F
tst-ifunc-isa-2-static-ENV = $(tst-ifunc-isa-2-ENV)
tst-hwcap-tunables-ARGS = -- $(host-test-program-cmd)
+
+CFLAGS-tst-gnu2-tls2.c += -msse
+CFLAGS-tst-gnu2-tls2mod0.c += -msse2 -mtune=haswell
+CFLAGS-tst-gnu2-tls2mod1.c += -msse2 -mtune=haswell
+CFLAGS-tst-gnu2-tls2mod2.c += -msse2 -mtune=haswell
endif
ifeq ($(subdir),math)
#define __WORDSIZE32_PTRDIFF_LONG 0
#endif
+#define __WORDSIZE_TIME64_COMPAT32 1
+
#ifdef __x86_64__
-# define __WORDSIZE_TIME64_COMPAT32 1
/* Both x86-64 and x32 use the 64-bit system call interface. */
# define __SYSCALL_WORDSIZE 64
-#else
-# define __WORDSIZE_TIME64_COMPAT32 0
#endif
if test $libc_cv_have_x86_lahf_sahf = yes; then
printf "%s\n" "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h
+ ISAFLAG="-DHAVE_X86_LAHF_SAHF"
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for MOVBE instruction support" >&5
printf %s "checking for MOVBE instruction support... " >&6; }
if test $libc_cv_have_x86_movbe = yes; then
printf "%s\n" "#define HAVE_X86_MOVBE 1" >>confdefs.h
+ ISAFLAG="$ISAFLAG -DHAVE_X86_MOVBE"
fi
+
+ # Check for ISA level support.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ISA level support" >&5
+printf %s "checking for ISA level support... " >&6; }
+if test ${libc_cv_have_x86_isa_level+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat > conftest.c <<EOF
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL >= 4
+libc_cv_have_x86_isa_level=4
+#elif MINIMUM_X86_ISA_LEVEL == 3
+libc_cv_have_x86_isa_level=3
+#elif MINIMUM_X86_ISA_LEVEL == 2
+libc_cv_have_x86_isa_level=2
+#elif defined __x86_64__
+libc_cv_have_x86_isa_level=baseline
+#elif MINIMUM_X86_ISA_LEVEL == 1
+libc_cv_have_x86_isa_level=1
+#else
+libc_cv_have_x86_isa_level=0
+#endif
+EOF
+ eval `${CC-cc} $CFLAGS $CPPFLAGS $ISAFLAG -I$srcdir -E conftest.c | grep libc_cv_have_x86_isa_level`
+ rm -rf conftest*
fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_have_x86_isa_level" >&5
+printf "%s\n" "$libc_cv_have_x86_isa_level" >&6; }
+elif test $base_machine = x86_64; then
+ libc_cv_have_x86_isa_level=baseline
+else
+ libc_cv_have_x86_isa_level=0
+fi
+if test $libc_cv_have_x86_isa_level = baseline; then
+ printf "%s\n" "#define MINIMUM_X86_ISA_LEVEL 1" >>confdefs.h
+
+else
+ printf "%s\n" "#define MINIMUM_X86_ISA_LEVEL $libc_cv_have_x86_isa_level" >>confdefs.h
+
+fi
+config_vars="$config_vars
+have-x86-isa-level = $libc_cv_have_x86_isa_level"
+config_vars="$config_vars
+x86-isa-level-3-or-above = 3 4"
config_vars="$config_vars
enable-x86-isa-level = $libc_cv_include_x86_isa_level"
fi])
if test $libc_cv_have_x86_lahf_sahf = yes; then
AC_DEFINE(HAVE_X86_LAHF_SAHF)
+ ISAFLAG="-DHAVE_X86_LAHF_SAHF"
fi
AC_CACHE_CHECK([for MOVBE instruction support],
libc_cv_have_x86_movbe, [dnl
fi])
if test $libc_cv_have_x86_movbe = yes; then
AC_DEFINE(HAVE_X86_MOVBE)
+ ISAFLAG="$ISAFLAG -DHAVE_X86_MOVBE"
fi
+
+ # Check for ISA level support.
+ AC_CACHE_CHECK([for ISA level support],
+ libc_cv_have_x86_isa_level, [dnl
+cat > conftest.c <<EOF
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL >= 4
+libc_cv_have_x86_isa_level=4
+#elif MINIMUM_X86_ISA_LEVEL == 3
+libc_cv_have_x86_isa_level=3
+#elif MINIMUM_X86_ISA_LEVEL == 2
+libc_cv_have_x86_isa_level=2
+#elif defined __x86_64__
+libc_cv_have_x86_isa_level=baseline
+#elif MINIMUM_X86_ISA_LEVEL == 1
+libc_cv_have_x86_isa_level=1
+#else
+libc_cv_have_x86_isa_level=0
+#endif
+EOF
+ eval `${CC-cc} $CFLAGS $CPPFLAGS $ISAFLAG -I$srcdir -E conftest.c | grep libc_cv_have_x86_isa_level`
+ rm -rf conftest*])
+elif test $base_machine = x86_64; then
+ libc_cv_have_x86_isa_level=baseline
+else
+ libc_cv_have_x86_isa_level=0
+fi
+if test $libc_cv_have_x86_isa_level = baseline; then
+ AC_DEFINE_UNQUOTED(MINIMUM_X86_ISA_LEVEL, 1)
+else
+ AC_DEFINE_UNQUOTED(MINIMUM_X86_ISA_LEVEL, $libc_cv_have_x86_isa_level)
fi
+LIBC_CONFIG_VAR([have-x86-isa-level], [$libc_cv_have_x86_isa_level])
+LIBC_CONFIG_VAR([x86-isa-level-3-or-above], [3 4])
LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level])
dnl Static PIE is supported.
#include <ldsodefs.h>
XSAVE_STATE_SIZE_OFFSET offsetof (struct cpu_features, xsave_state_size)
+XSAVE_STATE_FULL_SIZE_OFFSET offsetof (struct cpu_features, xsave_state_full_size)
#include <dl-hwcap.h>
#include <libc-pointer-arith.h>
+#include <isa-level.h>
#include <get-isa-level.h>
#include <cacheinfo.h>
#include <dl-cacheinfo.h>
extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
attribute_hidden;
-#if defined SHARED && defined __x86_64__
-# include <dl-plt-rewrite.h>
+#if defined SHARED
+extern void _dl_tlsdesc_dynamic_fxsave (void) attribute_hidden;
+extern void _dl_tlsdesc_dynamic_xsave (void) attribute_hidden;
+extern void _dl_tlsdesc_dynamic_xsavec (void) attribute_hidden;
+
+# ifdef __x86_64__
+# include <dl-plt-rewrite.h>
static void
TUNABLE_CALLBACK (set_plt_rewrite) (tunable_val_t *valp)
: plt_rewrite_jmp);
}
}
+# else
+extern void _dl_tlsdesc_dynamic_fnsave (void) attribute_hidden;
+# endif
+#endif
+
+#ifdef __x86_64__
+extern void _dl_runtime_resolve_fxsave (void) attribute_hidden;
+extern void _dl_runtime_resolve_xsave (void) attribute_hidden;
+extern void _dl_runtime_resolve_xsavec (void) attribute_hidden;
#endif
#ifdef __LP64__
__cpuid_count (0xd, 0, eax, ebx, ecx, edx);
if (ebx != 0)
{
+ /* NB: On AMX capable processors, ebx always includes AMX
+ states. */
unsigned int xsave_state_full_size
- = ALIGN_UP (ebx + STATE_SAVE_OFFSET, 64);
+ = ALIGN_UP (ebx + TLSDESC_CALL_REGISTER_SAVE_AREA, 64);
cpu_features->xsave_state_size
= xsave_state_full_size;
{
unsigned int xstate_comp_offsets[32];
unsigned int xstate_comp_sizes[32];
+#ifdef __x86_64__
+ unsigned int xstate_amx_comp_offsets[32];
+ unsigned int xstate_amx_comp_sizes[32];
+ unsigned int amx_ecx;
+#endif
unsigned int i;
xstate_comp_offsets[0] = 0;
xstate_comp_offsets[2] = 576;
xstate_comp_sizes[0] = 160;
xstate_comp_sizes[1] = 256;
+#ifdef __x86_64__
+ xstate_amx_comp_offsets[0] = 0;
+ xstate_amx_comp_offsets[1] = 160;
+ xstate_amx_comp_offsets[2] = 576;
+ xstate_amx_comp_sizes[0] = 160;
+ xstate_amx_comp_sizes[1] = 256;
+#endif
for (i = 2; i < 32; i++)
{
- if ((STATE_SAVE_MASK & (1 << i)) != 0)
+ if ((FULL_STATE_SAVE_MASK & (1 << i)) != 0)
{
__cpuid_count (0xd, i, eax, ebx, ecx, edx);
- xstate_comp_sizes[i] = eax;
+#ifdef __x86_64__
+ /* Include this in xsave_state_full_size. */
+ amx_ecx = ecx;
+ xstate_amx_comp_sizes[i] = eax;
+ if ((AMX_STATE_SAVE_MASK & (1 << i)) != 0)
+ {
+ /* Exclude this from xsave_state_size. */
+ ecx = 0;
+ xstate_comp_sizes[i] = 0;
+ }
+ else
+#endif
+ xstate_comp_sizes[i] = eax;
}
else
{
+#ifdef __x86_64__
+ amx_ecx = 0;
+ xstate_amx_comp_sizes[i] = 0;
+#endif
ecx = 0;
xstate_comp_sizes[i] = 0;
}
if ((ecx & (1 << 1)) != 0)
xstate_comp_offsets[i]
= ALIGN_UP (xstate_comp_offsets[i], 64);
+#ifdef __x86_64__
+ xstate_amx_comp_offsets[i]
+ = (xstate_amx_comp_offsets[i - 1]
+ + xstate_amx_comp_sizes[i - 1]);
+ if ((amx_ecx & (1 << 1)) != 0)
+ xstate_amx_comp_offsets[i]
+ = ALIGN_UP (xstate_amx_comp_offsets[i],
+ 64);
+#endif
}
}
= xstate_comp_offsets[31] + xstate_comp_sizes[31];
if (size)
{
+#ifdef __x86_64__
+ unsigned int amx_size
+ = (xstate_amx_comp_offsets[31]
+ + xstate_amx_comp_sizes[31]);
+ amx_size
+ = ALIGN_UP ((amx_size
+ + TLSDESC_CALL_REGISTER_SAVE_AREA),
+ 64);
+ /* Set xsave_state_full_size to the compact AMX
+ state size for XSAVEC. NB: xsave_state_full_size
+ is only used in _dl_tlsdesc_dynamic_xsave and
+ _dl_tlsdesc_dynamic_xsavec. */
+ cpu_features->xsave_state_full_size = amx_size;
+#endif
cpu_features->xsave_state_size
- = ALIGN_UP (size + STATE_SAVE_OFFSET, 64);
+ = ALIGN_UP (size + TLSDESC_CALL_REGISTER_SAVE_AREA,
+ 64);
CPU_FEATURE_SET (cpu_features, XSAVEC);
}
}
TUNABLE_CALLBACK (set_x86_shstk));
#endif
+ if (MINIMUM_X86_ISA_LEVEL >= AVX_X86_ISA_LEVEL
+ || (GLRO(dl_x86_cpu_features).xsave_state_size != 0))
+ {
+ if (CPU_FEATURE_USABLE_P (cpu_features, XSAVEC))
+ {
+#ifdef __x86_64__
+ GLRO(dl_x86_64_runtime_resolve) = _dl_runtime_resolve_xsavec;
+#endif
+#ifdef SHARED
+ GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_xsavec;
+#endif
+ }
+ else
+ {
+#ifdef __x86_64__
+ GLRO(dl_x86_64_runtime_resolve) = _dl_runtime_resolve_xsave;
+#endif
+#ifdef SHARED
+ GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_xsave;
+#endif
+ }
+ }
+ else
+ {
+#ifdef __x86_64__
+ GLRO(dl_x86_64_runtime_resolve) = _dl_runtime_resolve_fxsave;
+# ifdef SHARED
+ GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_fxsave;
+# endif
+#else
+# ifdef SHARED
+ if (CPU_FEATURE_USABLE_P (cpu_features, FXSR))
+ GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_fxsave;
+ else
+ GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_fnsave;
+# endif
+#endif
+ }
+
#ifdef SHARED
# ifdef __x86_64__
TUNABLE_GET (plt_rewrite, tunable_val_t *,
long int data = -1;
long int shared = -1;
long int shared_per_thread = -1;
- long int core = -1;
unsigned int threads = 0;
unsigned long int level1_icache_size = -1;
unsigned long int level1_icache_linesize = -1;
if (cpu_features->basic.kind == arch_kind_intel)
{
data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
- core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features);
shared_per_thread = shared;
= handle_intel (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
level1_dcache_linesize
= handle_intel (_SC_LEVEL1_DCACHE_LINESIZE, cpu_features);
- level2_cache_size = core;
+ level2_cache_size
+ = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
level2_cache_assoc
= handle_intel (_SC_LEVEL2_CACHE_ASSOC, cpu_features);
level2_cache_linesize
level4_cache_size
= handle_intel (_SC_LEVEL4_CACHE_SIZE, cpu_features);
- get_common_cache_info (&shared, &shared_per_thread, &threads, core);
+ get_common_cache_info (&shared, &shared_per_thread, &threads,
+ level2_cache_size);
}
else if (cpu_features->basic.kind == arch_kind_zhaoxin)
{
data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE);
- core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
shared_per_thread = shared;
level1_dcache_size = data;
level1_dcache_assoc = handle_zhaoxin (_SC_LEVEL1_DCACHE_ASSOC);
level1_dcache_linesize = handle_zhaoxin (_SC_LEVEL1_DCACHE_LINESIZE);
- level2_cache_size = core;
+ level2_cache_size = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
level2_cache_assoc = handle_zhaoxin (_SC_LEVEL2_CACHE_ASSOC);
level2_cache_linesize = handle_zhaoxin (_SC_LEVEL2_CACHE_LINESIZE);
level3_cache_size = shared;
level3_cache_assoc = handle_zhaoxin (_SC_LEVEL3_CACHE_ASSOC);
level3_cache_linesize = handle_zhaoxin (_SC_LEVEL3_CACHE_LINESIZE);
- get_common_cache_info (&shared, &shared_per_thread, &threads, core);
+ get_common_cache_info (&shared, &shared_per_thread, &threads,
+ level2_cache_size);
}
else if (cpu_features->basic.kind == arch_kind_amd)
{
data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
- core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
level1_dcache_size = data;
level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
- level2_cache_size = core;
+ level2_cache_size = handle_amd (_SC_LEVEL2_CACHE_SIZE);;
level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC);
level2_cache_linesize = handle_amd (_SC_LEVEL2_CACHE_LINESIZE);
level3_cache_size = shared;
if (shared <= 0)
{
/* No shared L3 cache. All we have is the L2 cache. */
- shared = core;
+ shared = level2_cache_size;
}
else if (cpu_features->basic.family < 0x17)
{
/* Account for exclusive L2 and L3 caches. */
- shared += core;
+ shared += level2_cache_size;
}
shared_per_thread = shared;
if (CPU_FEATURE_USABLE_P (cpu_features, FSRM))
rep_movsb_threshold = 2112;
+ /* For AMD CPUs that support ERMS (Zen3+), REP MOVSB is in a lot of
+ cases slower than the vectorized path (and for some alignments,
+ it is really slow, check BZ #30994). */
+ if (cpu_features->basic.kind == arch_kind_amd)
+ rep_movsb_threshold = non_temporal_threshold;
+
/* The default threshold to use Enhanced REP STOSB. */
unsigned long int rep_stosb_threshold = 2048;
minimum value is fixed. */
rep_stosb_threshold = TUNABLE_GET (x86_rep_stosb_threshold,
long int, NULL);
+ if (cpu_features->basic.kind == arch_kind_amd
+ && !TUNABLE_IS_INITIALIZED (x86_rep_stosb_threshold))
+ /* For AMD Zen3+ architecture, the performance of the vectorized loop is
+ slightly better than ERMS. */
+ rep_stosb_threshold = SIZE_MAX;
TUNABLE_SET_WITH_BOUNDS (x86_data_cache_size, data, 0, SIZE_MAX);
TUNABLE_SET_WITH_BOUNDS (x86_shared_cache_size, shared, 0, SIZE_MAX);
SIZE_MAX);
unsigned long int rep_movsb_stop_threshold;
- /* ERMS feature is implemented from AMD Zen3 architecture and it is
- performing poorly for data above L2 cache size. Henceforth, adding
- an upper bound threshold parameter to limit the usage of Enhanced
- REP MOVSB operations and setting its value to L2 cache size. */
- if (cpu_features->basic.kind == arch_kind_amd)
- rep_movsb_stop_threshold = core;
/* Setting the upper bound of ERMS to the computed value of
- non-temporal threshold for architectures other than AMD. */
- else
- rep_movsb_stop_threshold = non_temporal_threshold;
+ non-temporal threshold for all architectures. */
+ rep_movsb_stop_threshold = non_temporal_threshold;
cpu_features->data_cache_size = data;
cpu_features->shared_cache_size = shared;
#else
,
#endif
+
+#if defined SHARED && !IS_IN (ldconfig)
+# if !defined PROCINFO_DECL
+ ._dl_x86_tlsdesc_dynamic
+# else
+PROCINFO_CLASS void * _dl_x86_tlsdesc_dynamic
+# endif
+# ifndef PROCINFO_DECL
+= NULL
+# endif
+# ifdef PROCINFO_DECL
+;
+# else
+,
+# endif
+#endif
--- /dev/null
+#define SHARED 1
+
+#include <ldsodefs.h>
+
+RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET offsetof (struct rtld_global_ro, _dl_x86_cpu_features)
+#ifdef __x86_64__
+RTLD_GLOBAL_DL_X86_FEATURE_1_OFFSET offsetof (struct rtld_global, _dl_x86_feature_1)
+#endif
/* The full state size for XSAVE when XSAVEC is disabled by
GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
+
+ and the AMX state size when XSAVEC is available.
*/
unsigned int xsave_state_full_size;
/* Data cache size for use in memory and string routines, typically
# define __X86_ISA_V1 0
#endif
-#if __X86_ISA_V1 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 \
+#ifdef __x86_64__
+# ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
+# define __GCC_HAVE_SYNC_COMPARE_AND_SWAP
+# endif
+#else
+# ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+# define __GCC_HAVE_SYNC_COMPARE_AND_SWAP
+# endif
+#endif
+
+#if __X86_ISA_V1 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP \
&& defined HAVE_X86_LAHF_SAHF && defined __POPCNT__ && defined __SSE3__ \
&& defined __SSSE3__ && defined __SSE4_1__ && defined __SSE4_2__
/* NB: ISAs in x86-64 ISA level v2 are used. */
# define __X86_ISA_V4 0
#endif
-#define MINIMUM_X86_ISA_LEVEL \
+#ifndef MINIMUM_X86_ISA_LEVEL
+# define MINIMUM_X86_ISA_LEVEL \
(__X86_ISA_V1 + __X86_ISA_V2 + __X86_ISA_V3 + __X86_ISA_V4)
+#endif
/* Depending on the minimum ISA level, a feature check result can be a
compile-time constant.. */
#include <sysdeps/generic/sysdep.h>
+/* The extended state feature IDs in the state component bitmap. */
+#define X86_XSTATE_X87_ID 0
+#define X86_XSTATE_SSE_ID 1
+#define X86_XSTATE_AVX_ID 2
+#define X86_XSTATE_BNDREGS_ID 3
+#define X86_XSTATE_BNDCFG_ID 4
+#define X86_XSTATE_K_ID 5
+#define X86_XSTATE_ZMM_H_ID 6
+#define X86_XSTATE_ZMM_ID 7
+#define X86_XSTATE_PKRU_ID 9
+#define X86_XSTATE_TILECFG_ID 17
+#define X86_XSTATE_TILEDATA_ID 18
+#define X86_XSTATE_APX_F_ID 19
+
+#ifdef __x86_64__
/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need
space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be
- aligned to 16 bytes for fxsave and 64 bytes for xsave. */
-#define STATE_SAVE_OFFSET (8 * 7 + 8)
+ aligned to 16 bytes for fxsave and 64 bytes for xsave. It is non-zero
+ because MOV, instead of PUSH, is used to save registers onto stack.
+
+ +==================+<- stack frame start aligned at 8 or 16 bytes
+ | |<- paddings for stack realignment of 64 bytes
+ |------------------|<- xsave buffer end aligned at 64 bytes
+ | |<-
+ | |<-
+ | |<-
+ |------------------|<- xsave buffer start at STATE_SAVE_OFFSET(%rsp)
+ | |<- 8-byte padding for 64-byte alignment
+ | |<- R9
+ | |<- R8
+ | |<- RDI
+ | |<- RSI
+ | |<- RDX
+ | |<- RCX
+ | |<- RAX
+ +==================+<- RSP aligned at 64 bytes
+
+ */
+# define STATE_SAVE_OFFSET (8 * 7 + 8)
+
+/* _dl_tlsdesc_dynamic preserves RDI, RSI and RBX before realigning
+ stack. After realigning stack, it saves RCX, RDX, R8, R9, R10 and
+ R11. Allocate space for RDI, RSI and RBX to avoid clobbering saved
+ RDI, RSI and RBX values on stack by xsave.
+
+ +==================+<- stack frame start aligned at 8 or 16 bytes
+ | |<- RDI saved in the red zone
+ | |<- RSI saved in the red zone
+ | |<- RBX saved in the red zone
+ | |<- paddings for stack realignment of 64 bytes
+ |------------------|<- xsave buffer end aligned at 64 bytes
+ | |<-
+ | |<-
+ | |<-
+ |------------------|<- xsave buffer start at STATE_SAVE_OFFSET(%rsp)
+ | |<- 8-byte padding for 64-byte alignment
+ | |<- 8-byte padding for 64-byte alignment
+ | |<- R11
+ | |<- R10
+ | |<- R9
+ | |<- R8
+ | |<- RDX
+ | |<- RCX
+ +==================+<- RSP aligned at 64 bytes
+
+ Define the total register save area size for all integer registers by
+ adding 24 to STATE_SAVE_OFFSET since RDI, RSI and RBX are saved onto
+ stack without adjusting stack pointer first, using the red-zone. */
+# define TLSDESC_CALL_REGISTER_SAVE_AREA (STATE_SAVE_OFFSET + 24)
+
+/* Save SSE, AVX, AVX512, mask, bound and APX registers. Bound and APX
+ registers are mutually exclusive. */
+# define STATE_SAVE_MASK \
+ ((1 << X86_XSTATE_SSE_ID) \
+ | (1 << X86_XSTATE_AVX_ID) \
+ | (1 << X86_XSTATE_BNDREGS_ID) \
+ | (1 << X86_XSTATE_K_ID) \
+ | (1 << X86_XSTATE_ZMM_H_ID) \
+ | (1 << X86_XSTATE_ZMM_ID) \
+ | (1 << X86_XSTATE_APX_F_ID))
+
+/* AMX state mask. */
+# define AMX_STATE_SAVE_MASK \
+ ((1 << X86_XSTATE_TILECFG_ID) | (1 << X86_XSTATE_TILEDATA_ID))
+
+/* States to be included in xsave_state_full_size. */
+# define FULL_STATE_SAVE_MASK \
+ (STATE_SAVE_MASK | AMX_STATE_SAVE_MASK)
+#else
+/* Offset for fxsave/xsave area used by _dl_tlsdesc_dynamic. Since i386
+ uses PUSH to save registers onto stack, use 0 here. */
+# define STATE_SAVE_OFFSET 0
+# define TLSDESC_CALL_REGISTER_SAVE_AREA 0
+
+/* Save SSE, AVX, AXV512, mask and bound registers. */
+# define STATE_SAVE_MASK \
+ ((1 << X86_XSTATE_SSE_ID) \
+ | (1 << X86_XSTATE_AVX_ID) \
+ | (1 << X86_XSTATE_BNDREGS_ID) \
+ | (1 << X86_XSTATE_K_ID) \
+ | (1 << X86_XSTATE_ZMM_H_ID))
+
+/* States to be included in xsave_state_size. */
+# define FULL_STATE_SAVE_MASK STATE_SAVE_MASK
+#endif
-/* Save SSE, AVX, AVX512, mask and bound registers. */
-#define STATE_SAVE_MASK \
- ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7))
+/* States which should be saved for TLSDESC_CALL and TLS_DESC_CALL.
+ Compiler assumes that all registers, including AMX and x87 FPU
+ stack registers, are unchanged after CALL, except for EFLAGS and
+ RAX/EAX. */
+#define TLSDESC_CALL_STATE_SAVE_MASK \
+ (FULL_STATE_SAVE_MASK | (1 << X86_XSTATE_X87_ID))
/* Constants for bits in __x86_string_control: */
#endif
fails += CHECK_FEATURE_ACTIVE (avx, AVX);
fails += CHECK_FEATURE_ACTIVE (avx2, AVX2);
-#if __GNUC_PREREQ (7, 0)
+#if __GNUC_PREREQ (7, 0) && !__GNUC_PREREQ (15, 0)
fails += CHECK_FEATURE_ACTIVE (avx5124fmaps, AVX512_4FMAPS);
fails += CHECK_FEATURE_ACTIVE (avx5124vnniw, AVX512_4VNNIW);
#endif
#if __GNUC_PREREQ (6, 0)
fails += CHECK_FEATURE_ACTIVE (avx512bw, AVX512BW);
fails += CHECK_FEATURE_ACTIVE (avx512cd, AVX512CD);
+# if !__GNUC_PREREQ (15, 0)
fails += CHECK_FEATURE_ACTIVE (avx512er, AVX512ER);
+# endif
fails += CHECK_FEATURE_ACTIVE (avx512dq, AVX512DQ);
#endif
#if __GNUC_PREREQ (5, 0)
fails += CHECK_FEATURE_ACTIVE (avx512f, AVX512F);
#endif
#if __GNUC_PREREQ (6, 0)
+# if !__GNUC_PREREQ (15, 0)
fails += CHECK_FEATURE_ACTIVE (avx512pf, AVX512PF);
+# endif
fails += CHECK_FEATURE_ACTIVE (avx512vl, AVX512VL);
#endif
#if __GNUC_PREREQ (5, 0)
#endif
fails += CHECK_FEATURE_ACTIVE (popcnt, POPCNT);
#if __GNUC_PREREQ (11, 0)
+# if !__GNUC_PREREQ (15, 0)
fails += CHECK_FEATURE_ACTIVE (prefetchwt1, PREFETCHWT1);
+# endif
fails += CHECK_FEATURE_ACTIVE (ptwrite, PTWRITE);
fails += CHECK_FEATURE_ACTIVE (rdpid, RDPID);
fails += CHECK_FEATURE_ACTIVE (rdrnd, RDRAND);
--- /dev/null
+#ifndef __x86_64__
+#include <sys/platform/x86.h>
+
+#define IS_SUPPORTED() CPU_FEATURE_ACTIVE (SSE2)
+#endif
+
+/* Clear XMM0...XMM7 */
+#define PREPARE_MALLOC() \
+{ \
+ asm volatile ("xorps %%xmm0, %%xmm0" : : : "xmm0" ); \
+ asm volatile ("xorps %%xmm1, %%xmm1" : : : "xmm1" ); \
+ asm volatile ("xorps %%xmm2, %%xmm2" : : : "xmm2" ); \
+ asm volatile ("xorps %%xmm3, %%xmm3" : : : "xmm3" ); \
+ asm volatile ("xorps %%xmm4, %%xmm4" : : : "xmm4" ); \
+ asm volatile ("xorps %%xmm5, %%xmm5" : : : "xmm5" ); \
+ asm volatile ("xorps %%xmm6, %%xmm6" : : : "xmm6" ); \
+ asm volatile ("xorps %%xmm7, %%xmm7" : : : "xmm7" ); \
+}
+
+#include <elf/tst-gnu2-tls2.c>
--- /dev/null
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
endif
ifeq ($(subdir),csu)
-gen-as-const-headers += features-offsets.sym link-defines.sym
+gen-as-const-headers += link-defines.sym
endif
ifeq ($(subdir),gmon)
$(objpfx)tst-plt-rewrite2: $(objpfx)tst-plt-rewritemod2.so
endif
+test-internal-extras += tst-gnu2-tls2mod1
+
endif # $(subdir) == elf
ifeq ($(subdir),csu)
tests += \
tst-cet-legacy-1 \
+ tst-cet-legacy-10 \
+ tst-cet-legacy-10-static \
+ tst-cet-legacy-10a \
+ tst-cet-legacy-10a-static \
tst-cet-legacy-1a \
tst-cet-legacy-2 \
tst-cet-legacy-2a \
tst-cet-legacy-8 \
tst-cet-legacy-9 \
tst-cet-legacy-9-static \
- tst-cet-legacy-10 \
- tst-cet-legacy-10-static \
- tst-cet-legacy-10a \
- tst-cet-legacy-10a-static \
# tests
tests-static += \
- tst-cet-legacy-9-static \
tst-cet-legacy-10-static \
tst-cet-legacy-10a-static \
+ tst-cet-legacy-9-static \
# tests-static
tst-cet-legacy-1a-ARGS = -- $(host-test-program-cmd)
config_vars="$config_vars
enable-cet = $enable_cet"
+# Check if -mamx-tile works properly.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -mamx-tile works properly" >&5
+printf %s "checking whether -mamx-tile works properly... " >&6; }
+if test ${libc_cv_x86_have_amx_tile+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat > conftest.c <<EOF
+#include <x86intrin.h>
+EOF
+ libc_cv_x86_have_amx_tile=no
+ if { ac_try='${CC-cc} -E $CFLAGS -mamx-tile conftest.c > conftest.i'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ if grep -q __builtin_ia32_ldtilecfg conftest.i; then
+ libc_cv_x86_have_amx_tile=yes
+ fi
+ fi
+ rm -rf conftest*
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_x86_have_amx_tile" >&5
+printf "%s\n" "$libc_cv_x86_have_amx_tile" >&6; }
+config_vars="$config_vars
+have-mamx-tile = $libc_cv_x86_have_amx_tile"
+
test -n "$critic_missing" && as_fn_error $? "
*** $critic_missing" "$LINENO" 5
fi
LIBC_CONFIG_VAR([enable-cet], [$enable_cet])
+# Check if -mamx-tile works properly.
+AC_CACHE_CHECK(whether -mamx-tile works properly,
+ libc_cv_x86_have_amx_tile, [dnl
+cat > conftest.c <<EOF
+#include <x86intrin.h>
+EOF
+ libc_cv_x86_have_amx_tile=no
+ if AC_TRY_COMMAND(${CC-cc} -E $CFLAGS -mamx-tile conftest.c > conftest.i); then
+ if grep -q __builtin_ia32_ldtilecfg conftest.i; then
+ libc_cv_x86_have_amx_tile=yes
+ fi
+ fi
+ rm -rf conftest*])
+LIBC_CONFIG_VAR([have-mamx-tile], [$libc_cv_x86_have_amx_tile])
+
test -n "$critic_missing" && AC_MSG_ERROR([
*** $critic_missing])
int lazy, int profile)
{
Elf64_Addr *got;
- extern void _dl_runtime_resolve_fxsave (ElfW(Word)) attribute_hidden;
- extern void _dl_runtime_resolve_xsave (ElfW(Word)) attribute_hidden;
- extern void _dl_runtime_resolve_xsavec (ElfW(Word)) attribute_hidden;
extern void _dl_runtime_profile_sse (ElfW(Word)) attribute_hidden;
extern void _dl_runtime_profile_avx (ElfW(Word)) attribute_hidden;
extern void _dl_runtime_profile_avx512 (ElfW(Word)) attribute_hidden;
/* Identify this shared object. */
*(ElfW(Addr) *) (got + 1) = (ElfW(Addr)) l;
- const struct cpu_features* cpu_features = __get_cpu_features ();
-
#ifdef SHARED
/* The got[2] entry contains the address of a function which gets
called to get the address of a so far unresolved function and
end in this function. */
if (__glibc_unlikely (profile))
{
+ const struct cpu_features* cpu_features = __get_cpu_features ();
if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, AVX512F))
*(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_profile_avx512;
else if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, AVX))
/* This function will get called to fix up the GOT entry
indicated by the offset on the stack, and then jump to
the resolved address. */
- if (MINIMUM_X86_ISA_LEVEL >= AVX_X86_ISA_LEVEL
- || GLRO(dl_x86_cpu_features).xsave_state_size != 0)
- *(ElfW(Addr) *) (got + 2)
- = (CPU_FEATURE_USABLE_P (cpu_features, XSAVEC)
- ? (ElfW(Addr)) &_dl_runtime_resolve_xsavec
- : (ElfW(Addr)) &_dl_runtime_resolve_xsave);
- else
- *(ElfW(Addr) *) (got + 2)
- = (ElfW(Addr)) &_dl_runtime_resolve_fxsave;
+ *(ElfW(Addr) *) (got + 2)
+ = (ElfW(Addr)) GLRO(dl_x86_64_runtime_resolve);
}
}
{
td->arg = _dl_make_tlsdesc_dynamic
(sym_map, sym->st_value + reloc->r_addend);
- td->entry = _dl_tlsdesc_dynamic;
+ td->entry = GLRO(dl_x86_tlsdesc_dynamic);
}
else
# endif
#include <sysdeps/x86/dl-procinfo.c>
+#if !IS_IN (ldconfig)
+# if !defined PROCINFO_DECL && defined SHARED
+ ._dl_x86_64_runtime_resolve
+# else
+PROCINFO_CLASS void * _dl_x86_64_runtime_resolve
+# endif
+# ifndef PROCINFO_DECL
+= NULL
+# endif
+# if !defined SHARED || defined PROCINFO_DECL
+;
+# else
+,
+# endif
+#endif
+
#undef PROCINFO_DECL
#undef PROCINFO_CLASS
--- /dev/null
+/* Thread-local storage handling in the ELF dynamic linker. x86_64 version.
+ Copyright (C) 2004-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef SECTION
+# define SECTION(p) p
+#endif
+
+#undef REGISTER_SAVE_AREA
+#undef LOCAL_STORAGE_AREA
+#undef BASE
+
+#include "dl-trampoline-state.h"
+
+ .section SECTION(.text),"ax",@progbits
+
+ .hidden _dl_tlsdesc_dynamic
+ .global _dl_tlsdesc_dynamic
+ .type _dl_tlsdesc_dynamic,@function
+
+ /* %rax points to the TLS descriptor, such that 0(%rax) points to
+ _dl_tlsdesc_dynamic itself, and 8(%rax) points to a struct
+ tlsdesc_dynamic_arg object. It must return in %rax the offset
+ between the thread pointer and the object denoted by the
+ argument, without clobbering any registers.
+
+ The assembly code that follows is a rendition of the following
+ C code, hand-optimized a little bit.
+
+ptrdiff_t
+_dl_tlsdesc_dynamic (register struct tlsdesc *tdp asm ("%rax"))
+{
+ struct tlsdesc_dynamic_arg *td = tdp->arg;
+ dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + DTV_OFFSET);
+ if (__builtin_expect (td->gen_count <= dtv[0].counter
+ && (dtv[td->tlsinfo.ti_module].pointer.val
+ != TLS_DTV_UNALLOCATED),
+ 1))
+ return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset
+ - __thread_pointer;
+
+ return __tls_get_addr_internal (&td->tlsinfo) - __thread_pointer;
+}
+*/
+ cfi_startproc
+ .align 16
+_dl_tlsdesc_dynamic:
+ _CET_ENDBR
+ /* Preserve call-clobbered registers that we modify.
+ We need two scratch regs anyway. */
+ movq %rsi, -16(%rsp)
+ mov %fs:DTV_OFFSET, %RSI_LP
+ movq %rdi, -8(%rsp)
+ movq TLSDESC_ARG(%rax), %rdi
+ movq (%rsi), %rax
+ cmpq %rax, TLSDESC_GEN_COUNT(%rdi)
+ ja 2f
+ movq TLSDESC_MODID(%rdi), %rax
+ salq $4, %rax
+ movq (%rax,%rsi), %rax
+ cmpq $-1, %rax
+ je 2f
+ addq TLSDESC_MODOFF(%rdi), %rax
+1:
+ movq -16(%rsp), %rsi
+ sub %fs:0, %RAX_LP
+ movq -8(%rsp), %rdi
+ ret
+2:
+#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+ movq %rbx, -24(%rsp)
+ mov %RSP_LP, %RBX_LP
+ cfi_def_cfa_register(%rbx)
+ and $-STATE_SAVE_ALIGNMENT, %RSP_LP
+#endif
+#ifdef REGISTER_SAVE_AREA
+# if DL_RUNTIME_RESOLVE_REALIGN_STACK
+ /* STATE_SAVE_OFFSET has space for 8 integer registers. But we
+ need space for RCX, RDX, RSI, RDI, R8, R9, R10 and R11, plus
+ RBX above. */
+ sub $(REGISTER_SAVE_AREA + STATE_SAVE_ALIGNMENT), %RSP_LP
+# else
+ sub $REGISTER_SAVE_AREA, %RSP_LP
+ cfi_adjust_cfa_offset(REGISTER_SAVE_AREA)
+# endif
+#else
+ /* Allocate stack space of the required size to save the state. */
+ sub _rtld_local_ro+RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET+XSAVE_STATE_FULL_SIZE_OFFSET(%rip), %RSP_LP
+#endif
+ /* Besides rdi and rsi, saved above, save rcx, rdx, r8, r9,
+ r10 and r11. */
+ movq %rcx, REGISTER_SAVE_RCX(%rsp)
+ movq %rdx, REGISTER_SAVE_RDX(%rsp)
+ movq %r8, REGISTER_SAVE_R8(%rsp)
+ movq %r9, REGISTER_SAVE_R9(%rsp)
+ movq %r10, REGISTER_SAVE_R10(%rsp)
+ movq %r11, REGISTER_SAVE_R11(%rsp)
+#ifdef USE_FXSAVE
+ fxsave STATE_SAVE_OFFSET(%rsp)
+#else
+ movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax
+ xorl %edx, %edx
+ /* Clear the XSAVE Header. */
+# ifdef USE_XSAVE
+ movq %rdx, (STATE_SAVE_OFFSET + 512)(%rsp)
+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8)(%rsp)
+# endif
+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 2)(%rsp)
+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 3)(%rsp)
+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 4)(%rsp)
+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 5)(%rsp)
+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 6)(%rsp)
+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 7)(%rsp)
+# ifdef USE_XSAVE
+ xsave STATE_SAVE_OFFSET(%rsp)
+# else
+ xsavec STATE_SAVE_OFFSET(%rsp)
+# endif
+#endif
+ /* %rdi already points to the tlsinfo data structure. */
+ call HIDDEN_JUMPTARGET (__tls_get_addr)
+ # Get register content back.
+#ifdef USE_FXSAVE
+ fxrstor STATE_SAVE_OFFSET(%rsp)
+#else
+ /* Save and retore __tls_get_addr return value stored in RAX. */
+ mov %RAX_LP, %RCX_LP
+ movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax
+ xorl %edx, %edx
+ xrstor STATE_SAVE_OFFSET(%rsp)
+ mov %RCX_LP, %RAX_LP
+#endif
+ movq REGISTER_SAVE_R11(%rsp), %r11
+ movq REGISTER_SAVE_R10(%rsp), %r10
+ movq REGISTER_SAVE_R9(%rsp), %r9
+ movq REGISTER_SAVE_R8(%rsp), %r8
+ movq REGISTER_SAVE_RDX(%rsp), %rdx
+ movq REGISTER_SAVE_RCX(%rsp), %rcx
+#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+ mov %RBX_LP, %RSP_LP
+ cfi_def_cfa_register(%rsp)
+ movq -24(%rsp), %rbx
+ cfi_restore(%rbx)
+#else
+ add $REGISTER_SAVE_AREA, %RSP_LP
+ cfi_adjust_cfa_offset(-REGISTER_SAVE_AREA)
+#endif
+ jmp 1b
+ cfi_endproc
+ .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+
+#undef STATE_SAVE_ALIGNMENT
#include <sysdep.h>
#include <tls.h>
+#include <cpu-features-offsets.h>
+#include <features-offsets.h>
+#include <isa-level.h>
#include "tlsdesc.h"
+#include "dl-trampoline-save.h"
+
+/* Area on stack to save and restore registers used for parameter
+ passing when calling _dl_tlsdesc_dynamic. */
+#define REGISTER_SAVE_RCX 0
+#define REGISTER_SAVE_RDX (REGISTER_SAVE_RCX + 8)
+#define REGISTER_SAVE_R8 (REGISTER_SAVE_RDX + 8)
+#define REGISTER_SAVE_R9 (REGISTER_SAVE_R8 + 8)
+#define REGISTER_SAVE_R10 (REGISTER_SAVE_R9 + 8)
+#define REGISTER_SAVE_R11 (REGISTER_SAVE_R10 + 8)
.text
.size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
#ifdef SHARED
- .hidden _dl_tlsdesc_dynamic
- .global _dl_tlsdesc_dynamic
- .type _dl_tlsdesc_dynamic,@function
-
- /* %rax points to the TLS descriptor, such that 0(%rax) points to
- _dl_tlsdesc_dynamic itself, and 8(%rax) points to a struct
- tlsdesc_dynamic_arg object. It must return in %rax the offset
- between the thread pointer and the object denoted by the
- argument, without clobbering any registers.
-
- The assembly code that follows is a rendition of the following
- C code, hand-optimized a little bit.
-
-ptrdiff_t
-_dl_tlsdesc_dynamic (register struct tlsdesc *tdp asm ("%rax"))
-{
- struct tlsdesc_dynamic_arg *td = tdp->arg;
- dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + DTV_OFFSET);
- if (__builtin_expect (td->gen_count <= dtv[0].counter
- && (dtv[td->tlsinfo.ti_module].pointer.val
- != TLS_DTV_UNALLOCATED),
- 1))
- return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset
- - __thread_pointer;
-
- return __tls_get_addr_internal (&td->tlsinfo) - __thread_pointer;
-}
-*/
- cfi_startproc
- .align 16
-_dl_tlsdesc_dynamic:
- _CET_ENDBR
- /* Preserve call-clobbered registers that we modify.
- We need two scratch regs anyway. */
- movq %rsi, -16(%rsp)
- mov %fs:DTV_OFFSET, %RSI_LP
- movq %rdi, -8(%rsp)
- movq TLSDESC_ARG(%rax), %rdi
- movq (%rsi), %rax
- cmpq %rax, TLSDESC_GEN_COUNT(%rdi)
- ja .Lslow
- movq TLSDESC_MODID(%rdi), %rax
- salq $4, %rax
- movq (%rax,%rsi), %rax
- cmpq $-1, %rax
- je .Lslow
- addq TLSDESC_MODOFF(%rdi), %rax
-.Lret:
- movq -16(%rsp), %rsi
- sub %fs:0, %RAX_LP
- movq -8(%rsp), %rdi
- ret
-.Lslow:
- /* Besides rdi and rsi, saved above, save rdx, rcx, r8, r9,
- r10 and r11. Also, align the stack, that's off by 8 bytes. */
- subq $72, %rsp
- cfi_adjust_cfa_offset (72)
- movq %rdx, 8(%rsp)
- movq %rcx, 16(%rsp)
- movq %r8, 24(%rsp)
- movq %r9, 32(%rsp)
- movq %r10, 40(%rsp)
- movq %r11, 48(%rsp)
- /* %rdi already points to the tlsinfo data structure. */
- call HIDDEN_JUMPTARGET (__tls_get_addr)
- movq 8(%rsp), %rdx
- movq 16(%rsp), %rcx
- movq 24(%rsp), %r8
- movq 32(%rsp), %r9
- movq 40(%rsp), %r10
- movq 48(%rsp), %r11
- addq $72, %rsp
- cfi_adjust_cfa_offset (-72)
- jmp .Lret
- cfi_endproc
- .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+# if MINIMUM_X86_ISA_LEVEL < AVX_X86_ISA_LEVEL
+# define USE_FXSAVE
+# define STATE_SAVE_ALIGNMENT 16
+# define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_fxsave
+# include "dl-tlsdesc-dynamic.h"
+# undef _dl_tlsdesc_dynamic
+# undef USE_FXSAVE
+# endif
+
+# define USE_XSAVE
+# define STATE_SAVE_ALIGNMENT 64
+# define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_xsave
+# include "dl-tlsdesc-dynamic.h"
+# undef _dl_tlsdesc_dynamic
+# undef USE_XSAVE
+
+# define USE_XSAVEC
+# define STATE_SAVE_ALIGNMENT 64
+# define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_xsavec
+# include "dl-tlsdesc-dynamic.h"
+# undef _dl_tlsdesc_dynamic
+# undef USE_XSAVEC
#endif /* SHARED */
--- /dev/null
+/* x86-64 PLT trampoline register save macros.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef DL_STACK_ALIGNMENT
+/* Due to GCC bug:
+
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
+
+ __tls_get_addr may be called with 8-byte stack alignment. Although
+ this bug has been fixed in GCC 4.9.4, 5.3 and 6, we can't assume
+ that stack will be always aligned at 16 bytes. */
+# define DL_STACK_ALIGNMENT 8
+#endif
+
+/* True if _dl_runtime_resolve should align stack for STATE_SAVE or align
+ stack to 16 bytes before calling _dl_fixup. */
+#define DL_RUNTIME_RESOLVE_REALIGN_STACK \
+ (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \
+ || 16 > DL_STACK_ALIGNMENT)
--- /dev/null
+/* x86-64 PLT dl-trampoline state macros.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#if (STATE_SAVE_ALIGNMENT % 16) != 0
+# error STATE_SAVE_ALIGNMENT must be multiple of 16
+#endif
+
+#if (STATE_SAVE_OFFSET % STATE_SAVE_ALIGNMENT) != 0
+# error STATE_SAVE_OFFSET must be multiple of STATE_SAVE_ALIGNMENT
+#endif
+
+#if DL_RUNTIME_RESOLVE_REALIGN_STACK
+/* Local stack area before jumping to function address: RBX. */
+# define LOCAL_STORAGE_AREA 8
+# define BASE rbx
+# ifdef USE_FXSAVE
+/* Use fxsave to save XMM registers. */
+# define REGISTER_SAVE_AREA (512 + STATE_SAVE_OFFSET)
+# if (REGISTER_SAVE_AREA % 16) != 0
+# error REGISTER_SAVE_AREA must be multiple of 16
+# endif
+# endif
+#else
+# ifndef USE_FXSAVE
+# error USE_FXSAVE must be defined
+# endif
+/* Use fxsave to save XMM registers. */
+# define REGISTER_SAVE_AREA (512 + STATE_SAVE_OFFSET + 8)
+/* Local stack area before jumping to function address: All saved
+ registers. */
+# define LOCAL_STORAGE_AREA REGISTER_SAVE_AREA
+# define BASE rsp
+# if (REGISTER_SAVE_AREA % 16) != 8
+# error REGISTER_SAVE_AREA must be odd multiple of 8
+# endif
+#endif
#include <features-offsets.h>
#include <link-defines.h>
#include <isa-level.h>
-
-#ifndef DL_STACK_ALIGNMENT
-/* Due to GCC bug:
-
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
-
- __tls_get_addr may be called with 8-byte stack alignment. Although
- this bug has been fixed in GCC 4.9.4, 5.3 and 6, we can't assume
- that stack will be always aligned at 16 bytes. We use unaligned
- 16-byte move to load and store SSE registers, which has no penalty
- on modern processors if stack is 16-byte aligned. */
-# define DL_STACK_ALIGNMENT 8
-#endif
-
-/* True if _dl_runtime_resolve should align stack for STATE_SAVE or align
- stack to 16 bytes before calling _dl_fixup. */
-#define DL_RUNTIME_RESOLVE_REALIGN_STACK \
- (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \
- || 16 > DL_STACK_ALIGNMENT)
+#include "dl-trampoline-save.h"
/* Area on stack to save and restore registers used for parameter
passing when calling _dl_fixup. */
# undef LOCAL_STORAGE_AREA
# undef BASE
-# if (STATE_SAVE_ALIGNMENT % 16) != 0
-# error STATE_SAVE_ALIGNMENT must be multiple of 16
-# endif
-
-# if (STATE_SAVE_OFFSET % STATE_SAVE_ALIGNMENT) != 0
-# error STATE_SAVE_OFFSET must be multiple of STATE_SAVE_ALIGNMENT
-# endif
-
-# if DL_RUNTIME_RESOLVE_REALIGN_STACK
-/* Local stack area before jumping to function address: RBX. */
-# define LOCAL_STORAGE_AREA 8
-# define BASE rbx
-# ifdef USE_FXSAVE
-/* Use fxsave to save XMM registers. */
-# define REGISTER_SAVE_AREA (512 + STATE_SAVE_OFFSET)
-# if (REGISTER_SAVE_AREA % 16) != 0
-# error REGISTER_SAVE_AREA must be multiple of 16
-# endif
-# endif
-# else
-# ifndef USE_FXSAVE
-# error USE_FXSAVE must be defined
-# endif
-/* Use fxsave to save XMM registers. */
-# define REGISTER_SAVE_AREA (512 + STATE_SAVE_OFFSET + 8)
-/* Local stack area before jumping to function address: All saved
- registers. */
-# define LOCAL_STORAGE_AREA REGISTER_SAVE_AREA
-# define BASE rsp
-# if (REGISTER_SAVE_AREA % 16) != 8
-# error REGISTER_SAVE_AREA must be odd multiple of 8
-# endif
-# endif
+# include "dl-trampoline-state.h"
.globl _dl_runtime_resolve
.hidden _dl_runtime_resolve
+++ /dev/null
-#define SHARED 1
-
-#include <ldsodefs.h>
-
-RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET offsetof (struct rtld_global_ro, _dl_x86_cpu_features)
-RTLD_GLOBAL_DL_X86_FEATURE_1_OFFSET offsetof (struct rtld_global, _dl_x86_feature_1)
ifeq ($(subdir),math)
-libm-sysdep_routines += \
- s_ceil-c \
- s_ceilf-c \
- s_floor-c \
- s_floorf-c \
- s_rint-c \
- s_rintf-c \
- s_nearbyint-c \
- s_nearbyintf-c \
- s_roundeven-c \
- s_roundevenf-c \
- s_trunc-c \
- s_truncf-c \
-# libm-sysdep_routines
-
-libm-sysdep_routines += \
- s_ceil-sse4_1 \
- s_ceilf-sse4_1 \
- s_floor-sse4_1 \
- s_floorf-sse4_1 \
- s_nearbyint-sse4_1 \
- s_nearbyintf-sse4_1 \
- s_roundeven-sse4_1 \
- s_roundevenf-sse4_1 \
- s_rint-sse4_1 \
- s_rintf-sse4_1 \
- s_trunc-sse4_1 \
- s_truncf-sse4_1 \
-# libm-sysdep_routines
-
-libm-sysdep_routines += \
- e_asin-fma \
- e_atan2-fma \
- e_exp-fma \
- e_log-fma \
- e_log2-fma \
- e_pow-fma \
- s_atan-fma \
- s_expm1-fma \
- s_log1p-fma \
- s_sin-fma \
- s_sincos-fma \
- s_tan-fma \
-# libm-sysdep_routines
-
CFLAGS-e_asin-fma.c = -mfma -mavx2
CFLAGS-e_atan2-fma.c = -mfma -mavx2
CFLAGS-e_exp-fma.c = -mfma -mavx2
CFLAGS-s_tan-fma.c = -mfma -mavx2
CFLAGS-s_sincos-fma.c = -mfma -mavx2
-libm-sysdep_routines += \
- s_cosf-sse2 \
- s_sincosf-sse2 \
- s_sinf-sse2 \
-# libm-sysdep_routines
-
-libm-sysdep_routines += \
- e_exp2f-fma \
- e_expf-fma \
- e_log2f-fma \
- e_logf-fma \
- e_powf-fma \
- s_cosf-fma \
- s_sincosf-fma \
- s_sinf-fma \
-# libm-sysdep_routines
-
CFLAGS-e_exp2f-fma.c = -mfma -mavx2
CFLAGS-e_expf-fma.c = -mfma -mavx2
CFLAGS-e_log2f-fma.c = -mfma -mavx2
CFLAGS-s_cosf-fma.c = -mfma -mavx2
CFLAGS-s_sincosf-fma.c = -mfma -mavx2
+# Check if ISA level is 3 or above.
+ifneq (,$(filter $(have-x86-isa-level),$(x86-isa-level-3-or-above)))
+libm-sysdep_routines += \
+ s_ceil-avx \
+ s_ceilf-avx \
+ s_floor-avx \
+ s_floorf-avx \
+ s_nearbyint-avx \
+ s_nearbyintf-avx \
+ s_rint-avx \
+ s_rintf-avx \
+ s_roundeven-avx \
+ s_roundevenf-avx \
+ s_trunc-avx \
+ s_truncf-avx \
+# libm-sysdep_routines
+else
libm-sysdep_routines += \
+ e_asin-fma \
+ e_asin-fma4 \
+ e_atan2-avx \
+ e_atan2-fma \
+ e_atan2-fma4 \
+ e_exp-avx \
+ e_exp-fma \
e_exp-fma4 \
+ e_exp2f-fma \
+ e_expf-fma \
+ e_log-avx \
+ e_log-fma \
e_log-fma4 \
+ e_log2-fma \
+ e_log2f-fma \
+ e_logf-fma \
+ e_pow-fma \
e_pow-fma4 \
- e_asin-fma4 \
+ e_powf-fma \
+ s_atan-avx \
+ s_atan-fma \
s_atan-fma4 \
- e_atan2-fma4 \
+ s_ceil-sse4_1 \
+ s_ceilf-sse4_1 \
+ s_cosf-fma \
+ s_cosf-sse2 \
+ s_expm1-fma \
+ s_floor-sse4_1 \
+ s_floorf-sse4_1 \
+ s_log1p-fma \
+ s_nearbyint-sse4_1 \
+ s_nearbyintf-sse4_1 \
+ s_rint-sse4_1 \
+ s_rintf-sse4_1 \
+ s_roundeven-sse4_1 \
+ s_roundevenf-sse4_1 \
+ s_sin-avx \
+ s_sin-fma \
s_sin-fma4 \
+ s_sincos-avx \
+ s_sincos-fma \
s_sincos-fma4 \
+ s_sincosf-fma \
+ s_sincosf-sse2 \
+ s_sinf-fma \
+ s_sinf-sse2 \
+ s_tan-avx \
+ s_tan-fma \
s_tan-fma4 \
+ s_trunc-sse4_1 \
+ s_truncf-sse4_1 \
+# libm-sysdep_routines
+ifeq ($(have-x86-isa-level),baseline)
+libm-sysdep_routines += \
+ s_ceil-c \
+ s_ceilf-c \
+ s_floor-c \
+ s_floorf-c \
+ s_nearbyint-c \
+ s_nearbyintf-c \
+ s_rint-c \
+ s_rintf-c \
+ s_roundeven-c \
+ s_roundevenf-c \
+ s_trunc-c \
+ s_truncf-c \
# libm-sysdep_routines
+endif
+endif
CFLAGS-e_asin-fma4.c = -mfma4
CFLAGS-e_atan2-fma4.c = -mfma4
CFLAGS-s_tan-fma4.c = -mfma4
CFLAGS-s_sincos-fma4.c = -mfma4
-libm-sysdep_routines += \
- e_exp-avx \
- e_log-avx \
- s_atan-avx \
- e_atan2-avx \
- s_sin-avx \
- s_sincos-avx \
- s_tan-avx \
-# libm-sysdep_routines
-
CFLAGS-e_atan2-avx.c = -msse2avx -DSSE2AVX
CFLAGS-e_exp-avx.c = -msse2avx -DSSE2AVX
CFLAGS-e_log-avx.c = -msse2avx -DSSE2AVX
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-finite.h>
extern double __redirect_ieee754_asin (double);
extern double __redirect_ieee754_acos (double);
-#define SYMBOL_NAME ieee754_asin
-#include "ifunc-fma4.h"
+# define SYMBOL_NAME ieee754_asin
+# include "ifunc-fma4.h"
libc_ifunc_redirected (__redirect_ieee754_asin, __ieee754_asin,
IFUNC_SELECTOR ());
libm_alias_finite (__ieee754_asin, __asin)
-#undef SYMBOL_NAME
-#define SYMBOL_NAME ieee754_acos
-#include "ifunc-fma4.h"
+# undef SYMBOL_NAME
+# define SYMBOL_NAME ieee754_acos
+# include "ifunc-fma4.h"
libc_ifunc_redirected (__redirect_ieee754_acos, __ieee754_acos,
IFUNC_SELECTOR ());
libm_alias_finite (__ieee754_acos, __acos)
-#define __ieee754_acos __ieee754_acos_sse2
-#define __ieee754_asin __ieee754_asin_sse2
+# define __ieee754_acos __ieee754_acos_sse2
+# define __ieee754_asin __ieee754_asin_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/e_asin.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-finite.h>
extern double __redirect_ieee754_atan2 (double, double);
-#define SYMBOL_NAME ieee754_atan2
-#include "ifunc-avx-fma4.h"
+# define SYMBOL_NAME ieee754_atan2
+# include "ifunc-avx-fma4.h"
libc_ifunc_redirected (__redirect_ieee754_atan2,
__ieee754_atan2, IFUNC_SELECTOR ());
libm_alias_finite (__ieee754_atan2, __atan2)
-#define __ieee754_atan2 __ieee754_atan2_sse2
+# define __ieee754_atan2 __ieee754_atan2_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/e_atan2.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <math.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <math.h>
+# include <libm-alias-finite.h>
extern double __redirect_ieee754_exp (double);
-#define SYMBOL_NAME ieee754_exp
-#include "ifunc-avx-fma4.h"
+# define SYMBOL_NAME ieee754_exp
+# include "ifunc-avx-fma4.h"
libc_ifunc_redirected (__redirect_ieee754_exp, __ieee754_exp,
IFUNC_SELECTOR ());
libm_alias_finite (__ieee754_exp, __exp)
-#define __exp __ieee754_exp_sse2
+# define __exp __ieee754_exp_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/e_exp.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# include <libm-alias-finite.h>
extern float __redirect_exp2f (float);
-#define SYMBOL_NAME exp2f
-#include "ifunc-fma.h"
+# define SYMBOL_NAME exp2f
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_exp2f, __exp2f, IFUNC_SELECTOR ());
-#ifdef SHARED
+# ifdef SHARED
versioned_symbol (libm, __ieee754_exp2f, exp2f, GLIBC_2_27);
libm_alias_float_other (__exp2, exp2)
-#else
+# else
libm_alias_float (__exp2, exp2)
-#endif
+# endif
strong_alias (__exp2f, __ieee754_exp2f)
libm_alias_finite (__exp2f, __exp2f)
-#define __exp2f __exp2f_sse2
+# define __exp2f __exp2f_sse2
+#endif
#include <sysdeps/ieee754/flt-32/e_exp2f.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# include <libm-alias-finite.h>
extern float __redirect_expf (float);
-#define SYMBOL_NAME expf
-#include "ifunc-fma.h"
+# define SYMBOL_NAME expf
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_expf, __expf, IFUNC_SELECTOR ());
-#ifdef SHARED
+# ifdef SHARED
__hidden_ver1 (__expf, __GI___expf, __redirect_expf)
__attribute__ ((visibility ("hidden")));
versioned_symbol (libm, __ieee754_expf, expf, GLIBC_2_27);
libm_alias_float_other (__exp, exp)
-#else
+# else
libm_alias_float (__exp, exp)
-#endif
+# endif
strong_alias (__expf, __ieee754_expf)
libm_alias_finite (__expf, __expf)
-#define __expf __expf_sse2
+# define __expf __expf_sse2
+#endif
#include <sysdeps/ieee754/flt-32/e_expf.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <math.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <math.h>
+# include <libm-alias-finite.h>
extern double __redirect_ieee754_log (double);
-#define SYMBOL_NAME ieee754_log
-#include "ifunc-avx-fma4.h"
+# define SYMBOL_NAME ieee754_log
+# include "ifunc-avx-fma4.h"
libc_ifunc_redirected (__redirect_ieee754_log, __ieee754_log,
IFUNC_SELECTOR ());
libm_alias_finite (__ieee754_log, __log)
-#define __log __ieee754_log_sse2
+# define __log __ieee754_log_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/e_log.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-double.h>
+# include <libm-alias-finite.h>
extern double __redirect_log2 (double);
-#define SYMBOL_NAME log2
-#include "ifunc-fma.h"
+# define SYMBOL_NAME log2
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_log2, __log2, IFUNC_SELECTOR ());
-#ifdef SHARED
+# ifdef SHARED
__hidden_ver1 (__log2, __GI___log2, __redirect_log2)
__attribute__ ((visibility ("hidden")));
versioned_symbol (libm, __ieee754_log2, log2, GLIBC_2_29);
libm_alias_double_other (__log2, log2)
-#else
+# else
libm_alias_double (__log2, log2)
-#endif
+# endif
strong_alias (__log2, __ieee754_log2)
libm_alias_finite (__log2, __log2)
-#define __log2 __log2_sse2
+# define __log2 __log2_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/e_log2.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# include <libm-alias-finite.h>
extern float __redirect_log2f (float);
-#define SYMBOL_NAME log2f
-#include "ifunc-fma.h"
+# define SYMBOL_NAME log2f
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_log2f, __log2f, IFUNC_SELECTOR ());
-#ifdef SHARED
+# ifdef SHARED
__hidden_ver1 (__log2f, __GI___log2f, __redirect_log2f)
__attribute__ ((visibility ("hidden")));
versioned_symbol (libm, __ieee754_log2f, log2f, GLIBC_2_27);
libm_alias_float_other (__log2, log2)
-#else
+# else
libm_alias_float (__log2, log2)
-#endif
+# endif
strong_alias (__log2f, __ieee754_log2f)
libm_alias_finite (__log2f, __log2f)
-#define __log2f __log2f_sse2
+# define __log2f __log2f_sse2
+#endif
#include <sysdeps/ieee754/flt-32/e_log2f.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# include <libm-alias-finite.h>
extern float __redirect_logf (float);
-#define SYMBOL_NAME logf
-#include "ifunc-fma.h"
+# define SYMBOL_NAME logf
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_logf, __logf, IFUNC_SELECTOR ());
-#ifdef SHARED
+# ifdef SHARED
__hidden_ver1 (__logf, __GI___logf, __redirect_logf)
__attribute__ ((visibility ("hidden")));
versioned_symbol (libm, __ieee754_logf, logf, GLIBC_2_27);
libm_alias_float_other (__log, log)
-#else
+# else
libm_alias_float (__log, log)
-#endif
+# endif
strong_alias (__logf, __ieee754_logf)
libm_alias_finite (__logf, __logf)
-#define __logf __logf_sse2
+# define __logf __logf_sse2
+#endif
#include <sysdeps/ieee754/flt-32/e_logf.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <math.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <math.h>
+# include <libm-alias-finite.h>
extern double __redirect_ieee754_pow (double, double);
-#define SYMBOL_NAME ieee754_pow
-#include "ifunc-fma4.h"
+# define SYMBOL_NAME ieee754_pow
+# include "ifunc-fma4.h"
libc_ifunc_redirected (__redirect_ieee754_pow,
__ieee754_pow, IFUNC_SELECTOR ());
libm_alias_finite (__ieee754_pow, __pow)
-#define __pow __ieee754_pow_sse2
+# define __pow __ieee754_pow_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/e_pow.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
-#include <libm-alias-finite.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# include <libm-alias-finite.h>
-#define powf __redirect_powf
-#define __DECL_SIMD___redirect_powf
-#include <math.h>
-#undef powf
+# define powf __redirect_powf
+# define __DECL_SIMD___redirect_powf
+# include <math.h>
+# undef powf
-#define SYMBOL_NAME powf
-#include "ifunc-fma.h"
+# define SYMBOL_NAME powf
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_powf, __powf, IFUNC_SELECTOR ());
-#ifdef SHARED
+# ifdef SHARED
__hidden_ver1 (__powf, __GI___powf, __redirect_powf)
__attribute__ ((visibility ("hidden")));
versioned_symbol (libm, __ieee754_powf, powf, GLIBC_2_27);
libm_alias_float_other (__pow, pow)
-#else
+# else
libm_alias_float (__pow, pow)
-#endif
+# endif
strong_alias (__powf, __ieee754_powf)
libm_alias_finite (__powf, __powf)
-#define __powf __powf_sse2
+# define __powf __powf_sse2
+#endif
#include <sysdeps/ieee754/flt-32/e_powf.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-double.h>
extern double __redirect_atan (double);
-#define SYMBOL_NAME atan
-#include "ifunc-avx-fma4.h"
+# define SYMBOL_NAME atan
+# include "ifunc-avx-fma4.h"
libc_ifunc_redirected (__redirect_atan, __atan, IFUNC_SELECTOR ());
libm_alias_double (__atan, atan)
-#define __atan __atan_sse2
+# define __atan __atan_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/s_atan.c>
--- /dev/null
+/* AVX implementation of ceil function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-double.h>
+
+ .text
+ENTRY(__ceil)
+ vroundsd $10, %xmm0, %xmm0, %xmm0
+ ret
+END(__ceil)
+
+libm_alias_double (__ceil, ceil)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-double.h>
+# define __ceil_sse41 __ceil
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__ceil_sse41)
roundsd $10, %xmm0, %xmm0
ret
END(__ceil_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_double (__ceil, ceil)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define NO_MATH_REDIRECT
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# define NO_MATH_REDIRECT
+# include <libm-alias-double.h>
-#define ceil __redirect_ceil
-#define __ceil __redirect___ceil
-#include <math.h>
-#undef ceil
-#undef __ceil
+# define ceil __redirect_ceil
+# define __ceil __redirect___ceil
+# include <math.h>
+# undef ceil
+# undef __ceil
-#define SYMBOL_NAME ceil
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME ceil
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_ceil, __ceil, IFUNC_SELECTOR ());
libm_alias_double (__ceil, ceil)
+#endif
--- /dev/null
+/* AVX implementation of ceilf function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-float.h>
+
+ .text
+ENTRY(__ceilf)
+ vroundss $10, %xmm0, %xmm0, %xmm0
+ ret
+END(__ceilf)
+
+libm_alias_float (__ceil, ceil)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# define __ceilf_sse41 __ceilf
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__ceilf_sse41)
roundss $10, %xmm0, %xmm0
ret
END(__ceilf_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_float (__ceil, ceil)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define NO_MATH_REDIRECT
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# define NO_MATH_REDIRECT
+# include <libm-alias-float.h>
-#define ceilf __redirect_ceilf
-#define __ceilf __redirect___ceilf
-#include <math.h>
-#undef ceilf
-#undef __ceilf
+# define ceilf __redirect_ceilf
+# define __ceilf __redirect___ceilf
+# include <math.h>
+# undef ceilf
+# undef __ceilf
-#define SYMBOL_NAME ceilf
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME ceilf
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_ceilf, __ceilf, IFUNC_SELECTOR ());
libm_alias_float (__ceil, ceil)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-float.h>
extern float __redirect_cosf (float);
-#define SYMBOL_NAME cosf
-#include "ifunc-fma.h"
+# define SYMBOL_NAME cosf
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_cosf, __cosf, IFUNC_SELECTOR ());
libm_alias_float (__cos, cos)
+#else
+# include <sysdeps/ieee754/flt-32/s_cosf.c>
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-double.h>
extern double __redirect_expm1 (double);
-#define SYMBOL_NAME expm1
-#include "ifunc-fma.h"
+# define SYMBOL_NAME expm1
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_expm1, __expm1, IFUNC_SELECTOR ());
libm_alias_double (__expm1, expm1)
-#define __expm1 __expm1_sse2
+# define __expm1 __expm1_sse2
/* NB: __expm1 may be expanded to __expm1_sse2 in the following
prototypes. */
extern long double __expm1l (long double);
extern long double __expm1f128 (long double);
+#endif
#include <sysdeps/ieee754/dbl-64/s_expm1.c>
--- /dev/null
+/* AVX implementation of floor function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-double.h>
+
+ .text
+ENTRY(__floor)
+ vroundsd $9, %xmm0, %xmm0, %xmm0
+ ret
+END(__floor)
+
+libm_alias_double (__floor, floor)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-double.h>
+# define __floor_sse41 __floor
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__floor_sse41)
roundsd $9, %xmm0, %xmm0
ret
END(__floor_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_double (__floor, floor)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define NO_MATH_REDIRECT
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# define NO_MATH_REDIRECT
+# include <libm-alias-double.h>
-#define floor __redirect_floor
-#define __floor __redirect___floor
-#include <math.h>
-#undef floor
-#undef __floor
+# define floor __redirect_floor
+# define __floor __redirect___floor
+# include <math.h>
+# undef floor
+# undef __floor
-#define SYMBOL_NAME floor
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME floor
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_floor, __floor, IFUNC_SELECTOR ());
libm_alias_double (__floor, floor)
+#endif
--- /dev/null
+/* AVX implementation of floorf function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-float.h>
+
+ .text
+ENTRY(__floorf)
+ vroundss $9, %xmm0, %xmm0, %xmm0
+ ret
+END(__floorf)
+
+libm_alias_float (__floor, floor)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# define __floorf_sse41 __floorf
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__floorf_sse41)
roundss $9, %xmm0, %xmm0
ret
END(__floorf_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_float (__floor, floor)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define NO_MATH_REDIRECT
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# define NO_MATH_REDIRECT
+# include <libm-alias-float.h>
-#define floorf __redirect_floorf
-#define __floorf __redirect___floorf
-#include <math.h>
-#undef floorf
-#undef __floorf
+# define floorf __redirect_floorf
+# define __floorf __redirect___floorf
+# include <math.h>
+# undef floorf
+# undef __floorf
-#define SYMBOL_NAME floorf
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME floorf
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_floorf, __floorf, IFUNC_SELECTOR ());
libm_alias_float (__floor, floor)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-double.h>
extern double __redirect_log1p (double);
-#define SYMBOL_NAME log1p
-#include "ifunc-fma.h"
+# define SYMBOL_NAME log1p
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_log1p, __log1p, IFUNC_SELECTOR ());
-#define __log1p __log1p_sse2
+# define __log1p __log1p_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/s_log1p.c>
--- /dev/null
+/* AVX implementation of nearbyint function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-double.h>
+
+ .text
+ENTRY(__nearbyint)
+ vroundsd $0xc, %xmm0, %xmm0, %xmm0
+ ret
+END(__nearbyint)
+
+libm_alias_double (__nearbyint, nearbyint)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-double.h>
+# define __nearbyint_sse41 __nearbyint
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__nearbyint_sse41)
roundsd $0xc, %xmm0, %xmm0
ret
END(__nearbyint_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_double (__nearbyint, nearbyint)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-double.h>
-#define nearbyint __redirect_nearbyint
-#define __nearbyint __redirect___nearbyint
-#include <math.h>
-#undef nearbyint
-#undef __nearbyint
+# define nearbyint __redirect_nearbyint
+# define __nearbyint __redirect___nearbyint
+# include <math.h>
+# undef nearbyint
+# undef __nearbyint
-#define SYMBOL_NAME nearbyint
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME nearbyint
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_nearbyint, __nearbyint,
IFUNC_SELECTOR ());
libm_alias_double (__nearbyint, nearbyint)
+#endif
--- /dev/null
+/* AVX implmentation of nearbyintf function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-float.h>
+
+ .text
+ENTRY(__nearbyintf)
+ vroundss $0xc, %xmm0, %xmm0, %xmm0
+ ret
+END(__nearbyintf)
+
+libm_alias_float (__nearbyint, nearbyint)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# define __nearbyintf_sse41 __nearbyintf
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__nearbyintf_sse41)
roundss $0xc, %xmm0, %xmm0
ret
END(__nearbyintf_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_float (__nearbyint, nearbyint)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-float.h>
-#define nearbyintf __redirect_nearbyintf
-#define __nearbyintf __redirect___nearbyintf
-#include <math.h>
-#undef nearbyintf
-#undef __nearbyintf
+# define nearbyintf __redirect_nearbyintf
+# define __nearbyintf __redirect___nearbyintf
+# include <math.h>
+# undef nearbyintf
+# undef __nearbyintf
-#define SYMBOL_NAME nearbyintf
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME nearbyintf
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_nearbyintf, __nearbyintf,
IFUNC_SELECTOR ());
libm_alias_float (__nearbyint, nearbyint)
+#endif
--- /dev/null
+/* AVX implementation of rint function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-double.h>
+
+ .text
+ENTRY(__rint)
+ vroundsd $4, %xmm0, %xmm0, %xmm0
+ ret
+END(__rint)
+
+libm_alias_double (__rint, rint)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-double.h>
+# define __rint_sse41 __rint
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__rint_sse41)
roundsd $4, %xmm0, %xmm0
ret
END(__rint_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_double (__rint, rint)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define NO_MATH_REDIRECT
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# define NO_MATH_REDIRECT
+# include <libm-alias-double.h>
-#define rint __redirect_rint
-#define __rint __redirect___rint
-#include <math.h>
-#undef rint
-#undef __rint
+# define rint __redirect_rint
+# define __rint __redirect___rint
+# include <math.h>
+# undef rint
+# undef __rint
-#define SYMBOL_NAME rint
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME rint
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_rint, __rint, IFUNC_SELECTOR ());
libm_alias_double (__rint, rint)
+#endif
--- /dev/null
+/* AVX implementation of rintf function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-float.h>
+
+ .text
+ENTRY(__rintf)
+ vroundss $4, %xmm0, %xmm0, %xmm0
+ ret
+END(__rintf)
+
+libm_alias_float (__rint, rint)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# define __rintf_sse41 __rintf
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__rintf_sse41)
roundss $4, %xmm0, %xmm0
ret
END(__rintf_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_float (__rint, rint)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define NO_MATH_REDIRECT
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# define NO_MATH_REDIRECT
+# include <libm-alias-float.h>
-#define rintf __redirect_rintf
-#define __rintf __redirect___rintf
-#include <math.h>
-#undef rintf
-#undef __rintf
+# define rintf __redirect_rintf
+# define __rintf __redirect___rintf
+# include <math.h>
+# undef rintf
+# undef __rintf
-#define SYMBOL_NAME rintf
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME rintf
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_rintf, __rintf, IFUNC_SELECTOR ());
libm_alias_float (__rint, rint)
+#endif
--- /dev/null
+/* AVX implementation of roundeven function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-double.h>
+
+ .text
+ENTRY(__roundeven)
+ vroundsd $8, %xmm0, %xmm0, %xmm0
+ ret
+END(__roundeven)
+
+libm_alias_double (__roundeven, roundeven)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-double.h>
+# define __roundeven_sse41 __roundeven
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__roundeven_sse41)
roundsd $8, %xmm0, %xmm0
ret
END(__roundeven_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_double (__roundeven, roundeven)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-double.h>
-#define roundeven __redirect_roundeven
-#define __roundeven __redirect___roundeven
-#include <math.h>
-#undef roundeven
-#undef __roundeven
+# define roundeven __redirect_roundeven
+# define __roundeven __redirect___roundeven
+# include <math.h>
+# undef roundeven
+# undef __roundeven
-#define SYMBOL_NAME roundeven
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME roundeven
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_roundeven, __roundeven, IFUNC_SELECTOR ());
libm_alias_double (__roundeven, roundeven)
+#endif
--- /dev/null
+/* AVX implementation of roundevenf function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-float.h>
+
+ .text
+ENTRY(__roundevenf)
+ vroundss $8, %xmm0, %xmm0, %xmm0
+ ret
+END(__roundevenf)
+
+libm_alias_float (__roundeven, roundeven)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# define __roundevenf_sse41 __roundevenf
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__roundevenf_sse41)
roundss $8, %xmm0, %xmm0
ret
END(__roundevenf_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_float (__roundeven, roundeven)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-float.h>
-#define roundevenf __redirect_roundevenf
-#define __roundevenf __redirect___roundevenf
-#include <math.h>
-#undef roundevenf
-#undef __roundevenf
+# define roundevenf __redirect_roundevenf
+# define __roundevenf __redirect___roundevenf
+# include <math.h>
+# undef roundevenf
+# undef __roundevenf
-#define SYMBOL_NAME roundevenf
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME roundevenf
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_roundevenf, __roundevenf, IFUNC_SELECTOR ());
libm_alias_float (__roundeven, roundeven)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-double.h>
extern double __redirect_sin (double);
extern double __redirect_cos (double);
-#define SYMBOL_NAME sin
-#include "ifunc-avx-fma4.h"
+# define SYMBOL_NAME sin
+# include "ifunc-avx-fma4.h"
libc_ifunc_redirected (__redirect_sin, __sin, IFUNC_SELECTOR ());
libm_alias_double (__sin, sin)
-#undef SYMBOL_NAME
-#define SYMBOL_NAME cos
-#include "ifunc-avx-fma4.h"
+# undef SYMBOL_NAME
+# define SYMBOL_NAME cos
+# include "ifunc-avx-fma4.h"
libc_ifunc_redirected (__redirect_cos, __cos, IFUNC_SELECTOR ());
libm_alias_double (__cos, cos)
-#define __cos __cos_sse2
-#define __sin __sin_sse2
+# define __cos __cos_sse2
+# define __sin __sin_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/s_sin.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-double.h>
extern void __redirect_sincos (double, double *, double *);
-#define SYMBOL_NAME sincos
-#include "ifunc-fma4.h"
+# define SYMBOL_NAME sincos
+# include "ifunc-fma4.h"
libc_ifunc_redirected (__redirect_sincos, __sincos, IFUNC_SELECTOR ());
libm_alias_double (__sincos, sincos)
-#define __sincos __sincos_sse2
+# define __sincos __sincos_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/s_sincos.c>
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-float.h>
extern void __redirect_sincosf (float, float *, float *);
-#define SYMBOL_NAME sincosf
-#include "ifunc-fma.h"
+# define SYMBOL_NAME sincosf
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_sincosf, __sincosf, IFUNC_SELECTOR ());
libm_alias_float (__sincos, sincos)
+#else
+# include <sysdeps/ieee754/flt-32/s_sincosf.c>
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-float.h>
extern float __redirect_sinf (float);
-#define SYMBOL_NAME sinf
-#include "ifunc-fma.h"
+# define SYMBOL_NAME sinf
+# include "ifunc-fma.h"
libc_ifunc_redirected (__redirect_sinf, __sinf, IFUNC_SELECTOR ());
libm_alias_float (__sin, sin)
+#else
+# include <sysdeps/ieee754/flt-32/s_sinf.c>
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < AVX2_X86_ISA_LEVEL
+# include <libm-alias-double.h>
extern double __redirect_tan (double);
-#define SYMBOL_NAME tan
-#include "ifunc-avx-fma4.h"
+# define SYMBOL_NAME tan
+# include "ifunc-avx-fma4.h"
libc_ifunc_redirected (__redirect_tan, __tan, IFUNC_SELECTOR ());
libm_alias_double (__tan, tan)
-#define __tan __tan_sse2
+# define __tan __tan_sse2
+#endif
#include <sysdeps/ieee754/dbl-64/s_tan.c>
--- /dev/null
+/* AVX implementation of trunc function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-double.h>
+
+ .text
+ENTRY(__trunc)
+ vroundsd $11, %xmm0, %xmm0, %xmm0
+ ret
+END(__trunc)
+
+libm_alias_double (__trunc, trunc)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-double.h>
+# define __trunc_sse41 __trunc
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__trunc_sse41)
roundsd $11, %xmm0, %xmm0
ret
END(__trunc_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_double (__trunc, trunc)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define NO_MATH_REDIRECT
-#include <libm-alias-double.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# define NO_MATH_REDIRECT
+# include <libm-alias-double.h>
-#define trunc __redirect_trunc
-#define __trunc __redirect___trunc
-#include <math.h>
-#undef trunc
-#undef __trunc
+# define trunc __redirect_trunc
+# define __trunc __redirect___trunc
+# include <math.h>
+# undef trunc
+# undef __trunc
-#define SYMBOL_NAME trunc
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME trunc
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_trunc, __trunc, IFUNC_SELECTOR ());
libm_alias_double (__trunc, trunc)
+#endif
--- /dev/null
+/* AVX implementation of truncf function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <libm-alias-float.h>
+
+ .text
+ENTRY(__truncf)
+ vroundss $11, %xmm0, %xmm0, %xmm0
+ ret
+END(__truncf)
+
+libm_alias_float (__trunc, trunc)
#include <sysdep.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+# include <libm-alias-float.h>
+# define __truncf_sse41 __truncf
+ .text
+#else
.section .text.sse4.1,"ax",@progbits
+#endif
+
ENTRY(__truncf_sse41)
roundss $11, %xmm0, %xmm0
ret
END(__truncf_sse41)
+
+#if MINIMUM_X86_ISA_LEVEL == SSE4_1_X86_ISA_LEVEL
+libm_alias_float (__trunc, trunc)
+#endif
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define NO_MATH_REDIRECT
-#include <libm-alias-float.h>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL < SSE4_1_X86_ISA_LEVEL
+# define NO_MATH_REDIRECT
+# include <libm-alias-float.h>
-#define truncf __redirect_truncf
-#define __truncf __redirect___truncf
-#include <math.h>
-#undef truncf
-#undef __truncf
+# define truncf __redirect_truncf
+# define __truncf __redirect___truncf
+# include <math.h>
+# undef truncf
+# undef __truncf
-#define SYMBOL_NAME truncf
-#include "ifunc-sse4_1.h"
+# define SYMBOL_NAME truncf
+# include "ifunc-sse4_1.h"
libc_ifunc_redirected (__redirect_truncf, __truncf, IFUNC_SELECTOR ());
libm_alias_float (__trunc, trunc)
+#endif
-#include <sysdeps/../math/w_exp.c>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL >= AVX2_X86_ISA_LEVEL
+# include <sysdeps/ieee754/dbl-64/w_exp.c>
+#else
+# include <sysdeps/../math/w_exp.c>
+#endif
-#include <sysdeps/../math/w_log.c>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL >= AVX2_X86_ISA_LEVEL
+# include <sysdeps/ieee754/dbl-64/w_log.c>
+#else
+# include <sysdeps/../math/w_log.c>
+#endif
-#include <sysdeps/../math/w_pow.c>
+#include <sysdeps/x86/isa-level.h>
+#if MINIMUM_X86_ISA_LEVEL >= AVX2_X86_ISA_LEVEL
+# include <sysdeps/ieee754/dbl-64/w_pow.c>
+#else
+# include <sysdeps/../math/w_pow.c>
+#endif
memchr-avx2 \
memchr-avx2-rtm \
memchr-evex \
- memchr-evex512 \
memchr-evex-rtm \
+ memchr-evex512 \
memchr-sse2 \
memcmp-avx2-movbe \
memcmp-avx2-movbe-rtm \
rawmemchr-avx2 \
rawmemchr-avx2-rtm \
rawmemchr-evex \
- rawmemchr-evex512 \
rawmemchr-evex-rtm \
+ rawmemchr-evex512 \
rawmemchr-sse2 \
stpcpy-avx2 \
stpcpy-avx2-rtm \
2. If size is less than VEC, use integer register stores.
3. If size is from VEC_SIZE to 2 * VEC_SIZE, use 2 VEC stores.
4. If size is from 2 * VEC_SIZE to 4 * VEC_SIZE, use 4 VEC stores.
- 5. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
+ 5. On machines ERMS feature, if size is greater or equal than
+ __x86_rep_stosb_threshold then REP STOSB will be used.
+ 6. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
4 VEC stores and store 4 * VEC at a time until done. */
#include <sysdep.h>
-#ifndef WCSCAT
-# define WCSCAT __wcsncat_evex
+#ifndef WCSNCAT
+# define WCSNCAT __wcsncat_evex
#endif
#define USE_AS_WCSCPY
#define USE_AS_STRCAT
-#define STRNCAT WCSCAT
+#define STRNCAT WCSNCAT
#include "strncat-evex.S"
--- /dev/null
+/* Check if TLSDESC relocation preserves %rdi, %rsi and %rbx.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* On AVX512 machines, OFFSET == 40 caused _dl_tlsdesc_dynamic_xsavec
+ to clobber %rdi, %rsi and %rbx. On Intel AVX CPUs, the state size
+ is 960 bytes and this test didn't fail. It may be due to the unused
+ last 128 bytes. On AMD AVX CPUs, the state size is 832 bytes and
+ this test might fail without the fix. */
+#ifndef OFFSET
+# define OFFSET 40
+#endif
+
+ .text
+ .p2align 4
+ .globl apply_tls
+ .type apply_tls, @function
+apply_tls:
+ cfi_startproc
+ _CET_ENDBR
+ pushq %rbp
+ cfi_def_cfa_offset (16)
+ cfi_offset (6, -16)
+ movdqu (%RDI_LP), %xmm0
+ lea tls_var1@TLSDESC(%rip), %RAX_LP
+ mov %RSP_LP, %RBP_LP
+ cfi_def_cfa_register (6)
+ /* Align stack to 64 bytes. */
+ and $-64, %RSP_LP
+ sub $OFFSET, %RSP_LP
+ pushq %rbx
+ /* Set %ebx to 0xbadbeef. */
+ movl $0xbadbeef, %ebx
+ movl $0xbadbeef, %esi
+ movq %rdi, saved_rdi(%rip)
+ movq %rsi, saved_rsi(%rip)
+ call *tls_var1@TLSCALL(%RAX_LP)
+ /* Check if _dl_tlsdesc_dynamic preserves %rdi, %rsi and %rbx. */
+ cmpq saved_rdi(%rip), %rdi
+ jne L(hlt)
+ cmpq saved_rsi(%rip), %rsi
+ jne L(hlt)
+ cmpl $0xbadbeef, %ebx
+ jne L(hlt)
+ add %fs:0, %RAX_LP
+ movups %xmm0, 32(%RAX_LP)
+ movdqu 16(%RDI_LP), %xmm1
+ mov %RAX_LP, %RBX_LP
+ movups %xmm1, 48(%RAX_LP)
+ lea 32(%RBX_LP), %RAX_LP
+ pop %rbx
+ leave
+ cfi_def_cfa (7, 8)
+ ret
+L(hlt):
+ hlt
+ cfi_endproc
+ .size apply_tls, .-apply_tls
+ .hidden tls_var1
+ .globl tls_var1
+ .section .tbss,"awT",@nobits
+ .align 16
+ .type tls_var1, @object
+ .size tls_var1, 3200
+tls_var1:
+ .zero 3200
+ .local saved_rdi
+ .comm saved_rdi,8,8
+ .local saved_rsi
+ .comm saved_rsi,8,8
+ .section .note.GNU-stack,"",@progbits
status=$?
if test $status -eq 77; then
exit 77
-elif test $status == 139; then
+elif test $status -eq 139; then
exit 0
else
exit 1
status=$?
if test $status -eq 77; then
exit 77
-elif test $status == 139; then
+elif test $status -eq 139; then
exit 0
else
exit 1
status=$?
if test $status -eq 77; then
exit 77
-elif test $status == 139; then
+elif test $status -eq 139; then
exit 0
else
exit 1
__BEGIN_DECLS
/* Message queue control operation. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf) __THROW;
#else
# ifdef __REDIRECT_NTH
__BEGIN_DECLS
/* Semaphore control operation. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int semctl (int __semid, int __semnum, int __cmd, ...) __THROW;
#else
# ifdef __REDIRECT_NTH
#ifdef __USE_GNU
/* Operate on semaphore with timeout. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int semtimedop (int __semid, struct sembuf *__sops, size_t __nsops,
const struct timespec *__timeout) __THROW;
# else
facility. The definition is found in XPG4.2. */
/* Shared memory control operation. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf) __THROW;
#else
# ifdef __REDIRECT_NTH
has nanoseconds instead of microseconds. */
struct timespec
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
__time64_t tv_sec; /* Seconds. */
#else
__time_t tv_sec; /* Seconds. */
#endif
#if __WORDSIZE == 64 \
|| (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64) \
- || (__TIMESIZE == 32 && !defined __USE_TIME_BITS64)
+ || (__TIMESIZE == 32 && !defined __USE_TIME64_REDIRECTS)
__syscall_slong_t tv_nsec; /* Nanoseconds. */
#else
# if __BYTE_ORDER == __BIG_ENDIAN
microsecond but also has a range of years. */
struct timeval
{
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
__time64_t tv_sec; /* Seconds. */
__suseconds64_t tv_usec; /* Microseconds. */
#else
#include <bits/types.h>
/* Returned by `time'. */
-#ifdef __USE_TIME_BITS64
+#ifdef __USE_TIME64_REDIRECTS
typedef __time64_t time_t;
#else
typedef __time_t time_t;
use localtime etc. instead.
This function itself is semi-obsolete;
most callers should use time or clock_gettime instead. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern int gettimeofday (struct timeval *__restrict __tv,
void *__restrict __tz) __THROW __nonnull ((1));
#else
#endif
#ifdef __USE_MISC
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Set the current time of day and timezone information.
This call is restricted to the super-user.
Setting the timezone in this way is obsolete, but we don't yet
typedef int __itimer_which_t;
#endif
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
/* Set *VALUE to the current setting of timer WHICH.
Return 0 on success, -1 on errors. */
extern int getitimer (__itimer_which_t __which,
#endif
#ifdef __USE_MISC
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Same as `utimes', but does not follow symbolic links. */
extern int lutimes (const char *__file, const struct timeval __tvp[2])
__THROW __nonnull ((1));
#endif
#ifdef __USE_GNU
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Change the access time of FILE relative to FD to TVP[0] and the
modification time of FILE to TVP[1]. If TVP is a null pointer, use
the current time instead. Returns 0 on success, -1 on errors. */
The result / CLOCKS_PER_SEC is program time in seconds. */
extern clock_t clock (void) __THROW;
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
/* Return the current time and put it in *TIMER if TIMER is not NULL. */
extern time_t time (time_t *__timer) __THROW;
#endif
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
/* Return the `struct tm' representation of *TIMER
in Universal Coordinated Time (aka Greenwich Mean Time). */
extern struct tm *gmtime (const time_t *__timer) __THROW;
#if defined __USE_POSIX || __GLIBC_USE (ISOC2X)
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Return the `struct tm' representation of *TIMER in UTC,
using *TP to store the result. */
extern struct tm *gmtime_r (const time_t *__restrict __timer,
extern char *asctime (const struct tm *__tp) __THROW;
/* Equivalent to `asctime (localtime (timer))'. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern char *ctime (const time_t *__timer) __THROW;
#else
# ifdef __REDIRECT_NTH
char *__restrict __buf) __THROW;
/* Equivalent to `asctime_r (localtime_r (timer, *TMP*), buf)'. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
extern char *ctime_r (const time_t *__restrict __timer,
char *__restrict __buf) __THROW;
#else
#if defined __USE_MISC || __GLIBC_USE (ISOC2X)
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Like `mktime', but for TP represents Universal Time, not local time. */
extern time_t timegm (struct tm *__tp) __THROW;
# else
/* Miscellaneous functions many Unices inherited from the public domain
localtime package. These are included only for compatibility. */
-#ifndef __USE_TIME_BITS64
+#ifndef __USE_TIME64_REDIRECTS
/* Another name for `mktime'. */
extern time_t timelocal (struct tm *__tp) __THROW;
#else
#ifdef __USE_POSIX199309
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Pause execution for a number of nanoseconds.
This function is a cancellation point and therefore not marked with
This function is a cancellation point and therefore not marked with
__THROW. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int clock_nanosleep (clockid_t __clock_id, int __flags,
const struct timespec *__req,
struct timespec *__rem);
extern int timer_delete (timer_t __timerid) __THROW;
/* Set timer TIMERID to VALUE, returning old value in OVALUE. */
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
extern int timer_settime (timer_t __timerid, int __flags,
const struct itimerspec *__restrict __value,
struct itimerspec *__restrict __ovalue) __THROW;
#ifdef __USE_ISOC11
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Set TS to calendar time based in time base BASE. */
extern int timespec_get (struct timespec *__ts, int __base)
__THROW __nonnull ((1));
#if __GLIBC_USE (ISOC2X)
-# ifndef __USE_TIME_BITS64
+# ifndef __USE_TIME64_REDIRECTS
/* Set TS to resolution of time base BASE. */
extern int timespec_getres (struct timespec *__ts, int __base)
__THROW;
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 2.1 of the License.
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 2.1 of the License.
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of