From patchwork Sat Apr 19 08:08:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefani Seibold X-Patchwork-Id: 340472 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 633BA1400BE for ; Sat, 19 Apr 2014 18:09:14 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:subject:from:to:cc:date :content-type:mime-version:content-transfer-encoding; q=dns; s= default; b=qbW3prdkU7UWU4I0m/I5hH72r8UnzCMrTW3r4ds/sYApoXuD7U3FZ 5m2YJr+R4NkxnaXjmBHDpa/A8IHKH6FX1bBHmJEaHT9zMYRXVdC0YTWqglSF08J3 +q8TB1uGlxAfAVnWcLBrqjq+J6bzfKQ7mSUY7xBhdJO/4EcS2uj8Ag= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:subject:from:to:cc:date :content-type:mime-version:content-transfer-encoding; s=default; bh=jaWMqdzsbo/KIsqfth7xa0CiPvQ=; b=ayfAtxXZo+AHDowl507FpoBdh3wI hfbDzjkGVonyiyzVufH/YJDhs28H4dE/4cwMdY3IXcHZLb2VcqXxXmntoFxQOARj zocUnWW2JRy/igxWA3e4HNRGDpAByYbWnY7GSUucnLvrlhnmpSHANKpfXc2t8B9G Wrgqa9XpYTTH6AA= Received: (qmail 16955 invoked by alias); 19 Apr 2014 08:09:08 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 16943 invoked by uid 89); 19 Apr 2014 08:09:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 X-HELO: www84.your-server.de Message-ID: <1397894884.5444.1.camel@vger.seibold.net> Subject: [PATCH] linux, x86: Add 32 bit vDSO time function support From: Stefani Seibold To: libc-alpha@sourceware.org Cc: "H. Peter Anvin" , Andy Lutomirski , Martin Runge , Andreas Brief Date: Sat, 19 Apr 2014 10:08:04 +0200 Mime-Version: 1.0 This patch add support for 32 bit vDSO time functions provided by the linux kernel 3.15, which will be also supported the ia32 emulation mode. The VDSO time functions __vdso_time(), __vdso_gettimeofday() and __vdso_clock_getttime() are fast and a reliable way to get the exact time without the overhead of a kernel system call. This results in a performance increase between 4 and 13 for this functions, depending on the CPU and the function. The patch is not very intrusive, since it only make changes in the sysdeps/unix/sysv/linux/i386 path. The code is copied and based from the file in the sysdeps/unix/sysv/linux/i386/x86_64 path. The patch is against commit c54e5cf7db32709b4f04a117f44f69dc5684cbf2 I habe signed a ASSIGNMENT - GLIBC form which is already confirmed. ChangeLog: 2014-04-19 Stefani Seibold * sysdeps/unix/sysv/linux/i386/clock_gettime.c: Add header * sysdeps/unix/sysv/linux/i386/timespec_get.c: Add header 2014-03-04 Stefani Seibold * sysdeps/unix/sysv/linux/i386/Makefile: New file * sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h: New file * sysdeps/unix/sysv/linux/i386/clock_gettime.c: New file * sysdeps/unix/sysv/linux/i386/gettimeofday.c: New file * sysdeps/unix/sysv/linux/i386/init-first.c: New file * sysdeps/unix/sysv/linux/i386/time.c: New file * sysdeps/unix/sysv/linux/i386/timespec_get.c: New file Signed-off-by: Stefani Seibold --- sysdeps/unix/sysv/linux/i386/Makefile | 4 ++ sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h | 31 +++++++++++++ sysdeps/unix/sysv/linux/i386/clock_gettime.c | 37 +++++++++++++++ sysdeps/unix/sysv/linux/i386/gettimeofday.c | 65 ++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/i386/init-first.c | 52 +++++++++++++++++++++ sysdeps/unix/sysv/linux/i386/time.c | 67 +++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/i386/timespec_get.c | 27 +++++++++++ 7 files changed, 283 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h create mode 100644 sysdeps/unix/sysv/linux/i386/clock_gettime.c create mode 100644 sysdeps/unix/sysv/linux/i386/gettimeofday.c create mode 100644 sysdeps/unix/sysv/linux/i386/init-first.c create mode 100644 sysdeps/unix/sysv/linux/i386/time.c create mode 100644 sysdeps/unix/sysv/linux/i386/timespec_get.c diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile index acc3021..3222f46 100644 --- a/sysdeps/unix/sysv/linux/i386/Makefile +++ b/sysdeps/unix/sysv/linux/i386/Makefile @@ -21,3 +21,7 @@ endif ifeq ($(subdir),stdlib) gen-as-const-headers += ucontext_i.sym endif + +ifeq ($(subdir),elf) +sysdep_routines += dl-vdso +endif diff --git a/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h new file mode 100644 index 0000000..f291924 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/bits/libc-vdso.h @@ -0,0 +1,31 @@ +/* Resolve function pointers to VDSO functions. + Copyright (C) 2005-2014 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, see + . */ + +#ifndef _LIBC_VDSO_H +#define _LIBC_VDSO_H + +#include +#include + +#ifdef SHARED + +extern long int (*__vdso_clock_gettime) (clockid_t, struct timespec *); + +#endif + +#endif /* _LIBC_VDSO_H */ diff --git a/sysdeps/unix/sysv/linux/i386/clock_gettime.c b/sysdeps/unix/sysv/linux/i386/clock_gettime.c new file mode 100644 index 0000000..049bc93 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/clock_gettime.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002-2014 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, see + . */ + +#include "bits/libc-vdso.h" + +#ifdef SHARED +# define SYSCALL_GETTIME(id, tp) \ + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \ + long int v_ret; \ + PTR_DEMANGLE (f); \ + v_ret = f (id, tp); \ + if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); \ + v_ret = -1; \ + } \ + v_ret; }) +# define INTERNAL_GETTIME(id, tp) \ + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \ + PTR_DEMANGLE (f); \ + f (id, tp); }) +#endif + +#include "../clock_gettime.c" diff --git a/sysdeps/unix/sysv/linux/i386/gettimeofday.c b/sysdeps/unix/sysv/linux/i386/gettimeofday.c new file mode 100644 index 0000000..f2be8fb --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/gettimeofday.c @@ -0,0 +1,65 @@ +/* Copyright (C) 2002-2014 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, see + . */ + +#include + +#ifdef SHARED + +# include +# include +# include + +static int +fallback_gettimeofday (struct timeval *tv, struct timezone *tz) +{ + return INLINE_SYSCALL (gettimeofday, 2, tv, tz); +} + +void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday"); + +void * +gettimeofday_ifunc (void) +{ + PREPARE_VERSION (linux26, "LINUX_2.6", 61765110); + + /* If the vDSO is not available we fall back on the old syscall. */ + return (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26) + ?: (void *) fallback_gettimeofday); +} +asm (".type __gettimeofday, %gnu_indirect_function"); + +/* This is doing "libc_hidden_def (__gettimeofday)" but the compiler won't + let us do it in C because it doesn't know we're defining __gettimeofday + here in this file. */ +asm (".globl __GI___gettimeofday\n" + "__GI___gettimeofday = __gettimeofday"); + +#else + +# include +# include + +int +__gettimeofday (struct timeval *tv, struct timezone *tz) +{ + return INLINE_SYSCALL (gettimeofday, 2, tv, tz); +} +libc_hidden_def (__gettimeofday) + +#endif +weak_alias (__gettimeofday, gettimeofday) +libc_hidden_weak (gettimeofday) diff --git a/sysdeps/unix/sysv/linux/i386/init-first.c b/sysdeps/unix/sysv/linux/i386/init-first.c new file mode 100644 index 0000000..e8e96d0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/init-first.c @@ -0,0 +1,52 @@ +/* Initialization code run first thing by the ELF startup code. Linux/i386. + Copyright (C) 2007-2014 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, see + . */ + +#ifdef SHARED +# include +# include +# include +# include + +long int (*__vdso_clock_gettime) (clockid_t, struct timespec *) + __attribute__ ((nocommon)); +strong_alias (__vdso_clock_gettime, __GI___vdso_clock_gettime attribute_hidden) + + +long int fallback_clock_gettime(clockid_t id, struct timespec *tp) +{ + INTERNAL_SYSCALL_DECL (err); + return INTERNAL_SYSCALL (clock_gettime, err, 2, id, tp); +} + + +static inline void +_libc_vdso_platform_setup (void) +{ + PREPARE_VERSION (linux26, "LINUX_2.6", 61765110); + + void *p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26); + if (p == NULL) + p = fallback_clock_gettime; + PTR_MANGLE (p); + __GI___vdso_clock_gettime = p; +} + +# define VDSO_SETUP _libc_vdso_platform_setup +#endif + +#include diff --git a/sysdeps/unix/sysv/linux/i386/time.c b/sysdeps/unix/sysv/linux/i386/time.c new file mode 100644 index 0000000..f1a4c66 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/time.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2001-2014 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, see + . */ + +#ifdef SHARED +/* Redefine time so that the compiler won't complain about the type + mismatch with the IFUNC selector in strong_alias, below. */ +#undef time +#define time __redirect_time +#include +#include + +static time_t +fallback_time (time_t *t) +{ + INTERNAL_SYSCALL_DECL (err); + return INTERNAL_SYSCALL (time, err, 1, t); +} + + +#include + +/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle + ifunc symbol properly. */ +extern __typeof (__redirect_time) __libc_time; +void *time_ifunc (void) __asm__ ("__libc_time"); + +void * +time_ifunc (void) +{ + PREPARE_VERSION (linux26, "LINUX_2.6", 61765110); + + /* If the vDSO is not available we fall back on the old syscall. */ + return _dl_vdso_vsym ("__vdso_time", &linux26) ?: (void *) fallback_time; +} +__asm (".type __libc_time, %gnu_indirect_function"); + +#undef time +strong_alias (__libc_time, time) +libc_hidden_ver (__libc_time, time) + +#else + +# include +# include + +time_t +time (time_t *t) +{ + INTERNAL_SYSCALL_DECL (err); + return INTERNAL_SYSCALL (time, err, 1, t); +} + +#endif diff --git a/sysdeps/unix/sysv/linux/i386/timespec_get.c b/sysdeps/unix/sysv/linux/i386/timespec_get.c new file mode 100644 index 0000000..6eb83c1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/timespec_get.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2002-2014 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, see + . */ + +#include "bits/libc-vdso.h" + +#ifdef SHARED +# define INTERNAL_GETTIME(id, tp) \ + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \ + PTR_DEMANGLE (f); \ + f (id, tp); }) +#endif + +#include "../timespec_get.c"