unix: merge Linux readv/writev implementation with Darwin/OpenBSD

This reduces some code duplication.

Change-Id: Ib648f90a26960d0bc25d2fe27e9b3fb1419ac02d
Reviewed-on: https://go-review.googlesource.com/c/sys/+/777161
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/readv_unix.go b/unix/readv_unix.go
index 7725ec8..38a2be9 100644
--- a/unix/readv_unix.go
+++ b/unix/readv_unix.go
@@ -2,17 +2,21 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build darwin || openbsd
+//go:build darwin || linux || openbsd
 
 package unix
 
 import "unsafe"
 
+// minIovec is the size of the small initial allocation used by
+// Readv, Writev, etc.
+//
 // This small allocation gets stack allocated, which lets the
 // common use case of len(iovs) <= minIovec avoid more expensive
 // heap allocations.
 const minIovec = 8
 
+// appendBytes converts bs to Iovecs and appends them to vecs.
 func appendBytes(vecs []Iovec, bs [][]byte) []Iovec {
 	for _, b := range bs {
 		var v Iovec
@@ -27,7 +31,9 @@
 	return vecs
 }
 
-func writevRacedetect(iovecs []Iovec, n int) {
+// writevRaceDetect tells the race detector that the program
+// has read the first n bytes stored in iovecs.
+func writevRaceDetect(iovecs []Iovec, n int) {
 	if !raceenabled {
 		return
 	}
@@ -40,7 +46,9 @@
 	}
 }
 
-func readvRacedetect(iovecs []Iovec, n int, err error) {
+// readvRaceDetect tells the race detector that the program
+// has written to the first n bytes stored in iovecs.
+func readvRaceDetect(iovecs []Iovec, n int, err error) {
 	if !raceenabled {
 		return
 	}
@@ -60,7 +68,7 @@
 	iovecs := make([]Iovec, 0, minIovec)
 	iovecs = appendBytes(iovecs, iovs)
 	n, err = readv(fd, iovecs)
-	readvRacedetect(iovecs, n, err)
+	readvRaceDetect(iovecs, n, err)
 	return n, err
 }
 
@@ -68,7 +76,7 @@
 	iovecs := make([]Iovec, 0, minIovec)
 	iovecs = appendBytes(iovecs, iovs)
 	n, err = preadv(fd, iovecs, offset)
-	readvRacedetect(iovecs, n, err)
+	readvRaceDetect(iovecs, n, err)
 	return n, err
 }
 
@@ -79,7 +87,7 @@
 		raceReleaseMerge(unsafe.Pointer(&ioSync))
 	}
 	n, err = writev(fd, iovecs)
-	writevRacedetect(iovecs, n)
+	writevRaceDetect(iovecs, n)
 	return n, err
 }
 
@@ -90,6 +98,6 @@
 		raceReleaseMerge(unsafe.Pointer(&ioSync))
 	}
 	n, err = pwritev(fd, iovecs, offset)
-	writevRacedetect(iovecs, n)
+	writevRaceDetect(iovecs, n)
 	return n, err
 }
diff --git a/unix/readv_unix_test.go b/unix/readv_unix_test.go
index f753e61..2193c42 100644
--- a/unix/readv_unix_test.go
+++ b/unix/readv_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build darwin || openbsd
+//go:build darwin || linux || openbsd
 
 package unix_test
 
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index f7b82bc..ce4d7ab 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -2150,33 +2150,10 @@
 //sys	exitThread(code int) (err error) = SYS_EXIT
 //sys	readv(fd int, iovs []Iovec) (n int, err error) = SYS_READV
 //sys	writev(fd int, iovs []Iovec) (n int, err error) = SYS_WRITEV
-//sys	preadv(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PREADV
-//sys	pwritev(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PWRITEV
-//sys	preadv2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PREADV2
-//sys	pwritev2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PWRITEV2
-
-// minIovec is the size of the small initial allocation used by
-// Readv, Writev, etc.
-//
-// This small allocation gets stack allocated, which lets the
-// common use case of len(iovs) <= minIovs avoid more expensive
-// heap allocations.
-const minIovec = 8
-
-// appendBytes converts bs to Iovecs and appends them to vecs.
-func appendBytes(vecs []Iovec, bs [][]byte) []Iovec {
-	for _, b := range bs {
-		var v Iovec
-		v.SetLen(len(b))
-		if len(b) > 0 {
-			v.Base = &b[0]
-		} else {
-			v.Base = (*byte)(unsafe.Pointer(&_zero))
-		}
-		vecs = append(vecs, v)
-	}
-	return vecs
-}
+//sys	preadvSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PREADV
+//sys	pwritevSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PWRITEV
+//sys	preadv2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PREADV2
+//sys	pwritev2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PWRITEV2
 
 // offs2lohi splits offs into its low and high order bits.
 func offs2lohi(offs int64) (lo, hi uintptr) {
@@ -2184,69 +2161,23 @@
 	return uintptr(offs), uintptr(uint64(offs) >> (longBits - 1) >> 1) // two shifts to avoid false positive in vet
 }
 
