On Fri, 1 Nov 2019, Alistair Francis wrote:
> The nptl/check-abi-libpthread test is failing on a large number of
> archs. This is what seems to be failing, although I can't figure out
> why:
Because you're removing nanosleep from pthread-compat-wrappers.
If you want to remove a symbol from libpthread that is duplicated in libc,
you need to make sure that, for *every* glibc configuration[*], the symbol
versions of that symbol in libpthread are a subset of the symbol versions
of that symbol in libc. If that is the case, you can remove the symbol
from libpthread, updating all the ABI test baselines at the same time. See
many patches of Florian's for examples of moving a symbol from libpthread
to libc. If some symbol version isn't already in libc, it needs to be
added there (see the move of clock_*, for example).
I think such changes to remove duplicate function definitions from
libpthread are to be encouraged, now that it's possible to move a
versioned symbol (from another library to libc) that way. But they should
*not* be mixed in with other changes to how the function is implemented,
and you do need to check that all required symbol versions are already in
libc as described above. If moving two symbols at once (as in this patch
which affects both nanosleep and __nanosleep) you need to make such a
check for both symbols.
[*] That is, every configuration where you're removing the symbol from
libpthread. If your change is only for NPTL, you don't need to be
concerned with Hurd.
* Joseph Myers:
> On Fri, 1 Nov 2019, Alistair Francis wrote:
>
>> The nptl/check-abi-libpthread test is failing on a large number of
>> archs. This is what seems to be failing, although I can't figure out
>> why:
>
> Because you're removing nanosleep from pthread-compat-wrappers.
>
> If you want to remove a symbol from libpthread that is duplicated in libc,
> you need to make sure that, for *every* glibc configuration[*], the symbol
> versions of that symbol in libpthread are a subset of the symbol versions
> of that symbol in libc. If that is the case, you can remove the symbol
> from libpthread, updating all the ABI test baselines at the same time. See
> many patches of Florian's for examples of moving a symbol from libpthread
> to libc. If some symbol version isn't already in libc, it needs to be
> added there (see the move of clock_*, for example).
And it has to be added at the version currently under development,
otherwise applications which link against that symbol will encounter
various obscure failures when running on older glibc versions, rather
than the (now standard) missing symbol version failure.
> I think such changes to remove duplicate function definitions from
> libpthread are to be encouraged, now that it's possible to move a
> versioned symbol (from another library to libc) that way. But they should
> *not* be mixed in with other changes to how the function is implemented,
> and you do need to check that all required symbol versions are already in
> libc as described above. If moving two symbols at once (as in this patch
> which affects both nanosleep and __nanosleep) you need to make such a
> check for both symbols.
I agree.
@@ -165,6 +165,8 @@ extern struct tm *__tz_convert (__time64_t timer, int use_localtime,
extern int __nanosleep (const struct timespec *__requested_time,
struct timespec *__remaining);
hidden_proto (__nanosleep)
+extern int __clock_nanosleep (clockid_t clock_id, int flags,
+ const struct timespec *req, struct timespec *rem);
extern int __getdate_r (const char *__string, struct tm *__resbufp)
attribute_hidden;
@@ -187,6 +189,26 @@ libc_hidden_proto (__difftime64)
extern double __difftime (time_t time1, time_t time0);
+#if __TIMESIZE == 64
+# define __thrd_sleep_time64 thrd_sleep
+# define __clock_nanosleep_time64 __clock_nanosleep
+# define __nanosleep_time64 __nanosleep
+# define __nanosleep_nocancel_time64 __nanosleep_nocancel
+#else
+extern int __thrd_sleep_time64 (const struct __timespec64* time_point,
+ struct __timespec64* remaining);
+libc_hidden_proto (__thrd_sleep_time64)
+extern int __clock_nanosleep_time64 (clockid_t clock_id,
+ int flags, const struct __timespec64 *req,
+ struct __timespec64 *rem);
+libc_hidden_proto (__clock_nanosleep_time64)
+extern int __nanosleep_time64 (const struct __timespec64 *requested_time,
+ struct __timespec64 *remaining);
+libc_hidden_proto (__nanosleep_time64)
+extern int __nanosleep_nocancel_time64 (const struct __timespec64 *requested_time,
+ struct __timespec64 *remaining);
+libc_hidden_proto (__nanosleep_nocancel_time64)
+#endif
/* Use in the clock_* functions. Size of the field representing the
actual clock ID. */
@@ -44,7 +44,7 @@ pthread-compat-wrappers = \
write read close accept \
connect recv recvfrom send \
sendto fsync lseek lseek64 \
- msync nanosleep open open64 pause \
+ msync open open64 pause \
pread pread64 pwrite pwrite64 \
tcdrain wait waitpid msgrcv msgsnd \
sigwait sigsuspend \
@@ -17,23 +17,18 @@
<https://www.gnu.org/licenses/>. */
#include <time.h>
-#include <sysdep-cancel.h>
-
-#include "thrd_priv.h"
+#include <errno.h>
int
thrd_sleep (const struct timespec* time_point, struct timespec* remaining)
{
- INTERNAL_SYSCALL_DECL (err);
- int ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, time_point, remaining);
- if (INTERNAL_SYSCALL_ERROR_P (ret, err))
- {
- /* C11 states thrd_sleep function returns -1 if it has been interrupted
- by a signal, or a negative value if it fails. */
- ret = INTERNAL_SYSCALL_ERRNO (ret, err);
- if (ret == EINTR)
- return -1;
- return -2;
- }
- return 0;
+ int ret = __clock_nanosleep (CLOCK_REALTIME, 0, time_point, remaining);
+ /* C11 states thrd_sleep function returns -1 if it has been interrupted
+ by a signal, or a negative value if it fails. */
+ switch (ret)
+ {
+ case 0: return 0;
+ case EINTR: return -1;
+ default: return -2;
+ }
}
@@ -22,10 +22,15 @@
/* Pause execution for a number of nanoseconds. */
int
__nanosleep (const struct timespec *requested_time,
- struct timespec *remaining)
+ struct timespec *remaining)
{
- __set_errno (ENOSYS);
- return -1;
+ int ret = __clock_nanosleep (CLOCK_REALTIME, 0, requested_time, remaining);
+ if (ret != 0)
+ {
+ __set_errno (ret);
+ return -1;
+ }
+ return ret;
}
stub_warning (nanosleep)
@@ -16,6 +16,7 @@
<https://www.gnu.org/licenses/>. */
#include <time.h>
+#include <kernel-features.h>
#include <errno.h>
#include <sysdep-cancel.h>
@@ -26,9 +27,11 @@
/* We can simply use the syscall. The CPU clocks are not supported
with this function. */
int
-__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
- struct timespec *rem)
+__clock_nanosleep_time64 (clockid_t clock_id, int flags, const struct __timespec64 *req,
+ struct __timespec64 *rem)
{
+ int r = -1;
+
if (clock_id == CLOCK_THREAD_CPUTIME_ID)
return EINVAL;
if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
@@ -37,12 +40,66 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
/* If the call is interrupted by a signal handler or encounters an error,
it returns a positive value similar to errno. */
INTERNAL_SYSCALL_DECL (err);
- int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, clock_id, flags,
- req, rem);
+
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_clock_nanosleep_time64
+# define __NR_clock_nanosleep_time64 __NR_clock_nanosleep
+# endif
+ r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
+ flags, req, rem);
+#else
+# ifdef __NR_clock_nanosleep_time64
+ long int ret_64;
+
+ ret_64 = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
+ flags, req, rem);
+
+ if (ret_64 == 0 || errno != ENOSYS)
+ {
+ return (INTERNAL_SYSCALL_ERROR_P (ret_64, err)
+ ? INTERNAL_SYSCALL_ERRNO (ret_64, err) : 0);
+ }
+# endif /* __NR_clock_nanosleep_time64 */
+ struct timespec ts32, tr32;
+
+ if (! in_time_t_range (req->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ ts32 = valid_timespec64_to_timespec (*req);
+ r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, &ts32, &tr32);
+
+ if ((r == 0 || errno != ENOSYS) && rem)
+ *rem = valid_timespec_to_timespec64 (tr32);
+#endif /* __ASSUME_TIME64_SYSCALLS */
+
return (INTERNAL_SYSCALL_ERROR_P (r, err)
- ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
+ ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
}
+#if __TIMESIZE != 64
+int
+__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
+ struct timespec *rem)
+{
+ int r;
+ struct __timespec64 treq64, trem64;
+
+ treq64 = valid_timespec_to_timespec64 (*req);
+ r = __clock_nanosleep_time64 (clock_id, flags, &treq64, &trem64);
+
+ if (r == 0 || errno != ENOSYS)
+ {
+ if (rem)
+ *rem = valid_timespec64_to_timespec (trem64);
+ }
+
+ return r;
+}
+#endif
+
versioned_symbol (libc, __clock_nanosleep, clock_nanosleep, GLIBC_2_17);
/* clock_nanosleep moved to libc in version 2.17;
old binaries may expect the symbol version it had in librt. */
deleted file mode 100644
@@ -1,31 +0,0 @@
-/* Linux nanosleep syscall implementation.
- Copyright (C) 2017-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/>. */
-
-#include <time.h>
-#include <sysdep-cancel.h>
-#include <not-cancel.h>
-
-/* Pause execution for a number of nanoseconds. */
-int
-__nanosleep (const struct timespec *requested_time,
- struct timespec *remaining)
-{
- return SYSCALL_CANCEL (nanosleep, requested_time, remaining);
-}
-hidden_def (__nanosleep)
-weak_alias (__nanosleep, nanosleep)