import glibc-2.28-127.el8

This commit is contained in:
CentOS Sources 2020-11-03 06:44:24 -05:00 committed by Andrew Lukoshko
parent 88b287be24
commit d24c9cf076
91 changed files with 17562 additions and 3 deletions

View File

@ -0,0 +1,176 @@
commit a803367bab167f5ec4fde1f0d0ec447707c29520
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Feb 14 20:55:39 2020 +0100
powerpc64: Add memory protection key support [BZ #23202]
The 32-bit protection key behavior is somewhat unclear on 32-bit powerpc,
so this change is restricted to the 64-bit variants.
Flag translation is needed because of hardware differences between the
POWER implementation (read and write flags) and the Intel implementation
(write and read+write flags).
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
new file mode 100644
index 0000000000000000..623b073d5a585d51
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
@@ -0,0 +1,55 @@
+/* Helper functions for manipulating memory protection keys, for powerpc64.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ARCH_PKEY_H
+#define _ARCH_PKEY_H
+
+/* Read and write access bits in the AMR register. Needs to be
+ translated from and to PKEY_DISABLE_* flags. */
+#define PKEY_AMR_READ 1UL
+#define PKEY_AMR_WRITE 2UL
+
+/* Return the value of the AMR register. */
+static inline unsigned long int
+pkey_read (void)
+{
+ unsigned long int result;
+ __asm__ volatile ("mfspr %0, 13" : "=r" (result));
+ return result;
+}
+
+/* Overwrite the AMR register with VALUE. */
+static inline void
+pkey_write (unsigned long int value)
+{
+ __asm__ volatile ("mtspr 13, %0" : : "r" (value));
+}
+
+/* Number of the largest supported key. This depends on the width of
+ the AMR register. */
+#define PKEY_MAX (sizeof (unsigned long int) * 8 / 2 - 1)
+_Static_assert (PKEY_MAX == 15 || PKEY_MAX == 31, "PKEY_MAX value");
+
+/* Translate key number into AMR index position. */
+static inline int
+pkey_index (int key)
+{
+ return 2 * (PKEY_MAX - key);
+}
+
+#endif /* _ARCH_PKEY_H */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c
new file mode 100644
index 0000000000000000..856ba061b90eabd2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c
@@ -0,0 +1,42 @@
+/* Reading the per-thread memory protection key, powerpc64 version.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <arch-pkey.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+int
+pkey_get (int key)
+{
+ if (key < 0 || key > PKEY_MAX)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+ unsigned int index = pkey_index (key);
+ unsigned long int amr = pkey_read ();
+ unsigned int bits = (amr >> index) & 3;
+
+ /* Translate from AMR values. PKEY_AMR_READ standing alone is not
+ currently representable. */
+ if (bits & PKEY_AMR_READ)
+ return PKEY_DISABLE_ACCESS;
+ else if (bits == PKEY_AMR_WRITE)
+ return PKEY_DISABLE_WRITE;
+ return 0;
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c
new file mode 100644
index 0000000000000000..20b372ee2983abd5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c
@@ -0,0 +1,48 @@
+/* Changing the per-thread memory protection key, powerpc64 version.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <arch-pkey.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+int
+pkey_set (int key, unsigned int rights)
+{
+ if (key < 0 || key > PKEY_MAX || rights > 3)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ /* Translate to AMR bit values. */
+ unsigned long int bits;
+ if (rights & PKEY_DISABLE_ACCESS)
+ /* The PKEY_DISABLE_WRITE bit does not matter. */
+ bits = PKEY_AMR_READ | PKEY_AMR_WRITE;
+ else if (rights == PKEY_DISABLE_WRITE)
+ bits = PKEY_AMR_WRITE;
+ else
+ bits = 0;
+
+ unsigned int index = pkey_index (key);
+ unsigned long int mask = 3UL << index;
+ unsigned long int amr = pkey_read ();
+ amr = (amr & ~mask) | (bits << index);
+ pkey_write (amr);
+ return 0;
+}

View File

@ -0,0 +1,53 @@
commit 8d42bf859a289944749d9f978c076cd318119867
Author: Lucas A. M. Magalhaes <lamm@linux.ibm.com>
Date: Mon Feb 17 09:09:52 2020 -0300
Fix tst-pkey expectations on pkey_get [BZ #23202]
From the GNU C Library manual, the pkey_set can receive a combination of
PKEY_DISABLE_WRITE and PKEY_DISABLE_ACCESS. However PKEY_DISABLE_ACCESS
is more restrictive than PKEY_DISABLE_WRITE and includes its behavior.
The test expects that after setting
(PKEY_DISABLE_WRITE|PKEY_DISABLE_ACCESS) pkey_get should return the
same. This may not be true as PKEY_DISABLE_ACCESS will succeed in
describing the state of the key in this case.
The pkey behavior during signal handling is different between x86 and
POWER. This change make the test compatible with both architectures.
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
diff --git a/sysdeps/unix/sysv/linux/tst-pkey.c b/sysdeps/unix/sysv/linux/tst-pkey.c
index 5f721d4444490945..600b6f0098def773 100644
--- a/sysdeps/unix/sysv/linux/tst-pkey.c
+++ b/sysdeps/unix/sysv/linux/tst-pkey.c
@@ -37,7 +37,7 @@ static pthread_barrier_t barrier;
/* The keys used for testing. These have been allocated with access
rights set based on their array index. */
-enum { key_count = 4 };
+enum { key_count = 3 };
static int keys[key_count];
static volatile int *pages[key_count];
@@ -111,14 +111,16 @@ check_page_access (int page, bool write)
}
static volatile sig_atomic_t sigusr1_handler_ran;
-
-/* Used to check that access is revoked in signal handlers. */
+/* Used to check the behavior in signal handlers. In x86 all access are
+ revoked during signal handling. In PowerPC the key permissions are
+ inherited by the interrupted thread. This test accept both approaches. */
static void
sigusr1_handler (int signum)
{
TEST_COMPARE (signum, SIGUSR1);
for (int i = 0; i < key_count; ++i)
- TEST_COMPARE (pkey_get (keys[i]), PKEY_DISABLE_ACCESS);
+ TEST_VERIFY (pkey_get (keys[i]) == PKEY_DISABLE_ACCESS
+ || pkey_get (keys[i]) == i);
sigusr1_handler_ran = 1;
}

View File

@ -0,0 +1,46 @@
commit 70ba28f7ab2923d4e36ffc9d5d2e32357353b25c
Author: Lucas A. M. Magalhaes <lamm@linux.ibm.com>
Date: Thu Jan 16 10:39:12 2020 -0300
Fix tst-pkey.c pkey_alloc return checks and manual
This test was failing in some powerpc systems as it was not checking
for ENOSPC return.
As said on the Linux man-pages and can be observed by the implementation
at mm/mprotect.c in the Linux Kernel source. The syscall pkey_alloc can
return EINVAL or ENOSPC. ENOSPC will indicate either that all keys are
in use or that the kernel does not support pkeys.
Reviewed-by: Gabriel F. T. Gomes <gabriel@inconstante.net.br>
diff --git a/manual/memory.texi b/manual/memory.texi
index a1435aad1acd3239..4731a38bcc5701e0 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -3289,6 +3289,10 @@ in which memory protection keys are disabled.
@item ENOSPC
All available protection keys already have been allocated.
+
+The system does not implement memory protection keys or runs in a mode
+in which memory protection keys are disabled.
+
@end table
@end deftypefun
diff --git a/sysdeps/unix/sysv/linux/tst-pkey.c b/sysdeps/unix/sysv/linux/tst-pkey.c
index 600b6f0098def773..40d7e9f24dec3e57 100644
--- a/sysdeps/unix/sysv/linux/tst-pkey.c
+++ b/sysdeps/unix/sysv/linux/tst-pkey.c
@@ -199,6 +199,10 @@ do_test (void)
if (errno == EINVAL)
FAIL_UNSUPPORTED
("CPU does not support memory protection keys: %m");
+ if (errno == ENOSPC)
+ FAIL_UNSUPPORTED
+ ("no keys available or kernel does not support memory"
+ " protection keys");
FAIL_EXIT1 ("pkey_alloc: %m");
}
TEST_COMPARE (pkey_get (keys[0]), 0);

View File

@ -0,0 +1,36 @@
commit e627106266ad8785457fadbf5bf67ed604d2a353
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon May 11 11:20:02 2020 +0200
POWER: Add context-synchronizing instructions to pkey_write [BZ #25954]
Sandipan Das reported that,
"The Power ISA mandates that all writes to the Authority
Mask Register (AMR) must always be preceded as well as
succeeded by a context-synchronizing instruction. This
applies to both the privileged and unprivileged variants
of the Move To AMR instruction.
This [requirement] is from Table 6 of Chapter 11 in page 1134 of Power
ISA 3.0B. The document can be found here:
<https://ibm.ent.box.com/s/1hzcwkwf8rbju5h9iyf44wm94amnlcrv>
"
See this kernel patch submission:
<https://lore.kernel.org/linuxppc-dev/5f65cf37be993760de8112a88da194e3ccbb2bf8.1588959697.git.sandipan@linux.ibm.com/>
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
index 623b073d5a585d51..25d080c9a6f30942 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
@@ -37,7 +37,7 @@ pkey_read (void)
static inline void
pkey_write (unsigned long int value)
{
- __asm__ volatile ("mtspr 13, %0" : : "r" (value));
+ __asm__ volatile ("isync; mtspr 13, %0; isync" : : "r" (value));
}
/* Number of the largest supported key. This depends on the width of

View File

@ -0,0 +1,151 @@
From: Ian Kent <ikent@redhat.com>
Date: Mon, 2 Sep 2019 11:26:14 +0000 (+0200)
Subject: Use autofs "ignore" mount hint in getmntent_r/getmntent
X-Git-Tag: changelog-ends-here~75
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=08b7e9988272113ca5640cf5e115ea51449fb392
Use autofs "ignore" mount hint in getmntent_r/getmntent
Historically autofs mounts were not included in mount table
listings. This is the case in other SysV autofs implementations
and was also the case with Linux autofs.
But now that /etc/mtab is a symlink to the proc filesystem
mount table the autofs mount entries appear in the mount table
on Linux.
Prior to the symlinking of /etc/mtab mount table it was
sufficient to call mount(2) and simply not update /etc/mtab
to exclude autofs mounts from mount listings.
Also, with the symlinking of /etc/mtab we have seen a shift in
usage toward using the proc mount tables directly.
But the autofs mount entries need to be retained when coming
from the proc file system for applications that need them
(largely autofs file system users themselves) so filtering out
these entries within the kernel itself can't be done. So it
needs be done in user space.
There are three reasons to omit the autofs mount entries.
One is that certain types of auto-mounts have an autofs mount
for every entry in their autofs mount map and these maps can
be quite large. This leads to mount table listings containing
a lot of unnecessary entries.
Also, this change in behaviour between autofs implementations
can cause problems for applications that use getmntent(3) in
other OS implementations as well as Linux.
Lastly, there's very little that user space can do with autofs
mount entries since this must be left to the autofs mount owner,
typically the automount daemon. But it can also lead to attempts
to access automount managed paths resulting mounts being triggered
when they aren't needed or mounts staying mounted for much longer
thay they need be. While the point of this change ins't to help
with these problems (and it can be quite a problem) it may be
a welcome side effect.
So the Linux autofs file system has been modified to accept a
pseudo mount option of "ignore" (as is used in other OS
implementations) so that user space can use this as a hint to
skip autofs entries on reading the mount table.
The Linux autofs automount daemon used getmntent(3) itself and
has been modified to use the proc file system directly so that
it can "ignore" mount option.
The use of this mount option is opt-in and a configuration
option has been added which defaults to not use this option
so if there are applications that need these entries, other
than autofs itself, they can be retained. Also, since this
filtering is based on an added mount option earlier versions
of Linux autofs iand other autofs file system users will not
use the option and so won't be affected by the change.
---
diff --git a/misc/mntent_r.c b/misc/mntent_r.c
index 5d88c45c6f..d90e8d7087 100644
--- a/misc/mntent_r.c
+++ b/misc/mntent_r.c
@@ -18,6 +18,7 @@
#include <alloca.h>
#include <mntent.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <string.h>
@@ -112,26 +113,18 @@ decode_name (char *buf)
return buf;
}
-
-/* Read one mount table entry from STREAM. Returns a pointer to storage
- reused on the next call, or null for EOF or error (use feof/ferror to
- check). */
-struct mntent *
-__getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
+static bool
+get_mnt_entry (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
{
char *cp;
char *head;
- flockfile (stream);
do
{
char *end_ptr;
if (__fgets_unlocked (buffer, bufsiz, stream) == NULL)
- {
- funlockfile (stream);
- return NULL;
- }
+ return false;
end_ptr = strchr (buffer, '\n');
if (end_ptr != NULL) /* chop newline */
@@ -181,9 +174,40 @@ __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
case 2:
break;
}
+
+ return true;
+}
+
+/* Read one mount table entry from STREAM. Returns a pointer to storage
+ reused on the next call, or null for EOF or error (use feof/ferror to
+ check). */
+struct mntent *
+__getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
+{
+ struct mntent *result;
+
+ flockfile (stream);
+ while (true)
+ if (get_mnt_entry (stream, mp, buffer, bufsiz))
+ {
+ /* If the file system is autofs look for a mount option hint
+ ("ignore") to skip the entry. */
+ if (strcmp (mp->mnt_type, "autofs") == 0 && __hasmntopt (mp, "ignore"))
+ memset (mp, 0, sizeof (*mp));
+ else
+ {
+ result = mp;
+ break;
+ }
+ }
+ else
+ {
+ result = NULL;
+ break;
+ }
funlockfile (stream);
- return mp;
+ return result;
}
libc_hidden_def (__getmntent_r)
weak_alias (__getmntent_r, getmntent_r)

View File

@ -0,0 +1,169 @@
From: Florian Weimer <fweimer@redhat.com>
Date: Mon, 2 Sep 2019 10:40:38 +0000 (+0200)
Subject: Add misc/tst-mntent-autofs, testing autofs "ignore" filtering
X-Git-Tag: changelog-ends-here~74
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=9a1e7257a4292d3aea45c8317df3956f4331d8ce
Add misc/tst-mntent-autofs, testing autofs "ignore" filtering
---
diff -rup a/misc/Makefile b/misc/Makefile
--- a/misc/Makefile 2020-03-25 18:30:42.275895917 -0400
+++ b/misc/Makefile 2020-03-25 18:37:55.527738814 -0400
@@ -84,7 +84,8 @@ tests := tst-dirname tst-tsearch tst-fds
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
tst-mntent-blank-corrupt tst-mntent-blank-passno bug18240 \
tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
- tst-preadvwritev2 tst-preadvwritev64v2
+ tst-preadvwritev2 tst-preadvwritev64v2 \
+ tst-mntent-autofs
# Tests which need libdl.
ifeq (yes,$(build-shared))
diff --git a/misc/tst-mntent-autofs.c b/misc/tst-mntent-autofs.c
new file mode 100644
index 0000000000..bf4d4e73b4
--- /dev/null
+++ b/misc/tst-mntent-autofs.c
@@ -0,0 +1,141 @@
+/* Test autofs "ignore" filtering for getment_r.
+ Copyright (C) 2019 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 <array_length.h>
+#include <errno.h>
+#include <mntent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+
+struct test_case
+{
+ const char *line;
+ struct
+ {
+ /* Like struct mntent, but with const pointers. */
+ const char *mnt_fsname;
+ const char *mnt_dir;
+ const char *mnt_type;
+ const char *mnt_opts;
+ int mnt_freq;
+ int mnt_passno;
+ } expected;
+};
+
+static struct test_case test_cases[] =
+ {
+ { "/etc/auto.direct /mnt/auto/1 autofs defaults 0 0",
+ { "/etc/auto.direct", "/mnt/auto/1", "autofs", "defaults", 0, 0 } },
+
+ /* These entries are filtered out. */
+ { "/etc/auto.2 /mnt/auto/2 autofs ignore 0 0", { NULL, } },
+ { "/etc/auto.3 /mnt/auto/3 autofs ignore,other 1 2", { NULL, } },
+ { "/etc/auto.4 /mnt/auto/4 autofs other,ignore 3 4", { NULL, } },
+ { "/etc/auto.5 /mnt/auto/5 autofs opt1,ignore,opt2 5 6", { NULL, } },
+
+ /* Dummy entry to make the desynchronization more obvious. */
+ { "/dev/sda1 / xfs defaults 0 0",
+ { "/dev/sda1", "/", "xfs", "defaults", 0, 0 } },
+
+ /* These are not filtered because the file system is not autofs. */
+ { "/etc/auto.direct /mnt/auto/6 autofs1 ignore 0 0",
+ { "/etc/auto.direct", "/mnt/auto/6", "autofs1", "ignore", 0, 0 } },
+ { "/etc/auto.direct /mnt/auto/7 autofs1 ignore,other 0 0",
+ { "/etc/auto.direct", "/mnt/auto/7", "autofs1", "ignore,other", 0, 0 } },
+ { "/etc/auto.direct /mnt/auto/8 autofs1 other,ignore 0 0",
+ { "/etc/auto.direct", "/mnt/auto/8", "autofs1", "other,ignore", 0, 0 } },
+ { "/etc/auto.direct /mnt/auto/9 autofs1 opt1,ignore,opt2 0 0",
+ { "/etc/auto.direct", "/mnt/auto/9", "autofs1", "opt1,ignore,opt2", } },
+
+ /* These are not filtered because the string "ignore" is not an
+ option name. */
+ { "/etc/auto.direct /mnt/auto/10 autofs noignore 1 2",
+ { "/etc/auto.direct", "/mnt/auto/10", "autofs", "noignore", 1, 2 } },
+ { "/etc/auto.direct /mnt/auto/11 autofs noignore,other 0 0",
+ { "/etc/auto.direct", "/mnt/auto/11", "autofs", "noignore,other", } },
+ { "/etc/auto.direct /mnt/auto/12 autofs other,noignore 0 0",
+ { "/etc/auto.direct", "/mnt/auto/12", "autofs", "other,noignore", } },
+ { "/etc/auto.direct /mnt/auto/13 autofs errors=ignore 0 0",
+ { "/etc/auto.direct", "/mnt/auto/13", "autofs", "errors=ignore", } },
+ { "/etc/auto.direct /mnt/auto/14 autofs errors=ignore,other 0 0",
+ { "/etc/auto.direct", "/mnt/auto/14", "autofs",
+ "errors=ignore,other", } },
+ { "/etc/auto.direct /mnt/auto/15 autofs other,errors=ignore 0 0",
+ { "/etc/auto.direct", "/mnt/auto/15", "autofs",
+ "other,errors=ignore", } },
+
+ /* These are not filtered because the string is escaped. '\151'
+ is 'i', but it is not actually decoded by the parser. */
+ { "/etc/auto.\\151gnore /mnt/auto/16 autofs \\151gnore 0 0",
+ { "/etc/auto.\\151gnore", "/mnt/auto/16", "autofs",
+ "\\151gnore", } },
+ };
+
+static int
+do_test (void)
+{
+ char *path;
+ xclose (create_temp_file ("tst-mntent-autofs-", &path));
+
+ /* Write the test file. */
+ FILE *fp = xfopen (path, "w");
+ for (size_t i = 0; i < array_length (test_cases); ++i)
+ fprintf (fp, "%s\n", test_cases[i].line);
+ xfclose (fp);
+
+ /* Open the test file again, this time for parsing. */
+ fp = setmntent (path, "r");
+ TEST_VERIFY_EXIT (fp != NULL);
+ char buffer[512];
+ struct mntent me;
+
+ for (size_t i = 0; i < array_length (test_cases); ++i)
+ {
+ if (test_cases[i].expected.mnt_type == NULL)
+ continue;
+
+ memset (buffer, 0xcc, sizeof (buffer));
+ memset (&me, 0xcc, sizeof (me));
+ struct mntent *pme = getmntent_r (fp, &me, buffer, sizeof (buffer));
+ TEST_VERIFY_EXIT (pme != NULL);
+ TEST_VERIFY (pme == &me);
+ TEST_COMPARE_STRING (test_cases[i].expected.mnt_fsname, me.mnt_fsname);
+ TEST_COMPARE_STRING (test_cases[i].expected.mnt_dir, me.mnt_dir);
+ TEST_COMPARE_STRING (test_cases[i].expected.mnt_type, me.mnt_type);
+ TEST_COMPARE_STRING (test_cases[i].expected.mnt_opts, me.mnt_opts);
+ TEST_COMPARE (test_cases[i].expected.mnt_freq, me.mnt_freq);
+ TEST_COMPARE (test_cases[i].expected.mnt_passno, me.mnt_passno);
+ }
+
+ TEST_VERIFY (getmntent_r (fp, &me, buffer, sizeof (buffer)) == NULL);
+
+ TEST_COMPARE (feof (fp), 1);
+ TEST_COMPARE (ferror (fp), 0);
+ errno = 0;
+ TEST_COMPARE (endmntent (fp), 1);
+ TEST_COMPARE (errno, 0);
+ free (path);
+ return 0;
+}
+
+#include <support/test-driver.c>

View File

@ -0,0 +1,18 @@
commit 27cec9aed97447dff887a88f4241604fffd8c525
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Jul 2 16:45:52 2019 +0200
malloc: Add nptl, htl dependency for the subdirectory [BZ #24757]
memusagestat may indirectly link against libpthread. The built
libpthread should be used, but that is only possible if it has been
built before the malloc programs.
diff --git a/malloc/Depend b/malloc/Depend
index 910c6d915211870f..f5e248047c4c46dd 100644
--- a/malloc/Depend
+++ b/malloc/Depend
@@ -1 +1,3 @@
dlfcn
+nptl
+htl

View File

@ -0,0 +1,996 @@
commit 41d6f74e6cb6a92ab428c11ee1e408b2a16aa1b0
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Jul 2 15:12:20 2019 +0200
nptl: Remove vfork IFUNC-based forwarder from libpthread [BZ #20188]
With commit f0b2132b35248c1f4a80f62a2c38cddcc802aa8c ("ld.so:
Support moving versioned symbols between sonames [BZ #24741]"), the
dynamic linker will find the definition of vfork in libc and binds
a vfork reference to that symbol, even if the soname in the version
reference says that the symbol should be located in libpthread.
As a result, the forwarder (whether it's IFUNC-based or a duplicate
of the libc implementation) is no longer necessary.
On older architectures, a placeholder symbol is required, to make sure
that the GLIBC_2.1.2 symbol version does not go away, or is turned in
to a weak symbol definition by the link editor. (The symbol version
needs to preserved so that the symbol coverage check in
elf/dl-version.c does not fail for old binaries.)
mips32 is an outlier: It defined __vfork@@GLIBC_2.2, but the
baseline is GLIBC_2.0. Since there are other @@GLIBC_2.2 symbols,
the placeholder symbol is not needed there.
Conflicts:
nptl/Makefile
(Missing lll_timedwait_tid removal, missing pthread_mutex_conf.)
nptl/pt-vfork.c
sysdeps/unix/sysv/linux/aarch64/pt-vfork.c
sysdeps/unix/sysv/linux/alpha/pt-vfork.S
sysdeps/unix/sysv/linux/hppa/pt-vfork.S
sysdeps/unix/sysv/linux/ia64/pt-vfork.S
sysdeps/unix/sysv/linux/microblaze/pt-vfork.S
(Removal after copyright year change upstream.)
diff --git a/nptl/Makefile b/nptl/Makefile
index 071c53866d14d2fe..447dce0590295c9c 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -121,7 +121,7 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \
cancellation \
lowlevellock \
lll_timedlock_wait lll_timedwait_tid \
- pt-fork pt-vfork pt-fcntl \
+ pt-fork pt-fcntl \
$(pthread-compat-wrappers) \
pt-raise pt-system \
flockfile ftrylockfile funlockfile \
@@ -145,7 +145,8 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \
mtx_destroy mtx_init mtx_lock mtx_timedlock \
mtx_trylock mtx_unlock call_once cnd_broadcast \
cnd_destroy cnd_init cnd_signal cnd_timedwait cnd_wait \
- tss_create tss_delete tss_get tss_set
+ tss_create tss_delete tss_get tss_set \
+ libpthread-compat
# pthread_setuid pthread_seteuid pthread_setreuid \
# pthread_setresuid \
# pthread_setgid pthread_setegid pthread_setregid \
diff --git a/nptl/Versions b/nptl/Versions
index e7f691da7a15e9c3..6007fd03e7ed117c 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -36,7 +36,6 @@ libc {
__libc_alloca_cutoff;
# Internal libc interface to libpthread
__libc_dl_error_tsd;
- __libc_vfork;
__libc_pthread_init;
__libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
__libc_allocate_rtsig_private;
@@ -98,7 +97,7 @@ libpthread {
sem_destroy; sem_getvalue; sem_init; sem_post; sem_trywait; sem_wait;
# Special fork handling.
- fork; __fork; vfork;
+ fork; __fork;
# Cancellation points.
close; __close; fcntl; __fcntl; read; __read; write; __write; accept;
@@ -152,7 +151,7 @@ libpthread {
}
GLIBC_2.1.2 {
- __vfork;
+ __libpthread_version_placeholder;
}
GLIBC_2.2 {
diff --git a/nptl/libpthread-compat.c b/nptl/libpthread-compat.c
new file mode 100644
index 0000000000000000..ea29e9f47b698a25
--- /dev/null
+++ b/nptl/libpthread-compat.c
@@ -0,0 +1,37 @@
+/* Placeholder definitions to pull in removed symbol versions.
+ Copyright (C) 2019 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 <shlib-compat.h>
+
+/* This is an unused compatibility symbol definition, to prevent ld
+ from creating a weak version definition for GLIBC_2.1.2. (__vfork
+ used to be defined at that version, but it is now provided by libc,
+ and there are no versions left in libpthread for that symbol
+ version.) If the ABI baseline for glibc is the GLIBC_2.2 symbol
+ version or later, the placeholder symbol is not needed because
+ there are plenty of other symbols which populate those later
+ versions. */
+#if (SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_2))
+void
+attribute_compat_text_section
+__libpthread_version_placeholder (void)
+{
+}
+compat_symbol (libpthread, __libpthread_version_placeholder,
+ __libpthread_version_placeholder, GLIBC_2_1_2);
+#endif
diff --git a/nptl/pt-vfork.c b/nptl/pt-vfork.c
deleted file mode 100644
index 2f890d3f3070d0e2..0000000000000000
--- a/nptl/pt-vfork.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread.
- Copyright (C) 2014-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <unistd.h>
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so; so we define them using IFUNC to
- redirect to the libc function. */
-
-/* Note! If the architecture doesn't support IFUNC, then we need an
- alternate target-specific mechanism to implement this. So we just
- assume IFUNC here and require that the target override this file
- if necessary.
-
- If the architecture can assume all supported versions of gcc will
- produce a tail-call to __libc_vfork, consider including the version
- in sysdeps/unix/sysv/linux/aarch64/pt-vfork.c. */
-
-#if !HAVE_IFUNC
-# error "must write pt-vfork for this machine or get IFUNC support"
-#endif
-
-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-extern __typeof (vfork) __libc_vfork; /* Defined in libc. */
-
-# undef INIT_ARCH
-# define INIT_ARCH()
-# define DEFINE_VFORK(name) libc_ifunc (name, &__libc_vfork)
-
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-extern __typeof(vfork) vfork_ifunc;
-DEFINE_VFORK (vfork_ifunc)
-compat_symbol (libpthread, vfork_ifunc, vfork, GLIBC_2_0);
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-extern __typeof(vfork) __vfork_ifunc;
-DEFINE_VFORK (__vfork_ifunc)
-compat_symbol (libpthread, __vfork_ifunc, __vfork, GLIBC_2_1_2);
-#endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
index 9a9e4cee85b18a35..6945b7cbe4c2bde8 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
@@ -45,7 +45,6 @@ GLIBC_2.17 __read F
GLIBC_2.17 __res_state F
GLIBC_2.17 __send F
GLIBC_2.17 __sigaction F
-GLIBC_2.17 __vfork F
GLIBC_2.17 __wait F
GLIBC_2.17 __write F
GLIBC_2.17 _pthread_cleanup_pop F
@@ -216,7 +215,6 @@ GLIBC_2.17 siglongjmp F
GLIBC_2.17 sigwait F
GLIBC_2.17 system F
GLIBC_2.17 tcdrain F
-GLIBC_2.17 vfork F
GLIBC_2.17 wait F
GLIBC_2.17 waitpid F
GLIBC_2.17 write F
diff --git a/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c b/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c
deleted file mode 100644
index 2b277f25ec200be2..0000000000000000
--- a/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread.
- Copyright (C) 2014-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so. */
-
-#if HAVE_IFUNC
-# include <nptl/pt-vfork.c>
-#elif (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-/* Thankfully, on AArch64 we can rely on the compiler generating
- a tail call here. */
-
-extern void __libc_vfork (void);
-
-void
-vfork_compat (void)
-{
- __libc_vfork ();
-}
-
-# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0);
-# endif
-
-# if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-strong_alias (vfork_compat, vfork_compat2)
-compat_symbol (libpthread, vfork_compat2, __vfork, GLIBC_2_1_2);
-# endif
-
-#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
index b413007ccbd2b7b3..2d9b958efa99feb8 100644
--- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F
GLIBC_2.0 sigwait F
GLIBC_2.0 system F
GLIBC_2.0 tcdrain F
-GLIBC_2.0 vfork F
GLIBC_2.0 wait F
GLIBC_2.0 waitpid F
GLIBC_2.0 write F
@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F
GLIBC_2.1.1 sem_close F
GLIBC_2.1.1 sem_open F
GLIBC_2.1.1 sem_unlink F
-GLIBC_2.1.2 __vfork F
+GLIBC_2.1.2 __libpthread_version_placeholder F
GLIBC_2.11 pthread_sigqueue F
GLIBC_2.12 pthread_getname_np F
GLIBC_2.12 pthread_mutex_consistent F
diff --git a/sysdeps/unix/sysv/linux/alpha/pt-vfork.S b/sysdeps/unix/sysv/linux/alpha/pt-vfork.S
deleted file mode 100644
index 7ecaa78dd0eda2fe..0000000000000000
--- a/sysdeps/unix/sysv/linux/alpha/pt-vfork.S
+++ /dev/null
@@ -1,43 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread.
- Copyright (C) 2014-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so. */
-
-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-#include <vfork.S>
-
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-compat_symbol (libpthread, __libc_vfork, vfork, GLIBC_2_0);
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-strong_alias (__libc_vfork, __vfork_compat)
-compat_symbol (libpthread, __vfork_compat, __vfork, GLIBC_2_1_2);
-#endif
diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
index af82a4c632988185..ee3d0290d01f184e 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -74,7 +74,6 @@ GLIBC_2.4 __read F
GLIBC_2.4 __res_state F
GLIBC_2.4 __send F
GLIBC_2.4 __sigaction F
-GLIBC_2.4 __vfork F
GLIBC_2.4 __wait F
GLIBC_2.4 __write F
GLIBC_2.4 _pthread_cleanup_pop F
@@ -239,7 +238,6 @@ GLIBC_2.4 siglongjmp F
GLIBC_2.4 sigwait F
GLIBC_2.4 system F
GLIBC_2.4 tcdrain F
-GLIBC_2.4 vfork F
GLIBC_2.4 wait F
GLIBC_2.4 waitpid F
GLIBC_2.4 write F
diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
index bcba07f57558174f..e9b3be6ac8e8f367 100644
--- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
@@ -46,7 +46,6 @@ GLIBC_2.2 __read F
GLIBC_2.2 __res_state F
GLIBC_2.2 __send F
GLIBC_2.2 __sigaction F
-GLIBC_2.2 __vfork F
GLIBC_2.2 __wait F
GLIBC_2.2 __write F
GLIBC_2.2 _pthread_cleanup_pop F
@@ -192,7 +191,6 @@ GLIBC_2.2 siglongjmp F
GLIBC_2.2 sigwait F
GLIBC_2.2 system F
GLIBC_2.2 tcdrain F
-GLIBC_2.2 vfork F
GLIBC_2.2 wait F
GLIBC_2.2 waitpid F
GLIBC_2.2 write F
diff --git a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data
index 5f3475de191778f6..867413f0c54d3d71 100644
--- a/sysdeps/unix/sysv/linux/hppa/localplt.data
+++ b/sysdeps/unix/sysv/linux/hppa/localplt.data
@@ -10,7 +10,6 @@ libc.so: __sigsetjmp
libc.so: _IO_funlockfile
libc.so: __errno_location
libm.so: matherr
-libpthread.so: __errno_location
# The main malloc is interposed into the dynamic linker, for
# allocations after the initial link (when dlopen is used).
ld.so: malloc
diff --git a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S b/sysdeps/unix/sysv/linux/hppa/pt-vfork.S
deleted file mode 100644
index 45f7620d90cb5b8f..0000000000000000
--- a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Copyright (C) 2005-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library. If not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#define _ERRNO_H 1
-#include <bits/errno.h>
-#include <tcb-offsets.h>
-
-/* Clone the calling process, but without copying the whole address space.
- The calling process is suspended until the new process exits or is
- replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
- and the process ID of the new process to the old process. */
-
-.Lthread_start: ASM_LINE_SEP
-
- /* r26, r25, r24, r23 are free since vfork has no arguments */
-ENTRY(__vfork)
- /* We must not create a frame. When the child unwinds to call
- exec it will clobber the same frame that the parent
- needs to unwind. */
-
- /* Save the PIC register. */
-#ifdef PIC
- copy %r19, %r25 /* parent */
-#endif
-
- /* Syscall saves and restores all register states */
- ble 0x100(%sr2,%r0)
- ldi __NR_vfork,%r20
-
- /* Check for error */
- ldi -4096,%r1
- comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */
- b,n .Lerror
-
- /* Return, and DO NOT restore rp. The child may have called
- functions that updated the frame's rp. This works because
- the kernel ensures rp is preserved across the vfork
- syscall. */
- bv,n %r0(%rp)
-
-.Lerror:
- /* Now we need a stack to call a function. We are assured
- that there is no child now, so it's safe to create
- a frame. */
- stw %rp, -20(%sp)
- .cfi_offset 2, -20
- stwm %r3, 64(%sp)
- .cfi_def_cfa_offset -64
- .cfi_offset 3, 0
- stw %sp, -4(%sp)
-
- sub %r0,%ret0,%r3
- SYSCALL_ERROR_HANDLER
- /* Restore the PIC register (in delay slot) on error */
-#ifdef PIC
- copy %r25, %r19 /* parent */
-#else
- nop
-#endif
- /* Write syscall return into errno location */
- stw %r3, 0(%ret0)
- ldw -84(%sp), %rp
- bv %r0(%rp)
- ldwm -64(%sp), %r3
-PSEUDO_END (__vfork)
-libc_hidden_def (__vfork)
-weak_alias (__vfork, vfork)
diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
index bece86d24624ea26..7199aae573649f49 100644
--- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F
GLIBC_2.0 sigwait F
GLIBC_2.0 system F
GLIBC_2.0 tcdrain F
-GLIBC_2.0 vfork F
GLIBC_2.0 wait F
GLIBC_2.0 waitpid F
GLIBC_2.0 write F
@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F
GLIBC_2.1.1 sem_close F
GLIBC_2.1.1 sem_open F
GLIBC_2.1.1 sem_unlink F
-GLIBC_2.1.2 __vfork F
+GLIBC_2.1.2 __libpthread_version_placeholder F
GLIBC_2.11 pthread_sigqueue F
GLIBC_2.12 pthread_getname_np F
GLIBC_2.12 pthread_mutex_consistent F
diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
index ccc94498268a5c74..e8a65642caec7ff1 100644
--- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
@@ -46,7 +46,6 @@ GLIBC_2.2 __read F
GLIBC_2.2 __res_state F
GLIBC_2.2 __send F
GLIBC_2.2 __sigaction F
-GLIBC_2.2 __vfork F
GLIBC_2.2 __wait F
GLIBC_2.2 __write F
GLIBC_2.2 _pthread_cleanup_pop F
@@ -192,7 +191,6 @@ GLIBC_2.2 siglongjmp F
GLIBC_2.2 sigwait F
GLIBC_2.2 system F
GLIBC_2.2 tcdrain F
-GLIBC_2.2 vfork F
GLIBC_2.2 wait F
GLIBC_2.2 waitpid F
GLIBC_2.2 write F
diff --git a/sysdeps/unix/sysv/linux/ia64/pt-vfork.S b/sysdeps/unix/sysv/linux/ia64/pt-vfork.S
deleted file mode 100644
index 61f3e387b455d731..0000000000000000
--- a/sysdeps/unix/sysv/linux/ia64/pt-vfork.S
+++ /dev/null
@@ -1,48 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread. IA64 version.
- Copyright (C) 2014-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so. */
-
-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-LOCAL_LEAF (vfork_compat)
- br __libc_vfork
- ;;
-END (vfork_compat)
-
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-weak_alias (vfork_compat, vfork)
-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0);
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-strong_alias (vfork_compat, __vfork_compat)
-compat_symbol (libpthread, __vfork_compat, __vfork, GLIBC_2_1_2);
-#endif
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
index af82a4c632988185..ee3d0290d01f184e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
@@ -74,7 +74,6 @@ GLIBC_2.4 __read F
GLIBC_2.4 __res_state F
GLIBC_2.4 __send F
GLIBC_2.4 __sigaction F
-GLIBC_2.4 __vfork F
GLIBC_2.4 __wait F
GLIBC_2.4 __write F
GLIBC_2.4 _pthread_cleanup_pop F
@@ -239,7 +238,6 @@ GLIBC_2.4 siglongjmp F
GLIBC_2.4 sigwait F
GLIBC_2.4 system F
GLIBC_2.4 tcdrain F
-GLIBC_2.4 vfork F
GLIBC_2.4 wait F
GLIBC_2.4 waitpid F
GLIBC_2.4 write F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
index bece86d24624ea26..7199aae573649f49 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F
GLIBC_2.0 sigwait F
GLIBC_2.0 system F
GLIBC_2.0 tcdrain F
-GLIBC_2.0 vfork F
GLIBC_2.0 wait F
GLIBC_2.0 waitpid F
GLIBC_2.0 write F
@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F
GLIBC_2.1.1 sem_close F
GLIBC_2.1.1 sem_open F
GLIBC_2.1.1 sem_unlink F
-GLIBC_2.1.2 __vfork F
+GLIBC_2.1.2 __libpthread_version_placeholder F
GLIBC_2.11 pthread_sigqueue F
GLIBC_2.12 pthread_getname_np F
GLIBC_2.12 pthread_mutex_consistent F
diff --git a/sysdeps/unix/sysv/linux/m68k/pt-vfork.c b/sysdeps/unix/sysv/linux/m68k/pt-vfork.c
deleted file mode 100644
index 5fbc6526aa2af493..0000000000000000
--- a/sysdeps/unix/sysv/linux/m68k/pt-vfork.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/aarch64/pt-vfork.c>
diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
index 5067375d237a0c9f..e0fbe6848f7945bd 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
@@ -45,7 +45,6 @@ GLIBC_2.18 __read F
GLIBC_2.18 __res_state F
GLIBC_2.18 __send F
GLIBC_2.18 __sigaction F
-GLIBC_2.18 __vfork F
GLIBC_2.18 __wait F
GLIBC_2.18 __write F
GLIBC_2.18 _pthread_cleanup_pop F
@@ -218,7 +217,6 @@ GLIBC_2.18 siglongjmp F
GLIBC_2.18 sigwait F
GLIBC_2.18 system F
GLIBC_2.18 tcdrain F
-GLIBC_2.18 vfork F
GLIBC_2.18 wait F
GLIBC_2.18 waitpid F
GLIBC_2.18 write F
diff --git a/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S b/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S
deleted file mode 100644
index 74bc1cdf7455f597..0000000000000000
--- a/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S
+++ /dev/null
@@ -1,49 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread.
- Copyright (C) 2014-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so.
-
- As of GCC 7, microblaze can *not* rely on the compiler to generate
- a tail call from this vfork to __libc_vfork. */
-
-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-ENTRY (vfork_compat)
- bri __libc_vfork@PLT
-END (vfork_compat)
-
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0)
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-strong_alias (vfork_compat, vfork_compat2)
-compat_symbol (libpthread, vfork_compat2, __vfork, GLIBC_2_1_2)
-#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
index 02144967c638cdbe..f60b22efb5b5f683 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F
GLIBC_2.0 sigwait F
GLIBC_2.0 system F
GLIBC_2.0 tcdrain F
-GLIBC_2.0 vfork F
GLIBC_2.0 wait F
GLIBC_2.0 waitpid F
GLIBC_2.0 write F
@@ -140,7 +139,6 @@ GLIBC_2.2 __pthread_rwlock_unlock F
GLIBC_2.2 __pthread_rwlock_wrlock F
GLIBC_2.2 __pwrite64 F
GLIBC_2.2 __res_state F
-GLIBC_2.2 __vfork F
GLIBC_2.2 lseek64 F
GLIBC_2.2 open64 F
GLIBC_2.2 pread F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
index 02144967c638cdbe..f60b22efb5b5f683 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F
GLIBC_2.0 sigwait F
GLIBC_2.0 system F
GLIBC_2.0 tcdrain F
-GLIBC_2.0 vfork F
GLIBC_2.0 wait F
GLIBC_2.0 waitpid F
GLIBC_2.0 write F
@@ -140,7 +139,6 @@ GLIBC_2.2 __pthread_rwlock_unlock F
GLIBC_2.2 __pthread_rwlock_wrlock F
GLIBC_2.2 __pwrite64 F
GLIBC_2.2 __res_state F
-GLIBC_2.2 __vfork F
GLIBC_2.2 lseek64 F
GLIBC_2.2 open64 F
GLIBC_2.2 pread F
diff --git a/sysdeps/unix/sysv/linux/mips/pt-vfork.S b/sysdeps/unix/sysv/linux/mips/pt-vfork.S
deleted file mode 100644
index 65cc3823ac872b35..0000000000000000
--- a/sysdeps/unix/sysv/linux/mips/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/nios2/pt-vfork.S b/sysdeps/unix/sysv/linux/nios2/pt-vfork.S
deleted file mode 100644
index 147427a42d2d74a7..0000000000000000
--- a/sysdeps/unix/sysv/linux/nios2/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-# Nios2 does not require a stub for vfork in libpthread.
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
index 09e8447b06f828be..c7d9b7898640730d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F
GLIBC_2.0 sigwait F
GLIBC_2.0 system F
GLIBC_2.0 tcdrain F
-GLIBC_2.0 vfork F
GLIBC_2.0 wait F
GLIBC_2.0 waitpid F
GLIBC_2.0 write F
@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F
GLIBC_2.1.1 sem_close F
GLIBC_2.1.1 sem_open F
GLIBC_2.1.1 sem_unlink F
-GLIBC_2.1.2 __vfork F
+GLIBC_2.1.2 __libpthread_version_placeholder F
GLIBC_2.11 pthread_sigqueue F
GLIBC_2.12 pthread_getname_np F
GLIBC_2.12 pthread_mutex_consistent F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread-le.abilist
index 9a9e4cee85b18a35..6945b7cbe4c2bde8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread-le.abilist
@@ -45,7 +45,6 @@ GLIBC_2.17 __read F
GLIBC_2.17 __res_state F
GLIBC_2.17 __send F
GLIBC_2.17 __sigaction F
-GLIBC_2.17 __vfork F
GLIBC_2.17 __wait F
GLIBC_2.17 __write F
GLIBC_2.17 _pthread_cleanup_pop F
@@ -216,7 +215,6 @@ GLIBC_2.17 siglongjmp F
GLIBC_2.17 sigwait F
GLIBC_2.17 system F
GLIBC_2.17 tcdrain F
-GLIBC_2.17 vfork F
GLIBC_2.17 wait F
GLIBC_2.17 waitpid F
GLIBC_2.17 write F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist
index 8300958d4721d6a6..3500cce6c1124996 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist
@@ -68,7 +68,6 @@ GLIBC_2.3 __read F
GLIBC_2.3 __res_state F
GLIBC_2.3 __send F
GLIBC_2.3 __sigaction F
-GLIBC_2.3 __vfork F
GLIBC_2.3 __wait F
GLIBC_2.3 __write F
GLIBC_2.3 _pthread_cleanup_pop F
@@ -214,7 +213,6 @@ GLIBC_2.3 siglongjmp F
GLIBC_2.3 sigwait F
GLIBC_2.3 system F
GLIBC_2.3 tcdrain F
-GLIBC_2.3 vfork F
GLIBC_2.3 wait F
GLIBC_2.3 waitpid F
GLIBC_2.3 write F
diff --git a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S b/sysdeps/unix/sysv/linux/riscv/pt-vfork.S
deleted file mode 100644
index 1cc8931700702e65..0000000000000000
--- a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-/* Not needed. */
diff --git a/sysdeps/unix/sysv/linux/s390/pt-vfork.S b/sysdeps/unix/sysv/linux/s390/pt-vfork.S
deleted file mode 100644
index 65cc3823ac872b35..0000000000000000
--- a/sysdeps/unix/sysv/linux/s390/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
index d05468f3b2732e92..f093634d7edce2f2 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F
GLIBC_2.0 sigwait F
GLIBC_2.0 system F
GLIBC_2.0 tcdrain F
-GLIBC_2.0 vfork F
GLIBC_2.0 wait F
GLIBC_2.0 waitpid F
GLIBC_2.0 write F
@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F
GLIBC_2.1.1 sem_close F
GLIBC_2.1.1 sem_open F
GLIBC_2.1.1 sem_unlink F
-GLIBC_2.1.2 __vfork F
+GLIBC_2.1.2 __libpthread_version_placeholder F
GLIBC_2.11 pthread_sigqueue F
GLIBC_2.12 pthread_getname_np F
GLIBC_2.12 pthread_mutex_consistent F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
index e8161aa747402b72..47204f166c29a773 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
@@ -48,7 +48,6 @@ GLIBC_2.2 __read F
GLIBC_2.2 __res_state F
GLIBC_2.2 __send F
GLIBC_2.2 __sigaction F
-GLIBC_2.2 __vfork F
GLIBC_2.2 __wait F
GLIBC_2.2 __write F
GLIBC_2.2 _pthread_cleanup_pop F
@@ -194,7 +193,6 @@ GLIBC_2.2 siglongjmp F
GLIBC_2.2 sigwait F
GLIBC_2.2 system F
GLIBC_2.2 tcdrain F
-GLIBC_2.2 vfork F
GLIBC_2.2 wait F
GLIBC_2.2 waitpid F
GLIBC_2.2 write F
diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
index bcba07f57558174f..e9b3be6ac8e8f367 100644
--- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
@@ -46,7 +46,6 @@ GLIBC_2.2 __read F
GLIBC_2.2 __res_state F
GLIBC_2.2 __send F
GLIBC_2.2 __sigaction F
-GLIBC_2.2 __vfork F
GLIBC_2.2 __wait F
GLIBC_2.2 __write F
GLIBC_2.2 _pthread_cleanup_pop F
@@ -192,7 +191,6 @@ GLIBC_2.2 siglongjmp F
GLIBC_2.2 sigwait F
GLIBC_2.2 system F
GLIBC_2.2 tcdrain F
-GLIBC_2.2 vfork F
GLIBC_2.2 wait F
GLIBC_2.2 waitpid F
GLIBC_2.2 write F
diff --git a/sysdeps/unix/sysv/linux/sh/pt-vfork.S b/sysdeps/unix/sysv/linux/sh/pt-vfork.S
deleted file mode 100644
index 65cc3823ac872b35..0000000000000000
--- a/sysdeps/unix/sysv/linux/sh/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/sparc/pt-vfork.S b/sysdeps/unix/sysv/linux/sparc/pt-vfork.S
deleted file mode 100644
index 65cc3823ac872b35..0000000000000000
--- a/sysdeps/unix/sysv/linux/sparc/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
index b413007ccbd2b7b3..2d9b958efa99feb8 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F
GLIBC_2.0 sigwait F
GLIBC_2.0 system F
GLIBC_2.0 tcdrain F
-GLIBC_2.0 vfork F
GLIBC_2.0 wait F
GLIBC_2.0 waitpid F
GLIBC_2.0 write F
@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F
GLIBC_2.1.1 sem_close F
GLIBC_2.1.1 sem_open F
GLIBC_2.1.1 sem_unlink F
-GLIBC_2.1.2 __vfork F
+GLIBC_2.1.2 __libpthread_version_placeholder F
GLIBC_2.11 pthread_sigqueue F
GLIBC_2.12 pthread_getname_np F
GLIBC_2.12 pthread_mutex_consistent F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
index ccc94498268a5c74..e8a65642caec7ff1 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
@@ -46,7 +46,6 @@ GLIBC_2.2 __read F
GLIBC_2.2 __res_state F
GLIBC_2.2 __send F
GLIBC_2.2 __sigaction F
-GLIBC_2.2 __vfork F
GLIBC_2.2 __wait F
GLIBC_2.2 __write F
GLIBC_2.2 _pthread_cleanup_pop F
@@ -192,7 +191,6 @@ GLIBC_2.2 siglongjmp F
GLIBC_2.2 sigwait F
GLIBC_2.2 system F
GLIBC_2.2 tcdrain F
-GLIBC_2.2 vfork F
GLIBC_2.2 wait F
GLIBC_2.2 waitpid F
GLIBC_2.2 write F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
index 931c8277a859999e..4fbb72ffb37ba689 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
@@ -46,7 +46,6 @@ GLIBC_2.2.5 __read F
GLIBC_2.2.5 __res_state F
GLIBC_2.2.5 __send F
GLIBC_2.2.5 __sigaction F
-GLIBC_2.2.5 __vfork F
GLIBC_2.2.5 __wait F
GLIBC_2.2.5 __write F
GLIBC_2.2.5 _pthread_cleanup_pop F
@@ -193,7 +192,6 @@ GLIBC_2.2.5 siglongjmp F
GLIBC_2.2.5 sigwait F
GLIBC_2.2.5 system F
GLIBC_2.2.5 tcdrain F
-GLIBC_2.2.5 vfork F
GLIBC_2.2.5 wait F
GLIBC_2.2.5 waitpid F
GLIBC_2.2.5 write F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
index c09c9b015a66f8f9..eec4b99b8bb69d74 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
@@ -45,7 +45,6 @@ GLIBC_2.16 __read F
GLIBC_2.16 __res_state F
GLIBC_2.16 __send F
GLIBC_2.16 __sigaction F
-GLIBC_2.16 __vfork F
GLIBC_2.16 __wait F
GLIBC_2.16 __write F
GLIBC_2.16 _pthread_cleanup_pop F
@@ -216,7 +215,6 @@ GLIBC_2.16 siglongjmp F
GLIBC_2.16 sigwait F
GLIBC_2.16 system F
GLIBC_2.16 tcdrain F
-GLIBC_2.16 vfork F
GLIBC_2.16 wait F
GLIBC_2.16 waitpid F
GLIBC_2.16 write F

View File

@ -0,0 +1,51 @@
commit f289e656ec8221756519a601042bc9fbe1b310fb
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Feb 8 10:21:56 2019 +0100
rt: Turn forwards from librt to libc into compat symbols [BZ #24194]
As the result of commit 6e6249d0b461b952d0f544792372663feb6d792a
("BZ#14743: Move clock_* symbols from librt to libc."), in glibc 2.17,
clock_gettime, clock_getres, clock_settime, clock_getcpuclockid,
clock_nanosleep were added to libc, and the file rt/clock-compat.c
was added with forwarders to the actual implementations in libc.
These forwarders were wrapped in
#if SHLIB_COMPAT (librt, GLIBC_2_2, GLIBC_2_17)
so that they are not present for newer architectures (such as
powerpc64le) with a 2.17 or later ABI baseline. But the forwarders
were not marked as compatibility symbols. As a result, on older
architectures, historic configure checks such as
AC_CHECK_LIB(rt, clock_gettime)
still cause linking against librt, even though this is completely
unnecessary. It also creates a needless porting hazard because
architectures behave differently when it comes to symbol availability.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/rt/clock-compat.c b/rt/clock-compat.c
index f816973c05c29d5d..11e71aa89019b173 100644
--- a/rt/clock-compat.c
+++ b/rt/clock-compat.c
@@ -30,14 +30,16 @@
#if HAVE_IFUNC
# undef INIT_ARCH
# define INIT_ARCH()
-# define COMPAT_REDIRECT(name, proto, arglist) libc_ifunc (name, &__##name)
+# define COMPAT_REDIRECT(name, proto, arglist) libc_ifunc (name, &__##name) \
+ compat_symbol (librt, name, name, GLIBC_2_2);
#else
# define COMPAT_REDIRECT(name, proto, arglist) \
int \
name proto \
{ \
return __##name arglist; \
- }
+ } \
+ compat_symbol (librt, name, name, GLIBC_2_2);
#endif
COMPAT_REDIRECT (clock_getres,

View File

@ -0,0 +1,256 @@
commit b06f4c0094d3c68be39ada0ed26ae99d51f48013
Author: Wilco Dijkstra <wdijkstr@arm.com>
Date: Fri Feb 1 12:19:42 2019 +0000
Cleanup clock_*time includes
Clock_gettime, settime and getres implementations are unncessarily
complex due to using defines and C file inclusion. Simplify the
code by replacing the redundant defines and removing the inclusion,
making it much easier to understand. No functional changes.
* sysdeps/posix/clock_getres.c (__clock_getres): Cleanup.
* sysdeps/unix/clock_gettime.c (__clock_gettime): Cleanup.
* sysdeps/unix/clock_settime.c (__clock_settime): Cleanup.
* sysdeps/unix/sysv/linux/clock_getres.c (__clock_getres): Cleanup.
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime): Cleanup.
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime): Cleanup.
diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c
index e7924e0891b0a476..43228c381e6a73f1 100644
--- a/sysdeps/posix/clock_getres.c
+++ b/sysdeps/posix/clock_getres.c
@@ -82,20 +82,11 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
switch (clock_id)
{
-#ifdef SYSDEP_GETRES
- SYSDEP_GETRES;
-#endif
-
-#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
retval = realtime_getres (res);
break;
-#endif /* handled REALTIME */
default:
-#ifdef SYSDEP_GETRES_CPU
- SYSDEP_GETRES_CPU;
-#endif
#if HP_TIMING_AVAIL
if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
== CLOCK_THREAD_CPUTIME_ID)
@@ -105,7 +96,7 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
__set_errno (EINVAL);
break;
-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+#if HP_TIMING_AVAIL
case CLOCK_PROCESS_CPUTIME_ID:
case CLOCK_THREAD_CPUTIME_ID:
retval = hp_timing_getres (res);
diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index 96df78ab1ed09c04..f19fdf7e5f310973 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -95,11 +95,6 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
switch (clock_id)
{
-#ifdef SYSDEP_GETTIME
- SYSDEP_GETTIME;
-#endif
-
-#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
{
struct timeval tv;
@@ -108,12 +103,8 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
TIMEVAL_TO_TIMESPEC (&tv, tp);
}
break;
-#endif
default:
-#ifdef SYSDEP_GETTIME_CPU
- SYSDEP_GETTIME_CPU (clock_id, tp);
-#endif
#if HP_TIMING_AVAIL
if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
== CLOCK_THREAD_CPUTIME_ID)
@@ -123,7 +114,7 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
__set_errno (EINVAL);
break;
-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+#if HP_TIMING_AVAIL
case CLOCK_PROCESS_CPUTIME_ID:
retval = hp_timing_gettime (clock_id, tp);
break;
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index 38813eddf7b66ca1..9d5857e61b966b44 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -21,7 +21,7 @@
#include <ldsodefs.h>
-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+#if HP_TIMING_AVAIL
/* Clock frequency of the processor. We make it a 64-bit variable
because some jokers are already playing with processors with more
than 4GHz. */
@@ -84,29 +84,15 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
switch (clock_id)
{
-#define HANDLE_REALTIME \
- do { \
- struct timeval tv; \
- TIMESPEC_TO_TIMEVAL (&tv, tp); \
- \
- retval = __settimeofday (&tv, NULL); \
- } while (0)
-
-#ifdef SYSDEP_SETTIME
- SYSDEP_SETTIME;
-#endif
-
-#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
- HANDLE_REALTIME;
+ {
+ struct timeval tv;
+ TIMESPEC_TO_TIMEVAL (&tv, tp);
+ retval = __settimeofday (&tv, NULL);
+ }
break;
-#endif
default:
-#ifdef SYSDEP_SETTIME_CPU
- SYSDEP_SETTIME_CPU;
-#endif
-#ifndef HANDLED_CPUTIME
# if HP_TIMING_AVAIL
if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID
|| CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID)
@@ -117,7 +103,6 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
__set_errno (EINVAL);
retval = -1;
}
-#endif
break;
}
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 5d94f59afee80fa9..2517e66910a79d93 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -26,26 +26,10 @@
#endif
#include <sysdep-vdso.h>
-#define SYSCALL_GETRES \
- retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, res); \
- break
-
-/* The REALTIME and MONOTONIC clock are definitely supported in the
- kernel. */
-#define SYSDEP_GETRES \
- SYSDEP_GETRES_CPUTIME \
- case CLOCK_REALTIME: \
- case CLOCK_MONOTONIC: \
- case CLOCK_MONOTONIC_RAW: \
- case CLOCK_REALTIME_COARSE: \
- case CLOCK_MONOTONIC_COARSE: \
- SYSCALL_GETRES
-
-/* We handled the REALTIME clock here. */
-#define HANDLED_REALTIME 1
-#define HANDLED_CPUTIME 1
-
-#define SYSDEP_GETRES_CPU SYSCALL_GETRES
-#define SYSDEP_GETRES_CPUTIME /* Default catches them too. */
-
-#include <sysdeps/posix/clock_getres.c>
+/* Get resolution of clock. */
+int
+__clock_getres (clockid_t clock_id, struct timespec *res)
+{
+ return INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+}
+weak_alias (__clock_getres, clock_getres)
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index d837fa36b1b901e5..dadfc518b74baea0 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -26,22 +26,11 @@
#endif
#include <sysdep-vdso.h>
-/* The REALTIME and MONOTONIC clock are definitely supported in the
- kernel. */
-#define SYSDEP_GETTIME \
- SYSDEP_GETTIME_CPUTIME; \
- case CLOCK_REALTIME: \
- case CLOCK_MONOTONIC: \
- retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \
- break
-
-/* We handled the REALTIME clock here. */
-#define HANDLED_REALTIME 1
-#define HANDLED_CPUTIME 1
-
-#define SYSDEP_GETTIME_CPU(clock_id, tp) \
- retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \
- break
-#define SYSDEP_GETTIME_CPUTIME /* Default catches them too. */
-
-#include <sysdeps/unix/clock_gettime.c>
+/* Get current value of CLOCK and store it in TP. */
+int
+__clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+ return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);
+}
+weak_alias (__clock_gettime, clock_gettime)
+libc_hidden_def (__clock_gettime)
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index 5f3f22f74b3e745c..c71461a4f6deac5a 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -21,18 +21,17 @@
#include "kernel-posix-cpu-timers.h"
-
-/* The REALTIME clock is definitely supported in the kernel. */
-#define SYSDEP_SETTIME \
- case CLOCK_REALTIME: \
- retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp); \
- break
-
-/* We handled the REALTIME clock here. */
-#define HANDLED_REALTIME 1
-
-#define HANDLED_CPUTIME 1
-#define SYSDEP_SETTIME_CPU \
- retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
-
-#include <sysdeps/unix/clock_settime.c>
+/* Set CLOCK to value TP. */
+int
+__clock_settime (clockid_t clock_id, const struct timespec *tp)
+{
+ /* Make sure the time cvalue is OK. */
+ if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
+}
+weak_alias (__clock_settime, clock_settime)

View File

@ -0,0 +1,735 @@
commit 38cc11daa43b11b12a7774405accee1007de1adf
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Jan 16 16:22:29 2019 +0000
nptl: Remove pthread_clock_gettime pthread_clock_settime
This patch removes CLOCK_THREAD_CPUTIME_ID and CLOCK_PROCESS_CPUTIME_ID support
from clock_gettime and clock_settime generic implementation. For Linux, kernel
already provides supports through the syscall and Hurd HTL lacks
__pthread_clock_gettime and __pthread_clock_settime internal implementation.
As described in clock_gettime man-page [1] on 'Historical note for SMP
system', implementing CLOCK_{THREAD,PROCESS}_CPUTIME_ID with timer registers
is error-prone and susceptible to timing and accurary issues that the libc
can not deal without kernel support.
This allows removes unused code which, however, still incur in some runtime
overhead in thread creation (the struct pthread cpuclock_offset
initialization).
If hurd eventually wants to support them it should either either implement as
a kernel facility (or something related due its architecture) or in system
specific implementation.
Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. I also
checked on a i686-gnu build.
* nptl/Makefile (libpthread-routines): Remove pthread_clock_gettime and
pthread_clock_settime.
* nptl/pthreadP.h (__find_thread_by_id): Remove prototype.
* elf/dl-support.c [!HP_TIMING_NOAVAIL] (_dl_cpuclock_offset): Remove.
(_dl_non_dynamic_init): Remove _dl_cpuclock_offset setting.
* elf/rtld.c (_dl_start_final): Likewise.
* nptl/allocatestack.c (__find_thread_by_id): Remove function.
* sysdeps/generic/ldsodefs.h [!HP_TIMING_NOAVAIL] (_dl_cpuclock_offset):
Remove.
* sysdeps/mach/hurd/dl-sysdep.c [!HP_TIMING_NOAVAIL]
(_dl_cpuclock_offset): Remove.
* nptl/descr.h (struct pthread): Rename cpuclock_offset to
cpuclock_offset_ununsed.
* nptl/nptl-init.c (__pthread_initialize_minimal_internal): Remove
cpuclock_offset set.
* nptl/pthread_create.c (START_THREAD_DEFN): Likewise.
* sysdeps/nptl/fork.c (__libc_fork): Likewise.
* nptl/pthread_clock_gettime.c: Remove file.
* nptl/pthread_clock_settime.c: Likewise.
* sysdeps/unix/clock_gettime.c (hp_timing_gettime): Remove function.
[HP_TIMING_AVAIL] (realtime_gettime): Remove CLOCK_THREAD_CPUTIME_ID
and CLOCK_PROCESS_CPUTIME_ID support.
* sysdeps/unix/clock_settime.c (hp_timing_gettime): Likewise.
[HP_TIMING_AVAIL] (realtime_gettime): Likewise.
* sysdeps/posix/clock_getres.c (hp_timing_getres): Likewise.
[HP_TIMING_AVAIL] (__clock_getres): Likewise.
* sysdeps/unix/clock_nanosleep.c (CPUCLOCK_P, INVALID_CLOCK_P):
Likewise.
(__clock_nanosleep): Remove CPUCLOCK_P and INVALID_CLOCK_P usage.
[1] http://man7.org/linux/man-pages/man2/clock_gettime.2.html
Conflicts:
nptl/pthread_clock_gettime.c
nptl/pthread_clock_settime.c
(Removal after copyright year update upstream.)
diff --git a/elf/dl-support.c b/elf/dl-support.c
index c8439fcc53d126f3..ef5455b91c17ca30 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -127,11 +127,6 @@ void *_dl_random;
#include <dl-procruntime.c>
#include <dl-procinfo.c>
-/* Initial value of the CPU clock. */
-#ifndef HP_TIMING_NONAVAIL
-hp_timing_t _dl_cpuclock_offset;
-#endif
-
void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
size_t _dl_pagesize = EXEC_PAGESIZE;
@@ -312,9 +307,6 @@ _dl_non_dynamic_init (void)
_dl_main_map.l_phdr = GL(dl_phdr);
_dl_main_map.l_phnum = GL(dl_phnum);
- if (HP_SMALL_TIMING_AVAIL)
- HP_TIMING_NOW (_dl_cpuclock_offset);
-
_dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
/* Set up the data structures for the system-supplied DSO early,
diff --git a/elf/rtld.c b/elf/rtld.c
index 0aa1a2a19f649e16..e107bd14f9478a90 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -401,8 +401,6 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
# endif
#endif
- HP_TIMING_NOW (GL(dl_cpuclock_offset));
-
/* Initialize the stack end variable. */
__libc_stack_end = __builtin_frame_address (0);
diff --git a/nptl/Makefile b/nptl/Makefile
index 447dce0590295c9c..d6b37b6efd3b7d78 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -109,7 +109,6 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \
pthread_once \
old_pthread_atfork \
pthread_getcpuclockid \
- pthread_clock_gettime pthread_clock_settime \
shm-directory \
sem_init sem_destroy \
sem_open sem_close sem_unlink \
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index d0971a97fdbe098e..5fa45b19987717e1 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -964,54 +964,6 @@ __reclaim_stacks (void)
}
-#if HP_TIMING_AVAIL
-# undef __find_thread_by_id
-/* Find a thread given the thread ID. */
-attribute_hidden
-struct pthread *
-__find_thread_by_id (pid_t tid)
-{
- struct pthread *result = NULL;
-
- lll_lock (stack_cache_lock, LLL_PRIVATE);
-
- /* Iterate over the list with system-allocated threads first. */
- list_t *runp;
- list_for_each (runp, &stack_used)
- {
- struct pthread *curp;
-
- curp = list_entry (runp, struct pthread, list);
-
- if (curp->tid == tid)
- {
- result = curp;
- goto out;
- }
- }
-
- /* Now the list with threads using user-allocated stacks. */
- list_for_each (runp, &__stack_user)
- {
- struct pthread *curp;
-
- curp = list_entry (runp, struct pthread, list);
-
- if (curp->tid == tid)
- {
- result = curp;
- goto out;
- }
- }
-
- out:
- lll_unlock (stack_cache_lock, LLL_PRIVATE);
-
- return result;
-}
-#endif
-
-
#ifdef SIGSETXID
static void
setxid_mark_thread (struct xid_command *cmdp, struct pthread *t)
diff --git a/nptl/descr.h b/nptl/descr.h
index 9c01e1b9863b178c..c3b81d8b27839502 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -343,8 +343,7 @@ struct pthread
unsigned int setxid_futex;
#if HP_TIMING_AVAIL
- /* Offset of the CPU clock at start thread start time. */
- hp_timing_t cpuclock_offset;
+ hp_timing_t cpuclock_offset_ununsed;
#endif
/* If the thread waits to join another one the ID of the latter is
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index 907411d5bca2af79..098bc059f4771ef2 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -275,9 +275,6 @@ __pthread_initialize_minimal_internal (void)
THREAD_SETMEM (pd, user_stack, true);
if (LLL_LOCK_INITIALIZER != 0)
THREAD_SETMEM (pd, lock, LLL_LOCK_INITIALIZER);
-#if HP_TIMING_AVAIL
- THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset));
-#endif
/* Initialize the robust mutex data. */
{
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 19efe1e35feed5be..00be8f92793e8710 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -406,16 +406,6 @@ extern int __pthread_multiple_threads attribute_hidden;
extern int *__libc_multiple_threads_ptr attribute_hidden;
#endif
-/* Find a thread given its TID. */
-extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden
-#ifdef SHARED
-;
-#else
-weak_function;
-#define __find_thread_by_id(tid) \
- (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL)
-#endif
-
extern void __pthread_init_static_tls (struct link_map *) attribute_hidden;
extern size_t __pthread_get_minstack (const pthread_attr_t *attr);
diff --git a/nptl/pthread_clock_gettime.c b/nptl/pthread_clock_gettime.c
deleted file mode 100644
index 6bc75cfe3f1ff856..0000000000000000
--- a/nptl/pthread_clock_gettime.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, see <http://www.gnu.org/licenses/>. */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-#include "pthreadP.h"
-
-
-#if HP_TIMING_AVAIL
-int
-__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
- struct timespec *tp)
-{
- hp_timing_t tsc;
-
- /* Get the current counter. */
- HP_TIMING_NOW (tsc);
-
- /* This is the ID of the thread we are looking for. */
- pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE;
-
- /* Compute the offset since the start time of the process. */
- if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid))
- /* Our own clock. */
- tsc -= THREAD_GETMEM (THREAD_SELF, cpuclock_offset);
- else
- {
- /* This is more complicated. We have to locate the thread based
- on the ID. This means walking the list of existing
- threads. */
- struct pthread *thread = __find_thread_by_id (tid);
- if (thread == NULL)
- {
- __set_errno (EINVAL);
- return -1;
- }
-
- /* There is a race here. The thread might terminate and the stack
- become unusable. But this is the user's problem. */
- tsc -= thread->cpuclock_offset;
- }
-
- /* Compute the seconds. */
- tp->tv_sec = tsc / freq;
-
- /* And the nanoseconds. This computation should be stable until
- we get machines with about 16GHz frequency. */
- tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq;
-
- return 0;
-}
-#endif
diff --git a/nptl/pthread_clock_settime.c b/nptl/pthread_clock_settime.c
deleted file mode 100644
index 29d35c64cfa817a3..0000000000000000
--- a/nptl/pthread_clock_settime.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, see <http://www.gnu.org/licenses/>. */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-#include "pthreadP.h"
-
-
-#if HP_TIMING_AVAIL
-int
-__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset)
-{
- /* This is the ID of the thread we are looking for. */
- pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE;
-
- /* Compute the offset since the start time of the process. */
- if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid))
- /* Our own clock. */
- THREAD_SETMEM (THREAD_SELF, cpuclock_offset, offset);
- else
- {
- /* This is more complicated. We have to locate the thread based
- on the ID. This means walking the list of existing
- threads. */
- struct pthread *thread = __find_thread_by_id (tid);
- if (thread == NULL)
- {
- __set_errno (EINVAL);
- return -1;
- }
-
- /* There is a race here. The thread might terminate and the stack
- become unusable. But this is the user's problem. */
- thread->cpuclock_offset = offset;
- }
-
- return 0;
-}
-#endif
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index fe75d04113b8aa3f..f58a15cd1c7bbb6f 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -379,13 +379,6 @@ START_THREAD_DEFN
{
struct pthread *pd = START_THREAD_SELF;
-#if HP_TIMING_AVAIL
- /* Remember the time when the thread was started. */
- hp_timing_t now;
- HP_TIMING_NOW (now);
- THREAD_SETMEM (pd, cpuclock_offset, now);
-#endif
-
/* Initialize resolver state pointer. */
__resp = &pd->res;
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index c6b7e61badbfd513..f0185ce0d16c0f69 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -359,11 +359,6 @@ struct rtld_global
/* The object to be initialized first. */
EXTERN struct link_map *_dl_initfirst;
-#if HP_SMALL_TIMING_AVAIL
- /* Start time on CPU clock. */
- EXTERN hp_timing_t _dl_cpuclock_offset;
-#endif
-
/* Map of shared object to be profiled. */
EXTERN struct link_map *_dl_profile_map;
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index b72913d3baaed1d9..7bd1d70c96c229e0 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -62,10 +62,6 @@ int __libc_multiple_libcs = 0; /* Defining this here avoids the inclusion
void *__libc_stack_end = NULL;
rtld_hidden_data_def(__libc_stack_end)
-#if HP_TIMING_AVAIL
-hp_timing_t _dl_cpuclock_offset;
-#endif
-
/* TODO: Initialize. */
void *_dl_random attribute_relro = NULL;
@@ -246,10 +242,6 @@ unfmh(); /* XXX */
/* Initialize frequently used global variable. */
GLRO(dl_pagesize) = __getpagesize ();
-#if HP_TIMING_AVAIL
- HP_TIMING_NOW (_dl_cpuclock_offset);
-#endif
-
fmh(); /* XXX */
/* See hurd/hurdstartup.c; this deals with getting information
diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
index 1a9429b579cd346e..37db30f3d1e846b6 100644
--- a/sysdeps/nptl/fork.c
+++ b/sysdeps/nptl/fork.c
@@ -83,14 +83,6 @@ __libc_fork (void)
if (__fork_generation_pointer != NULL)
*__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR;
-#if HP_TIMING_AVAIL
- /* The CPU clock of the thread and process have to be set to zero. */
- hp_timing_t now;
- HP_TIMING_NOW (now);
- THREAD_SETMEM (self, cpuclock_offset, now);
- GL(dl_cpuclock_offset) = now;
-#endif
-
#ifdef __NR_set_robust_list
/* Initialize the robust mutex list setting in the kernel which has
been reset during the fork. We do not check for errors because if
diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c
index 43228c381e6a73f1..5b0d8eb8a1a0593e 100644
--- a/sysdeps/posix/clock_getres.c
+++ b/sysdeps/posix/clock_getres.c
@@ -24,37 +24,6 @@
#include <libc-internal.h>
-#if HP_TIMING_AVAIL
-static long int nsec; /* Clock frequency of the processor. */
-
-static int
-hp_timing_getres (struct timespec *res)
-{
- if (__glibc_unlikely (nsec == 0))
- {
- hp_timing_t freq;
-
- /* This can only happen if we haven't initialized the `nsec'
- variable yet. Do this now. We don't have to protect this
- code against multiple execution since all of them should
- lead to the same result. */
- freq = __get_clockfreq ();
- if (__glibc_unlikely (freq == 0))
- /* Something went wrong. */
- return -1;
-
- nsec = MAX (UINT64_C (1000000000) / freq, 1);
- }
-
- /* Fill in the values.
- The seconds are always zero (unless we have a 1Hz machine). */
- res->tv_sec = 0;
- res->tv_nsec = nsec;
-
- return 0;
-}
-#endif
-
static inline int
realtime_getres (struct timespec *res)
{
@@ -87,21 +56,8 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
break;
default:
-#if HP_TIMING_AVAIL
- if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
- == CLOCK_THREAD_CPUTIME_ID)
- retval = hp_timing_getres (res);
- else
-#endif
- __set_errno (EINVAL);
- break;
-
-#if HP_TIMING_AVAIL
- case CLOCK_PROCESS_CPUTIME_ID:
- case CLOCK_THREAD_CPUTIME_ID:
- retval = hp_timing_getres (res);
+ __set_errno (EINVAL);
break;
-#endif
}
return retval;
diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index f19fdf7e5f310973..f3ebbe15ccc2e95e 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -24,57 +24,6 @@
#include <ldsodefs.h>
-#if HP_TIMING_AVAIL
-/* Clock frequency of the processor. We make it a 64-bit variable
- because some jokers are already playing with processors with more
- than 4GHz. */
-static hp_timing_t freq;
-
-
-/* This function is defined in the thread library. */
-extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
- struct timespec *tp)
- __attribute__ ((__weak__));
-
-static int
-hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
-{
- hp_timing_t tsc;
-
- if (__glibc_unlikely (freq == 0))
- {
- /* This can only happen if we haven't initialized the `freq'
- variable yet. Do this now. We don't have to protect this
- code against multiple execution since all of them should
- lead to the same result. */
- freq = __get_clockfreq ();
- if (__glibc_unlikely (freq == 0))
- /* Something went wrong. */
- return -1;
- }
-
- if (clock_id != CLOCK_PROCESS_CPUTIME_ID
- && __pthread_clock_gettime != NULL)
- return __pthread_clock_gettime (clock_id, freq, tp);
-
- /* Get the current counter. */
- HP_TIMING_NOW (tsc);
-
- /* Compute the offset since the start time of the process. */
- tsc -= GL(dl_cpuclock_offset);
-
- /* Compute the seconds. */
- tp->tv_sec = tsc / freq;
-
- /* And the nanoseconds. This computation should be stable until
- we get machines with about 16GHz frequency. */
- tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq;
-
- return 0;
-}
-#endif
-
-
static inline int
realtime_gettime (struct timespec *tp)
{
@@ -105,20 +54,8 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
break;
default:
-#if HP_TIMING_AVAIL
- if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
- == CLOCK_THREAD_CPUTIME_ID)
- retval = hp_timing_gettime (clock_id, tp);
- else
-#endif
- __set_errno (EINVAL);
- break;
-
-#if HP_TIMING_AVAIL
- case CLOCK_PROCESS_CPUTIME_ID:
- retval = hp_timing_gettime (clock_id, tp);
+ __set_errno (EINVAL);
break;
-#endif
}
return retval;
diff --git a/sysdeps/unix/clock_nanosleep.c b/sysdeps/unix/clock_nanosleep.c
index 97b3d6b6ab9e4581..13dd0f4b905ec631 100644
--- a/sysdeps/unix/clock_nanosleep.c
+++ b/sysdeps/unix/clock_nanosleep.c
@@ -19,23 +19,8 @@
#include <assert.h>
#include <errno.h>
#include <time.h>
-#include <hp-timing.h>
#include <sysdep-cancel.h>
-#if HP_TIMING_AVAIL
-# define CPUCLOCK_P(clock) \
- ((clock) == CLOCK_PROCESS_CPUTIME_ID \
- || ((clock) & ((1 << CLOCK_IDFIELD_SIZE) - 1)) == CLOCK_THREAD_CPUTIME_ID)
-#else
-# define CPUCLOCK_P(clock) 0
-#endif
-
-#ifndef INVALID_CLOCK_P
-# define INVALID_CLOCK_P(cl) \
- ((cl) < CLOCK_REALTIME || (cl) > CLOCK_THREAD_CPUTIME_ID)
-#endif
-
-
/* This implementation assumes that these is only a `nanosleep' system
call. So we have to remap all other activities. */
int
@@ -51,14 +36,7 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
if (clock_id == CLOCK_THREAD_CPUTIME_ID)
return EINVAL; /* POSIX specifies EINVAL for this case. */
-#ifdef SYSDEP_NANOSLEEP
- SYSDEP_NANOSLEEP;
-#endif
-
- if (CPUCLOCK_P (clock_id))
- return ENOTSUP;
-
- if (INVALID_CLOCK_P (clock_id))
+ if (clock_id < CLOCK_REALTIME || clock_id > CLOCK_THREAD_CPUTIME_ID)
return EINVAL;
/* If we got an absolute time, remap it. */
@@ -71,7 +49,7 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
assert (sizeof (sec) >= sizeof (now.tv_sec));
/* Get the current time for this clock. */
- if (__builtin_expect (__clock_gettime (clock_id, &now), 0) != 0)
+ if (__clock_gettime (clock_id, &now) != 0)
return errno;
/* Compute the difference. */
@@ -90,12 +68,12 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
/* Make sure we are not modifying the struct pointed to by REM. */
rem = NULL;
}
- else if (__builtin_expect (flags, 0) != 0)
+ else if (flags != 0)
return EINVAL;
else if (clock_id != CLOCK_REALTIME)
/* Not supported. */
return ENOTSUP;
- return __builtin_expect (__nanosleep (req, rem), 0) ? errno : 0;
+ return __nanosleep (req, rem), 0 ? errno : 0;
}
weak_alias (__clock_nanosleep, clock_nanosleep)
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index 9d5857e61b966b44..4f5640f67047cef6 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -21,59 +21,11 @@
#include <ldsodefs.h>
-#if HP_TIMING_AVAIL
-/* Clock frequency of the processor. We make it a 64-bit variable
- because some jokers are already playing with processors with more
- than 4GHz. */
-static hp_timing_t freq;
-
-
-/* This function is defined in the thread library. */
-extern void __pthread_clock_settime (clockid_t clock_id, hp_timing_t offset)
- __attribute__ ((__weak__));
-
-
-static int
-hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
-{
- hp_timing_t tsc;
- hp_timing_t usertime;
-
- /* First thing is to get the current time. */
- HP_TIMING_NOW (tsc);
-
- if (__glibc_unlikely (freq == 0))
- {
- /* This can only happen if we haven't initialized the `freq'
- variable yet. Do this now. We don't have to protect this
- code against multiple execution since all of them should lead
- to the same result. */
- freq = __get_clockfreq ();
- if (__glibc_unlikely (freq == 0))
- /* Something went wrong. */
- return -1;
- }
-
- /* Convert the user-provided time into CPU ticks. */
- usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull;
-
- /* Determine the offset and use it as the new base value. */
- if (clock_id == CLOCK_PROCESS_CPUTIME_ID
- || __pthread_clock_settime == NULL)
- GL(dl_cpuclock_offset) = tsc - usertime;
- else
- __pthread_clock_settime (clock_id, tsc - usertime);
-
- return 0;
-}
-#endif
-
-
/* Set CLOCK to value TP. */
int
__clock_settime (clockid_t clock_id, const struct timespec *tp)
{
- int retval;
+ int retval = -1;
/* Make sure the time cvalue is OK. */
if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
@@ -93,16 +45,7 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
break;
default:
-# if HP_TIMING_AVAIL
- if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID
- || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID)
- retval = hp_timing_settime (clock_id, tp);
- else
-# endif
- {
- __set_errno (EINVAL);
- retval = -1;
- }
+ __set_errno (EINVAL);
break;
}

View File

@ -0,0 +1,745 @@
commit 6e8ba7fd574f530afb9681f21604475d5756d773
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Fri Feb 8 16:53:40 2019 +0000
Remove __get_clockfreq
With clock_getres, clock_gettime, and clock_settime refactor to remove the
generic CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID support through
hp-timing, there is no usage of internal __get_clockfreq. This patch removes
both generic and Linux implementation..
Checked with a build against aarch64-linux-gnu, i686-linux-gnu, ia64-linux-gnu,
sparc64-linux-gnu, powerpc-linux-gnu-power4.
* include/libc-internal.h (__get_clockfreq): Remove prototype.
* rt/Makefile (clock-routines): Remove get_clockfreq.
* rt/get_clockfreq.c: Remove file.
* sysdeps/unix/sysv/linux/i386/get_clockfreq.c: Likewise.
* sysdeps/unix/sysv/linux/ia64/get_clockfreq.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c: Likewise.
* sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c: Move code to ...
* sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c: ... here.
Conflicts:
rt/get_clockfreq.c
sysdeps/unix/sysv/linux/i386/get_clockfreq.c
sysdeps/unix/sysv/linux/ia64/get_clockfreq.c
sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
(Removal after copyright year change upstream.)
sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
(Likewise. Missing backport of aa0e46636a5b71 ("Break
further lines before not after operators.").)
diff --git a/include/libc-internal.h b/include/libc-internal.h
index 2167990c52bd708b..2ec07d9355db1808 100644
--- a/include/libc-internal.h
+++ b/include/libc-internal.h
@@ -36,9 +36,6 @@ libc_hidden_proto (__profile_frequency)
extern void __cyg_profile_func_enter (void *this_fn, void *call_site);
extern void __cyg_profile_func_exit (void *this_fn, void *call_site);
-/* Get frequency of the system processor. */
-extern hp_timing_t __get_clockfreq (void);
-
/* Free all allocated resources. */
extern void __libc_freeres (void);
libc_hidden_proto (__libc_freeres)
diff --git a/rt/Makefile b/rt/Makefile
index 6d6b896ee9817c5c..14f38ef74d262188 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -28,7 +28,7 @@ aio-routines := aio_cancel aio_error aio_fsync aio_misc aio_read \
aio_read64 aio_return aio_suspend aio_write \
aio_write64 lio_listio lio_listio64 aio_sigqueue \
aio_notify
-clock-routines := get_clockfreq clock_getcpuclockid \
+clock-routines := clock_getcpuclockid \
clock_getres clock_gettime clock_settime \
clock_nanosleep
timer-routines := timer_create timer_delete timer_getoverr \
diff --git a/rt/get_clockfreq.c b/rt/get_clockfreq.c
deleted file mode 100644
index e695a6018c0b8322..0000000000000000
--- a/rt/get_clockfreq.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Get frequency of the system processor.
- Copyright (C) 2000-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <libc-internal.h>
-
-hp_timing_t
-__get_clockfreq (void)
-{
- /* There is no generic way to find this out since we have in general
- no counter register either. */
- return 0;
-}
diff --git a/sysdeps/unix/sysv/linux/i386/get_clockfreq.c b/sysdeps/unix/sysv/linux/i386/get_clockfreq.c
deleted file mode 100644
index 633f186be80f10b0..0000000000000000
--- a/sysdeps/unix/sysv/linux/i386/get_clockfreq.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Get frequency of the system processor. i386/Linux version.
- Copyright (C) 2000-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-hp_timing_t
-__get_clockfreq (void)
-{
- /* We read the information from the /proc filesystem. It contains at
- least one line like
- cpu MHz : 497.840237
- or also
- cpu MHz : 497.841
- We search for this line and convert the number in an integer. */
- static hp_timing_t result;
- int fd;
-
- /* If this function was called before, we know the result. */
- if (result != 0)
- return result;
-
- fd = __open ("/proc/cpuinfo", O_RDONLY);
- if (__glibc_likely (fd != -1))
- {
- /* XXX AFAIK the /proc filesystem can generate "files" only up
- to a size of 4096 bytes. */
- char buf[4096];
- ssize_t n;
-
- n = __read (fd, buf, sizeof buf);
- if (__builtin_expect (n, 1) > 0)
- {
- char *mhz = memmem (buf, n, "cpu MHz", 7);
-
- if (__glibc_likely (mhz != NULL))
- {
- char *endp = buf + n;
- int seen_decpoint = 0;
- int ndigits = 0;
-
- /* Search for the beginning of the string. */
- while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
- ++mhz;
-
- while (mhz < endp && *mhz != '\n')
- {
- if (*mhz >= '0' && *mhz <= '9')
- {
- result *= 10;
- result += *mhz - '0';
- if (seen_decpoint)
- ++ndigits;
- }
- else if (*mhz == '.')
- seen_decpoint = 1;
-
- ++mhz;
- }
-
- /* Compensate for missing digits at the end. */
- while (ndigits++ < 6)
- result *= 10;
- }
- }
-
- __close (fd);
- }
-
- return result;
-}
diff --git a/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c b/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c
deleted file mode 100644
index f9d683a90247ac60..0000000000000000
--- a/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Get frequency of the system processor. IA-64/Linux version.
- Copyright (C) 2001-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-
-hp_timing_t
-__get_clockfreq (void)
-{
- /* We read the information from the /proc filesystem. It contains at
- least one line like
- itc MHz : 733.390988
- We search for this line and convert the number in an integer. */
- static hp_timing_t result;
- int fd;
-
- /* If this function was called before, we know the result. */
- if (result != 0)
- return result;
-
- fd = __open ("/proc/cpuinfo", O_RDONLY);
- if (__builtin_expect (fd != -1, 1))
- {
- /* XXX AFAIK the /proc filesystem can generate "files" only up
- to a size of 4096 bytes. */
- char buf[4096];
- ssize_t n;
-
- n = __read (fd, buf, sizeof buf);
- if (__builtin_expect (n, 1) > 0)
- {
- char *mhz = memmem (buf, n, "itc MHz", 7);
-
- if (__builtin_expect (mhz != NULL, 1))
- {
- char *endp = buf + n;
- int seen_decpoint = 0;
- int ndigits = 0;
-
- /* Search for the beginning of the string. */
- while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
- ++mhz;
-
- while (mhz < endp && *mhz != '\n')
- {
- if (*mhz >= '0' && *mhz <= '9')
- {
- result *= 10;
- result += *mhz - '0';
- if (seen_decpoint)
- ++ndigits;
- }
- else if (*mhz == '.')
- seen_decpoint = 1;
-
- ++mhz;
- }
-
- /* Compensate for missing digits at the end. */
- while (ndigits++ < 6)
- result *= 10;
- }
- }
-
- __close (fd);
- }
-
- return result;
-}
diff --git a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c b/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
deleted file mode 100644
index 3a2216021bfb5408..0000000000000000
--- a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Get frequency of the system processor. powerpc/Linux version.
- Copyright (C) 2000-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <sysdep.h>
-#include <libc-vdso.h>
-#include <not-cancel.h>
-
-hp_timing_t
-__get_clockfreq (void)
-{
- hp_timing_t result = 0L;
-
-#ifdef SHARED
- /* The vDSO does not return an error (it clear cr0.so on returning). */
- INTERNAL_SYSCALL_DECL (err);
- result =
- INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, uint64_t, 0);
-#else
- /* We read the information from the /proc filesystem. /proc/cpuinfo
- contains at least one line like:
- timebase : 33333333
- We search for this line and convert the number into an integer. */
- int fd = __open_nocancel ("/proc/cpuinfo", O_RDONLY);
- if (__glibc_likely (fd != -1))
- return result;
-
- /* The timebase will be in the 1st 1024 bytes for systems with up
- to 8 processors. If the first read returns less then 1024
- bytes read, we have the whole cpuinfo and can start the scan.
- Otherwise we will have to read more to insure we have the
- timebase value in the scan. */
- char buf[1024];
- ssize_t n;
-
- n = __read_nocancel (fd, buf, sizeof (buf));
- if (n == sizeof (buf))
- {
- /* We are here because the 1st read returned exactly sizeof
- (buf) bytes. This implies that we are not at EOF and may
- not have read the timebase value yet. So we need to read
- more bytes until we know we have EOF. We copy the lower
- half of buf to the upper half and read sizeof (buf)/2
- bytes into the lower half of buf and repeat until we
- reach EOF. We can assume that the timebase will be in
- the last 512 bytes of cpuinfo, so two 512 byte half_bufs
- will be sufficient to contain the timebase and will
- handle the case where the timebase spans the half_buf
- boundry. */
- const ssize_t half_buf = sizeof (buf) / 2;
- while (n >= half_buf)
- {
- memcpy (buf, buf + half_buf, half_buf);
- n = __read_nocancel (fd, buf + half_buf, half_buf);
- }
- if (n >= 0)
- n += half_buf;
- }
- __close_nocancel (fd);
-
- if (__glibc_likely (n > 0))
- {
- char *mhz = memmem (buf, n, "timebase", 7);
-
- if (__glibc_likely (mhz != NULL))
- {
- char *endp = buf + n;
-
- /* Search for the beginning of the string. */
- while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
- ++mhz;
-
- while (mhz < endp && *mhz != '\n')
- {
- if (*mhz >= '0' && *mhz <= '9')
- {
- result *= 10;
- result += *mhz - '0';
- }
-
- ++mhz;
- }
- }
- }
-#endif
-
- return result;
-}
diff --git a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
index 6435e1f31529c7de..1177ccbc8faeafe7 100644
--- a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
+++ b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
@@ -17,11 +17,90 @@
<http://www.gnu.org/licenses/>. */
#include <stdint.h>
+#include <string.h>
+
#include <libc-internal.h>
+#include <not-cancel.h>
+#include <libc-vdso.h>
uint64_t
__get_timebase_freq (void)
{
- return (uint64_t) __get_clockfreq ();
+ hp_timing_t result = 0L;
+
+#ifdef SHARED
+ /* The vDSO does not return an error (it clear cr0.so on returning). */
+ INTERNAL_SYSCALL_DECL (err);
+ result =
+ INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, uint64_t, 0);
+#else
+ /* We read the information from the /proc filesystem. /proc/cpuinfo
+ contains at least one line like:
+ timebase : 33333333
+ We search for this line and convert the number into an integer. */
+ int fd = __open_nocancel ("/proc/cpuinfo", O_RDONLY);
+ if (__glibc_likely (fd != -1))
+ return result;
+
+ /* The timebase will be in the 1st 1024 bytes for systems with up
+ to 8 processors. If the first read returns less then 1024
+ bytes read, we have the whole cpuinfo and can start the scan.
+ Otherwise we will have to read more to insure we have the
+ timebase value in the scan. */
+ char buf[1024];
+ ssize_t n;
+
+ n = __read_nocancel (fd, buf, sizeof (buf));
+ if (n == sizeof (buf))
+ {
+ /* We are here because the 1st read returned exactly sizeof
+ (buf) bytes. This implies that we are not at EOF and may
+ not have read the timebase value yet. So we need to read
+ more bytes until we know we have EOF. We copy the lower
+ half of buf to the upper half and read sizeof (buf)/2
+ bytes into the lower half of buf and repeat until we
+ reach EOF. We can assume that the timebase will be in
+ the last 512 bytes of cpuinfo, so two 512 byte half_bufs
+ will be sufficient to contain the timebase and will
+ handle the case where the timebase spans the half_buf
+ boundry. */
+ const ssize_t half_buf = sizeof (buf) / 2;
+ while (n >= half_buf)
+ {
+ memcpy (buf, buf + half_buf, half_buf);
+ n = __read_nocancel (fd, buf + half_buf, half_buf);
+ }
+ if (n >= 0)
+ n += half_buf;
+ }
+ __close_nocancel (fd);
+
+ if (__glibc_likely (n > 0))
+ {
+ char *mhz = memmem (buf, n, "timebase", 7);
+
+ if (__glibc_likely (mhz != NULL))
+ {
+ char *endp = buf + n;
+
+ /* Search for the beginning of the string. */
+ while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
+ ++mhz;
+
+ while (mhz < endp && *mhz != '\n')
+ {
+ if (*mhz >= '0' && *mhz <= '9')
+ {
+ result *= 10;
+ result += *mhz - '0';
+ }
+
+ ++mhz;
+ }
+ }
+ }
+#endif
+
+ return result;
}
weak_alias (__get_timebase_freq, __ppc_get_timebase_freq)
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c b/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
deleted file mode 100644
index 6838a77a769ddae8..0000000000000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* Get frequency of the system processor. sparc64 version.
- Copyright (C) 2001-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <sys/ioctl.h>
-#include <asm/openpromio.h>
-
-static hp_timing_t
-__get_clockfreq_via_cpuinfo (void)
-{
- hp_timing_t result;
- int fd;
-
- result = 0;
-
- fd = __open ("/proc/cpuinfo", O_RDONLY);
- if (fd != -1)
- {
- char buf[8192];
- ssize_t n;
-
- n = __read (fd, buf, sizeof buf);
- if (n > 0)
- {
- char *mhz = memmem (buf, n, "Cpu0ClkTck", 7);
-
- if (mhz != NULL)
- {
- char *endp = buf + n;
-
- /* Search for the beginning of the string. */
- while (mhz < endp
- && (*mhz < '0' || *mhz > '9')
- && (*mhz < 'a' || *mhz > 'f')
- && *mhz != '\n')
- ++mhz;
-
- while (mhz < endp && *mhz != '\n')
- {
- if ((*mhz >= '0' && *mhz <= '9') ||
- (*mhz >= 'a' && *mhz <= 'f'))
- {
- result <<= 4;
- if (*mhz >= '0' && *mhz <= '9')
- result += *mhz - '0';
- else
- result += (*mhz - 'a') + 10;
- }
- ++mhz;
- }
- }
- }
-
- __close (fd);
- }
-
- return result;
-}
-
-static hp_timing_t
-__get_clockfreq_via_proc_openprom (void)
-{
- hp_timing_t result;
- int obp_fd;
-
- result = 0;
-
- obp_fd = __open ("/proc/openprom", O_RDONLY);
- if (obp_fd != -1)
- {
- unsigned long int buf[4096 / sizeof (unsigned long int)];
- struct dirent64 *dirp = (struct dirent64 *) buf;
- ssize_t len;
-
- while ((len = __getdents64 (obp_fd, (char *) dirp, sizeof (buf))) > 0)
- {
- struct dirent64 *this_dirp = dirp;
-
- while (len > 0)
- {
- char node[strlen ("/proc/openprom/")
- + _D_ALLOC_NAMLEN (this_dirp)
- + strlen ("/clock-frequency")];
- char *prop;
- int fd;
-
- /* Note that
- strlen("/clock-frequency") > strlen("/device_type")
- */
- __stpcpy (prop = __stpcpy (__stpcpy (node, "/proc/openprom/"),
- this_dirp->d_name),
- "/device_type");
- fd = __open (node, O_RDONLY);
- if (fd != -1)
- {
- char type_string[128];
- int ret;
-
- ret = __read (fd, type_string, sizeof (type_string));
- if (ret > 0 && strncmp (type_string, "'cpu'", 5) == 0)
- {
- int clkfreq_fd;
-
- __stpcpy (prop, "/clock-frequency");
- clkfreq_fd = __open (node, O_RDONLY);
- if (clkfreq_fd != -1)
- {
- if (__read (clkfreq_fd, type_string,
- sizeof (type_string)) > 0)
- result = (hp_timing_t)
- strtoumax (type_string, NULL, 16);
- __close (clkfreq_fd);
- }
- }
- __close (fd);
- }
-
- if (result != 0)
- break;
-
- len -= this_dirp->d_reclen;
- this_dirp = (struct dirent64 *)
- ((char *) this_dirp + this_dirp->d_reclen);
- }
- if (result != 0)
- break;
- }
- __close (obp_fd);
- }
-
- return result;
-}
-
-static void set_obp_int (struct openpromio *op, int val)
-{
- char *cp = op->oprom_array;
- int *ip = (int *) cp;
-
- *ip = val;
-}
-
-static int get_obp_int (struct openpromio *op)
-{
- char *cp = op->oprom_array;
- int *ip = (int *) cp;
-
- return *ip;
-}
-
-static hp_timing_t
-__get_clockfreq_via_dev_openprom (void)
-{
- hp_timing_t result;
- int obp_dev_fd;
-
- result = 0;
-
- obp_dev_fd = __open ("/dev/openprom", O_RDONLY);
- if (obp_dev_fd != -1)
- {
- char obp_buf[8192];
- struct openpromio *obp_cmd = (struct openpromio *)obp_buf;
- int ret;
-
- obp_cmd->oprom_size =
- sizeof (obp_buf) - sizeof (unsigned int);
- set_obp_int (obp_cmd, 0);
- ret = __ioctl (obp_dev_fd, OPROMCHILD, (char *) obp_cmd);
- if (ret == 0)
- {
- int cur_node = get_obp_int (obp_cmd);
-
- while (cur_node != 0 && cur_node != -1)
- {
- obp_cmd->oprom_size = sizeof (obp_buf) - sizeof (unsigned int);
- strcpy (obp_cmd->oprom_array, "device_type");
- ret = __ioctl (obp_dev_fd, OPROMGETPROP, (char *) obp_cmd);
- if (ret == 0
- && strncmp (obp_cmd->oprom_array, "cpu", 3) == 0)
- {
- obp_cmd->oprom_size = (sizeof (obp_buf)
- - sizeof (unsigned int));
- strcpy (obp_cmd->oprom_array, "clock-frequency");
- ret = __ioctl (obp_dev_fd, OPROMGETPROP, (char *) obp_cmd);
- if (ret == 0)
- result = (hp_timing_t) get_obp_int (obp_cmd);
- }
- obp_cmd->oprom_size = sizeof (obp_buf) - sizeof (unsigned int);
- set_obp_int (obp_cmd, cur_node);
- ret = __ioctl (obp_dev_fd, OPROMNEXT, (char *) obp_cmd);
- if (ret < 0)
- break;
- cur_node = get_obp_int (obp_cmd);
- }
- }
- }
-
- return result;
-}
-
-hp_timing_t
-__get_clockfreq (void)
-{
- static hp_timing_t result;
-
- /* If this function was called before, we know the result. */
- if (result != 0)
- return result;
-
- /* We first read the information from the /proc/cpuinfo file.
- It contains at least one line like
- Cpu0ClkTick : 000000002cb41780
- We search for this line and convert the number in an integer. */
- result = __get_clockfreq_via_cpuinfo ();
- if (result != 0)
- return result;
-
- /* If that did not work, try to find an OpenPROM node
- with device_type equal to 'cpu' using /dev/openprom
- and fetch the clock-frequency property from there. */
- result = __get_clockfreq_via_dev_openprom ();
- if (result != 0)
- return result;
-
- /* Finally, try the same lookup as above but using /proc/openprom. */
- result = __get_clockfreq_via_proc_openprom ();
-
- return result;
-}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
commit 58e8f5fd2ba47b6dc47fd4d0a35e4175c7c87aaa
Author: Andreas Schwab <schwab@suse.de>
Date: Wed Oct 9 17:46:47 2019 +0200
ldconfig: handle .dynstr located in separate segment (bug 25087)
To determine the load offset of the DT_STRTAB section search for the
segment containing it, instead of using the load offset of the first
segment.
diff --git a/elf/readelflib.c b/elf/readelflib.c
index 5a1e2dc2dfa36599..8774e779f5abbfbb 100644
--- a/elf/readelflib.c
+++ b/elf/readelflib.c
@@ -45,7 +45,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
{
int i;
unsigned int j;
- ElfW(Addr) loadaddr;
unsigned int dynamic_addr;
size_t dynamic_size;
char *program_interpreter;
@@ -87,7 +86,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
libc5/libc6. */
*flag = FLAG_ELF;
- loadaddr = -1;
dynamic_addr = 0;
dynamic_size = 0;
program_interpreter = NULL;
@@ -98,11 +96,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
switch (segment->p_type)
{
- case PT_LOAD:
- if (loadaddr == (ElfW(Addr)) -1)
- loadaddr = segment->p_vaddr - segment->p_offset;
- break;
-
case PT_DYNAMIC:
if (dynamic_addr)
error (0, 0, _("more than one dynamic segment\n"));
@@ -176,11 +169,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
}
}
- if (loadaddr == (ElfW(Addr)) -1)
- {
- /* Very strange. */
- loadaddr = 0;
- }
/* Now we can read the dynamic sections. */
if (dynamic_size == 0)
@@ -197,7 +185,29 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
check_ptr (dyn_entry);
if (dyn_entry->d_tag == DT_STRTAB)
{
- dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr);
+ /* Find the file offset of the segment containing the dynamic
+ string table. */
+ ElfW(Off) loadoff = -1;
+ for (i = 0, segment = elf_pheader;
+ i < elf_header->e_phnum; i++, segment++)
+ {
+ if (segment->p_type == PT_LOAD
+ && dyn_entry->d_un.d_val >= segment->p_vaddr
+ && (dyn_entry->d_un.d_val - segment->p_vaddr
+ < segment->p_filesz))
+ {
+ loadoff = segment->p_vaddr - segment->p_offset;
+ break;
+ }
+ }
+ if (loadoff == (ElfW(Off)) -1)
+ {
+ /* Very strange. */
+ loadoff = 0;
+ }
+
+ dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val
+ - loadoff);
check_ptr (dynamic_strings);
break;
}

View File

@ -0,0 +1,103 @@
Partial backport without the new tst-dlopen-aout-pie test. The test
fails because the a self-dlopen of a PIE binary succeeds, as commit
23d2e5faf0bca6d9b31bef4aa162b95ee64cbfc6 ("elf: Self-dlopen failure
with explict loader invocation [BZ #24900]") has not been backported.
commit 77523d5e43cb5721c23855eb6045b0607a3b30a0
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Oct 4 21:23:51 2019 +0200
elf: Assign TLS modid later during dlopen [BZ #24930]
Commit a42faf59d6d9f82e5293a9ebcc26d9c9e562b12b ("Fix BZ #16634.")
attempted to fix a TLS modid consistency issue by adding additional
checks to the open_verify function. However, this is fragile
because open_verify cannot reliably predict whether
_dl_map_object_from_fd will later fail in the more complex cases
(such as memory allocation failures). Therefore, this commit
assigns the TLS modid as late as possible. At that point, the link
map pointer will eventually be passed to _dl_close, which will undo
the TLS modid assignment.
Reviewed-by: Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
diff --git a/elf/dl-load.c b/elf/dl-load.c
index bb839ef70ff46f37..b190b28e32e47391 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1134,27 +1134,21 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
offset. We will adjust it later. */
l->l_tls_initimage = (void *) ph->p_vaddr;
- /* If not loading the initial set of shared libraries,
- check whether we should permit loading a TLS segment. */
- if (__glibc_likely (l->l_type == lt_library)
- /* If GL(dl_tls_dtv_slotinfo_list) == NULL, then rtld.c did
- not set up TLS data structures, so don't use them now. */
- || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL))
- {
- /* Assign the next available module ID. */
- l->l_tls_modid = _dl_next_tls_modid ();
- break;
- }
+ /* l->l_tls_modid is assigned below, once there is no
+ possibility for failure. */
+ if (l->l_type != lt_library
+ && GL(dl_tls_dtv_slotinfo_list) == NULL)
+ {
#ifdef SHARED
- /* We are loading the executable itself when the dynamic
- linker was executed directly. The setup will happen
- later. Otherwise, the TLS data structures are already
- initialized, and we assigned a TLS modid above. */
- assert (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0);
+ /* We are loading the executable itself when the dynamic
+ linker was executed directly. The setup will happen
+ later. */
+ assert (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0);
#else
- assert (false && "TLS not initialized in static application");
+ assert (false && "TLS not initialized in static application");
#endif
+ }
break;
case PT_GNU_STACK:
@@ -1395,6 +1389,18 @@ cannot enable executable stack as shared object requires");
add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val));
+ /* _dl_close can only eventually undo the module ID assignment (via
+ remove_slotinfo) if this function returns a pointer to a link
+ map. Therefore, delay this step until all possibilities for
+ failure have been excluded. */
+ if (l->l_tls_blocksize > 0
+ && (__glibc_likely (l->l_type == lt_library)
+ /* If GL(dl_tls_dtv_slotinfo_list) == NULL, then rtld.c did
+ not set up TLS data structures, so don't use them now. */
+ || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL)))
+ /* Assign the next available module ID. */
+ l->l_tls_modid = _dl_next_tls_modid ();
+
#ifdef DL_AFTER_LOAD
DL_AFTER_LOAD (l);
#endif
@@ -1662,17 +1668,6 @@ open_verify (const char *name, int fd,
errstring = N_("only ET_DYN and ET_EXEC can be loaded");
goto call_lose;
}
- else if (__glibc_unlikely (ehdr->e_type == ET_EXEC
- && (mode & __RTLD_OPENEXEC) == 0))
- {
- /* BZ #16634. It is an error to dlopen ET_EXEC (unless
- __RTLD_OPENEXEC is explicitly set). We return error here
- so that code in _dl_map_object_from_fd does not try to set
- l_tls_modid for this module. */
-
- errstring = N_("cannot dynamically load executable");
- goto call_lose;
- }
else if (__glibc_unlikely (ehdr->e_phentsize != sizeof (ElfW(Phdr))))
{
errstring = N_("ELF file's phentsize not the expected size");

View File

@ -0,0 +1,33 @@
commit f55e312bcd6582b5ff68fdcc1781c7017796dc91
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Nov 28 14:42:11 2019 +0100
libio: Disable vtable validation for pre-2.1 interposed handles [BZ #25203]
Commit c402355dfa7807b8e0adb27c009135a7e2b9f1b0 ("libio: Disable
vtable validation in case of interposition [BZ #23313]") only covered
the interposable glibc 2.1 handles, in libio/stdfiles.c. The
parallel code in libio/oldstdfiles.c needs similar detection logic.
Fixes (again) commit db3476aff19b75c4fdefbe65fcd5f0a90588ba51
("libio: Implement vtable verification [BZ #20191]").
Change-Id: Ief6f9f17e91d1f7263421c56a7dc018f4f595c21
(cherry picked from commit cb61630ed712d033f54295f776967532d3f4b46a)
diff --git a/libio/oldstdfiles.c b/libio/oldstdfiles.c
index f3dda89004..9fe809bd68 100644
--- a/libio/oldstdfiles.c
+++ b/libio/oldstdfiles.c
@@ -87,6 +87,11 @@ _IO_check_libio (void)
stdout->_vtable_offset = stderr->_vtable_offset =
((int) sizeof (struct _IO_FILE)
- (int) sizeof (struct _IO_FILE_complete));
+
+ if (_IO_stdin_.vtable != &_IO_old_file_jumps
+ || _IO_stdout_.vtable != &_IO_old_file_jumps
+ || _IO_stderr_.vtable != &_IO_old_file_jumps)
+ IO_set_accept_foreign_vtables (&_IO_vtable_check);
}
}

View File

@ -0,0 +1,48 @@
From 34e75eb497941f829115e6e8f34e899575f4e342 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Fri, 18 Oct 2019 14:57:14 +0200
Subject: [PATCH 01/28] S390: Add new s390 platform z15.
The new IBM z15 is added to platform string array.
The macro _DL_PLATFORMS_COUNT is incremented.
(cherry picked from commit 2901743568452403849be7295c8732faa7732339)
---
sysdeps/s390/dl-procinfo.c | 4 ++--
sysdeps/s390/dl-procinfo.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c
index 6ea220a171..6d76d7d008 100644
--- a/sysdeps/s390/dl-procinfo.c
+++ b/sysdeps/s390/dl-procinfo.c
@@ -63,11 +63,11 @@ PROCINFO_CLASS const char _dl_s390_cap_flags[19][9]
#if !defined PROCINFO_DECL && defined SHARED
._dl_s390_platforms
#else
-PROCINFO_CLASS const char _dl_s390_platforms[9][7]
+PROCINFO_CLASS const char _dl_s390_platforms[10][7]
#endif
#ifndef PROCINFO_DECL
= {
- "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14"
+ "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15"
}
#endif
#if !defined SHARED || defined PROCINFO_DECL
diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
index d03c69fffd..b367bbe8ce 100644
--- a/sysdeps/s390/dl-procinfo.h
+++ b/sysdeps/s390/dl-procinfo.h
@@ -23,7 +23,7 @@
#define _DL_HWCAP_COUNT 19
-#define _DL_PLATFORMS_COUNT 9
+#define _DL_PLATFORMS_COUNT 10
/* The kernel provides up to 32 capability bits with elf_hwcap. */
#define _DL_FIRST_PLATFORM 32
--
2.18.2

View File

@ -0,0 +1,159 @@
From 73f98d03d2cde34255c0a39ef18902bffdce0185 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:14 +0100
Subject: [PATCH 02/28] Always use wordsize-64 version of s_rint.c.
This patch replaces s_rint.c in sysdeps/dbl-64 with the one in
sysdeps/dbl-64/wordsize-64 and removes the latter one.
The code is not changed except changes in code style.
Also adjusted the include path in x86_64 file.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit ab48bdd098a675dddb360faafc497a61c4bd4334)
---
sysdeps/ieee754/dbl-64/s_rint.c | 32 ++++++------
sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c | 57 ---------------------
sysdeps/x86_64/fpu/multiarch/s_rint-c.c | 2 +-
3 files changed, 17 insertions(+), 74 deletions(-)
delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c
diff --git a/sysdeps/ieee754/dbl-64/s_rint.c b/sysdeps/ieee754/dbl-64/s_rint.c
index cb0f5ca298..7f3dc87b96 100644
--- a/sysdeps/ieee754/dbl-64/s_rint.c
+++ b/sysdeps/ieee754/dbl-64/s_rint.c
@@ -1,4 +1,3 @@
-/* @(#)s_rint.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
@@ -25,38 +24,39 @@
#include <libm-alias-double.h>
static const double
- TWO52[2] = {
- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+TWO52[2] = {
+ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
};
double
__rint (double x)
{
- int32_t i0, j0, sx;
- double w, t;
- GET_HIGH_WORD (i0, x);
- sx = (i0 >> 31) & 1;
- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
+ int64_t i0, sx;
+ int32_t j0;
+ EXTRACT_WORDS64 (i0, x);
+ sx = (i0 >> 63) & 1;
+ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
if (j0 < 52)
{
if (j0 < 0)
{
- w = TWO52[sx] + x;
- t = w - TWO52[sx];
- GET_HIGH_WORD (i0, t);
- SET_HIGH_WORD (t, (i0 & 0x7fffffff) | (sx << 31));
+ double w = TWO52[sx] + x;
+ double t = w - TWO52[sx];
+ EXTRACT_WORDS64 (i0, t);
+ INSERT_WORDS64 (t, (i0 & UINT64_C (0x7fffffffffffffff))
+ | (sx << 63));
return t;
}
}
else
{
if (j0 == 0x400)
- return x + x; /* inf or NaN */
+ return x + x; /* inf or NaN */
else
- return x; /* x is integral */
+ return x; /* x is integral */
}
- w = TWO52[sx] + x;
+ double w = TWO52[sx] + x;
return w - TWO52[sx];
}
#ifndef __rint
diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c
deleted file mode 100644
index 622e479c5f..0000000000
--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-/*
- * rint(x)
- * Return x rounded to integral value according to the prevailing
- * rounding mode.
- * Method:
- * Using floating addition.
- * Exception:
- * Inexact flag raised if x not equal to rint(x).
- */
-
-#include <math.h>
-#include <math_private.h>
-#include <libm-alias-double.h>
-
-static const double
-TWO52[2]={
- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
-};
-
-double
-__rint(double x)
-{
- int64_t i0,sx;
- int32_t j0;
- EXTRACT_WORDS64(i0,x);
- sx = (i0>>63)&1;
- j0 = ((i0>>52)&0x7ff)-0x3ff;
- if(j0<52) {
- if(j0<0) {
- double w = TWO52[sx]+x;
- double t = w-TWO52[sx];
- EXTRACT_WORDS64(i0,t);
- INSERT_WORDS64(t,(i0&UINT64_C(0x7fffffffffffffff))|(sx<<63));
- return t;
- }
- } else {
- if(j0==0x400) return x+x; /* inf or NaN */
- else return x; /* x is integral */
- }
- double w = TWO52[sx]+x;
- return w-TWO52[sx];
-}
-#ifndef __rint
-libm_alias_double (__rint, rint)
-#endif
diff --git a/sysdeps/x86_64/fpu/multiarch/s_rint-c.c b/sysdeps/x86_64/fpu/multiarch/s_rint-c.c
index 162a630ff9..b010150f52 100644
--- a/sysdeps/x86_64/fpu/multiarch/s_rint-c.c
+++ b/sysdeps/x86_64/fpu/multiarch/s_rint-c.c
@@ -1,3 +1,3 @@
#undef __rint
#define __rint __rint_c
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c>
+#include <sysdeps/ieee754/dbl-64/s_rint.c>
--
2.18.2

View File

@ -0,0 +1,257 @@
From 7741c9c7f566d09f57db45df9377ac497f6232a5 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:15 +0100
Subject: [PATCH 03/28] Always use wordsize-64 version of s_floor.c.
This patch replaces s_floor.c in sysdeps/dbl-64 with the one in
sysdeps/dbl-64/wordsize-64 and removes the latter one.
The code is not changed except changes in code style.
Also adjusted the include path in x86_64 and sparc64 files.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 95b0c2c431510013eb2f7385fc078ee2498f83bf)
Note: glibc 2.28 had no NO_MATH_REDIRECT in wordsize-64 version.
---
sysdeps/ieee754/dbl-64/s_floor.c | 92 +++++++++----------
sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c | 71 --------------
.../sparc64/fpu/multiarch/s_floor-generic.c | 2 +-
.../sparc64/fpu/multiarch/s_floor-vis3.c | 2 +-
sysdeps/x86_64/fpu/multiarch/s_floor-c.c | 2 +-
5 files changed, 45 insertions(+), 124 deletions(-)
delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c
diff --git a/sysdeps/ieee754/dbl-64/s_floor.c b/sysdeps/ieee754/dbl-64/s_floor.c
index f27c6f3ad2..b551a1aafa 100644
--- a/sysdeps/ieee754/dbl-64/s_floor.c
+++ b/sysdeps/ieee754/dbl-64/s_floor.c
@@ -1,4 +1,24 @@
-/* @(#)s_floor.c 5.1 93/09/24 */
+/* Round double to integer away from zero.
+ Copyright (C) 2011-2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 2011.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Based on a version which carries the following copyright: */
+
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
@@ -10,6 +30,11 @@
* ====================================================
*/
+#include <math.h>
+#include <math_private.h>
+#include <stdint.h>
+#include <libm-alias-double.h>
+
/*
* floor(x)
* Return x rounded toward -inf to integral value
@@ -17,68 +42,35 @@
* Bit twiddling.
*/
-#include <math.h>
-#include <math_private.h>
-#include <libm-alias-double.h>
-
double
__floor (double x)
{
- int32_t i0, i1, j0;
- uint32_t i, j;
- EXTRACT_WORDS (i0, i1, x);
- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
- if (j0 < 20)
+ int64_t i0;
+ EXTRACT_WORDS64 (i0, x);
+ int32_t j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
+ if (__glibc_likely (j0 < 52))
{
if (j0 < 0)
{
- /* return 0*sign(x) if |x|<1 */
+ /* return 0 * sign (x) if |x| < 1 */
if (i0 >= 0)
- {
- i0 = i1 = 0;
- }
- else if (((i0 & 0x7fffffff) | i1) != 0)
- {
- i0 = 0xbff00000; i1 = 0;
- }
+ i0 = 0;
+ else if ((i0 & 0x7fffffffffffffffl) != 0)
+ i0 = 0xbff0000000000000l;
}
else
{
- i = (0x000fffff) >> j0;
- if (((i0 & i) | i1) == 0)
- return x; /* x is integral */
+ uint64_t i = 0x000fffffffffffffl >> j0;
+ if ((i0 & i) == 0)
+ return x; /* x is integral */
if (i0 < 0)
- i0 += (0x00100000) >> j0;
- i0 &= (~i); i1 = 0;
- }
- }
- else if (j0 > 51)
- {
- if (j0 == 0x400)
- return x + x; /* inf or NaN */
- else
- return x; /* x is integral */
- }
- else
- {
- i = ((uint32_t) (0xffffffff)) >> (j0 - 20);
- if ((i1 & i) == 0)
- return x; /* x is integral */
- if (i0 < 0)
- {
- if (j0 == 20)
- i0 += 1;
- else
- {
- j = i1 + (1 << (52 - j0));
- if (j < i1)
- i0 += 1; /* got a carry */
- i1 = j;
- }
+ i0 += 0x0010000000000000l >> j0;
+ i0 &= ~i;
}
- i1 &= (~i);
+ INSERT_WORDS64 (x, i0);
}
- INSERT_WORDS (x, i0, i1);
+ else if (j0 == 0x400)
+ return x + x; /* inf or NaN */
return x;
}
#ifndef __floor
diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c
deleted file mode 100644
index f7e0a77ec3..0000000000
--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Round double to integer away from zero.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 2011.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-/* Based on a version which carries the following copyright: */
-
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-#include <math.h>
-#include <math_private.h>
-#include <stdint.h>
-#include <libm-alias-double.h>
-
-/*
- * floor(x)
- * Return x rounded toward -inf to integral value
- * Method:
- * Bit twiddling.
- */
-
-
-double
-__floor (double x)
-{
- int64_t i0;
- EXTRACT_WORDS64(i0,x);
- int32_t j0 = ((i0>>52)&0x7ff)-0x3ff;
- if(__builtin_expect(j0<52, 1)) {
- if(j0<0) {
- /* return 0*sign(x) if |x|<1 */
- if(i0>=0) {i0=0;}
- else if((i0&0x7fffffffffffffffl)!=0)
- { i0=0xbff0000000000000l;}
- } else {
- uint64_t i = (0x000fffffffffffffl)>>j0;
- if((i0&i)==0) return x; /* x is integral */
- if(i0<0) i0 += (0x0010000000000000l)>>j0;
- i0 &= (~i);
- }
- INSERT_WORDS64(x,i0);
- } else if (j0==0x400)
- return x+x; /* inf or NaN */
- return x;
-}
-#ifndef __floor
-libm_alias_double (__floor, floor)
-#endif
diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-generic.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-generic.c
index 0f3361a9fb..c92b600df1 100644
--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-generic.c
+++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-generic.c
@@ -1,2 +1,2 @@
#define __floor __floor_generic
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c>
+#include <sysdeps/ieee754/dbl-64/s_floor.c>
diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-vis3.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-vis3.c
index d9974161b0..35564b9139 100644
--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-vis3.c
+++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-vis3.c
@@ -20,4 +20,4 @@
#define __floor __floor_vis3
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c>
+#include <sysdeps/ieee754/dbl-64/s_floor.c>
diff --git a/sysdeps/x86_64/fpu/multiarch/s_floor-c.c b/sysdeps/x86_64/fpu/multiarch/s_floor-c.c
index 68733b69ef..002d12247e 100644
--- a/sysdeps/x86_64/fpu/multiarch/s_floor-c.c
+++ b/sysdeps/x86_64/fpu/multiarch/s_floor-c.c
@@ -1,3 +1,3 @@
#undef __floor
#define __floor __floor_c
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c>
+#include <sysdeps/ieee754/dbl-64/s_floor.c>
--
2.18.2

View File

@ -0,0 +1,192 @@
From d3833cb69c7ff42ac8df68ed7b646c98c3a32eb8 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:16 +0100
Subject: [PATCH 04/28] Always use wordsize-64 version of s_ceil.c.
This patch replaces s_ceil.c in sysdeps/dbl-64 with the one in
sysdeps/dbl-64/wordsize-64 and removes the latter one.
The code is not changed except changes in code style.
Also adjusted the include path in x86_64 and sparc64 files.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 9f234eafe8698fd9a441ca2309a299d0bd771156)
---
sysdeps/ieee754/dbl-64/s_ceil.c | 59 ++++++-------------
sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c | 51 ----------------
.../sparc64/fpu/multiarch/s_ceil-generic.c | 2 +-
.../sparc/sparc64/fpu/multiarch/s_ceil-vis3.c | 2 +-
sysdeps/x86_64/fpu/multiarch/s_ceil-c.c | 2 +-
5 files changed, 21 insertions(+), 95 deletions(-)
delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c
diff --git a/sysdeps/ieee754/dbl-64/s_ceil.c b/sysdeps/ieee754/dbl-64/s_ceil.c
index 5a7434c737..3becdfc515 100644
--- a/sysdeps/ieee754/dbl-64/s_ceil.c
+++ b/sysdeps/ieee754/dbl-64/s_ceil.c
@@ -24,61 +24,38 @@
double
__ceil (double x)
{
- int32_t i0, i1, j0;
- uint32_t i, j;
- EXTRACT_WORDS (i0, i1, x);
- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
- if (j0 < 20)
+ int64_t i0, i;
+ int32_t j0;
+ EXTRACT_WORDS64 (i0, x);
+ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
+ if (j0 <= 51)
{
if (j0 < 0)
{
- /* return 0*sign(x) if |x|<1 */
+ /* return 0 * sign(x) if |x| < 1 */
if (i0 < 0)
- {
- i0 = 0x80000000; i1 = 0;
- }
- else if ((i0 | i1) != 0)
- {
- i0 = 0x3ff00000; i1 = 0;
- }
+ i0 = INT64_C (0x8000000000000000);
+ else if (i0 != 0)
+ i0 = INT64_C (0x3ff0000000000000);
}
else
{
- i = (0x000fffff) >> j0;
- if (((i0 & i) | i1) == 0)
- return x; /* x is integral */
+ i = INT64_C (0x000fffffffffffff) >> j0;
+ if ((i0 & i) == 0)
+ return x; /* x is integral */
if (i0 > 0)
- i0 += (0x00100000) >> j0;
- i0 &= (~i); i1 = 0;
+ i0 += UINT64_C (0x0010000000000000) >> j0;
+ i0 &= ~i;
}
}
- else if (j0 > 51)
+ else
{
if (j0 == 0x400)
- return x + x; /* inf or NaN */
+ return x + x; /* inf or NaN */
else
- return x; /* x is integral */
- }
- else
- {
- i = ((uint32_t) (0xffffffff)) >> (j0 - 20);
- if ((i1 & i) == 0)
- return x; /* x is integral */
- if (i0 > 0)
- {
- if (j0 == 20)
- i0 += 1;
- else
- {
- j = i1 + (1 << (52 - j0));
- if (j < i1)
- i0 += 1; /* got a carry */
- i1 = j;
- }
- }
- i1 &= (~i);
+ return x; /* x is integral */
}
- INSERT_WORDS (x, i0, i1);
+ INSERT_WORDS64 (x, i0);
return x;
}
#ifndef __ceil
diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c
deleted file mode 100644
index b99829d2b0..0000000000
--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* @(#)s_ceil.c 5.1 93/09/24 */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-/*
- * ceil(x)
- * Return x rounded toward -inf to integral value
- * Method:
- * Bit twiddling.
- */
-
-#include <math.h>
-#include <math_private.h>
-#include <libm-alias-double.h>
-
-double
-__ceil(double x)
-{
- int64_t i0,i;
- int32_t j0;
- EXTRACT_WORDS64(i0,x);
- j0 = ((i0>>52)&0x7ff)-0x3ff;
- if(j0<=51) {
- if(j0<0) {
- /* return 0*sign(x) if |x|<1 */
- if(i0<0) {i0=INT64_C(0x8000000000000000);}
- else if(i0!=0) { i0=INT64_C(0x3ff0000000000000);}
- } else {
- i = INT64_C(0x000fffffffffffff)>>j0;
- if((i0&i)==0) return x; /* x is integral */
- if(i0>0) i0 += UINT64_C(0x0010000000000000)>>j0;
- i0 &= (~i);
- }
- } else {
- if(j0==0x400) return x+x; /* inf or NaN */
- else return x; /* x is integral */
- }
- INSERT_WORDS64(x,i0);
- return x;
-}
-#ifndef __ceil
-libm_alias_double (__ceil, ceil)
-#endif
diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-generic.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-generic.c
index febea745e1..80f68b6766 100644
--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-generic.c
+++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-generic.c
@@ -1,2 +1,2 @@
#define __ceil __ceil_generic
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c>
+#include <sysdeps/ieee754/dbl-64/s_ceil.c>
diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-vis3.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-vis3.c
index a03a0090f0..59822e0f8c 100644
--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-vis3.c
+++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-vis3.c
@@ -20,4 +20,4 @@
#define __ceil __ceil_vis3
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c>
+#include <sysdeps/ieee754/dbl-64/s_ceil.c>
diff --git a/sysdeps/x86_64/fpu/multiarch/s_ceil-c.c b/sysdeps/x86_64/fpu/multiarch/s_ceil-c.c
index 6a5ea3ff27..ada28baa1a 100644
--- a/sysdeps/x86_64/fpu/multiarch/s_ceil-c.c
+++ b/sysdeps/x86_64/fpu/multiarch/s_ceil-c.c
@@ -1,2 +1,2 @@
#define __ceil __ceil_c
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c>
+#include <sysdeps/ieee754/dbl-64/s_ceil.c>
--
2.18.2

View File

@ -0,0 +1,157 @@
From e8f1c08a49d313b210ed4104c20646c105bab6a4 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:17 +0100
Subject: [PATCH 05/28] Always use wordsize-64 version of s_trunc.c.
This patch replaces s_trunc.c in sysdeps/dbl-64 with the one in
sysdeps/dbl-64/wordsize-64 and removes the latter one.
The code is not changed except changes in code style.
Also adjusted the include path in x86_64 and sparc64 files.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 1c94bf0f0a50ce66c808e2ea9b7e417785798b73)
---
sysdeps/ieee754/dbl-64/s_trunc.c | 25 ++++-----
sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c | 54 -------------------
.../sparc64/fpu/multiarch/s_trunc-generic.c | 2 +-
.../sparc64/fpu/multiarch/s_trunc-vis3.c | 2 +-
sysdeps/x86_64/fpu/multiarch/s_trunc-c.c | 2 +-
5 files changed, 13 insertions(+), 72 deletions(-)
delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c
diff --git a/sysdeps/ieee754/dbl-64/s_trunc.c b/sysdeps/ieee754/dbl-64/s_trunc.c
index 6ffabb410a..38bb33d337 100644
--- a/sysdeps/ieee754/dbl-64/s_trunc.c
+++ b/sysdeps/ieee754/dbl-64/s_trunc.c
@@ -26,31 +26,26 @@
double
__trunc (double x)
{
- int32_t i0, j0;
- uint32_t i1;
- int sx;
-
- EXTRACT_WORDS (i0, i1, x);
- sx = i0 & 0x80000000;
- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
- if (j0 < 20)
+ int64_t i0, j0;
+ int64_t sx;
+
+ EXTRACT_WORDS64 (i0, x);
+ sx = i0 & UINT64_C (0x8000000000000000);
+ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
+ if (j0 < 52)
{
if (j0 < 0)
/* The magnitude of the number is < 1 so the result is +-0. */
- INSERT_WORDS (x, sx, 0);
+ INSERT_WORDS64 (x, sx);
else
- INSERT_WORDS (x, sx | (i0 & ~(0x000fffff >> j0)), 0);
+ INSERT_WORDS64 (x, sx | (i0 & ~(UINT64_C (0x000fffffffffffff) >> j0)));
}
- else if (j0 > 51)
+ else
{
if (j0 == 0x400)
/* x is inf or NaN. */
return x + x;
}
- else
- {
- INSERT_WORDS (x, i0, i1 & ~(0xffffffffu >> (j0 - 20)));
- }
return x;
}
diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c
deleted file mode 100644
index 19a09b894e..0000000000
--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Truncate argument to nearest integral value not larger than the argument.
- Copyright (C) 1997-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for 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 <math.h>
-
-#include <math_private.h>
-#include <libm-alias-double.h>
-
-
-double
-__trunc (double x)
-{
- int64_t i0, j0;
- int64_t sx;
-
- EXTRACT_WORDS64 (i0, x);
- sx = i0 & UINT64_C(0x8000000000000000);
- j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
- if (j0 < 52)
- {
- if (j0 < 0)
- /* The magnitude of the number is < 1 so the result is +-0. */
- INSERT_WORDS64 (x, sx);
- else
- INSERT_WORDS64 (x, sx | (i0 & ~(UINT64_C(0x000fffffffffffff) >> j0)));
- }
- else
- {
- if (j0 == 0x400)
- /* x is inf or NaN. */
- return x + x;
- }
-
- return x;
-}
-#ifndef __trunc
-libm_alias_double (__trunc, trunc)
-#endif
diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-generic.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-generic.c
index 00abd2a643..c198ebb3d5 100644
--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-generic.c
+++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-generic.c
@@ -1,2 +1,2 @@
#define __trunc __trunc_generic
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c>
+#include <sysdeps/ieee754/dbl-64/s_trunc.c>
diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-vis3.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-vis3.c
index a89916ba89..766bb22629 100644
--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-vis3.c
+++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-vis3.c
@@ -20,4 +20,4 @@
#define __trunc __trunc_vis3
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c>
+#include <sysdeps/ieee754/dbl-64/s_trunc.c>
diff --git a/sysdeps/x86_64/fpu/multiarch/s_trunc-c.c b/sysdeps/x86_64/fpu/multiarch/s_trunc-c.c
index 6204ae3c77..8aa499fbb8 100644
--- a/sysdeps/x86_64/fpu/multiarch/s_trunc-c.c
+++ b/sysdeps/x86_64/fpu/multiarch/s_trunc-c.c
@@ -1,2 +1,2 @@
#define __trunc __trunc_c
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c>
+#include <sysdeps/ieee754/dbl-64/s_trunc.c>
--
2.18.2

View File

@ -0,0 +1,167 @@
From 577943dac79a5657bdfe51e06e289eb2473c3d2e Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:17 +0100
Subject: [PATCH 06/28] Always use wordsize-64 version of s_round.c.
This patch replaces s_round.c in sysdeps/dbl-64 with the one in
sysdeps/dbl-64/wordsize-64 and removes the latter one.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 36e9acbd5cb2c330c0d53195db4a0ee31f2c3097)
---
sysdeps/ieee754/dbl-64/s_round.c | 39 ++++--------
sysdeps/ieee754/dbl-64/wordsize-64/s_round.c | 65 --------------------
2 files changed, 12 insertions(+), 92 deletions(-)
delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_round.c
diff --git a/sysdeps/ieee754/dbl-64/s_round.c b/sysdeps/ieee754/dbl-64/s_round.c
index fa9e83196e..bf9922edca 100644
--- a/sysdeps/ieee754/dbl-64/s_round.c
+++ b/sysdeps/ieee754/dbl-64/s_round.c
@@ -21,38 +21,36 @@
#include <math_private.h>
#include <libm-alias-double.h>
+#include <stdint.h>
double
__round (double x)
{
- int32_t i0, j0;
- uint32_t i1;
+ int64_t i0, j0;
- EXTRACT_WORDS (i0, i1, x);
- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
- if (j0 < 20)
+ EXTRACT_WORDS64 (i0, x);
+ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
+ if (__glibc_likely (j0 < 52))
{
if (j0 < 0)
{
- i0 &= 0x80000000;
+ i0 &= UINT64_C (0x8000000000000000);
if (j0 == -1)
- i0 |= 0x3ff00000;
- i1 = 0;
+ i0 |= UINT64_C (0x3ff0000000000000);
}
else
{
- uint32_t i = 0x000fffff >> j0;
- if (((i0 & i) | i1) == 0)
+ uint64_t i = UINT64_C (0x000fffffffffffff) >> j0;
+ if ((i0 & i) == 0)
/* X is integral. */
return x;
- i0 += 0x00080000 >> j0;
+ i0 += UINT64_C (0x0008000000000000) >> j0;
i0 &= ~i;
- i1 = 0;
}
}
- else if (j0 > 51)
+ else
{
if (j0 == 0x400)
/* Inf or NaN. */
@@ -60,21 +58,8 @@ __round (double x)
else
return x;
}
- else
- {
- uint32_t i = 0xffffffff >> (j0 - 20);
- if ((i1 & i) == 0)
- /* X is integral. */
- return x;
-
- uint32_t j = i1 + (1 << (51 - j0));
- if (j < i1)
- i0 += 1;
- i1 = j;
- i1 &= ~i;
- }
- INSERT_WORDS (x, i0, i1);
+ INSERT_WORDS64 (x, i0);
return x;
}
libm_alias_double (__round, round)
diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c
deleted file mode 100644
index 3323621ce3..0000000000
--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Round double to integer away from zero.
- Copyright (C) 1997-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for 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 <math.h>
-
-#include <math_private.h>
-#include <libm-alias-double.h>
-#include <stdint.h>
-
-
-double
-__round (double x)
-{
- int64_t i0, j0;
-
- EXTRACT_WORDS64 (i0, x);
- j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
- if (__glibc_likely (j0 < 52))
- {
- if (j0 < 0)
- {
- i0 &= UINT64_C(0x8000000000000000);
- if (j0 == -1)
- i0 |= UINT64_C(0x3ff0000000000000);
- }
- else
- {
- uint64_t i = UINT64_C(0x000fffffffffffff) >> j0;
- if ((i0 & i) == 0)
- /* X is integral. */
- return x;
-
- i0 += UINT64_C(0x0008000000000000) >> j0;
- i0 &= ~i;
- }
- }
- else
- {
- if (j0 == 0x400)
- /* Inf or NaN. */
- return x + x;
- else
- return x;
- }
-
- INSERT_WORDS64 (x, i0);
- return x;
-}
-libm_alias_double (__round, round)
--
2.18.2

View File

@ -0,0 +1,255 @@
From 735a36828f349419379f15e942bfdf0c532d58eb Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:18 +0100
Subject: [PATCH 07/28] Use GCC builtins for nearbyint functions if desired.
This patch is using the corresponding GCC builtin for nearbyintf, nearbyint,
nearbintl and nearbyintf128 if the USE_FUNCTION_BUILTIN macros are defined to one
in math-use-builtins.h.
This is the case for s390 if build with at least --march=z196 --mzarch.
Otherwise the generic implementation is used. The code of the generic
implementation is not changed.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit ae3577f607b50bf3ce9b0877e43ad2508c9da61b)
Note: The TWO52 constants are now located in # ! USE_NEARBYINT_BUILTIN
---
sysdeps/generic/math-use-builtins.h | 29 ++++++++++++
sysdeps/ieee754/dbl-64/s_nearbyint.c | 17 ++++---
sysdeps/ieee754/float128/float128_private.h | 4 ++
sysdeps/ieee754/flt-32/s_nearbyintf.c | 17 ++++---
sysdeps/ieee754/ldbl-128/s_nearbyintl.c | 17 ++++---
sysdeps/s390/fpu/math-use-builtins.h | 49 +++++++++++++++++++++
6 files changed, 115 insertions(+), 18 deletions(-)
create mode 100644 sysdeps/generic/math-use-builtins.h
create mode 100644 sysdeps/s390/fpu/math-use-builtins.h
diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h
new file mode 100644
index 0000000000..e12490ed41
--- /dev/null
+++ b/sysdeps/generic/math-use-builtins.h
@@ -0,0 +1,29 @@
+/* Using math gcc builtins instead of generic implementation. Generic version.
+ Copyright (C) 2019 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 MATH_USE_BUILTINS_H
+#define MATH_USE_BUILTINS_H 1
+
+/* Define these macros to 1 to use __builtin_xyz instead of the
+ generic implementation. */
+#define USE_NEARBYINT_BUILTIN 0
+#define USE_NEARBYINTF_BUILTIN 0
+#define USE_NEARBYINTL_BUILTIN 0
+#define USE_NEARBYINTF128_BUILTIN 0
+
+#endif /* math-use-builtins.h */
diff --git a/sysdeps/ieee754/dbl-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/s_nearbyint.c
index 903121d456..6b9f44dc8d 100644
--- a/sysdeps/ieee754/dbl-64/s_nearbyint.c
+++ b/sysdeps/ieee754/dbl-64/s_nearbyint.c
@@ -29,16 +29,20 @@ static char rcsid[] = "$NetBSD: s_rint.c,v 1.8 1995/05/10 20:48:04 jtc Exp $";
#include <math-barriers.h>
#include <math_private.h>
#include <libm-alias-double.h>
-
-static const double
- TWO52[2] = {
- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
-};
+#include <math-use-builtins.h>
double
__nearbyint (double x)
{
+#if USE_NEARBYINT_BUILTIN
+ return __builtin_nearbyint (x);
+#else
+ /* Use generic implementation. */
+ static const double
+ TWO52[2] = {
+ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+ };
fenv_t env;
int32_t i0, j0, sx;
double w, t;
@@ -72,5 +76,6 @@ __nearbyint (double x)
math_force_eval (t);
libc_fesetenv (&env);
return t;
+#endif /* ! USE_NEARBYINT_BUILTIN */
}
libm_alias_double (__nearbyint, nearbyint)
diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h
index 9dd15601e6..0bf6e8dee2 100644
--- a/sysdeps/ieee754/float128/float128_private.h
+++ b/sysdeps/ieee754/float128/float128_private.h
@@ -138,6 +138,9 @@
#undef libm_alias_double_ldouble
#define libm_alias_double_ldouble(func) libm_alias_float64_float128 (func)
+#include <math-use-builtins.h>
+#undef USE_NEARBYINTL_BUILTIN
+#define USE_NEARBYINTL_BUILTIN USE_NEARBYINTF128_BUILTIN
/* IEEE function renames. */
#define __ieee754_acoshl __ieee754_acoshf128
@@ -339,6 +342,7 @@
/* Builtin renames. */
#define __builtin_copysignl __builtin_copysignf128
#define __builtin_signbitl __builtin_signbit
+#define __builtin_nearbyintl __builtin_nearbyintf128
/* Get the constant suffix from bits/floatn-compat.h. */
#define L(x) __f128 (x)
diff --git a/sysdeps/ieee754/flt-32/s_nearbyintf.c b/sysdeps/ieee754/flt-32/s_nearbyintf.c
index 4dfe491f27..438dcae8cc 100644
--- a/sysdeps/ieee754/flt-32/s_nearbyintf.c
+++ b/sysdeps/ieee754/flt-32/s_nearbyintf.c
@@ -20,16 +20,20 @@
#include <math-barriers.h>
#include <math_private.h>
#include <libm-alias-float.h>
-
-static const float
-TWO23[2]={
- 8.3886080000e+06, /* 0x4b000000 */
- -8.3886080000e+06, /* 0xcb000000 */
-};
+#include <math-use-builtins.h>
float
__nearbyintf(float x)
{
+#if USE_NEARBYINTF_BUILTIN
+ return __builtin_nearbyintf (x);
+#else
+ /* Use generic implementation. */
+ static const float
+ TWO23[2] = {
+ 8.3886080000e+06, /* 0x4b000000 */
+ -8.3886080000e+06, /* 0xcb000000 */
+ };
fenv_t env;
int32_t i0,j0,sx;
float w,t;
@@ -57,5 +61,6 @@ __nearbyintf(float x)
math_force_eval (t);
libc_fesetenvf (&env);
return t;
+#endif /* ! USE_NEARBYINT_BUILTIN */
}
libm_alias_float (__nearbyint, nearbyint)
diff --git a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
index f044cb4334..a4ad8e82e5 100644
--- a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
+++ b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
@@ -28,15 +28,19 @@
#include <math-barriers.h>
#include <math_private.h>
#include <libm-alias-ldouble.h>
-
-static const _Float128
-TWO112[2]={
- L(5.19229685853482762853049632922009600E+33), /* 0x406F000000000000, 0 */
- L(-5.19229685853482762853049632922009600E+33) /* 0xC06F000000000000, 0 */
-};
+#include <math-use-builtins.h>
_Float128 __nearbyintl(_Float128 x)
{
+#if USE_NEARBYINTL_BUILTIN
+ return __builtin_nearbyintl (x);
+#else
+ /* Use generic implementation. */
+ static const _Float128
+ TWO112[2] = {
+ L(5.19229685853482762853049632922009600E+33), /* 0x406F000000000000, 0 */
+ L(-5.19229685853482762853049632922009600E+33) /* 0xC06F000000000000, 0 */
+ };
fenv_t env;
int64_t i0,j0,sx;
uint64_t i1 __attribute__ ((unused));
@@ -65,5 +69,6 @@ _Float128 __nearbyintl(_Float128 x)
math_force_eval (t);
fesetenv (&env);
return t;
+#endif /* ! USE_NEARBYINTL_BUILTIN */
}
libm_alias_ldouble (__nearbyint, nearbyint)
diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h
new file mode 100644
index 0000000000..7abbfb3b50
--- /dev/null
+++ b/sysdeps/s390/fpu/math-use-builtins.h
@@ -0,0 +1,49 @@
+/* Using math gcc builtins instead of generic implementation. s390/s390x version.
+ Copyright (C) 2019 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 MATH_USE_BUILTINS_S390_H
+#define MATH_USE_BUILTINS_S390_H 1
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+
+# include <features.h> /* For __GNUC_PREREQ. */
+
+/* GCC emits the z196 zarch "load fp integer" instructions for these
+ builtins if build with at least --march=z196 -mzarch. Otherwise a
+ function call to libc is emitted. */
+# define USE_NEARBYINT_BUILTIN 1
+# define USE_NEARBYINTF_BUILTIN 1
+# define USE_NEARBYINTL_BUILTIN 1
+
+# if __GNUC_PREREQ (8, 0)
+# define USE_NEARBYINTF128_BUILTIN 1
+# else
+# define USE_NEARBYINTF128_BUILTIN 0
+# endif
+
+#else
+
+/* Disable the builtins if we do not have the z196 zarch instructions. */
+# define USE_NEARBYINT_BUILTIN 0
+# define USE_NEARBYINTF_BUILTIN 0
+# define USE_NEARBYINTL_BUILTIN 0
+# define USE_NEARBYINTF128_BUILTIN 0
+
+#endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */
+
+#endif /* math-use-builtins.h */
--
2.18.2

View File

@ -0,0 +1,210 @@
From d37e99de7ab1cd8c3d427f74bf8ceb5774795fe5 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:20 +0100
Subject: [PATCH 08/28] Use GCC builtins for rint functions if desired.
This patch is using the corresponding GCC builtin for rintf, rint,
rintl and rintf128 if the USE_FUNCTION_BUILTIN macros are defined to one
in math-use-builtins.h.
This is the case for s390 if build with at least --march=z196 --mzarch.
Otherwise the generic implementation is used. The code of the generic
implementation is not changed.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit a2a9b004297b777758420c952cb6eea5985d37fe)
---
sysdeps/generic/math-use-builtins.h | 5 +++++
sysdeps/ieee754/dbl-64/s_rint.c | 17 +++++++++++------
sysdeps/ieee754/float128/float128_private.h | 3 +++
sysdeps/ieee754/flt-32/s_rintf.c | 17 +++++++++++------
sysdeps/ieee754/ldbl-128/s_rintl.c | 17 +++++++++++------
sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++
6 files changed, 52 insertions(+), 18 deletions(-)
diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h
index e12490ed41..64b4a4bb5b 100644
--- a/sysdeps/generic/math-use-builtins.h
+++ b/sysdeps/generic/math-use-builtins.h
@@ -26,4 +26,9 @@
#define USE_NEARBYINTL_BUILTIN 0
#define USE_NEARBYINTF128_BUILTIN 0
+#define USE_RINT_BUILTIN 0
+#define USE_RINTF_BUILTIN 0
+#define USE_RINTL_BUILTIN 0
+#define USE_RINTF128_BUILTIN 0
+
#endif /* math-use-builtins.h */
diff --git a/sysdeps/ieee754/dbl-64/s_rint.c b/sysdeps/ieee754/dbl-64/s_rint.c
index 7f3dc87b96..5f4ac7c1e3 100644
--- a/sysdeps/ieee754/dbl-64/s_rint.c
+++ b/sysdeps/ieee754/dbl-64/s_rint.c
@@ -22,16 +22,20 @@
#include <math.h>
#include <math_private.h>
#include <libm-alias-double.h>
-
-static const double
-TWO52[2] = {
- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
-};
+#include <math-use-builtins.h>
double
__rint (double x)
{
+#if USE_RINT_BUILTIN
+ return __builtin_rint (x);
+#else
+ /* Use generic implementation. */
+ static const double
+ TWO52[2] = {
+ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+ };
int64_t i0, sx;
int32_t j0;
EXTRACT_WORDS64 (i0, x);
@@ -58,6 +62,7 @@ __rint (double x)
}
double w = TWO52[sx] + x;
return w - TWO52[sx];
+#endif /* ! USE_RINT_BUILTIN */
}
#ifndef __rint
libm_alias_double (__rint, rint)
diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h
index 0bf6e8dee2..b872aefbfd 100644
--- a/sysdeps/ieee754/float128/float128_private.h
+++ b/sysdeps/ieee754/float128/float128_private.h
@@ -141,6 +141,8 @@
#include <math-use-builtins.h>
#undef USE_NEARBYINTL_BUILTIN
#define USE_NEARBYINTL_BUILTIN USE_NEARBYINTF128_BUILTIN
+#undef USE_RINTL_BUILTIN
+#define USE_RINTL_BUILTIN USE_RINTF128_BUILTIN
/* IEEE function renames. */
#define __ieee754_acoshl __ieee754_acoshf128
@@ -343,6 +345,7 @@
#define __builtin_copysignl __builtin_copysignf128
#define __builtin_signbitl __builtin_signbit
#define __builtin_nearbyintl __builtin_nearbyintf128
+#define __builtin_rintl __builtin_rintf128
/* Get the constant suffix from bits/floatn-compat.h. */
#define L(x) __f128 (x)
diff --git a/sysdeps/ieee754/flt-32/s_rintf.c b/sysdeps/ieee754/flt-32/s_rintf.c
index db6f260a0b..a266b1999e 100644
--- a/sysdeps/ieee754/flt-32/s_rintf.c
+++ b/sysdeps/ieee754/flt-32/s_rintf.c
@@ -16,16 +16,20 @@
#include <math.h>
#include <math_private.h>
#include <libm-alias-float.h>
-
-static const float
-TWO23[2]={
- 8.3886080000e+06, /* 0x4b000000 */
- -8.3886080000e+06, /* 0xcb000000 */
-};
+#include <math-use-builtins.h>
float
__rintf(float x)
{
+#if USE_RINTF_BUILTIN
+ return __builtin_rintf (x);
+#else
+ /* Use generic implementation. */
+ static const float
+ TWO23[2] = {
+ 8.3886080000e+06, /* 0x4b000000 */
+ -8.3886080000e+06, /* 0xcb000000 */
+ };
int32_t i0,j0,sx;
float w,t;
GET_FLOAT_WORD(i0,x);
@@ -45,6 +49,7 @@ __rintf(float x)
}
w = TWO23[sx]+x;
return w-TWO23[sx];
+#endif /* ! USE_RINTF_BUILTIN */
}
#ifndef __rintf
libm_alias_float (__rint, rint)
diff --git a/sysdeps/ieee754/ldbl-128/s_rintl.c b/sysdeps/ieee754/ldbl-128/s_rintl.c
index 9e6637a225..f060503066 100644
--- a/sysdeps/ieee754/ldbl-128/s_rintl.c
+++ b/sysdeps/ieee754/ldbl-128/s_rintl.c
@@ -30,15 +30,19 @@ static char rcsid[] = "$NetBSD: $";
#include <math.h>
#include <math_private.h>
#include <libm-alias-ldouble.h>
-
-static const _Float128
-TWO112[2]={
- 5.19229685853482762853049632922009600E+33L, /* 0x406F000000000000, 0 */
- -5.19229685853482762853049632922009600E+33L /* 0xC06F000000000000, 0 */
-};
+#include <math-use-builtins.h>
_Float128 __rintl(_Float128 x)
{
+#if USE_RINTL_BUILTIN
+ return __builtin_rintl (x);
+#else
+ /* Use generic implementation. */
+ static const _Float128
+ TWO112[2] = {
+ 5.19229685853482762853049632922009600E+33L, /* 0x406F000000000000, 0 */
+ -5.19229685853482762853049632922009600E+33L /* 0xC06F000000000000, 0 */
+ };
int64_t i0,j0,sx;
uint64_t i1 __attribute__ ((unused));
_Float128 w,t;
@@ -59,5 +63,6 @@ _Float128 __rintl(_Float128 x)
}
w = TWO112[sx]+x;
return w-TWO112[sx];
+#endif /* ! USE_RINTL_BUILTIN */
}
libm_alias_ldouble (__rint, rint)
diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h
index 7abbfb3b50..8b702a6a90 100644
--- a/sysdeps/s390/fpu/math-use-builtins.h
+++ b/sysdeps/s390/fpu/math-use-builtins.h
@@ -30,10 +30,16 @@
# define USE_NEARBYINTF_BUILTIN 1
# define USE_NEARBYINTL_BUILTIN 1
+# define USE_RINT_BUILTIN 1
+# define USE_RINTF_BUILTIN 1
+# define USE_RINTL_BUILTIN 1
+
# if __GNUC_PREREQ (8, 0)
# define USE_NEARBYINTF128_BUILTIN 1
+# define USE_RINTF128_BUILTIN 1
# else
# define USE_NEARBYINTF128_BUILTIN 0
+# define USE_RINTF128_BUILTIN 0
# endif
#else
@@ -44,6 +50,11 @@
# define USE_NEARBYINTL_BUILTIN 0
# define USE_NEARBYINTF128_BUILTIN 0
+# define USE_RINT_BUILTIN 0
+# define USE_RINTF_BUILTIN 0
+# define USE_RINTL_BUILTIN 0
+# define USE_RINTF128_BUILTIN 0
+
#endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */
#endif /* math-use-builtins.h */
--
2.18.2

View File

@ -0,0 +1,182 @@
From 8353881ede286045dc5bdc00af6407560ca5d05b Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:20 +0100
Subject: [PATCH 09/28] Use GCC builtins for floor functions if desired.
This patch is using the corresponding GCC builtin for floorf, floor,
floorl and floorf128 if the USE_FUNCTION_BUILTIN macros are defined to one
in math-use-builtins.h.
This is the case for s390 if build with at least --march=z196 --mzarch.
Otherwise the generic implementation is used. The code of the generic
implementation is not changed.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 6c1b6a5e8cd91e0e1965509ad91e627e60eb00a3)
---
sysdeps/generic/math-use-builtins.h | 5 +++++
sysdeps/ieee754/dbl-64/s_floor.c | 6 ++++++
sysdeps/ieee754/float128/float128_private.h | 3 +++
sysdeps/ieee754/flt-32/s_floorf.c | 6 ++++++
sysdeps/ieee754/ldbl-128/s_floorl.c | 6 ++++++
sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++
6 files changed, 37 insertions(+)
diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h
index 64b4a4bb5b..e1c5df62e4 100644
--- a/sysdeps/generic/math-use-builtins.h
+++ b/sysdeps/generic/math-use-builtins.h
@@ -31,4 +31,9 @@
#define USE_RINTL_BUILTIN 0
#define USE_RINTF128_BUILTIN 0
+#define USE_FLOOR_BUILTIN 0
+#define USE_FLOORF_BUILTIN 0
+#define USE_FLOORL_BUILTIN 0
+#define USE_FLOORF128_BUILTIN 0
+
#endif /* math-use-builtins.h */
diff --git a/sysdeps/ieee754/dbl-64/s_floor.c b/sysdeps/ieee754/dbl-64/s_floor.c
index b551a1aafa..693938b708 100644
--- a/sysdeps/ieee754/dbl-64/s_floor.c
+++ b/sysdeps/ieee754/dbl-64/s_floor.c
@@ -34,6 +34,7 @@
#include <math_private.h>
#include <stdint.h>
#include <libm-alias-double.h>
+#include <math-use-builtins.h>
/*
* floor(x)
@@ -45,6 +46,10 @@
double
__floor (double x)
{
+#if USE_FLOOR_BUILTIN
+ return __builtin_floor (x);
+#else
+ /* Use generic implementation. */
int64_t i0;
EXTRACT_WORDS64 (i0, x);
int32_t j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
@@ -72,6 +77,7 @@ __floor (double x)
else if (j0 == 0x400)
return x + x; /* inf or NaN */
return x;
+#endif /* ! USE_FLOOR_BUILTIN */
}
#ifndef __floor
libm_alias_double (__floor, floor)
diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h
index b872aefbfd..667030ab06 100644
--- a/sysdeps/ieee754/float128/float128_private.h
+++ b/sysdeps/ieee754/float128/float128_private.h
@@ -143,6 +143,8 @@
#define USE_NEARBYINTL_BUILTIN USE_NEARBYINTF128_BUILTIN
#undef USE_RINTL_BUILTIN
#define USE_RINTL_BUILTIN USE_RINTF128_BUILTIN
+#undef USE_FLOORL_BUILTIN
+#define USE_FLOORL_BUILTIN USE_FLOORF128_BUILTIN
/* IEEE function renames. */
#define __ieee754_acoshl __ieee754_acoshf128
@@ -346,6 +348,7 @@
#define __builtin_signbitl __builtin_signbit
#define __builtin_nearbyintl __builtin_nearbyintf128
#define __builtin_rintl __builtin_rintf128
+#define __builtin_floorl __builtin_floorf128
/* Get the constant suffix from bits/floatn-compat.h. */
#define L(x) __f128 (x)
diff --git a/sysdeps/ieee754/flt-32/s_floorf.c b/sysdeps/ieee754/flt-32/s_floorf.c
index 12aed343a0..6d37ab90a1 100644
--- a/sysdeps/ieee754/flt-32/s_floorf.c
+++ b/sysdeps/ieee754/flt-32/s_floorf.c
@@ -23,10 +23,15 @@
#include <math.h>
#include <math_private.h>
#include <libm-alias-float.h>
+#include <math-use-builtins.h>
float
__floorf(float x)
{
+#if USE_FLOORF_BUILTIN
+ return __builtin_floorf (x);
+#else
+ /* Use generic implementation. */
int32_t i0,j0;
uint32_t i;
GET_FLOAT_WORD(i0,x);
@@ -49,6 +54,7 @@ __floorf(float x)
}
SET_FLOAT_WORD(x,i0);
return x;
+#endif /* ! USE_FLOORF_BUILTIN */
}
#ifndef __floorf
libm_alias_float (__floor, floor)
diff --git a/sysdeps/ieee754/ldbl-128/s_floorl.c b/sysdeps/ieee754/ldbl-128/s_floorl.c
index f9c5e014f9..6143fe6ec5 100644
--- a/sysdeps/ieee754/ldbl-128/s_floorl.c
+++ b/sysdeps/ieee754/ldbl-128/s_floorl.c
@@ -27,9 +27,14 @@ static char rcsid[] = "$NetBSD: $";
#include <math.h>
#include <math_private.h>
#include <libm-alias-ldouble.h>
+#include <math-use-builtins.h>
_Float128 __floorl(_Float128 x)
{
+#if USE_FLOORL_BUILTIN
+ return __builtin_floorl (x);
+#else
+ /* Use generic implementation. */
int64_t i0,i1,j0;
uint64_t i,j;
GET_LDOUBLE_WORDS64(i0,i1,x);
@@ -64,5 +69,6 @@ _Float128 __floorl(_Float128 x)
}
SET_LDOUBLE_WORDS64(x,i0,i1);
return x;
+#endif /* ! USE_FLOORL_BUILTIN */
}
libm_alias_ldouble (__floor, floor)
diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h
index 8b702a6a90..c213c16c6f 100644
--- a/sysdeps/s390/fpu/math-use-builtins.h
+++ b/sysdeps/s390/fpu/math-use-builtins.h
@@ -34,12 +34,18 @@
# define USE_RINTF_BUILTIN 1
# define USE_RINTL_BUILTIN 1
+# define USE_FLOOR_BUILTIN 1
+# define USE_FLOORF_BUILTIN 1
+# define USE_FLOORL_BUILTIN 1
+
# if __GNUC_PREREQ (8, 0)
# define USE_NEARBYINTF128_BUILTIN 1
# define USE_RINTF128_BUILTIN 1
+# define USE_FLOORF128_BUILTIN 1
# else
# define USE_NEARBYINTF128_BUILTIN 0
# define USE_RINTF128_BUILTIN 0
+# define USE_FLOORF128_BUILTIN 0
# endif
#else
@@ -55,6 +61,11 @@
# define USE_RINTL_BUILTIN 0
# define USE_RINTF128_BUILTIN 0
+# define USE_FLOOR_BUILTIN 0
+# define USE_FLOORF_BUILTIN 0
+# define USE_FLOORL_BUILTIN 0
+# define USE_FLOORF128_BUILTIN 0
+
#endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */
#endif /* math-use-builtins.h */
--
2.18.2

View File

@ -0,0 +1,182 @@
From 6c5e5f498cd004b3f42d97997898018df8f798a4 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:21 +0100
Subject: [PATCH 10/28] Use GCC builtins for ceil functions if desired.
This patch is using the corresponding GCC builtin for ceilf, ceil,
ceill and ceilf128 if the USE_FUNCTION_BUILTIN macros are defined to one
in math-use-builtins.h.
This is the case for s390 if build with at least --march=z196 --mzarch.
Otherwise the generic implementation is used. The code of the generic
implementation is not changed.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 62560ee84095274bab1050817f42e782df226a17)
---
sysdeps/generic/math-use-builtins.h | 5 +++++
sysdeps/ieee754/dbl-64/s_ceil.c | 6 ++++++
sysdeps/ieee754/float128/float128_private.h | 3 +++
sysdeps/ieee754/flt-32/s_ceilf.c | 7 ++++++-
sysdeps/ieee754/ldbl-128/s_ceill.c | 6 ++++++
sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++
6 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h
index e1c5df62e4..076ec661b0 100644
--- a/sysdeps/generic/math-use-builtins.h
+++ b/sysdeps/generic/math-use-builtins.h
@@ -36,4 +36,9 @@
#define USE_FLOORL_BUILTIN 0
#define USE_FLOORF128_BUILTIN 0
+#define USE_CEIL_BUILTIN 0
+#define USE_CEILF_BUILTIN 0
+#define USE_CEILL_BUILTIN 0
+#define USE_CEILF128_BUILTIN 0
+
#endif /* math-use-builtins.h */
diff --git a/sysdeps/ieee754/dbl-64/s_ceil.c b/sysdeps/ieee754/dbl-64/s_ceil.c
index 3becdfc515..ee4a3abc19 100644
--- a/sysdeps/ieee754/dbl-64/s_ceil.c
+++ b/sysdeps/ieee754/dbl-64/s_ceil.c
@@ -20,10 +20,15 @@
#include <math.h>
#include <math_private.h>
#include <libm-alias-double.h>
+#include <math-use-builtins.h>
double
__ceil (double x)
{
+#if USE_CEIL_BUILTIN
+ return __builtin_ceil (x);
+#else
+ /* Use generic implementation. */
int64_t i0, i;
int32_t j0;
EXTRACT_WORDS64 (i0, x);
@@ -57,6 +62,7 @@ __ceil (double x)
}
INSERT_WORDS64 (x, i0);
return x;
+#endif /* ! USE_CEIL_BUILTIN */
}
#ifndef __ceil
libm_alias_double (__ceil, ceil)
diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h
index 667030ab06..19352ca26c 100644
--- a/sysdeps/ieee754/float128/float128_private.h
+++ b/sysdeps/ieee754/float128/float128_private.h
@@ -145,6 +145,8 @@
#define USE_RINTL_BUILTIN USE_RINTF128_BUILTIN
#undef USE_FLOORL_BUILTIN
#define USE_FLOORL_BUILTIN USE_FLOORF128_BUILTIN
+#undef USE_CEILL_BUILTIN
+#define USE_CEILL_BUILTIN USE_CEILF128_BUILTIN
/* IEEE function renames. */
#define __ieee754_acoshl __ieee754_acoshf128
@@ -349,6 +351,7 @@
#define __builtin_nearbyintl __builtin_nearbyintf128
#define __builtin_rintl __builtin_rintf128
#define __builtin_floorl __builtin_floorf128
+#define __builtin_ceill __builtin_ceilf128
/* Get the constant suffix from bits/floatn-compat.h. */
#define L(x) __f128 (x)
diff --git a/sysdeps/ieee754/flt-32/s_ceilf.c b/sysdeps/ieee754/flt-32/s_ceilf.c
index f289ec2341..6cab7bdd62 100644
--- a/sysdeps/ieee754/flt-32/s_ceilf.c
+++ b/sysdeps/ieee754/flt-32/s_ceilf.c
@@ -16,11 +16,15 @@
#include <math.h>
#include <math_private.h>
#include <libm-alias-float.h>
-
+#include <math-use-builtins.h>
float
__ceilf(float x)
{
+#if USE_CEILF_BUILTIN
+ return __builtin_ceilf (x);
+#else
+ /* Use generic implementation. */
int32_t i0,j0;
uint32_t i;
@@ -43,6 +47,7 @@ __ceilf(float x)
}
SET_FLOAT_WORD(x,i0);
return x;
+#endif /* ! USE_CEILF_BUILTIN */
}
#ifndef __ceilf
libm_alias_float (__ceil, ceil)
diff --git a/sysdeps/ieee754/ldbl-128/s_ceill.c b/sysdeps/ieee754/ldbl-128/s_ceill.c
index e6aba5f2af..d212d86179 100644
--- a/sysdeps/ieee754/ldbl-128/s_ceill.c
+++ b/sysdeps/ieee754/ldbl-128/s_ceill.c
@@ -27,9 +27,14 @@ static char rcsid[] = "$NetBSD: $";
#include <math.h>
#include <math_private.h>
#include <libm-alias-ldouble.h>
+#include <math-use-builtins.h>
_Float128 __ceill(_Float128 x)
{
+#if USE_CEILL_BUILTIN
+ return __builtin_ceill (x);
+#else
+ /* Use generic implementation. */
int64_t i0,i1,j0;
uint64_t i,j;
GET_LDOUBLE_WORDS64(i0,i1,x);
@@ -63,5 +68,6 @@ _Float128 __ceill(_Float128 x)
}
SET_LDOUBLE_WORDS64(x,i0,i1);
return x;
+#endif /* ! USE_CEILL_BUILTIN */
}
libm_alias_ldouble (__ceil, ceil)
diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h
index c213c16c6f..5435cbb65f 100644
--- a/sysdeps/s390/fpu/math-use-builtins.h
+++ b/sysdeps/s390/fpu/math-use-builtins.h
@@ -38,14 +38,20 @@
# define USE_FLOORF_BUILTIN 1
# define USE_FLOORL_BUILTIN 1
+# define USE_CEIL_BUILTIN 1
+# define USE_CEILF_BUILTIN 1
+# define USE_CEILL_BUILTIN 1
+
# if __GNUC_PREREQ (8, 0)
# define USE_NEARBYINTF128_BUILTIN 1
# define USE_RINTF128_BUILTIN 1
# define USE_FLOORF128_BUILTIN 1
+# define USE_CEILF128_BUILTIN 1
# else
# define USE_NEARBYINTF128_BUILTIN 0
# define USE_RINTF128_BUILTIN 0
# define USE_FLOORF128_BUILTIN 0
+# define USE_CEILF128_BUILTIN 0
# endif
#else
@@ -66,6 +72,11 @@
# define USE_FLOORL_BUILTIN 0
# define USE_FLOORF128_BUILTIN 0
+# define USE_CEIL_BUILTIN 0
+# define USE_CEILF_BUILTIN 0
+# define USE_CEILL_BUILTIN 0
+# define USE_CEILF128_BUILTIN 0
+
#endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */
#endif /* math-use-builtins.h */
--
2.18.2

View File

@ -0,0 +1,187 @@
From abc72a0694c1c3d08354170da343eead8d9afcc1 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:22 +0100
Subject: [PATCH 11/28] Use GCC builtins for trunc functions if desired.
This patch is using the corresponding GCC builtin for truncf, trunc,
truncl and truncf128 if the USE_FUNCTION_BUILTIN macros are defined to one
in math-use-builtins.h.
This is the case for s390 if build with at least --march=z196 --mzarch.
Otherwise the generic implementation is used. The code of the generic
implementation is not changed.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 1ac9c1cf87216bf9f8ac4f7c9754d025d9f2c4ae)
---
sysdeps/generic/math-use-builtins.h | 5 +++++
sysdeps/ieee754/dbl-64/s_trunc.c | 6 ++++++
sysdeps/ieee754/float128/float128_private.h | 3 +++
sysdeps/ieee754/flt-32/s_truncf.c | 6 ++++++
sysdeps/ieee754/ldbl-128/s_truncl.c | 6 ++++++
sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++
6 files changed, 37 insertions(+)
diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h
index 076ec661b0..ab379f45ba 100644
--- a/sysdeps/generic/math-use-builtins.h
+++ b/sysdeps/generic/math-use-builtins.h
@@ -41,4 +41,9 @@
#define USE_CEILL_BUILTIN 0
#define USE_CEILF128_BUILTIN 0
+#define USE_TRUNC_BUILTIN 0
+#define USE_TRUNCF_BUILTIN 0
+#define USE_TRUNCL_BUILTIN 0
+#define USE_TRUNCF128_BUILTIN 0
+
#endif /* math-use-builtins.h */
diff --git a/sysdeps/ieee754/dbl-64/s_trunc.c b/sysdeps/ieee754/dbl-64/s_trunc.c
index 38bb33d337..708169c727 100644
--- a/sysdeps/ieee754/dbl-64/s_trunc.c
+++ b/sysdeps/ieee754/dbl-64/s_trunc.c
@@ -21,11 +21,16 @@
#include <math_private.h>
#include <libm-alias-double.h>
+#include <math-use-builtins.h>
double
__trunc (double x)
{
+#if USE_TRUNC_BUILTIN
+ return __builtin_trunc (x);
+#else
+ /* Use generic implementation. */
int64_t i0, j0;
int64_t sx;
@@ -48,6 +53,7 @@ __trunc (double x)
}
return x;
+#endif /* ! USE_TRUNC_BUILTIN */
}
#ifndef __trunc
libm_alias_double (__trunc, trunc)
diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h
index 19352ca26c..e248600ec2 100644
--- a/sysdeps/ieee754/float128/float128_private.h
+++ b/sysdeps/ieee754/float128/float128_private.h
@@ -147,6 +147,8 @@
#define USE_FLOORL_BUILTIN USE_FLOORF128_BUILTIN
#undef USE_CEILL_BUILTIN
#define USE_CEILL_BUILTIN USE_CEILF128_BUILTIN
+#undef USE_TRUNCL_BUILTIN
+#define USE_TRUNCL_BUILTIN USE_TRUNCF128_BUILTIN
/* IEEE function renames. */
#define __ieee754_acoshl __ieee754_acoshf128
@@ -352,6 +354,7 @@
#define __builtin_rintl __builtin_rintf128
#define __builtin_floorl __builtin_floorf128
#define __builtin_ceill __builtin_ceilf128
+#define __builtin_truncl __builtin_truncf128
/* Get the constant suffix from bits/floatn-compat.h. */
#define L(x) __f128 (x)
diff --git a/sysdeps/ieee754/flt-32/s_truncf.c b/sysdeps/ieee754/flt-32/s_truncf.c
index 2e1464aeac..71491e5175 100644
--- a/sysdeps/ieee754/flt-32/s_truncf.c
+++ b/sysdeps/ieee754/flt-32/s_truncf.c
@@ -21,11 +21,16 @@
#include <math_private.h>
#include <libm-alias-float.h>
+#include <math-use-builtins.h>
float
__truncf (float x)
{
+#if USE_TRUNCF_BUILTIN
+ return __builtin_truncf (x);
+#else
+ /* Use generic implementation. */
int32_t i0, j0;
int sx;
@@ -48,6 +53,7 @@ __truncf (float x)
}
return x;
+#endif /* ! USE_TRUNCF_BUILTIN */
}
#ifndef __truncf
libm_alias_float (__trunc, trunc)
diff --git a/sysdeps/ieee754/ldbl-128/s_truncl.c b/sysdeps/ieee754/ldbl-128/s_truncl.c
index f858ede3d2..aa49daaf85 100644
--- a/sysdeps/ieee754/ldbl-128/s_truncl.c
+++ b/sysdeps/ieee754/ldbl-128/s_truncl.c
@@ -22,11 +22,16 @@
#include <math_private.h>
#include <libm-alias-ldouble.h>
+#include <math-use-builtins.h>
_Float128
__truncl (_Float128 x)
{
+#if USE_TRUNCL_BUILTIN
+ return __builtin_truncl (x);
+#else
+ /* Use generic implementation. */
int32_t j0;
uint64_t i0, i1, sx;
@@ -53,5 +58,6 @@ __truncl (_Float128 x)
}
return x;
+#endif /* ! USE_TRUNCL_BUILTIN */
}
libm_alias_ldouble (__trunc, trunc)
diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h
index 5435cbb65f..a39715c612 100644
--- a/sysdeps/s390/fpu/math-use-builtins.h
+++ b/sysdeps/s390/fpu/math-use-builtins.h
@@ -42,16 +42,22 @@
# define USE_CEILF_BUILTIN 1
# define USE_CEILL_BUILTIN 1
+# define USE_TRUNC_BUILTIN 1
+# define USE_TRUNCF_BUILTIN 1
+# define USE_TRUNCL_BUILTIN 1
+
# if __GNUC_PREREQ (8, 0)
# define USE_NEARBYINTF128_BUILTIN 1
# define USE_RINTF128_BUILTIN 1
# define USE_FLOORF128_BUILTIN 1
# define USE_CEILF128_BUILTIN 1
+# define USE_TRUNCF128_BUILTIN 1
# else
# define USE_NEARBYINTF128_BUILTIN 0
# define USE_RINTF128_BUILTIN 0
# define USE_FLOORF128_BUILTIN 0
# define USE_CEILF128_BUILTIN 0
+# define USE_TRUNCF128_BUILTIN 0
# endif
#else
@@ -77,6 +83,11 @@
# define USE_CEILL_BUILTIN 0
# define USE_CEILF128_BUILTIN 0
+# define USE_TRUNC_BUILTIN 0
+# define USE_TRUNCF_BUILTIN 0
+# define USE_TRUNCL_BUILTIN 0
+# define USE_TRUNCF128_BUILTIN 0
+
#endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */
#endif /* math-use-builtins.h */
--
2.18.2

View File

@ -0,0 +1,187 @@
From f49dd4cc4e295803e517190d1798bd84561d56f4 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:24 +0100
Subject: [PATCH 12/28] Use GCC builtins for round functions if desired.
This patch is using the corresponding GCC builtin for roundf, round,
roundl and roundf128 if the USE_FUNCTION_BUILTIN macros are defined to one
in math-use-builtins.h.
This is the case for s390 if build with at least --march=z196 --mzarch.
Otherwise the generic implementation is used. The code of the generic
implementation is not changed.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit f82996f8159981619ac7ed8a4c1838c2ad72ab61)
---
sysdeps/generic/math-use-builtins.h | 5 +++++
sysdeps/ieee754/dbl-64/s_round.c | 6 ++++++
sysdeps/ieee754/float128/float128_private.h | 3 +++
sysdeps/ieee754/flt-32/s_roundf.c | 6 ++++++
sysdeps/ieee754/ldbl-128/s_roundl.c | 6 ++++++
sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++
6 files changed, 37 insertions(+)
diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h
index ab379f45ba..34ca438a8c 100644
--- a/sysdeps/generic/math-use-builtins.h
+++ b/sysdeps/generic/math-use-builtins.h
@@ -46,4 +46,9 @@
#define USE_TRUNCL_BUILTIN 0
#define USE_TRUNCF128_BUILTIN 0
+#define USE_ROUND_BUILTIN 0
+#define USE_ROUNDF_BUILTIN 0
+#define USE_ROUNDL_BUILTIN 0
+#define USE_ROUNDF128_BUILTIN 0
+
#endif /* math-use-builtins.h */
diff --git a/sysdeps/ieee754/dbl-64/s_round.c b/sysdeps/ieee754/dbl-64/s_round.c
index bf9922edca..1f8482adf8 100644
--- a/sysdeps/ieee754/dbl-64/s_round.c
+++ b/sysdeps/ieee754/dbl-64/s_round.c
@@ -22,11 +22,16 @@
#include <math_private.h>
#include <libm-alias-double.h>
#include <stdint.h>
+#include <math-use-builtins.h>
double
__round (double x)
{
+#if USE_ROUND_BUILTIN
+ return __builtin_round (x);
+#else
+ /* Use generic implementation. */
int64_t i0, j0;
EXTRACT_WORDS64 (i0, x);
@@ -61,5 +66,6 @@ __round (double x)
INSERT_WORDS64 (x, i0);
return x;
+#endif /* ! USE_ROUND_BUILTIN */
}
libm_alias_double (__round, round)
diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h
index e248600ec2..3297a71e44 100644
--- a/sysdeps/ieee754/float128/float128_private.h
+++ b/sysdeps/ieee754/float128/float128_private.h
@@ -149,6 +149,8 @@
#define USE_CEILL_BUILTIN USE_CEILF128_BUILTIN
#undef USE_TRUNCL_BUILTIN
#define USE_TRUNCL_BUILTIN USE_TRUNCF128_BUILTIN
+#undef USE_ROUNDL_BUILTIN
+#define USE_ROUNDL_BUILTIN USE_ROUNDF128_BUILTIN
/* IEEE function renames. */
#define __ieee754_acoshl __ieee754_acoshf128
@@ -355,6 +357,7 @@
#define __builtin_floorl __builtin_floorf128
#define __builtin_ceill __builtin_ceilf128
#define __builtin_truncl __builtin_truncf128
+#define __builtin_roundl __builtin_roundf128
/* Get the constant suffix from bits/floatn-compat.h. */
#define L(x) __f128 (x)
diff --git a/sysdeps/ieee754/flt-32/s_roundf.c b/sysdeps/ieee754/flt-32/s_roundf.c
index 7c95125d9c..6fdfbbbade 100644
--- a/sysdeps/ieee754/flt-32/s_roundf.c
+++ b/sysdeps/ieee754/flt-32/s_roundf.c
@@ -21,11 +21,16 @@
#include <math_private.h>
#include <libm-alias-float.h>
+#include <math-use-builtins.h>
float
__roundf (float x)
{
+#if USE_ROUNDF_BUILTIN
+ return __builtin_roundf (x);
+#else
+ /* Use generic implementation. */
int32_t i0, j0;
GET_FLOAT_WORD (i0, x);
@@ -60,5 +65,6 @@ __roundf (float x)
SET_FLOAT_WORD (x, i0);
return x;
+#endif /* ! USE_ROUNDF_BUILTIN */
}
libm_alias_float (__round, round)
diff --git a/sysdeps/ieee754/ldbl-128/s_roundl.c b/sysdeps/ieee754/ldbl-128/s_roundl.c
index 22789cedf3..564f8ac1b8 100644
--- a/sysdeps/ieee754/ldbl-128/s_roundl.c
+++ b/sysdeps/ieee754/ldbl-128/s_roundl.c
@@ -22,11 +22,16 @@
#include <math_private.h>
#include <libm-alias-ldouble.h>
+#include <math-use-builtins.h>
_Float128
__roundl (_Float128 x)
{
+#if USE_ROUNDL_BUILTIN
+ return __builtin_roundl (x);
+#else
+ /* Use generic implementation. */
int32_t j0;
uint64_t i1, i0;
@@ -77,5 +82,6 @@ __roundl (_Float128 x)
SET_LDOUBLE_WORDS64 (x, i0, i1);
return x;
+#endif /* ! USE_ROUNDL_BUILTIN */
}
libm_alias_ldouble (__round, round)
diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h
index a39715c612..51cb9f91ab 100644
--- a/sysdeps/s390/fpu/math-use-builtins.h
+++ b/sysdeps/s390/fpu/math-use-builtins.h
@@ -46,18 +46,24 @@
# define USE_TRUNCF_BUILTIN 1
# define USE_TRUNCL_BUILTIN 1
+# define USE_ROUND_BUILTIN 1
+# define USE_ROUNDF_BUILTIN 1
+# define USE_ROUNDL_BUILTIN 1
+
# if __GNUC_PREREQ (8, 0)
# define USE_NEARBYINTF128_BUILTIN 1
# define USE_RINTF128_BUILTIN 1
# define USE_FLOORF128_BUILTIN 1
# define USE_CEILF128_BUILTIN 1
# define USE_TRUNCF128_BUILTIN 1
+# define USE_ROUNDF128_BUILTIN 1
# else
# define USE_NEARBYINTF128_BUILTIN 0
# define USE_RINTF128_BUILTIN 0
# define USE_FLOORF128_BUILTIN 0
# define USE_CEILF128_BUILTIN 0
# define USE_TRUNCF128_BUILTIN 0
+# define USE_ROUNDF128_BUILTIN 0
# endif
#else
@@ -88,6 +94,11 @@
# define USE_TRUNCL_BUILTIN 0
# define USE_TRUNCF128_BUILTIN 0
+# define USE_ROUND_BUILTIN 0
+# define USE_ROUNDF_BUILTIN 0
+# define USE_ROUNDL_BUILTIN 0
+# define USE_ROUNDF128_BUILTIN 0
+
#endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */
#endif /* math-use-builtins.h */
--
2.18.2

View File

@ -0,0 +1,177 @@
From e93b17fad37a61f7ae9a663c617926b0f510921a Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:24 +0100
Subject: [PATCH 13/28] Use GCC builtins for copysign functions if desired.
This patch is always using the corresponding GCC builtin for copysignf, copysign,
and is using the builtin for copysignl, copysignf128 if the USE_FUNCTION_BUILTIN
macros are defined to one in math-use-builtins.h.
Altough the long double version is enabled by default we still need
the macro and the alternative implementation as the _Float128 version
of the builtin is not available with all supported GCC versions.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit f818afdd3b29d7eef2010448457c9f5c16e684cd)
---
sysdeps/generic/math-use-builtins.h | 9 +++++++++
sysdeps/ieee754/dbl-64/s_copysign.c | 9 ++-------
sysdeps/ieee754/float128/float128_private.h | 3 +++
sysdeps/ieee754/flt-32/s_copysignf.c | 12 ++++--------
sysdeps/ieee754/ldbl-128/s_copysignl.c | 6 ++++++
sysdeps/s390/fpu/math-use-builtins.h | 7 +++++++
6 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h
index 34ca438a8c..770b54ce61 100644
--- a/sysdeps/generic/math-use-builtins.h
+++ b/sysdeps/generic/math-use-builtins.h
@@ -19,6 +19,8 @@
#ifndef MATH_USE_BUILTINS_H
#define MATH_USE_BUILTINS_H 1
+#include <features.h> /* For __GNUC_PREREQ. */
+
/* Define these macros to 1 to use __builtin_xyz instead of the
generic implementation. */
#define USE_NEARBYINT_BUILTIN 0
@@ -51,4 +53,11 @@
#define USE_ROUNDL_BUILTIN 0
#define USE_ROUNDF128_BUILTIN 0
+#define USE_COPYSIGNL_BUILTIN 1
+#if __GNUC_PREREQ (7, 0)
+# define USE_COPYSIGNF128_BUILTIN 1
+#else
+# define USE_COPYSIGNF128_BUILTIN 0
+#endif
+
#endif /* math-use-builtins.h */
diff --git a/sysdeps/ieee754/dbl-64/s_copysign.c b/sysdeps/ieee754/dbl-64/s_copysign.c
index ab81d732ab..b95f1575d9 100644
--- a/sysdeps/ieee754/dbl-64/s_copysign.c
+++ b/sysdeps/ieee754/dbl-64/s_copysign.c
@@ -10,7 +10,7 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
+#if defined (LIBM_SCCS) && ! defined (lint)
static char rcsid[] = "$NetBSD: s_copysign.c,v 1.8 1995/05/10 20:46:57 jtc Exp $";
#endif
@@ -21,16 +21,11 @@ static char rcsid[] = "$NetBSD: s_copysign.c,v 1.8 1995/05/10 20:46:57 jtc Exp $
*/
#include <math.h>
-#include <math_private.h>
#include <libm-alias-double.h>
double
__copysign (double x, double y)
{
- uint32_t hx, hy;
- GET_HIGH_WORD (hx, x);
- GET_HIGH_WORD (hy, y);
- SET_HIGH_WORD (x, (hx & 0x7fffffff) | (hy & 0x80000000));
- return x;
+ return __builtin_copysign (x, y);
}
libm_alias_double (__copysign, copysign)
diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h
index 3297a71e44..077df0e09f 100644
--- a/sysdeps/ieee754/float128/float128_private.h
+++ b/sysdeps/ieee754/float128/float128_private.h
@@ -151,6 +151,8 @@
#define USE_TRUNCL_BUILTIN USE_TRUNCF128_BUILTIN
#undef USE_ROUNDL_BUILTIN
#define USE_ROUNDL_BUILTIN USE_ROUNDF128_BUILTIN
+#undef USE_COPYSIGNL_BUILTIN
+#define USE_COPYSIGNL_BUILTIN USE_COPYSIGNF128_BUILTIN
/* IEEE function renames. */
#define __ieee754_acoshl __ieee754_acoshf128
@@ -358,6 +360,7 @@
#define __builtin_ceill __builtin_ceilf128
#define __builtin_truncl __builtin_truncf128
#define __builtin_roundl __builtin_roundf128
+#define __builtin_copysignl __builtin_copysignf128
/* Get the constant suffix from bits/floatn-compat.h. */
#define L(x) __f128 (x)
diff --git a/sysdeps/ieee754/flt-32/s_copysignf.c b/sysdeps/ieee754/flt-32/s_copysignf.c
index 3c4ac7ce68..0247abd152 100644
--- a/sysdeps/ieee754/flt-32/s_copysignf.c
+++ b/sysdeps/ieee754/flt-32/s_copysignf.c
@@ -13,7 +13,7 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
+#if defined (LIBM_SCCS) && ! defined (lint)
static char rcsid[] = "$NetBSD: s_copysignf.c,v 1.4 1995/05/10 20:46:59 jtc Exp $";
#endif
@@ -24,15 +24,11 @@ static char rcsid[] = "$NetBSD: s_copysignf.c,v 1.4 1995/05/10 20:46:59 jtc Exp
*/
#include <math.h>
-#include <math_private.h>
#include <libm-alias-float.h>
-float __copysignf(float x, float y)
+float
+__copysignf (float x, float y)
{
- uint32_t ix,iy;
- GET_FLOAT_WORD(ix,x);
- GET_FLOAT_WORD(iy,y);
- SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000));
- return x;
+ return __builtin_copysignf (x, y);
}
libm_alias_float (__copysign, copysign)
diff --git a/sysdeps/ieee754/ldbl-128/s_copysignl.c b/sysdeps/ieee754/ldbl-128/s_copysignl.c
index d23e0f72ea..4cae8612dc 100644
--- a/sysdeps/ieee754/ldbl-128/s_copysignl.c
+++ b/sysdeps/ieee754/ldbl-128/s_copysignl.c
@@ -26,14 +26,20 @@ static char rcsid[] = "$NetBSD: $";
#include <math.h>
#include <math_private.h>
#include <libm-alias-ldouble.h>
+#include <math-use-builtins.h>
_Float128 __copysignl(_Float128 x, _Float128 y)
{
+#if USE_COPYSIGNL_BUILTIN
+ return __builtin_copysignl (x, y);
+#else
+ /* Use generic implementation. */
uint64_t hx,hy;
GET_LDOUBLE_MSW64(hx,x);
GET_LDOUBLE_MSW64(hy,y);
SET_LDOUBLE_MSW64(x,(hx&0x7fffffffffffffffULL)
|(hy&0x8000000000000000ULL));
return x;
+#endif /* ! USE_COPYSIGNL_BUILTIN */
}
libm_alias_ldouble (__copysign, copysign)
diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h
index 51cb9f91ab..4c4aad2ab5 100644
--- a/sysdeps/s390/fpu/math-use-builtins.h
+++ b/sysdeps/s390/fpu/math-use-builtins.h
@@ -101,4 +101,11 @@
#endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */
+#define USE_COPYSIGNL_BUILTIN 1
+#if __GNUC_PREREQ (7, 0)
+# define USE_COPYSIGNF128_BUILTIN 1
+#else
+# define USE_COPYSIGNF128_BUILTIN 0
+#endif
+
#endif /* math-use-builtins.h */
--
2.18.2

View File

@ -0,0 +1,180 @@
From bd7c710d3b234a8d3bd77aae358bd7f7a6ce576d Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:25 +0100
Subject: [PATCH 14/28] Adjust s_nearbyintf.c and s_nearbyintl.c regarding code
style.
This patch just adjusts the generic implementation regarding code style.
No functional change.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 6a3866dae98cccc8cd7a0a4c1fb409dba9192a83)
---
sysdeps/ieee754/flt-32/s_nearbyintf.c | 60 ++++++++++++-----------
sysdeps/ieee754/ldbl-128/s_nearbyintl.c | 63 ++++++++++++++-----------
2 files changed, 68 insertions(+), 55 deletions(-)
diff --git a/sysdeps/ieee754/flt-32/s_nearbyintf.c b/sysdeps/ieee754/flt-32/s_nearbyintf.c
index 438dcae8cc..5969e3e5b8 100644
--- a/sysdeps/ieee754/flt-32/s_nearbyintf.c
+++ b/sysdeps/ieee754/flt-32/s_nearbyintf.c
@@ -23,7 +23,7 @@
#include <math-use-builtins.h>
float
-__nearbyintf(float x)
+__nearbyintf (float x)
{
#if USE_NEARBYINTF_BUILTIN
return __builtin_nearbyintf (x);
@@ -34,33 +34,39 @@ __nearbyintf(float x)
8.3886080000e+06, /* 0x4b000000 */
-8.3886080000e+06, /* 0xcb000000 */
};
- fenv_t env;
- int32_t i0,j0,sx;
- float w,t;
- GET_FLOAT_WORD(i0,x);
- sx = (i0>>31)&1;
- j0 = ((i0>>23)&0xff)-0x7f;
- if(j0<23) {
- if(j0<0) {
- libc_feholdexceptf (&env);
- w = TWO23[sx] + math_opt_barrier (x);
- t = w-TWO23[sx];
- math_force_eval (t);
- libc_fesetenvf (&env);
- GET_FLOAT_WORD(i0,t);
- SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
- return t;
- }
- } else {
- if(__builtin_expect(j0==0x80, 0)) return x+x; /* inf or NaN */
- else return x; /* x is integral */
+ fenv_t env;
+ int32_t i0, j0, sx;
+ float w, t;
+ GET_FLOAT_WORD (i0, x);
+ sx = (i0 >> 31) & 1;
+ j0 = ((i0 >> 23) & 0xff) - 0x7f;
+ if (j0 < 23)
+ {
+ if (j0 < 0)
+ {
+ libc_feholdexceptf (&env);
+ w = TWO23[sx] + math_opt_barrier (x);
+ t = w - TWO23[sx];
+ math_force_eval (t);
+ libc_fesetenvf (&env);
+ GET_FLOAT_WORD (i0, t);
+ SET_FLOAT_WORD (t, (i0 & 0x7fffffff) | (sx << 31));
+ return t;
}
- libc_feholdexceptf (&env);
- w = TWO23[sx] + math_opt_barrier (x);
- t = w-TWO23[sx];
- math_force_eval (t);
- libc_fesetenvf (&env);
- return t;
+ }
+ else
+ {
+ if (__glibc_unlikely (j0 == 0x80))
+ return x + x; /* inf or NaN */
+ else
+ return x; /* x is integral */
+ }
+ libc_feholdexceptf (&env);
+ w = TWO23[sx] + math_opt_barrier (x);
+ t = w - TWO23[sx];
+ math_force_eval (t);
+ libc_fesetenvf (&env);
+ return t;
#endif /* ! USE_NEARBYINT_BUILTIN */
}
libm_alias_float (__nearbyint, nearbyint)
diff --git a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
index a4ad8e82e5..8d26786f78 100644
--- a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
+++ b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
@@ -30,7 +30,8 @@
#include <libm-alias-ldouble.h>
#include <math-use-builtins.h>
-_Float128 __nearbyintl(_Float128 x)
+_Float128
+__nearbyintl (_Float128 x)
{
#if USE_NEARBYINTL_BUILTIN
return __builtin_nearbyintl (x);
@@ -41,34 +42,40 @@ _Float128 __nearbyintl(_Float128 x)
L(5.19229685853482762853049632922009600E+33), /* 0x406F000000000000, 0 */
L(-5.19229685853482762853049632922009600E+33) /* 0xC06F000000000000, 0 */
};
- fenv_t env;
- int64_t i0,j0,sx;
- uint64_t i1 __attribute__ ((unused));
- _Float128 w,t;
- GET_LDOUBLE_WORDS64(i0,i1,x);
- sx = (((uint64_t)i0)>>63);
- j0 = ((i0>>48)&0x7fff)-0x3fff;
- if(j0<112) {
- if(j0<0) {
- feholdexcept (&env);
- w = TWO112[sx] + math_opt_barrier (x);
- t = w-TWO112[sx];
- math_force_eval (t);
- fesetenv (&env);
- GET_LDOUBLE_MSW64(i0,t);
- SET_LDOUBLE_MSW64(t,(i0&0x7fffffffffffffffLL)|(sx<<63));
- return t;
- }
- } else {
- if(j0==0x4000) return x+x; /* inf or NaN */
- else return x; /* x is integral */
+ fenv_t env;
+ int64_t i0, j0, sx;
+ uint64_t i1 __attribute__ ((unused));
+ _Float128 w, t;
+ GET_LDOUBLE_WORDS64 (i0, i1, x);
+ sx = (((uint64_t) i0) >> 63);
+ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
+ if (j0 < 112)
+ {
+ if (j0 < 0)
+ {
+ feholdexcept (&env);
+ w = TWO112[sx] + math_opt_barrier (x);
+ t = w - TWO112[sx];
+ math_force_eval (t);
+ fesetenv (&env);
+ GET_LDOUBLE_MSW64 (i0, t);
+ SET_LDOUBLE_MSW64 (t, (i0 & 0x7fffffffffffffffLL) | (sx << 63));
+ return t;
}
- feholdexcept (&env);
- w = TWO112[sx] + math_opt_barrier (x);
- t = w-TWO112[sx];
- math_force_eval (t);
- fesetenv (&env);
- return t;
+ }
+ else
+ {
+ if (j0 == 0x4000)
+ return x + x; /* inf or NaN */
+ else
+ return x; /* x is integral */
+ }
+ feholdexcept (&env);
+ w = TWO112[sx] + math_opt_barrier (x);
+ t = w - TWO112[sx];
+ math_force_eval (t);
+ fesetenv (&env);
+ return t;
#endif /* ! USE_NEARBYINTL_BUILTIN */
}
libm_alias_ldouble (__nearbyint, nearbyint)
--
2.18.2

View File

@ -0,0 +1,156 @@
From ce4f299c02be0a06130b70a62aa79b77385f4326 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:26 +0100
Subject: [PATCH 15/28] Adjust s_rintf.c and s_rintl.c regarding code style.
This patch just adjusts the generic implementation regarding code style.
No functional change.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 99b39a83e72f4b58e2f284fd844622df26b3b5fe)
---
sysdeps/ieee754/flt-32/s_rintf.c | 44 +++++++++++++++------------
sysdeps/ieee754/ldbl-128/s_rintl.c | 49 +++++++++++++++++-------------
2 files changed, 53 insertions(+), 40 deletions(-)
diff --git a/sysdeps/ieee754/flt-32/s_rintf.c b/sysdeps/ieee754/flt-32/s_rintf.c
index a266b1999e..3463a044e1 100644
--- a/sysdeps/ieee754/flt-32/s_rintf.c
+++ b/sysdeps/ieee754/flt-32/s_rintf.c
@@ -19,7 +19,7 @@
#include <math-use-builtins.h>
float
-__rintf(float x)
+__rintf (float x)
{
#if USE_RINTF_BUILTIN
return __builtin_rintf (x);
@@ -30,25 +30,31 @@ __rintf(float x)
8.3886080000e+06, /* 0x4b000000 */
-8.3886080000e+06, /* 0xcb000000 */
};
- int32_t i0,j0,sx;
- float w,t;
- GET_FLOAT_WORD(i0,x);
- sx = (i0>>31)&1;
- j0 = ((i0>>23)&0xff)-0x7f;
- if(j0<23) {
- if(j0<0) {
- w = TWO23[sx]+x;
- t = w-TWO23[sx];
- GET_FLOAT_WORD(i0,t);
- SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
- return t;
- }
- } else {
- if(j0==0x80) return x+x; /* inf or NaN */
- else return x; /* x is integral */
+ int32_t i0, j0, sx;
+ float w, t;
+ GET_FLOAT_WORD (i0, x);
+ sx = (i0 >> 31) & 1;
+ j0 = ((i0 >> 23) & 0xff) - 0x7f;
+ if (j0 < 23)
+ {
+ if(j0 < 0)
+ {
+ w = TWO23[sx] + x;
+ t = w - TWO23[sx];
+ GET_FLOAT_WORD (i0, t);
+ SET_FLOAT_WORD (t, (i0 & 0x7fffffff) | (sx << 31));
+ return t;
}
- w = TWO23[sx]+x;
- return w-TWO23[sx];
+ }
+ else
+ {
+ if (j0 == 0x80)
+ return x + x; /* inf or NaN */
+ else
+ return x; /* x is integral */
+ }
+ w = TWO23[sx] + x;
+ return w - TWO23[sx];
#endif /* ! USE_RINTF_BUILTIN */
}
#ifndef __rintf
diff --git a/sysdeps/ieee754/ldbl-128/s_rintl.c b/sysdeps/ieee754/ldbl-128/s_rintl.c
index f060503066..260f3aa9b9 100644
--- a/sysdeps/ieee754/ldbl-128/s_rintl.c
+++ b/sysdeps/ieee754/ldbl-128/s_rintl.c
@@ -13,7 +13,7 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
+#if defined (LIBM_SCCS) && ! defined (lint)
static char rcsid[] = "$NetBSD: $";
#endif
@@ -32,7 +32,8 @@ static char rcsid[] = "$NetBSD: $";
#include <libm-alias-ldouble.h>
#include <math-use-builtins.h>
-_Float128 __rintl(_Float128 x)
+_Float128
+__rintl (_Float128 x)
{
#if USE_RINTL_BUILTIN
return __builtin_rintl (x);
@@ -43,26 +44,32 @@ _Float128 __rintl(_Float128 x)
5.19229685853482762853049632922009600E+33L, /* 0x406F000000000000, 0 */
-5.19229685853482762853049632922009600E+33L /* 0xC06F000000000000, 0 */
};
- int64_t i0,j0,sx;
- uint64_t i1 __attribute__ ((unused));
- _Float128 w,t;
- GET_LDOUBLE_WORDS64(i0,i1,x);
- sx = (((uint64_t)i0)>>63);
- j0 = ((i0>>48)&0x7fff)-0x3fff;
- if(j0<112) {
- if(j0<0) {
- w = TWO112[sx]+x;
- t = w-TWO112[sx];
- GET_LDOUBLE_MSW64(i0,t);
- SET_LDOUBLE_MSW64(t,(i0&0x7fffffffffffffffLL)|(sx<<63));
- return t;
- }
- } else {
- if(j0==0x4000) return x+x; /* inf or NaN */
- else return x; /* x is integral */
+ int64_t i0, j0, sx;
+ uint64_t i1 __attribute__ ((unused));
+ _Float128 w, t;
+ GET_LDOUBLE_WORDS64 (i0, i1, x);
+ sx = (((uint64_t) i0) >> 63);
+ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
+ if (j0 < 112)
+ {
+ if (j0 < 0)
+ {
+ w = TWO112[sx] + x;
+ t = w - TWO112[sx];
+ GET_LDOUBLE_MSW64 (i0, t);
+ SET_LDOUBLE_MSW64 (t, (i0 & 0x7fffffffffffffffLL) | (sx << 63));
+ return t;
}
- w = TWO112[sx]+x;
- return w-TWO112[sx];
+ }
+ else
+ {
+ if (j0 == 0x4000)
+ return x + x; /* inf or NaN */
+ else
+ return x; /* x is integral */
+ }
+ w = TWO112[sx] + x;
+ return w - TWO112[sx];
#endif /* ! USE_RINTL_BUILTIN */
}
libm_alias_ldouble (__rint, rint)
--
2.18.2

View File

@ -0,0 +1,198 @@
From e96879644e4a9f4304725d1da9cc76b0c685b0b8 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:26 +0100
Subject: [PATCH 16/28] Adjust s_floorf.c and s_floorl.c regarding code style.
This patch just adjusts the generic implementation regarding code style.
No functional change.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit d3a0409ab615e133ff3ea27b492de75a607cff4a)
---
sysdeps/ieee754/flt-32/s_floorf.c | 55 +++++++++++-------
sysdeps/ieee754/ldbl-128/s_floorl.c | 89 ++++++++++++++++++-----------
2 files changed, 90 insertions(+), 54 deletions(-)
diff --git a/sysdeps/ieee754/flt-32/s_floorf.c b/sysdeps/ieee754/flt-32/s_floorf.c
index 6d37ab90a1..c45816e3bd 100644
--- a/sysdeps/ieee754/flt-32/s_floorf.c
+++ b/sysdeps/ieee754/flt-32/s_floorf.c
@@ -26,34 +26,45 @@
#include <math-use-builtins.h>
float
-__floorf(float x)
+__floorf (float x)
{
#if USE_FLOORF_BUILTIN
return __builtin_floorf (x);
#else
/* Use generic implementation. */
- int32_t i0,j0;
- uint32_t i;
- GET_FLOAT_WORD(i0,x);
- j0 = ((i0>>23)&0xff)-0x7f;
- if(j0<23) {
- if(j0<0) {
- /* return 0*sign(x) if |x|<1 */
- if(i0>=0) {i0=0;}
- else if((i0&0x7fffffff)!=0)
- { i0=0xbf800000;}
- } else {
- i = (0x007fffff)>>j0;
- if((i0&i)==0) return x; /* x is integral */
- if(i0<0) i0 += (0x00800000)>>j0;
- i0 &= (~i);
- }
- } else {
- if(__builtin_expect(j0==0x80, 0)) return x+x; /* inf or NaN */
- else return x; /* x is integral */
+ int32_t i0, j0;
+ uint32_t i;
+ GET_FLOAT_WORD (i0, x);
+ j0 = ((i0 >> 23) & 0xff) - 0x7f;
+ if (j0 < 23)
+ {
+ if (j0 < 0)
+ {
+ /* return 0 * sign (x) if |x| < 1 */
+ if (i0 >= 0)
+ i0 = 0;
+ else if ((i0 & 0x7fffffff) != 0)
+ i0 = 0xbf800000;
}
- SET_FLOAT_WORD(x,i0);
- return x;
+ else
+ {
+ i = (0x007fffff) >> j0;
+ if ((i0 & i) == 0)
+ return x; /* x is integral */
+ if (i0 < 0)
+ i0 += (0x00800000) >> j0;
+ i0 &= (~i);
+ }
+ }
+ else
+ {
+ if (__glibc_unlikely (j0 == 0x80))
+ return x + x; /* inf or NaN */
+ else
+ return x; /* x is integral */
+ }
+ SET_FLOAT_WORD (x, i0);
+ return x;
#endif /* ! USE_FLOORF_BUILTIN */
}
#ifndef __floorf
diff --git a/sysdeps/ieee754/ldbl-128/s_floorl.c b/sysdeps/ieee754/ldbl-128/s_floorl.c
index 6143fe6ec5..4fc10992c2 100644
--- a/sysdeps/ieee754/ldbl-128/s_floorl.c
+++ b/sysdeps/ieee754/ldbl-128/s_floorl.c
@@ -29,46 +29,71 @@ static char rcsid[] = "$NetBSD: $";
#include <libm-alias-ldouble.h>
#include <math-use-builtins.h>
-_Float128 __floorl(_Float128 x)
+_Float128
+__floorl (_Float128 x)
{
#if USE_FLOORL_BUILTIN
return __builtin_floorl (x);
#else
/* Use generic implementation. */
- int64_t i0,i1,j0;
- uint64_t i,j;
- GET_LDOUBLE_WORDS64(i0,i1,x);
- j0 = ((i0>>48)&0x7fff)-0x3fff;
- if(j0<48) {
- if(j0<0) {
- /* return 0*sign(x) if |x|<1 */
- if(i0>=0) {i0=i1=0;}
- else if(((i0&0x7fffffffffffffffLL)|i1)!=0)
- { i0=0xbfff000000000000ULL;i1=0;}
- } else {
- i = (0x0000ffffffffffffULL)>>j0;
- if(((i0&i)|i1)==0) return x; /* x is integral */
- if(i0<0) i0 += (0x0001000000000000LL)>>j0;
- i0 &= (~i); i1=0;
+ int64_t i0, i1, j0;
+ uint64_t i, j;
+ GET_LDOUBLE_WORDS64 (i0, i1, x);
+ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
+ if (j0 < 48)
+ {
+ if (j0 < 0)
+ {
+ /* return 0 * sign (x) if |x| < 1 */
+ if (i0 >= 0)
+ {
+ i0 = i1 = 0;
}
- } else if (j0>111) {
- if(j0==0x4000) return x+x; /* inf or NaN */
- else return x; /* x is integral */
- } else {
- i = -1ULL>>(j0-48);
- if((i1&i)==0) return x; /* x is integral */
- if(i0<0) {
- if(j0==48) i0+=1;
- else {
- j = i1+(1LL<<(112-j0));
- if(j<i1) i0 +=1 ; /* got a carry */
- i1=j;
- }
+ else if (((i0 & 0x7fffffffffffffffLL) | i1) != 0)
+ {
+ i0 = 0xbfff000000000000ULL;
+ i1 = 0;
}
- i1 &= (~i);
}
- SET_LDOUBLE_WORDS64(x,i0,i1);
- return x;
+ else
+ {
+ i = (0x0000ffffffffffffULL) >> j0;
+ if (((i0 & i) | i1) == 0)
+ return x; /* x is integral */
+ if (i0 < 0)
+ i0 += (0x0001000000000000LL) >> j0;
+ i0 &= (~i);
+ i1 = 0;
+ }
+ }
+ else if (j0 > 111)
+ {
+ if (j0 == 0x4000)
+ return x + x; /* inf or NaN */
+ else
+ return x; /* x is integral */
+ }
+ else
+ {
+ i = -1ULL >> (j0 - 48);
+ if ((i1 & i) == 0)
+ return x; /* x is integral */
+ if (i0 < 0)
+ {
+ if (j0 == 48)
+ i0 += 1;
+ else
+ {
+ j = i1 + (1LL << (112 - j0));
+ if (j < i1)
+ i0 += 1 ; /* got a carry */
+ i1 = j;
+ }
+ }
+ i1 &= (~i);
+ }
+ SET_LDOUBLE_WORDS64 (x, i0, i1);
+ return x;
#endif /* ! USE_FLOORL_BUILTIN */
}
libm_alias_ldouble (__floor, floor)
--
2.18.2

View File

@ -0,0 +1,207 @@
From 77b9cf86bba41d44e084337a11bfbf5ee7c98a38 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:27 +0100
Subject: [PATCH 17/28] Adjust s_ceilf.c and s_ceill.c regarding code style.
This patch just adjusts the generic implementation regarding code style.
No functional change.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 171d23d7cbce7b6f175a6690e625ccf80b647d23)
---
sysdeps/ieee754/flt-32/s_ceilf.c | 54 +++++++++++-------
sysdeps/ieee754/ldbl-128/s_ceill.c | 91 +++++++++++++++++++-----------
2 files changed, 92 insertions(+), 53 deletions(-)
diff --git a/sysdeps/ieee754/flt-32/s_ceilf.c b/sysdeps/ieee754/flt-32/s_ceilf.c
index 6cab7bdd62..f60d0ac1f5 100644
--- a/sysdeps/ieee754/flt-32/s_ceilf.c
+++ b/sysdeps/ieee754/flt-32/s_ceilf.c
@@ -19,34 +19,46 @@
#include <math-use-builtins.h>
float
-__ceilf(float x)
+__ceilf (float x)
{
#if USE_CEILF_BUILTIN
return __builtin_ceilf (x);
#else
/* Use generic implementation. */
- int32_t i0,j0;
- uint32_t i;
+ int32_t i0, j0;
+ uint32_t i;
- GET_FLOAT_WORD(i0,x);
- j0 = ((i0>>23)&0xff)-0x7f;
- if(j0<23) {
- if(j0<0) {
- /* return 0*sign(x) if |x|<1 */
- if(i0<0) {i0=0x80000000;}
- else if(i0!=0) { i0=0x3f800000;}
- } else {
- i = (0x007fffff)>>j0;
- if((i0&i)==0) return x; /* x is integral */
- if(i0>0) i0 += (0x00800000)>>j0;
- i0 &= (~i);
- }
- } else {
- if(__builtin_expect(j0==0x80, 0)) return x+x; /* inf or NaN */
- else return x; /* x is integral */
+ GET_FLOAT_WORD (i0, x);
+ j0 = ((i0 >> 23) & 0xff) - 0x7f;
+ if (j0 < 23)
+ {
+ if (j0 < 0)
+ {
+ /* return 0 * sign (x) if |x| < 1 */
+ if (i0 < 0)
+ i0 = 0x80000000;
+ else if (i0 != 0)
+ i0 = 0x3f800000;
}
- SET_FLOAT_WORD(x,i0);
- return x;
+ else
+ {
+ i = (0x007fffff) >> j0;
+ if ((i0 & i) == 0)
+ return x; /* x is integral */
+ if (i0 > 0)
+ i0 += (0x00800000) >> j0;
+ i0 &= (~i);
+ }
+ }
+ else
+ {
+ if (__glibc_unlikely (j0 == 0x80))
+ return x + x; /* inf or NaN */
+ else
+ return x; /* x is integral */
+ }
+ SET_FLOAT_WORD (x, i0);
+ return x;
#endif /* ! USE_CEILF_BUILTIN */
}
#ifndef __ceilf
diff --git a/sysdeps/ieee754/ldbl-128/s_ceill.c b/sysdeps/ieee754/ldbl-128/s_ceill.c
index d212d86179..df75dc3008 100644
--- a/sysdeps/ieee754/ldbl-128/s_ceill.c
+++ b/sysdeps/ieee754/ldbl-128/s_ceill.c
@@ -13,7 +13,7 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
+#if defined (LIBM_SCCS) && ! defined (lint)
static char rcsid[] = "$NetBSD: $";
#endif
@@ -29,45 +29,72 @@ static char rcsid[] = "$NetBSD: $";
#include <libm-alias-ldouble.h>
#include <math-use-builtins.h>
-_Float128 __ceill(_Float128 x)
+_Float128
+__ceill (_Float128 x)
{
#if USE_CEILL_BUILTIN
return __builtin_ceill (x);
#else
/* Use generic implementation. */
- int64_t i0,i1,j0;
- uint64_t i,j;
- GET_LDOUBLE_WORDS64(i0,i1,x);
- j0 = ((i0>>48)&0x7fff)-0x3fff;
- if(j0<48) {
- if(j0<0) {
- /* return 0*sign(x) if |x|<1 */
- if(i0<0) {i0=0x8000000000000000ULL;i1=0;}
- else if((i0|i1)!=0) { i0=0x3fff000000000000ULL;i1=0;}
- } else {
- i = (0x0000ffffffffffffULL)>>j0;
- if(((i0&i)|i1)==0) return x; /* x is integral */
- if(i0>0) i0 += (0x0001000000000000LL)>>j0;
- i0 &= (~i); i1=0;
+ int64_t i0, i1, j0;
+ uint64_t i, j;
+ GET_LDOUBLE_WORDS64 (i0, i1, x);
+ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
+ if (j0 < 48)
+ {
+ if (j0 < 0)
+ {
+ /* return 0 * sign (x) if |x| < 1 */
+ if (i0 < 0)
+ {
+ i0 = 0x8000000000000000ULL;
+ i1 = 0;
}
- } else if (j0>111) {
- if(j0==0x4000) return x+x; /* inf or NaN */
- else return x; /* x is integral */
- } else {
- i = -1ULL>>(j0-48);
- if((i1&i)==0) return x; /* x is integral */
- if(i0>0) {
- if(j0==48) i0+=1;
- else {
- j = i1+(1LL<<(112-j0));
- if(j<i1) i0 +=1 ; /* got a carry */
- i1=j;
- }
+ else if ((i0 | i1) != 0)
+ {
+ i0 = 0x3fff000000000000ULL;
+ i1 = 0;
}
- i1 &= (~i);
}
- SET_LDOUBLE_WORDS64(x,i0,i1);
- return x;
+ else
+ {
+ i = (0x0000ffffffffffffULL) >> j0;
+ if (((i0 & i) | i1) == 0)
+ return x; /* x is integral */
+ if (i0 > 0)
+ i0 += (0x0001000000000000LL) >> j0;
+ i0 &= (~i);
+ i1 = 0;
+ }
+ }
+ else if (j0 > 111)
+ {
+ if (j0 == 0x4000)
+ return x + x; /* inf or NaN */
+ else
+ return x; /* x is integral */
+ }
+ else
+ {
+ i = -1ULL >> (j0 - 48);
+ if ((i1 & i) == 0)
+ return x; /* x is integral */
+ if (i0 > 0)
+ {
+ if (j0 == 48)
+ i0 += 1;
+ else
+ {
+ j = i1 + (1LL << (112 - j0));
+ if (j < i1)
+ i0 += 1; /* got a carry */
+ i1 = j;
+ }
+ }
+ i1 &= (~i);
+ }
+ SET_LDOUBLE_WORDS64 (x, i0, i1);
+ return x;
#endif /* ! USE_CEILL_BUILTIN */
}
libm_alias_ldouble (__ceil, ceil)
--
2.18.2

View File

@ -0,0 +1,57 @@
From f6e3f49613f4a31bce8c5f52ae440f9c7b3646fb Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:28 +0100
Subject: [PATCH 18/28] Adjust s_copysignl.c regarding code style.
This patch just adjusts the generic implementation regarding code style.
No functional change.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 1902d5d5ff04771f16b67648789c75a18af06222)
---
sysdeps/ieee754/ldbl-128/s_copysignl.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/sysdeps/ieee754/ldbl-128/s_copysignl.c b/sysdeps/ieee754/ldbl-128/s_copysignl.c
index 4cae8612dc..9b0e44cf1d 100644
--- a/sysdeps/ieee754/ldbl-128/s_copysignl.c
+++ b/sysdeps/ieee754/ldbl-128/s_copysignl.c
@@ -13,7 +13,7 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
+#if defined (LIBM_SCCS) && ! defined (lint)
static char rcsid[] = "$NetBSD: $";
#endif
@@ -28,18 +28,19 @@ static char rcsid[] = "$NetBSD: $";
#include <libm-alias-ldouble.h>
#include <math-use-builtins.h>
-_Float128 __copysignl(_Float128 x, _Float128 y)
+_Float128
+__copysignl (_Float128 x, _Float128 y)
{
#if USE_COPYSIGNL_BUILTIN
return __builtin_copysignl (x, y);
#else
/* Use generic implementation. */
- uint64_t hx,hy;
- GET_LDOUBLE_MSW64(hx,x);
- GET_LDOUBLE_MSW64(hy,y);
- SET_LDOUBLE_MSW64(x,(hx&0x7fffffffffffffffULL)
- |(hy&0x8000000000000000ULL));
- return x;
+ uint64_t hx, hy;
+ GET_LDOUBLE_MSW64 (hx, x);
+ GET_LDOUBLE_MSW64 (hy, y);
+ SET_LDOUBLE_MSW64 (x, (hx & 0x7fffffffffffffffULL)
+ | (hy & 0x8000000000000000ULL));
+ return x;
#endif /* ! USE_COPYSIGNL_BUILTIN */
}
libm_alias_ldouble (__copysign, copysign)
--
2.18.2

View File

@ -0,0 +1,157 @@
From 855d045bc26175195dadafc28abf84e7b6613aac Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:28 +0100
Subject: [PATCH 19/28] S390: Use load-fp-integer instruction for roundeven
functions.
If compiled with z196 zarch support, the load-fp-integer instruction
is used to implement roundeven, roundevenf, roundevenl.
Otherwise the common-code implementation is used.
(cherry picked from commit 4399b163376b331773e43917dcf56ce68e43e6a0)
---
sysdeps/s390/fpu/s_roundeven.c | 39 +++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_roundevenf.c | 38 ++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_roundevenl.c | 39 +++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+)
create mode 100644 sysdeps/s390/fpu/s_roundeven.c
create mode 100644 sysdeps/s390/fpu/s_roundevenf.c
create mode 100644 sysdeps/s390/fpu/s_roundevenl.c
diff --git a/sysdeps/s390/fpu/s_roundeven.c b/sysdeps/s390/fpu/s_roundeven.c
new file mode 100644
index 0000000000..95a83a70e8
--- /dev/null
+++ b/sysdeps/s390/fpu/s_roundeven.c
@@ -0,0 +1,39 @@
+/* roundeven() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <libm-alias-double.h>
+
+double
+__roundeven (double x)
+{
+ double y;
+ /* The z196 zarch "load fp integer" (fidbra) instruction is rounding
+ x to the nearest integer with "ties to even" rounding mode
+ (M3-field: 4) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ ("fidbra %0,4,%1,4" : "=f" (y) : "f" (x));
+ return y;
+}
+hidden_def (__roundeven)
+libm_alias_double (__roundeven, roundeven)
+
+#else
+# include <sysdeps/ieee754/dbl-64/s_roundeven.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_roundevenf.c b/sysdeps/s390/fpu/s_roundevenf.c
new file mode 100644
index 0000000000..c620a0189c
--- /dev/null
+++ b/sysdeps/s390/fpu/s_roundevenf.c
@@ -0,0 +1,38 @@
+/* roundevenf() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <libm-alias-float.h>
+
+float
+__roundevenf (float x)
+{
+ float y;
+ /* The z196 zarch "load fp integer" (fiebra) instruction is rounding
+ x to the nearest integer with "ties to even" rounding mode
+ (M3-field: 4) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ ("fiebra %0,4,%1,4" : "=f" (y) : "f" (x));
+ return y;
+}
+libm_alias_float (__roundeven, roundeven)
+
+#else
+# include <sysdeps/ieee754/flt-32/s_roundevenf.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_roundevenl.c b/sysdeps/s390/fpu/s_roundevenl.c
new file mode 100644
index 0000000000..3481af2665
--- /dev/null
+++ b/sysdeps/s390/fpu/s_roundevenl.c
@@ -0,0 +1,39 @@
+/* roundevenl() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <math_private.h>
+# include <libm-alias-ldouble.h>
+
+_Float128
+__roundevenl (_Float128 x)
+{
+ _Float128 y;
+ /* The z196 zarch "load fp integer" (fixbra) instruction is rounding
+ x to the nearest integer with "ties to even" rounding mode
+ (M3-field: 4) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ ("fixbra %0,4,%1,4" : "=f" (y) : "f" (x));
+ return y;
+}
+libm_alias_ldouble (__roundeven, roundeven)
+
+#else
+# include <sysdeps/ieee754/ldbl-128/s_roundevenl.c>
+#endif
--
2.18.2

View File

@ -0,0 +1,207 @@
From 90e84ac5ac8e774ce0cfd3abc5f7d8834efd2c9b Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:29 +0100
Subject: [PATCH 20/28] S390: Use convert-to-fixed instruction for lrint
functions.
If compiled with z196 zarch support, the convert-to-fixed instruction
is used to implement lrint, lrintf, lrintl.
Otherwise the common-code implementation is used.
(cherry picked from commit e3f07622209c1b4436ef364b134dfd2cd4ca9976)
---
sysdeps/s390/fpu/s_lrint.c | 55 ++++++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_lrintf.c | 55 ++++++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_lrintl.c | 56 +++++++++++++++++++++++++++++++++++++
3 files changed, 166 insertions(+)
create mode 100644 sysdeps/s390/fpu/s_lrint.c
create mode 100644 sysdeps/s390/fpu/s_lrintf.c
create mode 100644 sysdeps/s390/fpu/s_lrintl.c
diff --git a/sysdeps/s390/fpu/s_lrint.c b/sysdeps/s390/fpu/s_lrint.c
new file mode 100644
index 0000000000..7be60665b5
--- /dev/null
+++ b/sysdeps/s390/fpu/s_lrint.c
@@ -0,0 +1,55 @@
+/* lrint() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <libm-alias-double.h>
+
+/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte).
+ Thus we need different instructions as the target size is encoded there.
+ Note: On s390 this instruction is only used if build with -mzarch. */
+# ifdef __s390x__
+# define INSN "cgdbra"
+# else
+# define INSN "cfdbra"
+# endif
+
+long int
+__lrint (double x)
+{
+ long int y;
+ /* The z196 zarch "convert to fixed" (cgdbra) instruction is rounding
+ according to current rounding mode (M3-field: 0).
+ First convert x with suppressed inexact exception and check if the
+ resulting value is beyond the target limits (indicated by cc=3;
+ Note: a nan is also indicated by cc=3).
+ If the resulting value is within the target limits, redo
+ without suppressing the inexact exception. */
+ __asm__ (INSN " %0,0,%1,4 \n\t"
+ "jo 1f \n\t"
+ INSN " %0,0,%1,0 \n\t"
+ "1:"
+ : "=&d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_double (__lrint, lrint)
+
+#else
+# include <sysdeps/ieee754/dbl-64/s_lrint.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_lrintf.c b/sysdeps/s390/fpu/s_lrintf.c
new file mode 100644
index 0000000000..d6a2a4081a
--- /dev/null
+++ b/sysdeps/s390/fpu/s_lrintf.c
@@ -0,0 +1,55 @@
+/* lrintf() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <libm-alias-float.h>
+
+/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte).
+ Thus we need different instructions as the target size is encoded there.
+ Note: On s390 this instruction is only used if build with -mzarch. */
+# ifdef __s390x__
+# define INSN "cgebra"
+# else
+# define INSN "cfebra"
+# endif
+
+long int
+__lrintf (float x)
+{
+ long int y;
+ /* The z196 zarch "convert to fixed" (cgebra) instruction is rounding
+ according to current rounding mode (M3-field: 0).
+ First convert x with suppressed inexact exception and check if the
+ resulting value is beyond the target limits (indicated by cc=3;
+ Note: a nan is also indicated by cc=3).
+ If the resulting value is within the target limits, redo
+ without suppressing the inexact exception. */
+ __asm__ (INSN " %0,0,%1,4 \n\t"
+ "jo 1f \n\t"
+ INSN " %0,0,%1,0 \n\t"
+ "1:"
+ : "=&d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_float (__lrint, lrint)
+
+#else
+# include <sysdeps/ieee754/flt-32/s_lrintf.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_lrintl.c b/sysdeps/s390/fpu/s_lrintl.c
new file mode 100644
index 0000000000..2d386ecff9
--- /dev/null
+++ b/sysdeps/s390/fpu/s_lrintl.c
@@ -0,0 +1,56 @@
+/* lrintl() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <math_private.h>
+# include <libm-alias-ldouble.h>
+
+/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte).
+ Thus we need different instructions as the target size is encoded there.
+ Note: On s390 this instruction is only used if build with -mzarch. */
+# ifdef __s390x__
+# define INSN "cgxbra"
+# else
+# define INSN "cfxbra"
+# endif
+
+long int
+__lrintl (_Float128 x)
+{
+ long int y;
+ /* The z196 zarch "convert to fixed" (cgxbra) instruction is rounding
+ according to current rounding mode (M3-field: 0).
+ First convert x with suppressed inexact exception and check if the
+ resulting value is beyond the target limits (indicated by cc=3;
+ Note: a nan is also indicated by cc=3).
+ If the resulting value is within the target limits, redo
+ without suppressing the inexact exception. */
+ __asm__ (INSN " %0,0,%1,4 \n\t"
+ "jo 1f \n\t"
+ INSN " %0,0,%1,0 \n\t"
+ "1:"
+ : "=&d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_ldouble (__lrint, lrint)
+
+#else
+# include <sysdeps/ieee754/ldbl-128/s_lrintl.c>
+#endif
--
2.18.2

View File

@ -0,0 +1,192 @@
From 429eff12541cc0779c381f84257c8860ece25b12 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:29 +0100
Subject: [PATCH 21/28] S390: Use convert-to-fixed instruction for llrint
functions.
If compiled with z196 zarch support, the convert-to-fixed instruction
is used to implement llrint, llrintf, llrintl.
Otherwise the common-code implementation is used.
(cherry picked from commit f10c1654fe13d797d2fd347dc47f72f93c58cf62)
---
sysdeps/s390/fpu/s_llrint.c | 50 +++++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_llrintf.c | 50 +++++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_llrintl.c | 51 ++++++++++++++++++++++++++++++++++++
3 files changed, 151 insertions(+)
create mode 100644 sysdeps/s390/fpu/s_llrint.c
create mode 100644 sysdeps/s390/fpu/s_llrintf.c
create mode 100644 sysdeps/s390/fpu/s_llrintl.c
diff --git a/sysdeps/s390/fpu/s_llrint.c b/sysdeps/s390/fpu/s_llrint.c
new file mode 100644
index 0000000000..edd796ae8c
--- /dev/null
+++ b/sysdeps/s390/fpu/s_llrint.c
@@ -0,0 +1,50 @@
+/* llrint() - S390 version.
+ Copyright (C) 2019 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 defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+/* We only support s390x as on s390 a long long int refers to a register pair
+ of two 4byte registers instead of a 8byte register which is produced by the
+ instruction.
+ Note: On s390 this instruction would only be used if build with -mzarch. */
+# include <math.h>
+# include <libm-alias-double.h>
+
+long long int
+__llrint (double x)
+{
+ long long int y;
+ /* The z196 zarch "convert to fixed" (cgdbra) instruction is rounding
+ according to current rounding mode (M3-field: 0).
+ First convert x with suppressed inexact exception and check if the
+ resulting value is beyond the target limits (indicated by cc=3;
+ Note: a nan is also indicated by cc=3).
+ If the resulting value is within the target limits, redo
+ without suppressing the inexact exception. */
+ __asm__ ("cgdbra %0,0,%1,4 \n\t"
+ "jo 1f \n\t"
+ "cgdbra %0,0,%1,0 \n\t"
+ "1:"
+ : "=&d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_double (__llrint, llrint)
+
+#else
+# include <sysdeps/ieee754/dbl-64/s_llrint.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_llrintf.c b/sysdeps/s390/fpu/s_llrintf.c
new file mode 100644
index 0000000000..3cbe7c581a
--- /dev/null
+++ b/sysdeps/s390/fpu/s_llrintf.c
@@ -0,0 +1,50 @@
+/* llrintf() - S390 version.
+ Copyright (C) 2019 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 defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+/* We only support s390x as on s390 a long long int refers to a register pair
+ of two 4byte registers instead of a 8byte register which is produced by the
+ instruction.
+ Note: On s390 this instruction would only be used if build with -mzarch. */
+# include <math.h>
+# include <libm-alias-float.h>
+
+long long int
+__llrintf (float x)
+{
+ long long int y;
+ /* The z196 zarch "convert to fixed" (cgebra) instruction is rounding
+ according to current rounding mode (M3-field: 0).
+ First convert x with suppressed inexact exception and check if the
+ resulting value is beyond the target limits (indicated by cc=3;
+ Note: a nan is also indicated by cc=3).
+ If the resulting value is within the target limits, redo
+ without suppressing the inexact exception. */
+ __asm__ ("cgebra %0,0,%1,4 \n\t"
+ "jo 1f \n\t"
+ "cgebra %0,0,%1,0 \n\t"
+ "1:"
+ : "=&d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_float (__llrint, llrint)
+
+#else
+# include <sysdeps/ieee754/flt-32/s_llrintf.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_llrintl.c b/sysdeps/s390/fpu/s_llrintl.c
new file mode 100644
index 0000000000..37eea5914f
--- /dev/null
+++ b/sysdeps/s390/fpu/s_llrintl.c
@@ -0,0 +1,51 @@
+/* llrintl() - S390 version.
+ Copyright (C) 2019 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 defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+/* We only support s390x as on s390 a long long int refers to a register pair
+ of two 4byte registers instead of a 8byte register which is produced by the
+ instruction.
+ Note: On s390 this instruction would only be used if build with -mzarch. */
+# include <math.h>
+# include <math_private.h>
+# include <libm-alias-ldouble.h>
+
+long long int
+__llrintl (_Float128 x)
+{
+ long long int y;
+ /* The z196 zarch "convert to fixed" (cgxbra) instruction is rounding
+ according to current rounding mode (M3-field: 0).
+ First convert x with suppressed inexact exception and check if the
+ resulting value is beyond the target limits (indicated by cc=3;
+ Note: a nan is also indicated by cc=3).
+ If the resulting value is within the target limits, redo
+ without suppressing the inexact exception. */
+ __asm__ ("cgxbra %0,0,%1,4 \n\t"
+ "jo 1f \n\t"
+ "cgxbra %0,0,%1,0 \n\t"
+ "1:"
+ : "=&d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_ldouble (__llrint, llrint)
+
+#else
+# include <sysdeps/ieee754/ldbl-128/s_llrintl.c>
+#endif
--
2.18.2

View File

@ -0,0 +1,183 @@
From 9f3ee7825b1eae00431ea6477fce8210aaced7db Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:30 +0100
Subject: [PATCH 22/28] S390: Use convert-to-fixed instruction for lround
functions.
If compiled with z196 zarch support, the convert-to-fixed instruction
is used to implement lround, lroundf, lroundl.
Otherwise the common-code implementation is used.
(cherry picked from commit 9d9f3527daf65fdca0eb46eaa324b81b8f94d88c)
---
sysdeps/s390/fpu/s_lround.c | 47 +++++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_lroundf.c | 47 +++++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_lroundl.c | 48 ++++++++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+)
create mode 100644 sysdeps/s390/fpu/s_lround.c
create mode 100644 sysdeps/s390/fpu/s_lroundf.c
create mode 100644 sysdeps/s390/fpu/s_lroundl.c
diff --git a/sysdeps/s390/fpu/s_lround.c b/sysdeps/s390/fpu/s_lround.c
new file mode 100644
index 0000000000..9290ec32cd
--- /dev/null
+++ b/sysdeps/s390/fpu/s_lround.c
@@ -0,0 +1,47 @@
+/* lround() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <libm-alias-double.h>
+
+/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte).
+ Thus we need different instructions as the target size is encoded there.
+ Note: On s390 this instruction is only used if build with -mzarch. */
+# ifdef __s390x__
+# define INSN "cgdbra"
+# else
+# define INSN "cfdbra"
+# endif
+
+long int
+__lround (double x)
+{
+ long int y;
+ /* The z196 zarch "convert to fixed" (cgdbra) instruction is rounding
+ x to the nearest integer with "ties away from 0" rounding mode
+ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ (INSN " %0,1,%1,4" : "=d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_double (__lround, lround)
+
+#else
+# include <sysdeps/ieee754/dbl-64/s_lround.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_lroundf.c b/sysdeps/s390/fpu/s_lroundf.c
new file mode 100644
index 0000000000..097b924c91
--- /dev/null
+++ b/sysdeps/s390/fpu/s_lroundf.c
@@ -0,0 +1,47 @@
+/* lroundf() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <libm-alias-float.h>
+
+/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte).
+ Thus we need different instructions as the target size is encoded there.
+ Note: On s390 this instruction is only used if build with -mzarch. */
+# ifdef __s390x__
+# define INSN "cgebra"
+# else
+# define INSN "cfebra"
+# endif
+
+long int
+__lroundf (float x)
+{
+ long int y;
+ /* The z196 zarch "convert to fixed" (cgebra) instruction is rounding
+ x to the nearest integer with "ties away from 0" rounding mode
+ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ (INSN " %0,1,%1,4" : "=d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_float (__lround, lround)
+
+#else
+# include <sysdeps/ieee754/flt-32/s_lroundf.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_lroundl.c b/sysdeps/s390/fpu/s_lroundl.c
new file mode 100644
index 0000000000..0ef77dc667
--- /dev/null
+++ b/sysdeps/s390/fpu/s_lroundl.c
@@ -0,0 +1,48 @@
+/* lroundl() - S390 version.
+ Copyright (C) 2019 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/>. */
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# include <math.h>
+# include <math_private.h>
+# include <libm-alias-ldouble.h>
+
+/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte).
+ Thus we need different instructions as the target size is encoded there.
+ Note: On s390 this instruction is only used if build with -mzarch. */
+# ifdef __s390x__
+# define INSN "cgxbra"
+# else
+# define INSN "cfxbra"
+# endif
+
+long int
+__lroundl (_Float128 x)
+{
+ long int y;
+ /* The z196 zarch "convert to fixed" (cgxbra) instruction is rounding
+ x to the nearest integer with "ties away from 0" rounding mode
+ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ (INSN " %0,1,%1,4" : "=d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_ldouble (__lround, lround)
+
+#else
+# include <sysdeps/ieee754/ldbl-128/s_lroundl.c>
+#endif
--
2.18.2

View File

@ -0,0 +1,168 @@
From dd8bfb911e89f3ad1da5cfa5618a8c52c62bb095 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:31 +0100
Subject: [PATCH 23/28] S390: Use convert-to-fixed instruction for llround
functions.
If compiled with z196 zarch support, the convert-to-fixed instruction
is used to implement llround, llroundf, llroundl.
Otherwise the common-code implementation is used.
(cherry picked from commit 7d42d614fdc2c9d9f6ad46111bd6130501d50460)
---
sysdeps/s390/fpu/s_llround.c | 42 ++++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_llroundf.c | 42 ++++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/s_llroundl.c | 43 +++++++++++++++++++++++++++++++++++
3 files changed, 127 insertions(+)
create mode 100644 sysdeps/s390/fpu/s_llround.c
create mode 100644 sysdeps/s390/fpu/s_llroundf.c
create mode 100644 sysdeps/s390/fpu/s_llroundl.c
diff --git a/sysdeps/s390/fpu/s_llround.c b/sysdeps/s390/fpu/s_llround.c
new file mode 100644
index 0000000000..f4a1b21637
--- /dev/null
+++ b/sysdeps/s390/fpu/s_llround.c
@@ -0,0 +1,42 @@
+/* llround() - S390 version.
+ Copyright (C) 2019 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 defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+/* We only support s390x as on s390 a long long int refers to a register pair
+ of two 4byte registers instead of a 8byte register which is produced by the
+ instruction.
+ Note: On s390 this instruction would only be used if build with -mzarch. */
+# include <math.h>
+# include <libm-alias-double.h>
+
+long long int
+__llround (double x)
+{
+ long long int y;
+ /* The z196 zarch "convert to fixed" (cgdbra) instruction is rounding
+ x to the nearest integer with "ties away from 0" rounding mode
+ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ ("cgdbra %0,1,%1,4" : "=d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_double (__llround, llround)
+
+#else
+# include <sysdeps/ieee754/dbl-64/s_llround.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_llroundf.c b/sysdeps/s390/fpu/s_llroundf.c
new file mode 100644
index 0000000000..d202f4be8c
--- /dev/null
+++ b/sysdeps/s390/fpu/s_llroundf.c
@@ -0,0 +1,42 @@
+/* llroundf() - S390 version.
+ Copyright (C) 2019 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 defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+/* We only support s390x as on s390 a long long int refers to a register pair
+ of two 4byte registers instead of a 8byte register which is produced by the
+ instruction.
+ Note: On s390 this instruction would only be used if build with -mzarch. */
+# include <math.h>
+# include <libm-alias-float.h>
+
+long long int
+__llroundf (float x)
+{
+ long long int y;
+ /* The z196 zarch "convert to fixed" (cgebra) instruction is rounding
+ x to the nearest integer with "ties away from 0" rounding mode
+ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ ("cgebra %0,1,%1,4" : "=d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_float (__llround, llround)
+
+#else
+# include <sysdeps/ieee754/flt-32/s_llroundf.c>
+#endif
diff --git a/sysdeps/s390/fpu/s_llroundl.c b/sysdeps/s390/fpu/s_llroundl.c
new file mode 100644
index 0000000000..58976cd5c5
--- /dev/null
+++ b/sysdeps/s390/fpu/s_llroundl.c
@@ -0,0 +1,43 @@
+/* llroundl() - S390 version.
+ Copyright (C) 2019 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 defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+/* We only support s390x as on s390 a long long int refers to a register pair
+ of two 4byte registers instead of a 8byte register which is produced by the
+ instruction.
+ Note: On s390 this instruction would only be used if build with -mzarch. */
+# include <math.h>
+# include <math_private.h>
+# include <libm-alias-ldouble.h>
+
+long long int
+__llroundl (_Float128 x)
+{
+ long long int y;
+ /* The z196 zarch "convert to fixed" (cgxbra) instruction is rounding
+ x to the nearest integer with "ties away from 0" rounding mode
+ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ ("cgxbra %0,1,%1,4" : "=d" (y) : "f" (x) : "cc");
+ return y;
+}
+libm_alias_ldouble (__llround, llround)
+
+#else
+# include <sysdeps/ieee754/ldbl-128/s_llroundl.c>
+#endif
--
2.18.2

View File

@ -0,0 +1,70 @@
From 33f3c934e3023b85c3774ee0482ec4da2a10a3b5 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:32 +0100
Subject: [PATCH 24/28] S390: Implement math-barriers math_opt_barrier and
math_force_eval.
This patch implements the s390 specific math barriers in order
to omit the store and load from stack if possible.
(cherry picked from commit 433a2ba68cd91842546e0f0d43d65835634d570d)
---
sysdeps/s390/fpu/math-barriers.h | 46 ++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
create mode 100644 sysdeps/s390/fpu/math-barriers.h
diff --git a/sysdeps/s390/fpu/math-barriers.h b/sysdeps/s390/fpu/math-barriers.h
new file mode 100644
index 0000000000..7c3e6b15e0
--- /dev/null
+++ b/sysdeps/s390/fpu/math-barriers.h
@@ -0,0 +1,46 @@
+/* Control when floating-point expressions are evaluated. s390 version.
+ Copyright (C) 2019 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 S390_MATH_BARRIERS_H
+#define S390_MATH_BARRIERS_H 1
+
+#ifdef HAVE_S390_VX_GCC_SUPPORT
+# define ASM_CONSTRAINT_VR "v"
+#else
+# define ASM_CONSTRAINT_VR
+#endif
+
+#define math_opt_barrier(x) \
+ ({ __typeof (x) __x = (x); \
+ if (__builtin_types_compatible_p (__typeof (x), _Float128)) \
+ __asm__ ("# math_opt_barrier_f128 %0" : "+fm" (__x)); \
+ else \
+ __asm__ ("# math_opt_barrier %0" \
+ : "+f" ASM_CONSTRAINT_VR "m" (__x)); \
+ __x; })
+#define math_force_eval(x) \
+ ({ __typeof (x) __x = (x); \
+ if (__builtin_types_compatible_p (__typeof (x), _Float128)) \
+ __asm__ __volatile__ ("# math_force_eval_f128 %0" \
+ : : "fm" (__x)); \
+ else \
+ __asm__ __volatile__ ("# math_force_eval %0" \
+ : : "f" ASM_CONSTRAINT_VR "m" (__x)); \
+ })
+
+#endif
--
2.18.2

View File

@ -0,0 +1,79 @@
From cf5397eb5b33bab37c16bcb2d1bbddbce1a27de2 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:33 +0100
Subject: [PATCH 25/28] S390: Implement roundtoint and converttoint and define
TOINT_INTRINSICS.
This patch implements roundtoint and convertoint for s390
by using the load-fp-integer and convert-to-fixed instructions.
Both functions are using "round to nearest with ties away from zero"
rounding mode and do not raise inexact exceptions.
(cherry picked from commit 2763d3145a326aa9afa613fe9e1b444cf912a883)
---
sysdeps/s390/fpu/math_private.h | 53 +++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
create mode 100644 sysdeps/s390/fpu/math_private.h
diff --git a/sysdeps/s390/fpu/math_private.h b/sysdeps/s390/fpu/math_private.h
new file mode 100644
index 0000000000..a1ae91a87c
--- /dev/null
+++ b/sysdeps/s390/fpu/math_private.h
@@ -0,0 +1,53 @@
+/* Configure optimized libm functions. S390 version.
+ Copyright (C) 2019 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 S390_MATH_PRIVATE_H
+#define S390_MATH_PRIVATE_H 1
+
+#include <stdint.h>
+#include <math.h>
+
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
+# define TOINT_INTRINSICS 1
+
+static inline double_t
+roundtoint (double_t x)
+{
+ double_t y;
+ /* The z196 zarch "load fp integer" (fidbra) instruction is rounding
+ x to the nearest integer with ties away from zero (M3-field: 1)
+ where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ ("fidbra %0,1,%1,4" : "=f" (y) : "f" (x));
+ return y;
+}
+
+static inline int32_t
+converttoint (double_t x)
+{
+ int32_t y;
+ /* The z196 zarch "convert to fixed" (cfdbra) instruction is rounding
+ x to the nearest integer with ties away from zero (M3-field: 1)
+ where inexact exceptions are suppressed (M4-field: 4). */
+ __asm__ ("cfdbra %0,1,%1,4" : "=d" (y) : "f" (x) : "cc");
+ return y;
+}
+#endif
+
+#include_next <math_private.h>
+
+#endif
--
2.18.2

View File

@ -0,0 +1,23 @@
From 363f9d7a6be5a3b400e3ea3daab583bccfcfa152 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:34 +0100
Subject: [PATCH 26/28] S390: Use sysdeps/ieee754/dbl-64/wordsize-64 on s390x.
This patch enables the usage of implementations in
sysdeps/ieee754/dbl-64/wordsize-64 on 64bit s390x.
(cherry picked from commit fcee34cc373daee6aa5320a6e1897cdf2005ab53)
---
sysdeps/s390/s390-64/Implies | 1 +
1 file changed, 1 insertion(+)
diff --git a/sysdeps/s390/s390-64/Implies b/sysdeps/s390/s390-64/Implies
index a8cae95f9d..7603c9859c 100644
--- a/sysdeps/s390/s390-64/Implies
+++ b/sysdeps/s390/s390-64/Implies
@@ -1 +1,2 @@
wordsize-64
+ieee754/dbl-64/wordsize-64
--
2.18.2

View File

@ -0,0 +1,294 @@
From 8e5e36d7ba097b8e110ab45794659156af182f54 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:31 +0100
Subject: [PATCH 27/28] S390: Implement libc_fe* macros.
This patch provides the s390 specific implementation for
libc_feholdexcept, libc_fesetround, libc_feholdexcept_setround,
libc_fetestexcept, libc_fesetenv, libc_feupdateenv_test,
libc_feupdateenv, libc_feholdsetround_ctx, libc_feresetround_ctx,
libc_feholdsetround_noex_ctx and libc_feresetround_noex_ctx.
(cherry picked from commit 7c94d036c17dfd352d11e9bf98e5d84122c1f95e)
Note: glibc-2.28 does not have a generic fenv_private.h.
Therefore include_next does not work. Instead fenv_private.h needs to
be included in the s390 specific mathp_private.h just before including
the generic math_private.h.
As the s390 specific math_private.h is introduced with the backport of
commit "S390: Implement roundtoint and converttoint and define TOINT_INTRINSICS.",
the order of cherry-picking was changed compared to upstream!
---
sysdeps/s390/fpu/fenv_private.h | 248 ++++++++++++++++++++++++++++++++
sysdeps/s390/fpu/math_private.h | 1 +
2 files changed, 249 insertions(+)
create mode 100644 sysdeps/s390/fpu/fenv_private.h
diff --git a/sysdeps/s390/fpu/fenv_private.h b/sysdeps/s390/fpu/fenv_private.h
new file mode 100644
index 0000000000..8899f8f434
--- /dev/null
+++ b/sysdeps/s390/fpu/fenv_private.h
@@ -0,0 +1,248 @@
+/* Private floating point rounding and exceptions handling. 390/s390x version.
+ Copyright (C) 2019 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 S390_FENV_PRIVATE_H
+#define S390_FENV_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+static __always_inline void
+libc_feholdexcept_s390 (fenv_t *envp)
+{
+ fpu_control_t fpc, fpc_new;
+
+ /* Store the environment. */
+ _FPU_GETCW (fpc);
+ envp->__fpc = fpc;
+
+ /* Clear the current exception flags and dxc field.
+ Hold from generating fpu exceptions temporarily. */
+ fpc_new = fpc & ~(FPC_FLAGS_MASK | FPC_DXC_MASK | FPC_EXCEPTION_MASK);
+
+ /* Only set new environment if it has changed. */
+ if (fpc_new != fpc)
+ _FPU_SETCW (fpc_new);
+}
+
+#define libc_feholdexcept libc_feholdexcept_s390
+#define libc_feholdexceptf libc_feholdexcept_s390
+#define libc_feholdexceptl libc_feholdexcept_s390
+
+static __always_inline void
+libc_fesetround_s390 (int round)
+{
+ __asm__ __volatile__ ("srnm 0(%0)" : : "a" (round));
+}
+
+#define libc_fesetround libc_fesetround_s390
+#define libc_fesetroundf libc_fesetround_s390
+#define libc_fesetroundl libc_fesetround_s390
+
+static __always_inline void
+libc_feholdexcept_setround_s390 (fenv_t *envp, int r)
+{
+ fpu_control_t fpc, fpc_new;
+
+ _FPU_GETCW (fpc);
+ envp->__fpc = fpc;
+
+ /* Clear the current exception flags and dxc field.
+ Hold from generating fpu exceptions temporarily.
+ Reset rounding mode bits. */
+ fpc_new = fpc & ~(FPC_FLAGS_MASK | FPC_DXC_MASK | FPC_EXCEPTION_MASK
+ | FPC_RM_MASK);
+
+ /* Set new rounding mode. */
+ fpc_new |= (r & FPC_RM_MASK);
+
+ /* Only set new environment if it has changed. */
+ if (fpc_new != fpc)
+ _FPU_SETCW (fpc_new);
+}
+
+#define libc_feholdexcept_setround libc_feholdexcept_setround_s390
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround_s390
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround_s390
+
+static __always_inline int
+libc_fetestexcept_s390 (int excepts)
+{
+ int res;
+ fexcept_t fpc;
+
+ _FPU_GETCW (fpc);
+
+ /* Get current exceptions. */
+ res = (fpc >> FPC_FLAGS_SHIFT) & FE_ALL_EXCEPT;
+ if ((fpc & FPC_NOT_FPU_EXCEPTION) == 0)
+ /* Bits 6, 7 of dxc-byte are zero,
+ thus bits 0-5 of dxc-byte correspond to the flag-bits.
+ Evaluate flags and last dxc-exception-code. */
+ res |= (fpc >> FPC_DXC_SHIFT) & FE_ALL_EXCEPT;
+
+ return res & excepts;
+}
+
+#define libc_fetestexcept libc_fetestexcept_s390
+#define libc_fetestexceptf libc_fetestexcept_s390
+#define libc_fetestexceptl libc_fetestexcept_s390
+
+static __always_inline void
+libc_fesetenv_s390 (const fenv_t *envp)
+{
+ _FPU_SETCW (envp->__fpc);
+}
+
+#define libc_fesetenv libc_fesetenv_s390
+#define libc_fesetenvf libc_fesetenv_s390
+#define libc_fesetenvl libc_fesetenv_s390
+
+static __always_inline int
+libc_feupdateenv_test_s390 (const fenv_t *envp, int ex)
+{
+ /* Get the currently raised exceptions. */
+ int excepts;
+ fexcept_t fpc_old;
+
+ _FPU_GETCW (fpc_old);
+
+ /* Get current exceptions. */
+ excepts = (fpc_old >> FPC_FLAGS_SHIFT) & FE_ALL_EXCEPT;
+ if ((fpc_old & FPC_NOT_FPU_EXCEPTION) == 0)
+ /* Bits 6, 7 of dxc-byte are zero,
+ thus bits 0-5 of dxc-byte correspond to the flag-bits.
+ Evaluate flags and last dxc-exception-code. */
+ excepts |= (fpc_old >> FPC_DXC_SHIFT) & FE_ALL_EXCEPT;
+
+ /* Merge the currently raised exceptions with those in envp. */
+ fpu_control_t fpc_new = envp->__fpc;
+ fpc_new |= excepts << FPC_FLAGS_SHIFT;
+
+ /* Install the new fpc from envp. */
+ if (fpc_new != fpc_old)
+ _FPU_SETCW (fpc_new);
+
+ /* Raise the exceptions if enabled in new fpc. */
+ if (__glibc_unlikely ((fpc_new >> FPC_EXCEPTION_MASK_SHIFT) & excepts))
+ __feraiseexcept (excepts);
+
+ return excepts & ex;
+}
+
+#define libc_feupdateenv_test libc_feupdateenv_test_s390
+#define libc_feupdateenv_testf libc_feupdateenv_test_s390
+#define libc_feupdateenv_testl libc_feupdateenv_test_s390
+
+static __always_inline void
+libc_feupdateenv_s390 (const fenv_t *envp)
+{
+ libc_feupdateenv_test_s390 (envp, 0);
+}
+
+#define libc_feupdateenv libc_feupdateenv_s390
+#define libc_feupdateenvf libc_feupdateenv_s390
+#define libc_feupdateenvl libc_feupdateenv_s390
+
+static __always_inline fenv_t
+libc_handle_user_fenv_s390 (const fenv_t *envp)
+{
+ fenv_t env;
+ if (envp == FE_DFL_ENV)
+ {
+ env.__fpc = _FPU_DEFAULT;
+ }
+ else if (envp == FE_NOMASK_ENV)
+ {
+ env.__fpc = FPC_EXCEPTION_MASK;
+ }
+ else
+ env = (*envp);
+
+ return env;
+}
+
+/* We have support for rounding mode context. */
+#define HAVE_RM_CTX 1
+
+static __always_inline void
+libc_feholdsetround_s390_ctx (struct rm_ctx *ctx, int r)
+{
+ fpu_control_t fpc;
+ int round;
+
+ _FPU_GETCW (fpc);
+ ctx->env.__fpc = fpc;
+
+ /* Check whether rounding modes are different. */
+ round = fpc & FPC_RM_MASK;
+
+ /* Set the rounding mode if changed. */
+ if (__glibc_unlikely (round != r))
+ {
+ ctx->updated_status = true;
+ libc_fesetround_s390 (r);
+ }
+ else
+ ctx->updated_status = false;
+}
+
+#define libc_feholdsetround_ctx libc_feholdsetround_s390_ctx
+#define libc_feholdsetroundf_ctx libc_feholdsetround_s390_ctx
+#define libc_feholdsetroundl_ctx libc_feholdsetround_s390_ctx
+
+static __always_inline void
+libc_feresetround_s390_ctx (struct rm_ctx *ctx)
+{
+ /* Restore the rounding mode if updated. */
+ if (__glibc_unlikely (ctx->updated_status))
+ {
+ fpu_control_t fpc;
+ _FPU_GETCW (fpc);
+ fpc = ctx->env.__fpc | (fpc & FPC_FLAGS_MASK);
+ _FPU_SETCW (fpc);
+ }
+}
+
+#define libc_feresetround_ctx libc_feresetround_s390_ctx
+#define libc_feresetroundf_ctx libc_feresetround_s390_ctx
+#define libc_feresetroundl_ctx libc_feresetround_s390_ctx
+
+static __always_inline void
+libc_feholdsetround_noex_s390_ctx (struct rm_ctx *ctx, int r)
+{
+ libc_feholdexcept_setround_s390 (&ctx->env, r);
+}
+
+#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_s390_ctx
+#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_s390_ctx
+#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_s390_ctx
+
+static __always_inline void
+libc_feresetround_noex_s390_ctx (struct rm_ctx *ctx)
+{
+ /* Restore exception flags and rounding mode. */
+ libc_fesetenv_s390 (&ctx->env);
+}
+
+#define libc_feresetround_noex_ctx libc_feresetround_noex_s390_ctx
+#define libc_feresetround_noexf_ctx libc_feresetround_noex_s390_ctx
+#define libc_feresetround_noexl_ctx libc_feresetround_noex_s390_ctx
+
+#endif
diff --git a/sysdeps/s390/fpu/math_private.h b/sysdeps/s390/fpu/math_private.h
index a1ae91a87c..f3c770d59a 100644
--- a/sysdeps/s390/fpu/math_private.h
+++ b/sysdeps/s390/fpu/math_private.h
@@ -48,6 +48,7 @@ converttoint (double_t x)
}
#endif
+#include <fenv_private.h>
#include_next <math_private.h>
#endif
--
2.18.2

View File

@ -0,0 +1,317 @@
From 2ab6ce8252a14e6ef0cfb33046dd565ae15085c2 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:32 +0100
Subject: [PATCH 28/28] S390: Use libc_fe* macros in fe* functions.
This patch updates the s390 specific functions fegetround,
fesetround, feholdexcept, fesetenv, feupdateenv, fegetexceptflag,
fetestexcept, fesetexceptflag, fetestexceptflag.
Now those functions are using the libc_fe* macros if possible.
Furthermore fegetexceptflag is now returning the exception from
dxc field shifted to the usual exception-flags.
Thus a special fetestexceptflag implementation is not needed anymore.
(cherry picked from commit 238adf59db85646ebae47876819bd896dae597bc)
---
sysdeps/s390/fpu/fegetround.c | 9 ++-------
sysdeps/s390/fpu/feholdexcpt.c | 12 ++---------
sysdeps/s390/fpu/fesetenv.c | 21 +++----------------
sysdeps/s390/fpu/fesetround.c | 9 +++------
sysdeps/s390/fpu/fetestexceptflag.c | 31 -----------------------------
sysdeps/s390/fpu/feupdateenv.c | 14 +++----------
sysdeps/s390/fpu/fgetexcptflg.c | 16 ++-------------
sysdeps/s390/fpu/fsetexcptflg.c | 23 ++++++++++-----------
sysdeps/s390/fpu/ftestexcept.c | 16 ++-------------
9 files changed, 27 insertions(+), 124 deletions(-)
delete mode 100644 sysdeps/s390/fpu/fetestexceptflag.c
diff --git a/sysdeps/s390/fpu/fegetround.c b/sysdeps/s390/fpu/fegetround.c
index 3c38bc9189..f1be1d12e1 100644
--- a/sysdeps/s390/fpu/fegetround.c
+++ b/sysdeps/s390/fpu/fegetround.c
@@ -17,17 +17,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <fenv_libc.h>
-#include <fpu_control.h>
+#include <get-rounding-mode.h>
int
__fegetround (void)
{
- fexcept_t cw;
-
- _FPU_GETCW (cw);
-
- return cw & FPC_RM_MASK;
+ return get_rounding_mode ();
}
libm_hidden_def (__fegetround)
weak_alias (__fegetround, fegetround)
diff --git a/sysdeps/s390/fpu/feholdexcpt.c b/sysdeps/s390/fpu/feholdexcpt.c
index 5daee5675d..48af7ff51b 100644
--- a/sysdeps/s390/fpu/feholdexcpt.c
+++ b/sysdeps/s390/fpu/feholdexcpt.c
@@ -17,19 +17,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <fenv_libc.h>
-#include <fpu_control.h>
+#include <fenv_private.h>
int __feholdexcept (fenv_t *envp)
{
- fexcept_t fpc;
- /* Store the environment. */
- __fegetenv (envp);
- /* Clear the current sticky bits as more than one exception
- may be generated. */
- fpc = envp->__fpc & ~(FPC_FLAGS_MASK | FPC_DXC_MASK);
- /* Hold from generating fpu exceptions temporarily. */
- _FPU_SETCW ((fpc & ~(FE_ALL_EXCEPT << FPC_EXCEPTION_MASK_SHIFT)));
+ libc_feholdexcept_s390 (envp);
return 0;
}
libm_hidden_def (__feholdexcept)
diff --git a/sysdeps/s390/fpu/fesetenv.c b/sysdeps/s390/fpu/fesetenv.c
index c6c275d79d..54ba2aa94a 100644
--- a/sysdeps/s390/fpu/fesetenv.c
+++ b/sysdeps/s390/fpu/fesetenv.c
@@ -17,28 +17,13 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <fenv_libc.h>
-#include <fpu_control.h>
-#include <stddef.h>
-#include <unistd.h>
+#include <fenv_private.h>
int
__fesetenv (const fenv_t *envp)
{
- fenv_t env;
-
- if (envp == FE_DFL_ENV)
- {
- env.__fpc = _FPU_DEFAULT;
- }
- else if (envp == FE_NOMASK_ENV)
- {
- env.__fpc = FPC_EXCEPTION_MASK;
- }
- else
- env = (*envp);
-
- _FPU_SETCW (env.__fpc);
+ fenv_t env = libc_handle_user_fenv_s390 (envp);
+ libc_fesetenv_s390 (&env);
/* Success. */
return 0;
diff --git a/sysdeps/s390/fpu/fesetround.c b/sysdeps/s390/fpu/fesetround.c
index d8a84d2c96..0a7fe2635b 100644
--- a/sysdeps/s390/fpu/fesetround.c
+++ b/sysdeps/s390/fpu/fesetround.c
@@ -17,21 +17,18 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <fenv_libc.h>
-#include <fpu_control.h>
+#include <fenv_private.h>
int
__fesetround (int round)
{
- if ((round|FPC_RM_MASK) != FPC_RM_MASK)
+ if ((round | FPC_RM_MASK) != FPC_RM_MASK)
{
/* ROUND is not a valid rounding mode. */
return 1;
}
- __asm__ __volatile__ ("srnm 0(%0)"
- :
- : "a" (round));
+ libc_fesetround_s390 (round);
return 0;
}
libm_hidden_def (__fesetround)
diff --git a/sysdeps/s390/fpu/fetestexceptflag.c b/sysdeps/s390/fpu/fetestexceptflag.c
deleted file mode 100644
index 784d356f7b..0000000000
--- a/sysdeps/s390/fpu/fetestexceptflag.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Test exception in saved exception state. S/390 version.
- Copyright (C) 2016-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <fenv.h>
-#include <fenv_libc.h>
-
-int
-fetestexceptflag (const fexcept_t *flagp, int excepts)
-{
- /* As *flagp is obtained by an earlier call of fegetexceptflag the
- bits 0-5 of dxc-byte are either zero or correspond to the
- flag-bits. Evaluate flags and last dxc-exception-code. */
- return (((*flagp >> FPC_FLAGS_SHIFT) | (*flagp >> FPC_DXC_SHIFT))
- & excepts
- & FE_ALL_EXCEPT);
-}
diff --git a/sysdeps/s390/fpu/feupdateenv.c b/sysdeps/s390/fpu/feupdateenv.c
index 4888e1a864..f6b3d7d2de 100644
--- a/sysdeps/s390/fpu/feupdateenv.c
+++ b/sysdeps/s390/fpu/feupdateenv.c
@@ -18,21 +18,13 @@
<http://www.gnu.org/licenses/>. */
-#include <fenv_libc.h>
-#include <fpu_control.h>
+#include <fenv_private.h>
int
__feupdateenv (const fenv_t *envp)
{
- fexcept_t temp;
-
- _FPU_GETCW (temp);
- temp = (temp & FPC_FLAGS_MASK) >> FPC_FLAGS_SHIFT;
-
- /* Raise the exceptions since the last call to feholdenv */
- /* re install saved environment. */
- __fesetenv (envp);
- __feraiseexcept ((int) temp);
+ fenv_t env = libc_handle_user_fenv_s390 (envp);
+ libc_feupdateenv_s390 (&env);
/* Success. */
return 0;
diff --git a/sysdeps/s390/fpu/fgetexcptflg.c b/sysdeps/s390/fpu/fgetexcptflg.c
index 2a0f6dc77c..1985b396c9 100644
--- a/sysdeps/s390/fpu/fgetexcptflg.c
+++ b/sysdeps/s390/fpu/fgetexcptflg.c
@@ -17,24 +17,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <fenv_libc.h>
-#include <fpu_control.h>
+#include <fenv_private.h>
int
fegetexceptflag (fexcept_t *flagp, int excepts)
{
- fexcept_t temp, newexcepts;
-
- /* Get the current exceptions. */
- _FPU_GETCW (temp);
- newexcepts = excepts << FPC_FLAGS_SHIFT;
- if ((temp & FPC_NOT_FPU_EXCEPTION) == 0)
- /* Bits 6, 7 of dxc-byte are zero,
- thus bits 0-5 of dxc-byte correspond to the flag-bits.
- Evaluate flags and last dxc-exception-code. */
- newexcepts |= excepts << FPC_DXC_SHIFT;
-
- *flagp = temp & newexcepts;
+ *flagp = libc_fetestexcept_s390 (excepts);
/* Success. */
return 0;
diff --git a/sysdeps/s390/fpu/fsetexcptflg.c b/sysdeps/s390/fpu/fsetexcptflg.c
index e50684c574..51d258cf17 100644
--- a/sysdeps/s390/fpu/fsetexcptflg.c
+++ b/sysdeps/s390/fpu/fsetexcptflg.c
@@ -24,29 +24,26 @@
int
fesetexceptflag (const fexcept_t *flagp, int excepts)
{
- fexcept_t temp, newexcepts;
+ fexcept_t fpc, fpc_new;
/* Get the current environment. We have to do this since we cannot
separately set the status word. */
- _FPU_GETCW (temp);
- /* Install the new exception bits in the Accrued Exception Byte. */
- excepts = excepts & FE_ALL_EXCEPT;
- newexcepts = excepts << FPC_FLAGS_SHIFT;
- temp &= ~newexcepts;
- if ((temp & FPC_NOT_FPU_EXCEPTION) == 0)
+ _FPU_GETCW (fpc);
+
+ /* Clear the current exception bits. */
+ fpc_new = fpc & ~((excepts & FE_ALL_EXCEPT) << FPC_FLAGS_SHIFT);
+ if ((fpc & FPC_NOT_FPU_EXCEPTION) == 0)
/* Bits 6, 7 of dxc-byte are zero,
thus bits 0-5 of dxc-byte correspond to the flag-bits.
Clear given exceptions in dxc-field. */
- temp &= ~(excepts << FPC_DXC_SHIFT);
+ fpc_new &= ~((excepts & FE_ALL_EXCEPT) << FPC_DXC_SHIFT);
- /* Integrate dxc-byte of flagp into flags. The dxc-byte of flagp contains
- either an ieee-exception or 0 (see fegetexceptflag). */
- temp |= (*flagp | ((*flagp >> FPC_DXC_SHIFT) << FPC_FLAGS_SHIFT))
- & newexcepts;
+ /* Set exceptions from flagp in flags-field. */
+ fpc_new |= (*flagp & excepts & FE_ALL_EXCEPT) << FPC_FLAGS_SHIFT;
/* Store the new status word (along with the rest of the environment.
Possibly new exceptions are set but they won't get executed. */
- _FPU_SETCW (temp);
+ _FPU_SETCW (fpc_new);
/* Success. */
return 0;
diff --git a/sysdeps/s390/fpu/ftestexcept.c b/sysdeps/s390/fpu/ftestexcept.c
index 727b9b342d..f2acecc1af 100644
--- a/sysdeps/s390/fpu/ftestexcept.c
+++ b/sysdeps/s390/fpu/ftestexcept.c
@@ -17,23 +17,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <fenv_libc.h>
-#include <fpu_control.h>
+#include <fenv_private.h>
int
fetestexcept (int excepts)
{
- fexcept_t temp, res;
-
- /* Get current exceptions. */
- _FPU_GETCW (temp);
- res = temp >> FPC_FLAGS_SHIFT;
- if ((temp & FPC_NOT_FPU_EXCEPTION) == 0)
- /* Bits 6, 7 of dxc-byte are zero,
- thus bits 0-5 of dxc-byte correspond to the flag-bits.
- Evaluate flags and last dxc-exception-code. */
- res |= temp >> FPC_DXC_SHIFT;
-
- return res & excepts & FE_ALL_EXCEPT;
+ return libc_fetestexcept_s390 (excepts);
}
libm_hidden_def (fetestexcept)
--
2.18.2

View File

@ -0,0 +1,160 @@
From af123aa95091d3d2d1b4ff027cf806ca1721d29d Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Wed, 11 Dec 2019 15:09:14 +0100
Subject: [PATCH 01/28] Always use wordsize-64 version of s_nearbyint.c.
This patch replaces s_nearbyint.c in sysdeps/dbl-64 with the one in
sysdeps/dbl-64/wordsize-64 and removes the latter one.
The code is not changed except changes in code style.
Also adjusted the include path in x86_64 file.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
sysdeps/ieee754/dbl-64/s_nearbyint.c | 38 ++++++--------
sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c | 65 ------------------------
sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c | 2 +-
3 files changed, 17 insertions(+), 88 deletions(-)
delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c
Note: tweaked by DJ for backport; some portions handled by glibc-rh1780204-07.patch
diff -rupN a/sysdeps/ieee754/dbl-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/s_nearbyint.c
--- a/sysdeps/ieee754/dbl-64/s_nearbyint.c 2020-04-09 21:17:04.281854809 -0400
+++ b/sysdeps/ieee754/dbl-64/s_nearbyint.c 2020-04-09 21:28:13.380741798 -0400
@@ -10,10 +10,6 @@
* ====================================================
*/
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: s_rint.c,v 1.8 1995/05/10 20:48:04 jtc Exp $";
-#endif
-
/*
* rint(x)
* Return x rounded to integral value according to the prevailing
@@ -44,35 +40,33 @@ __nearbyint (double x)
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
};
fenv_t env;
- int32_t i0, j0, sx;
- double w, t;
- GET_HIGH_WORD (i0, x);
- sx = (i0 >> 31) & 1;
- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
- if (j0 < 52)
+ int64_t i0, sx;
+ int32_t j0;
+ EXTRACT_WORDS64 (i0, x);
+ sx = (i0 >> 63) & 1;
+ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff;
+ if (__glibc_likely (j0 < 52))
{
if (j0 < 0)
{
libc_feholdexcept (&env);
- w = TWO52[sx] + math_opt_barrier (x);
- t = w - TWO52[sx];
+ double w = TWO52[sx] + math_opt_barrier (x);
+ double t = w - TWO52[sx];
math_force_eval (t);
libc_fesetenv (&env);
- GET_HIGH_WORD (i0, t);
- SET_HIGH_WORD (t, (i0 & 0x7fffffff) | (sx << 31));
- return t;
+ return copysign (t, x);
}
}
else
{
if (j0 == 0x400)
- return x + x; /* inf or NaN */
+ return x + x; /* inf or NaN */
else
- return x; /* x is integral */
+ return x; /* x is integral */
}
libc_feholdexcept (&env);
- w = TWO52[sx] + math_opt_barrier (x);
- t = w - TWO52[sx];
+ double w = TWO52[sx] + math_opt_barrier (x);
+ double t = w - TWO52[sx];
math_force_eval (t);
libc_fesetenv (&env);
return t;
diff -rupN a/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c
--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c 2018-08-01 01:10:47.000000000 -0400
+++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c 1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/* Adapted for use as nearbyint by Ulrich Drepper <drepper@cygnus.com>. */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-/*
- * rint(x)
- * Return x rounded to integral value according to the prevailing
- * rounding mode.
- * Method:
- * Using floating addition.
- * Exception:
- * Inexact flag raised if x not equal to rint(x).
- */
-
-#include <fenv.h>
-#include <math.h>
-#include <math-barriers.h>
-#include <math_private.h>
-#include <libm-alias-double.h>
-
-static const double
-TWO52[2]={
- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
-};
-
-double
-__nearbyint(double x)
-{
- fenv_t env;
- int64_t i0,sx;
- int32_t j0;
- EXTRACT_WORDS64(i0,x);
- sx = (i0>>63)&1;
- j0 = ((i0>>52)&0x7ff)-0x3ff;
- if(__builtin_expect(j0<52, 1)) {
- if(j0<0) {
- libc_feholdexcept (&env);
- double w = TWO52[sx] + math_opt_barrier (x);
- double t = w-TWO52[sx];
- math_force_eval (t);
- libc_fesetenv (&env);
- return __copysign (t, x);
- }
- } else {
- if(j0==0x400) return x+x; /* inf or NaN */
- else return x; /* x is integral */
- }
- libc_feholdexcept (&env);
- double w = TWO52[sx] + math_opt_barrier (x);
- double t = w-TWO52[sx];
- math_force_eval (t);
- libc_fesetenv (&env);
- return t;
-}
-libm_alias_double (__nearbyint, nearbyint)
diff -rupN a/sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c b/sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c
--- a/sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c 2018-08-01 01:10:47.000000000 -0400
+++ b/sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c 2020-04-09 21:28:13.205735274 -0400
@@ -1,3 +1,3 @@
#undef __nearbyint
#define __nearbyint __nearbyint_c
-#include <sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c>
+#include <sysdeps/ieee754/dbl-64/s_nearbyint.c>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
commit 0b3c9e57a41d9f7c26fb6aa45b99f671bef9c7e0
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Tue Aug 20 15:57:35 2019 -0500
[powerpc] fegetenv_status: simplify instruction generation
fegetenv_status() wants to use the lighter weight instruction 'mffsl'
for reading the Floating-Point Status and Control Register (FPSCR).
It currently will use it directly if compiled '-mcpu=power9', and will
perform a runtime check (cpu_supports("arch_3_00")) otherwise.
Nicely, it turns out that the 'mffsl' instruction will decode to
'mffs' on architectures older than "arch_3_00" because the additional
bits set for 'mffsl' are "don't care" for 'mffs'. 'mffs' is a superset
of 'mffsl'.
So, just generate 'mffsl'.
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index b244770d115ea7bb..e8d40ea256b6c5bc 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -36,9 +36,12 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; })
/* Equivalent to fegetenv_register, but only returns bits for
- status, exception enables, and mode. */
-
-#define fegetenv_status_ISA300() \
+ status, exception enables, and mode.
+ Nicely, it turns out that the 'mffsl' instruction will decode to
+ 'mffs' on architectures older than "power9" because the additional
+ bits set for 'mffsl' are "don't care" for 'mffs'. 'mffs' is a superset
+ of 'mffsl'. */
+#define fegetenv_status() \
({register double __fr; \
__asm__ __volatile__ ( \
".machine push; .machine \"power9\"; mffsl %0; .machine pop" \
@@ -46,18 +49,6 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
__fr; \
})
-#ifdef _ARCH_PWR9
-# define fegetenv_status() fegetenv_status_ISA300()
-#elif defined __BUILTIN_CPU_SUPPORTS__
-# define fegetenv_status() \
- (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \
- ? fegetenv_status_ISA300() \
- : fegetenv_register() \
- )
-#else
-# define fegetenv_status() fegetenv_register ()
-#endif
-
/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */
#define fesetenv_register(env) \
do { \

View File

@ -0,0 +1,128 @@
commit f1c56cdff09f650ad721fae026eb6a3651631f3d
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Sep 19 08:35:16 2019 -0500
[powerpc] SET_RESTORE_ROUND optimizations and bug fix
SET_RESTORE_ROUND brackets a block of code, temporarily setting and
restoring the rounding mode and letting everything else, including
exceptions generated within the block, pass through.
On powerpc, the current code clears the exception enables, which will hide
exceptions generated within the block. This issue was introduced by me
in commit e905212627350d54b58426214b5a54ddc852b0c9.
Fix this by not clearing exception enable bits in the prologue.
Also, since we are no longer changing the enable bits in either the
prologue or the epilogue, there is no need to test for entering/exiting
non-stop mode.
Also, optimize the prologue get/save/set rounding mode operations for
POWER9 and later by using 'mffscrn' when possible.
Suggested-by: Paul E. Murphy <murphyp@linux.ibm.com>
Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
Fixes: e905212627350d54b58426214b5a54ddc852b0c9
2019-09-19 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_and_set_rn): New.
(__fe_mffscrn): New.
* sysdeps/powerpc/fpu/fenv_private.h (libc_feholdsetround_ppc_ctx):
Do not clear enable bits, remove obsolete code, use
fegetenv_and_set_rn.
(libc_feresetround_ppc): Remove obsolete code, use
fegetenv_and_set_rn.
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index e8d40ea256b6c5bc..b10b6a141ded4bfd 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -49,6 +49,38 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
__fr; \
})
+#define __fe_mffscrn(rn) \
+ ({register fenv_union_t __fr; \
+ if (__builtin_constant_p (rn)) \
+ __asm__ __volatile__ ( \
+ ".machine push; .machine \"power9\"; mffscrni %0,%1; .machine pop" \
+ : "=f" (__fr.fenv) : "i" (rn)); \
+ else \
+ { \
+ __fr.l = (rn); \
+ __asm__ __volatile__ ( \
+ ".machine push; .machine \"power9\"; mffscrn %0,%1; .machine pop" \
+ : "=f" (__fr.fenv) : "f" (__fr.fenv)); \
+ } \
+ __fr.fenv; \
+ })
+
+/* Like fegetenv_status, but also sets the rounding mode. */
+#ifdef _ARCH_PWR9
+#define fegetenv_and_set_rn(rn) __fe_mffscrn (rn)
+#else
+/* 'mffscrn' will decode to 'mffs' on ARCH < 3_00, which is still necessary
+ but not sufficient, because it does not set the rounding mode.
+ Explicitly set the rounding mode when 'mffscrn' actually doesn't. */
+#define fegetenv_and_set_rn(rn) \
+ ({register fenv_union_t __fr; \
+ __fr.fenv = __fe_mffscrn (rn); \
+ if (__glibc_unlikely (!(GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00))) \
+ __fesetround_inline (rn); \
+ __fr.fenv; \
+ })
+#endif
+
/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */
#define fesetenv_register(env) \
do { \
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index b0149aa243e69f5a..30df92c9a4700dee 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -133,16 +133,7 @@ static __always_inline void
libc_feresetround_ppc (fenv_t *envp)
{
fenv_union_t new = { .fenv = *envp };
-
- /* If the old env has no enabled exceptions and the new env has any enabled
- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
- hardware into "precise mode" and may cause the FPU to run slower on some
- hardware. */
- if ((new.l & _FPU_ALL_TRAPS) != 0)
- (void) __fe_nomask_env_priv ();
-
- /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
- fesetenv_mode (new.fenv);
+ fegetenv_and_set_rn (new.l & FPSCR_RN_MASK);
}
static __always_inline int
@@ -184,22 +175,10 @@ libc_feupdateenv_ppc (fenv_t *e)
static __always_inline void
libc_feholdsetround_ppc_ctx (struct rm_ctx *ctx, int r)
{
- fenv_union_t old, new;
+ fenv_union_t old;
- old.fenv = fegetenv_status ();
-
- new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r;
-
- ctx->env = old.fenv;
- if (__glibc_unlikely (new.l != old.l))
- {
- if ((old.l & _FPU_ALL_TRAPS) != 0)
- (void) __fe_mask_env ();
- fesetenv_mode (new.fenv);
- ctx->updated_status = true;
- }
- else
- ctx->updated_status = false;
+ ctx->env = old.fenv = fegetenv_and_set_rn (r);
+ ctx->updated_status = (r != (old.l & FPSCR_RN_MASK));
}
static __always_inline void

View File

@ -0,0 +1,303 @@
commit e3d85df50b083c9ba68a40f5d45b201cbec4e68b
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Sep 19 09:13:14 2019 -0500
[powerpc] fenv_private.h clean up
fenv_private.h includes unused functions, magic macro constants, and
some replicated common code fragments.
Remove unused functions, replace magic constants with constants from
fenv_libc.h, and refactor replicated code.
Suggested-by: Paul E. Murphy <murphyp@linux.ibm.com>
Reviewed-By: Paul E Murphy <murphyp@linux.ibm.com>
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index 2a776c72fb5a2b70..bdf55ac62f1ffe4f 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -43,8 +43,7 @@ fedisableexcept (int excepts)
if (fe.l != curr.l)
fesetenv_mode (fe.fenv);
- if (new == 0 && result != 0)
- (void)__fe_mask_env ();
+ __TEST_AND_ENTER_NON_STOP (-1ULL, fe.l);
return result;
}
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index 6f5a828e80965bfa..78ebabed9232c0ad 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -43,8 +43,7 @@ feenableexcept (int excepts)
if (fe.l != curr.l)
fesetenv_mode (fe.fenv);
- if (new != 0 && result == 0)
- (void) __fe_nomask_env_priv ();
+ __TEST_AND_EXIT_NON_STOP (0ULL, fe.l);
return result;
}
diff --git a/sysdeps/powerpc/fpu/feholdexcpt.c b/sysdeps/powerpc/fpu/feholdexcpt.c
index 8ec3fbff82b22f51..9636ecaa0b600b0d 100644
--- a/sysdeps/powerpc/fpu/feholdexcpt.c
+++ b/sysdeps/powerpc/fpu/feholdexcpt.c
@@ -18,7 +18,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
int
__feholdexcept (fenv_t *envp)
@@ -35,11 +34,7 @@ __feholdexcept (fenv_t *envp)
if (new.l == old.l)
return 0;
- /* If the old env had any enabled exceptions, then mask SIGFPE in the
- MSR FE0/FE1 bits. This may allow the FPU to run faster because it
- always takes the default action and can not generate SIGFPE. */
- if ((old.l & _FPU_MASK_ALL) != 0)
- (void)__fe_mask_env ();
+ __TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
/* Put the new state in effect. */
fesetenv_register (new.fenv);
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index b10b6a141ded4bfd..36b639c3939586f6 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -27,6 +27,26 @@ extern const fenv_t *__fe_nomask_env_priv (void);
extern const fenv_t *__fe_mask_env (void) attribute_hidden;
+/* If the old env had any enabled exceptions and the new env has no enabled
+ exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
+ FPU to run faster because it always takes the default action and can not
+ generate SIGFPE. */
+#define __TEST_AND_ENTER_NON_STOP(old, new) \
+ do { \
+ if (((old) & FPSCR_ENABLES_MASK) != 0 && ((new) & FPSCR_ENABLES_MASK) == 0) \
+ (void) __fe_mask_env (); \
+ } while (0)
+
+/* If the old env has no enabled exceptions and the new env has any enabled
+ exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
+ hardware into "precise mode" and may cause the FPU to run slower on some
+ hardware. */
+#define __TEST_AND_EXIT_NON_STOP(old, new) \
+ do { \
+ if (((old) & FPSCR_ENABLES_MASK) == 0 && ((new) & FPSCR_ENABLES_MASK) != 0) \
+ (void) __fe_nomask_env_priv (); \
+ } while (0)
+
/* The sticky bits in the FPSCR indicating exceptions have occurred. */
#define FPSCR_STICKY_BITS ((FE_ALL_EXCEPT | FE_ALL_INVALID) & ~FE_INVALID)
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index 30df92c9a4700dee..c236d45db2f399a4 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -23,73 +23,20 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-/* Mask for the exception enable bits. */
-#define _FPU_ALL_TRAPS (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM \
- | _FPU_MASK_XM | _FPU_MASK_IM)
-
-/* Mask the rounding mode bits. */
-#define _FPU_MASK_RN 0xfffffffffffffffcLL
-
-/* Mask everything but the rounding modes and non-IEEE arithmetic flags. */
-#define _FPU_MASK_NOT_RN_NI 0xffffffff00000807LL
-
-/* Mask restore rounding mode and exception enabled. */
-#define _FPU_MASK_TRAPS_RN 0xffffffffffffff00LL
-
-/* Mask FP result flags, preserve fraction rounded/inexact bits. */
-#define _FPU_MASK_FRAC_INEX_RET_CC 0xfffffffffff80fffLL
-
static __always_inline void
-__libc_feholdbits_ppc (fenv_t *envp, unsigned long long mask,
- unsigned long long bits)
+libc_feholdexcept_setround_ppc (fenv_t *envp, int r)
{
fenv_union_t old, new;
old.fenv = *envp = fegetenv_register ();
- new.l = (old.l & mask) | bits;
-
- /* If the old env had any enabled exceptions, then mask SIGFPE in the
- MSR FE0/FE1 bits. This may allow the FPU to run faster because it
- always takes the default action and can not generate SIGFPE. */
- if ((old.l & _FPU_ALL_TRAPS) != 0)
- (void) __fe_mask_env ();
+ __TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
+ /* Clear everything and set the rounding mode. */
+ new.l = r;
fesetenv_register (new.fenv);
}
-static __always_inline void
-libc_feholdexcept_ppc (fenv_t *envp)
-{
- __libc_feholdbits_ppc (envp, _FPU_MASK_NOT_RN_NI, 0LL);
-}
-
-static __always_inline void
-libc_feholdexcept_setround_ppc (fenv_t *envp, int r)
-{
- __libc_feholdbits_ppc (envp, _FPU_MASK_NOT_RN_NI & _FPU_MASK_RN, r);
-}
-
-static __always_inline void
-libc_fesetround_ppc (int r)
-{
- __fesetround_inline (r);
-}
-
-static __always_inline int
-libc_fetestexcept_ppc (int e)
-{
- fenv_union_t u;
- u.fenv = fegetenv_register ();
- return u.l & e;
-}
-
-static __always_inline void
-libc_feholdsetround_ppc (fenv_t *e, int r)
-{
- __libc_feholdbits_ppc (e, _FPU_MASK_TRAPS_RN, r);
-}
-
static __always_inline unsigned long long
__libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
unsigned long long new_mask)
@@ -102,19 +49,8 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
/* Merge bits while masking unwanted bits from new and old env. */
new.l = (old.l & old_mask) | (new.l & new_mask);
- /* If the old env has no enabled exceptions and the new env has any enabled
- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
- hardware into "precise mode" and may cause the FPU to run slower on some
- hardware. */
- if ((old.l & _FPU_ALL_TRAPS) == 0 && (new.l & _FPU_ALL_TRAPS) != 0)
- (void) __fe_nomask_env_priv ();
-
- /* If the old env had any enabled exceptions and the new env has no enabled
- exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
- FPU to run faster because it always takes the default action and can not
- generate SIGFPE. */
- if ((old.l & _FPU_ALL_TRAPS) != 0 && (new.l & _FPU_ALL_TRAPS) == 0)
- (void) __fe_mask_env ();
+ __TEST_AND_EXIT_NON_STOP (old.l, new.l);
+ __TEST_AND_ENTER_NON_STOP (old.l, new.l);
/* Atomically enable and raise (if appropriate) exceptions set in `new'. */
fesetenv_register (new.fenv);
@@ -139,8 +75,8 @@ libc_feresetround_ppc (fenv_t *envp)
static __always_inline int
libc_feupdateenv_test_ppc (fenv_t *envp, int ex)
{
- return __libc_femergeenv_ppc (envp, _FPU_MASK_TRAPS_RN,
- _FPU_MASK_FRAC_INEX_RET_CC) & ex;
+ return __libc_femergeenv_ppc (envp, ~FPSCR_CONTROL_MASK,
+ ~FPSCR_STATUS_MASK) & ex;
}
static __always_inline void
@@ -193,8 +129,7 @@ libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r)
ctx->env = old.fenv;
if (__glibc_unlikely (new.l != old.l))
{
- if ((old.l & _FPU_ALL_TRAPS) != 0)
- (void) __fe_mask_env ();
+ __TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
fesetenv_register (new.fenv);
ctx->updated_status = true;
}
diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c
index ac927c8f3ada40b4..4eab5045c48105e3 100644
--- a/sysdeps/powerpc/fpu/fesetenv.c
+++ b/sysdeps/powerpc/fpu/fesetenv.c
@@ -28,19 +28,8 @@ __fesetenv (const fenv_t *envp)
new.fenv = *envp;
old.fenv = fegetenv_status ();
- /* If the old env has no enabled exceptions and the new env has any enabled
- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
- hardware into "precise mode" and may cause the FPU to run slower on some
- hardware. */
- if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0)
- (void) __fe_nomask_env_priv ();
-
- /* If the old env had any enabled exceptions and the new env has no enabled
- exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
- FPU to run faster because it always takes the default action and can not
- generate SIGFPE. */
- if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0)
- (void)__fe_mask_env ();
+ __TEST_AND_EXIT_NON_STOP (old.l, new.l);
+ __TEST_AND_ENTER_NON_STOP (old.l, new.l);
fesetenv_register (new.fenv);
diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c
index 29e088d5ab1c0d93..58ba02c0a1e64c27 100644
--- a/sysdeps/powerpc/fpu/fesetmode.c
+++ b/sysdeps/powerpc/fpu/fesetmode.c
@@ -33,11 +33,8 @@ fesetmode (const femode_t *modep)
if (old.l == new.l)
return 0;
- if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0)
- (void) __fe_nomask_env_priv ();
-
- if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0)
- (void) __fe_mask_env ();
+ __TEST_AND_EXIT_NON_STOP (old.l, new.l);
+ __TEST_AND_ENTER_NON_STOP (old.l, new.l);
fesetenv_mode (new.fenv);
return 0;
diff --git a/sysdeps/powerpc/fpu/feupdateenv.c b/sysdeps/powerpc/fpu/feupdateenv.c
index 2dbd1c4e9ec65ed0..fdd15651e0101f9e 100644
--- a/sysdeps/powerpc/fpu/feupdateenv.c
+++ b/sysdeps/powerpc/fpu/feupdateenv.c
@@ -20,8 +20,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
-
int
__feupdateenv (const fenv_t *envp)
{
@@ -36,19 +34,8 @@ __feupdateenv (const fenv_t *envp)
unchanged. */
new.l = (old.l & 0xffffffff1fffff00LL) | (new.l & 0x1ff80fff);
- /* If the old env has no enabled exceptions and the new env has any enabled
- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put
- the hardware into "precise mode" and may cause the FPU to run slower on
- some hardware. */
- if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
- (void) __fe_nomask_env_priv ();
-
- /* If the old env had any enabled exceptions and the new env has no enabled
- exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
- FPU to run faster because it always takes the default action and can not
- generate SIGFPE. */
- if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
- (void)__fe_mask_env ();
+ __TEST_AND_EXIT_NON_STOP (old.l, new.l);
+ __TEST_AND_ENTER_NON_STOP (old.l, new.l);
/* Atomically enable and raise (if appropriate) exceptions set in `new'. */
fesetenv_register (new.fenv);

View File

@ -0,0 +1,58 @@
commit 7413c188c77adb26a15cf0e98e0a991d09d73c65
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Sep 19 11:18:33 2019 -0500
[powerpc] libc_feupdateenv_test: optimize FPSCR access
ROUND_TO_ODD and a couple of other places use libc_feupdateenv_test to
restore the rounding mode and exception enables, preserve exception flags,
and test whether given exception(s) were generated.
If the exception flags haven't changed, then it is sufficient and a bit
more efficient to just restore the rounding mode and enables, rather than
writing the full Floating-Point Status and Control Register (FPSCR).
Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index 36b639c3939586f6..86ae7fda016abd8b 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -257,6 +257,10 @@ enum {
(FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK)
#define FPSCR_BASIC_EXCEPTIONS_MASK \
(FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK)
+#define FPSCR_EXCEPTIONS_MASK (FPSCR_BASIC_EXCEPTIONS_MASK| \
+ FPSCR_VXSNAN_MASK|FPSCR_VXISI_MASK|FPSCR_VXIDI_MASK|FPSCR_VXZDZ_MASK| \
+ FPSCR_VXIMZ_MASK|FPSCR_VXVC_MASK|FPSCR_VXSOFT_MASK|FPSCR_VXSQRT_MASK| \
+ FPSCR_VXCVI_MASK)
#define FPSCR_FPRF_MASK \
(FPSCR_FPRF_C_MASK|FPSCR_FPRF_FL_MASK|FPSCR_FPRF_FG_MASK| \
FPSCR_FPRF_FE_MASK|FPSCR_FPRF_FU_MASK)
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index c236d45db2f399a4..86a3611b3ef41759 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -52,8 +52,20 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
__TEST_AND_EXIT_NON_STOP (old.l, new.l);
__TEST_AND_ENTER_NON_STOP (old.l, new.l);
- /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
- fesetenv_register (new.fenv);
+ /* If requesting to keep status, replace control, and merge exceptions,
+ and exceptions haven't changed, we can just set new control instead
+ of the whole FPSCR. */
+ if ((old_mask & (FPSCR_CONTROL_MASK|FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK))
+ == (FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK) &&
+ (new_mask & (FPSCR_CONTROL_MASK|FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK))
+ == (FPSCR_CONTROL_MASK|FPSCR_EXCEPTIONS_MASK) &&
+ (old.l & FPSCR_EXCEPTIONS_MASK) == (new.l & FPSCR_EXCEPTIONS_MASK))
+ {
+ fesetenv_mode (new.fenv);
+ }
+ else
+ /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
+ fesetenv_register (new.fenv);
return old.l;
}

View File

@ -0,0 +1,56 @@
commit e68b1151f7460d5fa88c3a567c13f66052da79a7
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Sep 19 11:39:44 2019 -0500
[powerpc] __fesetround_inline optimizations
On POWER9, use more efficient means to update the 2-bit rounding mode
via the 'mffscrn' instruction (instead of two 'mtfsb0/1' instructions
or one 'mtfsfi' instruction that modifies 4 bits).
Suggested-by: Paul E. Murphy <murphyp@linux.ibm.com>
Reviewed-By: Paul E Murphy <murphyp@linux.ibm.com>
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index 86ae7fda016abd8b..c3f541c08440b20e 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -149,7 +149,12 @@ typedef union
static inline int
__fesetround_inline (int round)
{
- if ((unsigned int) round < 2)
+#ifdef _ARCH_PWR9
+ __fe_mffscrn (round);
+#else
+ if (__glibc_likely (GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00))
+ __fe_mffscrn (round);
+ else if ((unsigned int) round < 2)
{
asm volatile ("mtfsb0 30");
if ((unsigned int) round == 0)
@@ -165,7 +170,7 @@ __fesetround_inline (int round)
else
asm volatile ("mtfsb1 31");
}
-
+#endif
return 0;
}
@@ -174,7 +179,14 @@ __fesetround_inline (int round)
static inline void
__fesetround_inline_nocheck (const int round)
{
- asm volatile ("mtfsfi 7,%0" : : "i" (round));
+#ifdef _ARCH_PWR9
+ __fe_mffscrn (round);
+#else
+ if (__glibc_likely (GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00))
+ __fe_mffscrn (round);
+ else
+ asm volatile ("mtfsfi 7,%0" : : "i" (round));
+#endif
}
#define FPSCR_MASK(bit) (1 << (31 - (bit)))

View File

@ -0,0 +1,123 @@
commit 81ecb0ee4970865cbe5d1da733c4879b999c528f
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Sep 19 11:58:46 2019 -0500
[powerpc] Rename fegetenv_status to fegetenv_control
fegetenv_status is used variously to retrieve the FPSCR exception enable
bits, rounding mode bits, or both. These are referred to as the control
bits in the POWER ISA. FPSCR status bits are also returned by the
'mffs' and 'mffsl' instructions, but they are uniformly ignored by all
uses of fegetenv_status. Change the name to be reflective of its
current and expected use.
Reviewed-By: Paul E Murphy <murphyp@linux.ibm.com>
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index bdf55ac62f1ffe4f..1273987459655585 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -26,7 +26,7 @@ fedisableexcept (int excepts)
int result, new;
/* Get current exception mask to return. */
- fe.fenv = curr.fenv = fegetenv_status ();
+ fe.fenv = curr.fenv = fegetenv_control ();
result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index 78ebabed9232c0ad..fa233c305aedd5f6 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -26,7 +26,7 @@ feenableexcept (int excepts)
int result, new;
/* Get current exception mask to return. */
- fe.fenv = curr.fenv = fegetenv_status ();
+ fe.fenv = curr.fenv = fegetenv_control ();
result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
diff --git a/sysdeps/powerpc/fpu/fegetexcept.c b/sysdeps/powerpc/fpu/fegetexcept.c
index 9d77adea59939ece..6bbf11d9d5df61e5 100644
--- a/sysdeps/powerpc/fpu/fegetexcept.c
+++ b/sysdeps/powerpc/fpu/fegetexcept.c
@@ -25,7 +25,7 @@ __fegetexcept (void)
fenv_union_t fe;
int result = 0;
- fe.fenv = fegetenv_status ();
+ fe.fenv = fegetenv_control ();
if (fe.l & (1 << (31 - FPSCR_XE)))
result |= FE_INEXACT;
diff --git a/sysdeps/powerpc/fpu/fegetmode.c b/sysdeps/powerpc/fpu/fegetmode.c
index 75493e5f24c8b05b..57d6d5275485ebdc 100644
--- a/sysdeps/powerpc/fpu/fegetmode.c
+++ b/sysdeps/powerpc/fpu/fegetmode.c
@@ -21,6 +21,6 @@
int
fegetmode (femode_t *modep)
{
- *modep = fegetenv_status ();
+ *modep = fegetenv_control ();
return 0;
}
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index c3f541c08440b20e..b5c8da1adefe93cb 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -61,7 +61,7 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
'mffs' on architectures older than "power9" because the additional
bits set for 'mffsl' are "don't care" for 'mffs'. 'mffs' is a superset
of 'mffsl'. */
-#define fegetenv_status() \
+#define fegetenv_control() \
({register double __fr; \
__asm__ __volatile__ ( \
".machine push; .machine \"power9\"; mffsl %0; .machine pop" \
@@ -85,7 +85,7 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
__fr.fenv; \
})
-/* Like fegetenv_status, but also sets the rounding mode. */
+/* Like fegetenv_control, but also sets the rounding mode. */
#ifdef _ARCH_PWR9
#define fegetenv_and_set_rn(rn) __fe_mffscrn (rn)
#else
@@ -116,7 +116,7 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
/* Set the last 2 nibbles of the FPSCR, which contain the
exception enables and the rounding mode.
- 'fegetenv_status' retrieves these bits by reading the FPSCR. */
+ 'fegetenv_control' retrieves these bits by reading the FPSCR. */
#define fesetenv_mode(env) __builtin_mtfsf (0b00000011, (env));
/* This very handy macro:
diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c
index 4eab5045c48105e3..252114141cd87f8d 100644
--- a/sysdeps/powerpc/fpu/fesetenv.c
+++ b/sysdeps/powerpc/fpu/fesetenv.c
@@ -26,7 +26,7 @@ __fesetenv (const fenv_t *envp)
/* get the currently set exceptions. */
new.fenv = *envp;
- old.fenv = fegetenv_status ();
+ old.fenv = fegetenv_control ();
__TEST_AND_EXIT_NON_STOP (old.l, new.l);
__TEST_AND_ENTER_NON_STOP (old.l, new.l);
diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c
index 58ba02c0a1e64c27..e5938af04cb71ca1 100644
--- a/sysdeps/powerpc/fpu/fesetmode.c
+++ b/sysdeps/powerpc/fpu/fesetmode.c
@@ -27,7 +27,7 @@ fesetmode (const femode_t *modep)
/* Logic regarding enabled exceptions as in fesetenv. */
new.fenv = *modep;
- old.fenv = fegetenv_status ();
+ old.fenv = fegetenv_control ();
new.l = (new.l & ~FPSCR_STATUS_MASK) | (old.l & FPSCR_STATUS_MASK);
if (old.l == new.l)

View File

@ -0,0 +1,29 @@
commit 36c17c7079a5243a890ba43affff326a041775a9
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Sep 19 11:31:31 2019 -0500
[powerpc] libc_feholdsetround_noex_ppc_ctx: optimize FPSCR write
libc_feholdsetround_noex_ppc_ctx currently performs:
1. Read FPSCR, save to context.
2. Create new FPSCR value: clear enables and set new rounding mode.
3. Write new value to FPSCR.
Since other bits just pass through, there is no need to write them.
Instead, write just the changed values (enables and rounding mode),
which can be a bit more efficient.
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index 86a3611b3ef41759..c88142fe3053580f 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -142,7 +142,7 @@ libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r)
if (__glibc_unlikely (new.l != old.l))
{
__TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
- fesetenv_register (new.fenv);
+ fesetenv_mode (new.fenv);
ctx->updated_status = true;
}
else

View File

@ -0,0 +1,84 @@
commit d7a568af5546e0313abbc04060c8e9b0d3f750b4
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Sep 19 14:04:45 2019 -0500
[powerpc] Rename fesetenv_mode to fesetenv_control
fesetenv_mode is used variously to write the FPSCR exception enable
bits and rounding mode bits. These are referred to as the control
bits in the POWER ISA. Change the name to be reflective of its
current and expected use, and match up well with fegetenv_control.
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index 1273987459655585..efa9c422fe54f5d8 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -41,7 +41,7 @@ fedisableexcept (int excepts)
fe.l &= ~new;
if (fe.l != curr.l)
- fesetenv_mode (fe.fenv);
+ fesetenv_control (fe.fenv);
__TEST_AND_ENTER_NON_STOP (-1ULL, fe.l);
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index fa233c305aedd5f6..dfcc6fb7bd24b8db 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -41,7 +41,7 @@ feenableexcept (int excepts)
fe.l |= new;
if (fe.l != curr.l)
- fesetenv_mode (fe.fenv);
+ fesetenv_control (fe.fenv);
__TEST_AND_EXIT_NON_STOP (0ULL, fe.l);
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index b5c8da1adefe93cb..287fc9f8f70e051c 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -117,7 +117,7 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
/* Set the last 2 nibbles of the FPSCR, which contain the
exception enables and the rounding mode.
'fegetenv_control' retrieves these bits by reading the FPSCR. */
-#define fesetenv_mode(env) __builtin_mtfsf (0b00000011, (env));
+#define fesetenv_control(env) __builtin_mtfsf (0b00000011, (env));
/* This very handy macro:
- Sets the rounding mode to 'round to nearest';
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index c88142fe3053580f..666fbfdd9fef7759 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -61,7 +61,7 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
== (FPSCR_CONTROL_MASK|FPSCR_EXCEPTIONS_MASK) &&
(old.l & FPSCR_EXCEPTIONS_MASK) == (new.l & FPSCR_EXCEPTIONS_MASK))
{
- fesetenv_mode (new.fenv);
+ fesetenv_control (new.fenv);
}
else
/* Atomically enable and raise (if appropriate) exceptions set in `new'. */
@@ -142,7 +142,7 @@ libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r)
if (__glibc_unlikely (new.l != old.l))
{
__TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
- fesetenv_mode (new.fenv);
+ fesetenv_control (new.fenv);
ctx->updated_status = true;
}
else
diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c
index e5938af04cb71ca1..fdaecb1a6a25a820 100644
--- a/sysdeps/powerpc/fpu/fesetmode.c
+++ b/sysdeps/powerpc/fpu/fesetmode.c
@@ -36,6 +36,6 @@ fesetmode (const femode_t *modep)
__TEST_AND_EXIT_NON_STOP (old.l, new.l);
__TEST_AND_ENTER_NON_STOP (old.l, new.l);
- fesetenv_mode (new.fenv);
+ fesetenv_control (new.fenv);
return 0;
}

View File

@ -0,0 +1,64 @@
commit 7b8481b330720d28c019a2e5994492a1923d5daa
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Sep 19 11:11:04 2019 -0500
[powerpc] No need to enter "Ignore Exceptions Mode"
Since at least POWER8, there is no performance advantage to entering
"Ignore Exceptions Mode", and doing so conditionally requires
- the conditional logic, and
- a system call.
Make it a no-op for uses within glibc.
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index 666fbfdd9fef7759..e09137e892a8e3f3 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -23,6 +23,17 @@
#include <fenv_libc.h>
#include <fpu_control.h>
+#ifdef _ARCH_PWR8
+/* There is no performance advantage to non-stop mode. */
+/* The odd syntax here is to innocuously reference the given variables
+ to prevent warnings about unused variables. */
+#define __TEST_AND_BEGIN_NON_STOP(old, new) do {} while ((old) * (new) * 0 != 0)
+#define __TEST_AND_END_NON_STOP(old, new) do {} while ((old) * (new) * 0 != 0)
+#else
+#define __TEST_AND_BEGIN_NON_STOP __TEST_AND_ENTER_NON_STOP
+#define __TEST_AND_END_NON_STOP __TEST_AND_EXIT_NON_STOP
+#endif
+
static __always_inline void
libc_feholdexcept_setround_ppc (fenv_t *envp, int r)
{
@@ -30,7 +41,7 @@ libc_feholdexcept_setround_ppc (fenv_t *envp, int r)
old.fenv = *envp = fegetenv_register ();
- __TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
+ __TEST_AND_BEGIN_NON_STOP (old.l, 0ULL);
/* Clear everything and set the rounding mode. */
new.l = r;
@@ -49,8 +60,8 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
/* Merge bits while masking unwanted bits from new and old env. */
new.l = (old.l & old_mask) | (new.l & new_mask);
- __TEST_AND_EXIT_NON_STOP (old.l, new.l);
- __TEST_AND_ENTER_NON_STOP (old.l, new.l);
+ __TEST_AND_END_NON_STOP (old.l, new.l);
+ __TEST_AND_BEGIN_NON_STOP (old.l, new.l);
/* If requesting to keep status, replace control, and merge exceptions,
and exceptions haven't changed, we can just set new control instead
@@ -141,7 +152,7 @@ libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r)
ctx->env = old.fenv;
if (__glibc_unlikely (new.l != old.l))
{
- __TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
+ __TEST_AND_BEGIN_NON_STOP (old.l, 0ULL);
fesetenv_control (new.fenv);
ctx->updated_status = true;
}

View File

@ -0,0 +1,105 @@
commit de751ebc9efa97ce0115e42bd55fa1beeb614380
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Fri Mar 15 19:04:24 2019 -0400
[powerpc] get_rounding_mode: utilize faster method to get rounding mode
Add support to use 'mffsl' instruction if compiled for POWER9 (or later).
Also, mask the result to avoid bleeding unrelated bits into the result of
_FPU_GET_RC().
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
diff --git a/sysdeps/powerpc/fpu/get-rounding-mode.h b/sysdeps/powerpc/fpu/get-rounding-mode.h
new file mode 100644
index 0000000000000000..e2fdbbbcce72bd66
--- /dev/null
+++ b/sysdeps/powerpc/fpu/get-rounding-mode.h
@@ -0,0 +1,33 @@
+/* Determine floating-point rounding mode within libc. powerpc64 version.
+ Copyright (C) 2019 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/>. */
+
+#ifndef _POWERPC64_GET_ROUNDING_MODE_H
+#define _POWERPC64_GET_ROUNDING_MODE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+/* Return the floating-point rounding mode. */
+
+static inline int
+get_rounding_mode (void)
+{
+ return _FPU_GET_RC ();
+}
+
+#endif /* get-rounding-mode.h */
diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h
index 9d0698b4fc3eb595..62c478d72ae660cb 100644
--- a/sysdeps/powerpc/fpu_control.h
+++ b/sysdeps/powerpc/fpu_control.h
@@ -71,6 +71,8 @@ extern fpu_control_t __fpu_control;
# define _FPU_RC_UP 0x02
# define _FPU_RC_ZERO 0x01
+# define _FPU_MASK_RC (_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO)
+
# define _FPU_MASK_NI 0x04 /* non-ieee mode */
/* masking of interrupts */
@@ -94,15 +96,36 @@ extern fpu_control_t __fpu_control;
typedef unsigned int fpu_control_t;
/* Macros for accessing the hardware control word. */
+# define __FPU_MFFS() \
+ ({register double __fr; \
+ __asm__ ("mffs %0" : "=f" (__fr)); \
+ __fr; \
+ })
+
# define _FPU_GETCW(cw) \
({union { double __d; unsigned long long __ll; } __u; \
- register double __fr; \
- __asm__ ("mffs %0" : "=f" (__fr)); \
- __u.__d = __fr; \
+ __u.__d = __FPU_MFFS(); \
(cw) = (fpu_control_t) __u.__ll; \
(fpu_control_t) __u.__ll; \
})
+#ifdef _ARCH_PWR9
+# define __FPU_MFFSL() \
+ ({register double __fr; \
+ __asm__ ("mffsl %0" : "=f" (__fr)); \
+ __fr; \
+ })
+#else
+# define __FPU_MFFSL() __FPU_MFFS()
+#endif
+
+# define _FPU_GET_RC() \
+ ({union { double __d; unsigned long long __ll; } __u; \
+ __u.__d = __FPU_MFFSL(); \
+ __u.__ll &= _FPU_MASK_RC; \
+ (fpu_control_t) __u.__ll; \
+ })
+
# define _FPU_SETCW(cw) \
{ union { double __d; unsigned long long __ll; } __u; \
register double __fr; \

View File

@ -0,0 +1,65 @@
commit 49bc41b64239c4726f31fa35a1af4f22fb41d51f
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Tue Jun 11 14:37:37 2019 -0500
[powerpc] add 'volatile' to asm
Add 'volatile' keyword to a few asm statements, to force the compiler
to generate the instructions therein.
Some instances were implicitly volatile, but adding keyword for consistency.
2019-06-19 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (relax_fenv_state): Add 'volatile'.
* sysdeps/powerpc/fpu/fpu_control.h (__FPU_MFFS): Likewise.
(__FPU_MFFSL): Likewise.
(_FPU_SETCW): Likewise.
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index a0128c66444a3e46..d6945903b525748e 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -57,9 +57,9 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
#define relax_fenv_state() \
do { \
if (GLRO(dl_hwcap) & PPC_FEATURE_HAS_DFP) \
- asm (".machine push; .machine \"power6\"; " \
+ asm volatile (".machine push; .machine \"power6\"; " \
"mtfsfi 7,0,1; .machine pop"); \
- asm ("mtfsfi 7,0"); \
+ asm volatile ("mtfsfi 7,0"); \
} while(0)
/* Set/clear a particular FPSCR bit (for instance,
diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h
index 62c478d72ae660cb..90063d77bbbf794f 100644
--- a/sysdeps/powerpc/fpu_control.h
+++ b/sysdeps/powerpc/fpu_control.h
@@ -98,7 +98,7 @@ typedef unsigned int fpu_control_t;
/* Macros for accessing the hardware control word. */
# define __FPU_MFFS() \
({register double __fr; \
- __asm__ ("mffs %0" : "=f" (__fr)); \
+ __asm__ __volatile__("mffs %0" : "=f" (__fr)); \
__fr; \
})
@@ -112,7 +112,7 @@ typedef unsigned int fpu_control_t;
#ifdef _ARCH_PWR9
# define __FPU_MFFSL() \
({register double __fr; \
- __asm__ ("mffsl %0" : "=f" (__fr)); \
+ __asm__ __volatile__("mffsl %0" : "=f" (__fr)); \
__fr; \
})
#else
@@ -132,7 +132,7 @@ typedef unsigned int fpu_control_t;
__u.__ll = 0xfff80000LL << 32; /* This is a QNaN. */ \
__u.__ll |= (cw) & 0xffffffffLL; \
__fr = __u.__d; \
- __asm__ ("mtfsf 255,%0" : : "f" (__fr)); \
+ __asm__ __volatile__("mtfsf 255,%0" : : "f" (__fr)); \
}
/* Default control word set at startup. */

View File

@ -0,0 +1,200 @@
commit 3db85a9814784a74536a1f0e7b7ddbfef7dc84bb
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Jun 20 11:57:18 2019 -0500
powerpc: Use faster means to access FPSCR when possible in some cases
Using 'mffs' instruction to read the Floating Point Status Control Register
(FPSCR) can force a processor flush in some cases, with undesirable
performance impact. If the values of the bits in the FPSCR which force the
flush are not needed, an instruction that is new to POWER9 (ISA version 3.0),
'mffsl' can be used instead.
Cases included: get_rounding_mode, fegetround, fegetmode, fegetexcept.
* sysdeps/powerpc/bits/fenvinline.h (__fegetround): Use
__fegetround_ISA300() or __fegetround_ISA2() as appropriate.
(__fegetround_ISA300) New.
(__fegetround_ISA2) New.
* sysdeps/powerpc/fpu_control.h (IS_ISA300): New.
(_FPU_MFFS): Move implementation...
(_FPU_GETCW): Here.
(_FPU_MFFSL): Move implementation....
(_FPU_GET_RC_ISA300): Here. New.
(_FPU_GET_RC): Use _FPU_GET_RC_ISA300() or _FPU_GETCW() as appropriate.
* sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_status_ISA300): New.
(fegetenv_status): New.
* sysdeps/powerpc/fpu/fegetmode.c (fegetmode): Use fegetenv_status()
instead of fegetenv_register().
* sysdeps/powerpc/fpu/fegetexcept.c (__fegetexcept): Likewise.
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
diff --git a/sysdeps/powerpc/bits/fenvinline.h b/sysdeps/powerpc/bits/fenvinline.h
index 41316386ba75e903..caec8ead6e17219d 100644
--- a/sysdeps/powerpc/bits/fenvinline.h
+++ b/sysdeps/powerpc/bits/fenvinline.h
@@ -18,13 +18,36 @@
#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__
-/* Inline definition for fegetround. */
-# define __fegetround() \
- (__extension__ ({ int __fegetround_result; \
- __asm__ __volatile__ \
- ("mcrfs 7,7 ; mfcr %0" \
- : "=r"(__fegetround_result) : : "cr7"); \
- __fegetround_result & 3; }))
+/* Inline definitions for fegetround. */
+# define __fegetround_ISA300() \
+ (__extension__ ({ \
+ union { double __d; unsigned long long __ll; } __u; \
+ __asm__ __volatile__ ( \
+ ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \
+ : "=f" (__u.__d)); \
+ __u.__ll & 0x0000000000000003LL; \
+ }))
+
+# define __fegetround_ISA2() \
+ (__extension__ ({ \
+ int __fegetround_result; \
+ __asm__ __volatile__ ("mcrfs 7,7 ; mfcr %0" \
+ : "=r"(__fegetround_result) : : "cr7"); \
+ __fegetround_result & 3; \
+ }))
+
+# ifdef _ARCH_PWR9
+# define __fegetround() __fegetround_ISA300()
+# elif defined __BUILTIN_CPU_SUPPORTS__
+# define __fegetround() \
+ (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \
+ ? __fegetround_ISA300() \
+ : __fegetround_ISA2() \
+ )
+# else
+# define __fegetround() __fegetround_ISA2()
+# endif
+
# define fegetround() __fegetround ()
# ifndef __NO_MATH_INLINES
diff --git a/sysdeps/powerpc/fpu/fegetexcept.c b/sysdeps/powerpc/fpu/fegetexcept.c
index a053a32bfe11c0d4..9d77adea59939ece 100644
--- a/sysdeps/powerpc/fpu/fegetexcept.c
+++ b/sysdeps/powerpc/fpu/fegetexcept.c
@@ -25,7 +25,7 @@ __fegetexcept (void)
fenv_union_t fe;
int result = 0;
- fe.fenv = fegetenv_register ();
+ fe.fenv = fegetenv_status ();
if (fe.l & (1 << (31 - FPSCR_XE)))
result |= FE_INEXACT;
diff --git a/sysdeps/powerpc/fpu/fegetmode.c b/sysdeps/powerpc/fpu/fegetmode.c
index b83dc9f625d2248a..75493e5f24c8b05b 100644
--- a/sysdeps/powerpc/fpu/fegetmode.c
+++ b/sysdeps/powerpc/fpu/fegetmode.c
@@ -21,6 +21,6 @@
int
fegetmode (femode_t *modep)
{
- *modep = fegetenv_register ();
+ *modep = fegetenv_status ();
return 0;
}
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index d6945903b525748e..cc00df033da47c1a 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -35,6 +35,27 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
#define fegetenv_register() \
({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; })
+/* Equivalent to fegetenv_register, but only returns bits for
+ status, exception enables, and mode. */
+
+#define fegetenv_status_ISA300() \
+ ({register double __fr; \
+ __asm__ __volatile__ ( \
+ ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \
+ : "=f" (__fr)); \
+ __fr; \
+ })
+
+#ifdef _ARCH_PWR9
+# define fegetenv_status() fegetenv_status_ISA300()
+#else
+# define fegetenv_status() \
+ (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \
+ ? fegetenv_status_ISA300() \
+ : fegetenv_register() \
+ )
+#endif
+
/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */
#define fesetenv_register(env) \
do { \
diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h
index 90063d77bbbf794f..e0ee622e246c0d61 100644
--- a/sysdeps/powerpc/fpu_control.h
+++ b/sysdeps/powerpc/fpu_control.h
@@ -96,35 +96,37 @@ extern fpu_control_t __fpu_control;
typedef unsigned int fpu_control_t;
/* Macros for accessing the hardware control word. */
-# define __FPU_MFFS() \
- ({register double __fr; \
- __asm__ __volatile__("mffs %0" : "=f" (__fr)); \
- __fr; \
- })
-
# define _FPU_GETCW(cw) \
({union { double __d; unsigned long long __ll; } __u; \
- __u.__d = __FPU_MFFS(); \
+ __asm__ __volatile__("mffs %0" : "=f" (__u.__d)); \
(cw) = (fpu_control_t) __u.__ll; \
(fpu_control_t) __u.__ll; \
})
-#ifdef _ARCH_PWR9
-# define __FPU_MFFSL() \
- ({register double __fr; \
- __asm__ __volatile__("mffsl %0" : "=f" (__fr)); \
- __fr; \
+# define _FPU_GET_RC_ISA300() \
+ ({union { double __d; unsigned long long __ll; } __u; \
+ __asm__ __volatile__( \
+ ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \
+ : "=f" (__u.__d)); \
+ (fpu_control_t) (__u.__ll & _FPU_MASK_RC); \
})
-#else
-# define __FPU_MFFSL() __FPU_MFFS()
-#endif
-
-# define _FPU_GET_RC() \
- ({union { double __d; unsigned long long __ll; } __u; \
- __u.__d = __FPU_MFFSL(); \
- __u.__ll &= _FPU_MASK_RC; \
- (fpu_control_t) __u.__ll; \
+
+# ifdef _ARCH_PWR9
+# define _FPU_GET_RC() _FPU_GET_RC_ISA300()
+# elif defined __BUILTIN_CPU_SUPPORTS__
+# define _FPU_GET_RC() \
+ ({fpu_control_t __rc; \
+ __rc = __glibc_likely (__builtin_cpu_supports ("arch_3_00")) \
+ ? _FPU_GET_RC_ISA300 () \
+ : _FPU_GETCW (__rc) & _FPU_MASK_RC; \
+ __rc; \
+ })
+# else
+# define _FPU_GET_RC() \
+ ({fpu_control_t __rc = _FPU_GETCW (__rc) & _FPU_MASK_RC; \
+ __rc; \
})
+# endif
# define _FPU_SETCW(cw) \
{ union { double __d; unsigned long long __ll; } __u; \

View File

@ -0,0 +1,37 @@
commit b5232c9f9e6048b8f780d3cbfadbc8e59bb90ce4
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Mon Jul 8 17:06:19 2019 -0500
[powerpc] fenv_libc.h: protect use of __builtin_cpu_supports
Using __builtin_cpu_supports() requires support in GCC and Glibc.
My recent patch to fenv_libc.h added an unprotected use of
__builtin_cpu_supports(). Compilation of Glibc itself will fail
with a sufficiently new GCC and sufficiently old Glibc:
../sysdeps/powerpc/fpu/fegetexcept.c: In function __fegetexcept:
../sysdeps/powerpc/fpu/fenv_libc.h:52:20: error: builtin __builtin_cpu_supports needs GLIBC (2.23 and newer) that exports hardware capability bits [-Werror]
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Fixes 3db85a9814784a74536a1f0e7b7ddbfef7dc84bb.
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index cc00df033da47c1a..9dca6e760cc51946 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -48,12 +48,14 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
#ifdef _ARCH_PWR9
# define fegetenv_status() fegetenv_status_ISA300()
-#else
+#elif defined __BUILTIN_CPU_SUPPORTS__
# define fegetenv_status() \
(__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \
? fegetenv_status_ISA300() \
: fegetenv_register() \
)
+#else
+# define fegetenv_status() fegetenv_register ()
#endif
/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */

View File

@ -0,0 +1,185 @@
commit cd7ce12a027656ad3cda774454088de5a2c7fbfa
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Fri Jul 12 20:13:58 2019 -0500
[powerpc] fe{en,dis}ableexcept optimize bit translations
The exceptions passed to fe{en,dis}ableexcept() are defined in the ABI
as a bitmask, a combination of FE_INVALID, FE_OVERFLOW, etc.
Within the functions, these bits must be translated to/from the corresponding
enable bits in the Floating Point Status Control Register (FPSCR).
This translation is currently done bit-by-bit. The compiler generates
a series of conditional bit operations. Nicely, the "FE" exception
bits are all a uniform offset from the FPSCR enable bits, so the bit-by-bit
operation can instead be performed by a shift with appropriate masking.
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index 2daed44a419301e8..90bc3d12c6d8558c 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -33,16 +33,7 @@ fedisableexcept (int excepts)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
/* Sets the new exception mask. */
- if (excepts & FE_INEXACT)
- fe.l &= ~(1 << (31 - FPSCR_XE));
- if (excepts & FE_DIVBYZERO)
- fe.l &= ~(1 << (31 - FPSCR_ZE));
- if (excepts & FE_UNDERFLOW)
- fe.l &= ~(1 << (31 - FPSCR_UE));
- if (excepts & FE_OVERFLOW)
- fe.l &= ~(1 << (31 - FPSCR_OE));
- if (excepts & FE_INVALID)
- fe.l &= ~(1 << (31 - FPSCR_VE));
+ fe.l &= ~ fenv_exceptions_to_reg (excepts);
if (fe.l != curr.l)
fesetenv_register (fe.fenv);
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index 19cfe28e7aa307d4..e029971b9a460c28 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -33,16 +33,7 @@ feenableexcept (int excepts)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
/* Sets the new exception mask. */
- if (excepts & FE_INEXACT)
- fe.l |= (1 << (31 - FPSCR_XE));
- if (excepts & FE_DIVBYZERO)
- fe.l |= (1 << (31 - FPSCR_ZE));
- if (excepts & FE_UNDERFLOW)
- fe.l |= (1 << (31 - FPSCR_UE));
- if (excepts & FE_OVERFLOW)
- fe.l |= (1 << (31 - FPSCR_OE));
- if (excepts & FE_INVALID)
- fe.l |= (1 << (31 - FPSCR_VE));
+ fe.l |= fenv_exceptions_to_reg (excepts);
if (fe.l != curr.l)
fesetenv_register (fe.fenv);
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index 9dca6e760cc51946..f9634a64d186c076 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -129,60 +129,108 @@ __fesetround_inline_nocheck (const int round)
asm volatile ("mtfsfi 7,%0" : : "i" (round));
}
+#define FPSCR_MASK(bit) (1 << (31 - (bit)))
+
/* Definitions of all the FPSCR bit numbers */
enum {
FPSCR_FX = 0, /* exception summary */
+#define FPSCR_FX_MASK (FPSCR_MASK (FPSCR_FX))
FPSCR_FEX, /* enabled exception summary */
+#define FPSCR_FEX_MASK (FPSCR_MASK FPSCR_FEX))
FPSCR_VX, /* invalid operation summary */
+#define FPSCR_VX_MASK (FPSCR_MASK (FPSCR_VX))
FPSCR_OX, /* overflow */
+#define FPSCR_OX_MASK (FPSCR_MASK (FPSCR_OX))
FPSCR_UX, /* underflow */
+#define FPSCR_UX_MASK (FPSCR_MASK (FPSCR_UX))
FPSCR_ZX, /* zero divide */
+#define FPSCR_ZX_MASK (FPSCR_MASK (FPSCR_ZX))
FPSCR_XX, /* inexact */
+#define FPSCR_XX_MASK (FPSCR_MASK (FPSCR_XX))
FPSCR_VXSNAN, /* invalid operation for sNaN */
+#define FPSCR_VXSNAN_MASK (FPSCR_MASK (FPSCR_VXSNAN))
FPSCR_VXISI, /* invalid operation for Inf-Inf */
+#define FPSCR_VXISI_MASK (FPSCR_MASK (FPSCR_VXISI))
FPSCR_VXIDI, /* invalid operation for Inf/Inf */
+#define FPSCR_VXIDI_MASK (FPSCR_MASK (FPSCR_VXIDI))
FPSCR_VXZDZ, /* invalid operation for 0/0 */
+#define FPSCR_VXZDZ_MASK (FPSCR_MASK (FPSCR_VXZDZ))
FPSCR_VXIMZ, /* invalid operation for Inf*0 */
+#define FPSCR_VXIMZ_MASK (FPSCR_MASK (FPSCR_VXIMZ))
FPSCR_VXVC, /* invalid operation for invalid compare */
+#define FPSCR_VXVC_MASK (FPSCR_MASK (FPSCR_VXVC))
FPSCR_FR, /* fraction rounded [fraction was incremented by round] */
+#define FPSCR_FR_MASK (FPSCR_MASK (FPSCR_FR))
FPSCR_FI, /* fraction inexact */
+#define FPSCR_FI_MASK (FPSCR_MASK (FPSCR_FI))
FPSCR_FPRF_C, /* result class descriptor */
+#define FPSCR_FPRF_C_MASK (FPSCR_MASK (FPSCR_FPRF_C))
FPSCR_FPRF_FL, /* result less than (usually, less than 0) */
+#define FPSCR_FPRF_FL_MASK (FPSCR_MASK (FPSCR_FPRF_FL))
FPSCR_FPRF_FG, /* result greater than */
+#define FPSCR_FPRF_FG_MASK (FPSCR_MASK (FPSCR_FPRF_FG))
FPSCR_FPRF_FE, /* result equal to */
+#define FPSCR_FPRF_FE_MASK (FPSCR_MASK (FPSCR_FPRF_FE))
FPSCR_FPRF_FU, /* result unordered */
+#define FPSCR_FPRF_FU_MASK (FPSCR_MASK (FPSCR_FPRF_FU))
FPSCR_20, /* reserved */
FPSCR_VXSOFT, /* invalid operation set by software */
+#define FPSCR_VXSOFT_MASK (FPSCR_MASK (FPSCR_VXSOFT))
FPSCR_VXSQRT, /* invalid operation for square root */
+#define FPSCR_VXSQRT_MASK (FPSCR_MASK (FPSCR_VXSQRT))
FPSCR_VXCVI, /* invalid operation for invalid integer convert */
+#define FPSCR_VXCVI_MASK (FPSCR_MASK (FPSCR_VXCVI))
FPSCR_VE, /* invalid operation exception enable */
+#define FPSCR_VE_MASK (FPSCR_MASK (FPSCR_VE))
FPSCR_OE, /* overflow exception enable */
+#define FPSCR_OE_MASK (FPSCR_MASK (FPSCR_OE))
FPSCR_UE, /* underflow exception enable */
+#define FPSCR_UE_MASK (FPSCR_MASK (FPSCR_UE))
FPSCR_ZE, /* zero divide exception enable */
+#define FPSCR_ZE_MASK (FPSCR_MASK (FPSCR_ZE))
FPSCR_XE, /* inexact exception enable */
+#define FPSCR_XE_MASK (FPSCR_MASK (FPSCR_XE))
#ifdef _ARCH_PWR6
FPSCR_29, /* Reserved in ISA 2.05 */
+#define FPSCR_NI_MASK (FPSCR_MASK (FPSCR_29))
#else
- FPSCR_NI /* non-IEEE mode (typically, no denormalised numbers) */
+ FPSCR_NI, /* non-IEEE mode (typically, no denormalised numbers) */
+#define FPSCR_NI_MASK (FPSCR_MASK (FPSCR_NI))
#endif /* _ARCH_PWR6 */
/* the remaining two least-significant bits keep the rounding mode */
+ FPSCR_RN_hi,
+#define FPSCR_RN_hi_MASK (FPSCR_MASK (FPSCR_RN_hi))
+ FPSCR_RN_lo
+#define FPSCR_RN_lo_MASK (FPSCR_MASK (FPSCR_RN_lo))
};
+#define FPSCR_RN_MASK (FPSCR_RN_hi_MASK|FPSCR_RN_lo_MASK)
+#define FPSCR_ENABLES_MASK \
+ (FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK)
+#define FPSCR_BASIC_EXCEPTIONS_MASK \
+ (FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK)
+
+#define FPSCR_CONTROL_MASK (FPSCR_ENABLES_MASK|FPSCR_NI_MASK|FPSCR_RN_MASK)
+
+/* The bits in the FENV(1) ABI for exceptions correspond one-to-one with bits
+ in the FPSCR, albeit shifted to different but corresponding locations.
+ Similarly, the exception indicator bits in the FPSCR correspond one-to-one
+ with the exception enable bits. It is thus possible to map the FENV(1)
+ exceptions directly to the FPSCR enables with a simple mask and shift,
+ and vice versa. */
+#define FPSCR_EXCEPT_TO_ENABLE_SHIFT 22
+
static inline int
fenv_reg_to_exceptions (unsigned long long l)
{
- int result = 0;
- if (l & (1 << (31 - FPSCR_XE)))
- result |= FE_INEXACT;
- if (l & (1 << (31 - FPSCR_ZE)))
- result |= FE_DIVBYZERO;
- if (l & (1 << (31 - FPSCR_UE)))
- result |= FE_UNDERFLOW;
- if (l & (1 << (31 - FPSCR_OE)))
- result |= FE_OVERFLOW;
- if (l & (1 << (31 - FPSCR_VE)))
- result |= FE_INVALID;
- return result;
+ return (((int)l) & FPSCR_ENABLES_MASK) << FPSCR_EXCEPT_TO_ENABLE_SHIFT;
+}
+
+static inline unsigned long long
+fenv_exceptions_to_reg (int excepts)
+{
+ return (unsigned long long)
+ (excepts & FE_ALL_EXCEPT) >> FPSCR_EXCEPT_TO_ENABLE_SHIFT;
}
#ifdef _ARCH_PWR6

View File

@ -0,0 +1,174 @@
commit 3c1766ea10043f2e9625f3cba3bda37c84b32cf0
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Thu Jul 18 19:37:13 2019 -0500
[powerpc] fe{en,dis}ableexcept, fesetmode: optimize FPSCR accesses
Since fe{en,dis}ableexcept() and fesetmode() read-modify-write just the
"mode" (exception enable and rounding mode) bits of the Floating Point Status
Control Register (FPSCR), the lighter weight 'mffsl' instruction can be used
to read the FPSCR (enables and rounding mode), and 'mtfsf 0b00000011' can be
used to write just those bits back to the FPSCR. The net is better performance.
In addition, fe{en,dis}ableexcept() read the FPSCR again after writing it, or
they determine that it doesn't need to be written because it is not changing.
In either case, the local variable holds the current values of the enable
bits in the FPSCR. This local variable can be used instead of again reading
the FPSCR.
Also, that value of the FPSCR which is read the second time is validated
against the requested enables. Since the write can't fail, this validation
step is unnecessary, and can be removed. Instead, the exceptions to be
enabled (or disabled) are transformed into available bits in the FPSCR,
then validated after being transformed back, to ensure that all requested
bits are actually being set. For example, FE_INVALID_SQRT can be
requested, but cannot actually be set. This bit is not mapped during the
transformations, so a test for that bit being set before and after
transformations will show the bit would not be set, and the function will
return -1 for failure.
Finally, convert the local macros in fesetmode.c to more generally useful
macros in fenv_libc.h.
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index 90bc3d12c6d8558c..2a776c72fb5a2b70 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -26,23 +26,25 @@ fedisableexcept (int excepts)
int result, new;
/* Get current exception mask to return. */
- fe.fenv = curr.fenv = fegetenv_register ();
+ fe.fenv = curr.fenv = fegetenv_status ();
result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
+ new = fenv_exceptions_to_reg (excepts);
+
+ if (fenv_reg_to_exceptions (new) != excepts)
+ return -1;
+
/* Sets the new exception mask. */
- fe.l &= ~ fenv_exceptions_to_reg (excepts);
+ fe.l &= ~new;
if (fe.l != curr.l)
- fesetenv_register (fe.fenv);
+ fesetenv_mode (fe.fenv);
- new = __fegetexcept ();
if (new == 0 && result != 0)
(void)__fe_mask_env ();
- if ((new & excepts) != 0)
- result = -1;
return result;
}
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index e029971b9a460c28..6f5a828e80965bfa 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -26,24 +26,25 @@ feenableexcept (int excepts)
int result, new;
/* Get current exception mask to return. */
- fe.fenv = curr.fenv = fegetenv_register ();
+ fe.fenv = curr.fenv = fegetenv_status ();
result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
+ new = fenv_exceptions_to_reg (excepts);
+
+ if (fenv_reg_to_exceptions (new) != excepts)
+ return -1;
+
/* Sets the new exception mask. */
- fe.l |= fenv_exceptions_to_reg (excepts);
+ fe.l |= new;
if (fe.l != curr.l)
- fesetenv_register (fe.fenv);
+ fesetenv_mode (fe.fenv);
- new = __fegetexcept ();
if (new != 0 && result == 0)
(void) __fe_nomask_env_priv ();
- if ((new & excepts) != excepts)
- result = -1;
-
return result;
}
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index f9634a64d186c076..b244770d115ea7bb 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -71,6 +71,11 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
asm volatile ("mtfsf 0xff,%0" : : "f" (d)); \
} while(0)
+/* Set the last 2 nibbles of the FPSCR, which contain the
+ exception enables and the rounding mode.
+ 'fegetenv_status' retrieves these bits by reading the FPSCR. */
+#define fesetenv_mode(env) __builtin_mtfsf (0b00000011, (env));
+
/* This very handy macro:
- Sets the rounding mode to 'round to nearest';
- Sets the processor into IEEE mode; and
@@ -209,8 +214,11 @@ enum {
(FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK)
#define FPSCR_BASIC_EXCEPTIONS_MASK \
(FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK)
-
+#define FPSCR_FPRF_MASK \
+ (FPSCR_FPRF_C_MASK|FPSCR_FPRF_FL_MASK|FPSCR_FPRF_FG_MASK| \
+ FPSCR_FPRF_FE_MASK|FPSCR_FPRF_FU_MASK)
#define FPSCR_CONTROL_MASK (FPSCR_ENABLES_MASK|FPSCR_NI_MASK|FPSCR_RN_MASK)
+#define FPSCR_STATUS_MASK (FPSCR_FR_MASK|FPSCR_FI_MASK|FPSCR_FPRF_MASK)
/* The bits in the FENV(1) ABI for exceptions correspond one-to-one with bits
in the FPSCR, albeit shifted to different but corresponding locations.
diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c
index 32203a24ff434a32..29e088d5ab1c0d93 100644
--- a/sysdeps/powerpc/fpu/fesetmode.c
+++ b/sysdeps/powerpc/fpu/fesetmode.c
@@ -19,11 +19,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM \
- | _FPU_MASK_XM | _FPU_MASK_IM)
-
-#define FPU_STATUS 0xbffff700ULL
-
int
fesetmode (const femode_t *modep)
{
@@ -32,18 +27,18 @@ fesetmode (const femode_t *modep)
/* Logic regarding enabled exceptions as in fesetenv. */
new.fenv = *modep;
- old.fenv = fegetenv_register ();
- new.l = (new.l & ~FPU_STATUS) | (old.l & FPU_STATUS);
+ old.fenv = fegetenv_status ();
+ new.l = (new.l & ~FPSCR_STATUS_MASK) | (old.l & FPSCR_STATUS_MASK);
if (old.l == new.l)
return 0;
- if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
+ if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0)
(void) __fe_nomask_env_priv ();
- if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
+ if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0)
(void) __fe_mask_env ();
- fesetenv_register (new.fenv);
+ fesetenv_mode (new.fenv);
return 0;
}

View File

@ -0,0 +1,124 @@
commit e905212627350d54b58426214b5a54ddc852b0c9
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Fri Aug 2 22:47:57 2019 -0400
[powerpc] SET_RESTORE_ROUND improvements
SET_RESTORE_ROUND uses libc_feholdsetround_ppc_ctx and
libc_feresetround_ppc_ctx to bracket a block of code where the floating point
rounding mode must be set to a certain value.
For the *prologue*, libc_feholdsetround_ppc_ctx is used and performs:
1. Read/save FPSCR.
2. Create new value for FPSCR with new rounding mode and enables cleared.
3. If new value is different than current value,
a. If transitioning from a state where some exceptions enabled,
enter "ignore exceptions / non-stop" mode.
b. Write new value to FPSCR.
c. Put a mark on the wall indicating the FPSCR was changed.
(1) uses the 'mffs' instruction. On POWER9, the lighter weight 'mffsl'
instruction can be used, but it doesn't return all of the bits in the FPSCR.
fegetenv_status uses 'mffsl' on POWER9, 'mffs' otherwise, and can thus be
used instead of fegetenv_register.
(3b) uses 'mtfsf 0b11111111' to write the entire FPSCR, so it must
instead use 'mtfsf 0b00000011' to write just the enables and the mode,
because some of the rest of the bits are not valid if 'mffsl' was used.
fesetenv_mode uses 'mtfsf 0b00000011' on POWER9, 'mtfsf 0b11111111'
otherwise.
For the *epilogue*, libc_feresetround_ppc_ctx checks the mark on the wall, then
calls libc_feresetround_ppc, which just calls __libc_femergeenv_ppc with
parameters such that it performs:
1. Retreive saved value of FPSCR, saved in prologue above.
2. Read FPSCR.
3. Create new value of FPSCR where:
- Summary bits and exception indicators = current OR saved.
- Rounding mode and enables = saved.
- Status bits = current.
4. If transitioning from some exceptions enabled to none,
enter "ignore exceptions / non-stop" mode.
5. If transitioning from no exceptions enabled to some,
enter "catch exceptions" mode.
6. Write new value to FPSCR.
The summary bits are hardwired to the exception indicators, so there is no
need to restore any saved summary bits.
The exception indicator bits, which are sticky and remain set unless
explicitly cleared, would only need to be restored if the code block
might explicitly clear any of them. This is certainly not expected.
So, the only bits that need to be restored are the enables and the mode.
If it is the case that only those bits are to be restored, there is no need to
read the FPSCR. Steps (2) and (3) are unnecessary, and step (6) only needs to
write the bits being restored.
We know we are transitioning out of "ignore exceptions" mode, so step (4) is
unnecessary, and in step (6), we only need to check the state we are
entering.
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index 945ab98018450092..b0149aa243e69f5a 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -132,7 +132,17 @@ libc_fesetenv_ppc (const fenv_t *envp)
static __always_inline void
libc_feresetround_ppc (fenv_t *envp)
{
- __libc_femergeenv_ppc (envp, _FPU_MASK_TRAPS_RN, _FPU_MASK_FRAC_INEX_RET_CC);
+ fenv_union_t new = { .fenv = *envp };
+
+ /* If the old env has no enabled exceptions and the new env has any enabled
+ exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
+ hardware into "precise mode" and may cause the FPU to run slower on some
+ hardware. */
+ if ((new.l & _FPU_ALL_TRAPS) != 0)
+ (void) __fe_nomask_env_priv ();
+
+ /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
+ fesetenv_mode (new.fenv);
}
static __always_inline int
@@ -176,9 +186,30 @@ libc_feholdsetround_ppc_ctx (struct rm_ctx *ctx, int r)
{
fenv_union_t old, new;
+ old.fenv = fegetenv_status ();
+
+ new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r;
+
+ ctx->env = old.fenv;
+ if (__glibc_unlikely (new.l != old.l))
+ {
+ if ((old.l & _FPU_ALL_TRAPS) != 0)
+ (void) __fe_mask_env ();
+ fesetenv_mode (new.fenv);
+ ctx->updated_status = true;
+ }
+ else
+ ctx->updated_status = false;
+}
+
+static __always_inline void
+libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r)
+{
+ fenv_union_t old, new;
+
old.fenv = fegetenv_register ();
- new.l = (old.l & _FPU_MASK_TRAPS_RN) | r;
+ new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r;
ctx->env = old.fenv;
if (__glibc_unlikely (new.l != old.l))
@@ -218,6 +249,9 @@ libc_feresetround_ppc_ctx (struct rm_ctx *ctx)
#define libc_feholdsetround_ctx libc_feholdsetround_ppc_ctx
#define libc_feholdsetroundf_ctx libc_feholdsetround_ppc_ctx
#define libc_feholdsetroundl_ctx libc_feholdsetround_ppc_ctx
+#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_ppc_ctx
+#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ppc_ctx
+#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ppc_ctx
#define libc_feresetround_ctx libc_feresetround_ppc_ctx
#define libc_feresetroundf_ctx libc_feresetround_ppc_ctx
#define libc_feresetroundl_ctx libc_feresetround_ppc_ctx

View File

@ -0,0 +1,61 @@
commit fec2bd2c2d31bc731cf61623e150d047746954bd
Author: Paul A. Clarke <pc@us.ibm.com>
Date: Tue Aug 6 00:13:45 2019 -0400
[powerpc] fesetenv: optimize FPSCR access
fesetenv() reads the current value of the Floating-Point Status and Control
Register (FPSCR) to determine the difference between the current state of
exception enables and the newly requested state. All of these bits are also
returned by the lighter weight 'mffsl' instruction used by fegetenv_status().
Use that instead.
Also, remove a local macro _FPU_MASK_ALL in favor of a common macro,
FPU_ENABLES_MASK from fenv_libc.h.
Finally, use a local variable ('new') in favor of a pointer dereference
('*envp').
diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c
index ad9fda15b12f15e3..ac927c8f3ada40b4 100644
--- a/sysdeps/powerpc/fpu/fesetenv.c
+++ b/sysdeps/powerpc/fpu/fesetenv.c
@@ -19,8 +19,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
-
int
__fesetenv (const fenv_t *envp)
{
@@ -28,25 +26,23 @@ __fesetenv (const fenv_t *envp)
/* get the currently set exceptions. */
new.fenv = *envp;
- old.fenv = fegetenv_register ();
- if (old.l == new.l)
- return 0;
+ old.fenv = fegetenv_status ();
/* If the old env has no enabled exceptions and the new env has any enabled
exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
hardware into "precise mode" and may cause the FPU to run slower on some
hardware. */
- if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
+ if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0)
(void) __fe_nomask_env_priv ();
/* If the old env had any enabled exceptions and the new env has no enabled
exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
FPU to run faster because it always takes the default action and can not
generate SIGFPE. */
- if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
+ if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0)
(void)__fe_mask_env ();
- fesetenv_register (*envp);
+ fesetenv_register (new.fenv);
/* Success. */
return 0;

View File

@ -0,0 +1,29 @@
commit 953ceff17a4a15b10cfdd5edc3c8cae4884c8ec3
Author: Kamlesh Kumar <kamleshbhalui@gmail.com>
Date: Thu Dec 5 16:49:00 2019 +0100
<string.h>: Define __CORRECT_ISO_CPP_STRING_H_PROTO for Clang [BZ #25232]
Without the asm redirects, strchr et al. are not const-correct.
libc++ has a wrapper header that works with and without
__CORRECT_ISO_CPP_STRING_H_PROTO (using a Clang extension). But when
Clang is used with libstdc++ or just C headers, the overloaded functions
with the correct types are not declared.
This change does not impact current GCC (with libstdc++ or libc++).
diff --git a/string/string.h b/string/string.h
index 73c22a535a..faf997b972 100644
--- a/string/string.h
+++ b/string/string.h
@@ -33,7 +33,8 @@ __BEGIN_DECLS
#include <stddef.h>
/* Tell the caller that we provide correct C++ prototypes. */
-#if defined __cplusplus && __GNUC_PREREQ (4, 4)
+#if defined __cplusplus && (__GNUC_PREREQ (4, 4) \
+ || __glibc_clang_prereq (3, 5))
# define __CORRECT_ISO_CPP_STRING_H_PROTO
#endif

View File

@ -0,0 +1,121 @@
commit 16554464bcd9d77b07c6ff419dc54f00e394fa50
Author: DJ Delorie <dj@redhat.com>
Date: Tue Dec 3 17:44:36 2019 -0500
Correct range checking in mallopt/mxfast/tcache [BZ #25194]
do_set_tcache_max, do_set_mxfast:
Fix two instances of comparing "size_t < 0"
Both cases have upper limit, so the "negative value" case
is already handled via overflow semantics.
do_set_tcache_max, do_set_tcache_count:
Fix return value on error. Note: currently not used.
mallopt:
pass return value of helper functions to user. Behavior should
only be actually changed for mxfast, where we restore the old
(pre-tunables) behavior.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 90825b2aaed53761..00a37f218c0ab3b2 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -5111,13 +5111,14 @@ static inline int
__always_inline
do_set_tcache_max (size_t value)
{
- if (value >= 0 && value <= MAX_TCACHE_SIZE)
+ if (value <= MAX_TCACHE_SIZE)
{
LIBC_PROBE (memory_tunable_tcache_max_bytes, 2, value, mp_.tcache_max_bytes);
mp_.tcache_max_bytes = value;
mp_.tcache_bins = csize2tidx (request2size(value)) + 1;
+ return 1;
}
- return 1;
+ return 0;
}
static inline int
@@ -5128,8 +5129,9 @@ do_set_tcache_count (size_t value)
{
LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
mp_.tcache_count = value;
+ return 1;
}
- return 1;
+ return 0;
}
static inline int
@@ -5146,7 +5148,7 @@ static inline int
__always_inline
do_set_mxfast (size_t value)
{
- if (value >= 0 && value <= MAX_FAST_SIZE)
+ if (value <= MAX_FAST_SIZE)
{
LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ());
set_max_fast (value);
@@ -5171,18 +5173,24 @@ __libc_mallopt (int param_number, int value)
(see definition of set_max_fast). */
malloc_consolidate (av);
+ /* Many of these helper functions take a size_t. We do not worry
+ about overflow here, because negative int values will wrap to
+ very large size_t values and the helpers have sufficient range
+ checking for such conversions. Many of these helpers are also
+ used by the tunables macros in arena.c. */
+
switch (param_number)
{
case M_MXFAST:
- do_set_mxfast (value);
+ res = do_set_mxfast (value);
break;
case M_TRIM_THRESHOLD:
- do_set_trim_threshold (value);
+ res = do_set_trim_threshold (value);
break;
case M_TOP_PAD:
- do_set_top_pad (value);
+ res = do_set_top_pad (value);
break;
case M_MMAP_THRESHOLD:
@@ -5190,25 +5198,25 @@ __libc_mallopt (int param_number, int value)
break;
case M_MMAP_MAX:
- do_set_mmaps_max (value);
+ res = do_set_mmaps_max (value);
break;
case M_CHECK_ACTION:
- do_set_mallopt_check (value);
+ res = do_set_mallopt_check (value);
break;
case M_PERTURB:
- do_set_perturb_byte (value);
+ res = do_set_perturb_byte (value);
break;
case M_ARENA_TEST:
if (value > 0)
- do_set_arena_test (value);
+ res = do_set_arena_test (value);
break;
case M_ARENA_MAX:
if (value > 0)
- do_set_arena_max (value);
+ res = do_set_arena_max (value);
break;
}
__libc_lock_unlock (av->mutex);

View File

@ -0,0 +1,29 @@
commit ef21bd2d8c6805c0c186a01f7c5039189f51b8c4
Author: DJ Delorie <dj@redhat.com>
Date: Fri Oct 18 17:15:52 2019 -0400
loadarchive: guard against locale-archive corruption (Bug #25115)
_nl_load_locale_from_archive() checks for a zero size, but
divides by both (size) and (size-2). Extend the check to
guard against a size of two or less.
Tested by manually corrupting locale-archive and running a program
that calls setlocale() with LOCPATH unset (size is typically very
large).
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/locale/loadarchive.c b/locale/loadarchive.c
index 516d30d8d16bd578..b308fd886f44e1fd 100644
--- a/locale/loadarchive.c
+++ b/locale/loadarchive.c
@@ -274,7 +274,7 @@ _nl_load_locale_from_archive (int category, const char **namep)
+ head->namehash_offset);
/* Avoid division by 0 if the file is corrupted. */
- if (__glibc_unlikely (head->namehash_size == 0))
+ if (__glibc_unlikely (head->namehash_size <= 2))
goto close_and_out;
idx = hval % head->namehash_size;

View File

@ -0,0 +1,382 @@
From: Florian Weimer <fweimer@redhat.com>
Date: Tue, 11 Feb 2020 12:52:06 +0000 (+0100)
Subject: Add internal <file_change_detection.h> header file
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=6c80c6e8767b860a5e18e136d04a80be2a8dce15
Add internal <file_change_detection.h> header file
The code started out with bits form resolv/resolv_conf.c, but it
was enhanced to deal with directories and FIFOs in a more predictable
manner. A test case is included as well.
This will be used to implement the /etc/resolv.conf change detection.
This currently lives in a header file only. Once there are multiple
users, the implementations should be moved into C files.
---
diff -rupN a/include/file_change_detection.h b/include/file_change_detection.h
--- a/include/file_change_detection.h 1969-12-31 19:00:00.000000000 -0500
+++ b/include/file_change_detection.h 2020-03-25 16:57:24.227929816 -0400
@@ -0,0 +1,140 @@
+/* Detecting file changes using modification times.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* Items for identifying a particular file version. Excerpt from
+ struct stat64. */
+struct file_change_detection
+{
+ /* Special values: 0 if file does not exist. -1 to force mismatch
+ with the next comparison. */
+ off64_t size;
+
+ ino64_t ino;
+ struct timespec mtime;
+ struct timespec ctime;
+};
+
+/* Returns true if *LEFT and *RIGHT describe the same version of the
+ same file. */
+static bool __attribute__ ((unused))
+file_is_unchanged (const struct file_change_detection *left,
+ const struct file_change_detection *right)
+{
+ if (left->size < 0 || right->size < 0)
+ /* Negative sizes are used as markers and never match. */
+ return false;
+ else if (left->size == 0 && right->size == 0)
+ /* Both files are empty or do not exist, so they have the same
+ content, no matter what the other fields indicate. */
+ return true;
+ else
+ return left->size == right->size
+ && left->ino == right->ino
+ && left->mtime.tv_sec == right->mtime.tv_sec
+ && left->mtime.tv_nsec == right->mtime.tv_nsec
+ && left->ctime.tv_sec == right->ctime.tv_sec
+ && left->ctime.tv_nsec == right->ctime.tv_nsec;
+}
+
+/* Extract file change information to *FILE from the stat buffer
+ *ST. */
+static void __attribute__ ((unused))
+file_change_detection_for_stat (struct file_change_detection *file,
+ const struct stat64 *st)
+{
+ if (S_ISDIR (st->st_mode))
+ /* Treat as empty file. */
+ file->size = 0;
+ else if (!S_ISREG (st->st_mode))
+ /* Non-regular files cannot be cached. */
+ file->size = -1;
+ else
+ {
+ file->size = st->st_size;
+ file->ino = st->st_ino;
+ file->mtime = st->st_mtim;
+ file->ctime = st->st_ctim;
+ }
+}
+
+/* Writes file change information for PATH to *FILE. Returns true on
+ success. For benign errors, *FILE is cleared, and true is
+ returned. For errors indicating resource outages and the like,
+ false is returned. */
+static bool __attribute__ ((unused))
+file_change_detection_for_path (struct file_change_detection *file,
+ const char *path)
+{
+ struct stat64 st;
+ if (stat64 (path, &st) != 0)
+ switch (errno)
+ {
+ case EACCES:
+ case EISDIR:
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ case EPERM:
+ /* Ignore errors due to file system contents. Instead, treat
+ the file as empty. */
+ file->size = 0;
+ return true;
+ default:
+ /* Other errors are fatal. */
+ return false;
+ }
+ else /* stat64 was successfull. */
+ {
+ file_change_detection_for_stat (file, &st);
+ return true;
+ }
+}
+
+/* Writes file change information for the stream FP to *FILE. Returns
+ ture on success, false on failure. If FP is NULL, treat the file
+ as non-existing. */
+static bool __attribute__ ((unused))
+file_change_detection_for_fp (struct file_change_detection *file,
+ FILE *fp)
+{
+ if (fp == NULL)
+ {
+ /* The file does not exist. */
+ file->size = 0;
+ return true;
+ }
+ else
+ {
+ struct stat64 st;
+ if (fstat64 (__fileno (fp), &st) != 0)
+ /* If we already have a file descriptor, all errors are fatal. */
+ return false;
+ else
+ {
+ file_change_detection_for_stat (file, &st);
+ return true;
+ }
+ }
+}
diff -rupN a/io/Makefile b/io/Makefile
--- a/io/Makefile 2020-03-25 16:55:42.442195992 -0400
+++ b/io/Makefile 2020-03-25 16:58:48.571023810 -0400
@@ -74,6 +74,7 @@ tests := test-utime test-stat test-stat
tst-posix_fallocate tst-posix_fallocate64 \
tst-fts tst-fts-lfs tst-open-tmpfile \
tst-copy_file_range tst-getcwd-abspath \
+ tst-file_change_detection
# Likewise for statx, but we do not need static linking here.
tests-internal += tst-statx
diff -rupN a/io/tst-file_change_detection.c b/io/tst-file_change_detection.c
--- a/io/tst-file_change_detection.c 1969-12-31 19:00:00.000000000 -0500
+++ b/io/tst-file_change_detection.c 2020-03-25 16:57:24.242930366 -0400
@@ -0,0 +1,206 @@
+/* Test for <file_change_detection.c>.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* The header uses the internal __fileno symbol, which is not
+ available outside of libc (even to internal tests). */
+#define __fileno(fp) fileno (fp)
+
+#include <file_change_detection.h>
+
+#include <array_length.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/test-driver.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+#include <unistd.h>
+
+static void
+all_same (struct file_change_detection *array, size_t length)
+{
+ for (size_t i = 0; i < length; ++i)
+ for (size_t j = 0; j < length; ++j)
+ {
+ if (test_verbose > 0)
+ printf ("info: comparing %zu and %zu\n", i, j);
+ TEST_VERIFY (file_is_unchanged (array + i, array + j));
+ }
+}
+
+static void
+all_different (struct file_change_detection *array, size_t length)
+{
+ for (size_t i = 0; i < length; ++i)
+ for (size_t j = 0; j < length; ++j)
+ {
+ if (i == j)
+ continue;
+ if (test_verbose > 0)
+ printf ("info: comparing %zu and %zu\n", i, j);
+ TEST_VERIFY (!file_is_unchanged (array + i, array + j));
+ }
+}
+
+static int
+do_test (void)
+{
+ /* Use a temporary directory with various paths. */
+ char *tempdir = support_create_temp_directory ("tst-file_change_detection-");
+
+ char *path_dangling = xasprintf ("%s/dangling", tempdir);
+ char *path_does_not_exist = xasprintf ("%s/does-not-exist", tempdir);
+ char *path_empty1 = xasprintf ("%s/empty1", tempdir);
+ char *path_empty2 = xasprintf ("%s/empty2", tempdir);
+ char *path_fifo = xasprintf ("%s/fifo", tempdir);
+ char *path_file1 = xasprintf ("%s/file1", tempdir);
+ char *path_file2 = xasprintf ("%s/file2", tempdir);
+ char *path_loop = xasprintf ("%s/loop", tempdir);
+ char *path_to_empty1 = xasprintf ("%s/to-empty1", tempdir);
+ char *path_to_file1 = xasprintf ("%s/to-file1", tempdir);
+
+ add_temp_file (path_dangling);
+ add_temp_file (path_empty1);
+ add_temp_file (path_empty2);
+ add_temp_file (path_fifo);
+ add_temp_file (path_file1);
+ add_temp_file (path_file2);
+ add_temp_file (path_loop);
+ add_temp_file (path_to_empty1);
+ add_temp_file (path_to_file1);
+
+ xsymlink ("target-does-not-exist", path_dangling);
+ support_write_file_string (path_empty1, "");
+ support_write_file_string (path_empty2, "");
+ TEST_COMPARE (mknod (path_fifo, 0777 | S_IFIFO, 0), 0);
+ support_write_file_string (path_file1, "line\n");
+ support_write_file_string (path_file2, "line\n");
+ xsymlink ("loop", path_loop);
+ xsymlink ("empty1", path_to_empty1);
+ xsymlink ("file1", path_to_file1);
+
+ FILE *fp_file1 = xfopen (path_file1, "r");
+ FILE *fp_file2 = xfopen (path_file2, "r");
+ FILE *fp_empty1 = xfopen (path_empty1, "r");
+ FILE *fp_empty2 = xfopen (path_empty2, "r");
+
+ /* Test for the same (empty) files. */
+ {
+ struct file_change_detection fcd[10];
+ int i = 0;
+ /* Two empty files always have the same contents. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty1));
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty2));
+ /* So does a missing file (which is treated as empty). */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++],
+ path_does_not_exist));
+ /* And a symbolic link loop. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_loop));
+ /* And a dangling symbolic link. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_dangling));
+ /* And a directory. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], tempdir));
+ /* And a symbolic link to an empty file. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_to_empty1));
+ /* Likewise for access the file via a FILE *. */
+ TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_empty1));
+ TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_empty2));
+ /* And a NULL FILE * (missing file). */
+ TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], NULL));
+ TEST_COMPARE (i, array_length (fcd));
+
+ all_same (fcd, array_length (fcd));
+ }
+
+ /* Symbolic links are resolved. */
+ {
+ struct file_change_detection fcd[3];
+ int i = 0;
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file1));
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_to_file1));
+ TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_file1));
+ TEST_COMPARE (i, array_length (fcd));
+ all_same (fcd, array_length (fcd));
+ }
+
+ /* Test for different files. */
+ {
+ struct file_change_detection fcd[5];
+ int i = 0;
+ /* The other files are not empty. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty1));
+ /* These two files have the same contents, but have different file
+ identity. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file1));
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file2));
+ /* FIFOs are always different, even with themselves. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_fifo));
+ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_fifo));
+ TEST_COMPARE (i, array_length (fcd));
+ all_different (fcd, array_length (fcd));
+
+ /* Replacing the file with its symbolic link does not make a
+ difference. */
+ TEST_VERIFY (file_change_detection_for_path (&fcd[1], path_to_file1));
+ all_different (fcd, array_length (fcd));
+ }
+
+ /* Wait for a file change. Depending on file system time stamp
+ resolution, this subtest blocks for a while. */
+ for (int use_stdio = 0; use_stdio < 2; ++use_stdio)
+ {
+ struct file_change_detection initial;
+ TEST_VERIFY (file_change_detection_for_path (&initial, path_file1));
+ while (true)
+ {
+ support_write_file_string (path_file1, "line\n");
+ struct file_change_detection current;
+ if (use_stdio)
+ TEST_VERIFY (file_change_detection_for_fp (&current, fp_file1));
+ else
+ TEST_VERIFY (file_change_detection_for_path (&current, path_file1));
+ if (!file_is_unchanged (&initial, &current))
+ break;
+ /* Wait for a bit to reduce system load. */
+ usleep (100 * 1000);
+ }
+ }
+
+ fclose (fp_empty1);
+ fclose (fp_empty2);
+ fclose (fp_file1);
+ fclose (fp_file2);
+
+ free (path_dangling);
+ free (path_does_not_exist);
+ free (path_empty1);
+ free (path_empty2);
+ free (path_fifo);
+ free (path_file1);
+ free (path_file2);
+ free (path_loop);
+ free (path_to_empty1);
+ free (path_to_file1);
+
+ free (tempdir);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

View File

@ -0,0 +1,94 @@
From: Florian Weimer <fweimer@redhat.com>
Date: Tue, 21 Jan 2020 15:52:33 +0000 (+0100)
Subject: resolv: Use <file_change_detection.h> in __resolv_conf_get_current
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=9642b85fd0dfa5731020a3271c08e33e1dc05c85
resolv: Use <file_change_detection.h> in __resolv_conf_get_current
Only minor functional changes (i.e., regarding the handling of
directories, which are now treated as empty files).
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
index 08c50ef19e..d954ba9a5a 100644
--- a/resolv/resolv_conf.c
+++ b/resolv/resolv_conf.c
@@ -24,6 +24,7 @@
#include <resolv-internal.h>
#include <sys/stat.h>
#include <libc-symbols.h>
+#include <file_change_detection.h>
/* _res._u._ext.__glibc_extension_index is used as an index into a
struct resolv_conf_array object. The intent of this construction
@@ -68,12 +69,8 @@ struct resolv_conf_global
/* Cached current configuration object for /etc/resolv.conf. */
struct resolv_conf *conf_current;
- /* These properties of /etc/resolv.conf are used to check if the
- configuration needs reloading. */
- struct timespec conf_mtime;
- struct timespec conf_ctime;
- off64_t conf_size;
- ino64_t conf_ino;
+ /* File system identification for /etc/resolv.conf. */
+ struct file_change_detection file_resolve_conf;
};
/* Lazily allocated storage for struct resolv_conf_global. */
@@ -123,37 +120,16 @@ conf_decrement (struct resolv_conf *conf)
struct resolv_conf *
__resolv_conf_get_current (void)
{
- struct stat64 st;
- if (stat64 (_PATH_RESCONF, &st) != 0)
- {
- switch (errno)
- {
- case EACCES:
- case EISDIR:
- case ELOOP:
- case ENOENT:
- case ENOTDIR:
- case EPERM:
- /* Ignore errors due to file system contents. */
- memset (&st, 0, sizeof (st));
- break;
- default:
- /* Other errors are fatal. */
- return NULL;
- }
- }
+ struct file_change_detection initial;
+ if (!file_change_detection_for_path (&initial, _PATH_RESCONF))
+ return NULL;
struct resolv_conf_global *global_copy = get_locked_global ();
if (global_copy == NULL)
return NULL;
struct resolv_conf *conf;
if (global_copy->conf_current != NULL
- && (global_copy->conf_mtime.tv_sec == st.st_mtim.tv_sec
- && global_copy->conf_mtime.tv_nsec == st.st_mtim.tv_nsec
- && global_copy->conf_ctime.tv_sec == st.st_ctim.tv_sec
- && global_copy->conf_ctime.tv_nsec == st.st_ctim.tv_nsec
- && global_copy->conf_ino == st.st_ino
- && global_copy->conf_size == st.st_size))
+ && file_is_unchanged (&initial, &global_copy->file_resolve_conf))
/* We can reuse the cached configuration object. */
conf = global_copy->conf_current;
else
@@ -171,10 +147,7 @@ __resolv_conf_get_current (void)
read could be a newer version of the file, but this does
not matter because this will lead to an extraneous reload
later. */
- global_copy->conf_mtime = st.st_mtim;
- global_copy->conf_ctime = st.st_ctim;
- global_copy->conf_ino = st.st_ino;
- global_copy->conf_size = st.st_size;
+ global_copy->file_resolve_conf = initial;
}
}

View File

@ -0,0 +1,46 @@
From: Florian Weimer <fweimer@redhat.com>
Date: Tue, 21 Jan 2020 16:11:01 +0000 (+0100)
Subject: resolv: Fix file handle leak in __resolv_conf_load [BZ #25429]
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=a1a20f029299dc27170912bb9233070c8403444d
resolv: Fix file handle leak in __resolv_conf_load [BZ #25429]
res_vinit_1 did not close the stream on errors, only on success.
This change moves closing the stream to __resolv_conf_load, for both
the success and error cases.
Fixes commit 89f187a40fc0ad4e22838526bfe34d73f758b776 ("resolv: Use
getline for configuration file reading in res_vinit_1") and commit
3f853f22c87f0b671c0366eb290919719fa56c0e ("resolv: Lift domain search
list limits [BZ #19569] [BZ #21475]"), where memory allocation was
introduced into res_vinit_1.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
diff --git a/resolv/res_init.c b/resolv/res_init.c
index 95dce098aa..09345718cd 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -508,7 +508,6 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
continue;
}
}
- fclose (fp);
}
if (__glibc_unlikely (nameserver_list_size (&parser->nameserver_list) == 0))
{
@@ -593,6 +592,13 @@ __resolv_conf_load (struct __res_state *preinit)
}
resolv_conf_parser_free (&parser);
+ if (fp != NULL)
+ {
+ int saved_errno = errno;
+ fclose (fp);
+ __set_errno (saved_errno);
+ }
+
return conf;
}

View File

@ -0,0 +1,96 @@
From: Florian Weimer <fweimer@redhat.com>
Date: Tue, 21 Jan 2020 16:25:39 +0000 (+0100)
Subject: resolv: Enhance __resolv_conf_load to capture file change data
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=dd0b4df329ff7ff2a656404db271c8ee8379ff9d
resolv: Enhance __resolv_conf_load to capture file change data
The data is captured after reading the file. This allows callers
to check the change data against an earlier measurement.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
diff --git a/resolv/res_init.c b/resolv/res_init.c
index 09345718cd..98d84f264d 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -103,6 +103,7 @@
#include <inet/net-internal.h>
#include <errno.h>
#include <resolv_conf.h>
+#include <file_change_detection.h>
static uint32_t net_mask (struct in_addr);
@@ -549,7 +550,8 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
}
struct resolv_conf *
-__resolv_conf_load (struct __res_state *preinit)
+__resolv_conf_load (struct __res_state *preinit,
+ struct file_change_detection *change)
{
/* Ensure that /etc/hosts.conf has been loaded (once). */
_res_hconf_init ();
@@ -577,7 +579,13 @@ __resolv_conf_load (struct __res_state *preinit)
resolv_conf_parser_init (&parser, preinit);
struct resolv_conf *conf = NULL;
- if (res_vinit_1 (fp, &parser))
+ bool ok = res_vinit_1 (fp, &parser);
+ if (ok && change != NULL)
+ /* Update the file change information if the configuration was
+ loaded successfully. */
+ ok = file_change_detection_for_fp (change, fp);
+
+ if (ok)
{
parser.template.nameserver_list
= nameserver_list_begin (&parser.nameserver_list);
@@ -615,7 +623,7 @@ __res_vinit (res_state statp, int preinit)
if (preinit && has_preinit_values (statp))
/* For the preinit case, we cannot use the cached configuration
because some settings could be different. */
- conf = __resolv_conf_load (statp);
+ conf = __resolv_conf_load (statp, NULL);
else
conf = __resolv_conf_get_current ();
if (conf == NULL)
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
index d954ba9a5a..bdd2ebb909 100644
--- a/resolv/resolv_conf.c
+++ b/resolv/resolv_conf.c
@@ -136,7 +136,7 @@ __resolv_conf_get_current (void)
{
/* Parse configuration while holding the lock. This avoids
duplicate work. */
- conf = __resolv_conf_load (NULL);
+ conf = __resolv_conf_load (NULL, NULL);
if (conf != NULL)
{
if (global_copy->conf_current != NULL)
diff --git a/resolv/resolv_conf.h b/resolv/resolv_conf.h
index 01cbff9111..101e14bfe5 100644
--- a/resolv/resolv_conf.h
+++ b/resolv/resolv_conf.h
@@ -63,12 +63,16 @@ struct resolv_conf
and the struct resolv_context facility. */
struct __res_state;
+struct file_change_detection;
/* Read /etc/resolv.conf and return a configuration object, or NULL if
/etc/resolv.conf cannot be read due to memory allocation errors.
- If PREINIT is not NULL, some configuration values are taken from the
- struct __res_state object. */
-struct resolv_conf *__resolv_conf_load (struct __res_state *preinit)
+ If PREINIT is not NULL, some configuration values are taken from
+ the struct __res_state object. If CHANGE is not null, file change
+ detection data is written to *CHANGE, based on the state of the
+ file after reading it. */
+struct resolv_conf *__resolv_conf_load (struct __res_state *preinit,
+ struct file_change_detection *change)
attribute_hidden __attribute__ ((warn_unused_result));
/* Return a configuration object for the current /etc/resolv.conf

View File

@ -0,0 +1,52 @@
From: Florian Weimer <fweimer@redhat.com>
Date: Tue, 21 Jan 2020 16:38:15 +0000 (+0100)
Subject: resolv: Fix ABA race in /etc/resolv.conf change detection [BZ #25420]
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=fa00db0a6eb755837ae5d413515e0da582b304f3
resolv: Fix ABA race in /etc/resolv.conf change detection [BZ #25420]
__resolv_conf_get_current should only record the initial file
change data if after verifying that file just read matches the
original measurement. Fixes commit aef16cc8a4c670036d45590877
("resolv: Automatically reload a changed /etc/resolv.conf file
[BZ #984]").
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
index bdd2ebb909..29a1f4fb94 100644
--- a/resolv/resolv_conf.c
+++ b/resolv/resolv_conf.c
@@ -136,18 +136,25 @@ __resolv_conf_get_current (void)
{
/* Parse configuration while holding the lock. This avoids
duplicate work. */
- conf = __resolv_conf_load (NULL, NULL);
+ struct file_change_detection after_load;
+ conf = __resolv_conf_load (NULL, &after_load);
if (conf != NULL)
{
if (global_copy->conf_current != NULL)
conf_decrement (global_copy->conf_current);
global_copy->conf_current = conf; /* Takes ownership. */
- /* Update file modification stamps. The configuration we
- read could be a newer version of the file, but this does
- not matter because this will lead to an extraneous reload
- later. */
- global_copy->file_resolve_conf = initial;
+ /* Update file change detection data, but only if it matches
+ the initial measurement. This avoids an ABA race in case
+ /etc/resolv.conf is temporarily replaced while the file
+ is read (after the initial measurement), and restored to
+ the initial version later. */
+ if (file_is_unchanged (&initial, &after_load))
+ global_copy->file_resolve_conf = after_load;
+ else
+ /* If there is a discrepancy, trigger a reload during the
+ next use. */
+ global_copy->file_resolve_conf.size = -1;
}
}

View File

@ -0,0 +1,481 @@
From: Florian Weimer <fweimer@redhat.com>
Date: Tue, 18 Feb 2020 12:44:48 +0000 (+0100)
Subject: Move implementation of <file_change_detection.h> into a C file
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=631cf64bc1d8306e011ef39f60b8cb6de91bd271
Move implementation of <file_change_detection.h> into a C file
file_change_detection_for_stat partially initialize
struct file_change_detection in some cases, when the size member
alone determines the outcome of all comparisons. This results
in maybe-uninitialized compiler warnings in case of sufficiently
aggressive inlining.
Once the implementation is moved into a separate C file, this kind
of inlining is no longer possible, so the compiler warnings are gone.
---
diff --git a/include/file_change_detection.h b/include/file_change_detection.h
index aaed0a9b6d..767e578555 100644
--- a/include/file_change_detection.h
+++ b/include/file_change_detection.h
@@ -16,9 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <errno.h>
+#ifndef _FILE_CHANGE_DETECTION_H
+#define _FILE_CHANGE_DETECTION_H
+
#include <stdbool.h>
-#include <stddef.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -38,103 +39,32 @@ struct file_change_detection
/* Returns true if *LEFT and *RIGHT describe the same version of the
same file. */
-static bool __attribute__ ((unused))
-file_is_unchanged (const struct file_change_detection *left,
- const struct file_change_detection *right)
-{
- if (left->size < 0 || right->size < 0)
- /* Negative sizes are used as markers and never match. */
- return false;
- else if (left->size == 0 && right->size == 0)
- /* Both files are empty or do not exist, so they have the same
- content, no matter what the other fields indicate. */
- return true;
- else
- return left->size == right->size
- && left->ino == right->ino
- && left->mtime.tv_sec == right->mtime.tv_sec
- && left->mtime.tv_nsec == right->mtime.tv_nsec
- && left->ctime.tv_sec == right->ctime.tv_sec
- && left->ctime.tv_nsec == right->ctime.tv_nsec;
-}
+bool __file_is_unchanged (const struct file_change_detection *left,
+ const struct file_change_detection *right);
/* Extract file change information to *FILE from the stat buffer
*ST. */
-static void __attribute__ ((unused))
-file_change_detection_for_stat (struct file_change_detection *file,
- const struct stat64 *st)
-{
- if (S_ISDIR (st->st_mode))
- /* Treat as empty file. */
- file->size = 0;
- else if (!S_ISREG (st->st_mode))
- /* Non-regular files cannot be cached. */
- file->size = -1;
- else
- {
- file->size = st->st_size;
- file->ino = st->st_ino;
- file->mtime = st->st_mtim;
- file->ctime = st->st_ctim;
- }
-}
+void __file_change_detection_for_stat (struct file_change_detection *file,
+ const struct stat64 *st);
/* Writes file change information for PATH to *FILE. Returns true on
success. For benign errors, *FILE is cleared, and true is
returned. For errors indicating resource outages and the like,
false is returned. */
-static bool __attribute__ ((unused))
-file_change_detection_for_path (struct file_change_detection *file,
- const char *path)
-{
- struct stat64 st;
- if (stat64 (path, &st) != 0)
- switch (errno)
- {
- case EACCES:
- case EISDIR:
- case ELOOP:
- case ENOENT:
- case ENOTDIR:
- case EPERM:
- /* Ignore errors due to file system contents. Instead, treat
- the file as empty. */
- file->size = 0;
- return true;
- default:
- /* Other errors are fatal. */
- return false;
- }
- else /* stat64 was successfull. */
- {
- file_change_detection_for_stat (file, &st);
- return true;
- }
-}
+bool __file_change_detection_for_path (struct file_change_detection *file,
+ const char *path);
/* Writes file change information for the stream FP to *FILE. Returns
ture on success, false on failure. If FP is NULL, treat the file
as non-existing. */
-static bool __attribute__ ((unused))
-file_change_detection_for_fp (struct file_change_detection *file,
- FILE *fp)
-{
- if (fp == NULL)
- {
- /* The file does not exist. */
- file->size = 0;
- return true;
- }
- else
- {
- struct stat64 st;
- if (fstat64 (__fileno (fp), &st) != 0)
- /* If we already have a file descriptor, all errors are fatal. */
- return false;
- else
- {
- file_change_detection_for_stat (file, &st);
- return true;
- }
- }
-}
+bool __file_change_detection_for_fp (struct file_change_detection *file,
+ FILE *fp);
+
+#ifndef _ISOMAC
+libc_hidden_proto (__file_is_unchanged)
+libc_hidden_proto (__file_change_detection_for_stat)
+libc_hidden_proto (__file_change_detection_for_path)
+libc_hidden_proto (__file_change_detection_for_fp)
+#endif
+
+#endif /* _FILE_CHANGE_DETECTION_H */
diff --git a/io/Makefile b/io/Makefile
index 04c4647dc0..cf380f3516 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -55,7 +55,7 @@ routines := \
posix_fadvise posix_fadvise64 \
posix_fallocate posix_fallocate64 \
sendfile sendfile64 copy_file_range \
- utimensat futimens
+ utimensat futimens file_change_detection
# These routines will be omitted from the libc shared object.
# Instead the static object files will be included in a special archive
diff --git a/io/Versions b/io/Versions
index f7e5dbe49e..ee468055ff 100644
--- a/io/Versions
+++ b/io/Versions
@@ -137,5 +137,9 @@ libc {
__fcntl_nocancel;
__open64_nocancel;
__write_nocancel;
+ __file_is_unchanged;
+ __file_change_detection_for_stat;
+ __file_change_detection_for_path;
+ __file_change_detection_for_fp;
}
}
diff --git a/io/file_change_detection.c b/io/file_change_detection.c
new file mode 100644
index 0000000000..c6d700ed05
--- /dev/null
+++ b/io/file_change_detection.c
@@ -0,0 +1,118 @@
+/* Detecting file changes using modification times.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <file_change_detection.h>
+
+#include <errno.h>
+#include <stddef.h>
+
+bool
+__file_is_unchanged (const struct file_change_detection *left,
+ const struct file_change_detection *right)
+{
+ if (left->size < 0 || right->size < 0)
+ /* Negative sizes are used as markers and never match. */
+ return false;
+ else if (left->size == 0 && right->size == 0)
+ /* Both files are empty or do not exist, so they have the same
+ content, no matter what the other fields indicate. */
+ return true;
+ else
+ return left->size == right->size
+ && left->ino == right->ino
+ && left->mtime.tv_sec == right->mtime.tv_sec
+ && left->mtime.tv_nsec == right->mtime.tv_nsec
+ && left->ctime.tv_sec == right->ctime.tv_sec
+ && left->ctime.tv_nsec == right->ctime.tv_nsec;
+}
+libc_hidden_def (__file_is_unchanged)
+
+void
+__file_change_detection_for_stat (struct file_change_detection *file,
+ const struct stat64 *st)
+{
+ if (S_ISDIR (st->st_mode))
+ /* Treat as empty file. */
+ file->size = 0;
+ else if (!S_ISREG (st->st_mode))
+ /* Non-regular files cannot be cached. */
+ file->size = -1;
+ else
+ {
+ file->size = st->st_size;
+ file->ino = st->st_ino;
+ file->mtime = st->st_mtim;
+ file->ctime = st->st_ctim;
+ }
+}
+libc_hidden_def (__file_change_detection_for_stat)
+
+bool
+__file_change_detection_for_path (struct file_change_detection *file,
+ const char *path)
+{
+ struct stat64 st;
+ if (stat64 (path, &st) != 0)
+ switch (errno)
+ {
+ case EACCES:
+ case EISDIR:
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ case EPERM:
+ /* Ignore errors due to file system contents. Instead, treat
+ the file as empty. */
+ file->size = 0;
+ return true;
+ default:
+ /* Other errors are fatal. */
+ return false;
+ }
+ else /* stat64 was successfull. */
+ {
+ __file_change_detection_for_stat (file, &st);
+ return true;
+ }
+}
+libc_hidden_def (__file_change_detection_for_path)
+
+bool
+__file_change_detection_for_fp (struct file_change_detection *file,
+ FILE *fp)
+{
+ if (fp == NULL)
+ {
+ /* The file does not exist. */
+ file->size = 0;
+ return true;
+ }
+ else
+ {
+ struct stat64 st;
+ if (fstat64 (__fileno (fp), &st) != 0)
+ /* If we already have a file descriptor, all errors are fatal. */
+ return false;
+ else
+ {
+ __file_change_detection_for_stat (file, &st);
+ return true;
+ }
+ }
+}
+libc_hidden_def (__file_change_detection_for_fp)
diff --git a/io/tst-file_change_detection.c b/io/tst-file_change_detection.c
index 035dd39c4d..6e00e787b1 100644
--- a/io/tst-file_change_detection.c
+++ b/io/tst-file_change_detection.c
@@ -16,10 +16,6 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-/* The header uses the internal __fileno symbol, which is not
- available outside of libc (even to internal tests). */
-#define __fileno(fp) fileno (fp)
-
#include <file_change_detection.h>
#include <array_length.h>
@@ -40,7 +36,7 @@ all_same (struct file_change_detection *array, size_t length)
{
if (test_verbose > 0)
printf ("info: comparing %zu and %zu\n", i, j);
- TEST_VERIFY (file_is_unchanged (array + i, array + j));
+ TEST_VERIFY (__file_is_unchanged (array + i, array + j));
}
}
@@ -54,7 +50,7 @@ all_different (struct file_change_detection *array, size_t length)
continue;
if (test_verbose > 0)
printf ("info: comparing %zu and %zu\n", i, j);
- TEST_VERIFY (!file_is_unchanged (array + i, array + j));
+ TEST_VERIFY (!__file_is_unchanged (array + i, array + j));
}
}
@@ -105,24 +101,24 @@ do_test (void)
struct file_change_detection fcd[10];
int i = 0;
/* Two empty files always have the same contents. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty1));
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty2));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_empty1));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_empty2));
/* So does a missing file (which is treated as empty). */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++],
- path_does_not_exist));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++],
+ path_does_not_exist));
/* And a symbolic link loop. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_loop));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_loop));
/* And a dangling symbolic link. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_dangling));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_dangling));
/* And a directory. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], tempdir));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], tempdir));
/* And a symbolic link to an empty file. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_to_empty1));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_to_empty1));
/* Likewise for access the file via a FILE *. */
- TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_empty1));
- TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_empty2));
+ TEST_VERIFY (__file_change_detection_for_fp (&fcd[i++], fp_empty1));
+ TEST_VERIFY (__file_change_detection_for_fp (&fcd[i++], fp_empty2));
/* And a NULL FILE * (missing file). */
- TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], NULL));
+ TEST_VERIFY (__file_change_detection_for_fp (&fcd[i++], NULL));
TEST_COMPARE (i, array_length (fcd));
all_same (fcd, array_length (fcd));
@@ -132,9 +128,9 @@ do_test (void)
{
struct file_change_detection fcd[3];
int i = 0;
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file1));
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_to_file1));
- TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_file1));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_file1));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_to_file1));
+ TEST_VERIFY (__file_change_detection_for_fp (&fcd[i++], fp_file1));
TEST_COMPARE (i, array_length (fcd));
all_same (fcd, array_length (fcd));
}
@@ -144,20 +140,20 @@ do_test (void)
struct file_change_detection fcd[5];
int i = 0;
/* The other files are not empty. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty1));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_empty1));
/* These two files have the same contents, but have different file
identity. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file1));
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file2));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_file1));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_file2));
/* FIFOs are always different, even with themselves. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_fifo));
- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_fifo));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_fifo));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_fifo));
TEST_COMPARE (i, array_length (fcd));
all_different (fcd, array_length (fcd));
/* Replacing the file with its symbolic link does not make a
difference. */
- TEST_VERIFY (file_change_detection_for_path (&fcd[1], path_to_file1));
+ TEST_VERIFY (__file_change_detection_for_path (&fcd[1], path_to_file1));
all_different (fcd, array_length (fcd));
}
@@ -166,16 +162,17 @@ do_test (void)
for (int use_stdio = 0; use_stdio < 2; ++use_stdio)
{
struct file_change_detection initial;
- TEST_VERIFY (file_change_detection_for_path (&initial, path_file1));
+ TEST_VERIFY (__file_change_detection_for_path (&initial, path_file1));
while (true)
{
support_write_file_string (path_file1, "line\n");
struct file_change_detection current;
if (use_stdio)
- TEST_VERIFY (file_change_detection_for_fp (&current, fp_file1));
+ TEST_VERIFY (__file_change_detection_for_fp (&current, fp_file1));
else
- TEST_VERIFY (file_change_detection_for_path (&current, path_file1));
- if (!file_is_unchanged (&initial, &current))
+ TEST_VERIFY (__file_change_detection_for_path
+ (&current, path_file1));
+ if (!__file_is_unchanged (&initial, &current))
break;
/* Wait for a bit to reduce system load. */
usleep (100 * 1000);
diff --git a/resolv/res_init.c b/resolv/res_init.c
index 98d84f264d..ee5dfdd391 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -583,7 +583,7 @@ __resolv_conf_load (struct __res_state *preinit,
if (ok && change != NULL)
/* Update the file change information if the configuration was
loaded successfully. */
- ok = file_change_detection_for_fp (change, fp);
+ ok = __file_change_detection_for_fp (change, fp);
if (ok)
{
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
index 29a1f4fb94..286149ffad 100644
--- a/resolv/resolv_conf.c
+++ b/resolv/resolv_conf.c
@@ -121,7 +121,7 @@ struct resolv_conf *
__resolv_conf_get_current (void)
{
struct file_change_detection initial;
- if (!file_change_detection_for_path (&initial, _PATH_RESCONF))
+ if (!__file_change_detection_for_path (&initial, _PATH_RESCONF))
return NULL;
struct resolv_conf_global *global_copy = get_locked_global ();
@@ -129,7 +129,7 @@ __resolv_conf_get_current (void)
return NULL;
struct resolv_conf *conf;
if (global_copy->conf_current != NULL
- && file_is_unchanged (&initial, &global_copy->file_resolve_conf))
+ && __file_is_unchanged (&initial, &global_copy->file_resolve_conf))
/* We can reuse the cached configuration object. */
conf = global_copy->conf_current;
else
@@ -149,7 +149,7 @@ __resolv_conf_get_current (void)
/etc/resolv.conf is temporarily replaced while the file
is read (after the initial measurement), and restored to
the initial version later. */
- if (file_is_unchanged (&initial, &after_load))
+ if (__file_is_unchanged (&initial, &after_load))
global_copy->file_resolve_conf = after_load;
else
/* If there is a discrepancy, trigger a reload during the

View File

@ -0,0 +1,28 @@
commit 8b222fa38700422b4da6731806835f0bbf40920d
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Jan 20 18:37:13 2020 +0100
getaddrinfo: Fix resource leak after strdup failure in gethosts [BZ #25425]
Filip Ochnik spotted that one of the error jumps in gethosts fails to
call __resolv_context_put to release the resolver context.
Fixes commit 352f4ff9a268b81ef5d4b2413f582565806e4790 ("resolv:
Introduce struct resolv_context [BZ #21668]") and commit
964263bb8d650f1681665c55704fb01a8e725621 ("getaddrinfo: Release
resolver context on error in gethosts [BZ #21885]").
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 6a5805c9e63a257c..fae3dea81f19dba6 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -292,6 +292,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
canonbuf = __strdup (localcanon); \
if (canonbuf == NULL) \
{ \
+ __resolv_context_put (res_ctx); \
result = -EAI_SYSTEM; \
goto free_and_return; \
} \

View File

@ -0,0 +1,170 @@
commit 0499a353a6e196f468e7ec554cb13c82011f0e36
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Mar 2 14:24:27 2020 +0100
elf: Add elf/check-wx-segment, a test for the presence of WX segments
Writable, executable segments defeat security hardening. The
existing check for DT_TEXTREL does not catch this.
hppa and SPARC currently keep the PLT in an RWX load segment.
# Conflicts:
# sysdeps/sparc/Makefile
diff --git a/elf/Makefile b/elf/Makefile
index f1a16fe8ca594c57..a52d9b1f6a4364a7 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -378,6 +378,7 @@ tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \
$(objpfx)tst-rtld-preload.out
endif
tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
+ $(objpfx)check-wx-segment.out \
$(objpfx)check-localplt.out $(objpfx)check-initfini.out
endif
@@ -1148,6 +1149,12 @@ $(objpfx)check-execstack.out: $(..)scripts/check-execstack.awk \
$(evaluate-test)
generated += check-execstack.out
+$(objpfx)check-wx-segment.out: $(..)scripts/check-wx-segment.py \
+ $(all-built-dso:=.phdr)
+ $(PYTHON) $^ --xfail="$(check-wx-segment-xfail)" > $@; \
+ $(evaluate-test)
+generated += check-wx-segment.out
+
$(objpfx)tst-dlmodcount: $(libdl)
$(objpfx)tst-dlmodcount.out: $(test-modules)
diff --git a/scripts/check-wx-segment.py b/scripts/check-wx-segment.py
new file mode 100644
index 0000000000000000..e1fa79387ce22c4b
--- /dev/null
+++ b/scripts/check-wx-segment.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python3
+# Check ELF program headers for WX segments.
+# Copyright (C) 2020 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+"""Check that the program headers do not contain write-exec segments."""
+
+import argparse
+import os.path
+import re
+import sys
+
+# Regular expression to extract the RWE flags field. The
+# address/offset columns have varying width.
+RE_LOAD = re.compile(
+ r'^ LOAD +(?:0x[0-9a-fA-F]+ +){5}([R ][W ][ E]) +0x[0-9a-fA-F]+\n\Z')
+
+def process_file(path, inp, xfail):
+ """Analyze one input file."""
+
+ errors = 0
+ for line in inp:
+ error = None
+ if line.startswith(' LOAD '):
+ match = RE_LOAD.match(line)
+ if match is None:
+ error = 'Invalid LOAD line'
+ else:
+ flags, = match.groups()
+ if 'W' in flags and 'E' in flags:
+ if xfail:
+ print('{}: warning: WX segment (as expected)'.format(
+ path))
+ else:
+ error = 'WX segment'
+
+ if error is not None:
+ print('{}: error: {}: {!r}'.format(path, error, line.strip()))
+ errors += 1
+
+ if xfail and errors == 0:
+ print('{}: warning: missing expected WX segment'.format(path))
+ return errors
+
+
+def main():
+ """The main entry point."""
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--xfail',
+ help='Mark input files as XFAILed ("*" for all)',
+ type=str, default='')
+ parser.add_argument('phdrs',
+ help='Files containing readelf -Wl output',
+ nargs='*')
+ opts = parser.parse_args(sys.argv)
+
+ xfails = set(opts.xfail.split(' '))
+ xfails_all = opts.xfail.strip() == '*'
+
+ errors = 0
+ for path in opts.phdrs:
+ xfail = ((os.path.basename(path) + '.phdrs') in xfails
+ or xfails_all)
+ with open(path) as inp:
+ errors += process_file(path, inp, xfail)
+ if errors > 0:
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/sysdeps/sparc/Makefile b/sysdeps/sparc/Makefile
index 3f0c0964002560f0..a1004e819c9b0c38 100644
--- a/sysdeps/sparc/Makefile
+++ b/sysdeps/sparc/Makefile
@@ -16,5 +16,14 @@ CPPFLAGS-crti.S += -fPIC
CPPFLAGS-crtn.S += -fPIC
endif
+ifeq ($(subdir),elf)
+
+# Lazy binding on SPARC rewrites the PLT sequence. See the Solaris
+# Linker and Libraries Guide, section SPARC: Procedure Linkage Table.
+# <https://docs.oracle.com/cd/E19455-01/816-0559/chapter6-1236/index.html>
+test-xfail-check-wx-segment = *
+
+endif # $(subdir) == elf
+
# The assembler on SPARC needs the -fPIC flag even when it's assembler code.
ASFLAGS-.os += -fPIC
diff --git a/sysdeps/unix/sysv/linux/hppa/Makefile b/sysdeps/unix/sysv/linux/hppa/Makefile
index e1637f54f508c007..c89ec8318208205d 100644
--- a/sysdeps/unix/sysv/linux/hppa/Makefile
+++ b/sysdeps/unix/sysv/linux/hppa/Makefile
@@ -3,9 +3,14 @@ ifeq ($(subdir),stdlib)
gen-as-const-headers += ucontext_i.sym
endif
+ifeq ($(subdir),elf)
# Supporting non-executable stacks on HPPA requires changes to both
# the Linux kernel and glibc. The kernel currently needs an executable
# stack for syscall restarts and signal returns.
-ifeq ($(subdir),elf)
test-xfail-check-execstack = yes
-endif
+
+# On hppa, the PLT is executable because it contains an executable
+# trampoline used during lazy binding.
+test-xfail-check-wx-segment = *
+
+endif # $(subdir) == elf

View File

@ -0,0 +1,49 @@
commit 279c68ce1336d84d82ce491a4b77086e574ba380
Author: DJ Delorie <dj@redhat.com>
Date: Mon Feb 3 14:57:23 2020 -0500
Run nptl/tst-pthread-getattr in a container
See https://bugzilla.redhat.com/show_bug.cgi?id=1653942
This test depends on the kernel's assignment of memory regions, but
running under ld.so explicitly changes those assignments, sometimes
sufficiently to cause the test to fail (esp with address space
randomization).
The easiest way to "fix" the test, is to run it the way the user would
- without ld.so. Running it in a container does that.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/nptl/Makefile b/nptl/Makefile
index b1003cf56b31ddfa..071c53866d14d2fe 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -293,7 +293,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
tst-exec1 tst-exec2 tst-exec3 tst-exec4 tst-exec5 \
tst-exit1 tst-exit2 tst-exit3 \
tst-stdio1 tst-stdio2 \
- tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \
+ tst-stack1 tst-stack2 tst-stack3 tst-stack4 \
tst-pthread-attr-affinity tst-pthread-mutexattr \
tst-unload \
tst-dlsym1 \
@@ -322,6 +322,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
tst-rwlock-pwn \
tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall
+tests-container = tst-pthread-getattr
+
tests-internal := tst-rwlock19 tst-rwlock20 \
tst-sem11 tst-sem12 tst-sem13 \
tst-barrier5 tst-signal7 tst-mutex8 tst-mutex8-static \
@@ -633,7 +635,7 @@ ifeq ($(build-shared),yes)
$(addprefix $(objpfx), \
$(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \
$(tests-nolibpthread), \
- $(tests) $(tests-internal) $(xtests) $(test-srcs))): \
+ $(tests) $(tests-internal) $(xtests) $(test-srcs) $(tests-container))): \
$(objpfx)libpthread.so
$(objpfx)tst-unload: $(libdl)
# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,

View File

@ -0,0 +1,28 @@
commit a331150af65477fc3fa72ab341eed5e0b2daf7f3
Author: Joseph Myers <joseph@codesourcery.com>
Date: Thu Nov 28 20:32:09 2019 +0000
Update syscall-names.list for Linux 5.4.
This patch updates syscall-names.list for Linux 5.4. There are no new
syscalls, so this is just a matter of updating the version number
listed in the file.
Tested with build-many-glibcs.py.
Reworked for RHEL 8.3.0.
diff -Nrup a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
--- a/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-05 20:20:41.471686371 -0400
+++ b/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-05 20:21:56.871912297 -0400
@@ -22,8 +22,8 @@
# names are only used if the installed kernel headers also provide
# them.
-# The list of system calls is current as of Linux 5.3.
-kernel 5.3
+# The list of system calls is current as of Linux 5.4.
+kernel 5.4
FAST_atomic_update
FAST_cmpxchg

View File

@ -0,0 +1,29 @@
commit 5828bc4523230685ac29a4a882967913255f5666
Author: Joseph Myers <joseph@codesourcery.com>
Date: Fri Feb 7 13:54:58 2020 +0000
Update syscall lists for Linux 5.5.
Linux 5.5 has no new syscalls to add to syscall-names.list, but it
does newly enable the clone3 syscall for AArch64. This patch updates
the kernel version listed in syscall-names.list and regenerates the
AArch64 arch-syscall.h.
Tested with build-many-glibcs.py.
Modified to only update syscall-names.list for RHEL 8.3.0.
diff -Nrup a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
--- a/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-06 12:10:47.683272882 -0400
+++ b/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-06 12:12:41.769598687 -0400
@@ -22,8 +22,8 @@
# names are only used if the installed kernel headers also provide
# them.
-# The list of system calls is current as of Linux 5.4.
-kernel 5.4
+# The list of system calls is current as of Linux 5.5.
+kernel 5.5
FAST_atomic_update
FAST_cmpxchg

View File

@ -0,0 +1,26 @@
commit 6cf6a91d05d626698f158078961b3bffcb39ff8c
Author: Joseph Myers <joseph@codesourcery.com>
Date: Wed Feb 12 13:37:16 2020 +0000
Rename RWF_WRITE_LIFE_NOT_SET to RWH_WRITE_LIFE_NOT_SET following Linux 5.5.
Linux 5.5 renames RWF_WRITE_LIFE_NOT_SET to RWH_WRITE_LIFE_NOT_SET,
with the old name kept as an alias. This patch makes the
corresponding change in glibc.
Tested for x86_64.
diff --git a/sysdeps/unix/sysv/linux/bits/fcntl-linux.h b/sysdeps/unix/sysv/linux/bits/fcntl-linux.h
index 07a889d683..b06488a847 100644
--- a/sysdeps/unix/sysv/linux/bits/fcntl-linux.h
+++ b/sysdeps/unix/sysv/linux/bits/fcntl-linux.h
@@ -290,7 +290,8 @@ struct f_owner_ex
#ifdef __USE_GNU
/* Hint values for F_{GET,SET}_RW_HINT. */
-# define RWF_WRITE_LIFE_NOT_SET 0
+# define RWH_WRITE_LIFE_NOT_SET 0
+# define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET
# define RWH_WRITE_LIFE_NONE 1
# define RWH_WRITE_LIFE_SHORT 2
# define RWH_WRITE_LIFE_MEDIUM 3

View File

@ -0,0 +1,54 @@
commit e788beaf093bfafecd6b4456b984bd927c18987a
Author: Joseph Myers <joseph@codesourcery.com>
Date: Fri Apr 3 18:07:55 2020 +0000
Update syscall lists for Linux 5.6.
Linux 5.6 has new openat2 and pidfd_getfd syscalls. This patch adds
them to syscall-names.list and regenerates the arch-syscall.h files.
Tested with build-many-glibcs.py.
Modified to only update syscall-names.list for RHEL 8.3.0.
Also cleaned up typos in the comments.
diff -Nrup a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
--- a/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-06 12:27:10.519027866 -0400
+++ b/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-06 12:31:53.665812810 -0400
@@ -16,14 +16,13 @@
# License along with the GNU C Library; if not, see
# <http://www.gnu.org/licenses/>.
-# This file contains the list of system call names names. It has to
-# remain in alphabetica order. Lines which start with # are treated
-# as comments. This file can list all potential system calls. The
-# names are only used if the installed kernel headers also provide
-# them.
+# This file contains the list of system call names. It has to remain in
+# alphabetical order. Lines which start with # are treated as comments.
+# This file can list all potential system calls. The names are only
+# used if the installed kernel headers also provide them.
-# The list of system calls is current as of Linux 5.5.
-kernel 5.5
+# The list of system calls is current as of Linux 5.6.
+kernel 5.6
FAST_atomic_update
FAST_cmpxchg
@@ -293,6 +292,7 @@ open
open_by_handle_at
open_tree
openat
+openat2
osf_adjtime
osf_afs_syscall
osf_alt_plock
@@ -411,6 +411,7 @@ perf_event_open
perfctr
perfmonctl
personality
+pidfd_getfd
pidfd_open
pidfd_send_signal
pipe

View File

@ -0,0 +1,113 @@
commit 9333498794cde1d5cca518badf79533a24114b6f
Author: Joseph Myers <joseph@codesourcery.com>
Date: Wed Feb 12 23:31:56 2020 +0000
Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487).
Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero
argument (an representation where all the significand bits, including
the explicit high bit, are zero, but the exponent is not zero, which
is not a valid representation for the long double type).
Although this is not a valid long double representation, existing
practice in this area (see bug 4586, originally marked invalid but
subsequently fixed) is that we still seek to avoid invalid memory
accesses as a result, in case of programs that treat arbitrary binary
data as long double representations, although the invalid
representations of the ldbl-96 format do not need to be consistently
handled the same as any particular valid representation.
This patch makes the range reduction detect pseudo-zero and unnormal
representations that would otherwise go to __kernel_rem_pio2, and
returns a NaN for them instead of continuing with the range reduction
process. (Pseudo-zero and unnormal representations whose unbiased
exponent is less than -1 have already been safely returned from the
function before this point without going through the rest of range
reduction.) Pseudo-zero representations would previously result in
the value passed to __kernel_rem_pio2 being all-zero, which is
definitely unsafe; unnormal representations would previously result in
a value passed whose high bit is zero, which might well be unsafe
since that is not a form of input expected by __kernel_rem_pio2.
Tested for x86_64.
Revised for RHEL 8.3.0.
diff -Nrup a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c
--- a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c 2018-08-01 01:10:47.000000000 -0400
+++ b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c 2020-04-03 13:05:02.609844427 -0400
@@ -209,6 +209,18 @@ __ieee754_rem_pio2l (long double x, long
y[1] = y[0];
return 0;
}
+
+ if ((i0 & 0x80000000) == 0)
+ {
+ /* Pseudo-zero and unnormal representations are not valid
+ representations of long double. We need to avoid stack
+ corruption in __kernel_rem_pio2, which expects input in a
+ particular normal form, but those representations do not need
+ to be consistently handled like any particular floating-point
+ value. */
+ y[1] = y[0] = __builtin_nanl ("");
+ return 0;
+ }
/* Split the 64 bits of the mantissa into three 24-bit integers
stored in a double array. */
diff -Nrup a/sysdeps/ieee754/ldbl-96/Makefile b/sysdeps/ieee754/ldbl-96/Makefile
--- a/sysdeps/ieee754/ldbl-96/Makefile 2018-08-01 01:10:47.000000000 -0400
+++ b/sysdeps/ieee754/ldbl-96/Makefile 2020-04-03 13:03:20.233546734 -0400
@@ -17,5 +17,6 @@
# <http://www.gnu.org/licenses/>.
ifeq ($(subdir),math)
-tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96
+tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo
+CFLAGS-test-sinl-pseudo.c += -fstack-protector-all
endif
diff -Nrup a/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c
--- a/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c 1969-12-31 19:00:00.000000000 -0500
+++ b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c 2020-04-03 13:05:37.857952212 -0400
@@ -0,0 +1,41 @@
+/* Test sinl for pseudo-zeros and unnormals for ldbl-96 (bug 25487).
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_ldbl.h>
+#include <stdint.h>
+
+static int
+do_test (void)
+{
+ for (int i = 0; i < 64; i++)
+ {
+ uint64_t sig = i == 63 ? 0 : 1ULL << i;
+ long double ld;
+ SET_LDOUBLE_WORDS (ld, 0x4141,
+ sig >> 32, sig & 0xffffffffULL);
+ /* The requirement is that no stack overflow occurs when the
+ pseudo-zero or unnormal goes through range reduction. */
+ volatile long double ldr;
+ ldr = sinl (ld);
+ (void) ldr;
+ }
+ return 0;
+}
+
+#include <support/test-driver.c>

View File

@ -0,0 +1,21 @@
commit c10acd40262486dac597001aecc20ad9d3bd0e4a
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Feb 13 17:01:15 2020 +0100
math/test-sinl-pseudo: Use stack protector only if available
This fixes commit 9333498794cde1d5cca518bad ("Avoid ldbl-96 stack
corruption from range reduction of pseudo-zero (bug 25487).").
diff --git a/sysdeps/ieee754/ldbl-96/Makefile b/sysdeps/ieee754/ldbl-96/Makefile
index 318628aed6..6030adf7e7 100644
--- a/sysdeps/ieee754/ldbl-96/Makefile
+++ b/sysdeps/ieee754/ldbl-96/Makefile
@@ -18,5 +18,7 @@
ifeq ($(subdir),math)
tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo
+ifeq ($(have-ssp),yes)
CFLAGS-test-sinl-pseudo.c += -fstack-protector-all
endif
+endif # $(subdir) == math

View File

@ -0,0 +1,517 @@
commit eb447b7b4bd6177f876ba9420ad9e048c27bae91
Author: David Kilroy <David.Kilroy@arm.com>
Date: Wed Feb 12 14:28:15 2020 -0300
elf: Allow dlopen of filter object to work [BZ #16272]
There are two fixes that are needed to be able to dlopen filter
objects. First _dl_map_object_deps cannot assume that map will be at
the beginning of l_searchlist.r_list[], as filtees are inserted before
map. Secondly dl_open_worker needs to ensure that filtees get
relocated.
In _dl_map_object_deps:
* avoiding removing relocation dependencies of map by setting
l_reserved to 0 and otherwise processing the rest of the search
list.
* ensure that map remains at the beginning of l_initfini - the list
of things that need initialisation (and destruction). Do this by
splitting the copy up. This may not be required, but matches the
initialization order without dlopen.
Modify dl_open_worker to relocate the objects in new->l_inifini.
new->l_initfini is constructed in _dl_map_object_deps, and lists the
objects that need initialization and destruction. Originally the list
of objects in new->l_next are relocated. All of these objects should
also be included in new->l_initfini (both lists are populated with
dependencies in _dl_map_object_deps). We can't use new->l_prev to pick
up filtees, as during a recursive dlopen from an interposed malloc
call, l->prev can contain objects that are not ready for relocation.
Add tests to verify that symbols resolve to the filtee implementation
when auxiliary and filter objects are used, both as a normal link and
when dlopen'd.
Tested by running the testsuite on x86_64.
# Conflicts:
# elf/Makefile
diff --git a/elf/Makefile b/elf/Makefile
index a52d9b1f6a4364a7..b4b618ce62a9e6df 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -192,7 +192,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \
- tst-dlopenfail tst-dlopenfail-2
+ tst-dlopenfail tst-dlopenfail-2 \
+ tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -302,7 +303,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
tst-initlazyfailmod tst-finilazyfailmod \
tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
- tst-dlopenfailmod3
+ tst-dlopenfailmod3 \
+ tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee
ifeq (yes,$(have-mtls-dialect-gnu2))
tests += tst-gnu2-tls1
@@ -1626,3 +1628,15 @@ $(objpfx)tst-dlopen-nodelete-reloc-mod17.so: \
$(objpfx)tst-dlopen-nodelete-reloc-mod15.so \
$(objpfx)tst-dlopen-nodelete-reloc-mod16.so
LDFLAGS-tst-dlopen-nodelete-reloc-mod17.so = -Wl,--no-as-needed
+
+LDFLAGS-tst-filterobj-flt.so = -Wl,--filter=$(objpfx)tst-filterobj-filtee.so
+$(objpfx)tst-filterobj: $(objpfx)tst-filterobj-flt.so
+$(objpfx)tst-filterobj-dlopen: $(libdl)
+$(objpfx)tst-filterobj.out: $(objpfx)tst-filterobj-filtee.so
+$(objpfx)tst-filterobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so
+
+LDFLAGS-tst-filterobj-aux.so = -Wl,--auxiliary=$(objpfx)tst-filterobj-filtee.so
+$(objpfx)tst-auxobj: $(objpfx)tst-filterobj-aux.so
+$(objpfx)tst-auxobj-dlopen: $(libdl)
+$(objpfx)tst-auxobj.out: $(objpfx)tst-filterobj-filtee.so
+$(objpfx)tst-auxobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 9d9b1ba7f244348a..50f053a1586efdc3 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -485,14 +485,18 @@ _dl_map_object_deps (struct link_map *map,
map->l_searchlist.r_list = &l_initfini[nlist + 1];
map->l_searchlist.r_nlist = nlist;
+ unsigned int map_index = UINT_MAX;
for (nlist = 0, runp = known; runp; runp = runp->next)
{
if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
/* This can happen when we trace the loading. */
--map->l_searchlist.r_nlist;
- else
+ else {
+ if (runp->map == map)
+ map_index = nlist;
map->l_searchlist.r_list[nlist++] = runp->map;
+ }
/* Now clear all the mark bits we set in the objects on the search list
to avoid duplicates, so the next call starts fresh. */
@@ -550,13 +554,14 @@ Filters not supported with LD_TRACE_PRELINKING"));
}
/* Maybe we can remove some relocation dependencies now. */
- assert (map->l_searchlist.r_list[0] == map);
struct link_map_reldeps *l_reldeps = NULL;
if (map->l_reldeps != NULL)
{
- for (i = 1; i < nlist; ++i)
+ for (i = 0; i < nlist; ++i)
map->l_searchlist.r_list[i]->l_reserved = 1;
+ /* Avoid removing relocation dependencies of the main binary. */
+ map->l_reserved = 0;
struct link_map **list = &map->l_reldeps->list[0];
for (i = 0; i < map->l_reldeps->act; ++i)
if (list[i]->l_reserved)
@@ -581,16 +586,30 @@ Filters not supported with LD_TRACE_PRELINKING"));
}
}
- for (i = 1; i < nlist; ++i)
+ for (i = 0; i < nlist; ++i)
map->l_searchlist.r_list[i]->l_reserved = 0;
}
- /* Sort the initializer list to take dependencies into account. The binary
- itself will always be initialize last. */
- memcpy (l_initfini, map->l_searchlist.r_list,
- nlist * sizeof (struct link_map *));
- /* We can skip looking for the binary itself which is at the front of
- the search list. */
+ /* Sort the initializer list to take dependencies into account. Always
+ initialize the binary itself last. */
+ assert (map_index < nlist);
+ if (map_index > 0)
+ {
+ /* Copy the binary into position 0. */
+ l_initfini[0] = map->l_searchlist.r_list[map_index];
+
+ /* Copy the filtees. */
+ for (i = 0; i < map_index; ++i)
+ l_initfini[i+1] = map->l_searchlist.r_list[i];
+
+ /* Copy the remainder. */
+ for (i = map_index + 1; i < nlist; ++i)
+ l_initfini[i] = map->l_searchlist.r_list[i];
+ }
+ else
+ memcpy (l_initfini, map->l_searchlist.r_list,
+ nlist * sizeof (struct link_map *));
+
_dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false);
/* Terminate the list of dependencies. */
diff --git a/elf/dl-open.c b/elf/dl-open.c
index d834b89754d2b073..d31356f7e17dfb14 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -618,22 +618,25 @@ dl_open_worker (void *a)
allows IFUNC relocations to work and it also means copy
relocation of dependencies are if necessary overwritten. */
unsigned int nmaps = 0;
- struct link_map *l = new;
+ unsigned int j = 0;
+ struct link_map *l = new->l_initfini[0];
do
{
if (! l->l_real->l_relocated)
++nmaps;
- l = l->l_next;
+ l = new->l_initfini[++j];
}
while (l != NULL);
+ /* Stack allocation is limited by the number of loaded objects. */
struct link_map *maps[nmaps];
nmaps = 0;
- l = new;
+ j = 0;
+ l = new->l_initfini[0];
do
{
if (! l->l_real->l_relocated)
maps[nmaps++] = l;
- l = l->l_next;
+ l = new->l_initfini[++j];
}
while (l != NULL);
_dl_sort_maps (maps, nmaps, NULL, false);
diff --git a/elf/tst-auxobj-dlopen.c b/elf/tst-auxobj-dlopen.c
new file mode 100644
index 0000000000000000..cb54aba19470a1fe
--- /dev/null
+++ b/elf/tst-auxobj-dlopen.c
@@ -0,0 +1,47 @@
+/* Test for BZ#16272, dlopen'ing an auxiliary filter object.
+ Ensure that symbols from the resolve correctly.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+static int do_test (void)
+{
+ void *lib = xdlopen ("tst-filterobj-aux.so", RTLD_LAZY);
+ char *(*fn)(void) = xdlsym (lib, "get_text");
+ const char* text = fn ();
+
+ printf ("%s\n", text);
+
+ /* Verify the text matches what we expect from the filtee */
+ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)");
+
+ fn = xdlsym (lib, "get_text2");
+ text = fn ();
+
+ printf ("%s\n", text);
+
+ /* Verify the text matches what we expect from the auxiliary object */
+ TEST_COMPARE_STRING (text, "Hello from auxiliary filter object (PASS)");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-auxobj.c b/elf/tst-auxobj.c
new file mode 100644
index 0000000000000000..bdc7713b04b4a79b
--- /dev/null
+++ b/elf/tst-auxobj.c
@@ -0,0 +1,42 @@
+/* Test that symbols from auxiliary filter objects are resolved to the
+ filtee.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <support/check.h>
+#include "tst-filterobj-filtee.h"
+
+static int do_test (void)
+{
+ const char* text = get_text ();
+ printf ("%s\n", text);
+
+ /* Verify the text matches what we expect from the filtee */
+ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)");
+
+ text = get_text2 ();
+ printf ("%s\n", text);
+
+ /* Verify the text matches what we expect from the auxiliary object */
+ TEST_COMPARE_STRING (text, "Hello from auxiliary filter object (PASS)");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-filterobj-aux.c b/elf/tst-filterobj-aux.c
new file mode 100644
index 0000000000000000..0b732f2fb3a69a7f
--- /dev/null
+++ b/elf/tst-filterobj-aux.c
@@ -0,0 +1,33 @@
+/* Auxiliary filter object.
+ Contains symbols to be resolved in filtee, and one which doesn't.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-filterobj-filtee.h"
+
+/* We never want to see the output of the auxiliary object. */
+const char *get_text (void)
+{
+ return "Hello from auxiliary filter object (FAIL)";
+}
+
+/* The filtee doesn't implement this symbol, so this should resolve. */
+const char *get_text2 (void)
+{
+ return "Hello from auxiliary filter object (PASS)";
+}
diff --git a/elf/tst-filterobj-dlopen.c b/elf/tst-filterobj-dlopen.c
new file mode 100644
index 0000000000000000..c5b5072979802b98
--- /dev/null
+++ b/elf/tst-filterobj-dlopen.c
@@ -0,0 +1,39 @@
+/* Test for BZ#16272, dlopen'ing a filter object.
+ Ensure that symbols from the filter object resolve to the filtee.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+static int do_test (void)
+{
+ void *lib = xdlopen ("tst-filterobj-flt.so", RTLD_LAZY);
+ char *(*fn)(void) = xdlsym (lib, "get_text");
+ const char* text = fn ();
+
+ printf ("%s\n", text);
+
+ /* Verify the text matches what we expect from the filtee */
+ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-filterobj-filtee.c b/elf/tst-filterobj-filtee.c
new file mode 100644
index 0000000000000000..8fa557cbd251f53c
--- /dev/null
+++ b/elf/tst-filterobj-filtee.c
@@ -0,0 +1,27 @@
+/* Filtee for BZ#16272 test.
+ Contains desired symbol implementations.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-filterobj-filtee.h"
+
+/* This is the real implementation that wants to be called */
+const char *get_text (void)
+{
+ return "Hello from filtee (PASS)";
+}
diff --git a/elf/tst-filterobj-filtee.h b/elf/tst-filterobj-filtee.h
new file mode 100644
index 0000000000000000..46aee28178b88a77
--- /dev/null
+++ b/elf/tst-filterobj-filtee.h
@@ -0,0 +1,24 @@
+/* Filtee header for BZ#16272 test.
+ Contains prototypes for symbols implemented in the filtee.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+const char *get_text (void);
+
+/* For testing auxiliary filter object. */
+const char *get_text2 (void);
diff --git a/elf/tst-filterobj-flt.c b/elf/tst-filterobj-flt.c
new file mode 100644
index 0000000000000000..5062654be6f14a80
--- /dev/null
+++ b/elf/tst-filterobj-flt.c
@@ -0,0 +1,27 @@
+/* Filter object for BZ#16272 test.
+ Contains symbols to be resolved in filtee.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-filterobj-filtee.h"
+
+/* We never want to see the output of the filter object */
+const char *get_text (void)
+{
+ return "Hello from filter object (FAIL)";
+}
diff --git a/elf/tst-filterobj.c b/elf/tst-filterobj.c
new file mode 100644
index 0000000000000000..96bfae019ea670bc
--- /dev/null
+++ b/elf/tst-filterobj.c
@@ -0,0 +1,36 @@
+/* Test that symbols from filter objects are resolved to the filtee.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <support/check.h>
+#include "tst-filterobj-filtee.h"
+
+static int do_test (void)
+{
+ const char* text = get_text ();
+
+ printf ("%s\n", text);
+
+ /* Verify the text matches what we expect from the filtee */
+ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)");
+
+ return 0;
+}
+
+#include <support/test-driver.c>

View File

@ -0,0 +1,37 @@
commit 71bcfa62451dfaa015326d3524f2a0e2d09d80ed
Author: David Kilroy <David.Kilroy@arm.com>
Date: Wed Feb 12 14:30:31 2020 -0300
elf: avoid redundant sort in dlopen
l_initfini is already sorted by dependency in _dl_map_object_deps(),
so avoid sorting again in dl_open_worker().
Tested by running the testsuite on x86_64.
diff --git a/elf/dl-open.c b/elf/dl-open.c
index d31356f7e17dfb14..980a28c836ca9a7a 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -614,9 +614,10 @@ dl_open_worker (void *a)
if (GLRO(dl_lazy))
reloc_mode |= mode & RTLD_LAZY;
- /* Sort the objects by dependency for the relocation process. This
- allows IFUNC relocations to work and it also means copy
- relocation of dependencies are if necessary overwritten. */
+ /* Objects must be sorted by dependency for the relocation process.
+ This allows IFUNC relocations to work and it also means copy
+ relocation of dependencies are if necessary overwritten.
+ __dl_map_object_deps has already sorted l_initfini for us. */
unsigned int nmaps = 0;
unsigned int j = 0;
struct link_map *l = new->l_initfini[0];
@@ -639,7 +640,6 @@ dl_open_worker (void *a)
l = new->l_initfini[++j];
}
while (l != NULL);
- _dl_sort_maps (maps, nmaps, NULL, false);
int relocation_in_progress = 0;

View File

@ -0,0 +1,68 @@
commit 0a8ce6a0966283b17f373f430929bcadef1ae205
Author: David Kilroy <David.Kilroy@arm.com>
Date: Wed Feb 12 14:31:17 2020 -0300
elf: avoid stack allocation in dl_open_worker
As the sort was removed, there's no need to keep a separate map of
links. Instead, when relocating objects iterate over l_initfini
directly.
This allows us to remove the loop copying l_initfini elements into
map. We still need a loop to identify the first and last elements that
need relocation.
Tested by running the testsuite on x86_64.
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 980a28c836ca9a7a..46a4c1e5a3f8d2dd 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -618,25 +618,18 @@ dl_open_worker (void *a)
This allows IFUNC relocations to work and it also means copy
relocation of dependencies are if necessary overwritten.
__dl_map_object_deps has already sorted l_initfini for us. */
- unsigned int nmaps = 0;
+ unsigned int first = UINT_MAX;
+ unsigned int last = 0;
unsigned int j = 0;
struct link_map *l = new->l_initfini[0];
do
{
if (! l->l_real->l_relocated)
- ++nmaps;
- l = new->l_initfini[++j];
- }
- while (l != NULL);
- /* Stack allocation is limited by the number of loaded objects. */
- struct link_map *maps[nmaps];
- nmaps = 0;
- j = 0;
- l = new->l_initfini[0];
- do
- {
- if (! l->l_real->l_relocated)
- maps[nmaps++] = l;
+ {
+ if (first == UINT_MAX)
+ first = j;
+ last = j + 1;
+ }
l = new->l_initfini[++j];
}
while (l != NULL);
@@ -651,9 +644,12 @@ dl_open_worker (void *a)
them. However, such relocation dependencies in IFUNC resolvers
are undefined anyway, so this is not a problem. */
- for (unsigned int i = nmaps; i-- > 0; )
+ for (unsigned int i = last; i-- > first; )
{
- l = maps[i];
+ l = new->l_initfini[i];
+
+ if (l->l_real->l_relocated)
+ continue;
if (! relocation_in_progress)
{

View File

@ -0,0 +1,58 @@
commit ddc650e9b3dc916eab417ce9f79e67337b05035c
Author: Andreas Schwab <schwab@suse.de>
Date: Wed Feb 19 17:21:46 2020 +0100
Fix use-after-free in glob when expanding ~user (bug 25414)
The value of `end_name' points into the value of `dirname', thus don't
deallocate the latter before the last use of the former.
diff --git a/posix/glob.c b/posix/glob.c
index cba9cd1819..4580cefb9f 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -827,31 +827,32 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
size_t home_len = strlen (p->pw_dir);
size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
- char *d;
+ char *d, *newp;
+ bool use_alloca = glob_use_alloca (alloca_used,
+ home_len + rest_len + 1);
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
- malloc_dirname = 0;
-
- if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
- dirname = alloca_account (home_len + rest_len + 1,
- alloca_used);
+ if (use_alloca)
+ newp = alloca_account (home_len + rest_len + 1, alloca_used);
else
{
- dirname = malloc (home_len + rest_len + 1);
- if (dirname == NULL)
+ newp = malloc (home_len + rest_len + 1);
+ if (newp == NULL)
{
scratch_buffer_free (&pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
- malloc_dirname = 1;
}
- d = mempcpy (dirname, p->pw_dir, home_len);
+ d = mempcpy (newp, p->pw_dir, home_len);
if (end_name != NULL)
d = mempcpy (d, end_name, rest_len);
*d = '\0';
+ if (__glibc_unlikely (malloc_dirname))
+ free (dirname);
+ dirname = newp;
+ malloc_dirname = !use_alloca;
+
dirlen = home_len + rest_len;
dirname_modified = 1;
}

View File

@ -0,0 +1,59 @@
commit d93769405996dfc11d216ddbe415946617b5a494
Author: Andreas Schwab <schwab@suse.de>
Date: Mon Jan 20 17:01:50 2020 +0100
Fix array overflow in backtrace on PowerPC (bug 25423)
When unwinding through a signal frame the backtrace function on PowerPC
didn't check array bounds when storing the frame address. Fixes commit
d400dcac5e ("PowerPC: fix backtrace to handle signal trampolines").
diff --git a/debug/tst-backtrace5.c b/debug/tst-backtrace5.c
index e7ce410845..b2f46160e7 100644
--- a/debug/tst-backtrace5.c
+++ b/debug/tst-backtrace5.c
@@ -89,6 +89,18 @@ handle_signal (int signum)
}
/* Symbol names are not available for static functions, so we do not
check do_test. */
+
+ /* Check that backtrace does not return more than what fits in the array
+ (bug 25423). */
+ for (int j = 0; j < NUM_FUNCTIONS; j++)
+ {
+ n = backtrace (addresses, j);
+ if (n > j)
+ {
+ FAIL ();
+ return;
+ }
+ }
}
NO_INLINE int
diff --git a/sysdeps/powerpc/powerpc32/backtrace.c b/sysdeps/powerpc/powerpc32/backtrace.c
index 7c2d4726f8..d1456c8ae4 100644
--- a/sysdeps/powerpc/powerpc32/backtrace.c
+++ b/sysdeps/powerpc/powerpc32/backtrace.c
@@ -114,6 +114,8 @@ __backtrace (void **array, int size)
}
if (gregset)
{
+ if (count + 1 == size)
+ break;
array[++count] = (void*)((*gregset)[PT_NIP]);
current = (void*)((*gregset)[PT_R1]);
}
diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c
index 65c260ab76..8a53a1088f 100644
--- a/sysdeps/powerpc/powerpc64/backtrace.c
+++ b/sysdeps/powerpc/powerpc64/backtrace.c
@@ -87,6 +87,8 @@ __backtrace (void **array, int size)
if (is_sigtramp_address (current->return_address))
{
struct signal_frame_64 *sigframe = (struct signal_frame_64*) current;
+ if (count + 1 == size)
+ break;
array[++count] = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_NIP];
current = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_R1];
}

View File

@ -0,0 +1,136 @@
commit 284f42bc778e487dfd5dff5c01959f93b9e0c4f5
Author: Wilco Dijkstra <wdijkstr@arm.com>
Date: Fri Aug 3 17:24:12 2018 +0100
Simplify and speedup strstr/strcasestr first match
Looking at the benchtests, both strstr and strcasestr spend a lot of time
in a slow initialization loop handling one character per iteration.
This can be simplified and use the much faster strlen/strnlen/strchr/memcmp.
Read ahead a few cachelines to reduce the number of strnlen calls, which
improves performance by ~3-4%. This patch improves the time taken for the
full strstr benchtest by >40%.
* string/strcasestr.c (STRCASESTR): Simplify and speedup first match.
* string/strstr.c (AVAILABLE): Likewise.
diff --git a/string/strcasestr.c b/string/strcasestr.c
index 421764bd1b0ff22e..8aa76037dcc052f3 100644
--- a/string/strcasestr.c
+++ b/string/strcasestr.c
@@ -59,31 +59,22 @@
case-insensitive comparison. This function gives unspecified
results in multibyte locales. */
char *
-STRCASESTR (const char *haystack_start, const char *needle_start)
+STRCASESTR (const char *haystack, const char *needle)
{
- const char *haystack = haystack_start;
- const char *needle = needle_start;
size_t needle_len; /* Length of NEEDLE. */
size_t haystack_len; /* Known minimum length of HAYSTACK. */
- bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */
-
- /* Determine length of NEEDLE, and in the process, make sure
- HAYSTACK is at least as long (no point processing all of a long
- NEEDLE if HAYSTACK is too short). */
- while (*haystack && *needle)
- {
- ok &= (TOLOWER ((unsigned char) *haystack)
- == TOLOWER ((unsigned char) *needle));
- haystack++;
- needle++;
- }
- if (*needle)
+
+ /* Handle empty NEEDLE special case. */
+ if (needle[0] == '\0')
+ return (char *) haystack;
+
+ /* Ensure HAYSTACK length is at least as long as NEEDLE length.
+ Since a match may occur early on in a huge HAYSTACK, use strnlen
+ and read ahead a few cachelines for improved performance. */
+ needle_len = strlen (needle);
+ haystack_len = __strnlen (haystack, needle_len + 256);
+ if (haystack_len < needle_len)
return NULL;
- if (ok)
- return (char *) haystack_start;
- needle_len = needle - needle_start;
- haystack = haystack_start + 1;
- haystack_len = needle_len - 1;
/* Perform the search. Abstract memory is considered to be an array
of 'unsigned char' values, not an array of 'char' values. See
@@ -91,10 +82,10 @@ STRCASESTR (const char *haystack_start, const char *needle_start)
if (needle_len < LONG_NEEDLE_THRESHOLD)
return two_way_short_needle ((const unsigned char *) haystack,
haystack_len,
- (const unsigned char *) needle_start,
+ (const unsigned char *) needle,
needle_len);
return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
- (const unsigned char *) needle_start,
+ (const unsigned char *) needle,
needle_len);
}
diff --git a/string/strstr.c b/string/strstr.c
index 79ebcc75329d0b17..f74d7189ed1319f6 100644
--- a/string/strstr.c
+++ b/string/strstr.c
@@ -51,33 +51,32 @@
if NEEDLE is empty, otherwise NULL if NEEDLE is not found in
HAYSTACK. */
char *
-STRSTR (const char *haystack_start, const char *needle_start)
+STRSTR (const char *haystack, const char *needle)
{
- const char *haystack = haystack_start;
- const char *needle = needle_start;
size_t needle_len; /* Length of NEEDLE. */
size_t haystack_len; /* Known minimum length of HAYSTACK. */
- bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */
-
- /* Determine length of NEEDLE, and in the process, make sure
- HAYSTACK is at least as long (no point processing all of a long
- NEEDLE if HAYSTACK is too short). */
- while (*haystack && *needle)
- ok &= *haystack++ == *needle++;
- if (*needle)
+
+ /* Handle empty NEEDLE special case. */
+ if (needle[0] == '\0')
+ return (char *) haystack;
+
+ /* Skip until we find the first matching char from NEEDLE. */
+ haystack = strchr (haystack, needle[0]);
+ if (haystack == NULL || needle[1] == '\0')
+ return (char *) haystack;
+
+ /* Ensure HAYSTACK length is at least as long as NEEDLE length.
+ Since a match may occur early on in a huge HAYSTACK, use strnlen
+ and read ahead a few cachelines for improved performance. */
+ needle_len = strlen (needle);
+ haystack_len = __strnlen (haystack, needle_len + 256);
+ if (haystack_len < needle_len)
return NULL;
- if (ok)
- return (char *) haystack_start;
-
- /* Reduce the size of haystack using strchr, since it has a smaller
- linear coefficient than the Two-Way algorithm. */
- needle_len = needle - needle_start;
- haystack = strchr (haystack_start + 1, *needle_start);
- if (!haystack || __builtin_expect (needle_len == 1, 0))
+
+ /* Check whether we have a match. This improves performance since we avoid
+ the initialization overhead of the two-way algorithm. */
+ if (memcmp (haystack, needle, needle_len) == 0)
return (char *) haystack;
- needle -= needle_len;
- haystack_len = (haystack > haystack_start + needle_len ? 1
- : needle_len + haystack_start - haystack);
/* Perform the search. Abstract memory is considered to be an array
of 'unsigned char' values, not an array of 'char' values. See

View File

@ -0,0 +1,260 @@
commit 5e0a7ecb6629461b28adc1a5aabcc0ede122f201
Author: Wilco Dijkstra <wdijkstr@arm.com>
Date: Wed Jun 12 11:38:52 2019 +0100
Improve performance of strstr
This patch significantly improves performance of strstr using a novel
modified Horspool algorithm. Needles up to size 256 use a bad-character
table indexed by hashed pairs of characters to quickly skip past mismatches.
Long needles use a self-adapting filtering step to avoid comparing the whole
needle repeatedly.
By limiting the needle length to 256, the shift table only requires 8 bits
per entry, lowering preprocessing overhead and minimizing cache effects.
This limit also implies worst-case performance is linear.
Small needles up to size 3 use a dedicated linear search. Very long needles
use the Two-Way algorithm.
The performance gain using the improved bench-strstr on Cortex-A72 is 5.8
times basic_strstr and 3.7 times twoway_strstr.
Tested against GLIBC testsuite, randomized tests and the GNULIB strstr test
(https://git.savannah.gnu.org/cgit/gnulib.git/tree/tests/test-strstr.c).
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
* string/str-two-way.h (two_way_short_needle): Add inline to avoid
warning.
(two_way_long_needle): Block inlining.
* string/strstr.c (strstr2): Add new function.
(strstr3): Likewise.
(STRSTR): Completely rewrite strstr to improve performance.
diff --git a/string/str-two-way.h b/string/str-two-way.h
index 523d946c59412e1f..358959bef0fd6f74 100644
--- a/string/str-two-way.h
+++ b/string/str-two-way.h
@@ -221,7 +221,7 @@ critical_factorization (const unsigned char *needle, size_t needle_len,
most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.
If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */
-static RETURN_TYPE
+static inline RETURN_TYPE
two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
const unsigned char *needle, size_t needle_len)
{
@@ -382,8 +382,11 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible.
If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and
- sublinear performance is not possible. */
-static RETURN_TYPE
+ sublinear performance is not possible.
+
+ Since this function is large and complex, block inlining to avoid
+ slowing down the common case of small needles. */
+__attribute__((noinline)) static RETURN_TYPE
two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
const unsigned char *needle, size_t needle_len)
{
diff --git a/string/strstr.c b/string/strstr.c
index f74d7189ed1319f6..7ffb18ab4285b060 100644
--- a/string/strstr.c
+++ b/string/strstr.c
@@ -16,29 +16,17 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-/* This particular implementation was written by Eric Blake, 2008. */
-
#ifndef _LIBC
# include <config.h>
#endif
-/* Specification of strstr. */
#include <string.h>
-#include <stdbool.h>
-
-#ifndef _LIBC
-# define __builtin_expect(expr, val) (expr)
-#endif
-
#define RETURN_TYPE char *
#define AVAILABLE(h, h_l, j, n_l) \
(((j) + (n_l) <= (h_l)) \
|| ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \
(j) + (n_l) <= (h_l)))
-#define CHECK_EOL (1)
-#define RET0_IF_0(a) if (!a) goto ret0
-#define FASTSEARCH(S,C,N) (void*) strchr ((void*)(S), (C))
#include "str-two-way.h"
#undef strstr
@@ -47,47 +35,128 @@
#define STRSTR strstr
#endif
-/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK
- if NEEDLE is empty, otherwise NULL if NEEDLE is not found in
- HAYSTACK. */
-char *
-STRSTR (const char *haystack, const char *needle)
+static inline char *
+strstr2 (const unsigned char *hs, const unsigned char *ne)
{
- size_t needle_len; /* Length of NEEDLE. */
- size_t haystack_len; /* Known minimum length of HAYSTACK. */
-
- /* Handle empty NEEDLE special case. */
- if (needle[0] == '\0')
- return (char *) haystack;
+ uint32_t h1 = (ne[0] << 16) | ne[1];
+ uint32_t h2 = 0;
+ for (int c = hs[0]; h1 != h2 && c != 0; c = *++hs)
+ h2 = (h2 << 16) | c;
+ return h1 == h2 ? (char *)hs - 2 : NULL;
+}
- /* Skip until we find the first matching char from NEEDLE. */
- haystack = strchr (haystack, needle[0]);
- if (haystack == NULL || needle[1] == '\0')
- return (char *) haystack;
+static inline char *
+strstr3 (const unsigned char *hs, const unsigned char *ne)
+{
+ uint32_t h1 = ((uint32_t)ne[0] << 24) | (ne[1] << 16) | (ne[2] << 8);
+ uint32_t h2 = 0;
+ for (int c = hs[0]; h1 != h2 && c != 0; c = *++hs)
+ h2 = (h2 | c) << 8;
+ return h1 == h2 ? (char *)hs - 3 : NULL;
+}
- /* Ensure HAYSTACK length is at least as long as NEEDLE length.
- Since a match may occur early on in a huge HAYSTACK, use strnlen
+/* Hash character pairs so a small shift table can be used. All bits of
+ p[0] are included, but not all bits from p[-1]. So if two equal hashes
+ match on p[-1], p[0] matches too. Hash collisions are harmless and result
+ in smaller shifts. */
+#define hash2(p) (((size_t)(p)[0] - ((size_t)(p)[-1] << 3)) % sizeof (shift))
+
+/* Fast strstr algorithm with guaranteed linear-time performance.
+ Small needles up to size 3 use a dedicated linear search. Longer needles
+ up to size 256 use a novel modified Horspool algorithm. It hashes pairs
+ of characters to quickly skip past mismatches. The main search loop only
+ exits if the last 2 characters match, avoiding unnecessary calls to memcmp
+ and allowing for a larger skip if there is no match. A self-adapting
+ filtering check is used to quickly detect mismatches in long needles.
+ By limiting the needle length to 256, the shift table can be reduced to 8
+ bits per entry, lowering preprocessing overhead and minimizing cache effects.
+ The limit also implies worst-case performance is linear.
+ Needles larger than 256 characters use the linear-time Two-Way algorithm. */
+char *
+STRSTR (const char *haystack, const char *needle)
+{
+ const unsigned char *hs = (const unsigned char *) haystack;
+ const unsigned char *ne = (const unsigned char *) needle;
+
+ /* Handle short needle special cases first. */
+ if (ne[0] == '\0')
+ return (char *)hs;
+ hs = (const unsigned char *)strchr ((const char*)hs, ne[0]);
+ if (hs == NULL || ne[1] == '\0')
+ return (char*)hs;
+ if (ne[2] == '\0')
+ return strstr2 (hs, ne);
+ if (ne[3] == '\0')
+ return strstr3 (hs, ne);
+
+ /* Ensure haystack length is at least as long as needle length.
+ Since a match may occur early on in a huge haystack, use strnlen
and read ahead a few cachelines for improved performance. */
- needle_len = strlen (needle);
- haystack_len = __strnlen (haystack, needle_len + 256);
- if (haystack_len < needle_len)
+ size_t ne_len = strlen ((const char*)ne);
+ size_t hs_len = __strnlen ((const char*)hs, ne_len | 512);
+ if (hs_len < ne_len)
return NULL;
- /* Check whether we have a match. This improves performance since we avoid
- the initialization overhead of the two-way algorithm. */
- if (memcmp (haystack, needle, needle_len) == 0)
- return (char *) haystack;
-
- /* Perform the search. Abstract memory is considered to be an array
- of 'unsigned char' values, not an array of 'char' values. See
- ISO C 99 section 6.2.6.1. */
- if (needle_len < LONG_NEEDLE_THRESHOLD)
- return two_way_short_needle ((const unsigned char *) haystack,
- haystack_len,
- (const unsigned char *) needle, needle_len);
- return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
- (const unsigned char *) needle, needle_len);
+ /* Check whether we have a match. This improves performance since we
+ avoid initialization overheads. */
+ if (memcmp (hs, ne, ne_len) == 0)
+ return (char *) hs;
+
+ /* Use Two-Way algorithm for very long needles. */
+ if (__glibc_unlikely (ne_len > 256))
+ return two_way_long_needle (hs, hs_len, ne, ne_len);
+
+ const unsigned char *end = hs + hs_len - ne_len;
+ uint8_t shift[256];
+ size_t tmp, shift1;
+ size_t m1 = ne_len - 1;
+ size_t offset = 0;
+
+ /* Initialize bad character shift hash table. */
+ memset (shift, 0, sizeof (shift));
+ for (int i = 1; i < m1; i++)
+ shift[hash2 (ne + i)] = i;
+ /* Shift1 is the amount we can skip after matching the hash of the
+ needle end but not the full needle. */
+ shift1 = m1 - shift[hash2 (ne + m1)];
+ shift[hash2 (ne + m1)] = m1;
+
+ while (1)
+ {
+ if (__glibc_unlikely (hs > end))
+ {
+ end += __strnlen ((const char*)end + m1 + 1, 2048);
+ if (hs > end)
+ return NULL;
+ }
+
+ /* Skip past character pairs not in the needle. */
+ do
+ {
+ hs += m1;
+ tmp = shift[hash2 (hs)];
+ }
+ while (tmp == 0 && hs <= end);
+
+ /* If the match is not at the end of the needle, shift to the end
+ and continue until we match the hash of the needle end. */
+ hs -= tmp;
+ if (tmp < m1)
+ continue;
+
+ /* Hash of the last 2 characters matches. If the needle is long,
+ try to quickly filter out mismatches. */
+ if (m1 < 15 || memcmp (hs + offset, ne + offset, 8) == 0)
+ {
+ if (memcmp (hs, ne, m1) == 0)
+ return (void *) hs;
+
+ /* Adjust filter offset when it doesn't find the mismatch. */
+ offset = (offset >= 8 ? offset : m1) - 8;
+ }
+
+ /* Skip based on matching the hash of the needle end. */
+ hs += shift1;
+ }
}
libc_hidden_builtin_def (strstr)
-
-#undef LONG_NEEDLE_THRESHOLD

View File

@ -0,0 +1,194 @@
commit 790b8dda4455865cb8c3a47801f4304c1a43baf6
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue May 19 14:09:38 2020 +0200
nss_compat: internal_end*ent may clobber errno, hiding ERANGE [BZ #25976]
During cleanup, before returning from get*_r functions, the end*ent
calls must not change errno. Otherwise, an ERANGE error from the
underlying implementation can be hidden, causing unexpected lookup
failures. This commit introduces an internal_end*ent_noerror
function which saves and restore errno, and marks the original
internal_end*ent function as warn_unused_result, so that it is used
only in contexts were errors from it can be handled explicitly.
Reviewed-by: DJ Delorie <dj@redhat.com>
diff --git a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c
index 012929eae7048702..fca9f4860f72e3d2 100644
--- a/nss/nss_compat/compat-grp.c
+++ b/nss/nss_compat/compat-grp.c
@@ -142,7 +142,7 @@ _nss_compat_setgrent (int stayopen)
}
-static enum nss_status
+static enum nss_status __attribute_warn_unused_result__
internal_endgrent (ent_t *ent)
{
if (ent->stream != NULL)
@@ -163,6 +163,15 @@ internal_endgrent (ent_t *ent)
return NSS_STATUS_SUCCESS;
}
+/* Like internal_endgrent, but preserve errno in all cases. */
+static void
+internal_endgrent_noerror (ent_t *ent)
+{
+ int saved_errno = errno;
+ enum nss_status unused __attribute__ ((unused)) = internal_endgrent (ent);
+ __set_errno (saved_errno);
+}
+
enum nss_status
_nss_compat_endgrent (void)
{
@@ -483,7 +492,7 @@ _nss_compat_getgrnam_r (const char *name, struct group *grp,
if (result == NSS_STATUS_SUCCESS)
result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop);
- internal_endgrent (&ent);
+ internal_endgrent_noerror (&ent);
return result;
}
@@ -612,7 +621,7 @@ _nss_compat_getgrgid_r (gid_t gid, struct group *grp,
if (result == NSS_STATUS_SUCCESS)
result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop);
- internal_endgrent (&ent);
+ internal_endgrent_noerror (&ent);
return result;
}
diff --git a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c
index 5beaa6b88b7e1764..d7a89ea8e7718ab0 100644
--- a/nss/nss_compat/compat-initgroups.c
+++ b/nss/nss_compat/compat-initgroups.c
@@ -133,7 +133,7 @@ internal_setgrent (ent_t *ent)
}
-static enum nss_status
+static enum nss_status __attribute_warn_unused_result__
internal_endgrent (ent_t *ent)
{
if (ent->stream != NULL)
@@ -157,6 +157,15 @@ internal_endgrent (ent_t *ent)
return NSS_STATUS_SUCCESS;
}
+/* Like internal_endgrent, but preserve errno in all cases. */
+static void
+internal_endgrent_noerror (ent_t *ent)
+{
+ int saved_errno = errno;
+ enum nss_status unused __attribute__ ((unused)) = internal_endgrent (ent);
+ __set_errno (saved_errno);
+}
+
/* Add new group record. */
static void
add_group (long int *start, long int *size, gid_t **groupsp, long int limit,
@@ -501,7 +510,7 @@ _nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start,
done:
scratch_buffer_free (&tmpbuf);
- internal_endgrent (&intern);
+ internal_endgrent_noerror (&intern);
return status;
}
diff --git a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c
index a903452cdf96de74..8832fb7518d8bbff 100644
--- a/nss/nss_compat/compat-pwd.c
+++ b/nss/nss_compat/compat-pwd.c
@@ -259,7 +259,7 @@ _nss_compat_setpwent (int stayopen)
}
-static enum nss_status
+static enum nss_status __attribute_warn_unused_result__
internal_endpwent (ent_t *ent)
{
if (ent->stream != NULL)
@@ -287,6 +287,15 @@ internal_endpwent (ent_t *ent)
return NSS_STATUS_SUCCESS;
}
+/* Like internal_endpwent, but preserve errno in all cases. */
+static void
+internal_endpwent_noerror (ent_t *ent)
+{
+ int saved_errno = errno;
+ enum nss_status unused __attribute__ ((unused)) = internal_endpwent (ent);
+ __set_errno (saved_errno);
+}
+
enum nss_status
_nss_compat_endpwent (void)
{
@@ -822,7 +831,7 @@ _nss_compat_getpwnam_r (const char *name, struct passwd *pwd,
if (result == NSS_STATUS_SUCCESS)
result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop);
- internal_endpwent (&ent);
+ internal_endpwent_noerror (&ent);
return result;
}
@@ -1061,7 +1070,7 @@ _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd,
if (result == NSS_STATUS_SUCCESS)
result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop);
- internal_endpwent (&ent);
+ internal_endpwent_noerror (&ent);
return result;
}
diff --git a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c
index eb96ca09172d5743..684a06007ab84ac9 100644
--- a/nss/nss_compat/compat-spwd.c
+++ b/nss/nss_compat/compat-spwd.c
@@ -215,7 +215,7 @@ _nss_compat_setspent (int stayopen)
}
-static enum nss_status
+static enum nss_status __attribute_warn_unused_result__
internal_endspent (ent_t *ent)
{
if (ent->stream != NULL)
@@ -244,6 +244,15 @@ internal_endspent (ent_t *ent)
return NSS_STATUS_SUCCESS;
}
+/* Like internal_endspent, but preserve errno in all cases. */
+static void
+internal_endspent_noerror (ent_t *ent)
+{
+ int saved_errno = errno;
+ enum nss_status unused __attribute__ ((unused)) = internal_endspent (ent);
+ __set_errno (saved_errno);
+}
+
enum nss_status
_nss_compat_endspent (void)
{
@@ -261,7 +270,6 @@ _nss_compat_endspent (void)
return result;
}
-
static enum nss_status
getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent,
char *group, char *buffer, size_t buflen,
@@ -786,7 +794,7 @@ _nss_compat_getspnam_r (const char *name, struct spwd *pwd,
if (result == NSS_STATUS_SUCCESS)
result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop);
- internal_endspent (&ent);
+ internal_endspent_noerror (&ent);
return result;
}

View File

@ -1,6 +1,6 @@
%define glibcsrcdir glibc-2.28
%define glibcversion 2.28
%define glibcrelease 101%{?dist}
%define glibcrelease 127%{?dist}
# Pre-release tarballs are pulled in from git using a command that is
# effectively:
#
@ -396,6 +396,96 @@ Patch262: glibc-rh1410154-13.patch
Patch263: glibc-rh1410154-14.patch
Patch264: glibc-rh1410154-15.patch
Patch265: glibc-rh1410154-16.patch
Patch266: glibc-rh1810142-1.patch
Patch267: glibc-rh1810142-2.patch
Patch268: glibc-rh1810142-3.patch
Patch269: glibc-rh1810142-4.patch
Patch270: glibc-rh1810142-5.patch
Patch271: glibc-rh1810142-6.patch
Patch272: glibc-rh1743445-1.patch
Patch273: glibc-rh1743445-2.patch
Patch274: glibc-rh1780204-01.patch
Patch275: glibc-rh1780204-02.patch
Patch276: glibc-rh1780204-03.patch
Patch277: glibc-rh1780204-04.patch
Patch278: glibc-rh1780204-05.patch
Patch279: glibc-rh1780204-06.patch
Patch280: glibc-rh1780204-07.patch
Patch281: glibc-rh1780204-08.patch
Patch282: glibc-rh1780204-09.patch
Patch283: glibc-rh1780204-10.patch
Patch284: glibc-rh1780204-11.patch
Patch285: glibc-rh1780204-12.patch
Patch286: glibc-rh1780204-13.patch
Patch287: glibc-rh1780204-14.patch
Patch288: glibc-rh1780204-15.patch
Patch289: glibc-rh1780204-16.patch
Patch290: glibc-rh1780204-17.patch
Patch291: glibc-rh1780204-18.patch
Patch292: glibc-rh1780204-19.patch
Patch293: glibc-rh1780204-20.patch
Patch294: glibc-rh1780204-21.patch
Patch295: glibc-rh1780204-22.patch
Patch296: glibc-rh1780204-23.patch
Patch297: glibc-rh1780204-24.patch
Patch298: glibc-rh1780204-25.patch
Patch299: glibc-rh1780204-26.patch
Patch300: glibc-rh1780204-27.patch
Patch301: glibc-rh1780204-28.patch
Patch302: glibc-rh1784519.patch
Patch303: glibc-rh1775819.patch
Patch304: glibc-rh1774114.patch
Patch305: glibc-rh1812756-1.patch
Patch306: glibc-rh1812756-2.patch
Patch307: glibc-rh1812756-3.patch
Patch308: glibc-rh1757354.patch
Patch309: glibc-rh1784520.patch
Patch310: glibc-rh1784525.patch
Patch311: glibc-rh1810146.patch
Patch312: glibc-rh1810223-1.patch
Patch313: glibc-rh1810223-2.patch
Patch314: glibc-rh1811796-1.patch
Patch315: glibc-rh1811796-2.patch
Patch316: glibc-rh1813398.patch
Patch317: glibc-rh1813399.patch
Patch318: glibc-rh1810224-1.patch
Patch319: glibc-rh1810224-2.patch
Patch320: glibc-rh1810224-3.patch
Patch321: glibc-rh1810224-4.patch
Patch322: glibc-rh1783303-1.patch
Patch323: glibc-rh1783303-2.patch
Patch324: glibc-rh1783303-3.patch
Patch325: glibc-rh1783303-4.patch
Patch326: glibc-rh1783303-5.patch
Patch327: glibc-rh1783303-6.patch
Patch328: glibc-rh1783303-7.patch
Patch329: glibc-rh1783303-8.patch
Patch330: glibc-rh1783303-9.patch
Patch331: glibc-rh1783303-10.patch
Patch332: glibc-rh1783303-11.patch
Patch333: glibc-rh1783303-12.patch
Patch334: glibc-rh1783303-13.patch
Patch335: glibc-rh1783303-14.patch
Patch336: glibc-rh1783303-15.patch
Patch337: glibc-rh1783303-16.patch
Patch338: glibc-rh1783303-17.patch
Patch339: glibc-rh1783303-18.patch
Patch340: glibc-rh1642150-1.patch
Patch341: glibc-rh1642150-2.patch
Patch342: glibc-rh1642150-3.patch
Patch343: glibc-rh1774115.patch
Patch344: glibc-rh1780204-29.patch
Patch345: glibc-rh1748197-1.patch
Patch346: glibc-rh1748197-2.patch
Patch347: glibc-rh1748197-3.patch
Patch348: glibc-rh1748197-4.patch
Patch349: glibc-rh1748197-5.patch
Patch350: glibc-rh1748197-6.patch
Patch351: glibc-rh1748197-7.patch
Patch352: glibc-rh1642150-4.patch
Patch353: glibc-rh1836867.patch
Patch354: glibc-rh1821531-1.patch
Patch355: glibc-rh1821531-2.patch
##############################################################################
# Continued list of core "glibc" package information:
@ -412,6 +502,13 @@ Provides: bundled(gnulib)
Requires(pre): basesystem
%ifarch %{ix86}
# Automatically install the 32-bit variant if the 64-bit variant has
# been installed. This covers the case when glibc.i686 is installed
# after nss_db.x86_64. (See below for the other ordering.)
Recommends: (nss_db(x86-32) if nss_db(x86-64))
%endif
# This is for building auxiliary programs like memusage, nscd
# For initial glibc bootstraps it can be commented out
%if %{without bootstrap}
@ -803,6 +900,12 @@ performance with LDAP, and may help with DNS as well.
%package -n nss_db
Summary: Name Service Switch (NSS) module using hash-indexed files
Requires: %{name}%{_isa} = %{version}-%{release}
%ifarch x86_64
# Automatically install the 32-bit variant if the 64-bit variant has
# been installed. This covers the case when glibc.i686 is installed
# before nss_db.x86_64. (See above for the other ordering.)
Recommends: (nss_db(x86-32) if glibc(x86-32))
%endif
%description -n nss_db
The nss_db Name Service Switch module uses hash-indexed files in /var/db
@ -1273,8 +1376,7 @@ pushd %{glibc_sysroot}%{_prefix}/lib/locale
rm -f locale-archive
# Intentionally we do not pass --alias-file=, aliases will be added
# by build-locale-archive.
$olddir/build-%{target}/elf/ld.so \
--library-path $olddir/build-%{target}/ \
$olddir/build-%{target}/testrun.sh \
$olddir/build-%{target}/locale/localedef \
--prefix %{glibc_sysroot} --add-to-archive \
eo *_*
@ -2282,6 +2384,86 @@ fi
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
%changelog
* Tue Jun 09 2020 Carlos O'Donell <calros@redhat.com> - 2.28-127
- Improve performance of library strstr() function (#1821531)
* Wed May 27 2020 Florian Weimer <fweimer@redhat.com> - 2.28-126
- Do not clobber errno in nss_compat (#1836867)
* Thu May 14 2020 Carlos O'Donell <carlos@redhat.com> - 2.28-125
- Support building rpm under newer versions of Coverity Scan (#1835999)
* Mon May 11 2020 Florian Weimer <fweimer@redhat.com> - 2.28-124
- Enhance memory protection key support on ppc64le (#1642150)
* Thu Apr 23 2020 Florian Weimer <fweimer@redhat.com> - 2.28-123
- Reduce IFUNC resolver usage in libpthread and librt (#1748197)
* Thu Apr 9 2020 DJ Delorie <dj@redhat.com> - 2.28-122
- Math library optimizations for IBM Z (#1780204)
- Additional patch for s_nearbyint.c
* Wed Apr 8 2020 Florian Weimer <fweimer@redhat.com> - 2.28-121
- elf: Assign TLS modid later during dlopen (#1774115)
* Wed Apr 8 2020 Florian Weimer <fweimer@redhat.com> - 2.28-120
- x86-64: Automatically install nss_db.i686 for 32-bit environments (#1807824)
* Tue Apr 7 2020 Florian Weimer <fweimer@redhat.com> - 2.28-119
- ppc64le: Enable protection key support (#1642150)
* Tue Apr 7 2020 Florian Weimer <fweimer@redhat.com> - 2.28-118
- ppc64le: floating-point status and exception optimizations (#1783303)
* Fri Apr 3 2020 Patsy Griffin <patsy@redhat.com> - 2.28-117
- Update to Linux 5.6 syscall-names.list. (#1810224)
* Fri Apr 3 2020 Patsy Griffin <patsy@redhat.com> - 2.28-116
- CVE-2020-1751: Fix an array overflow in backtrace on PowerPC. (#1813399)
* Fri Apr 3 2020 Patsy Griffin <patsy@redhat.com> - 2.28-115
- CVE:2020-1752: Fix a use after free in glob when expanding ~user. (#1813398)
* Fri Apr 3 2020 Patsy Griffin <patsy@redhat.com> - 2.28-114
- CVE-2020-10029: Prevent stack corruption from crafted input in cosl, sinl,
sincosl, and tanl function. (#1811796)
* Thu Apr 2 2020 Carlos O'Donell <carlos@redhat.com> - 2.28-113
- Improve elf/ and nptl/ testsuites (#1810223)
* Thu Apr 2 2020 Carlos O'Donell <carlos@redhat.com> - 2.28-112
- Fix resource leak in getaddrinfo (#1810146)
* Thu Apr 2 2020 Carlos O'Donell <carlos@redhat.com> - 2.28-111
- Protect locale archive against corruption (#1784525)
* Thu Apr 2 2020 Carlos O'Donell <carlos@redhat.com> - 2.28-110
- Properly handle signed vs. unsigned values in mallopt (#1784520)
* Thu Apr 2 2020 Carlos O'Donell <carlos@redhat.com> - 2.28-109
- Update and harmonize locale names with CLDR (#1757354)
* Thu Apr 2 2020 Carlos O'Donell <carlos@redhat.com> - 2.28-108
- Fix filter and auxiliary filter implementation (#1812756)
* Thu Apr 2 2020 Carlos O'Donell <carlos@redhat.com> - 2.28-107
- Handle .dynstr located in separate segment (#1774114)
* Fri Mar 27 2020 Patsy Griffin <patsy@redhat.com> - 2.28-106
- Disable vtable validation for pre-2.1 interposed handles (#1775819)
* Fri Mar 27 2020 Patsy Griffin <patsy@redhat.com> - 2.28-105
- Define __CORRECT_ISO_CPP_STRING_H_PROTO for Clang. (#1784519)
* Wed Mar 25 2020 DJ Delorie <dj@redhat.com> - 2.28-104
- Math library optimizations for IBM Z (#1780204)
* Wed Mar 25 2020 DJ Delorie <dj@redhat.com> - 2.28-103
- Filter "ignore" autofs mount entries in getmntent (#1743445)
* Wed Mar 25 2020 DJ Delorie <dj@redhat.com> - 2.28-102
- Fix /etc/resolv.conf reloading defects (#1810142)
* Thu Jan 16 2020 Florian Weimer <fweimer@redhat.com> - 2.28-101
- ld.so: Reset GL (dl_initfirst) pointer on dlopen failure (#1410154)