linux, x86: Add 32 bit vDSO time function support

Message ID 1397894884.5444.1.camel@vger.seibold.net
State Superseded
Headers

Commit Message

Stefani Seibold April 19, 2014, 8:08 a.m. UTC
  This patch add support for 32 bit vDSO time functions provided by the linux
kernel 3.15, which will be also supported the ia32 emulation mode.

The VDSO time functions __vdso_time(), __vdso_gettimeofday() and
__vdso_clock_getttime() are fast and a reliable way to get the exact
time without the overhead of a kernel system call.

This results in a performance increase between 4 and 13 for this
functions, depending on the CPU and the function.

The patch is not very intrusive, since it only make changes in the
sysdeps/unix/sysv/linux/i386 path.

The code is copied and based from the file in the
sysdeps/unix/sysv/linux/i386/x86_64 path.

The patch is against commit c54e5cf7db32709b4f04a117f44f69dc5684cbf2

I habe signed a ASSIGNMENT - GLIBC form which is already confirmed.

ChangeLog:

2014-04-19  Stefani Seibold  <stefani@seibold.net>

        * sysdeps/unix/sysv/linux/i386/clock_gettime.c: Add header
        * sysdeps/unix/sysv/linux/i386/timespec_get.c: Add header

2014-03-04  Stefani Seibold  <stefani@seibold.net>

        * sysdeps/unix/sysv/linux/i386/Makefile: New file
        * sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h: New file
        * sysdeps/unix/sysv/linux/i386/clock_gettime.c: New file
        * sysdeps/unix/sysv/linux/i386/gettimeofday.c: New file
        * sysdeps/unix/sysv/linux/i386/init-first.c: New file
        * sysdeps/unix/sysv/linux/i386/time.c: New file
        * sysdeps/unix/sysv/linux/i386/timespec_get.c: New file

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 sysdeps/unix/sysv/linux/i386/Makefile         |  4 ++
 sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h | 31 +++++++++++++
 sysdeps/unix/sysv/linux/i386/clock_gettime.c  | 37 +++++++++++++++
 sysdeps/unix/sysv/linux/i386/gettimeofday.c   | 65 ++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/i386/init-first.c     | 52 +++++++++++++++++++++
 sysdeps/unix/sysv/linux/i386/time.c           | 67 +++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/i386/timespec_get.c   | 27 +++++++++++
 7 files changed, 283 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h
 create mode 100644 sysdeps/unix/sysv/linux/i386/clock_gettime.c
 create mode 100644 sysdeps/unix/sysv/linux/i386/gettimeofday.c
 create mode 100644 sysdeps/unix/sysv/linux/i386/init-first.c
 create mode 100644 sysdeps/unix/sysv/linux/i386/time.c
 create mode 100644 sysdeps/unix/sysv/linux/i386/timespec_get.c
  

Comments

Rich Felker April 20, 2014, 5:34 p.m. UTC | #1
On Sat, Apr 19, 2014 at 10:08:04AM +0200, Stefani Seibold wrote:
> This patch add support for 32 bit vDSO time functions provided by the linux
> kernel 3.15, which will be also supported the ia32 emulation mode.

This patch looks excessively large considering that it's just adding
to 32-bit x86 functionality which is already implemented for x86_64. I
believe it also already exists for ppc and maybe some other archs. If
it really requires this much code duplication to add the same feature
to each arch, I think some serious refactoring is called for...

Rich
  
Adhemerval Zanella Netto April 22, 2014, 1:45 p.m. UTC | #2
Hi Stefani,

Some comments bellow.


