This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 01/12] linux: Fix vDSO macros build with time64 interfaces


As indicated on libc-help [1] the ec138c67cb commit broke 32-bit
builds when configured with --enable-kernel=5.1 or higher.  The
scenario 10 from [2] might also occur in this configuration and
INLINE_VSYSCALL will try to use the vDSO symbol and
HAVE_CLOCK_GETTIME64_VSYSCALL does not set HAVE_VSYSCALL prior its
usage.

Also, there is no easy way to just enable the code to use one
vDSO sysmbo since the macro INLINE_VSYSCALL is redefined if
HAVE_VSYSCALL is set.

Instead of adding more pre-processor handling and making the code
even more convoluted, this patch removes the requirement of defining
HAVE_VSYSCALL before including sysdep-vdso.h to enable vDSO usage.

The INLINE_VSYSCALL now only tries to call the vDSO symbol through
the function pointer, the fallback code to try the syscall is done
explicitly.  The internal INLINE_VSYSCALL_CALL semantic is also
changed to return a negative errno value in case of an error, it allows
simplify INLINE_VSYSCALL implementation.

The macro is now expect to be called inside the HAVE_*_VSYSCALL and
it does not fallback to call the syscall (this should be done
explicitly).  Also, calling the INLINE_VSYSCALL macro with a vDSO name
not defined by the architecture will trigger a build error.

Internally it is also simplified to expected a negative value with
errno embedded similar on how the Linux syscall work.  It simplifies
error handling.

Both clock_getres and clock_gettime vDSO code for time64_t were
removed since there is no vDSO setup code for the symbol (currently
an architecture can not set HAVE_CLOCK_GETTIME64_VSYSCALL).

Checked on i686-linux-gnu (default and with --enable-kernel=5.1),
x86_64-linux-gnu, aarch64-linux-gnu, and powerpc64le-linux-gnu.
I also checked against a build to mips64-linux-gnu and
sparc64-linux-gnu.

[1] https://sourceware.org/ml/libc-help/2019-12/msg00014.html
---
 .../unix/sysv/linux/aarch64/gettimeofday.c    |  8 +-
 sysdeps/unix/sysv/linux/clock_getres.c        | 43 ++++++----
 sysdeps/unix/sysv/linux/clock_gettime.c       | 45 +++++++----
 sysdeps/unix/sysv/linux/getcpu.c              | 13 +--
 sysdeps/unix/sysv/linux/mips/sysdep.h         | 16 ----
 .../sysv/linux/powerpc/get_timebase_freq.c    |  3 +-
 .../unix/sysv/linux/powerpc/gettimeofday.c    |  8 +-
 .../sysv/linux/powerpc/powerpc32/sysdep.h     | 10 ++-
 .../sysv/linux/powerpc/powerpc64/sysdep.h     | 10 ++-
 sysdeps/unix/sysv/linux/powerpc/time.c        |  9 +--
 sysdeps/unix/sysv/linux/sched_getcpu.c        | 17 ++--
 sysdeps/unix/sysv/linux/sparc/sysdep.h        |  7 --
 sysdeps/unix/sysv/linux/sysdep-vdso.h         | 79 +++++--------------
 sysdeps/unix/sysv/linux/x86/gettimeofday.c    |  8 +-
 sysdeps/unix/sysv/linux/x86/time.c            | 11 +--
 15 files changed, 117 insertions(+), 170 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/aarch64/gettimeofday.c b/sysdeps/unix/sysv/linux/aarch64/gettimeofday.c
index 7e772e05ce..07d38466e2 100644
--- a/sysdeps/unix/sysv/linux/aarch64/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/aarch64/gettimeofday.c
@@ -22,10 +22,6 @@
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 /* Used as a fallback in the ifunc resolver if VDSO is not available
@@ -36,7 +32,9 @@ __gettimeofday_vsyscall (struct timeval *restrict tv, void *restrict tz)
   if (__glibc_unlikely (tz != 0))
     memset (tz, 0, sizeof *tz);
 
-  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+  if (INLINE_VSYSCALL (gettimeofday, 2, tv, tz) == 0)
+    return 0;
+  return INLINE_SYSCALL_CALL (gettimeofday, tv, tz);
 }
 
 #ifdef SHARED
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 9497f78787..6c12f1d1e9 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -20,9 +20,6 @@
 #include <errno.h>
 #include <time.h>
 
-#ifdef HAVE_CLOCK_GETRES_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 #include <shlib-compat.h>
 #include <kernel-features.h>
@@ -31,25 +28,39 @@
 int
 __clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
 {
+  int r = -1;
+
 #ifdef __ASSUME_TIME64_SYSCALLS
-# ifndef __NR_clock_getres_time64
-  return INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+  /* 64 bit ABIs or Newer 32-bit ABIs that only support 64-bit time_t.  */
+# ifdef __NR_clock_getres_time64
+  r = INLINE_SYSCALL_CALL (clock_getres_time64, clock_id, res);
 # else
