[v2] Add x86 32 bit vDSO time function support
Commit Message
Hi,
This is a respin of my x86 vDSO cleanup / time support. The new ftime testcase
showed the initial patch was not really generating correct code for internal
ifunc for i386. Similar to a previous bug that was presented in ppc32, linker
creates an incorrect PLT stub for internal __gettimeofday usage. I tried some
binutils (2.23, 2.24, master), but all show the same behavior. x86_64 is ok,
I checked and ftime does call __gettimeofday from vDSO.
I didn't dig into this issue, so if someone with more experience in i386 ABI
could take a look it will helpful. Currently I'm setting the internal
getimeofday for i386 to its syscall version.
Checked on i386 and x86_64 on a 3.10 kernel and on a 3.16 kernel.
--
2014-10-09 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Stefani Seibold <stefani@seibold.net>
* sysdeps/unix/sysv/linux/x86_64/Makefile [$(subdir) = elf]
(sysdep_routines): Add dl-vdso here, ...
* sysdeps/unix/sysv/linux/x86/Makefile [$(subdir) = elf]
(sysdep_routines): ... not here.
* sysdeps/unix/sysv/linux/i386/gettimeofday.c: New file: set syscall
fallback when vDSO is not presented.
* sysdeps/unix/sysv/linux/x86_64/init-first.c (__vdso_clock_gettime):
Define with libc_hidden_proto/libc_hidden_data_def definitions.
(_libc_vdso_platform_setup): Rename to __vdso_platform_setup.
* sysdeps/unix/sysv/linux/i386/init-first.c: New file: likewise.
* sysdeps/unix/sysv/linux/i386/time.c: New file: likewise.
* sysdeps/unix/sysv/linux/x86_64/bits/libc-vdso.h: Moved to ...
* sysdeps/unix/sysv/linux/x86/libc-vdso.h: ... here.
* sysdeps/unix/sysv/linux/x86_64/clock_gettime.c: Move to ...
* sysdeps/unix/sysv/linux/x86/clock_gettime.c: ... here.
* sysdeps/unix/sysv/linux/x86_64/gettimeofday.c: Move to ...
* sysdeps/unix/sysv/linux/x86/gettimeofday.c: ... here. Also added
fallback configurable symbol when vDSO is not available.
* sysdeps/unix/sysv/linux/x86_64/time.c: Move to ...
* sysdeps/unix/sysv/linux/x86/time.c: ... here. Also refactored to
be able to redefine fallback symbol when vDSO is not available.
* sysdeps/unix/sysv/linux/x86_64/timespec_get.c: Move to ...
* sysdeps/unix/sysv/linux/x86/timespec_get.c: ... here.
---
Comments
On 10/09/2014 01:31 PM, Adhemerval Zanella wrote:
> diff --git a/sysdeps/unix/sysv/linux/i386/init-first.c b/sysdeps/unix/sysv/linux/i386/init-first.c
> new file mode 100644
> index 0000000..dc3b1ba
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/init-first.c
> @@ -0,0 +1,52 @@
> +/* Initialization code run first thing by the ELF startup code. Linux/i386.
> + Copyright (C) 2014 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/>. */
> +
> +#ifdef SHARED
> +# include <time.h>
> +# include <sysdep.h>
> +# include <dl-vdso.h>
> +# include <libc-vdso.h>
> +
> +long int (*__vdso_clock_gettime) (clockid_t, struct timespec *)
> + __attribute__ ((nocommon));
> +libc_hidden_proto (__vdso_clock_gettime)
> +libc_hidden_data_def (__vdso_clock_gettime)
> +
> +static long int
> +clock_gettime_syscall (clockid_t id, struct timespec *tp)
> +{
> + INTERNAL_SYSCALL_DECL (err);
> + return INTERNAL_SYSCALL (clock_gettime, err, 2, id, tp);
> +}
> +
> +static inline void
> +__vdso_platform_setup (void)
> +{
> + PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
Perhaps:
PREPARE_VERSION_KNOWN (linux26, LINUX_2_6);
(here and several other places)
> +
> + void *p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
> + if (p == NULL)
> + p = clock_gettime_syscall;
> + PTR_MANGLE (p);
> + __vdso_clock_gettime = p;
> +}
> +
> +# define VDSO_SETUP __vdso_platform_setup
> +#endif
> +
> +#include <csu/init-first.c>
[...]
> diff --git a/sysdeps/unix/sysv/linux/x86/clock_gettime.c b/sysdeps/unix/sysv/linux/x86/clock_gettime.c
> new file mode 100644
> index 0000000..2547a8c
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/clock_gettime.c
> @@ -0,0 +1,38 @@
> +/* Get the current value of a clock. Linux/x86 version.
> + Copyright (C) 2014 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-vdso.h>
> +
> +#ifdef SHARED
> +# define SYSCALL_GETTIME(id, tp) \
> + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
> + long int v_ret; \
> + PTR_DEMANGLE (f); \
> + v_ret = (*f) (id, tp); \
> + if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { \
> + __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); \
> + v_ret = -1; \
> + } \
> + v_ret; })
Does introducing the dispatch through function pointer here cause a
measurable performance regression on i386 kernels which lack the VDSO?
If so, is that a concern?
When I've tried this approach on ARM, it appears to do so (around 5%
slowdown).
> +# define INTERNAL_GETTIME(id, tp) \
> + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
> + PTR_DEMANGLE (f); \
> + (*f) (id, tp); })
> +#endif
I'm probably missing something, but I am failing to see the need for an
INTERNAL_GETTIME definition in
sysdeps/unix/sysv/linux/x86/clock_gettime.c. I know this patch is
merely moving existing code, but sysdeps/unix/sysv/linux/clock_gettime.c
does not use INTERNAL_GETTIME, and neither does
sysdeps/unix/clock_gettime.c.
INTERNAL_GETTIME is needed for timespec_get, but I am not seeing the
need to duplicate it for clock_gettime.
On 09-10-2014 17:50, Nathan Lynch wrote:
> On 10/09/2014 01:31 PM, Adhemerval Zanella wrote:
>> +static long int
>> +clock_gettime_syscall (clockid_t id, struct timespec *tp)
>> +{
>> + INTERNAL_SYSCALL_DECL (err);
>> + return INTERNAL_SYSCALL (clock_gettime, err, 2, id, tp);
>> +}
>> +
>> +static inline void
>> +__vdso_platform_setup (void)
>> +{
>> + PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
> Perhaps:
>
> PREPARE_VERSION_KNOWN (linux26, LINUX_2_6);
>
> (here and several other places)
Thanks, I fixed it on all the places nows.
>
>> +#ifdef SHARED
>> +# define SYSCALL_GETTIME(id, tp) \
>> + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
>> + long int v_ret; \
>> + PTR_DEMANGLE (f); \
>> + v_ret = (*f) (id, tp); \
>> + if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { \
>> + __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); \
>> + v_ret = -1; \
>> + } \
>> + v_ret; })
> Does introducing the dispatch through function pointer here cause a
> measurable performance regression on i386 kernels which lack the VDSO?
> If so, is that a concern?
>
> When I've tried this approach on ARM, it appears to do so (around 5%
> slowdown).
Using a simple benchmark (in attachments) the difference in such scenarios is not
as drastic as ARM it seems:
kernel: Linux birita 3.13.0-39
CPU: Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
EGLIBC 2.19-0ubuntu6.3: 1415.12 cycles
GLIBC 2.20 master: 1421.66 cycles
>
>
>> +# define INTERNAL_GETTIME(id, tp) \
>> + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
>> + PTR_DEMANGLE (f); \
>> + (*f) (id, tp); })
>> +#endif
> I'm probably missing something, but I am failing to see the need for an
> INTERNAL_GETTIME definition in
> sysdeps/unix/sysv/linux/x86/clock_gettime.c. I know this patch is
> merely moving existing code, but sysdeps/unix/sysv/linux/clock_gettime.c
> does not use INTERNAL_GETTIME, and neither does
> sysdeps/unix/clock_gettime.c.
>
> INTERNAL_GETTIME is needed for timespec_get, but I am not seeing the
> need to duplicate it for clock_gettime.
i386 does not define HAVE_CLOCK_GETTIME_VSYSCALL and thus:
sysdeps/unix/sysv/linux/clock_gettime.c:
26: # define INTERNAL_VSYSCALL INTERNAL_SYSCALL
and then if INTERNAL_GETTIME is not defined, it will as:
37 #ifndef INTERNAL_GETTIME
38 # define INTERNAL_GETTIME(id, tp) \
39 INTERNAL_VSYSCALL (clock_gettime, err, 2, id, tp)
40 #endif
And without proper set the PTR_DEMANGLE is not called either.
With PREPARE_VERSION_KNOWN fixes, is it ok to commit?
On 03-11-2014 18:30, Adhemerval Zanella wrote:
> On 09-10-2014 17:50, Nathan Lynch wrote:
>> On 10/09/2014 01:31 PM, Adhemerval Zanella wrote:
>>> +static long int
>>> +clock_gettime_syscall (clockid_t id, struct timespec *tp)
>>> +{
>>> + INTERNAL_SYSCALL_DECL (err);
>>> + return INTERNAL_SYSCALL (clock_gettime, err, 2, id, tp);
>>> +}
>>> +
>>> +static inline void
>>> +__vdso_platform_setup (void)
>>> +{
>>> + PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
>> Perhaps:
>>
>> PREPARE_VERSION_KNOWN (linux26, LINUX_2_6);
>>
>> (here and several other places)
> Thanks, I fixed it on all the places nows.
>
>>> +#ifdef SHARED
>>> +# define SYSCALL_GETTIME(id, tp) \
>>> + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
>>> + long int v_ret; \
>>> + PTR_DEMANGLE (f); \
>>> + v_ret = (*f) (id, tp); \
>>> + if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { \
>>> + __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); \
>>> + v_ret = -1; \
>>> + } \
>>> + v_ret; })
>> Does introducing the dispatch through function pointer here cause a
>> measurable performance regression on i386 kernels which lack the VDSO?
>> If so, is that a concern?
>>
>> When I've tried this approach on ARM, it appears to do so (around 5%
>> slowdown).
> Using a simple benchmark (in attachments) the difference in such scenarios is not
> as drastic as ARM it seems:
>
> kernel: Linux birita 3.13.0-39
> CPU: Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
>
> EGLIBC 2.19-0ubuntu6.3: 1415.12 cycles
> GLIBC 2.20 master: 1421.66 cycles
>
>>
>>> +# define INTERNAL_GETTIME(id, tp) \
>>> + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
>>> + PTR_DEMANGLE (f); \
>>> + (*f) (id, tp); })
>>> +#endif
>> I'm probably missing something, but I am failing to see the need for an
>> INTERNAL_GETTIME definition in
>> sysdeps/unix/sysv/linux/x86/clock_gettime.c. I know this patch is
>> merely moving existing code, but sysdeps/unix/sysv/linux/clock_gettime.c
>> does not use INTERNAL_GETTIME, and neither does
>> sysdeps/unix/clock_gettime.c.
>>
>> INTERNAL_GETTIME is needed for timespec_get, but I am not seeing the
>> need to duplicate it for clock_gettime.
> i386 does not define HAVE_CLOCK_GETTIME_VSYSCALL and thus:
>
> sysdeps/unix/sysv/linux/clock_gettime.c:
>
> 26: # define INTERNAL_VSYSCALL INTERNAL_SYSCALL
>
> and then if INTERNAL_GETTIME is not defined, it will as:
>
> 37 #ifndef INTERNAL_GETTIME
> 38 # define INTERNAL_GETTIME(id, tp) \
> 39 INTERNAL_VSYSCALL (clock_gettime, err, 2, id, tp)
> 40 #endif
>
> And without proper set the PTR_DEMANGLE is not called either.
>
> With PREPARE_VERSION_KNOWN fixes, is it ok to commit?
>
Send the missing simple benchmark.
On 11/03/2014 02:30 PM, Adhemerval Zanella wrote:
> On 09-10-2014 17:50, Nathan Lynch wrote:
>> On 10/09/2014 01:31 PM, Adhemerval Zanella wrote:
>>
>>> +#ifdef SHARED
>>> +# define SYSCALL_GETTIME(id, tp) \
>>> + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
>>> + long int v_ret; \
>>> + PTR_DEMANGLE (f); \
>>> + v_ret = (*f) (id, tp); \
>>> + if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { \
>>> + __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); \
>>> + v_ret = -1; \
>>> + } \
>>> + v_ret; })
>> Does introducing the dispatch through function pointer here cause a
>> measurable performance regression on i386 kernels which lack the VDSO?
>> If so, is that a concern?
>>
>> When I've tried this approach on ARM, it appears to do so (around 5%
>> slowdown).
>
> Using a simple benchmark (in attachments) the difference in such scenarios is not
> as drastic as ARM it seems:
>
> kernel: Linux birita 3.13.0-39
> CPU: Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
>
> EGLIBC 2.19-0ubuntu6.3: 1415.12 cycles
> GLIBC 2.20 master: 1421.66 cycles
OK.
>>> +# define INTERNAL_GETTIME(id, tp) \
>>> + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
>>> + PTR_DEMANGLE (f); \
>>> + (*f) (id, tp); })
>>> +#endif
>> I'm probably missing something, but I am failing to see the need for an
>> INTERNAL_GETTIME definition in
>> sysdeps/unix/sysv/linux/x86/clock_gettime.c. I know this patch is
>> merely moving existing code, but sysdeps/unix/sysv/linux/clock_gettime.c
>> does not use INTERNAL_GETTIME, and neither does
>> sysdeps/unix/clock_gettime.c.
>>
>> INTERNAL_GETTIME is needed for timespec_get, but I am not seeing the
>> need to duplicate it for clock_gettime.
>
> i386 does not define HAVE_CLOCK_GETTIME_VSYSCALL and thus:
>
> sysdeps/unix/sysv/linux/clock_gettime.c:
>
> 26: # define INTERNAL_VSYSCALL INTERNAL_SYSCALL
>
> and then if INTERNAL_GETTIME is not defined, it will as:
>
> 37 #ifndef INTERNAL_GETTIME
> 38 # define INTERNAL_GETTIME(id, tp) \
> 39 INTERNAL_VSYSCALL (clock_gettime, err, 2, id, tp)
> 40 #endif
>
> And without proper set the PTR_DEMANGLE is not called either.
I think my point might be better expressed as: why is INTERNAL_GETTIME
defined in linux/clock_gettime.c at all? It is not used in the
clock_gettime implementation.
The only use in glibc of a macro by that name is in
linux/timespec_get.c, and the arch can override it in its own
timespec_get.c (as x86_64 currently does).
> With PREPARE_VERSION_KNOWN fixes, is it ok to commit?
I have no objection, FWIW.
new file mode 100644
@@ -0,0 +1,39 @@
+/* gettimeofday - get the time. Linux/i386 version.
+ Copyright (C) 2014 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 <sys/time.h>
+
+#ifdef SHARED
+
+# include <dl-vdso.h>
+# include <errno.h>
+
+/* If the vDSO is not available we fall back on the syscall. */
+static int
+__gettimeofday_syscall (struct timeval *tv, struct timezone *tz)
+{
+ return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+}
+# define GETTIMEOFAY_FALLBACK (void*) (&__gettimeofday_syscall)
+# undef libc_ifunc_hidden_def
+# define libc_ifunc_hidden_def(name) \
+ libc_ifunc_hidden_def1 (__GI_##name, __gettimeofday_syscall)
+
+#endif
+
+#include <sysdeps/unix/sysv/linux/x86/gettimeofday.c>
new file mode 100644
@@ -0,0 +1,52 @@
+/* Initialization code run first thing by the ELF startup code. Linux/i386.
+ Copyright (C) 2014 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/>. */
+
+#ifdef SHARED
+# include <time.h>
+# include <sysdep.h>
+# include <dl-vdso.h>
+# include <libc-vdso.h>
+
+long int (*__vdso_clock_gettime) (clockid_t, struct timespec *)
+ __attribute__ ((nocommon));
+libc_hidden_proto (__vdso_clock_gettime)
+libc_hidden_data_def (__vdso_clock_gettime)
+
+static long int
+clock_gettime_syscall (clockid_t id, struct timespec *tp)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ return INTERNAL_SYSCALL (clock_gettime, err, 2, id, tp);
+}
+
+static inline void
+__vdso_platform_setup (void)
+{
+ PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
+
+ void *p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
+ if (p == NULL)
+ p = clock_gettime_syscall;
+ PTR_MANGLE (p);
+ __vdso_clock_gettime = p;
+}
+
+# define VDSO_SETUP __vdso_platform_setup
+#endif
+
+#include <csu/init-first.c>
new file mode 100644
@@ -0,0 +1,37 @@
+/* time -- Get number of seconds since Epoch. Linux/i386 version.
+ Copyright (C) 2014 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/>. */
+
+#ifdef SHARED
+
+# include <dl-vdso.h>
+# include <errno.h>
+
+/* If the vDSO is not available we fall back on the old vsyscall. */
+static time_t
+__time_syscall (time_t *t)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ return INTERNAL_SYSCALL (time, err, 1, t);
+}
+# define TIME_FALLBACK (void*) &__time_syscall
+# undef libc_ifunc_hidden_def
+# define libc_ifunc_hidden_def(name) \
+ libc_ifunc_hidden_def1 (__GI_##name, __time_syscall)
+#endif
+
+#include <sysdeps/unix/sysv/linux/x86/time.c>
@@ -19,3 +19,7 @@ libpthread-sysdep_routines += init-arch
libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
elision-trylock
endif
+
+ifeq ($(subdir),elf)
+sysdep_routines += dl-vdso
+endif
new file mode 100644
@@ -0,0 +1,38 @@
+/* Get the current value of a clock. Linux/x86 version.
+ Copyright (C) 2014 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-vdso.h>
+
+#ifdef SHARED
+# define SYSCALL_GETTIME(id, tp) \
+ ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
+ long int v_ret; \
+ PTR_DEMANGLE (f); \
+ v_ret = (*f) (id, tp); \
+ if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { \
+ __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); \
+ v_ret = -1; \
+ } \
+ v_ret; })
+# define INTERNAL_GETTIME(id, tp) \
+ ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
+ PTR_DEMANGLE (f); \
+ (*f) (id, tp); })
+#endif
+
+#include <sysdeps/unix/sysv/linux/clock_gettime.c>
new file mode 100644
@@ -0,0 +1,53 @@
+/* gettimeofday - get the time. Linux/x86 version.
+ 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 <sys/time.h>
+
+#ifdef SHARED
+
+# include <dl-vdso.h>
+
+void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday");
+
+void *
+gettimeofday_ifunc (void)
+{
+ PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
+
+ /* If the vDSO is not available we fall back on the old vsyscall. */
+ return (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26)
+ ?: GETTIMEOFAY_FALLBACK);
+}
+asm (".type __gettimeofday, %gnu_indirect_function");
+
+libc_ifunc_hidden_def(__gettimeofday)
+
+#else
+
+# include <sysdep.h>
+# include <errno.h>
+
+int
+__gettimeofday (struct timeval *tv, struct timezone *tz)
+{
+ return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+}
+libc_hidden_def (__gettimeofday)
+
+#endif
+weak_alias (__gettimeofday, gettimeofday)
+libc_hidden_weak (gettimeofday)
new file mode 100644
@@ -0,0 +1,31 @@
+/* Resolve function pointers to VDSO functions.
+ Copyright (C) 2005-2014 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 _LIBC_VDSO_H
+#define _LIBC_VDSO_H
+
+#include <time.h>
+#include <sys/time.h>
+
+#ifdef SHARED
+
+extern long int (*__vdso_clock_gettime) (clockid_t, struct timespec *);
+
+#endif
+
+#endif /* _LIBC_VDSO_H */
new file mode 100644
@@ -0,0 +1,49 @@
+/* time -- Get number of seconds since Epoch. Linux/x86 version.
+ Copyright (C) 2014 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 <time.h>
+
+#ifdef SHARED
+
+#include <dl-vdso.h>
+
+void *time_ifunc (void) __asm__ ("time");
+
+void *
+time_ifunc (void)
+{
+ PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
+
+ return _dl_vdso_vsym ("__vdso_time", &linux26) ?: TIME_FALLBACK;
+}
+asm (".type time, %gnu_indirect_function");
+
+libc_ifunc_hidden_def(time)
+
+#else
+
+# include <sysdep.h>
+
+time_t
+time (time_t *t)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ return INTERNAL_SYSCALL (time, err, 1, t);
+}
+
+#endif
new file mode 100644
@@ -0,0 +1,29 @@
+/* timespec_get -- returns the calendar time based on a given time base.
+ Linux/x86 version.
+ Copyright (C) 2014 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-vdso.h>
+
+#ifdef SHARED
+# define INTERNAL_GETTIME(id, tp) \
+ ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
+ PTR_DEMANGLE (f); \
+ (*f) (id, tp); })
+#endif
+
+#include <sysdeps/unix/sysv/linux/timespec_get.c>
@@ -13,7 +13,3 @@ endif
ifeq ($(subdir),misc)
gen-as-const-headers += sigaltstack-offsets.sym
endif
-
-ifeq ($(subdir),elf)
-sysdep_routines += dl-vdso
-endif
deleted file mode 100644
@@ -1,31 +0,0 @@
-/* Resolve function pointers to VDSO functions.
- Copyright (C) 2005-2014 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 _LIBC_VDSO_H
-#define _LIBC_VDSO_H
-
-#include <time.h>
-#include <sys/time.h>
-
-#ifdef SHARED
-
-extern long int (*__vdso_clock_gettime) (clockid_t, struct timespec *);
-
-#endif
-
-#endif /* _LIBC_VDSO_H */
deleted file mode 100644
@@ -1,20 +0,0 @@
-#include "bits/libc-vdso.h"
-
-#ifdef SHARED
-# define SYSCALL_GETTIME(id, tp) \
- ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
- long int v_ret; \
- PTR_DEMANGLE (f); \
- v_ret = f (id, tp); \
- if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { \
- __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); \
- v_ret = -1; \
- } \
- v_ret; })
-# define INTERNAL_GETTIME(id, tp) \
- ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
- PTR_DEMANGLE (f); \
- f (id, tp); })
-#endif
-
-#include "../clock_gettime.c"
@@ -18,42 +18,9 @@
#include <sys/time.h>
#ifdef SHARED
-
-# include <dl-vdso.h>
-
+/* If the vDSO is not available we fall back on the old vsyscall. */
# define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000ul
-
-void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday");
-
-void *
-gettimeofday_ifunc (void)
-{
- PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
-
- /* If the vDSO is not available we fall back on the old vsyscall. */
- return (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26)
- ?: (void *) VSYSCALL_ADDR_vgettimeofday);
-}
-asm (".type __gettimeofday, %gnu_indirect_function");
-
-/* This is doing "libc_hidden_def (__gettimeofday)" but the compiler won't
- let us do it in C because it doesn't know we're defining __gettimeofday
- here in this file. */
-asm (".globl __GI___gettimeofday\n"
- "__GI___gettimeofday = __gettimeofday");
-
-#else
-
-# include <sysdep.h>
-# include <errno.h>
-
-int
-__gettimeofday (struct timeval *tv, struct timezone *tz)
-{
- return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
-}
-libc_hidden_def (__gettimeofday)
-
+# define GETTIMEOFAY_FALLBACK (void*)VSYSCALL_ADDR_vgettimeofday
#endif
-weak_alias (__gettimeofday, gettimeofday)
-libc_hidden_weak (gettimeofday)
+
+#include <sysdeps/unix/sysv/linux/x86/gettimeofday.c>
@@ -20,20 +20,20 @@
# include <time.h>
# include <sysdep.h>
# include <dl-vdso.h>
-# include <bits/libc-vdso.h>
+# include <libc-vdso.h>
long int (*__vdso_clock_gettime) (clockid_t, struct timespec *)
__attribute__ ((nocommon));
-strong_alias (__vdso_clock_gettime, __GI___vdso_clock_gettime attribute_hidden)
+libc_hidden_proto (__vdso_clock_gettime)
+libc_hidden_data_def (__vdso_clock_gettime)
long int (*__vdso_getcpu) (unsigned *, unsigned *, void *) attribute_hidden;
-
extern long int __syscall_clock_gettime (clockid_t, struct timespec *);
static inline void
-_libc_vdso_platform_setup (void)
+__vdso_platform_setup (void)
{
PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
@@ -41,7 +41,7 @@ _libc_vdso_platform_setup (void)
if (p == NULL)
p = __syscall_clock_gettime;
PTR_MANGLE (p);
- __GI___vdso_clock_gettime = p;
+ __vdso_clock_gettime = p;
p = _dl_vdso_vsym ("__vdso_getcpu", &linux26);
/* If the vDSO is not available we fall back on the old vsyscall. */
@@ -52,7 +52,7 @@ _libc_vdso_platform_setup (void)
__vdso_getcpu = p;
}
-# define VDSO_SETUP _libc_vdso_platform_setup
+# define VDSO_SETUP __vdso_platform_setup
#endif
#include <csu/init-first.c>
@@ -16,45 +16,9 @@
<http://www.gnu.org/licenses/>. */
#ifdef SHARED
-/* Redefine time so that the compiler won't complain about the type
- mismatch with the IFUNC selector in strong_alias, below. */
-#undef time
-#define time __redirect_time
-#include <time.h>
-
-#include <dl-vdso.h>
-
+/* If the vDSO is not available we fall back on the old vsyscall. */
#define VSYSCALL_ADDR_vtime 0xffffffffff600400
-
-/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
- ifunc symbol properly. */
-extern __typeof (__redirect_time) __libc_time;
-void *time_ifunc (void) __asm__ ("__libc_time");
-
-void *
-time_ifunc (void)
-{
- PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
-
- /* If the vDSO is not available we fall back on the old vsyscall. */
- return _dl_vdso_vsym ("__vdso_time", &linux26) ?: (void *) VSYSCALL_ADDR_vtime;
-}
-__asm (".type __libc_time, %gnu_indirect_function");
-
-#undef time
-strong_alias (__libc_time, time)
-libc_hidden_ver (__libc_time, time)
-
-#else
-
-# include <time.h>
-# include <sysdep.h>
-
-time_t
-time (time_t *t)
-{
- INTERNAL_SYSCALL_DECL (err);
- return INTERNAL_SYSCALL (time, err, 1, t);
-}
-
+#define TIME_FALLBACK (void*)VSYSCALL_ADDR_vtime
#endif
+
+#include <sysdeps/unix/sysv/linux/x86/time.c>
deleted file mode 100644
@@ -1,10 +0,0 @@
-#include "bits/libc-vdso.h"
-
-#ifdef SHARED
-# define INTERNAL_GETTIME(id, tp) \
- ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
- PTR_DEMANGLE (f); \
- f (id, tp); })
-#endif
-
-#include "../timespec_get.c"