mirror of
https://github.com/rwinkhart/sys.git
synced 2026-08-28 04:46:44 -04:00
Add OpenBSD libc syscall wrappers for vectored I/O, and share the existing Darwin wrapper implementation and tests. Fixes golang/go#78049 Change-Id: Ie2743ef36a5cb73b05cc551c9c1108503f5992b6 Reviewed-on: https://go-review.googlesource.com/c/sys/+/771300 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> Reviewed-by: Ian Lance Taylor <iant@golang.org> Auto-Submit: Ian Lance Taylor <iant@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
96 lines
2.1 KiB
Go
96 lines
2.1 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 || openbsd
|
|
|
|
package unix
|
|
|
|
import "unsafe"
|
|
|
|
// This small allocation gets stack allocated, which lets the
|
|
// common use case of len(iovs) <= minIovec avoid more expensive
|
|
// heap allocations.
|
|
const minIovec = 8
|
|
|
|
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
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|