mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
2005-12-08 Steven Munroe <sjmunroe@us.ibm.com>
Tom Gall <tom_gall@vnet.ibm.com> * elf/rtld.c (dl_main): Initialize l_local_scope for sysinfo_map. * sysdeps/powerpc/elf/libc-start.c: Move this... * sysdeps/unix/sysv/linux/powerpc/libc-start.c: ...to here. * sysdeps/powerpc/powerpc32/dl-start.S: Add _dl_main_dispatch label. * sysdeps/powerpc/powerpc32/hp-timing.h: New file. * sysdeps/unix/sysv/linux/powerpc/Versions: New file. * sysdeps/unix/sysv/linux/clock_getres.c: If HAVE_CLOCK_GETRES_VSYSCALL is not defined, redefine INTERNAL_VSYSCALL and INLINE_VSYSCALL to INTERNAL_SYSCALL and INLINE_SYSCALL respectively. Otherwise include <bits/libc-vdso.h>. Use INLINE_VSYSCALL and INTERNAL_SYSCALL instead of the normal versions throughout the code. * sysdeps/unix/sysv/linux/clock_gettime.c: Likewise if HAVE_CLOCK_GETTIME_VSYSCALL is defined. * sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h: New file. * sysdeps/unix/sysv/linux/powerpc/dl-vdso.c: New file. * sysdeps/unix/sysv/linux/powerpc/dl-vdso.h: New file. * sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c: Use vDSO. * sysdeps/unix/sysv/linux/powerpc/gettimeofday.c: New file. * sysdeps/unix/sysv/linux/powerpc/Makefile: Add dl-vdso to routines. * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Define INLINE_VSYSCALL, INTERNAL_VSYSCALL, INTERNAL_SYSCALL_NCS, INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK, HAVE_CLOCK_GETRES_VSYSCALL, and HAVE_CLOCK_GETTIME_VSYSCALL. * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise.
This commit is contained in:
parent
4e54d7e476
commit
8c2e201ba9
28
ChangeLog
28
ChangeLog
@ -1,3 +1,31 @@
|
||||
2005-12-08 Steven Munroe <sjmunroe@us.ibm.com>
|
||||
Tom Gall <tom_gall@vnet.ibm.com>
|
||||
|
||||
* elf/rtld.c (dl_main): Initialize l_local_scope for sysinfo_map.
|
||||
* sysdeps/powerpc/elf/libc-start.c: Move this...
|
||||
* sysdeps/unix/sysv/linux/powerpc/libc-start.c: ...to here.
|
||||
* sysdeps/powerpc/powerpc32/dl-start.S: Add _dl_main_dispatch label.
|
||||
* sysdeps/powerpc/powerpc32/hp-timing.h: New file.
|
||||
* sysdeps/unix/sysv/linux/powerpc/Versions: New file.
|
||||
* sysdeps/unix/sysv/linux/clock_getres.c: If HAVE_CLOCK_GETRES_VSYSCALL
|
||||
is not defined, redefine INTERNAL_VSYSCALL and INLINE_VSYSCALL to
|
||||
INTERNAL_SYSCALL and INLINE_SYSCALL respectively. Otherwise include
|
||||
<bits/libc-vdso.h>. Use INLINE_VSYSCALL and INTERNAL_SYSCALL instead
|
||||
of the normal versions throughout the code.
|
||||
* sysdeps/unix/sysv/linux/clock_gettime.c: Likewise if
|
||||
HAVE_CLOCK_GETTIME_VSYSCALL is defined.
|
||||
* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h: New file.
|
||||
* sysdeps/unix/sysv/linux/powerpc/dl-vdso.c: New file.
|
||||
* sysdeps/unix/sysv/linux/powerpc/dl-vdso.h: New file.
|
||||
* sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c: Use vDSO.
|
||||
* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c: New file.
|
||||
* sysdeps/unix/sysv/linux/powerpc/Makefile: Add dl-vdso to routines.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Define
|
||||
INLINE_VSYSCALL, INTERNAL_VSYSCALL, INTERNAL_SYSCALL_NCS,
|
||||
INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK, HAVE_CLOCK_GETRES_VSYSCALL,
|
||||
and HAVE_CLOCK_GETTIME_VSYSCALL.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise.
|
||||
|
||||
2005-12-29 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h [ASSEMBLER]:
|
||||
|
@ -1307,6 +1307,13 @@ ld.so does not support TLS, but program uses it!\n");
|
||||
_dl_setup_hash (l);
|
||||
l->l_relocated = 1;
|
||||
|
||||
/* Initialize l_local_scope to contain just this map. This allows
|
||||
the use of dl_lookup_symbol_x to resolve symbols within the vdso.
|
||||
So we create a single entry list pointing to l_real as its only
|
||||
element */
|
||||
l->l_local_scope[0]->r_nlist = 1;
|
||||
l->l_local_scope[0]->r_list = &l->l_real;
|
||||
|
||||
/* Now that we have the info handy, use the DSO image's soname
|
||||
so this object can be looked up by name. Note that we do not
|
||||
set l_name here. That field gives the file name of the DSO,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Machine-dependent ELF startup code. PowerPC version.
|
||||
Copyright (C) 1995-2000, 2002, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2000, 2002, 2004, 2005 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
|
||||
@ -98,6 +98,7 @@ ENTRY(_dl_start_user)
|
||||
Take the opportunity to clear LR, so anyone who accidentally returns
|
||||
from _start gets SEGV. Also clear the next few words of the stack. */
|
||||
|
||||
ENTRY(_dl_main_dispatch)
|
||||
li r31,0
|
||||
stw r31,0(r1)
|
||||
mtlr r31
|
||||
|
82
sysdeps/powerpc/powerpc32/hp-timing.h
Normal file
82
sysdeps/powerpc/powerpc32/hp-timing.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* High precision, low overhead timing functions. Linux/PPC32 version.
|
||||
Copyright (C) 2005 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _HP_TIMING_H
|
||||
#define _HP_TIMING_H 1
|
||||
|
||||
|
||||
/* There are no generic definitions for the times. We could write something
|
||||
using the `gettimeofday' system call where available but the overhead of
|
||||
the system call might be too high.
|
||||
|
||||
In case a platform supports timers in the hardware the following macros
|
||||
and types must be defined:
|
||||
|
||||
- HP_TIMING_AVAIL: test for availability.
|
||||
|
||||
- HP_TIMING_INLINE: this macro is non-zero if the functionality is not
|
||||
implemented using function calls but instead uses some inlined code
|
||||
which might simply consist of a few assembler instructions. We have to
|
||||
know this since we might want to use the macros here in places where we
|
||||
cannot make function calls.
|
||||
|
||||
- hp_timing_t: This is the type for variables used to store the time
|
||||
values.
|
||||
|
||||
- HP_TIMING_ZERO: clear `hp_timing_t' object.
|
||||
|
||||
- HP_TIMING_NOW: place timestamp for current time in variable given as
|
||||
parameter.
|
||||
|
||||
- HP_TIMING_DIFF_INIT: do whatever is necessary to be able to use the
|
||||
HP_TIMING_DIFF macro.
|
||||
|
||||
- HP_TIMING_DIFF: compute difference between two times and store it
|
||||
in a third. Source and destination might overlap.
|
||||
|
||||
- HP_TIMING_ACCUM: add time difference to another variable. This might
|
||||
be a bit more complicated to implement for some platforms as the
|
||||
operation should be thread-safe and 64bit arithmetic on 32bit platforms
|
||||
is not.
|
||||
|
||||
- HP_TIMING_ACCUM_NT: this is the variant for situations where we know
|
||||
there are no threads involved.
|
||||
|
||||
- HP_TIMING_PRINT: write decimal representation of the timing value into
|
||||
the given string. This operation need not be inline even though
|
||||
HP_TIMING_INLINE is specified.
|
||||
|
||||
*/
|
||||
|
||||
/* Provide dummy definitions. */
|
||||
#define HP_TIMING_AVAIL (0)
|
||||
#define HP_TIMING_INLINE (0)
|
||||
typedef unsigned long long int hp_timing_t;
|
||||
#define HP_TIMING_ZERO(Var)
|
||||
#define HP_TIMING_NOW(var)
|
||||
#define HP_TIMING_DIFF_INIT()
|
||||
#define HP_TIMING_DIFF(Diff, Start, End)
|
||||
#define HP_TIMING_ACCUM(Sum, Diff)
|
||||
#define HP_TIMING_ACCUM_NT(Sum, Diff)
|
||||
#define HP_TIMING_PRINT(Buf, Len, Val)
|
||||
|
||||
/* Since this implementation is not available we tell the user about it. */
|
||||
#define HP_TIMING_NONAVAIL 1
|
||||
|
||||
#endif /* hp-timing.h */
|
@ -1,5 +1,5 @@
|
||||
/* clock_getres -- Get the resolution of a POSIX clockid_t. Linux version.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005 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
|
||||
@ -24,9 +24,17 @@
|
||||
|
||||
#include "kernel-features.h"
|
||||
|
||||
#ifndef HAVE_CLOCK_GETRES_VSYSCALL
|
||||
# undef INTERNAL_VSYSCALL
|
||||
# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
|
||||
# undef INLINE_VSYSCALL
|
||||
# define INLINE_VSYSCALL INLINE_SYSCALL
|
||||
#else
|
||||
# include <bits/libc-vdso.h>
|
||||
#endif
|
||||
|
||||
#define SYSCALL_GETRES \
|
||||
retval = INLINE_SYSCALL (clock_getres, 2, clock_id, res); \
|
||||
retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, res); \
|
||||
break
|
||||
|
||||
#ifdef __ASSUME_POSIX_TIMERS
|
||||
@ -52,7 +60,7 @@ maybe_syscall_getres (clockid_t clock_id, struct timespec *res)
|
||||
if (!__libc_missing_posix_timers)
|
||||
{
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
|
||||
int r = INTERNAL_VSYSCALL (clock_getres, err, 2, clock_id, res);
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||
return 0;
|
||||
|
||||
@ -109,7 +117,7 @@ maybe_syscall_getres_cpu (clockid_t clock_id, struct timespec *res)
|
||||
if (!__libc_missing_posix_cpu_timers)
|
||||
{
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
|
||||
int r = INTERNAL_VSYSCALL (clock_getres, err, 2, clock_id, res);
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||
return 0;
|
||||
|
||||
@ -128,7 +136,7 @@ maybe_syscall_getres_cpu (clockid_t clock_id, struct timespec *res)
|
||||
{
|
||||
/* Check whether the kernel supports CPU clocks at all.
|
||||
If not, record it for the future. */
|
||||
r = INTERNAL_SYSCALL (clock_getres, err, 2,
|
||||
r = INTERNAL_VSYSCALL (clock_getres, err, 2,
|
||||
MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
|
||||
NULL);
|
||||
if (INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* clock_gettime -- Get current time from a POSIX clockid_t. Linux version.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005 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
|
||||
@ -23,9 +23,17 @@
|
||||
#include "kernel-posix-cpu-timers.h"
|
||||
#include "kernel-features.h"
|
||||
|
||||
#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
|
||||
# undef INTERNAL_VSYSCALL
|
||||
# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
|
||||
# undef INLINE_VSYSCALL
|
||||
# define INLINE_VSYSCALL INLINE_SYSCALL
|
||||
#else
|
||||
# include <bits/libc-vdso.h>
|
||||
#endif
|
||||
|
||||
#define SYSCALL_GETTIME \
|
||||
retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
|
||||
retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \
|
||||
break
|
||||
|
||||
#ifdef __ASSUME_POSIX_TIMERS
|
||||
@ -51,7 +59,7 @@ maybe_syscall_gettime (clockid_t clock_id, struct timespec *tp)
|
||||
if (!__libc_missing_posix_timers)
|
||||
{
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
|
||||
int r = INTERNAL_VSYSCALL (clock_gettime, err, 2, clock_id, tp);
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||
return 0;
|
||||
|
||||
@ -108,7 +116,7 @@ maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp)
|
||||
if (!__libc_missing_posix_cpu_timers)
|
||||
{
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
|
||||
int r = INTERNAL_VSYSCALL (clock_gettime, err, 2, clock_id, tp);
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||
return 0;
|
||||
|
||||
@ -127,7 +135,7 @@ maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp)
|
||||
{
|
||||
/* Check whether the kernel supports CPU clocks at all.
|
||||
If not, record it for the future. */
|
||||
r = INTERNAL_SYSCALL (clock_getres, err, 2,
|
||||
r = INTERNAL_VSYSCALL (clock_getres, err, 2,
|
||||
MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
|
||||
NULL);
|
||||
if (INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||
|
@ -6,3 +6,7 @@ endif
|
||||
ifeq ($(subdir),stdlib)
|
||||
gen-as-const-headers += ucontext_i.sym
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
routines += dl-vdso
|
||||
endif
|
||||
|
7
sysdeps/unix/sysv/linux/powerpc/Versions
Normal file
7
sysdeps/unix/sysv/linux/powerpc/Versions
Normal file
@ -0,0 +1,7 @@
|
||||
libc {
|
||||
GLIBC_PRIVATE {
|
||||
__vdso_get_tbfreq;
|
||||
__vdso_clock_gettime;
|
||||
__vdso_clock_getres;
|
||||
}
|
||||
}
|
36
sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
Normal file
36
sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* Resolve function pointers to VDSO functions.
|
||||
Copyright (C) 2005 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
|
||||
#ifndef _LIBC_VDSO_H
|
||||
#define _LIBC_VDSO_H
|
||||
|
||||
#ifdef SHARED
|
||||
|
||||
extern void *__vdso_gettimeofday;
|
||||
|
||||
extern void *__vdso_clock_gettime;
|
||||
|
||||
extern void *__vdso_clock_getres;
|
||||
|
||||
extern void *__vdso_get_tbfreq;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _LIBC_VDSO_H */
|
59
sysdeps/unix/sysv/linux/powerpc/dl-vdso.c
Normal file
59
sysdeps/unix/sysv/linux/powerpc/dl-vdso.c
Normal file
@ -0,0 +1,59 @@
|
||||
/* ELF symbol resolve functions for VDSO objects.
|
||||
Copyright (C) 2005 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include <dl-hash.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
|
||||
void *
|
||||
internal_function
|
||||
_dl_vdso_vsym (const char *name, const char *version)
|
||||
{
|
||||
struct link_map *map = GLRO (dl_sysinfo_map);
|
||||
void *value = NULL;
|
||||
|
||||
|
||||
if (map != NULL)
|
||||
{
|
||||
/* Use a WEAK REF so we don't error out if the symbol is not found. */
|
||||
ElfW (Sym) wsym;
|
||||
memset (&wsym, 0, sizeof (ElfW (Sym)));
|
||||
wsym.st_info = (unsigned char) ELFW (ST_INFO (STB_WEAK, STT_NOTYPE));
|
||||
|
||||
/* Compute hash value to the version string. */
|
||||
struct r_found_version vers;
|
||||
vers.name = version;
|
||||
vers.hidden = 1;
|
||||
vers.hash = _dl_elf_hash (version);
|
||||
/* We don't have a specific file where the symbol can be found. */
|
||||
vers.filename = NULL;
|
||||
|
||||
/* Search the scope of the vdso map. */
|
||||
const ElfW (Sym) *ref = &wsym;
|
||||
lookup_t result = GLRO (dl_lookup_symbol_x) (name, map, &ref,
|
||||
map->l_local_scope,
|
||||
&vers, 0, 0, NULL);
|
||||
|
||||
if (ref != NULL)
|
||||
value = DL_SYMBOL_ADDRESS (result, ref);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
27
sysdeps/unix/sysv/linux/powerpc/dl-vdso.h
Normal file
27
sysdeps/unix/sysv/linux/powerpc/dl-vdso.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* ELF symbol resolve functions for VDSO objects.
|
||||
Copyright (C) 2005 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _DL_VDSO_H
|
||||
#define _DL_VDSO_H 1
|
||||
|
||||
/* Functions for resolving symbols in the VDSO link map. */
|
||||
extern void *_dl_vdso_vsym (const char *name, const char *version)
|
||||
internal_function attribute_hidden;
|
||||
|
||||
#endif /* dl-vdso.h */
|
@ -22,7 +22,8 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <libc-internal.h>
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <bits/libc-vdso.h>
|
||||
|
||||
hp_timing_t
|
||||
__get_clockfreq (void)
|
||||
@ -38,7 +39,16 @@ __get_clockfreq (void)
|
||||
if (timebase_freq != 0)
|
||||
return timebase_freq;
|
||||
|
||||
/* If we can use the vDSO to obtain the timebase even better. */
|
||||
#ifdef SHARED
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
timebase_freq = INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, 0);
|
||||
if (INTERNAL_SYSCALL_ERROR_P (timebase_freq, err)
|
||||
&& INTERNAL_SYSCALL_ERRNO (timebase_freq, err) == ENOSYS)
|
||||
#endif
|
||||
{
|
||||
int fd = open ("/proc/cpuinfo", O_RDONLY);
|
||||
|
||||
if (__builtin_expect (fd != -1, 1))
|
||||
{
|
||||
/* The timebase will be in the 1st 1024 bytes for systems with up
|
||||
@ -82,7 +92,8 @@ __get_clockfreq (void)
|
||||
char *endp = buf + n;
|
||||
|
||||
/* Search for the beginning of the string. */
|
||||
while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
|
||||
while (mhz < endp && (*mhz < '0' || *mhz > '9')
|
||||
&& *mhz != '\n')
|
||||
++mhz;
|
||||
|
||||
while (mhz < endp && *mhz != '\n')
|
||||
@ -100,6 +111,7 @@ __get_clockfreq (void)
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
return timebase_freq;
|
||||
}
|
||||
|
42
sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
Normal file
42
sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* Copyright (C) 2005 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <bp-checks.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <hp-timing.h>
|
||||
|
||||
#undef __gettimeofday
|
||||
#include <bits/libc-vdso.h>
|
||||
|
||||
/* Get the current time of day and timezone information,
|
||||
putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled.
|
||||
Returns 0 on success, -1 on errors. */
|
||||
|
||||
int
|
||||
__gettimeofday (tv, tz)
|
||||
struct timeval *tv;
|
||||
struct timezone *tz;
|
||||
{
|
||||
return INLINE_VSYSCALL (gettimeofday, 2, CHECK_1 (tv), CHECK_1 (tz));
|
||||
}
|
||||
|
||||
INTDEF (__gettimeofday)
|
||||
weak_alias (__gettimeofday, gettimeofday)
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1998,2000-2004,2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1998,2000,2001,2002,2003,2004,2005 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
|
||||
@ -24,15 +24,14 @@
|
||||
|
||||
extern int __cache_line_size;
|
||||
weak_extern (__cache_line_size)
|
||||
|
||||
/* The main work is done in the generic function. */
|
||||
#define LIBC_START_MAIN generic_start_main
|
||||
#define LIBC_START_DISABLE_INLINE
|
||||
#define LIBC_START_MAIN_AUXVEC_ARG
|
||||
#define MAIN_AUXVEC_ARG
|
||||
#define INIT_MAIN_ARGS
|
||||
#include <csu/libc-start.c>
|
||||
|
||||
|
||||
struct startup_info
|
||||
{
|
||||
void *__unbounded sda_base;
|
||||
@ -42,6 +41,35 @@ struct startup_info
|
||||
};
|
||||
|
||||
|
||||
#ifdef SHARED
|
||||
# include <sys/time.h>
|
||||
# include <dl-vdso.h>
|
||||
# undef __gettimeofday
|
||||
# undef __clock_gettime
|
||||
# undef __clock_getres
|
||||
# include <bits/libc-vdso.h>
|
||||
|
||||
void *__vdso_gettimeofday;
|
||||
void *__vdso_clock_gettime;
|
||||
void *__vdso_clock_getres;
|
||||
void *__vdso_get_tbfreq;
|
||||
|
||||
static inline void _libc_vdso_platform_setup (void)
|
||||
{
|
||||
__vdso_gettimeofday = _dl_vdso_vsym ("__kernel_gettimeofday",
|
||||
"LINUX_2.6.15");
|
||||
|
||||
__vdso_clock_gettime = _dl_vdso_vsym ("__kernel_clock_gettime",
|
||||
"LINUX_2.6.15");
|
||||
|
||||
__vdso_clock_getres = _dl_vdso_vsym ("__kernel_clock_getres",
|
||||
"LINUX_2.6.15");
|
||||
|
||||
__vdso_get_tbfreq = _dl_vdso_vsym ("__kernel_vdso_get_tbfreq",
|
||||
"LINUX_2.6.15");
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
/* GKM FIXME: GCC: this should get __BP_ prefix by virtue of the
|
||||
BPs in the arglist of startup_info.main and startup_info.init. */
|
||||
@ -92,7 +120,10 @@ BP_SYM (__libc_start_main) (int argc, char *__unbounded *__unbounded ubp_av,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SHARED
|
||||
/* Resolve and initialize function pointers for VDSO functions. */
|
||||
_libc_vdso_platform_setup ();
|
||||
#endif
|
||||
return generic_start_main (stinfo->main, argc, ubp_av, auxvec,
|
||||
stinfo->init, stinfo->fini, rtld_fini,
|
||||
stack_on_entry);
|
@ -55,6 +55,109 @@
|
||||
|
||||
# include <errno.h>
|
||||
|
||||
# ifdef SHARED
|
||||
# define INLINE_VSYSCALL(name, nr, args...) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
__label__ iserr; \
|
||||
INTERNAL_SYSCALL_DECL (sc_err); \
|
||||
long int sc_ret; \
|
||||
\
|
||||
if (__vdso_##name != NULL) \
|
||||
{ \
|
||||
sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, sc_err, nr, ##args); \
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
|
||||
goto out; \
|
||||
if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS) \
|
||||
goto iserr; \
|
||||
} \
|
||||
\
|
||||
sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args); \
|
||||
if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
|
||||
{ \
|
||||
iserr: \
|
||||
__set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \
|
||||
sc_ret = -1L; \
|
||||
} \
|
||||
out: \
|
||||
sc_ret; \
|
||||
})
|
||||
# else
|
||||
# define INLINE_VSYSCALL(name, nr, args...) \
|
||||
INLINE_SYSCALL (name, nr, ##args)
|
||||
# endif
|
||||
|
||||
# ifdef SHARED
|
||||
# define INTERNAL_VSYSCALL(name, err, nr, args...) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
long int v_ret; \
|
||||
\
|
||||
if (__vdso_##name != NULL) \
|
||||
{ \
|
||||
v_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err) \
|
||||
|| INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS) \
|
||||
goto out; \
|
||||
} \
|
||||
v_ret = INTERNAL_SYSCALL (name, err, nr, ##args); \
|
||||
out: \
|
||||
v_ret; \
|
||||
})
|
||||
# else
|
||||
# define INTERNAL_VSYSCALL(name, err, nr, args...) \
|
||||
INTERNAL_SYSCALL (name, err, nr, ##args)
|
||||
# endif
|
||||
|
||||
# define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \
|
||||
({ \
|
||||
long int sc_ret = ENOSYS; \
|
||||
\
|
||||
if (__vdso_##name != NULL) \
|
||||
sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
|
||||
else \
|
||||
err = 1 << 28; \
|
||||
sc_ret; \
|
||||
})
|
||||
|
||||
/* List of system calls which are supported as vsyscalls. */
|
||||
# define HAVE_CLOCK_GETRES_VSYSCALL 1
|
||||
# define HAVE_CLOCK_GETTIME_VSYSCALL 1
|
||||
|
||||
/* Define a macro which expands inline into the wrapper code for a VDSO
|
||||
call. This use is for internal calls that do not need to handle errors
|
||||
normally. It will never touch errno.
|
||||
On powerpc a system call basically clobbers the same registers like a
|
||||
function call, with the exception of LR (which is needed for the
|
||||
"sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
|
||||
an error return status). */
|
||||
# define INTERNAL_VSYSCALL_NCS(funcptr, err, nr, args...) \
|
||||
({ \
|
||||
register void *r0 __asm__ ("r0"); \
|
||||
register long int r3 __asm__ ("r3"); \
|
||||
register long int r4 __asm__ ("r4"); \
|
||||
register long int r5 __asm__ ("r5"); \
|
||||
register long int r6 __asm__ ("r6"); \
|
||||
register long int r7 __asm__ ("r7"); \
|
||||
register long int r8 __asm__ ("r8"); \
|
||||
register long int r9 __asm__ ("r9"); \
|
||||
register long int r10 __asm__ ("r10"); \
|
||||
register long int r11 __asm__ ("r11"); \
|
||||
register long int r12 __asm__ ("r12"); \
|
||||
LOADARGS_##nr (funcptr, args); \
|
||||
__asm__ __volatile__ \
|
||||
("mtctr %0\n\t" \
|
||||
"bctrl\n\t" \
|
||||
"mfcr %0" \
|
||||
: "=&r" (r0), \
|
||||
"=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \
|
||||
"=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \
|
||||
: ASM_INPUT_##nr \
|
||||
: "cr0", "ctr", "lr", "memory"); \
|
||||
err = (long int) r0; \
|
||||
(int) r3; \
|
||||
})
|
||||
|
||||
# undef INLINE_SYSCALL
|
||||
# define INLINE_SYSCALL(name, nr, args...) \
|
||||
({ \
|
||||
|
@ -69,6 +69,112 @@
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
/* This version is for kernels that implement system calls that
|
||||
behave like function calls as far as register saving.
|
||||
It falls back to the syscall in the case that the vDSO doesn't
|
||||
exist or fails for ENOSYS */
|
||||
#ifdef SHARED
|
||||
# define INLINE_VSYSCALL(name, nr, args...) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
__label__ iserr; \
|
||||
INTERNAL_SYSCALL_DECL (sc_err); \
|
||||
long int sc_ret; \
|
||||
\
|
||||
if (__vdso_##name != NULL) \
|
||||
{ \
|
||||
sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, sc_err, nr, ##args); \
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
|
||||
goto out; \
|
||||
if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS) \
|
||||
goto iserr; \
|
||||
} \
|
||||
\
|
||||
sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args); \
|
||||
if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
|
||||
{ \
|
||||
iserr: \
|
||||
__set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \
|
||||
sc_ret = -1L; \
|
||||
} \
|
||||
out: \
|
||||
sc_ret; \
|
||||
})
|
||||
#else
|
||||
# define INLINE_VSYSCALL(name, nr, args...) \
|
||||
INLINE_SYSCALL (name, nr, ##args)
|
||||
#endif
|
||||
|
||||
#ifdef SHARED
|
||||
# define INTERNAL_VSYSCALL(name, err, nr, args...) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
long int v_ret; \
|
||||
\
|
||||
if (__vdso_##name != NULL) \
|
||||
{ \
|
||||
v_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err) \
|
||||
|| INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS) \
|
||||
goto out; \
|
||||
} \
|
||||
v_ret = INTERNAL_SYSCALL (name, err, nr, ##args); \
|
||||
out: \
|
||||
v_ret; \
|
||||
})
|
||||
#else
|
||||
# define INTERNAL_VSYSCALL(name, err, nr, args...) \
|
||||
INTERNAL_SYSCALL (name, err, nr, ##args)
|
||||
#endif
|
||||
|
||||
/* This version is for internal uses when there is no desire
|
||||
to set errno */
|
||||
#define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \
|
||||
({ \
|
||||
long int sc_ret = ENOSYS; \
|
||||
\
|
||||
if (__vdso_##name != NULL) \
|
||||
sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
|
||||
else \
|
||||
err = 1 << 28; \
|
||||
sc_ret; \
|
||||
})
|
||||
|
||||
/* List of system calls which are supported as vsyscalls. */
|
||||
#define HAVE_CLOCK_GETRES_VSYSCALL 1
|
||||
#define HAVE_CLOCK_GETTIME_VSYSCALL 1
|
||||
|
||||
/* Define a macro which expands inline into the wrapper code for a system
|
||||
call. This use is for internal calls that do not need to handle errors
|
||||
normally. It will never touch errno. This returns just what the kernel
|
||||
gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
|
||||
the negation of the return value in the kernel gets reverted. */
|
||||
|
||||
#define INTERNAL_VSYSCALL_NCS(funcptr, err, nr, args...) \
|
||||
({ \
|
||||
register void *r0 __asm__ ("r0"); \
|
||||
register long int r3 __asm__ ("r3"); \
|
||||
register long int r4 __asm__ ("r4"); \
|
||||
register long int r5 __asm__ ("r5"); \
|
||||
register long int r6 __asm__ ("r6"); \
|
||||
register long int r7 __asm__ ("r7"); \
|
||||
register long int r8 __asm__ ("r8"); \
|
||||
LOADARGS_##nr (funcptr, args); \
|
||||
__asm__ __volatile__ \
|
||||
("mtctr %0\n\t" \
|
||||
"bctrl\n\t" \
|
||||
"mfcr %0\n\t" \
|
||||
"0:" \
|
||||
: "=&r" (r0), \
|
||||
"=&r" (r3), "=&r" (r4), "=&r" (r5), \
|
||||
"=&r" (r6), "=&r" (r7), "=&r" (r8) \
|
||||
: ASM_INPUT_##nr \
|
||||
: "r9", "r10", "r11", "r12", \
|
||||
"cr0", "ctr", "lr", "memory"); \
|
||||
err = (long int) r0; \
|
||||
(int) r3; \
|
||||
})
|
||||
|
||||
#undef INLINE_SYSCALL
|
||||
|
||||
/* This version is for kernels that implement system calls that
|
||||
@ -101,7 +207,7 @@
|
||||
register long int r6 __asm__ ("r6"); \
|
||||
register long int r7 __asm__ ("r7"); \
|
||||
register long int r8 __asm__ ("r8"); \
|
||||
LOADARGS_##nr(name, args); \
|
||||
LOADARGS_##nr (name, ##args); \
|
||||
__asm__ __volatile__ \
|
||||
("sc\n\t" \
|
||||
"mfcr %0\n\t" \
|
||||
@ -116,7 +222,7 @@
|
||||
(int) r3; \
|
||||
})
|
||||
#define INTERNAL_SYSCALL(name, err, nr, args...) \
|
||||
INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
|
||||
INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, args)
|
||||
|
||||
#undef INTERNAL_SYSCALL_DECL
|
||||
#define INTERNAL_SYSCALL_DECL(err) long int err
|
||||
|
Loading…
Reference in New Issue
Block a user