Fix more EINTR handling problems. Add jump prediction.

This commit is contained in:
Ulrich Drepper
2005-08-29 06:25:06 +00:00
parent c2c3b1ecbe
commit 6abe27be71
14 changed files with 132 additions and 97 deletions
+4
View File
@@ -1,3 +1,7 @@
2005-08-28 Ulrich Drepper <drepper@redhat.com>
* system.h: Define pwrite_retry, write_retry, and pread_retry.
2005-08-06 Ulrich Drepper <drepper@redhat.com>
* Makefile.am (xmalloc_CFLAGS): Define only if !GPROF.
+8
View File
@@ -37,4 +37,12 @@ extern int crc32_file (int fd, uint32_t *resp);
#define gettext_noop(Str) Str
#define pwrite_retry(fd, buf, len, off) \
TEMP_FAILURE_RETRY (pwrite (fd, buf, len, off))
#define write_retry(fd, buf, n) \
TEMP_FAILURE_RETRY (write (fd, buf, n))
#define pread_retry(fd, buf, len, off) \
TEMP_FAILURE_RETRY (pread (fd, buf, len, off))
#endif /* system.h */
+11
View File
@@ -1,5 +1,16 @@
2005-08-28 Ulrich Drepper <drepper@redhat.com>
* elf32_getphdr.c: Include <system.h>. Use pread_retry instead of
pread. And branch prediction where useful.
* elf_begin.c: Likewise.
* elf_getdata.c: Likewise.
* elf_getshstrndx.c: Likewise.
* elf_readall.c: Likewise.
* gelf_rawchunk.c: Likewise.
* elf32_updatefile.c: Include <system.h>. Use pread_retry instead of
pread. And branch prediction where useful.
* elf_getarsym.c: Don't define pread_retry here.
* Makefile.am: Use $(LINK) not $(CC) when creating DSO.
(%.os): Use COMPILE.os.
(COMPILE.os): Filter out gconv options.
+6 -3
View File
@@ -19,9 +19,11 @@
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <system.h>
#include "libelfP.h"
#include "common.h"
@@ -148,9 +150,10 @@ elfw2(LIBELFBITS,getphdr) (elf)
elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
/* Read the header. */
if ((size_t) pread (elf->fildes,
elf->state.ELFW(elf,LIBELFBITS).phdr, size,
(elf->start_offset + ehdr->e_phoff)) != size)
ssize_t n = pread_retry (elf->fildes,
elf->state.ELFW(elf,LIBELFBITS).phdr, size,
elf->start_offset + ehdr->e_phoff);
if (unlikely ((size_t) n != size))
{
/* Severe problems. We cannot read the data. */
__libelf_seterrno (ELF_E_READ_ERROR);
+7 -4
View File
@@ -20,8 +20,10 @@
#endif
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <system.h>
#include "libelfP.h"
#include "common.h"
@@ -122,12 +124,13 @@ elfw2(LIBELFBITS,getshdr) (scn)
CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
}
}
else if (elf->fildes != -1)
else if (likely (elf->fildes != -1))
{
/* Read the header. */
if ((size_t) pread (elf->fildes,
elf->state.ELFW(elf,LIBELFBITS).shdr, size,
elf->start_offset + ehdr->e_shoff) != size)
ssize_t n = pread_retry (elf->fildes,
elf->state.ELFW(elf,LIBELFBITS).shdr, size,
elf->start_offset + ehdr->e_shoff);
if (unlikely ((size_t) n != size))
{
/* Severe problems. We cannot read the data. */
__libelf_seterrno (ELF_E_READ_ERROR);
+16 -14
View File
@@ -20,6 +20,7 @@
#endif
#include <assert.h>
#include <errno.h>
#include <libelf.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -27,6 +28,7 @@
#include <unistd.h>
#include <sys/param.h>
#include <system.h>
#include "libelfP.h"
@@ -326,7 +328,7 @@ fill (int fd, off_t pos, size_t len, char *fillbuf, size_t *filledp)
/* This many bytes we want to write in this round. */
size_t n = MIN (filled, len);
if (unlikely ((size_t) pwrite (fd, fillbuf, n, pos) != n))
if (unlikely ((size_t) pwrite_retry (fd, fillbuf, n, pos) != n))
{
__libelf_seterrno (ELF_E_WRITE_ERROR);
return 1;
@@ -381,8 +383,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
}
/* Write out the ELF header. */
if (unlikely (pwrite (elf->fildes, out_ehdr,
sizeof (ElfW2(LIBELFBITS,Ehdr)), 0)
if (unlikely (pwrite_retry (elf->fildes, out_ehdr,
sizeof (ElfW2(LIBELFBITS,Ehdr)), 0)
!= sizeof (ElfW2(LIBELFBITS,Ehdr))))
{
__libelf_seterrno (ELF_E_WRITE_ERROR);
@@ -441,10 +443,10 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
}
/* Write out the ELF header. */
if (unlikely ((size_t) pwrite (elf->fildes, out_phdr,
sizeof (ElfW2(LIBELFBITS,Phdr))
* ehdr->e_phnum, ehdr->e_phoff)
!= sizeof (ElfW2(LIBELFBITS,Phdr)) * ehdr->e_phnum))
size_t phdr_size = sizeof (ElfW2(LIBELFBITS,Phdr)) * ehdr->e_phnum;
if (unlikely ((size_t) pwrite_retry (elf->fildes, out_phdr,
phdr_size, ehdr->e_phoff)
!= phdr_size))
{
__libelf_seterrno (ELF_E_WRITE_ERROR);
return 1;
@@ -544,10 +546,10 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
(*fctp) (buf, dl->data.d.d_buf, dl->data.d.d_size, 1);
}
if (unlikely ((size_t) pwrite (elf->fildes, buf,
dl->data.d.d_size,
last_offset)
!= dl->data.d.d_size))
ssize_t n = pwrite_retry (elf->fildes, buf,
dl->data.d.d_size,
last_offset);
if (unlikely ((size_t) n != dl->data.d.d_size))
{
if (buf != dl->data.d.d_buf && buf != tmpbuf)
free (buf);
@@ -593,9 +595,9 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
/* Write out the section header table. */
if (shdr_flags & ELF_F_DIRTY
&& unlikely ((size_t) pwrite (elf->fildes, shdr_data,
sizeof (ElfW2(LIBELFBITS,Shdr))
* shnum, shdr_offset)
&& unlikely ((size_t) pwrite_retry (elf->fildes, shdr_data,
sizeof (ElfW2(LIBELFBITS,Shdr))
* shnum, shdr_offset)
!= sizeof (ElfW2(LIBELFBITS,Shdr)) * shnum))
{
__libelf_seterrno (ELF_E_WRITE_ERROR);
+43 -45
View File
@@ -31,6 +31,7 @@
#include <sys/param.h>
#include <sys/stat.h>
#include <system.h>
#include "libelfP.h"
#include "common.h"
@@ -144,12 +145,10 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
+ offset))->sh_size,
sizeof (Elf32_Word));
else
if (TEMP_FAILURE_RETRY (pread (fildes, &size,
sizeof (Elf32_Word),
offset + ehdr.e32->e_shoff
+ offsetof (Elf32_Shdr,
sh_size)))
!= sizeof (Elf32_Word))
if (unlikely (pread_retry (fildes, &size, sizeof (Elf32_Word),
offset + ehdr.e32->e_shoff
+ offsetof (Elf32_Shdr, sh_size))
!= sizeof (Elf32_Word)))
return (size_t) -1l;
if (e_ident[EI_DATA] != MY_ELFDATA)
@@ -188,12 +187,10 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
+ offset))->sh_size,
sizeof (Elf64_Xword));
else
if (TEMP_FAILURE_RETRY (pread (fildes, &size,
sizeof (Elf64_Word),
offset + ehdr.e64->e_shoff
+ offsetof (Elf64_Shdr,
sh_size)))
!= sizeof (Elf64_Xword))
if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Word),
offset + ehdr.e64->e_shoff
+ offsetof (Elf64_Shdr, sh_size))
!= sizeof (Elf64_Xword)))
return (size_t) -1l;
if (e_ident[EI_DATA] != MY_ELFDATA)
@@ -459,11 +456,11 @@ read_unmmaped_file (int fildes, off_t offset, size_t maxsize, Elf_Cmd cmd,
} mem;
/* Read the head of the file. */
ssize_t nread = pread (fildes, mem.header, MIN (MAX (sizeof (Elf64_Ehdr),
SARMAG),
maxsize),
offset);
if (nread == -1)
ssize_t nread = pread_retry (fildes, mem.header,
MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
maxsize),
offset);
if (unlikely (nread == -1))
/* We cannot even read the head of the file. Maybe FILDES is associated
with an unseekable device. This is nothing we can handle. */
return NULL;
@@ -597,8 +594,9 @@ read_long_names (Elf *elf)
else
{
/* Read the header from the file. */
if (pread (elf->fildes, &hdrm, sizeof (hdrm),
elf->start_offset + offset) != sizeof (hdrm))
if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
elf->start_offset + offset)
!= sizeof (hdrm)))
return NULL;
hdr = &hdrm;
@@ -628,10 +626,10 @@ read_long_names (Elf *elf)
len);
else
{
if ((size_t) pread (elf->fildes, newp, len,
elf->start_offset + offset
+ sizeof (struct ar_hdr))
!= len)
if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
elf->start_offset + offset
+ sizeof (struct ar_hdr))
!= len))
{
/* We were not able to read all data. */
free (newp);
@@ -681,8 +679,8 @@ __libelf_next_arhdr (elf)
if (elf->map_address != NULL)
{
/* See whether this entry is in the file. */
if (elf->state.ar.offset + sizeof (struct ar_hdr)
> elf->start_offset + elf->maximum_size)
if (unlikely (elf->state.ar.offset + sizeof (struct ar_hdr)
> elf->start_offset + elf->maximum_size))
{
/* This record is not anymore in the file. */
__libelf_seterrno (ELF_E_RANGE);
@@ -694,10 +692,9 @@ __libelf_next_arhdr (elf)
{
ar_hdr = &elf->state.ar.ar_hdr;
if (TEMP_FAILURE_RETRY (pread (elf->fildes, ar_hdr,
sizeof (struct ar_hdr),
elf->state.ar.offset))
!= sizeof (struct ar_hdr))
if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
elf->state.ar.offset)
!= sizeof (struct ar_hdr)))
{
/* Something went wrong while reading the file. */
__libelf_seterrno (ELF_E_RANGE);
@@ -706,7 +703,7 @@ __libelf_next_arhdr (elf)
}
/* One little consistency check. */
if (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0)
if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
{
/* This is no valid archive. */
__libelf_seterrno (ELF_E_ARCHIVE_FMAG);
@@ -730,14 +727,14 @@ __libelf_next_arhdr (elf)
&& memcmp (ar_hdr->ar_name, "// ", 16) == 0)
/* This is the array with the long names. */
elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
else if (isdigit (ar_hdr->ar_name[1]))
else if (likely (isdigit (ar_hdr->ar_name[1])))
{
size_t offset;
/* This is a long name. First we have to read the long name
table, if this hasn't happened already. */
if (elf->state.ar.long_names == NULL
&& read_long_names (elf) == NULL)
if (unlikely (elf->state.ar.long_names == NULL
&& read_long_names (elf) == NULL))
{
/* No long name table although it is reference. The archive is
broken. */
@@ -746,7 +743,7 @@ __libelf_next_arhdr (elf)
}
offset = atol (ar_hdr->ar_name + 1);
if (offset >= elf->state.ar.long_names_len)
if (unlikely (offset >= elf->state.ar.long_names_len))
{
/* The index in the long name table is larger than the table. */
__libelf_seterrno (ELF_E_INVALID_ARCHIVE);
@@ -860,7 +857,7 @@ __libelf_next_arhdr (elf)
if (ar_hdr->ar_size[sizeof (ar_hdr->ar_size) - 1] == ' ')
{
if (ar_hdr->ar_size[0] == ' ')
if (unlikely (ar_hdr->ar_size[0] == ' '))
/* Something is really wrong. We cannot live without a size for
the member since it will not be possible to find the next
archive member. */
@@ -900,7 +897,7 @@ dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
fildes = ref->fildes;
/* The file descriptor better should be the same. If it was disconnected
already (using `elf_cntl') we do not test it. */
else if (ref->fildes != -1 && fildes != ref->fildes)
else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
{
__libelf_seterrno (ELF_E_FD_MISMATCH);
return NULL;
@@ -909,10 +906,10 @@ dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
/* The mode must allow reading. I.e., a descriptor creating with a
command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
not allowed. */
if (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
&& ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
&& ref->cmd != ELF_C_READ_MMAP_PRIVATE)
if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
&& ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
&& ref->cmd != ELF_C_READ_MMAP_PRIVATE))
{
__libelf_seterrno (ELF_E_INVALID_OP);
return NULL;
@@ -989,7 +986,7 @@ elf_begin (fildes, cmd, ref)
{
Elf *retval;
if (! __libelf_version_initialized)
if (unlikely (! __libelf_version_initialized))
{
/* Version wasn't set so far. */
__libelf_seterrno (ELF_E_NO_VERSION);
@@ -999,7 +996,7 @@ elf_begin (fildes, cmd, ref)
if (ref != NULL)
/* Make sure the descriptor is not suddenly going away. */
rwlock_rdlock (ref->lock);
else if (fcntl (fildes, F_GETFL) == -1 && errno == EBADF)
else if (unlikely (fcntl (fildes, F_GETFL) == -1 && errno == EBADF))
{
/* We cannot do anything productive without a file descriptor. */
__libelf_seterrno (ELF_E_INVALID_FILE);
@@ -1015,7 +1012,7 @@ elf_begin (fildes, cmd, ref)
case ELF_C_READ_MMAP_PRIVATE:
/* If we have a reference it must also be opened this way. */
if (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE)
if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
{
__libelf_seterrno (ELF_E_INVALID_CMD);
retval = NULL;
@@ -1039,8 +1036,9 @@ elf_begin (fildes, cmd, ref)
command. */
if (ref != NULL)
{
if (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP)
if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
&& ref->cmd != ELF_C_WRITE
&& ref->cmd != ELF_C_WRITE_MMAP))
{
/* This is not ok. REF must also be opened for writing. */
__libelf_seterrno (ELF_E_INVALID_CMD);
+1 -4
View File
@@ -28,14 +28,11 @@
#include <string.h>
#include <unistd.h>
#include <system.h>
#include <dl-hash.h>
#include "libelfP.h"
#define pread_retry(fd, buf, len, off) \
TEMP_FAILURE_RETRY (pread (fd, buf, len, off))
Elf_Arsym *
elf_getarsym (elf, ptr)
Elf *elf;
+8 -5
View File
@@ -19,11 +19,13 @@
# include <config.h>
#endif
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include "libelfP.h"
#include <system.h>
#include "common.h"
#include "elf-knowledge.h"
@@ -239,7 +241,7 @@ __libelf_set_rawdata (Elf_Scn *scn)
if (entsize == 0)
entsize = 1;
if (size % entsize != 0)
if (unlikely (size % entsize != 0))
{
__libelf_seterrno (ELF_E_INVALID_DATA);
return 1;
@@ -250,7 +252,7 @@ __libelf_set_rawdata (Elf_Scn *scn)
{
/* First see whether the information in the section header is
valid and it does not ask for too much. */
if (offset + size > elf->maximum_size)
if (unlikely (offset + size > elf->maximum_size))
{
/* Something is wrong. */
__libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
@@ -260,7 +262,7 @@ __libelf_set_rawdata (Elf_Scn *scn)
scn->rawdata_base = scn->rawdata.d.d_buf
= (char *) elf->map_address + elf->start_offset + offset;
}
else if (elf->fildes != -1)
else if (likely (elf->fildes != -1))
{
/* We have to read the data from the file. Allocate the needed
memory. */
@@ -272,8 +274,9 @@ __libelf_set_rawdata (Elf_Scn *scn)
return 1;
}
if ((size_t) pread (elf->fildes, scn->rawdata.d.d_buf, size,
elf->start_offset + offset) != size)
ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
elf->start_offset + offset);
if (unlikely ((size_t) n != size))
{
/* Cannot read the data. */
free (scn->rawdata.d.d_buf);
+10 -8
View File
@@ -1,5 +1,5 @@
/* Return section index of section header string table.
Copyright (C) 2002 Red Hat, Inc.
Copyright (C) 2002, 2005 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
This program is free software; you can redistribute it and/or modify
@@ -20,10 +20,12 @@
#endif
#include <assert.h>
#include <errno.h>
#include <gelf.h>
#include <stddef.h>
#include <unistd.h>
#include <system.h>
#include "libelfP.h"
#include "common.h"
@@ -100,8 +102,9 @@ elf_getshstrndx (elf, dst)
the first one. */
Elf32_Shdr shdr_mem;
if (pread (elf->fildes, &shdr_mem, sizeof (Elf32_Shdr),
offset) != sizeof (Elf32_Shdr))
if (unlikely (pread_retry (elf->fildes, &shdr_mem,
sizeof (Elf32_Shdr), offset)
!= sizeof (Elf32_Shdr)))
{
/* We must be able to read this ELF section header. */
__libelf_seterrno (ELF_E_INVALID_FILE);
@@ -116,15 +119,13 @@ elf_getshstrndx (elf, dst)
}
else
{
size_t offset;
if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
{
num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
goto success;
}
offset = elf->state.elf64.ehdr->e_shoff;
size_t offset = elf->state.elf64.ehdr->e_shoff;
if (elf->map_address != NULL
&& elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
@@ -139,8 +140,9 @@ elf_getshstrndx (elf, dst)
the first one. */
Elf64_Shdr shdr_mem;
if (pread (elf->fildes, &shdr_mem, sizeof (Elf64_Shdr),
offset) != sizeof (Elf64_Shdr))
if (unlikely (pread_retry (elf->fildes, &shdr_mem,
sizeof (Elf64_Shdr), offset)
!= sizeof (Elf64_Shdr)))
{
/* We must be able to read this ELF section header. */
__libelf_seterrno (ELF_E_INVALID_FILE);
+7 -3
View File
@@ -1,5 +1,5 @@
/* Read all of the file associated with the descriptor.
Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Red Hat, Inc.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
This program is free software; you can redistribute it and/or modify
@@ -19,8 +19,10 @@
# include <config.h>
#endif
#include <errno.h>
#include <unistd.h>
#include <system.h>
#include "libelfP.h"
#include "common.h"
@@ -78,8 +80,10 @@ __libelf_readall (elf)
if (mem != NULL)
{
/* Read the file content. */
if ((size_t) pread (elf->fildes, mem, elf->maximum_size,
elf->start_offset) != elf->maximum_size)
if (unlikely ((size_t) pread_retry (elf->fildes, mem,
elf->maximum_size,
elf->start_offset)
!= elf->maximum_size))
{
/* Something went wrong. */
__libelf_seterrno (ELF_E_READ_ERROR);
+9 -6
View File
@@ -1,5 +1,5 @@
/* Retrieve uninterpreted chunk of the file contents.
Copyright (C) 2002 Red Hat, Inc.
Copyright (C) 2002, 2005 Red Hat, Inc.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
This program is free software; you can redistribute it and/or modify
@@ -19,11 +19,13 @@
# include <config.h>
#endif
#include <errno.h>
#include <libelf.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <system.h>
#include "libelfP.h"
@@ -40,9 +42,9 @@ gelf_rawchunk (elf, offset, size)
return NULL;
}
if (offset >= elf->maximum_size
|| offset + size >= elf->maximum_size
|| offset + size < offset)
if (unlikely (offset >= elf->maximum_size
|| offset + size >= elf->maximum_size
|| offset + size < offset))
{
/* Invalid request. */
__libelf_seterrno (ELF_E_INVALID_OP);
@@ -59,8 +61,9 @@ gelf_rawchunk (elf, offset, size)
__libelf_seterrno (ELF_E_NOMEM);
else
/* Read the file content. */
if ((size_t) pread (elf->fildes, result, size, elf->start_offset + offset)
!= size)
if (unlikely ((size_t) pread_retry (elf->fildes, result, size,
elf->start_offset + offset)
!= size))
{
/* Something went wrong. */
__libelf_seterrno (ELF_E_READ_ERROR);
+2
View File
@@ -1,5 +1,7 @@
2005-08-28 Ulrich Drepper <drepper@redhat.com>
* ranlib.c: Don't define pread_retry and write_retry here.
* Makefile.an [BUILD_STATIC] (libdw): Add -ldl.
(CLEANFILES): Add *.gcno *.gcda *.gconv.
-5
View File
@@ -40,11 +40,6 @@
#include <system.h>
#define pread_retry(fd, buf, n, off) \
TEMP_FAILURE_RETRY (pread (fd, buf, n, off))
#define write_retry(fd, buf, n) \
TEMP_FAILURE_RETRY (write (fd, buf, n))
#if __BYTE_ORDER == __LITTLE_ENDIAN
# define le_bswap_32(val) bswap_32 (val)
#else