-func Readv(fd int, iovs [][]byte) (n int, err error) {
-	iovecs := make([]Iovec, 0, minIovec)
-	iovecs = appendBytes(iovecs, iovs)
-	n, err = readv(fd, iovecs)
-	readvRacedetect(iovecs, n, err)
-	return n, err
-}
-
-func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) {
-	iovecs := make([]Iovec, 0, minIovec)
-	iovecs = appendBytes(iovecs, iovs)
+func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) {
 	lo, hi := offs2lohi(offset)
-	n, err = preadv(fd, iovecs, lo, hi)
-	readvRacedetect(iovecs, n, err)
-	return n, err
+	return preadvSyscall(fd, iovecs, lo, hi)
 }
 
 func Preadv2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) {
 	iovecs := make([]Iovec, 0, minIovec)
 	iovecs = appendBytes(iovecs, iovs)
 	lo, hi := offs2lohi(offset)
-	n, err = preadv2(fd, iovecs, lo, hi, flags)
-	readvRacedetect(iovecs, n, err)
+	n, err = preadv2Syscall(fd, iovecs, lo, hi, flags)
+	readvRaceDetect(iovecs, n, err)
 	return n, err
 }
 
-func readvRacedetect(iovecs []Iovec, n int, err error) {
-	if !raceenabled {
-		return
-	}
-	for i := 0; n > 0 && i < len(iovecs); i++ {
-		m := min(int(iovecs[i].Len), n)
-		n -= m
-		if m > 0 {
-			raceWriteRange(unsafe.Pointer(iovecs[i].Base), m)
-		}
-	}
-	if err == nil {
-		raceAcquire(unsafe.Pointer(&ioSync))
-	}
-}
-
-func Writev(fd int, iovs [][]byte) (n int, err error) {
-	iovecs := make([]Iovec, 0, minIovec)
-	iovecs = appendBytes(iovecs, iovs)
-	if raceenabled {
-		raceReleaseMerge(unsafe.Pointer(&ioSync))
-	}
-	n, err = writev(fd, iovecs)
-	writevRacedetect(iovecs, n)
-	return n, err
-}
-
-func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) {
-	iovecs := make([]Iovec, 0, minIovec)
-	iovecs = appendBytes(iovecs, iovs)
-	if raceenabled {
-		raceReleaseMerge(unsafe.Pointer(&ioSync))
-	}
+func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) {
 	lo, hi := offs2lohi(offset)
-	n, err = pwritev(fd, iovecs, lo, hi)
-	writevRacedetect(iovecs, n)
-	return n, err
+	return pwritevSyscall(fd, iovecs, lo, hi)
 }
 
 func Pwritev2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) {
@@ -2256,24 +2187,11 @@
 		raceReleaseMerge(unsafe.Pointer(&ioSync))
 	}
 	lo, hi := offs2lohi(offset)
-	n, err = pwritev2(fd, iovecs, lo, hi, flags)
-	writevRacedetect(iovecs, n)
+	n, err = pwritev2Syscall(fd, iovecs, lo, hi, flags)
+	writevRaceDetect(iovecs, n)
 	return n, err
 }
 
-func writevRacedetect(iovecs []Iovec, n int) {
-	if !raceenabled {
-		return
-	}
-	for i := 0; n > 0 && i < len(iovecs); i++ {
-		m := min(int(iovecs[i].Len), n)
-		n -= m
-		if m > 0 {
-			raceReadRange(unsafe.Pointer(iovecs[i].Base), m)
-		}
-	}
-}
-
 // mmap varies by architecture; see syscall_linux_*.go.
 //sys	munmap(addr uintptr, length uintptr) (err error)
 //sys	mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go
index 886f5de..80f40e4 100644
--- a/unix/zsyscall_linux.go
+++ b/unix/zsyscall_linux.go
@@ -1785,7 +1785,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func preadv(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) {
+func preadvSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(iovs) > 0 {
 		_p0 = unsafe.Pointer(&iovs[0])
@@ -1802,7 +1802,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pwritev(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) {
+func pwritevSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(iovs) > 0 {
 		_p0 = unsafe.Pointer(&iovs[0])
@@ -1819,7 +1819,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func preadv2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) {
+func preadv2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(iovs) > 0 {
 		_p0 = unsafe.Pointer(&iovs[0])
@@ -1836,7 +1836,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pwritev2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) {
+func pwritev2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(iovs) > 0 {
 		_p0 = unsafe.Pointer(&iovs[0])