-  return INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);
+#  ifdef HAVE_CLOCK_GETRES_VSYSCALL
+  r = INLINE_VSYSCALL (clock_getres, 2, clock_id, res);
+#  endif
+  if (r == -1)
+    r = INLINE_SYSCALL_CALL (clock_getres, clock_id, res);
 # endif
 #else
+  /* Old 32-bit ABI with possible 64-bit time_t support.  */
 # ifdef __NR_clock_getres_time64
-  int ret = INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);
-  if (ret == 0 || errno != ENOSYS)
-    return ret;
+  r = INLINE_SYSCALL_CALL (clock_getres_time64, clock_id, res);
 # endif
-  struct timespec ts32;
-  int retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);
-  if (! retval && res)
-    *res = valid_timespec_to_timespec64 (ts32);
-
-  return retval;
+  if (r == -1)
+    {
+      /* Fallback code that uses 32-bit support.  */
+      struct timespec ts32;
+# ifdef HAVE_CLOCK_GETRES_VSYSCALL
+      r = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);
+# endif
+      if (r == -1)
+	r = INLINE_SYSCALL_CALL (clock_getres, clock_id, &ts32);
+      if (r == 0)
+	*res = valid_timespec_to_timespec64 (ts32);
+    }
 #endif
+
+  return r;
 }
 
 #if __TIMESIZE != 64
@@ -60,7 +71,7 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
   int retval;
 
   retval = __clock_getres64 (clock_id, &ts64);
-  if (! retval && res)
+  if (retval == 0 && res ! = NULL)
     *res = valid_timespec64_to_timespec (ts64);
 
   return retval;
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index 875c4fe905..4ea56c9a4b 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -21,10 +21,6 @@
 #include <errno.h>
 #include <time.h>
 #include "kernel-posix-cpu-timers.h"
-
-#ifdef HAVE_CLOCK_GETTIME_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 #include <shlib-compat.h>
@@ -33,24 +29,39 @@
 int
 __clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
 {
+  int r = -1;
+
 #ifdef __ASSUME_TIME64_SYSCALLS
-# ifndef __NR_clock_gettime64
-#  define __NR_clock_gettime64   __NR_clock_gettime
-#  define __vdso_clock_gettime64 __vdso_clock_gettime
+  /* 64 bit ABIs or Newer 32-bit ABIs that only support 64-bit time_t.  */
+# ifdef __NR_clock_gettime64
+  r = INLINE_SYSCALL_CALL (clock_gettime64, clock_id, tp);
+# else
+#  ifdef HAVE_CLOCK_GETTIME_VSYSCALL
+  r = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);
+#  endif
+  if (r == -1)
+    r = INLINE_SYSCALL_CALL (clock_gettime, clock_id, tp);
 # endif
-   return INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);
 #else
-# if defined HAVE_CLOCK_GETTIME64_VSYSCALL
-  int ret64 = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);
-  if (ret64 == 0 || errno != ENOSYS)
-    return ret64;
+  /* Old 32-bit ABI with possible 64-bit time_t support.  */
+# ifdef __NR_clock_gettime64
+  r = INLINE_SYSCALL_CALL (clock_gettime64, clock_id, tp);
 # endif
-  struct timespec tp32;
-  int ret = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &tp32);
-  if (ret == 0)
-    *tp = valid_timespec_to_timespec64 (tp32);
-  return ret;
+  if (r == -1)
+    {
+      /* Fallback code that uses 32-bit support.  */
+      struct timespec tp32;
+# ifdef HAVE_CLOCK_GETTIME_VSYSCALL
+      r = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &tp32);
+# endif
+      if (r == -1)
+	r = INLINE_SYSCALL_CALL (clock_gettime, clock_id, &tp32);
+      if (r == 0)
+	*tp = valid_timespec_to_timespec64 (tp32);
+    }
 #endif
