[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