Add x86 32 bit vDSO time function support

Linux 3.15 adds support for clock_gettime, gettimeofday, and time vDSO
(commit id 37c975545ec63320789962bf307f000f08fabd48).  This patch adds
GLIBC supports to use such symbol when they are avaiable.

Along with x86 vDSO support, this patch cleanup x86_64 code by moving
all common code to x86 common folder.  Only init-first.c is different
between implementations.
This commit is contained in:
Adhemerval Zanella 2014-06-27 14:00:18 -07:00
parent 49a9f6ab64
commit ca677d3c3c
17 changed files with 340 additions and 118 deletions

View File

@ -1,3 +1,30 @@
2015-01-12 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Stefani Seibold <stefani@seibold.net>
* sysdeps/unix/sysv/linux/x86_64/Makefile [$(subdir) = elf]
(sysdep_routines): Add dl-vdso here, ...
* sysdeps/unix/sysv/linux/x86/Makefile [$(subdir) = elf]
(sysdep_routines): ... not here.
* sysdeps/unix/sysv/linux/i386/gettimeofday.c: New file: set syscall
fallback when vDSO is not presented.
* sysdeps/unix/sysv/linux/x86_64/init-first.c (__vdso_clock_gettime):
Define with libc_hidden_proto/libc_hidden_data_def definitions.
(_libc_vdso_platform_setup): Rename to __vdso_platform_setup.
* sysdeps/unix/sysv/linux/i386/init-first.c: New file: likewise.
* sysdeps/unix/sysv/linux/i386/time.c: New file: likewise.
* sysdeps/unix/sysv/linux/x86_64/bits/libc-vdso.h: Moved to ...
* sysdeps/unix/sysv/linux/x86/libc-vdso.h: ... here.
* sysdeps/unix/sysv/linux/x86_64/clock_gettime.c: Move to ...
* sysdeps/unix/sysv/linux/x86/clock_gettime.c: ... here.
* sysdeps/unix/sysv/linux/x86_64/gettimeofday.c: Move to ...
* sysdeps/unix/sysv/linux/x86/gettimeofday.c: ... here. Also added
fallback configurable symbol when vDSO is not available.
* sysdeps/unix/sysv/linux/x86_64/time.c: Move to ...
* sysdeps/unix/sysv/linux/x86/time.c: ... here. Also refactored to
be able to redefine fallback symbol when vDSO is not available.
* sysdeps/unix/sysv/linux/x86_64/timespec_get.c: Move to ...
* sysdeps/unix/sysv/linux/x86/timespec_get.c: ... here.
2015-01-12 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
* sysdeps/powerpc/nptl/tls.h (tcbhead_t): Add tm_capable field.

View File

@ -0,0 +1,39 @@
/* gettimeofday - get the time. Linux/i386 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
<http://www.gnu.org/licenses/>. */
#include <sys/time.h>
#ifdef SHARED
# include <dl-vdso.h>
# include <errno.h>
/* If the vDSO is not available we fall back on the syscall. */
static int
__gettimeofday_syscall (struct timeval *tv, struct timezone *tz)
{
return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
}
# define GETTIMEOFAY_FALLBACK (void*) (&__gettimeofday_syscall)
# undef libc_ifunc_hidden_def
# define libc_ifunc_hidden_def(name) \
libc_ifunc_hidden_def1 (__GI_##name, __gettimeofday_syscall)
#endif
#include <sysdeps/unix/sysv/linux/x86/gettimeofday.c>

View File

@ -0,0 +1,52 @@
/* Initialization code run first thing by the ELF startup code. Linux/i386.
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 <time.h>
# include <sysdep.h>
# include <dl-vdso.h>
# include <libc-vdso.h>
long int (*__vdso_clock_gettime) (clockid_t, struct timespec *)
__attribute__ ((nocommon));
libc_hidden_proto (__vdso_clock_gettime)
libc_hidden_data_def (__vdso_clock_gettime)
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);
}
static inline void
__vdso_platform_setup (void)
{
PREPARE_VERSION_KNOWN (linux26, LINUX_2_6);
void *p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
if (p == NULL)
p = clock_gettime_syscall;
PTR_MANGLE (p);
__vdso_clock_gettime = p;
}
# define VDSO_SETUP __vdso_platform_setup
#endif
#include <csu/init-first.c>

View File

@ -0,0 +1,37 @@
/* time -- Get number of seconds since Epoch. Linux/i386 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
<http://www.gnu.org/licenses/>. */
#ifdef SHARED
# include <dl-vdso.h>
# include <errno.h>
/* If the vDSO is not available we fall back on the old vsyscall. */
static time_t
__time_syscall (time_t *t)
{
INTERNAL_SYSCALL_DECL (err);
return INTERNAL_SYSCALL (time, err, 1, t);
}
# define TIME_FALLBACK (void*) &__time_syscall
# undef libc_ifunc_hidden_def
# define libc_ifunc_hidden_def(name) \
libc_ifunc_hidden_def1 (__GI_##name, __time_syscall)
#endif
#include <sysdeps/unix/sysv/linux/x86/time.c>

View File

@ -19,3 +19,7 @@ libpthread-sysdep_routines += init-arch
libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
elision-trylock
endif
ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
endif

View File

@ -0,0 +1,34 @@
/* Get the current value of a clock. Linux/x86 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
<http://www.gnu.org/licenses/>. */
#include <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; })
#endif
#include <sysdeps/unix/sysv/linux/clock_gettime.c>

View File

@ -0,0 +1,54 @@
/* gettimeofday - get the time. Linux/x86 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
<http://www.gnu.org/licenses/>. */
#include <sys/time.h>
#ifdef SHARED
# include <dl-vdso.h>
void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday");
void *
gettimeofday_ifunc (void)
{
PREPARE_VERSION_KNOWN (linux26, LINUX_2_6);
/* If the vDSO is not available we fall back on the old vsyscall. */
return (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26)
?: GETTIMEOFAY_FALLBACK);
}
asm (".type __gettimeofday, %gnu_indirect_function");
libc_ifunc_hidden_def(__gettimeofday)
#else
# include <sysdep.h>
# include <errno.h>
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)