+
+  return r;
 }
 
 #if __TIMESIZE != 64
diff --git a/sysdeps/unix/sysv/linux/getcpu.c b/sysdeps/unix/sysv/linux/getcpu.c
index fdd27203af..8b26b3e19e 100644
--- a/sysdeps/unix/sysv/linux/getcpu.c
+++ b/sysdeps/unix/sysv/linux/getcpu.c
@@ -18,21 +18,16 @@
 #include <errno.h>
 #include <sched.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETCPU_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 int
 __getcpu (unsigned int *cpu, unsigned int *node)
 {
-#ifdef __NR_getcpu
-  return INLINE_VSYSCALL (getcpu, 3, cpu, node, NULL);
-#else
-  __set_errno (ENOSYS);
-  return -1;
+#ifdef HAVE_GETCPU_VSYSCALL
+  if (INLINE_VSYSCALL (getcpu, 3, cpu, node, NULL) == 0)
+    return 0;
 #endif
+  return INLINE_SYSCALL_CALL (getcpu, cpu, node, NULL);
 }
 weak_alias (__getcpu, getcpu)
 libc_hidden_def (__getcpu)
diff --git a/sysdeps/unix/sysv/linux/mips/sysdep.h b/sysdeps/unix/sysv/linux/mips/sysdep.h
index 82a3cf9f3d..2470f32d58 100644
--- a/sysdeps/unix/sysv/linux/mips/sysdep.h
+++ b/sysdeps/unix/sysv/linux/mips/sysdep.h
@@ -22,19 +22,3 @@
 /* List of system calls which are supported as vsyscalls.  */
 #define HAVE_CLOCK_GETTIME_VSYSCALL     "__vdso_clock_gettime"
 #define HAVE_GETTIMEOFDAY_VSYSCALL      "__vdso_gettimeofday"
-
-#ifndef __ASSEMBLER__
-
-/* Standard MIPS syscalls have an error flag, and return a positive errno
-   when the error flag is set. Emulate this behaviour for vsyscalls so that
-   the INTERNAL_SYSCALL_{ERROR_P,ERRNO} macros work correctly.  */
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)		\
-  ({									\
-    long _ret = funcptr (args);						\
-    err = ((unsigned long) (_ret) >= (unsigned long) -4095L);		\
-    if (err)								\
-      _ret = -_ret;							\
-    _ret;								\
-  })
-
-#endif /* __ASSEMBLER__  */
diff --git a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
index 29b6624b9a..32b9ab5da5 100644
--- a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
+++ b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
@@ -106,7 +106,6 @@ __get_timebase_freq (void)
   if (vdsop == NULL)
     return get_timebase_freq_fallback ();
 
-  INTERNAL_SYSCALL_DECL (err);
-  return INTERNAL_VSYSCALL_CALL_TYPE (vdsop, err, uint64_t, 0);
+  return INTERNAL_VSYSCALL_CALL_TYPE (vdsop, uint64_t, 0);
 }
 weak_alias (__get_timebase_freq, __ppc_get_timebase_freq)
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index 18d8f7cb7a..1982b1e025 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -17,10 +17,6 @@
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 static int
@@ -29,7 +25,9 @@ __gettimeofday_syscall (struct timeval *restrict tv, void *restrict tz)
   if (__glibc_unlikely (tz != 0))
     memset (tz, 0, sizeof *tz);
 
-  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+  if (INLINE_VSYSCALL (gettimeofday, 2, tv, tz) == 0)
+    return 0;
+  return INLINE_SYSCALL_CALL (gettimeofday, tv, tz);
 }
 
 #ifdef SHARED
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
index a3bb552254..3d208dc192 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
@@ -41,7 +41,7 @@
    function call, with the exception of LR (which is needed for the
    "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
    an error return status).  */
