diff options
| -rw-r--r-- | ChangeLog | 28 | ||||
| -rw-r--r-- | elf/rtld.c | 7 | ||||
| -rw-r--r-- | sysdeps/powerpc/powerpc32/dl-start.S | 3 | ||||
| -rw-r--r-- | sysdeps/powerpc/powerpc32/hp-timing.h | 82 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/clock_getres.c | 18 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/clock_gettime.c | 18 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/Makefile | 4 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/Versions | 7 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h | 36 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/dl-vdso.c | 59 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/dl-vdso.h | 27 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c | 110 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/gettimeofday.c | 42 | ||||
| -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.h | 109 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h | 118 |
16 files changed, 659 insertions, 98 deletions
@@ -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) - {< |