On 19-04-2014 05:08, Stefani Seibold wrote:
> This patch add support for 32 bit vDSO time functions provided by the linux
> kernel 3.15, which will be also supported the ia32 emulation mode.
>
> The VDSO time functions __vdso_time(), __vdso_gettimeofday() and
> __vdso_clock_getttime() are fast and a reliable way to get the exact
> time without the overhead of a kernel system call.
>
> This results in a performance increase between 4 and 13 for this
> functions, depending on the CPU and the function.
>
> The patch is not very intrusive, since it only make changes in the
> sysdeps/unix/sysv/linux/i386 path.
>
> The code is copied and based from the file in the
> sysdeps/unix/sysv/linux/i386/x86_64 path.
>
> The patch is against commit c54e5cf7db32709b4f04a117f44f69dc5684cbf2
>
> I habe signed a ASSIGNMENT - GLIBC form which is already confirmed.
>
> ChangeLog:
>
> 2014-04-19  Stefani Seibold  <stefani@seibold.net>
>
>         * sysdeps/unix/sysv/linux/i386/clock_gettime.c: Add header
>         * sysdeps/unix/sysv/linux/i386/timespec_get.c: Add header
>
> 2014-03-04  Stefani Seibold  <stefani@seibold.net>
>
>         * sysdeps/unix/sysv/linux/i386/Makefile: New file
>         * sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h: New file
>         * sysdeps/unix/sysv/linux/i386/clock_gettime.c: New file
>         * sysdeps/unix/sysv/linux/i386/gettimeofday.c: New file
>         * sysdeps/unix/sysv/linux/i386/init-first.c: New file
>         * sysdeps/unix/sysv/linux/i386/time.c: New file
>         * sysdeps/unix/sysv/linux/i386/timespec_get.c: New file
>
> Signed-off-by: Stefani Seibold <stefani@seibold.net>
> ---
>  sysdeps/unix/sysv/linux/i386/Makefile         |  4 ++
>  sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h | 31 +++++++++++++
>  sysdeps/unix/sysv/linux/i386/clock_gettime.c  | 37 +++++++++++++++
>  sysdeps/unix/sysv/linux/i386/gettimeofday.c   | 65 ++++++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/i386/init-first.c     | 52 +++++++++++++++++++++
>  sysdeps/unix/sysv/linux/i386/time.c           | 67 +++++++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/i386/timespec_get.c   | 27 +++++++++++
>  7 files changed, 283 insertions(+)
>  create mode 100644 sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/clock_gettime.c
>  create mode 100644 sysdeps/unix/sysv/linux/i386/gettimeofday.c
>  create mode 100644 sysdeps/unix/sysv/linux/i386/init-first.c
>  create mode 100644 sysdeps/unix/sysv/linux/i386/time.c
>  create mode 100644 sysdeps/unix/sysv/linux/i386/timespec_get.c
>
> diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
> index acc3021..3222f46 100644
> --- a/sysdeps/unix/sysv/linux/i386/Makefile
> +++ b/sysdeps/unix/sysv/linux/i386/Makefile
> @@ -21,3 +21,7 @@ endif
>  ifeq ($(subdir),stdlib)
>  gen-as-const-headers += ucontext_i.sym
>  endif
> +
> +ifeq ($(subdir),elf)
> +sysdep_routines += dl-vdso
> +endif
> diff --git a/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h
> new file mode 100644
> index 0000000..f291924
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h
> @@ -0,0 +1,31 @@
> +/* Resolve function pointers to VDSO functions.
> +   Copyright (C) 2005-2014 Free Software Foundation, Inc.

AFAIK for new file the copyright year should be inclusion one, even the file is based on
older glibc files.  This applies to other new files for this patch as well.

> +   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 */
> diff --git a/sysdeps/unix/sysv/linux/i386/clock_gettime.c b/sysdeps/unix/sysv/linux/i386/clock_gettime.c
> new file mode 100644
> index 0000000..049bc93
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/clock_gettime.c
> @@ -0,0 +1,37 @@
> +/* Copyright (C) 2002-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 "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"

Although it is not wrong, I wonder why i386/x86_64 code does not just add this kind of logic
on INLINE_VSYSCALL to check for vDSO avaliability and fallback to syscall code is the vDSO
does not exists (like powerpc code).  This means both this file and x86_64 would be superfluous.

Also, I would prefer to:

#include <sysdeps/unix/sysv/linux/clock_gettime.c>

Instead of relative paths.


> diff --git a/sysdeps/unix/sysv/linux/i386/gettimeofday.c b/sysdeps/unix/sysv/linux/i386/gettimeofday.c
> new file mode 100644
> index 0000000..f2be8fb
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/gettimeofday.c
> @@ -0,0 +1,65 @@
> +/* Copyright (C) 2002-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 <sysdep.h>
> +# include <errno.h>
> +
> +static int
> +fallback_gettimeofday (struct timeval *tv, struct timezone *tz)
> +{
> +  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
> +}
> +
> +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 syscall.  */
> +  return (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26)
> +	  ?: (void *) fallback_gettimeofday);
> +}
> +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)
> +
> +#endif
> +weak_alias (__gettimeofday, gettimeofday)
> +libc_hidden_weak (gettimeofday)
> 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..e8e96d0
> --- /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) 2007-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 <bits/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)
> +
> +
> +long int fallback_clock_gettime(clockid_t id, struct timespec *tp)
> +{
> +  INTERNAL_SYSCALL_DECL (err);
> +  return INTERNAL_SYSCALL (clock_gettime, err, 2, id, tp);
> +}
> +
> +
> +static inline void
> +_libc_vdso_platform_setup (void)
> +{
> +  PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
> +
> +  void *p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
> +  if (p == NULL)
> +    p = fallback_clock_gettime;
> +  PTR_MANGLE (p);
> +  __GI___vdso_clock_gettime = p;
> +}
> +
> +# define VDSO_SETUP _libc_vdso_platform_setup
> +#endif
> +
> +#include <csu/init-first.c>
> diff --git a/sysdeps/unix/sysv/linux/i386/time.c b/sysdeps/unix/sysv/linux/i386/time.c
> new file mode 100644
> index 0000000..f1a4c66
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/time.c
> @@ -0,0 +1,67 @@
> +/* Copyright (C) 2001-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
> +/* 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 <sysdep.h>
> +
> +static time_t
> +fallback_time (time_t *t)
> +{
> +  INTERNAL_SYSCALL_DECL (err);
> +  return INTERNAL_SYSCALL (time, err, 1, t);
> +}
> +
> +
> +#include <dl-vdso.h>
> +
> +/* 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 syscall.  */
> +  return _dl_vdso_vsym ("__vdso_time", &linux26) ?: (void *) fallback_time;
> +}
> +__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);
> +}
> +
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/i386/timespec_get.c b/sysdeps/unix/sysv/linux/i386/timespec_get.c
> new file mode 100644
> index 0000000..6eb83c1
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/timespec_get.c
> @@ -0,0 +1,27 @@
> +/* Copyright (C) 2002-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 "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"

And I tend to agree with Rich: this is a large patch to add a similar functionality
already existent in x86_64.  I'm just saying here x86_64/i386 makes more sense to
have a common base code, other arches different much in internal implementation (x86_64
for powerpc, for instance).
  
Stefani Seibold May 2, 2014, 8:56 p.m. UTC | #3
On Sun, 2014-04-20 at 13:34 -0400, Rich Felker wrote:
> On Sat, Apr 19, 2014 at 10:08:04AM +0200, Stefani Seibold wrote:
> > This patch add support for 32 bit vDSO time functions provided by the linux
> > kernel 3.15, which will be also supported the ia32 emulation mode.
> 
> This patch looks excessively large considering that it's just adding
> to 32-bit x86 functionality which is already implemented for x86_64. I
> believe it also already exists for ppc and maybe some other archs. If
> it really requires this much code duplication to add the same feature
> to each arch, I think some serious refactoring is called for...
> 

I am not sure what you expect...

But i have not the GLIBC knowledge nor the test equipment to unify and
refactoring the whole VDSO functionality in GLIBC. Since this kind of
rework impact a lot of different architectures it would need a lot of
tests.

All i can offer is to do a #include "../<x86_64 file>.c" instead of
duplicating the code.

- Stefani
  

Patch

diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index acc3021..3222f46 100644
--- a/sysdeps/unix/sysv/linux/i386/Makefile
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
@@ -21,3 +21,7 @@  endif
 ifeq ($(subdir),stdlib)
 gen-as-const-headers += ucontext_i.sym
 endif
+
+ifeq ($(subdir),elf)
+sysdep_routines += dl-vdso
+endif
diff --git a/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h
new file mode 100644
index 0000000..f291924
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h
@@ -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 */
diff --git a/sysdeps/unix/sysv/linux/i386/clock_gettime.c b/sysdeps/unix/sysv/linux/i386/clock_gettime.c
new file mode 100644
index 0000000..049bc93
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/clock_gettime.c
@@ -0,0 +1,37 @@ 
+/* Copyright (C) 2002-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 "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"
diff --git a/sysdeps/unix/sysv/linux/i386/gettimeofday.c b/sysdeps/unix/sysv/linux/i386/gettimeofday.c
new file mode 100644
index 0000000..f2be8fb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/gettimeofday.c
@@ -0,0 +1,65 @@ 
+/* Copyright (C) 2002-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 <sysdep.h>
+# include <errno.h>
+
+static int
+fallback_gettimeofday (struct timeval *tv, struct timezone *tz)
+{
+  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+}
+
+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 syscall.  */
+  return (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26)
+	  ?: (void *) fallback_gettimeofday);
+}
+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)
+
+#endif
+weak_alias (__gettimeofday, gettimeofday)
+libc_hidden_weak (gettimeofday)
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..e8e96d0
--- /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) 2007-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 <bits/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)
+
+
+long int fallback_clock_gettime(clockid_t id, struct timespec *tp)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  return INTERNAL_SYSCALL (clock_gettime, err, 2, id, tp);
+}
+
+
+static inline void
+_libc_vdso_platform_setup (void)
+{
+  PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
+
+  void *p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
+  if (p == NULL)
+    p = fallback_clock_gettime;
+  PTR_MANGLE (p);
+  __GI___vdso_clock_gettime = p;
+}
+
+# define VDSO_SETUP _libc_vdso_platform_setup
+#endif
+
+#include <csu/init-first.c>
diff --git a/sysdeps/unix/sysv/linux/i386/time.c b/sysdeps/unix/sysv/linux/i386/time.c
new file mode 100644
index 0000000..f1a4c66
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/time.c
@@ -0,0 +1,67 @@ 
+/* Copyright (C) 2001-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
+/* 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 <sysdep.h>
+
+static time_t
+fallback_time (time_t *t)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  return INTERNAL_SYSCALL (time, err, 1, t);
+}
+
+
+#include <dl-vdso.h>
+
+/* 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 syscall.  */
+  return _dl_vdso_vsym ("__vdso_time", &linux26) ?: (void *) fallback_time;
+}
+__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);
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/timespec_get.c b/sysdeps/unix/sysv/linux/i386/timespec_get.c
new file mode 100644
index 0000000..6eb83c1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/timespec_get.c
@@ -0,0 +1,27 @@ 
+/* Copyright (C) 2002-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 "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"