-# define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, type, nr, args...)	      \
+# define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, type, nr, args...)	      \
   ({									      \
     register void *r0  __asm__ ("r0");					      \
     register long int r3  __asm__ ("r3");				      \
@@ -63,13 +63,15 @@
        : "+r" (r0), "+r" (r3), "+r" (r4), "+r" (r5),  "+r" (r6),  "+r" (r7),  \
 	 "+r" (r8), "+r" (r9), "+r" (r10), "+r" (r11), "+r" (r12)	      \
        : : "cr0", "ctr", "lr", "memory");				      \
-    err = (long int) r0;						      \
+    long int err = (long int) r0;					      \
     __asm__ __volatile__ ("" : "=r" (rval) : "r" (r3), "r" (r4));	      \
+    if (INTERNAL_SYSCALL_ERROR_P (rval, err))			 	      \
+      rval = -rval;							      \
     rval;								      \
   })
 
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
-  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, long int, nr, args)
+#define INTERNAL_VSYSCALL_CALL(funcptr, nr, args...) \
+  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, long int, nr, args)
 
 # undef INLINE_SYSCALL
 # define INLINE_SYSCALL(name, nr, args...)				\
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
index 207d9d5709..65f5789c63 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -51,7 +51,7 @@
    gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
    the negation of the return value in the kernel gets reverted.  */
 
-#define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, type, nr, args...)    \
+#define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, type, nr, args...)         \
   ({									\
     register void *r0  __asm__ ("r0");					\
     register long int r3  __asm__ ("r3");				\
@@ -70,13 +70,15 @@
        : "+r" (r0), "+r" (r3), "+r" (r4), "+r" (r5),  "+r" (r6),        \
          "+r" (r7), "+r" (r8)						\
        : : "r9", "r10", "r11", "r12", "cr0", "ctr", "lr", "memory");	\
-    err = (long int) r0;						\
+    long int err = (long int) r0;					\
     __asm__ __volatile__ ("" : "=r" (rval) : "r" (r3));		        \
+    if (INTERNAL_SYSCALL_ERROR_P (rval, err))				\
+      rval = -rval;							\
     rval;								\
   })
 
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)		\
-  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, long int, nr, args)
+#define INTERNAL_VSYSCALL_CALL(funcptr, nr, args...)			\
+  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, long int, nr, args)
 
 /* This version is for kernels that implement system calls that
    behave like function calls as far as register saving.  */
diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c
index 80a4c73416..2059097c0a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/time.c
+++ b/sysdeps/unix/sysv/linux/powerpc/time.c
@@ -18,16 +18,15 @@
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_TIME_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 static time_t
 time_vsyscall (time_t *t)
 {
-  return INLINE_VSYSCALL (time, 1, t);
+  time_t ret = INLINE_VSYSCALL (time, 1, t);
+  if (ret != -1)
+    return ret;
+  return INLINE_SYSCALL_CALL (time, t);
 }
 
 #ifdef SHARED
diff --git a/sysdeps/unix/sysv/linux/sched_getcpu.c b/sysdeps/unix/sysv/linux/sched_getcpu.c
index 65dd9fdda7..23a60f1b52 100644
--- a/sysdeps/unix/sysv/linux/sched_getcpu.c
+++ b/sysdeps/unix/sysv/linux/sched_getcpu.c
@@ -18,22 +18,17 @@
 #include <errno.h>
 #include <sched.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETCPU_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 int
 sched_getcpu (void)
 {
-#ifdef __NR_getcpu
   unsigned int cpu;
-  int r = INLINE_VSYSCALL (getcpu, 3, &cpu, NULL, NULL);
-
-  return r == -1 ? r : cpu;
-#else
-  __set_errno (ENOSYS);
-  return -1;
+  int r = -1;
+#ifdef HAVE_GETCPU_VSYSCALL
+  r = INLINE_VSYSCALL (getcpu, 3, &cpu, NULL, NULL);
 #endif
+  if (r == -1)
+    r = INLINE_SYSCALL_CALL (getcpu, &cpu, NULL, NULL);
+  return r == -1 ? r : cpu;
 }
diff --git a/sysdeps/unix/sysv/linux/sparc/sysdep.h b/sysdeps/unix/sysv/linux/sparc/sysdep.h
index f38144c912..4ae0fca6ee 100644
--- a/sysdeps/unix/sysv/linux/sparc/sysdep.h
+++ b/sysdeps/unix/sysv/linux/sparc/sysdep.h
@@ -34,13 +34,6 @@
 
 #else	/* __ASSEMBLER__ */
 
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)		\
-  ({									\
-    long _ret = funcptr (args);						\
-    err = ((unsigned long) (_ret) >= (unsigned long) -4095L);		\
-    _ret;								\
-  })
-
 # define VDSO_NAME  "LINUX_2.6"
 # define VDSO_HASH  61765110
 
