mirror of
https://github.com/rwinkhart/sys.git
synced 2026-08-28 04:46:44 -04:00
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>
104 lines
2.5 KiB
Go
104 lines
2.5 KiB
Go
// Copyright 2026 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//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
|
|
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
|
|
}
|
|
|
|
// 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
|
|
}
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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
|
|
}
|
|
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 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)
|
|
n, err = preadv(fd, iovecs, offset)
|
|
readvRaceDetect(iovecs, n, err)
|
|
return n, err
|
|
}
|
|
|
|
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))
|
|
}
|
|
n, err = pwritev(fd, iovecs, offset)
|
|
writevRaceDetect(iovecs, n)
|
|
return n, err
|
|
}
|