aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog28
-rw-r--r--elf/rtld.c7
-rw-r--r--sysdeps/powerpc/powerpc32/dl-start.S3
-rw-r--r--sysdeps/powerpc/powerpc32/hp-timing.h82
-rw-r--r--sysdeps/unix/sysv/linux/clock_getres.c18
-rw-r--r--sysdeps/unix/sysv/linux/clock_gettime.c18
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/Makefile4
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/Versions7
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h36
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/dl-vdso.c59
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/dl-vdso.h27
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c110
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/gettimeofday.c42
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/libc-start.c (renamed from sysdeps/powerpc/elf/libc-start.c)89
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h109
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h118
16 files changed, 659 insertions, 98 deletions
diff --git a/ChangeLog b/ChangeLog
index 5201d34627..74d0a82e13 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2005-12-08 Steven Munroe <sjmunroe@us.ibm.com>
+ Tom Gall <tom_gall@vnet.ibm.com>
+
+ * elf/rtld.c (dl_main): Initialize l_local_scope for sysinfo_map.
+ * sysdeps/powerpc/elf/libc-start.c: Move this...
+ * sysdeps/unix/sysv/linux/powerpc/libc-start.c: ...to here.
+ * sysdeps/powerpc/powerpc32/dl-start.S: Add _dl_main_dispatch label.
+ * sysdeps/powerpc/powerpc32/hp-timing.h: New file.
+ * sysdeps/unix/sysv/linux/powerpc/Versions: New file.
+ * sysdeps/unix/sysv/linux/clock_getres.c: If HAVE_CLOCK_GETRES_VSYSCALL
+ is not defined, redefine INTERNAL_VSYSCALL and INLINE_VSYSCALL to
+ INTERNAL_SYSCALL and INLINE_SYSCALL respectively. Otherwise include
+ <bits/libc-vdso.h>. Use INLINE_VSYSCALL and INTERNAL_SYSCALL instead
+ of the normal versions throughout the code.
+ * sysdeps/unix/sysv/linux/clock_gettime.c: Likewise if
+ HAVE_CLOCK_GETTIME_VSYSCALL is defined.
+ * sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h: New file.
+ * sysdeps/unix/sysv/linux/powerpc/dl-vdso.c: New file.
+ * sysdeps/unix/sysv/linux/powerpc/dl-vdso.h: New file.
+ * sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c: Use vDSO.
+ * sysdeps/unix/sysv/linux/powerpc/gettimeofday.c: New file.
+ * sysdeps/unix/sysv/linux/powerpc/Makefile: Add dl-vdso to routines.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Define
+ INLINE_VSYSCALL, INTERNAL_VSYSCALL, INTERNAL_SYSCALL_NCS,
+ INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK, HAVE_CLOCK_GETRES_VSYSCALL,
+ and HAVE_CLOCK_GETTIME_VSYSCALL.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise.
+
2005-12-29 Ulrich Drepper <drepper@redhat.com>
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h [ASSEMBLER]:
diff --git a/elf/rtld.c b/elf/rtld.c
index 71bcf0ab71..76d129a0a0 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1307,6 +1307,13 @@ ld.so does not support TLS, but program uses it!\n");
_dl_setup_hash (l);
l->l_relocated = 1;
+ /* Initialize l_local_scope to contain just this map. This allows
+ the use of dl_lookup_symbol_x to resolve symbols within the vdso.
+ So we create a single entry list pointing to l_real as its only
+ element */
+ l->l_local_scope[0]->r_nlist = 1;
+ l->l_local_scope[0]->r_list = &l->l_real;
+
/* Now that we have the info handy, use the DSO image's soname
so this object can be looked up by name. Note that we do not
set l_name here. That field gives the file name of the DSO,
diff --git a/sysdeps/powerpc/powerpc32/dl-start.S b/sysdeps/powerpc/powerpc32/dl-start.S
index e1f7f6e24a..7403a352fa 100644
--- a/sysdeps/powerpc/powerpc32/dl-start.S
+++ b/sysdeps/powerpc/powerpc32/dl-start.S
@@ -1,5 +1,5 @@
/* Machine-dependent ELF startup code. PowerPC version.
- Copyright (C) 1995-2000, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2000, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -98,6 +98,7 @@ ENTRY(_dl_start_user)
Take the opportunity to clear LR, so anyone who accidentally returns
from _start gets SEGV. Also clear the next few words of the stack. */
+ENTRY(_dl_main_dispatch)
li r31,0
stw r31,0(r1)
mtlr r31
diff --git a/sysdeps/powerpc/powerpc32/hp-timing.h b/sysdeps/powerpc/powerpc32/hp-timing.h
new file mode 100644
index 0000000000..b62b0f2138
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/hp-timing.h
@@ -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 */
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 2d0136dfeb..44dcccd150 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -1,5 +1,5 @@
/* clock_getres -- Get the resolution of a POSIX clockid_t. Linux version.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -24,9 +24,17 @@
#include "kernel-features.h"
+#ifndef HAVE_CLOCK_GETRES_VSYSCALL
+# undef INTERNAL_VSYSCALL
+# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
+# undef INLINE_VSYSCALL
+# define INLINE_VSYSCALL INLINE_SYSCALL
+#else
+# include <bits/libc-vdso.h>
+#endif
#define SYSCALL_GETRES \
- retval = INLINE_SYSCALL (clock_getres, 2, clock_id, res); \
+ retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, res); \
break
#ifdef __ASSUME_POSIX_TIMERS
@@ -52,7 +60,7 @@ maybe_syscall_getres (clockid_t clock_id, struct timespec *res)
if (!__libc_missing_posix_timers)
{
INTERNAL_SYSCALL_DECL (err);
- int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
+ int r = INTERNAL_VSYSCALL (clock_getres, err, 2, clock_id, res);
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
return 0;
@@ -109,7 +117,7 @@ maybe_syscall_getres_cpu (clockid_t clock_id, struct timespec *res)
if (!__libc_missing_posix_cpu_timers)
{
INTERNAL_SYSCALL_DECL (err);
- int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
+ int r = INTERNAL_VSYSCALL (clock_getres, err, 2, clock_id, res);
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
return 0;
@@ -128,7 +136,7 @@ maybe_syscall_getres_cpu (clockid_t clock_id, struct timespec *res)
{
/* Check whether the kernel supports CPU clocks at all.
If not, record it for the future. */
- r = INTERNAL_SYSCALL (clock_getres, err, 2,
+ r = INTERNAL_VSYSCALL (clock_getres, err, 2,
MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
NULL);
if (INTERNAL_SYSCALL_ERROR_P (r, err))
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index bd79642dd5..315d595edc 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -1,5 +1,5 @@
/* clock_gettime -- Get current time from a POSIX clockid_t. Linux version.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -23,9 +23,17 @@
#include "kernel-posix-cpu-timers.h"
#include "kernel-features.h"
+#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
+# undef INTERNAL_VSYSCALL
+# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
+# undef INLINE_VSYSCALL
+# define INLINE_VSYSCALL INLINE_SYSCALL
+#else
+# include <bits/libc-vdso.h>
+#endif
#define SYSCALL_GETTIME \
- retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
+ retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \
break
#ifdef __ASSUME_POSIX_TIMERS
@@ -51,7 +59,7 @@ maybe_syscall_gettime (clockid_t clock_id, struct timespec *tp)
if (!__libc_missing_posix_timers)
{
INTERNAL_SYSCALL_DECL (err);
- int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ int r = INTERNAL_VSYSCALL (clock_gettime, err, 2, clock_id, tp);
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
return 0;
@@ -108,7 +116,7 @@ maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp)
if (!__libc_missing_posix_cpu_timers)
{
INTERNAL_SYSCALL_DECL (err);
- int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ int r = INTERNAL_VSYSCALL (clock_gettime, err, 2, clock_id, tp);
if (!INTERNAL_SYSCALL_ERROR_P (r, err))
return 0;
@@ -127,7 +135,7 @@ maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp)
{
/* Check whether the kernel supports CPU clocks at all.
If not, record it for the future. */
- r = INTERNAL_SYSCALL (clock_getres, err, 2,
+ r = INTERNAL_VSYSCALL (clock_getres, err, 2,
MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
NULL);
if (INTERNAL_SYSCALL_ERROR_P (r, err))
diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
index 55d2d0d273..ecd8057951 100644
--- a/sysdeps/unix/sysv/linux/powerpc/Makefile
+++ b/sysdeps/unix/sysv/linux/powerpc/Makefile
@@ -6,3 +6,7 @@ endif
ifeq ($(subdir),stdlib)
gen-as-const-headers += ucontext_i.sym
endif
+
+ifeq ($(subdir),elf)
+routines += dl-vdso
+endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/Versions b/sysdeps/unix/sysv/linux/powerpc/Versions
new file mode 100644
index 0000000000..1ef53b9e9c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/Versions
@@ -0,0 +1,7 @@
+libc {
+ GLIBC_PRIVATE {
+ __vdso_get_tbfreq;
+ __vdso_clock_gettime;
+ __vdso_clock_getres;
+ }
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
new file mode 100644
index 0000000000..f20a5a175c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -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 */
diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-vdso.c b/sysdeps/unix/sysv/linux/powerpc/dl-vdso.c
new file mode 100644
index 0000000000..e1be097734
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/dl-vdso.c
@@ -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;
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-vdso.h b/sysdeps/unix/sysv/linux/powerpc/dl-vdso.h
new file mode 100644
index 0000000000..a7dcb2e5ff
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/dl-vdso.h
@@ -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 */
diff --git a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c b/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
index ddaff303c5..6d2e766aa4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
+++ b/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
@@ -22,14 +22,15 @@
#include <string.h>
#include <unistd.h>
#include <libc-internal.h>
-
+#include <sysdep.h>
+#include <bits/libc-vdso.h>
hp_timing_t
__get_clockfreq (void)
{
/* We read the information from the /proc filesystem. /proc/cpuinfo
contains at least one line like:
- timebase : 33333333
+ timebase : 33333333
We search for this line and convert the number into an integer. */
static hp_timing_t timebase_freq;
hp_timing_t result = 0L;
@@ -38,67 +39,78 @@ __get_clockfreq (void)
if (timebase_freq != 0)
return timebase_freq;
- int fd = open ("/proc/cpuinfo", O_RDONLY);
- if (__builtin_expect (fd != -1, 1))
+ /* If we can use the vDSO to obtain the timebase even better. */
+#ifdef SHARED
+ INTERNAL_SYSCALL_DECL (err);
+ timebase_freq = INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, 0);
+ if (INTERNAL_SYSCALL_ERROR_P (timebase_freq, err)
+ && INTERNAL_SYSCALL_ERRNO (timebase_freq, err) == ENOSYS)
+#endif
{
- /* The timebase will be in the 1st 1024 bytes for systems with up
- 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;
+ int fd = open ("/proc/cpuinfo", O_RDONLY);
- n = read (fd, buf, sizeof (buf));
- if (n == sizeof (buf))
+ if (__builtin_expect (fd != -1, 1))
{
- /* We are here because the 1st read returned exactly sizeof
- (buf) bytes. This implies that we are not at EOF and may
- not have read the timebase value yet. So we need to read
- more bytes until we know we have EOF. We copy the lower
- 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
- the last 512 bytes of cpuinfo, so two 512 byte half_bufs
- will be sufficient to contain the timebase and will
- handle the case where the timebase spans the half_buf
- boundry. */
- const ssize_t half_buf = sizeof (buf) / 2;
- while (n >= half_buf)
+ /* The timebase will be in the 1st 1024 bytes for systems with up
+ 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 (n == sizeof (buf))
{
- memcpy (buf, buf + half_buf, half_buf);
- n = read (fd, buf + half_buf, half_buf);
+ /* We are here because the 1st read returned exactly sizeof
+ (buf) bytes. This implies that we are not at EOF and may
+ not have read the timebase value yet. So we need to read
+ more bytes until we know we have EOF. We copy the lower
+ 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
+ the last 512 bytes of cpuinfo, so two 512 byte half_bufs
+ will be sufficient to contain the timebase and will
+ handle the case where the timebase spans the half_buf
+ boundry. */
+ const ssize_t half_buf = sizeof (buf) / 2;
+ while (n >= half_buf)
+ {
+ memcpy (buf, buf + half_buf, half_buf);
+ n = read (fd, buf + half_buf, half_buf);
+ }
+ if (n >= 0)
+ n += half_buf;
}
- if (n >= 0)
- n += half_buf;
- }
-
- if (__builtin_expect (n, 1) > 0)
- {<