diff --git a/sysdeps/unix/sysv/linux/sysdep-vdso.h b/sysdeps/unix/sysv/linux/sysdep-vdso.h
index cf614fbf8b..04525340a5 100644
--- a/sysdeps/unix/sysv/linux/sysdep-vdso.h
+++ b/sysdeps/unix/sysv/linux/sysdep-vdso.h
@@ -21,69 +21,30 @@
 
 #include <dl-vdso.h>
 
+/* Return the errno value as a negative value in case of an error or 0 or
+   positive value otherwise.  */
 #ifndef INTERNAL_VSYSCALL_CALL
-# define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)		      \
+# define INTERNAL_VSYSCALL_CALL(funcptr, nr, args...)			     \
      funcptr (args)
 #endif
 
-#ifdef HAVE_VSYSCALL
-
-# include <libc-vdso.h>
-
-# 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;			      \
-    PTR_DEMANGLE (vdsop);						      \
-    if (vdsop != NULL)							      \
-      {									      \
-	sc_ret = INTERNAL_VSYSCALL_CALL (vdsop, sc_err, nr, ##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 v_ret;								      \
-									      \
-    __typeof (__vdso_##name) vdsop = __vdso_##name;			      \
-    PTR_DEMANGLE (vdsop);						      \
-    if (vdsop != NULL)							      \
-      {									      \
-	v_ret = INTERNAL_VSYSCALL_CALL (vdsop, err, nr, ##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;								      \
+#include <libc-vdso.h>
+
+#define INLINE_VSYSCALL(name, nr, args...)				     \
+  ({									     \
+    long int sc_ret = -1;						     \
+    __typeof (__vdso_##name) vdsop = __vdso_##name;			     \
+    PTR_DEMANGLE (vdsop);						     \
+    if (vdsop != NULL)							     \
+      {									     \
+	sc_ret = INTERNAL_VSYSCALL_CALL (vdsop, nr, ##args);	     	     \
+	if ((unsigned long) sc_ret > -4096UL)				     \
+	  {								     \
+	    __set_errno (-sc_ret);					     \
+	    sc_ret = -1L;						     \
+	  }								     \
+      }									     \
+    sc_ret;								     \
   })
-#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 /* USE_VSYSCALL && defined HAVE_VSYSCALL */
 
 #endif /* SYSDEP_VDSO_LINUX_H  */
diff --git a/sysdeps/unix/sysv/linux/x86/gettimeofday.c b/sysdeps/unix/sysv/linux/x86/gettimeofday.c
index 190127d31e..909575a7e3 100644
--- a/sysdeps/unix/sysv/linux/x86/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/x86/gettimeofday.c
@@ -18,10 +18,6 @@
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 static int
@@ -30,7 +26,9 @@ __gettimeofday_syscall (struct timeval *restrict tv, void *restrict tz)
   if (__glibc_unlikely (tz != 0))
     memset (tz, 0, sizeof *tz);
 
-  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+  if (INLINE_VSYSCALL (gettimeofday, 2, tv, tz) == 0)
+    return 0;
+  return INLINE_SYSCALL_CALL (gettimeofday, tv, tz);
 }
 
 #ifdef SHARED
diff --git a/sysdeps/unix/sysv/linux/x86/time.c b/sysdeps/unix/sysv/linux/x86/time.c
index 4a03c46d21..74bae4b07a 100644
--- a/sysdeps/unix/sysv/linux/x86/time.c
+++ b/sysdeps/unix/sysv/linux/x86/time.c
@@ -18,16 +18,17 @@
 
 #include <time.h>
 #include <sysdep.h>
-
-#ifdef HAVE_TIME_VSYSCALL
-# define HAVE_VSYSCALL
-#endif
 #include <sysdep-vdso.h>
 
 static time_t
 time_vsyscall (time_t *t)
 {
-  return INLINE_VSYSCALL (time, 1, t);
+#ifdef HAVE_TIME_VSYSCALL
+  time_t ret = INLINE_VSYSCALL (time, 1, t);
+  if (ret != -1)
+    return ret;
+#endif
+  return INLINE_SYSCALL_CALL (time, t);
 }
 
 #ifdef SHARED
-- 
2.17.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]