mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-27 11:43:34 +08:00
Update.
1998-12-27 Ulrich Drepper <drepper@cygnus.com> * elf/dl-lookup.c (_dl_num_relocations): New variable. (do_lookup): Increment _dl_num_relocations for every call. * elf/rtld.c (print_statistics): New function. (_dl_debug_statistics): New variable. Set when statistics are asked for. (rtld_total_time, relocate_time, load_time): New variables. Used in print_statistics. (_dl_start): Record start and end time of startup. Call print_statistics if needed. (dk_main): Record times for relocations and loading. (process_dl_debug): Recognize statistics. Low-level, low-overhead, high-precision timing funcationality. * sysdeps/generic/hp-timing.h: New file. * sysdeps/i386/i686/Makefile: New file. * sysdeps/i386/i686/hp-timing.h: New file. * sysdeps/i386/i686/hp-timing.c: New file. * sysdeps/i386/dl-machine.h (elf_machine_rel): Reverse order of OR clauses to avoid accessing global variables during rtld relocation. * sunrpc/rpc_main.c: Unify messages. * sysdeps/unix/sysv/linux/arm/Dist: Add ioperm.c and sys/io.h.
This commit is contained in:
parent
8352b484cf
commit
db276fa11c
27
ChangeLog
27
ChangeLog
@ -1,3 +1,30 @@
|
||||
1998-12-27 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* elf/dl-lookup.c (_dl_num_relocations): New variable.
|
||||
(do_lookup): Increment _dl_num_relocations for every call.
|
||||
* elf/rtld.c (print_statistics): New function.
|
||||
(_dl_debug_statistics): New variable. Set when statistics are asked
|
||||
for.
|
||||
(rtld_total_time, relocate_time, load_time): New variables. Used
|
||||
in print_statistics.
|
||||
(_dl_start): Record start and end time of startup. Call
|
||||
print_statistics if needed.
|
||||
(dk_main): Record times for relocations and loading.
|
||||
(process_dl_debug): Recognize statistics.
|
||||
|
||||
Low-level, low-overhead, high-precision timing funcationality.
|
||||
* sysdeps/generic/hp-timing.h: New file.
|
||||
* sysdeps/i386/i686/Makefile: New file.
|
||||
* sysdeps/i386/i686/hp-timing.h: New file.
|
||||
* sysdeps/i386/i686/hp-timing.c: New file.
|
||||
|
||||
* sysdeps/i386/dl-machine.h (elf_machine_rel): Reverse order of OR
|
||||
clauses to avoid accessing global variables during rtld relocation.
|
||||
|
||||
* sunrpc/rpc_main.c: Unify messages.
|
||||
|
||||
* sysdeps/unix/sysv/linux/arm/Dist: Add ioperm.c and sys/io.h.
|
||||
|
||||
1998-12-27 Roland McGrath <roland@baalperazim.frob.com>
|
||||
|
||||
* sysdeps/mach/hurd/bits/statfs.h (struct statfs, struct statfs64):
|
||||
|
174
elf/rtld.c
174
elf/rtld.c
@ -26,6 +26,7 @@
|
||||
#include <stdio-common/_itoa.h>
|
||||
#include <entry.h>
|
||||
#include <fpu_control.h>
|
||||
#include <hp-timing.h>
|
||||
#include "dynamic-link.h"
|
||||
#include "dl-librecon.h"
|
||||
|
||||
@ -58,6 +59,8 @@ static void print_unresolved (int errcode, const char *objname,
|
||||
static void print_missing_version (int errcode, const char *objname,
|
||||
const char *errsting);
|
||||
|
||||
/* Print the various times we collected. */
|
||||
static void print_statistics (void);
|
||||
|
||||
/* This is a list of all the modes the dynamic loader can be in. */
|
||||
enum mode { normal, list, verify, trace };
|
||||
@ -86,6 +89,7 @@ int _dl_debug_symbols;
|
||||
int _dl_debug_versions;
|
||||
int _dl_debug_reloc;
|
||||
int _dl_debug_files;
|
||||
int _dl_debug_statistics;
|
||||
const char *_dl_inhibit_rpath; /* RPATH values which should be
|
||||
ignored. */
|
||||
const char *_dl_origin_path;
|
||||
@ -118,6 +122,12 @@ struct link_map _dl_rtld_map;
|
||||
struct libname_list _dl_rtld_libname;
|
||||
struct libname_list _dl_rtld_libname2;
|
||||
|
||||
/* Variable for statistics. */
|
||||
static hp_timing_t rtld_total_time;
|
||||
static hp_timing_t relocate_time;
|
||||
static hp_timing_t load_time;
|
||||
extern unsigned long int _dl_num_relocations; /* in dl-lookup.c */
|
||||
|
||||
#ifdef RTLD_START
|
||||
RTLD_START
|
||||
#else
|
||||
@ -128,6 +138,8 @@ static ElfW(Addr)
|
||||
_dl_start (void *arg)
|
||||
{
|
||||
struct link_map bootstrap_map;
|
||||
hp_timing_t start_time;
|
||||
ElfW(Addr) start_addr;
|
||||
|
||||
/* This #define produces dynamic linking inline functions for
|
||||
bootstrap relocation instead of general-purpose relocation. */
|
||||
@ -136,6 +148,9 @@ _dl_start (void *arg)
|
||||
((*(sym))->st_shndx == SHN_UNDEF ? 0 : bootstrap_map.l_addr)
|
||||
#include "dynamic-link.h"
|
||||
|
||||
if (HP_TIMING_INLINE && HP_TIMING_AVAIL)
|
||||
HP_TIMING_NOW (start_time);
|
||||
|
||||
/* Figure out the run-time load address of the dynamic linker itself. */
|
||||
bootstrap_map.l_addr = elf_machine_load_address ();
|
||||
|
||||
@ -160,6 +175,16 @@ _dl_start (void *arg)
|
||||
the operating system's program loader where to find the program
|
||||
header table in core. */
|
||||
|
||||
if (HP_TIMING_AVAIL)
|
||||
{
|
||||
/* If it hasn't happen yet record the startup time. */
|
||||
if (! HP_TIMING_INLINE)
|
||||
HP_TIMING_NOW (start_time);
|
||||
|
||||
/* Initialize the timing functions. */
|
||||
HP_TIMING_DIFF_INIT ();
|
||||
}
|
||||
|
||||
/* Transfer data about ourselves to the permanent link_map structure. */
|
||||
_dl_rtld_map.l_addr = bootstrap_map.l_addr;
|
||||
_dl_rtld_map.l_ld = bootstrap_map.l_ld;
|
||||
@ -176,7 +201,23 @@ _dl_start (void *arg)
|
||||
file access. It will call `dl_main' (below) to do all the real work
|
||||
of the dynamic linker, and then unwind our frame and run the user
|
||||
entry point on the same stack we entered on. */
|
||||
return _dl_sysdep_start (arg, &dl_main);
|
||||
start_addr = _dl_sysdep_start (arg, &dl_main);
|
||||
|
||||
if (HP_TIMING_AVAIL)
|
||||
{
|
||||
hp_timing_t end_time;
|
||||
|
||||
/* Get the current time. */
|
||||
HP_TIMING_NOW (end_time);
|
||||
|
||||
/* Compute the difference. */
|
||||
HP_TIMING_DIFF (rtld_total_time, start_time, end_time);
|
||||
}
|
||||
|
||||
if (_dl_debug_statistics)
|
||||
print_statistics ();
|
||||
|
||||
return start_addr;
|
||||
}
|
||||
|
||||
/* Now life is peachy; we can do all normal operations.
|
||||
@ -300,6 +341,9 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
int has_interp = 0;
|
||||
unsigned int i;
|
||||
int paths_initialized = 0;
|
||||
hp_timing_t start;
|
||||
hp_timing_t stop;
|
||||
hp_timing_t diff;
|
||||
|
||||
/* Process the environment variable which control the behaviour. */
|
||||
process_envvars (&mode, &lazy);
|
||||
@ -413,7 +457,13 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
}
|
||||
}
|
||||
else
|
||||
_dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0);
|
||||
{
|
||||
HP_TIMING_NOW (start);
|
||||
_dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0);
|
||||
HP_TIMING_NOW (stop);
|
||||
|
||||
HP_TIMING_DIFF (load_time, start, stop);
|
||||
}
|
||||
|
||||
phdr = _dl_loaded->l_phdr;
|
||||
phent = _dl_loaded->l_phnum;
|
||||
@ -562,6 +612,9 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
containing a '/' are ignored since it is insecure. */
|
||||
char *list = strdupa (preloadlist);
|
||||
char *p;
|
||||
|
||||
HP_TIMING_NOW (start);
|
||||
|
||||
while ((p = strsep (&list, " :")) != NULL)
|
||||
if (p[0] != '\0'
|
||||
&& (! __libc_enable_secure || strchr (p, '/') == NULL))
|
||||
@ -572,6 +625,10 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
/* It is no duplicate. */
|
||||
++npreloads;
|
||||
}
|
||||
|
||||
HP_TIMING_NOW (stop);
|
||||
HP_TIMING_DIFF (diff, start, stop);
|
||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||
}
|
||||
|
||||
/* Read the contents of the file. */
|
||||
@ -621,6 +678,8 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
file[file_size - 1] = '\0';
|
||||
}
|
||||
|
||||
HP_TIMING_NOW (start);
|
||||
|
||||
if (file != problem)
|
||||
{
|
||||
char *p;
|
||||
@ -646,6 +705,10 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
++npreloads;
|
||||
}
|
||||
|
||||
HP_TIMING_NOW (stop);
|
||||
HP_TIMING_DIFF (diff, start, stop);
|
||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||
|
||||
/* We don't need the file anymore. */
|
||||
__munmap (file, file_size);
|
||||
}
|
||||
@ -668,7 +731,11 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
/* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
|
||||
specified some libraries to load, these are inserted before the actual
|
||||
dependencies in the executable's searchlist for symbol resolution. */
|
||||
HP_TIMING_NOW (start);
|
||||
_dl_map_object_deps (_dl_loaded, preloads, npreloads, mode == trace, 0);
|
||||
HP_TIMING_NOW (stop);
|
||||
HP_TIMING_DIFF (diff, start, stop);
|
||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||
|
||||
/* Mark all objects as being in the global scope. */
|
||||
for (i = _dl_loaded->l_searchlist.r_nlist; i > 0; )
|
||||
@ -884,6 +951,9 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
|
||||
struct link_map *l;
|
||||
int consider_profiling = _dl_profile != NULL;
|
||||
hp_timing_t start;
|
||||
hp_timing_t stop;
|
||||
hp_timing_t add;
|
||||
|
||||
/* If we are profiling we also must do lazy reloaction. */
|
||||
lazy |= consider_profiling;
|
||||
@ -891,13 +961,19 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
l = _dl_loaded;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
|
||||
HP_TIMING_NOW (start);
|
||||
do
|
||||
{
|
||||
if (l != &_dl_rtld_map)
|
||||
_dl_relocate_object (l, l->l_scope, lazy, consider_profiling);
|
||||
|
||||
l = l->l_prev;
|
||||
} while (l);
|
||||
}
|
||||
while (l);
|
||||
HP_TIMING_NOW (stop);
|
||||
|
||||
HP_TIMING_DIFF (relocate_time, start, stop);
|
||||
|
||||
/* Do any necessary cleanups for the startup OS interface code.
|
||||
We do these now so that no calls are made after rtld re-relocation
|
||||
@ -907,9 +983,15 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
_dl_sysdep_start_cleanup ();
|
||||
|
||||
if (_dl_rtld_map.l_opencount > 0)
|
||||
/* There was an explicit ref to the dynamic linker as a shared lib.
|
||||
Re-relocate ourselves with user-controlled symbol definitions. */
|
||||
_dl_relocate_object (&_dl_rtld_map, _dl_loaded->l_scope, 0, 0);
|
||||
{
|
||||
/* There was an explicit ref to the dynamic linker as a shared lib.
|
||||
Re-relocate ourselves with user-controlled symbol definitions. */
|
||||
HP_TIMING_NOW (start);
|
||||
_dl_relocate_object (&_dl_rtld_map, _dl_loaded->l_scope, 0, 0);
|
||||
HP_TIMING_NOW (stop);
|
||||
HP_TIMING_DIFF (add, start, stop);
|
||||
HP_TIMING_ACCUM_NT (relocate_time, add);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set up the variable which helps the assembler startup code. */
|
||||
@ -1101,6 +1183,14 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n",
|
||||
}
|
||||
break;
|
||||
|
||||
case 10:
|
||||
if (memcmp (dl_debug, "statistics", 10) == 0)
|
||||
{
|
||||
_dl_debug_statistics = 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1110,6 +1200,7 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n",
|
||||
char *startp = strndupa (dl_debug, len);
|
||||
_dl_sysdep_error ("warning: debug option `", startp,
|
||||
"' unknown; try LD_DEBUG=help\n", NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1291,3 +1382,74 @@ process_envvars (enum mode *modep, int *lazyp)
|
||||
|
||||
*modep = mode;
|
||||
}
|
||||
|
||||
|
||||
/* Print the various times we collected. */
|
||||
static void
|
||||
print_statistics (void)
|
||||
{
|
||||
char buf[200];
|
||||
char *cp;
|
||||
char *wp;
|
||||
|
||||
/* Total time rtld used. */
|
||||
if (HP_TIMING_AVAIL)
|
||||
{
|
||||
HP_TIMING_PRINT (buf, sizeof (buf), rtld_total_time);
|
||||
_dl_debug_message (1, "\nruntime linker statistics:\n"
|
||||
" total startup time in dynamic loader: ",
|
||||
buf, "\n", NULL);
|
||||
}
|
||||
|
||||
/* Print relocation statistics. */
|
||||
if (HP_TIMING_AVAIL)
|
||||
{
|
||||
HP_TIMING_PRINT (buf, sizeof (buf), relocate_time);
|
||||
_dl_debug_message (1, " time needed for relocation: ", buf,
|
||||
NULL);
|
||||
cp = _itoa_word ((1000 * relocate_time) / rtld_total_time,
|
||||
buf + sizeof (buf), 10, 0);
|
||||
wp = buf;
|
||||
switch (buf + sizeof (buf) - cp)
|
||||
{
|
||||
case 3:
|
||||
*wp++ = *cp++;
|
||||
case 2:
|
||||
*wp++ = *cp++;
|
||||
case 1:
|
||||
*wp++ = '.';
|
||||
*wp++ = *cp++;
|
||||
}
|
||||
*wp = '\0';
|
||||
_dl_debug_message (0, " (", buf, "%)\n", NULL);
|
||||
}
|
||||
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
_dl_debug_message (1, " number of relocations: ",
|
||||
_itoa_word (_dl_num_relocations,
|
||||
buf + sizeof (buf) - 1, 10, 0),
|
||||
"\n", NULL);
|
||||
|
||||
/* Time spend while loading the object and the dependencies. */
|
||||
if (HP_TIMING_AVAIL)
|
||||
{
|
||||
HP_TIMING_PRINT (buf, sizeof (buf), load_time);
|
||||
_dl_debug_message (1, " time needed to load objects: ", buf,
|
||||
NULL);
|
||||
cp = _itoa_word ((1000 * load_time) / rtld_total_time,
|
||||
buf + sizeof (buf), 10, 0);
|
||||
wp = buf;
|
||||
switch (buf + sizeof (buf) - cp)
|
||||
{
|
||||
case 3:
|
||||
*wp++ = *cp++;
|
||||
case 2:
|
||||
*wp++ = *cp++;
|
||||
case 1:
|
||||
*wp++ = '.';
|
||||
*wp++ = *cp++;
|
||||
}
|
||||
*wp = '\0';
|
||||
_dl_debug_message (0, " (", buf, "%)\n", NULL);
|
||||
}
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ check_nettype (const char *name, const char *list_to_check[])
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fprintf (stderr, _ ("illegal nettype :\'%s\'\n"), name);
|
||||
fprintf (stderr, _ ("illegal nettype :`%s'\n"), name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1144,7 +1144,7 @@ checkfiles (const char *infile, const char *outfile)
|
||||
else
|
||||
{
|
||||
fprintf (stderr,
|
||||
_("file '%s' already exists and may be overwritten\n"),
|
||||
_("file `%s' already exists and may be overwritten\n"),
|
||||
outfile);
|
||||
crash ();
|
||||
}
|
||||
@ -1411,7 +1411,7 @@ parseargs (int argc, const char *argv[], struct commandline *cmd)
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
fprintf (stderr, _("usage: %s infile\n"), cmdname);
|
||||
fprintf (stderr, _("usage: %s infile\n"), cmdname);
|
||||
fprintf (stderr, _("\t%s [-abkCLNTM][-Dname[=value]] [-i size] \
|
||||
[-I [-K seconds]] [-Y path] infile\n"), cmdname);
|
||||
fprintf (stderr, _("\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] \
|
||||
|
80
sysdeps/generic/hp-timing.h
Normal file
80
sysdeps/generic/hp-timing.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* High precision, low overhead timing functions. i686 version.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. 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 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)
|
||||
|
||||
#endif /* hp-timing.h */
|
@ -335,7 +335,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
||||
found. */
|
||||
break;
|
||||
if (sym->st_size > refsym->st_size
|
||||
|| (_dl_verbose && sym->st_size < refsym->st_size))
|
||||
|| (sym->st_size < refsym->st_size && _dl_verbose))
|
||||
{
|
||||
const char *strtab;
|
||||
|
||||
|
3
sysdeps/i386/i686/Makefile
Normal file
3
sysdeps/i386/i686/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
ifeq ($(subdir),csu)
|
||||
sysdep_routines += hp-timing
|
||||
endif
|
24
sysdeps/i386/i686/hp-timing.c
Normal file
24
sysdeps/i386/i686/hp-timing.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* Support for high precision, low overhead timing functions. i686 version.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <hp-timing.h>
|
||||
|
||||
/* We have to define the variable for the overhead. */
|
||||
hp_timing_t __libc_hp_timing_overhead;
|
160
sysdeps/i386/i686/hp-timing.h
Normal file
160
sysdeps/i386/i686/hp-timing.h
Normal file
@ -0,0 +1,160 @@
|
||||
/* High precision, low overhead timing functions. i686 version.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. 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
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio-common/_itoa.h>
|
||||
|
||||
/* The macros defined here use the timestamp counter in i586 and up versions
|
||||
of the x86 processors. They provide a very accurate way to measure the
|
||||
time with very little overhead. The time values themself have no real
|
||||
meaning, only differences are interesting.
|
||||
|
||||
This version is for the i686 processors. The difference to the i586
|
||||
version is that the timerstamp register is unconditionally used. This is
|
||||
not the case for the i586 version where we have to perform runtime test
|
||||
whether the processor really has this capability. We have to make this
|
||||
distinction since the sysdeps/i386/i586 code is supposed to work on all
|
||||
platforms while the i686 already contains i686-specific code.
|
||||
|
||||
The list of macros we need includes the following:
|
||||
|
||||
- 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.
|
||||
|
||||
*/
|
||||
|
||||
/* We always assume having the timestamp register. */
|
||||
#define HP_TIMING_AVAIL (1)
|
||||
|
||||
/* We indeed have inlined functions. */
|
||||
#define HP_TIMING_INLINE (1)
|
||||
|
||||
/* We use 64bit values for the times. */
|
||||
typedef unsigned long long int hp_timing_t;
|
||||
|
||||
/* Internal variabled used to store the overhead of the measurement
|
||||
opcodes. */
|
||||
extern hp_timing_t __libc_hp_timing_overhead;
|
||||
|
||||
/* Set timestamp value to zero. */
|
||||
#define HP_TIMING_ZERO(Var) (Var) = (0)
|
||||
|
||||
/* That's quite simple. Use the `rdtsc' instruction. Note that the value
|
||||
might not be 100% accurate since there might be some more instructions
|
||||
running in this moment. This could be changed by using a barrier like
|
||||
'cpuid' right before the `rdtsc' instruciton. But we are not interested
|
||||
in accurate clock cycles here so we don't do this. */
|
||||
#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rdtsc" : "=A" (Var))
|
||||
|
||||
/* Use two 'rdtsc' instructions in a row to find out how long it takes. */
|
||||
#define HP_TIMING_DIFF_INIT() \
|
||||
do { \
|
||||
int __cnt = 5; \
|
||||
__libc_hp_timing_overhead = ~0ull; \
|
||||
do \
|
||||
{ \
|
||||
hp_timing_t __t1, __t2; \
|
||||
HP_TIMING_NOW (__t1); \
|
||||
HP_TIMING_NOW (__t2); \
|
||||
if (__t2 - __t1 < __libc_hp_timing_overhead) \
|
||||
__libc_hp_timing_overhead = __t2 - __t1; \
|
||||
} \
|
||||
while (--__cnt > 0); \
|
||||
} while (0)
|
||||
|
||||
/* It's simple arithmetic for us. */
|
||||
#define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start))
|
||||
|
||||
/* We have to jump through hoops to get this correctly implemented. */
|
||||
#define HP_TIMING_ACCUM(Sum, Diff) \
|
||||
do { \
|
||||
char __not_done; \
|
||||
hp_timing_t __oldval = (Sum); \
|
||||
hp_timing_t __diff = (Diff) - __libc_hp_timing_overhead; \
|
||||
do \
|
||||
{ \
|
||||
hp_timing_t __newval = __oldval + __diff; \
|
||||
int __temp0, __temp1; \
|
||||
__asm__ __volatile__ ("xchgl %4, %%ebx\n\t" \
|
||||
"lock; cmpxchg8b %1\n\t" \
|
||||
"sete %0\n\t" \
|
||||
"movl %4, %%ebx" \
|
||||
: "=q" (__not_done), "=m" (Sum), \
|
||||
"=A" (__oldval), "=c" (__temp0), \
|
||||
"=SD" (__temp1) \
|
||||
: "1" (Sum), "2" (__oldval), \
|
||||
"3" (__newval >> 32), \
|
||||
"4" (__newval & 0xffffffff) \
|
||||
: "memory"); \
|
||||
} \
|
||||
while (__not_done); \
|
||||
} while (0)
|
||||
|
||||
/* No threads, no extra work. */
|
||||
#define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff)
|
||||
|
||||
/* Print the time value. */
|
||||
#define HP_TIMING_PRINT(Buf, Len, Val) \
|
||||
do { \
|
||||
char __buf[20]; \
|
||||
char *__cp = _itoa (Val, __buf + sizeof (__buf), 10, 0); \
|
||||
int __len = (Len); \
|
||||
char *__dest = (Buf); \
|
||||
while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \
|
||||
*__dest++ = *__cp++; \
|
||||
memcpy (__dest, " clock cycles", MIN (__len, sizeof (" clock cycles"))); \
|
||||
} while (0)
|
||||
|
||||
#endif /* hp-timing.h */
|
@ -1,7 +1,9 @@
|
||||
clone.S
|
||||
init-first.h
|
||||
ioperm.c
|
||||
setresuid.c
|
||||
setresgid.c
|
||||
setfsuid.c
|
||||
setfsgid.c
|
||||
bits/armsigctx.h
|
||||
sys/io.h
|
||||
|
Loading…
Reference in New Issue
Block a user