From: Ian Lance Taylor Date: Tue, 25 Apr 2017 04:01:08 +0000 (-0700) Subject: internal/poll: don't use r/w lock for Pread/Pwrite X-Git-Tag: go1.9beta1~498 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b0472e225bddf7c7ba2b61f10339106719f25b7f;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index f3e3c53d65..c461f04c39 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -122,29 +122,22 @@ func (fd *FD) Read(p []byte) (int, error) { // Pread wraps the pread system call. func (fd *FD) Pread(p []byte, off int64) (int, error) { - if err := fd.readLock(); err != nil { - return 0, err - } - defer fd.readUnlock() - if err := fd.pd.prepareRead(); err != nil { + // Call incref, not readLock, because since pread specifies the + // offset it is independent from other reads. + // Similarly, using the poller doesn't make sense for pread. + if err := fd.incref(); err != nil { return 0, err } if fd.IsStream && len(p) > maxRW { p = p[:maxRW] } - for { - n, err := syscall.Pread(fd.Sysfd, p, off) - if err != nil { - n = 0 - if err == syscall.EAGAIN { - if err = fd.pd.waitRead(); err == nil { - continue - } - } - } - err = fd.eofError(n, err) - return n, err + n, err := syscall.Pread(fd.Sysfd, p, off) + if err != nil { + n = 0 } + fd.decref() + err = fd.eofError(n, err) + return n, err } // ReadFrom wraps the recvfrom network call. @@ -233,13 +226,13 @@ func (fd *FD) Write(p []byte) (int, error) { // Pwrite wraps the pwrite system call. func (fd *FD) Pwrite(p []byte, off int64) (int, error) { - if err := fd.writeLock(); err != nil { - return 0, err - } - defer fd.writeUnlock() - if err := fd.pd.prepareWrite(); err != nil { + // Call incref, not writeLock, because since pwrite specifies the + // offset it is independent from other writes. + // Similarly, using the poller doesn't make sense for pwrite. + if err := fd.incref(); err != nil { return 0, err } + defer fd.decref() var nn int for { max := len(p) @@ -253,11 +246,6 @@ func (fd *FD) Pwrite(p []byte, off int64) (int, error) { if nn == len(p) { return nn, err } - if err == syscall.EAGAIN { - if err = fd.pd.waitWrite(); err == nil { - continue - } - } if err != nil { return nn, err } diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 89a4ea904c..4d7ec686d4 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -509,10 +509,12 @@ func (fd *FD) readConsole(b []byte) (int, error) { // Pread emulates the Unix pread system call. func (fd *FD) Pread(b []byte, off int64) (int, error) { - if err := fd.readLock(); err != nil { + // Call incref, not readLock, because since pread specifies the + // offset it is independent from other reads. + if err := fd.incref(); err != nil { return 0, err } - defer fd.readUnlock() + defer fd.decref() fd.l.Lock() defer fd.l.Unlock() @@ -643,10 +645,12 @@ func (fd *FD) writeConsole(b []byte) (int, error) { // Pwrite emulates the Unix pwrite system call. func (fd *FD) Pwrite(b []byte, off int64) (int, error) { - if err := fd.writeLock(); err != nil { + // Call incref, not writeLock, because since pwrite specifies the + // offset it is independent from other writes. + if err := fd.incref(); err != nil { return 0, err } - defer fd.writeUnlock() + defer fd.decref() fd.l.Lock() defer fd.l.Unlock()