From patchwork Fri Apr 3 17:25:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Lynch X-Patchwork-Id: 5998 Received: (qmail 86541 invoked by alias); 3 Apr 2015 17:25:42 -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 86532 invoked by uid 89); 3 Apr 2015 17:25:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com From: Nathan Lynch To: Subject: [RFC/PATCH] ARM: VDSO support Date: Fri, 3 Apr 2015 12:25:34 -0500 Message-ID: <1428081934-22419-1-git-send-email-nathan_lynch@codesourcery.com> MIME-Version: 1.0 Future versions of Linux on 32-bit ARM are expected to provide fast user-space implementations of the following system calls: - gettimeofday - clock_gettime The kernel implementation depends on the ARMv7 Generic Timers Extension to accelerate these system calls. So CPUs such as Cortex-A15 and -A7 benefit, while Cortex-A9, -A8, and pre-v7 CPUs do not. The kernel support is currently in linux-next and is slated for inclusion in Linux 4.1. I plan to ping or resubmit this patch once Linux 4.1 is released, but would appreciate any preliminary review in the meantime. For reference, the current kernel patch submission may be found here: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332573.html This patch adds support for the ARM VDSO to glibc. I have run make check on OMAP5 using kernels with and without the VDSO, with no new failures. ChangeLog: 2015-04-03 Nathan Lynch * sysdeps/unix/sysv/linux/arm/Makefile (sysdep_routines): Include dl-vdso. * sysdeps/unix/sysv/linux/arm/Versions: Add __vdso_clock_gettime and __vdso_gettimeofday. * sysdeps/unix/sysv/linux/arm/libc-vdso.h: New file: declare __vdso_clock_gettime, __vdso_gettimeofday. * sysdeps/unix/sysv/linux/arm/init-first.c: New file: Set __vdso_gettimeofday, __vdso_clock_gettime to vdso entry points if available. * sysdeps/unix/sysv/linux/arm/clock_gettime.c: New file: define SYSCALL_GETTIME, use __vdso_clock_gettime if set. * sysdeps/unix/sysv/linux/arm/gettimeofday.c: New file: define __gettimeofday, use __vdso_gettimeofday if set. --- sysdeps/unix/sysv/linux/arm/Makefile | 1 + sysdeps/unix/sysv/linux/arm/Versions | 2 + sysdeps/unix/sysv/linux/arm/clock_gettime.c | 48 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/arm/gettimeofday.c | 62 +++++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/arm/init-first.c | 52 ++++++++++++++++++++++++ sysdeps/unix/sysv/linux/arm/libc-vdso.h | 32 +++++++++++++++ 6 files changed, 197 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/arm/clock_gettime.c create mode 100644 sysdeps/unix/sysv/linux/arm/gettimeofday.c create mode 100644 sysdeps/unix/sysv/linux/arm/init-first.c create mode 100644 sysdeps/unix/sysv/linux/arm/libc-vdso.h diff --git a/sysdeps/unix/sysv/linux/arm/Makefile b/sysdeps/unix/sysv/linux/arm/Makefile index 50410b67b5fc..0ed6f088d574 100644 --- a/sysdeps/unix/sysv/linux/arm/Makefile +++ b/sysdeps/unix/sysv/linux/arm/Makefile @@ -1,4 +1,5 @@ ifeq ($(subdir),elf) +sysdep_routines += dl-vdso sysdep-rtld-routines += aeabi_read_tp libc-do-syscall endif diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions index a251b0fd7d87..7bc5936372bb 100644 --- a/sysdeps/unix/sysv/linux/arm/Versions +++ b/sysdeps/unix/sysv/linux/arm/Versions @@ -10,5 +10,7 @@ libc { GLIBC_PRIVATE { # A copy of sigaction lives in libpthread, and needs these. __default_sa_restorer; __default_rt_sa_restorer; + __vdso_clock_gettime; + __vdso_gettimeofday; } } diff --git a/sysdeps/unix/sysv/linux/arm/clock_gettime.c b/sysdeps/unix/sysv/linux/arm/clock_gettime.c new file mode 100644 index 000000000000..958db42c6b7c --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/clock_gettime.c @@ -0,0 +1,48 @@ +/* Get the current value of a clock. Linux/arm version. + Copyright (C) 2015 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 + +static long int +clock_gettime_syscall (clockid_t id, struct timespec *tp) +{ + INTERNAL_SYSCALL_DECL (err); + return INTERNAL_SYSCALL (clock_gettime, err, 2, id, tp); +} + + +# define SYSCALL_GETTIME(id, tp) \ + ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \ + long int v_ret; \ + PTR_DEMANGLE (f); \ + if (f) \ + v_ret = (*f) (id, tp); \ + else \ + v_ret = clock_gettime_syscall(id, tp); \ + if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); \ + v_ret = -1; \ + } \ + v_ret; }) +#endif + +#include diff --git a/sysdeps/unix/sysv/linux/arm/gettimeofday.c b/sysdeps/unix/sysv/linux/arm/gettimeofday.c new file mode 100644 index 000000000000..3665ade8f226 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/gettimeofday.c @@ -0,0 +1,62 @@ +/* gettimeofday - get the time. Linux/arm version. + Copyright (C) 2015 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 +#include + +#ifdef SHARED + +# include + +static long int +gettimeofday_syscall (struct timeval *tv, struct timezone *tz) +{ + INTERNAL_SYSCALL_DECL (err); + return INTERNAL_SYSCALL (gettimeofday, err, 2, tv, tz); +} + +int +__gettimeofday (struct timeval *tv, struct timezone *tz) +{ + long int (*f) (struct timeval *, struct timezone *) = __vdso_gettimeofday; + long int v_ret; + + PTR_DEMANGLE (f); + if (f) + v_ret = (*f) (tv, tz); + else + v_ret = gettimeofday_syscall(tv, tz); + if (INTERNAL_SYSCALL_ERROR_P (v_ret, )) { + __set_errno (INTERNAL_SYSCALL_ERRNO (v_ret, )); + v_ret = -1; + } + return v_ret; +} + +#else + +int +__gettimeofday (struct timeval *tv, struct timezone *tz) +{ + return INLINE_SYSCALL (gettimeofday, 2, tv, tz); +} + +#endif +libc_hidden_def (__gettimeofday) +weak_alias (__gettimeofday, gettimeofday) +libc_hidden_weak (gettimeofday) diff --git a/sysdeps/unix/sysv/linux/arm/init-first.c b/sysdeps/unix/sysv/linux/arm/init-first.c new file mode 100644 index 000000000000..c512d3a3e795 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/init-first.c @@ -0,0 +1,52 @@ +/* Initialization code run first thing by the ELF startup code. Linux/arm. + Copyright (C) 2015 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)); +libc_hidden_proto (__vdso_clock_gettime) +libc_hidden_data_def (__vdso_clock_gettime) + +long int (*__vdso_gettimeofday) (struct timeval *tv, struct timezone *tz) + __attribute__ ((nocommon)); +libc_hidden_proto (__vdso_gettimeofday) +libc_hidden_data_def (__vdso_gettimeofday) + +static inline void +__vdso_platform_setup (void) +{ + PREPARE_VERSION_KNOWN (linux26, LINUX_2_6); + + void *p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26); + PTR_MANGLE (p); + __vdso_clock_gettime = p; + + p = _dl_vdso_vsym ("__vdso_gettimeofday", &linux26); + PTR_MANGLE (p); + __vdso_gettimeofday = p; +} + +# define VDSO_SETUP __vdso_platform_setup +#endif + +#include diff --git a/sysdeps/unix/sysv/linux/arm/libc-vdso.h b/sysdeps/unix/sysv/linux/arm/libc-vdso.h new file mode 100644 index 000000000000..622ef4dd62c3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/libc-vdso.h @@ -0,0 +1,32 @@ +/* Resolve function pointers to VDSO functions. + Copyright (C) 2015 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 *); +extern long int (*__vdso_gettimeofday) (struct timeval *, struct timezone *); + +#endif + +#endif /* _LIBC_VDSO_H */