about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--sysdeps/unix/sysv/linux/tile/Versions1
-rw-r--r--sysdeps/unix/sysv/linux/tile/bits/libc-vdso.h2
-rw-r--r--sysdeps/unix/sysv/linux/tile/gettimeofday.c7
-rw-r--r--sysdeps/unix/sysv/linux/tile/init-first.c6
-rw-r--r--sysdeps/unix/sysv/linux/tile/sysdep.h59
6 files changed, 81 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 0ab15a2c53..e127a08c27 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 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.
+
 	* sysdeps/unix/sysv/linux/tile/clone.S (__clone): Fix code
 	to set up frame more cleanly.
 
diff --git a/sysdeps/unix/sysv/linux/tile/Versions b/sysdeps/unix/sysv/linux/tile/Versions
index 9b40d2839f..13da68fa79 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 c4aec16d19..f5b04ba669 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 6f62ab960c..2168c2a068 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 9790d223b1..fa39b94a30 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 a09f8a4adf..238b266a82 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.  */