Skip to content

Commit 3330b5e

Browse files
mschoenlaubgopherbot
authored andcommitted
unix: support Readv, Preadv, Writev and Pwritev for darwin
Darwin, starting with Big Sur, supports vectorized IO. Fixes golang/go#64710 Change-Id: Ic3a3c51009eab24f70665d8d3a145b328a7713c6 Reviewed-on: https://go-review.googlesource.com/c/sys/+/548795 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
1 parent 7401cce commit 3330b5e

7 files changed

+363
-1
lines changed

unix/darwin_amd64_test.go

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/darwin_arm64_test.go

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/syscall_darwin.go

+148-1
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,150 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI
602602
return
603603
}
604604

605-
//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error)
605+
// sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error)
606+
const minIovec = 8
607+
608+
func Readv(fd int, iovs [][]byte) (n int, err error) {
609+
if !darwinKernelVersionMin(11, 0, 0) {
610+
return 0, ENOSYS
611+
}
612+
613+
iovecs := make([]Iovec, 0, minIovec)
614+
iovecs = appendBytes(iovecs, iovs)
615+
n, err = readv(fd, iovecs)
616+
readvRacedetect(iovecs, n, err)
617+
return n, err
618+
}
619+
620+
func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) {
621+
if !darwinKernelVersionMin(11, 0, 0) {
622+
return 0, ENOSYS
623+
}
624+
iovecs := make([]Iovec, 0, minIovec)
625+
iovecs = appendBytes(iovecs, iovs)
626+
n, err = preadv(fd, iovecs, offset)
627+
readvRacedetect(iovecs, n, err)
628+
return n, err
629+
}
630+
631+
func Writev(fd int, iovs [][]byte) (n int, err error) {
632+
if !darwinKernelVersionMin(11, 0, 0) {
633+
return 0, ENOSYS
634+
}
635+
636+
iovecs := make([]Iovec, 0, minIovec)
637+
iovecs = appendBytes(iovecs, iovs)
638+
if raceenabled {
639+
raceReleaseMerge(unsafe.Pointer(&ioSync))
640+
}
641+
n, err = writev(fd, iovecs)
642+
writevRacedetect(iovecs, n)
643+
return n, err
644+
}
645+
646+
func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) {
647+
if !darwinKernelVersionMin(11, 0, 0) {
648+
return 0, ENOSYS
649+
}
650+
651+
iovecs := make([]Iovec, 0, minIovec)
652+
iovecs = appendBytes(iovecs, iovs)
653+
if raceenabled {
654+
raceReleaseMerge(unsafe.Pointer(&ioSync))
655+
}
656+
n, err = pwritev(fd, iovecs, offset)
657+
writevRacedetect(iovecs, n)
658+
return n, err
659+
}
660+
661+
func appendBytes(vecs []Iovec, bs [][]byte) []Iovec {
662+
for _, b := range bs {
663+
var v Iovec
664+
v.SetLen(len(b))
665+
if len(b) > 0 {
666+
v.Base = &b[0]
667+
} else {
668+
v.Base = (*byte)(unsafe.Pointer(&_zero))
669+
}
670+
vecs = append(vecs, v)
671+
}
672+
return vecs
673+
}
674+
675+
func writevRacedetect(iovecs []Iovec, n int) {
676+
if !raceenabled {
677+
return
678+
}
679+
for i := 0; n > 0 && i < len(iovecs); i++ {
680+
m := int(iovecs[i].Len)
681+
if m > n {
682+
m = n
683+
}
684+
n -= m
685+
if m > 0 {
686+
raceReadRange(unsafe.Pointer(iovecs[i].Base), m)
687+
}
688+
}
689+
}
690+
691+
func readvRacedetect(iovecs []Iovec, n int, err error) {
692+
if !raceenabled {
693+
return
694+
}
695+
for i := 0; n > 0 && i < len(iovecs); i++ {
696+
m := int(iovecs[i].Len)
697+
if m > n {
698+
m = n
699+
}
700+
n -= m
701+
if m > 0 {
702+
raceWriteRange(unsafe.Pointer(iovecs[i].Base), m)
703+
}
704+
}
705+
if err == nil {
706+
raceAcquire(unsafe.Pointer(&ioSync))
707+
}
708+
}
709+
710+
func darwinMajorMinPatch() (maj, min, patch int, err error) {
711+
var un Utsname
712+
err = Uname(&un)
713+
if err != nil {
714+
return
715+
}
716+
717+
var mmp [3]int
718+
c := 0
719+
Loop:
720+
for _, b := range un.Release[:] {
721+
switch {
722+
case b >= '0' && b <= '9':
723+
mmp[c] = 10*mmp[c] + int(b-'0')
724+
case b == '.':
725+
c++
726+
if c > 2 {
727+
return 0, 0, 0, ENOTSUP
728+
}
729+
case b == 0:
730+
break Loop
731+
default:
732+
return 0, 0, 0, ENOTSUP
733+
}
734+
}
735+
if c != 2 {
736+
return 0, 0, 0, ENOTSUP
737+
}
738+
return mmp[0], mmp[1], mmp[2], nil
739+
}
740+
741+
func darwinKernelVersionMin(maj, min, patch int) bool {
742+
actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch()
743+
if err != nil {
744+
return false
745+
}
746+
return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch)
747+
}
748+
606749
//sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)
607750

608751
//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error)
@@ -705,3 +848,7 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI
705848
//sys write(fd int, p []byte) (n int, err error)
706849
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
707850
//sys munmap(addr uintptr, length uintptr) (err error)
851+
//sys readv(fd int, iovecs []Iovec) (n int, err error)
852+
//sys preadv(fd int, iovecs []Iovec, offset int64) (n int, err error)
853+
//sys writev(fd int, iovecs []Iovec) (n int, err error)
854+
//sys pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error)

unix/zsyscall_darwin_amd64.go

+84
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/zsyscall_darwin_amd64.s

+20
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,26 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0
738738
GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8
739739
DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB)
740740

741+
TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0
742+
JMP libc_readv(SB)
743+
GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8
744+
DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB)
745+
746+
TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0
747+
JMP libc_preadv(SB)
748+
GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8
749+
DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB)
750+
751+
TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0
752+
JMP libc_writev(SB)
753+
GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8
754+
DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB)
755+
756+
TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0
757+
JMP libc_pwritev(SB)
758+
GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8
759+
DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB)
760+
741761
TEXT libc_fstat64_trampoline<>(SB),NOSPLIT,$0-0
742762
JMP libc_fstat64(SB)
743763
GLOBL ·libc_fstat64_trampoline_addr(SB), RODATA, $8

0 commit comments

Comments
 (0)