aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog27
-rw-r--r--elf/rtld.c174
-rw-r--r--sunrpc/rpc_main.c6
-rw-r--r--sysdeps/generic/hp-timing.h80
-rw-r--r--sysdeps/i386/dl-machine.h2
-rw-r--r--sysdeps/i386/i686/Makefile3
-rw-r--r--sysdeps/i386/i686/hp-timing.c24
-rw-r--r--sysdeps/i386/i686/hp-timing.h160
-rw-r--r--sysdeps/unix/sysv/linux/arm/Dist2
9 files changed, 468 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index f7b3c0d..51109f1 100644
--- a/ChangeLog
+++ b/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):
diff --git a/elf/rtld.c b/elf/rtld.c
index 38c7b05..df6a945 100644
--- a/elf/rtld.c
+++ b/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);
+ }
+}
diff --git a/sunrpc/rpc_main.c b/sunrpc/rpc_main.c
index 8302f81..2229c56 100644
--- a/sunrpc/rpc_main.c
+++ b/sunrpc/rpc_main.c
@@ -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] \
diff --git a/sysdeps/generic/hp-timing.h b/sysdeps/generic/hp-timing.h
new file mode 100644
index 0000000..7795f51
--- /dev/null
+++ b/sysdeps/generic/hp-timing.h
@@ -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 */
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 87d9248..8338a93 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.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;
diff --git a/sysdeps/i386/i686/Makefile b/sysdeps/i386/i686/Makefile
new file mode 100644
index 0000000..b4b60d0
--- /dev/null
+++ b/sysdeps/i386/i686/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),csu)
+sysdep_routines += hp-timing
+endif
diff --git a/sysdeps/i386/i686/hp-timing.c b/sysdeps/i386/i686/hp-timing.c
new file mode 100644
index 0000000..3f5fcfe
--- /dev/null
+++ b/sysdeps/i386/i686/hp-timing.c
@@ -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;
diff --git a/sysdeps/i386/i686/hp-timing.h b/sysdeps/i386/i686/hp-timing.h
new file mode 100644
index 0000000..ffbeb27
--- /dev/null
+++ b/sysdeps/i386/i686/hp-timing.h
@@ -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 */
diff --git a/sysdeps/unix/sysv/linux/arm/Dist b/sysdeps/unix/sysv/linux/arm/Dist
index 18aa31f..479a4ab 100644
--- a/sysdeps/unix/sysv/linux/arm/Dist
+++ b/sysdeps/unix/sysv/linux/arm/Dist
@@ -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