public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] s390: make use of vdso.
@ 2009-01-05 14:49 Martin Schwidefsky
  2009-01-08  0:42 ` Ulrich Drepper
  0 siblings, 1 reply; 2+ messages in thread
From: Martin Schwidefsky @ 2009-01-05 14:49 UTC (permalink / raw)
  To: Glibc hackers

Greetings,
the s390 vdso implementation has been intregrated into the upstream
kernel repository with git commit b020632e40c3ed5e8c0c066d022672907e8401cf.
This patch uses the vdso to speed up the glibc functions gettimeofday,
clock_gettime and clock_getres.

I have chosen kernel version 2.6.29 as symbol version as the next
kernel release will be the first one with the vdso support. 

-- 
blue skies,
  Martin.

"Reality continues to ruin my life." - Calvin.
--

2009-01-05  Martin Schwidefsky  <schwidefsky@de.ibm.com>

	* sysdeps/unix/sysv/linux/s390/bits/libc-vdso.h: New file.
	* sysdeps/unix/sysv/linux/s390/gettimeofday.c: New file.
	* sysdeps/unix/sysv/linux/s390/init-first.c: New file.
	* sysdeps/unix/sysv/linux/s390/Makefile (sysdep_routines): Add dl-vdso
	for elf subdir.
	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h (INLINE_VSYSCALL,
	INTERNAL_VSYSCALL, INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK,
	INTERNAL_SYSCALL_NCS, HAVE_CLOCK_GETRES_VSYSCALL and
	HAVE_CLOCK_GETTIME_VSYSCALL: Define.
	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h: Likewise.
	* sysdeps/unix/sysv/linux/s390/Versions: New file.

diff -urpN libc/sysdeps/unix/sysv/linux/s390/bits/libc-vdso.h libc-s390/sysdeps/unix/sysv/linux/s390/bits/libc-vdso.h
--- libc/sysdeps/unix/sysv/linux/s390/bits/libc-vdso.h	1970-01-01 01:00:00.000000000 +0100
+++ libc-s390/sysdeps/unix/sysv/linux/s390/bits/libc-vdso.h	2009-01-02 10:50:26.000000000 +0100
@@ -0,0 +1,35 @@
+/* Resolve function pointers to VDSO functions.
+   Copyright (C) 2008 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+
+#ifndef _LIBC_VDSO_H
+#define _LIBC_VDSO_H
+
+#ifdef SHARED
+
+extern long int (*__vdso_gettimeofday) (struct timeval *, void *)
+  attribute_hidden;
+
+extern long int (*__vdso_clock_gettime) (clockid_t, struct timespec *);
+
+extern long int (*__vdso_clock_getres) (clockid_t, struct timespec *);
+
+#endif
+
+#endif /* _LIBC_VDSO_H */
diff -urpN libc/sysdeps/unix/sysv/linux/s390/gettimeofday.c libc-s390/sysdeps/unix/sysv/linux/s390/gettimeofday.c
--- libc/sysdeps/unix/sysv/linux/s390/gettimeofday.c	1970-01-01 01:00:00.000000000 +0100
+++ libc-s390/sysdeps/unix/sysv/linux/s390/gettimeofday.c	2009-01-02 10:50:26.000000000 +0100
@@ -0,0 +1,42 @@
+/* Copyright (C) 2008 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <bp-checks.h>
+#include <stddef.h>
+#include <sys/time.h>
+#include <time.h>
+#include <hp-timing.h>
+
+#undef __gettimeofday
+#include <bits/libc-vdso.h>
+
+/* Get the current time of day and timezone information,
+   putting it into *TV and *TZ.  If TZ is NULL, *TZ is not filled.
+   Returns 0 on success, -1 on errors.  */
+
+int
+__gettimeofday (tv, tz)
+     struct timeval *tv;
+     struct timezone *tz;
+{
+  return INLINE_VSYSCALL (gettimeofday, 2, CHECK_1 (tv), CHECK_1 (tz));
+}
+
+INTDEF (__gettimeofday)
+weak_alias (__gettimeofday, gettimeofday)
diff -urpN libc/sysdeps/unix/sysv/linux/s390/init-first.c libc-s390/sysdeps/unix/sysv/linux/s390/init-first.c
--- libc/sysdeps/unix/sysv/linux/s390/init-first.c	1970-01-01 01:00:00.000000000 +0100
+++ libc-s390/sysdeps/unix/sysv/linux/s390/init-first.c	2009-01-02 10:52:22.000000000 +0100
@@ -0,0 +1,50 @@
+/* Copyright (C) 2008 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef SHARED
+# include <dl-vdso.h>
+# undef __gettimeofday
+# undef __clock_gettime
+# undef __clock_getres
+# include <bits/libc-vdso.h>
+
+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)
+
+long int (*__vdso_clock_getres) (clockid_t, struct timespec *)
+  __attribute__ ((nocommon));
+strong_alias (__vdso_clock_getres, __GI___vdso_clock_getres attribute_hidden)
+
+
+static inline void
+_libc_vdso_platform_setup (void)
+{
+  PREPARE_VERSION (linux2629, "LINUX_2.6.29", 123718585);
+
+  __vdso_gettimeofday = _dl_vdso_vsym ("__kernel_gettimeofday", &linux2629);
+  __vdso_clock_gettime = _dl_vdso_vsym ("__kernel_clock_gettime", &linux2629);
+  __vdso_clock_getres = _dl_vdso_vsym ("__kernel_clock_getres", &linux2629);
+}
+
+# define VDSO_SETUP _libc_vdso_platform_setup
+#endif
+
+#include "../init-first.c"
diff -urpN libc/sysdeps/unix/sysv/linux/s390/Makefile libc-s390/sysdeps/unix/sysv/linux/s390/Makefile
--- libc/sysdeps/unix/sysv/linux/s390/Makefile	2008-09-30 13:23:20.000000000 +0200
+++ libc-s390/sysdeps/unix/sysv/linux/s390/Makefile	2009-01-02 10:50:26.000000000 +0100
@@ -6,3 +6,7 @@ endif
 ifeq ($(subdir),stdlib)
 gen-as-const-headers += ucontext_i.sym
 endif
+
+ifeq ($(subdir),elf)
+sysdep_routines += dl-vdso
+endif
diff -urpN libc/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h libc-s390/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
--- libc/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h	2008-09-30 11:19:54.000000000 +0200
+++ libc-s390/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h	2009-01-02 10:50:26.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008
    Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
@@ -26,6 +26,11 @@
 #include <dl-sysdep.h>	/* For RTLD_PRIVATE_ERRNO.  */
 #include <tls.h>
 
+/* Define __set_errno() for INLINE_SYSCALL macro below.  */
+#ifndef __ASSEMBLER__
+#include <errno.h>
+#endif
+
 /* For Linux we can use the system call table in the header file
 	/usr/include/asm/unistd.h
    of the kernel.  But these symbols do not follow the SYS_* syntax
@@ -276,6 +281,100 @@
 #define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
 #define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
 
+#define CLOBBER_0 , "3", "4", "5"
+#define CLOBBER_1 , "3", "4", "5"
+#define CLOBBER_2 , "4", "5"
+#define CLOBBER_3 , "5"
+#define CLOBBER_4
+#define CLOBBER_5
+#define CLOBBER_6
+
+/* List of system calls which are supported as vsyscalls.  */
+#define HAVE_CLOCK_GETRES_VSYSCALL	1
+#define HAVE_CLOCK_GETTIME_VSYSCALL	1
+
+/* 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;							      \
+    long int _ret;							      \
+									      \
+    if (__vdso_##name != NULL)						      \
+      {									      \
+	_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, , nr, ##args);	      \
+	if (!INTERNAL_SYSCALL_ERROR_P (_ret, ))				      \
+	  goto out;							      \
+	if (INTERNAL_SYSCALL_ERRNO (_ret, ) != ENOSYS)			      \
+	  goto iserr;							      \
+      }									      \
+									      \
+    _ret = INTERNAL_SYSCALL (name, , nr, ##args);			      \
+    if (INTERNAL_SYSCALL_ERROR_P (_ret, ))				      \
+      {									      \
+      iserr:								      \
+        __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, ));			      \
+        _ret = -1L;							      \
+      }									      \
+  out:									      \
+    (int) _ret;								      \
+  })
+#else
+# define INLINE_VSYSCALL(name, nr, args...) \
+  INLINE_SYSCALL (name, nr, ##args)
+#endif
+
+#ifdef SHARED
+# define INTERNAL_VSYSCALL(name, err, nr, args...) \
+  ({									      \
+    __label__ out;							      \
+    long int _ret;							      \
+									      \
+    if (__vdso_##name != NULL)						      \
+      {									      \
+	_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args);	      \
+	if (!INTERNAL_SYSCALL_ERROR_P (_ret, err)			      \
+	    || INTERNAL_SYSCALL_ERRNO (_ret, err) != ENOSYS)		      \
+	  goto out;							      \
+      }									      \
+    _ret = INTERNAL_SYSCALL (name, err, nr, ##args);			      \
+  out:									      \
+    _ret;								      \
+  })
+#else
+# define INTERNAL_VSYSCALL(name, err, nr, args...) \
+  INTERNAL_SYSCALL (name, err, nr, ##args)
+#endif
+
+/* This version is for internal uses when there is no desire
+   to set errno */
+#define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...)	      \
+  ({									      \
+    long int _ret = ENOSYS;						      \
+									      \
+    if (__vdso_##name != NULL)						      \
+      _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args);	      \
+    else								      \
+      err = 1 << 28;							      \
+    _ret;								      \
+  })
+
+#define INTERNAL_VSYSCALL_NCS(fn, err, nr, args...)			      \
+  ({									      \
+    DECLARGS_##nr(args)							      \
+    register long _ret asm("2");						      \
+    asm volatile (							      \
+    "lr 11,14\n\t"							      \
+    "basr 14,%1\n\t"							      \
+    "lr 14,11\n\t"							      \
+    : "=d" (_ret)							      \
+    : "d" (fn) ASMFMT_##nr						      \
+    : "cc", "memory", "0", "1", "11" CLOBBER_##nr);			      \
+    _ret; })
 
 /* Pointer mangling support.  */
 #if defined NOT_IN_libc && defined IS_IN_rtld
diff -urpN libc/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h libc-s390/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
--- libc/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h	2008-09-30 11:19:54.000000000 +0200
+++ libc-s390/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h	2009-01-02 10:50:26.000000000 +0100
@@ -1,5 +1,5 @@
 /* Assembler macros for 64 bit S/390.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008
    Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
@@ -27,6 +27,11 @@
 #include <dl-sysdep.h>	/* For RTLD_PRIVATE_ERRNO.  */
 #include <tls.h>
 
+/* Define __set_errno() for INLINE_SYSCALL macro below.  */
+#ifndef __ASSEMBLER__
+#include <errno.h>
+#endif
+
 /* For Linux we can use the system call table in the header file
 	/usr/include/asm/unistd.h
    of the kernel.  But these symbols do not follow the SYS_* syntax
@@ -278,6 +283,101 @@
 #define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
 #define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
 
+#define CLOBBER_0 , "3", "4", "5"
+#define CLOBBER_1 , "3", "4", "5"
+#define CLOBBER_2 , "4", "5"
+#define CLOBBER_3 , "5"
+#define CLOBBER_4
+#define CLOBBER_5
+#define CLOBBER_6
+
+/* List of system calls which are supported as vsyscalls.  */
+#define HAVE_CLOCK_GETRES_VSYSCALL	1
+#define HAVE_CLOCK_GETTIME_VSYSCALL	1
+
+/* 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;							      \
+    long int _ret;							      \
+									      \
+    if (__vdso_##name != NULL)						      \
+      {									      \
+	_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, , nr, ##args);	      \
+	if (!INTERNAL_SYSCALL_ERROR_P (_ret, ))				      \
+	  goto out;							      \
+	if (INTERNAL_SYSCALL_ERRNO (_ret, ) != ENOSYS)			      \
+	  goto iserr;							      \
+      }									      \
+									      \
+    _ret = INTERNAL_SYSCALL (name, , nr, ##args);			      \
+    if (INTERNAL_SYSCALL_ERROR_P (_ret, ))				      \
+      {									      \
+      iserr:								      \
+        __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, ));			      \
+        _ret = -1L;							      \
+      }									      \
+  out:									      \
+    (int) _ret;								      \
+  })
+#else
+# define INLINE_VSYSCALL(name, nr, args...) \
+  INLINE_SYSCALL (name, nr, ##args)
+#endif
+
+#ifdef SHARED
+# define INTERNAL_VSYSCALL(name, err, nr, args...) \
+  ({									      \
+    __label__ out;							      \
+    long int _ret;							      \
+									      \
+    if (__vdso_##name != NULL)						      \
+      {									      \
+	_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args);	      \
+	if (!INTERNAL_SYSCALL_ERROR_P (_ret, err)			      \
+	    || INTERNAL_SYSCALL_ERRNO (_ret, err) != ENOSYS)		      \
+	  goto out;							      \
+      }									      \
+    _ret = INTERNAL_SYSCALL (name, err, nr, ##args);			      \
+  out:									      \
+    _ret;								      \
+  })
+#else
+# define INTERNAL_VSYSCALL(name, err, nr, args...) \
+  INTERNAL_SYSCALL (name, err, nr, ##args)
+#endif
+
+/* This version is for internal uses when there is no desire
+   to set errno */
+#define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...)	      \
+  ({									      \
+    long int _ret = ENOSYS;						      \
+									      \
+    if (__vdso_##name != NULL)						      \
+      _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args);	      \
+    else								      \
+      err = 1 << 28;							      \
+    _ret;								      \
+  })
+
+#define INTERNAL_VSYSCALL_NCS(fn, err, nr, args...)			      \
+  ({									      \
+    DECLARGS_##nr(args)							      \
+    register long _ret asm("2");					      \
+    asm volatile (							      \
+    "lgr 11,14\n\t"							      \
+    "basr 14,%1\n\t"							      \
+    "lgr 14,11\n\t"							      \
+    : "=d" (_ret)							      \
+    : "a" (fn) ASMFMT_##nr						      \
+    : "cc", "memory", "0", "1", "11" CLOBBER_##nr);			      \
+    _ret; })
+
 /* Pointer mangling support.  */
 #if defined NOT_IN_libc && defined IS_IN_rtld
 /* We cannot use the thread descriptor because in ld.so we use setjmp
diff -urpN libc/sysdeps/unix/sysv/linux/s390/Versions libc-s390/sysdeps/unix/sysv/linux/s390/Versions
--- libc/sysdeps/unix/sysv/linux/s390/Versions	1970-01-01 01:00:00.000000000 +0100
+++ libc-s390/sysdeps/unix/sysv/linux/s390/Versions	2009-01-02 10:50:26.000000000 +0100
@@ -0,0 +1,6 @@
+libc {
+  GLIBC_PRIVATE {
+    __vdso_clock_gettime;
+    __vdso_clock_getres;
+  }
+}


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] s390: make use of vdso.
  2009-01-05 14:49 [PATCH] s390: make use of vdso Martin Schwidefsky
@ 2009-01-08  0:42 ` Ulrich Drepper
  0 siblings, 0 replies; 2+ messages in thread
From: Ulrich Drepper @ 2009-01-08  0:42 UTC (permalink / raw)
  To: schwidefsky; +Cc: Glibc hackers

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Applied.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkllSLQACgkQ2ijCOnn/RHTOkwCgjqC0zMYkAnSEct+N8djUR74c
fEkAoKZKOfoKZq3Hw3oeUH81azITj18a
=lopc
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-01-08  0:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-05 14:49 [PATCH] s390: make use of vdso Martin Schwidefsky
2009-01-08  0:42 ` Ulrich Drepper

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).