mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
PR30724, cygwin ld performance regression since 014a602b86
According to the reporter of this bug the newlib fseek implementation
is likely slowed down by locking and fflush, only attempting to
optimise seeks when the file is opened read-only. Thus when writing
the output we get a dramatic slowdown due to commit 014a602b86
.
PR 30724
* bfd.c (enum bfd_last_io): New.
(struct bfd): Add last_io field.
* bfd-in2.h: Regenerate.
* bfd-io.c (bfd_bread, bfd_bwrite): Force seek if last_io is
opposite direction.
(bfd_seek): Reinstate optimisation for seek to same position.
This commit is contained in:
parent
7570a17cbb
commit
f82ee0c8dc
@ -1916,6 +1916,14 @@ enum bfd_direction
|
||||
both_direction = 3
|
||||
};
|
||||
|
||||
enum bfd_last_io
|
||||
{
|
||||
bfd_io_seek = 0,
|
||||
bfd_io_read = 1,
|
||||
bfd_io_write = 2,
|
||||
bfd_io_force = 3
|
||||
};
|
||||
|
||||
enum bfd_plugin_format
|
||||
{
|
||||
bfd_plugin_unknown = 0,
|
||||
@ -2068,6 +2076,20 @@ struct bfd
|
||||
/* The direction with which the BFD was opened. */
|
||||
ENUM_BITFIELD (bfd_direction) direction : 2;
|
||||
|
||||
/* POSIX.1-2017 (IEEE Std 1003.1) says of fopen : "When a file is
|
||||
opened with update mode ('+' as the second or third character in
|
||||
the mode argument), both input and output may be performed on
|
||||
the associated stream. However, the application shall ensure
|
||||
that output is not directly followed by input without an
|
||||
intervening call to fflush() or to a file positioning function
|
||||
(fseek(), fsetpos(), or rewind()), and input is not directly
|
||||
followed by output without an intervening call to a file
|
||||
positioning function, unless the input operation encounters
|
||||
end-of-file."
|
||||
This field tracks the last IO operation, so that bfd can insert
|
||||
a seek when IO direction changes. */
|
||||
ENUM_BITFIELD (bfd_last_io) last_io : 2;
|
||||
|
||||
/* Is the file descriptor being cached? That is, can it be closed as
|
||||
needed, and re-opened when accessed later? */
|
||||
unsigned int cacheable : 1;
|
||||
|
22
bfd/bfd.c
22
bfd/bfd.c
@ -53,6 +53,14 @@ EXTERNAL
|
||||
. both_direction = 3
|
||||
. };
|
||||
.
|
||||
.enum bfd_last_io
|
||||
. {
|
||||
. bfd_io_seek = 0,
|
||||
. bfd_io_read = 1,
|
||||
. bfd_io_write = 2,
|
||||
. bfd_io_force = 3
|
||||
. };
|
||||
.
|
||||
.enum bfd_plugin_format
|
||||
. {
|
||||
. bfd_plugin_unknown = 0,
|
||||
@ -208,6 +216,20 @@ CODE_FRAGMENT
|
||||
. {* The direction with which the BFD was opened. *}
|
||||
. ENUM_BITFIELD (bfd_direction) direction : 2;
|
||||
.
|
||||
. {* POSIX.1-2017 (IEEE Std 1003.1) says of fopen : "When a file is
|
||||
. opened with update mode ('+' as the second or third character in
|
||||
. the mode argument), both input and output may be performed on
|
||||
. the associated stream. However, the application shall ensure
|
||||
. that output is not directly followed by input without an
|
||||
. intervening call to fflush() or to a file positioning function
|
||||
. (fseek(), fsetpos(), or rewind()), and input is not directly
|
||||
. followed by output without an intervening call to a file
|
||||
. positioning function, unless the input operation encounters
|
||||
. end-of-file."
|
||||
. This field tracks the last IO operation, so that bfd can insert
|
||||
. a seek when IO direction changes. *}
|
||||
. ENUM_BITFIELD (bfd_last_io) last_io : 2;
|
||||
.
|
||||
. {* Is the file descriptor being cached? That is, can it be closed as
|
||||
. needed, and re-opened when accessed later? *}
|
||||
. unsigned int cacheable : 1;
|
||||
|
23
bfd/bfdio.c
23
bfd/bfdio.c
@ -279,6 +279,14 @@ bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (abfd->last_io == bfd_io_write)
|
||||
{
|
||||
abfd->last_io = bfd_io_force;
|
||||
if (bfd_seek (abfd, 0, SEEK_CUR) != 0)
|
||||
return -1;
|
||||
}
|
||||
abfd->last_io = bfd_io_read;
|
||||
|
||||
nread = abfd->iovec->bread (abfd, ptr, size);
|
||||
if (nread != -1)
|
||||
abfd->where += nread;
|
||||
@ -313,6 +321,14 @@ bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (abfd->last_io == bfd_io_read)
|
||||
{
|
||||
abfd->last_io = bfd_io_force;
|
||||
if (bfd_seek (abfd, 0, SEEK_CUR) != 0)
|
||||
return -1;
|
||||
}
|
||||
abfd->last_io = bfd_io_write;
|
||||
|
||||
nwrote = abfd->iovec->bwrite (abfd, ptr, size);
|
||||
if (nwrote != -1)
|
||||
abfd->where += nwrote;
|
||||
@ -456,6 +472,13 @@ bfd_seek (bfd *abfd, file_ptr position, int direction)
|
||||
if (direction != SEEK_CUR)
|
||||
position += offset;
|
||||
|
||||
if (((direction == SEEK_CUR && position == 0)
|
||||
|| (direction == SEEK_SET && (ufile_ptr) position == abfd->where))
|
||||
&& abfd->last_io != bfd_io_force)
|
||||
return 0;
|
||||
|
||||
abfd->last_io = bfd_io_seek;
|
||||
|
||||
result = abfd->iovec->bseek (abfd, position, direction);
|
||||
if (result != 0)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user