summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2014-10-01 15:10:04 -0400
committerChris Metcalf <cmetcalf@tilera.com>2014-10-06 11:22:14 -0400
commit845a73434c829341db4d250f837754afb17ae1a2 (patch)
treeba4bb2fcc0607d515108389edc030876b7401b92
parent83d641efd1f6eb699dd846b9e99af7bcff7e063e (diff)
downloadglibc-845a73434c829341db4d250f837754afb17ae1a2.tar.gz
tile: add clock_gettime support via vDSO
-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. */