mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-26 06:50:07 +00: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>
|
2005-12-29 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h [ASSEMBLER]:
|
* 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);
|
_dl_setup_hash (l);
|
||||||
l->l_relocated = 1;
|
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
|
/* 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
|
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,
|
set l_name here. That field gives the file name of the DSO,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Machine-dependent ELF startup code. PowerPC version.
|
/* 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.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
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
|
Take the opportunity to clear LR, so anyone who accidentally returns
|
||||||
from _start gets SEGV. Also clear the next few words of the stack. */
|
from _start gets SEGV. Also clear the next few words of the stack. */
|
||||||
|
|
||||||
|
ENTRY(_dl_main_dispatch)
|
||||||
li r31,0
|
li r31,0
|
||||||
stw r31,0(r1)
|
stw r31,0(r1)
|
||||||
mtlr r31
|
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.
|
/* 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.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -24,9 +24,17 @@
|
|||||||
|
|
||||||
#include "kernel-features.h"
|
#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 \
|
#define SYSCALL_GETRES \
|
||||||
retval = INLINE_SYSCALL (clock_getres, 2, clock_id, res); \
|
retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, res); \
|
||||||
break
|
break
|
||||||
|
|
||||||
#ifdef __ASSUME_POSIX_TIMERS
|
#ifdef __ASSUME_POSIX_TIMERS
|
||||||
@ -52,7 +60,7 @@ maybe_syscall_getres (clockid_t clock_id, struct timespec *res)
|
|||||||
if (!__libc_missing_posix_timers)
|
if (!__libc_missing_posix_timers)
|
||||||
{
|
{
|
||||||
INTERNAL_SYSCALL_DECL (err);
|
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))
|
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -109,7 +117,7 @@ maybe_syscall_getres_cpu (clockid_t clock_id, struct timespec *res)
|
|||||||
if (!__libc_missing_posix_cpu_timers)
|
if (!__libc_missing_posix_cpu_timers)
|
||||||
{
|
{
|
||||||
INTERNAL_SYSCALL_DECL (err);
|
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))
|
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||||
return 0;
|
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.
|
/* Check whether the kernel supports CPU clocks at all.
|
||||||
If not, record it for the future. */
|
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),
|
MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
|
||||||
NULL);
|
NULL);
|
||||||
if (INTERNAL_SYSCALL_ERROR_P (r, err))
|
if (INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* clock_gettime -- Get current time from a POSIX clockid_t. Linux version.
|
/* 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.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
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-posix-cpu-timers.h"
|
||||||
#include "kernel-features.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 \
|
#define SYSCALL_GETTIME \
|
||||||
retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
|
retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \
|
||||||
break
|
break
|
||||||
|
|
||||||
#ifdef __ASSUME_POSIX_TIMERS
|
#ifdef __ASSUME_POSIX_TIMERS
|
||||||
@ -51,7 +59,7 @@ maybe_syscall_gettime (clockid_t clock_id, struct timespec *tp)
|
|||||||
if (!__libc_missing_posix_timers)
|
if (!__libc_missing_posix_timers)
|
||||||
{
|
{
|
||||||
INTERNAL_SYSCALL_DECL (err);
|
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))
|
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -108,7 +116,7 @@ maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp)
|
|||||||
if (!__libc_missing_posix_cpu_timers)
|
if (!__libc_missing_posix_cpu_timers)
|
||||||
{
|
{
|
||||||
INTERNAL_SYSCALL_DECL (err);
|
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))
|
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||||
return 0;
|
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.
|
/* Check whether the kernel supports CPU clocks at all.
|
||||||
If not, record it for the future. */
|
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),
|
MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
|
||||||
NULL);
|
NULL);
|
||||||
if (INTERNAL_SYSCALL_ERROR_P (r, err))
|
if (INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||||
|
@ -6,3 +6,7 @@ endif
|
|||||||
ifeq ($(subdir),stdlib)
|
ifeq ($(subdir),stdlib)
|
||||||
gen-as-const-headers += ucontext_i.sym
|
gen-as-const-headers += ucontext_i.sym
|
||||||
endif
|
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,14 +22,15 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <libc-internal.h>
|
#include <libc-internal.h>
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <bits/libc-vdso.h>
|
||||||
|
|
||||||
hp_timing_t
|
hp_timing_t
|
||||||
__get_clockfreq (void)
|
__get_clockfreq (void)
|
||||||
{
|
{
|
||||||
/* We read the information from the /proc filesystem. /proc/cpuinfo
|
/* We read the information from the /proc filesystem. /proc/cpuinfo
|
||||||
contains at least one line like:
|
contains at least one line like:
|
||||||
timebase : 33333333
|
timebase : 33333333
|
||||||
We search for this line and convert the number into an integer. */
|
We search for this line and convert the number into an integer. */
|
||||||
static hp_timing_t timebase_freq;
|
static hp_timing_t timebase_freq;
|
||||||
hp_timing_t result = 0L;
|
hp_timing_t result = 0L;
|
||||||
@ -38,67 +39,78 @@ __get_clockfreq (void)
|
|||||||
if (timebase_freq != 0)
|
if (timebase_freq != 0)
|
||||||
return timebase_freq;
|
return timebase_freq;
|
||||||
|
|
||||||
int fd = open ("/proc/cpuinfo", O_RDONLY);
|
/* If we can use the vDSO to obtain the timebase even better. */
|
||||||
if (__builtin_expect (fd != -1, 1))
|
#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
|
||||||
{
|
{
|
||||||
/* The timebase will be in the 1st 1024 bytes for systems with up
|
int fd = open ("/proc/cpuinfo", O_RDONLY);
|
||||||
to 8 processors. If the first read returns less then 1024
|
|
||||||
bytes read, we have the whole cpuinfo and can start the scan.
|
|
||||||
Otherwise we will have to read more to insure we have the
|
|
||||||
timebase value in the scan. */
|
|
||||||
char buf[1024];
|
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
n = read (fd, buf, sizeof (buf));
|
if (__builtin_expect (fd != -1, 1))
|
||||||
if (n == sizeof (buf))
|
|
||||||
{
|
{
|
||||||
/* We are here because the 1st read returned exactly sizeof
|
/* The timebase will be in the 1st 1024 bytes for systems with up
|
||||||
(buf) bytes. This implies that we are not at EOF and may
|
to 8 processors. If the first read returns less then 1024
|
||||||
not have read the timebase value yet. So we need to read
|
bytes read, we have the whole cpuinfo and can start the scan.
|
||||||
more bytes until we know we have EOF. We copy the lower
|
Otherwise we will have to read more to insure we have the
|
||||||
half of buf to the upper half and read sizeof (buf)/2
|
timebase value in the scan. */
|
||||||
bytes into the lower half of buf and repeat until we
|
char buf[1024];
|
||||||
reach EOF. We can assume that the timebase will be in
|
ssize_t n;
|
||||||
the last 512 bytes of cpuinfo, so two 512 byte half_bufs
|
|
||||||
will be sufficient to contain the timebase and will
|
n = read (fd, buf, sizeof (buf));
|
||||||
handle the case where the timebase spans the half_buf
|
if (n == sizeof (buf))
|
||||||
boundry. */
|
|
||||||
const ssize_t half_buf = sizeof (buf) / 2;
|
|
||||||
while (n >= half_buf)
|
|
||||||
{
|
{
|
||||||
memcpy (buf, buf + half_buf, half_buf);
|
/* We are here because the 1st read returned exactly sizeof
|
||||||
n = read (fd, buf + half_buf, half_buf);
|
(buf) bytes. This implies that we are not at EOF and may
|
||||||
}
|
not have read the timebase value yet. So we need to read
|
||||||
if (n >= 0)
|
more bytes until we know we have EOF. We copy the lower
|
||||||
n += half_buf;
|
half of buf to the upper half and read sizeof (buf)/2
|
||||||
}
|
bytes into the lower half of buf and repeat until we
|
||||||
|
reach EOF. We can assume that the timebase will be in
|
||||||
if (__builtin_expect (n, 1) > 0)
|
the last 512 bytes of cpuinfo, so two 512 byte half_bufs
|
||||||
{
|
will be sufficient to contain the timebase and will
|
||||||
char *mhz = memmem (buf, n, "timebase", 7);
|
handle the case where the timebase spans the half_buf
|
||||||
|
boundry. */
|
||||||
if (__builtin_expect (mhz != NULL, 1))
|
const ssize_t half_buf = sizeof (buf) / 2;
|
||||||
{
|
while (n >= half_buf)
|
||||||
char *endp = buf + n;
|
|
||||||
|
|
||||||
/* Search for the beginning of the string. */
|
|
||||||
while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
|
|
||||||
++mhz;
|
|
||||||
|
|
||||||
while (mhz < endp && *mhz != '\n')
|
|
||||||
{
|
{
|
||||||
if (*mhz >= '0' && *mhz <= '9')
|
memcpy (buf, buf + half_buf, half_buf);
|
||||||
{
|
n = read (fd, buf + half_buf, half_buf);
|
||||||
result *= 10;
|
|
||||||
result += *mhz - '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
++mhz;
|
|
||||||
}
|
}
|
||||||
|
if (n >= 0)
|
||||||
|
n += half_buf;
|
||||||
}
|
}
|
||||||
timebase_freq = result;
|
|
||||||
|
if (__builtin_expect (n, 1) > 0)
|
||||||
|
{
|
||||||
|
char *mhz = memmem (buf, n, "timebase", 7);
|
||||||
|
|
||||||
|
if (__builtin_expect (mhz != NULL, 1))
|
||||||
|
{
|
||||||
|
char *endp = buf + n;
|
||||||
|
|
||||||
|
/* Search for the beginning of the string. */
|
||||||
|
while (mhz < endp && (*mhz < '0' || *mhz > '9')
|
||||||
|
&& *mhz != '\n')
|
||||||
|
++mhz;
|
||||||
|
|
||||||
|
while (mhz < endp && *mhz != '\n')
|
||||||
|
{
|
||||||
|
if (*mhz >= '0' && *mhz <= '9')
|
||||||
|
{
|
||||||
|
result *= 10;
|
||||||
|
result += *mhz - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
++mhz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timebase_freq = result;
|
||||||
|
}
|
||||||
|
close (fd);
|
||||||
}
|
}
|
||||||
close (fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return timebase_freq;
|
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.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -24,33 +24,61 @@
|
|||||||
|
|
||||||
extern int __cache_line_size;
|
extern int __cache_line_size;
|
||||||
weak_extern (__cache_line_size)
|
weak_extern (__cache_line_size)
|
||||||
|
|
||||||
/* The main work is done in the generic function. */
|
/* The main work is done in the generic function. */
|
||||||
#define LIBC_START_MAIN generic_start_main
|
#define LIBC_START_MAIN generic_start_main
|
||||||
#define LIBC_START_DISABLE_INLINE
|
#define LIBC_START_DISABLE_INLINE
|
||||||
#define LIBC_START_MAIN_AUXVEC_ARG
|
#define LIBC_START_MAIN_AUXVEC_ARG
|
||||||
#define MAIN_AUXVEC_ARG
|
#define MAIN_AUXVEC_ARG
|
||||||
|
#define INIT_MAIN_ARGS
|
||||||
#include <csu/libc-start.c>
|
#include <csu/libc-start.c>
|
||||||
|
|
||||||
|
|
||||||
struct startup_info
|
struct startup_info
|
||||||
{
|
{
|
||||||
void *__unbounded sda_base;
|
void *__unbounded sda_base;
|
||||||
int (*main) (int, char **, char **, void *);
|
int (*main) (int, char **, char **, void *);
|
||||||
int (*init) (int, char **, char **, void *);
|
int (*init) (int, char **, char **, void *);
|
||||||
void (*fini) (void);
|
void (*fini) (void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
int
|
||||||
/* GKM FIXME: GCC: this should get __BP_ prefix by virtue of the
|
/* GKM FIXME: GCC: this should get __BP_ prefix by virtue of the
|
||||||
BPs in the arglist of startup_info.main and startup_info.init. */
|
BPs in the arglist of startup_info.main and startup_info.init. */
|
||||||
BP_SYM (__libc_start_main) (int argc, char *__unbounded *__unbounded ubp_av,
|
BP_SYM (__libc_start_main) (int argc, char *__unbounded *__unbounded ubp_av,
|
||||||
char *__unbounded *__unbounded ubp_ev,
|
char *__unbounded *__unbounded ubp_ev,
|
||||||
ElfW(auxv_t) *__unbounded auxvec,
|
ElfW (auxv_t) * __unbounded auxvec,
|
||||||
void (*rtld_fini) (void),
|
void (*rtld_fini) (void),
|
||||||
struct startup_info *__unbounded stinfo,
|
struct startup_info *__unbounded stinfo,
|
||||||
char *__unbounded *__unbounded stack_on_entry)
|
char *__unbounded *__unbounded stack_on_entry)
|
||||||
{
|
{
|
||||||
#if __BOUNDED_POINTERS__
|
#if __BOUNDED_POINTERS__
|
||||||
char **argv;
|
char **argv;
|
||||||
@ -60,13 +88,13 @@ BP_SYM (__libc_start_main) (int argc, char *__unbounded *__unbounded ubp_av,
|
|||||||
|
|
||||||
/* the PPC SVR4 ABI says that the top thing on the stack will
|
/* the PPC SVR4 ABI says that the top thing on the stack will
|
||||||
be a NULL pointer, so if not we assume that we're being called
|
be a NULL pointer, so if not we assume that we're being called
|
||||||
as a statically-linked program by Linux... */
|
as a statically-linked program by Linux... */
|
||||||
if (*stack_on_entry != NULL)
|
if (*stack_on_entry != NULL)
|
||||||
{
|
{
|
||||||
char *__unbounded *__unbounded temp;
|
char *__unbounded * __unbounded temp;
|
||||||
/* ...in which case, we have argc as the top thing on the
|
/* ...in which case, we have argc as the top thing on the
|
||||||
stack, followed by argv (NULL-terminated), envp (likewise),
|
stack, followed by argv (NULL-terminated), envp (likewise),
|
||||||
and the auxilary vector. */
|
and the auxilary vector. */
|
||||||
/* 32/64-bit agnostic load from stack */
|
/* 32/64-bit agnostic load from stack */
|
||||||
argc = *(long int *__unbounded) stack_on_entry;
|
argc = *(long int *__unbounded) stack_on_entry;
|
||||||
ubp_av = stack_on_entry + 1;
|
ubp_av = stack_on_entry + 1;
|
||||||
@ -74,25 +102,28 @@ BP_SYM (__libc_start_main) (int argc, char *__unbounded *__unbounded ubp_av,
|
|||||||
#ifdef HAVE_AUX_VECTOR
|
#ifdef HAVE_AUX_VECTOR
|
||||||
temp = ubp_ev;
|
temp = ubp_ev;
|
||||||
while (*temp != NULL)
|
while (*temp != NULL)
|
||||||
++temp;
|
++temp;
|
||||||
auxvec = (ElfW(auxv_t) *)++temp;
|
auxvec = (ElfW (auxv_t) *)++ temp;
|
||||||
#endif
|
#endif
|
||||||
rtld_fini = NULL;
|
rtld_fini = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the __cache_line_size variable from the aux vector. */
|
/* Initialize the __cache_line_size variable from the aux vector. */
|
||||||
for (ElfW(auxv_t) *av = auxvec; av->a_type != AT_NULL; ++av)
|
for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av)
|
||||||
switch (av->a_type)
|
switch (av->a_type)
|
||||||
{
|
{
|
||||||
case AT_DCACHEBSIZE:
|
case AT_DCACHEBSIZE:
|
||||||
{
|
{
|
||||||
int *cls = & __cache_line_size;
|
int *cls = &__cache_line_size;
|
||||||
if (cls != NULL)
|
if (cls != NULL)
|
||||||
*cls = av->a_un.a_val;
|
*cls = av->a_un.a_val;
|
||||||
}
|
}
|
||||||
break;
|
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,
|
return generic_start_main (stinfo->main, argc, ubp_av, auxvec,
|
||||||
stinfo->init, stinfo->fini, rtld_fini,
|
stinfo->init, stinfo->fini, rtld_fini,
|
||||||
stack_on_entry);
|
stack_on_entry);
|
@ -55,6 +55,109 @@
|
|||||||
|
|
||||||
# include <errno.h>
|
# 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
|
# undef INLINE_SYSCALL
|
||||||
# define INLINE_SYSCALL(name, nr, args...) \
|
# define INLINE_SYSCALL(name, nr, args...) \
|
||||||
({ \
|
({ \
|
||||||
@ -93,7 +196,7 @@
|
|||||||
register long int r10 __asm__ ("r10"); \
|
register long int r10 __asm__ ("r10"); \
|
||||||
register long int r11 __asm__ ("r11"); \
|
register long int r11 __asm__ ("r11"); \
|
||||||
register long int r12 __asm__ ("r12"); \
|
register long int r12 __asm__ ("r12"); \
|
||||||
LOADARGS_##nr(name, args); \
|
LOADARGS_##nr(name, args); \
|
||||||
__asm__ __volatile__ \
|
__asm__ __volatile__ \
|
||||||
("sc \n\t" \
|
("sc \n\t" \
|
||||||
"mfcr %0" \
|
"mfcr %0" \
|
||||||
@ -115,11 +218,11 @@
|
|||||||
# undef INTERNAL_SYSCALL_ERRNO
|
# undef INTERNAL_SYSCALL_ERRNO
|
||||||
# define INTERNAL_SYSCALL_ERRNO(val, err) (val)
|
# define INTERNAL_SYSCALL_ERRNO(val, err) (val)
|
||||||
|
|
||||||
# define LOADARGS_0(name, dummy) \
|
# define LOADARGS_0(name, dummy) \
|
||||||
r0 = name
|
r0 = name
|
||||||
# define LOADARGS_1(name, __arg1) \
|
# define LOADARGS_1(name, __arg1) \
|
||||||
long int arg1 = (long int) (__arg1); \
|
long int arg1 = (long int) (__arg1); \
|
||||||
LOADARGS_0(name, 0); \
|
LOADARGS_0(name, 0); \
|
||||||
extern void __illegally_sized_syscall_arg1 (void); \
|
extern void __illegally_sized_syscall_arg1 (void); \
|
||||||
if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 4) \
|
if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 4) \
|
||||||
__illegally_sized_syscall_arg1 (); \
|
__illegally_sized_syscall_arg1 (); \
|
||||||
|
@ -62,12 +62,118 @@
|
|||||||
#ifdef __ASSEMBLER__
|
#ifdef __ASSEMBLER__
|
||||||
|
|
||||||
/* This seems to always be the case on PPC. */
|
/* This seems to always be the case on PPC. */
|
||||||
#define ALIGNARG(log2) log2
|
# define ALIGNARG(log2) log2
|
||||||
/* For ELF we need the `.type' directive to make shared libs work right. */
|
/* For ELF we need the `.type' directive to make shared libs work right. */
|
||||||
#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
|
# define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
|
||||||
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
# define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#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
|
#undef INLINE_SYSCALL
|
||||||
|
|
||||||
@ -101,7 +207,7 @@
|
|||||||
register long int r6 __asm__ ("r6"); \
|
register long int r6 __asm__ ("r6"); \
|
||||||
register long int r7 __asm__ ("r7"); \
|
register long int r7 __asm__ ("r7"); \
|
||||||
register long int r8 __asm__ ("r8"); \
|
register long int r8 __asm__ ("r8"); \
|
||||||
LOADARGS_##nr(name, args); \
|
LOADARGS_##nr (name, ##args); \
|
||||||
__asm__ __volatile__ \
|
__asm__ __volatile__ \
|
||||||
("sc\n\t" \
|
("sc\n\t" \
|
||||||
"mfcr %0\n\t" \
|
"mfcr %0\n\t" \
|
||||||
@ -116,7 +222,7 @@
|
|||||||
(int) r3; \
|
(int) r3; \
|
||||||
})
|
})
|
||||||
#define INTERNAL_SYSCALL(name, err, nr, args...) \
|
#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
|
#undef INTERNAL_SYSCALL_DECL
|
||||||
#define INTERNAL_SYSCALL_DECL(err) long int err
|
#define INTERNAL_SYSCALL_DECL(err) long int err
|
||||||
|
Loading…
Reference in New Issue
Block a user