View File

@ -0,0 +1,49 @@
/* time -- Get number of seconds since Epoch. Linux/x86 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
<http://www.gnu.org/licenses/>. */
#include <time.h>
#ifdef SHARED
#include <dl-vdso.h>
void *time_ifunc (void) __asm__ ("time");
void *
time_ifunc (void)
{
PREPARE_VERSION_KNOWN (linux26, LINUX_2_6);
return _dl_vdso_vsym ("__vdso_time", &linux26) ?: TIME_FALLBACK;
}
asm (".type time, %gnu_indirect_function");
libc_ifunc_hidden_def(time)
#else
# include <sysdep.h>
time_t
time (time_t *t)
{
INTERNAL_SYSCALL_DECL (err);
return INTERNAL_SYSCALL (time, err, 1, t);
}
#endif

View File

@ -0,0 +1,29 @@
/* timespec_get -- returns the calendar time based on a given time base.
Linux/x86 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
<http://www.gnu.org/licenses/>. */
#include <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 <sysdeps/unix/sysv/linux/timespec_get.c>

View File

@ -13,7 +13,3 @@ endif
ifeq ($(subdir),misc)
gen-as-const-headers += sigaltstack-offsets.sym
endif
ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
endif

View File

@ -1,20 +0,0 @@
#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"

View File

@ -18,42 +18,9 @@
#include <sys/time.h>
#ifdef SHARED
# include <dl-vdso.h>
/* If the vDSO is not available we fall back on the old vsyscall. */
# define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000ul
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 vsyscall. */
return (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26)
?: (void *) VSYSCALL_ADDR_vgettimeofday);
}
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 <sysdep.h>
# include <errno.h>
int
__gettimeofday (struct timeval *tv, struct timezone *tz)
{
return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
}
libc_hidden_def (__gettimeofday)
# define GETTIMEOFAY_FALLBACK (void*)VSYSCALL_ADDR_vgettimeofday
#endif
weak_alias (__gettimeofday, gettimeofday)
libc_hidden_weak (gettimeofday)
#include <sysdeps/unix/sysv/linux/x86/gettimeofday.c>

View File

@ -20,20 +20,20 @@
# include <time.h>
# include <sysdep.h>
# include <dl-vdso.h>
# include <bits/libc-vdso.h>
# include <libc-vdso.h>
long int (*__vdso_clock_gettime) (clockid_t, struct timespec *)
__attribute__ ((nocommon));
strong_alias (__vdso_clock_gettime, __GI___vdso_clock_gettime attribute_hidden)
libc_hidden_proto (__vdso_clock_gettime)
libc_hidden_data_def (__vdso_clock_gettime)
long int (*__vdso_getcpu) (unsigned *, unsigned *, void *) attribute_hidden;
extern long int __syscall_clock_gettime (clockid_t, struct timespec *);
static inline void
_libc_vdso_platform_setup (void)
__vdso_platform_setup (void)
{
PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
@ -41,7 +41,7 @@ _libc_vdso_platform_setup (void)
if (p == NULL)
p = __syscall_clock_gettime;
PTR_MANGLE (p);
__GI___vdso_clock_gettime = p;
__vdso_clock_gettime = p;
p = _dl_vdso_vsym ("__vdso_getcpu", &linux26);
/* If the vDSO is not available we fall back on the old vsyscall. */
@ -52,7 +52,7 @@ _libc_vdso_platform_setup (void)
__vdso_getcpu = p;
}
# define VDSO_SETUP _libc_vdso_platform_setup
# define VDSO_SETUP __vdso_platform_setup
#endif
#include <csu/init-first.c>

View File

@ -16,45 +16,9 @@
<http://www.gnu.org/licenses/>. */
#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 <time.h>
#include <dl-vdso.h>
/* If the vDSO is not available we fall back on the old vsyscall. */
#define VSYSCALL_ADDR_vtime 0xffffffffff600400
/* 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 vsyscall. */
return _dl_vdso_vsym ("__vdso_time", &linux26) ?: (void *) VSYSCALL_ADDR_vtime;
}
__asm (".type __libc_time, %gnu_indirect_function");
#undef time
strong_alias (__libc_time, time)
libc_hidden_ver (__libc_time, time)
#else
# include <time.h>
# include <sysdep.h>
time_t
time (time_t *t)
{
INTERNAL_SYSCALL_DECL (err);
return INTERNAL_SYSCALL (time, err, 1, t);
}
#define TIME_FALLBACK (void*)VSYSCALL_ADDR_vtime
#endif
#include <sysdeps/unix/sysv/linux/x86/time.c>

View File

@ -1,10 +0,0 @@
#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"

View File

@ -18,7 +18,7 @@
#ifdef SHARED
# include <dl-vdso.h>
# include <bits/libc-vdso.h>
# include <libc-vdso.h>
long int (*__vdso_clock_gettime) (clockid_t, struct timespec *)
__attribute__ ((nocommon));