Skip to content

Commit

Permalink
Add x86 32 bit vDSO time function support
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Adhemerval Zanella committed Jan 12, 2015
1 parent 49a9f6a commit ca677d3
Show file tree
Hide file tree
Showing 17 changed files with 340 additions and 118 deletions.
27 changes: 27 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
39 changes: 39 additions & 0 deletions sysdeps/unix/sysv/linux/i386/gettimeofday.c
Original file line number Diff line number Diff line change
@@ -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>
52 changes: 52 additions & 0 deletions sysdeps/unix/sysv/linux/i386/init-first.c
Original file line number Diff line number Diff line change
@@ -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>
37 changes: 37 additions & 0 deletions sysdeps/unix/sysv/linux/i386/time.c
Original file line number Diff line number Diff line change
@@ -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>
4 changes: 4 additions & 0 deletions sysdeps/unix/sysv/linux/x86/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
34 changes: 34 additions & 0 deletions sysdeps/unix/sysv/linux/x86/clock_gettime.c
Original file line number Diff line number Diff line change
@@ -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>
54 changes: 54 additions & 0 deletions sysdeps/unix/sysv/linux/x86/gettimeofday.c
Original file line number Diff line number Diff line change
@@ -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)
File renamed without changes.
49 changes: 49 additions & 0 deletions sysdeps/unix/sysv/linux/x86/time.c
Original file line number Diff line number Diff line change
@@ -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
29 changes: 29 additions & 0 deletions sysdeps/unix/sysv/linux/x86/timespec_get.c
Original file line number Diff line number Diff line change
@@ -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>
4 changes: 0 additions & 4 deletions sysdeps/unix/sysv/linux/x86_64/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,3 @@ endif
ifeq ($(subdir),misc)
gen-as-const-headers += sigaltstack-offsets.sym
endif

ifeq ($(subdir),elf)
sysdep_routines += dl-vdso
endif
20 changes: 0 additions & 20 deletions sysdeps/unix/sysv/linux/x86_64/clock_gettime.c

This file was deleted.

Loading

0 comments on commit ca677d3

Please sign in to comment.