Skip to content

Commit b0472e2

Browse files
internal/poll: don't use r/w lock for Pread/Pwrite
Since Pread/Pwrite specify a file offset, using incref is sufficient. This permits multiple Pread/Pwrite calls in parallel. Since Pread/Pwrite specify a file offset, it doesn't seem to make sense to use the poller for them, so don't. Updates #19586 Change-Id: I676be16bf519b9a45f8e6b1d991c44f10848bc11 Reviewed-on: https://go-review.googlesource.com/41670 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
1 parent 8ae60dc commit b0472e2

File tree

2 files changed

+23
-31
lines changed

2 files changed

+23
-31
lines changed

src/internal/poll/fd_unix.go

+15-27
Original file line numberDiff line numberDiff line change
@@ -122,29 +122,22 @@ func (fd *FD) Read(p []byte) (int, error) {
122122

123123
// Pread wraps the pread system call.
124124
func (fd *FD) Pread(p []byte, off int64) (int, error) {
125-
if err := fd.readLock(); err != nil {
126-
return 0, err
127-
}
128-
defer fd.readUnlock()
129-
if err := fd.pd.prepareRead(); err != nil {
125+
// Call incref, not readLock, because since pread specifies the
126+
// offset it is independent from other reads.
127+
// Similarly, using the poller doesn't make sense for pread.
128+
if err := fd.incref(); err != nil {
130129
return 0, err
131130
}
132131
if fd.IsStream && len(p) > maxRW {
133132
p = p[:maxRW]
134133
}
135-
for {
136-
n, err := syscall.Pread(fd.Sysfd, p, off)
137-
if err != nil {
138-
n = 0
139-
if err == syscall.EAGAIN {
140-
if err = fd.pd.waitRead(); err == nil {
141-
continue
142-
}
143-
}
144-
}
145-
err = fd.eofError(n, err)
146-
return n, err
134+
n, err := syscall.Pread(fd.Sysfd, p, off)
135+
if err != nil {
136+
n = 0
147137
}
138+
fd.decref()
139+
err = fd.eofError(n, err)
140+
return n, err
148141
}
149142

150143
// ReadFrom wraps the recvfrom network call.
@@ -233,13 +226,13 @@ func (fd *FD) Write(p []byte) (int, error) {
233226

234227
// Pwrite wraps the pwrite system call.
235228
func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
236-
if err := fd.writeLock(); err != nil {
237-
return 0, err
238-
}
239-
defer fd.writeUnlock()
240-
if err := fd.pd.prepareWrite(); err != nil {
229+
// Call incref, not writeLock, because since pwrite specifies the
230+
// offset it is independent from other writes.
231+
// Similarly, using the poller doesn't make sense for pwrite.
232+
if err := fd.incref(); err != nil {
241233
return 0, err
242234
}
235+
defer fd.decref()
243236
var nn int
244237
for {
245238
max := len(p)
@@ -253,11 +246,6 @@ func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
253246
if nn == len(p) {
254247
return nn, err
255248
}
256-
if err == syscall.EAGAIN {
257-
if err = fd.pd.waitWrite(); err == nil {
258-
continue
259-
}
260-
}
261249
if err != nil {
262250
return nn, err
263251
}

src/internal/poll/fd_windows.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -509,10 +509,12 @@ func (fd *FD) readConsole(b []byte) (int, error) {
509509

510510
// Pread emulates the Unix pread system call.
511511
func (fd *FD) Pread(b []byte, off int64) (int, error) {
512-
if err := fd.readLock(); err != nil {
512+
// Call incref, not readLock, because since pread specifies the
513+
// offset it is independent from other reads.
514+
if err := fd.incref(); err != nil {
513515
return 0, err
514516
}
515-
defer fd.readUnlock()
517+
defer fd.decref()
516518

517519
fd.l.Lock()
518520
defer fd.l.Unlock()
@@ -643,10 +645,12 @@ func (fd *FD) writeConsole(b []byte) (int, error) {
643645

644646
// Pwrite emulates the Unix pwrite system call.
645647
func (fd *FD) Pwrite(b []byte, off int64) (int, error) {
646-
if err := fd.writeLock(); err != nil {
648+
// Call incref, not writeLock, because since pwrite specifies the
649+
// offset it is independent from other writes.
650+
if err := fd.incref(); err != nil {
647651
return 0, err
648652
}
649-
defer fd.writeUnlock()
653+
defer fd.decref()
650654

651655
fd.l.Lock()
652656
defer fd.l.Unlock()

0 commit comments

Comments
 (0)