diff mbox

tile: add clock_gettime support via vDSO

Message ID 201410021559.s92FxUgw020872@farm-0002.internal.tilera.com
State New
Headers show

Commit Message

Chris Metcalf Oct. 1, 2014, 7:10 p.m. UTC
---
 sysdeps/unix/sysv/linux/tile/Versions         |  1 +
 sysdeps/unix/sysv/linux/tile/bits/libc-vdso.h |  2 +
 sysdeps/unix/sysv/linux/tile/gettimeofday.c   |  7 +---
 sysdeps/unix/sysv/linux/tile/init-first.c     |  6 +++
 sysdeps/unix/sysv/linux/tile/sysdep.h         | 59 +++++++++++++++++++++++++++
 5 files changed, 69 insertions(+), 6 deletions(-)

2014-10-02  Chris Metcalf  <cmetcalf@tilera.com>

	* sysdeps/unix/sysv/linux/tile/sysdep.h (INLINE_VSYSCALL): Define
	INLINE_VSYSCALL, INTERNAL_VSYSCALL, and
	HAVE_CLOCK_GETTIME_VSYSCALL macros.
	* sysdeps/unix/sysv/linux/tile/gettimeofday.c (__gettimeofday):
	Use INLINE_VSYSCALL macro.
	* sysdeps/unix/sysv/linux/tile/bits/libc-vdso: Add declaration of
	__vdso_clock_gettime.
	* sysdeps/unix/sysv/linux/tile/init-first.c
	(_libc_vdso_platform_setup): Set new __vdso_clock_gettime global.
	* sysdeps/unix/sysv/linux/tile/Versions (GLIBC_PRIVATE): Add
	__vdso_clock_gettime.
diff mbox

Patch

diff --git a/sysdeps/unix/sysv/linux/tile/Versions b/sysdeps/unix/sysv/linux/tile/Versions
index 9b40d2839fb3..13da68fa7915 100644
--- a/sysdeps/unix/sysv/linux/tile/Versions
+++ b/sysdeps/unix/sysv/linux/tile/Versions
@@ -13,5 +13,6 @@  libc {
   }
   GLIBC_PRIVATE {
     __syscall_error;
+    __vdso_clock_gettime;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/tile/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/tile/bits/libc-vdso.h
index c4aec16d19c0..f5b04ba66959 100644
--- a/sysdeps/unix/sysv/linux/tile/bits/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/tile/bits/libc-vdso.h
@@ -25,6 +25,8 @@ 
 extern long int (*__vdso_gettimeofday) (struct timeval *, void *)
   attribute_hidden;
 
+extern long int (*__vdso_clock_gettime) (clockid_t, struct timespec *);
+
 #endif
 
 #endif /* _LIBC_VDSO_H */
diff --git a/sysdeps/unix/sysv/linux/tile/gettimeofday.c b/sysdeps/unix/sysv/linux/tile/gettimeofday.c
index 6f62ab960c69..2168c2a0688d 100644
--- a/sysdeps/unix/sysv/linux/tile/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/tile/gettimeofday.c
@@ -24,12 +24,7 @@ 
 int
 __gettimeofday (struct timeval *tv, struct timezone *tz)
 {
-#ifdef SHARED
-  /* If the vDSO is available we use it. */
-  if (__vdso_gettimeofday != NULL)
-    return __vdso_gettimeofday (tv, tz);
-#endif
-  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
 }
 
 libc_hidden_def (__gettimeofday)
diff --git a/sysdeps/unix/sysv/linux/tile/init-first.c b/sysdeps/unix/sysv/linux/tile/init-first.c
index 9790d223b160..fa39b94a3060 100644
--- a/sysdeps/unix/sysv/linux/tile/init-first.c
+++ b/sysdeps/unix/sysv/linux/tile/init-first.c
@@ -21,11 +21,17 @@ 
 
 long int (*__vdso_gettimeofday) (struct timeval *, void *) attribute_hidden;
 
+long int (*__vdso_clock_gettime) (clockid_t, struct timespec *)
+  __attribute__ ((nocommon));
+strong_alias (__vdso_clock_gettime, __GI___vdso_clock_gettime attribute_hidden)
+
+
 static inline void
 _libc_vdso_platform_setup (void)
 {
   PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
   __vdso_gettimeofday = _dl_vdso_vsym ("__vdso_gettimeofday", &linux26);
+  __vdso_clock_gettime = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
 }
 
 #define VDSO_SETUP _libc_vdso_platform_setup
diff --git a/sysdeps/unix/sysv/linux/tile/sysdep.h b/sysdeps/unix/sysv/linux/tile/sysdep.h
index a09f8a4adf05..238b266a8216 100644
--- a/sysdeps/unix/sysv/linux/tile/sysdep.h
+++ b/sysdeps/unix/sysv/linux/tile/sysdep.h
@@ -202,6 +202,65 @@ 
   "=R02" (_clobber_r2), "=R03" (_clobber_r3), "=R04" (_clobber_r4),     \
     "=R05" (_clobber_r5), "=R10" (_clobber_r10)
 
+/* This version is for kernels that implement system calls that
+   behave like function calls as far as register saving.
+   It falls back to the syscall in the case that the vDSO doesn't
+   exist or fails for ENOSYS */
+# ifdef SHARED
+#  define INLINE_VSYSCALL(name, nr, args...) \
+  ({									      \
+    __label__ out;							      \
+    __label__ iserr;							      \
+    INTERNAL_SYSCALL_DECL (sc_err);					      \
+    long int sc_ret;							      \
+									      \
+    __typeof (__vdso_##name) vdsop = __vdso_##name;			      \
+    if (vdsop != NULL)							      \
+      {									      \
+        sc_ret = vdsop (args);						      \
+        if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))			      \
+          goto out;							      \
+        if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS)		      \
+          goto iserr;							      \
+      }									      \
+									      \
+    sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args);		      \
+    if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))			      \
+      {									      \
+      iserr:								      \
+        __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));		      \
+        sc_ret = -1L;							      \
+      }									      \
+  out:									      \
+    sc_ret;								      \
+  })
+#  define INTERNAL_VSYSCALL(name, err, nr, args...) \
+  ({									      \
+    __label__ out;							      \
+    long int v_ret;							      \
+									      \
+    __typeof (__vdso_##name) vdsop = __vdso_##name;			      \
+    if (vdsop != NULL)							      \
+      {									      \
+        v_ret = vdsop (args);						      \
+        if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err)			      \
+            || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS)		      \
+          goto out;							      \
+      }									      \
+    v_ret = INTERNAL_SYSCALL (name, err, nr, ##args);			      \
+  out:									      \
+    v_ret;								      \
+  })
+
+/* List of system calls which are supported as vsyscalls.  */
+#  define HAVE_CLOCK_GETTIME_VSYSCALL	1
+
+# else
+#  define INLINE_VSYSCALL(name, nr, args...) \
+  INLINE_SYSCALL (name, nr, ##args)
+#  define INTERNAL_VSYSCALL(name, err, nr, args...) \
+  INTERNAL_SYSCALL (name, err, nr, ##args)
+# endif
 #endif /* not __ASSEMBLER__ */
 
 /* Pointer mangling support.  */