[RFC] [PATCH] MIPS: Add VDSO support
Zubair Lutfullah Kakakhel
Zubair.Kakakhel@imgtec.com
Fri Apr 8 11:57:00 GMT 2016
+ Joseph.
Apologies. I forgot to cc you initially.
Regards,
ZubairLK
On 30/03/16 16:10, Zubair Lutfullah Kakakhel wrote:
> From: Alex Smith <alex.smith@imgtec.com>
>
> This patch adds support for using the implementations of gettimeofday()
> and clock_gettime() provided by the kernel in the VDSO. The VDSO will
> always provide clock_gettime() as CLOCK_{REALTIME,MONOTONIC}_COARSE can
> be implemented regardless of platform. CLOCK_{REALTIME,MONOTONIC}, along
> with gettimeofday(), are only implemented on platforms which make use of
> either the CP0 count or GIC as their clocksource. On other platforms,
> the VDSO does not provide the __vdso_gettimeofday symbol, as it is
> never useful.
>
> The VDSO functions return ENOSYS when they encounter an unsupported
> request, in which case glibc should fall back to the standard syscall.
>
> * sysdeps/unix/sysv/linux/mips/Makefile (sysdep_routines):
> Include dl-vdso.
> * sysdeps/unix/sysv/linux/mips/Versions: Add
> __vdso_clock_gettime.
> * sysdeps/unix/sysv/linux/mips/init-first.c: New file.
> * sysdeps/unix/sysv/linux/mips/libc-vdso.h: New file.
> * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h:
> (INTERNAL_VSYSCALL_CALL): Define to be compatible with MIPS
> definitions of INTERNAL_SYSCALL_{ERROR_P,ERRNO}.
> (HAVE_CLOCK_GETTIME_VSYSCALL): Define.
> (HAVE_GETTIMEOFDAY_VSYSCALL): Define.
> * sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h: Likewise.
> * sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h: Likewise.
>
> ---
> Hi,
>
> The kernel patches for vdso support are already upstream.
>
> I'm picking up this patch to upstream vdso support for MIPS in glibc.
>
> Rebased this patch on glibc-2.23
>
> Tested with upstream kernel 4.5 and QEMU emulating Malta.
>
> ./vdsotest gettimeofday bench
> gettimeofday: syscall: 1021 nsec/call
> gettimeofday: libc: 262 nsec/call
> gettimeofday: vdso: 174 nsec/call
>
> Regards,
> ZubairLK
>
> ---
> sysdeps/unix/sysv/linux/mips/Makefile | 2 ++
> sysdeps/unix/sysv/linux/mips/Versions | 4 +++
> sysdeps/unix/sysv/linux/mips/init-first.c | 44 ++++++++++++++++++++++++
> sysdeps/unix/sysv/linux/mips/libc-vdso.h | 33 ++++++++++++++++++
> sysdeps/unix/sysv/linux/mips/mips32/sysdep.h | 16 +++++++++
> sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h | 17 +++++++++
> sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h | 17 +++++++++
> 7 files changed, 133 insertions(+)
> create mode 100644 sysdeps/unix/sysv/linux/mips/init-first.c
> create mode 100644 sysdeps/unix/sysv/linux/mips/libc-vdso.h
>
> diff --git a/sysdeps/unix/sysv/linux/mips/Makefile b/sysdeps/unix/sysv/linux/mips/Makefile
> index 8127025..c6729c1 100644
> --- a/sysdeps/unix/sysv/linux/mips/Makefile
> +++ b/sysdeps/unix/sysv/linux/mips/Makefile
> @@ -96,6 +96,8 @@ ifeq ($(subdir),elf)
> ifeq ($(build-shared),yes)
> # This is needed for DSO loading from static binaries.
> sysdep-dl-routines += dl-static
> +
> +sysdep_routines += dl-vdso
> endif
> endif
>
> diff --git a/sysdeps/unix/sysv/linux/mips/Versions b/sysdeps/unix/sysv/linux/mips/Versions
> index a56322a..453f276 100644
> --- a/sysdeps/unix/sysv/linux/mips/Versions
> +++ b/sysdeps/unix/sysv/linux/mips/Versions
> @@ -37,4 +37,8 @@ libc {
> GLIBC_2.11 {
> fallocate64;
> }
> + GLIBC_PRIVATE {
> + # nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime).
> + __vdso_clock_gettime;
> + }
> }
> diff --git a/sysdeps/unix/sysv/linux/mips/init-first.c b/sysdeps/unix/sysv/linux/mips/init-first.c
> new file mode 100644
> index 0000000..46dba69
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/init-first.c
> @@ -0,0 +1,44 @@
> +/* Initialization code run first thing by the ELF startup code.
> + 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
> + <http://www.gnu.org/licenses/>. */
> +
> +#ifdef SHARED
> +# include <dl-vdso.h>
> +# include <libc-vdso.h>
> +
> +int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *) attribute_hidden;
> +int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
> +
> +static inline void
> +_libc_vdso_platform_setup (void)
> +{
> + PREPARE_VERSION_KNOWN (linux26, LINUX_2_6);
> +
> + void *p = _dl_vdso_vsym ("__vdso_gettimeofday", &linux26);
> + PTR_MANGLE (p);
> + VDSO_SYMBOL (gettimeofday) = p;
> +
> + p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
> + PTR_MANGLE (p);
> + VDSO_SYMBOL (clock_gettime) = p;
> +}
> +
> +# define VDSO_SETUP _libc_vdso_platform_setup
> +#endif
> +
> +#include <csu/init-first.c>
> diff --git a/sysdeps/unix/sysv/linux/mips/libc-vdso.h b/sysdeps/unix/sysv/linux/mips/libc-vdso.h
> new file mode 100644
> index 0000000..1580de8
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/libc-vdso.h
> @@ -0,0 +1,33 @@
> +/* VDSO function pointer declarations.
> + 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
> + <http://www.gnu.org/licenses/>. */
> +
> +#ifndef _LIBC_VDSO_H
> +#define _LIBC_VDSO_H
> +
> +#ifdef SHARED
> +
> +# include <sysdep-vdso.h>
> +
> +extern int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *)
> + attribute_hidden;
> +extern int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
> +
> +#endif
> +
> +#endif /* _LIBC_VDSO_H */
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
> index 2160df7..2335409 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
> @@ -371,6 +371,22 @@
> #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
> "$14", "$15", "$24", "$25", "hi", "lo", "memory"
>
> +/* 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; \
> + })
> +
> +/* List of system calls which are supported as vsyscalls. */
> +#define HAVE_CLOCK_GETTIME_VSYSCALL 1
> +#define HAVE_GETTIMEOFDAY_VSYSCALL 1
> +
> #endif /* __ASSEMBLER__ */
>
> /* Pointer mangling is not yet supported for MIPS. */
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
> index 466dcde..661b3dc 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
> @@ -295,6 +295,23 @@
>
> #define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
> "$14", "$15", "$24", "$25", "hi", "lo", "memory"
> +
> +/* 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; \
> + })
> +
> +/* List of system calls which are supported as vsyscalls. */
> +#define HAVE_CLOCK_GETTIME_VSYSCALL 1
> +#define HAVE_GETTIMEOFDAY_VSYSCALL 1
> +
> #endif /* __ASSEMBLER__ */
>
> /* Pointer mangling is not yet supported for MIPS. */
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
> index db8b237..476eca3 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
> @@ -291,6 +291,23 @@
>
> #define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
> "$14", "$15", "$24", "$25", "hi", "lo", "memory"
> +
> +/* 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; \
> + })
> +
> +/* List of system calls which are supported as vsyscalls. */
> +#define HAVE_CLOCK_GETTIME_VSYSCALL 1
> +#define HAVE_GETTIMEOFDAY_VSYSCALL 1
> +
> #endif /* __ASSEMBLER__ */
>
> /* Pointer mangling is not yet supported for MIPS. */
>
More information about the Libc-alpha
mailing list