From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23818 invoked by alias); 5 Jan 2009 14:49:30 -0000 Received: (qmail 23801 invoked by uid 22791); 5 Jan 2009 14:49:30 -0000 X-SWARE-Spam-Status: No, hits=-0.1 required=5.0 tests=AWL,BAYES_50,J_CHICKENPOX_22,SPF_SOFTFAIL X-Spam-Check-By: sourceware.org Received: from mtagate7.de.ibm.com (HELO mtagate7.de.ibm.com) (195.212.29.156) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 05 Jan 2009 14:49:24 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate7.de.ibm.com (8.13.8/8.13.8) with ESMTP id n05EnKHu150718 for ; Mon, 5 Jan 2009 14:49:20 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v9.1) with ESMTP id n05EnKrS4161692 for ; Mon, 5 Jan 2009 15:49:20 +0100 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n05EnKDK027119 for ; Mon, 5 Jan 2009 15:49:20 +0100 Received: from [9.152.212.40] (dyn-9-152-212-40.boeblingen.de.ibm.com [9.152.212.40]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n05EnKnC027116 for ; Mon, 5 Jan 2009 15:49:20 +0100 Subject: [PATCH] s390: make use of vdso. From: Martin Schwidefsky Reply-To: schwidefsky@de.ibm.com To: Glibc hackers Content-Type: text/plain Date: Mon, 05 Jan 2009 14:49:00 -0000 Message-Id: <1231166959.20209.1.camel@localhost> Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Mailing-List: contact libc-hacker-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sourceware.org X-SW-Source: 2009-01/txt/msg00000.txt.bz2 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 * 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 +#include +#include +#include +#include +#include + +#undef __gettimeofday +#include + +/* 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 +# undef __gettimeofday +# undef __clock_gettime +# undef __clock_getres +# include + +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 /* For RTLD_PRIVATE_ERRNO. */ #include +/* Define __set_errno() for INLINE_SYSCALL macro below. */ +#ifndef __ASSEMBLER__ +#include +#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 /* For RTLD_PRIVATE_ERRNO. */ #include +/* Define __set_errno() for INLINE_SYSCALL macro below. */ +#ifndef __ASSEMBLER__ +#include +#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; + } +}