From eaad82e00522075b805621309775131e27388791 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 1 Sep 2001 06:10:36 +0000 Subject: [PATCH] Update. 2001-08-31 Richard Henderson * elf/dl-support.c (_dl_cpuclock_offset): Protect with NONAVAIL. (HP_TIMING_AVAIL): Set to HP_SMALL_TIMING_AVAIL if present. * elf/rtld.c (HP_TIMING_AVAIL): Likewise. (print_statistics): Make scalar unsigned long long. * sysdeps/alpha/hp-timing.h: New file. 2001-08-31 Jakub Jelinek * stdio-common/perror.c (perror): Save errno early, pass it down to perror_internal. (perror_internal): Add errnum argument. 2001-08-31 Jakub Jelinek * sysdeps/alpha/dl-machine.h (elf_machine_rela): Remove unused code. Don't add old memory content for R_ALPHA_REFQUAD. --- ChangeLog | 19 ++++++ elf/dl-support.c | 13 ++-- elf/rtld.c | 16 +++-- stdio-common/perror.c | 10 ++-- sysdeps/alpha/dl-machine.h | 17 ------ sysdeps/alpha/hp-timing.h | 118 +++++++++++++++++++++++++++++++++++++ 6 files changed, 162 insertions(+), 31 deletions(-) create mode 100644 sysdeps/alpha/hp-timing.h diff --git a/ChangeLog b/ChangeLog index c22649af2e..a89e02e831 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2001-08-31 Richard Henderson + + * elf/dl-support.c (_dl_cpuclock_offset): Protect with NONAVAIL. + (HP_TIMING_AVAIL): Set to HP_SMALL_TIMING_AVAIL if present. + * elf/rtld.c (HP_TIMING_AVAIL): Likewise. + (print_statistics): Make scalar unsigned long long. + * sysdeps/alpha/hp-timing.h: New file. + +2001-08-31 Jakub Jelinek + + * stdio-common/perror.c (perror): Save errno early, pass it + down to perror_internal. + (perror_internal): Add errnum argument. + +2001-08-31 Jakub Jelinek + + * sysdeps/alpha/dl-machine.h (elf_machine_rela): Remove unused code. + Don't add old memory content for R_ALPHA_REFQUAD. + 2001-08-30 Ulrich Drepper * crypt/md5-crypt.c (__md5_crypt_r): Compute used and required diff --git a/elf/dl-support.c b/elf/dl-support.c index cd56ed411f..1332e8a89f 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -93,8 +93,14 @@ struct r_scope_elem *_dl_main_searchlist = &_dl_initial_searchlist; /* Nonzero during startup. */ int _dl_starting_up = 1; +/* We expect less than a second for relocation. */ +#ifdef HP_SMALL_TIMING_AVAIL +# undef HP_TIMING_AVAIL +# define HP_TIMING_AVAIL HP_SMALL_TIMING_AVAIL +#endif + /* Initial value of the CPU clock. */ -#if HP_TIMING_AVAIL +#ifndef HP_TIMING_NONAVAIL hp_timing_t _dl_cpuclock_offset; #endif @@ -133,9 +139,8 @@ static void non_dynamic_init (void) __attribute__ ((unused)); static void non_dynamic_init (void) { -#if HP_TIMING_AVAIL - HP_TIMING_NOW (_dl_cpuclock_offset); -#endif + if (HP_TIMING_AVAIL) + HP_TIMING_NOW (_dl_cpuclock_offset); if (!_dl_pagesize) _dl_pagesize = __getpagesize (); diff --git a/elf/rtld.c b/elf/rtld.c index fe521176e4..a01594a3ca 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -121,14 +121,20 @@ struct link_map _dl_rtld_map; struct libname_list _dl_rtld_libname; struct libname_list _dl_rtld_libname2; +/* We expect less than a second for relocation. */ +#ifdef HP_SMALL_TIMING_AVAIL +# undef HP_TIMING_AVAIL +# define HP_TIMING_AVAIL HP_SMALL_TIMING_AVAIL +#endif + /* Variable for statistics. */ #ifndef HP_TIMING_NONAVAIL static hp_timing_t rtld_total_time; static hp_timing_t relocate_time; static hp_timing_t load_time; #endif -extern unsigned long int _dl_num_relocations; /* in dl-lookup.c */ -extern unsigned long int _dl_num_cache_relocations; /* in dl-lookup.c */ +extern unsigned long int _dl_num_relocations; /* in dl-lookup.c */ +extern unsigned long int _dl_num_cache_relocations; /* in dl-reloc.c */ static ElfW(Addr) _dl_start_final (void *arg, struct link_map *bootstrap_map_p, hp_timing_t start_time); @@ -136,7 +142,7 @@ static ElfW(Addr) _dl_start_final (void *arg, struct link_map *bootstrap_map_p, #ifdef RTLD_START RTLD_START #else -#error "sysdeps/MACHINE/dl-machine.h fails to define RTLD_START" +# error "sysdeps/MACHINE/dl-machine.h fails to define RTLD_START" #endif static ElfW(Addr) @@ -1506,7 +1512,7 @@ print_statistics (void) { char pbuf[30]; HP_TIMING_PRINT (buf, sizeof (buf), relocate_time); - cp = _itoa_word ((1000 * relocate_time) / rtld_total_time, + cp = _itoa_word ((1000ULL * relocate_time) / rtld_total_time, pbuf + sizeof (pbuf), 10, 0); wp = pbuf; switch (pbuf + sizeof (pbuf) - cp) @@ -1535,7 +1541,7 @@ print_statistics (void) { char pbuf[30]; HP_TIMING_PRINT (buf, sizeof (buf), load_time); - cp = _itoa_word ((1000 * load_time) / rtld_total_time, + cp = _itoa_word ((1000ULL * load_time) / rtld_total_time, pbuf + sizeof (pbuf), 10, 0); wp = pbuf; switch (pbuf + sizeof (pbuf) - cp) diff --git a/stdio-common/perror.c b/stdio-common/perror.c index a1995e975e..077eed5867 100644 --- a/stdio-common/perror.c +++ b/stdio-common/perror.c @@ -26,10 +26,9 @@ #endif static void -perror_internal (FILE *fp, const char *s) +perror_internal (FILE *fp, const char *s, int errnum) { char buf[1024]; - int errnum = errno; const char *colon; const char *errstring; @@ -55,6 +54,7 @@ perror_internal (FILE *fp, const char *s) void perror (const char *s) { + int errnum = errno; #ifdef USE_IN_LIBIO FILE *fp; int fd = -1; @@ -73,20 +73,20 @@ perror (const char *s) __close (fd); /* Use standard error as is. */ - perror_internal (stderr, s); + perror_internal (stderr, s, errnum); } else { /* We don't have to do any special hacks regarding the file position. Since the stderr stream wasn't used so far we just write to the descriptor. */ - perror_internal (fp, s); + perror_internal (fp, s, errnum); /* Close the stream. */ fclose (fp); ((_IO_FILE *) stderr)->_offset = _IO_pos_BAD; } #else - perror_internal (stderr, s); + perror_internal (stderr, s, errnum); #endif } diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h index a97bdf4501..2a414ca448 100644 --- a/sysdeps/alpha/dl-machine.h +++ b/sysdeps/alpha/dl-machine.h @@ -522,24 +522,7 @@ elf_machine_rela (struct link_map *map, else if (r_type == R_ALPHA_REFQUAD) { void *reloc_addr_1 = reloc_addr; - Elf64_Addr reloc_addr_val; - /* Load value without causing unaligned trap. */ - memcpy (&reloc_addr_val, reloc_addr_1, 8); - sym_value += reloc_addr_val; - if (map == &_dl_rtld_map) - { - /* Undo the relocation done here during bootstrapping. - Now we will relocate anew, possibly using a binding - found in the user program or a loaded library rather - than the dynamic linker's built-in definitions used - while loading those libraries. */ - const Elf64_Sym *const dlsymtab - = (void *) D_PTR (map, l_info[DT_SYMTAB]); - sym_value -= map->l_addr; - sym_value -= dlsymtab[ELF64_R_SYM(reloc->r_info)].st_value; - sym_value -= reloc->r_addend; - } /* Store value without causing unaligned trap. */ memcpy (reloc_addr_1, &sym_value, 8); } diff --git a/sysdeps/alpha/hp-timing.h b/sysdeps/alpha/hp-timing.h new file mode 100644 index 0000000000..ccae06b487 --- /dev/null +++ b/sysdeps/alpha/hp-timing.h @@ -0,0 +1,118 @@ +/* High precision, low overhead timing functions. Alpha version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 2001. + + 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 + +#include +#include +#include + +/* The macros defined here use the timestamp counter in IA-64. 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. + + 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 have the timestamp register, but it's got only a 4 second + range. Use it for ld.so profiling only. */ +#define HP_TIMING_AVAIL (0) +#define HP_SMALL_TIMING_AVAIL (1) + +/* We indeed have inlined functions. */ +#define HP_TIMING_INLINE (1) + +/* We use 32 bit values for the times. */ +typedef unsigned int hp_timing_t; + +/* Set timestamp value to zero. */ +#define HP_TIMING_ZERO(VAR) (VAR) = (0) + +/* The "rpcc" instruction returns a 32-bit counting half and a 32-bit + "virtual cycle counter displacement". Subtracting the two gives us + a virtual cycle count. */ +#define HP_TIMING_NOW(VAR) \ + do { \ + unsigned long int x_; \ + asm volatile ("rpcc %0" : "=r"(x_)); \ + (VAR) = (int) (x_) - (int) (x_ >> 32); \ + } while (0) + +/* ??? Two rpcc instructions can be scheduled simultaneously. */ +#define HP_TIMING_DIFF_INIT() do { } while (0) + +/* It's simple arithmetic for us. */ +#define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start)) + +/* ??? Don't bother, since we're only used for ld.so. */ +#define HP_TIMING_ACCUM(Sum, Diff) not implemented + +/* 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_word (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 */