github.com/bir3/gocompiler@v0.9.2202/src/internal/poll/writev.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build unix 6 7 package poll 8 9 import ( 10 "io" 11 "runtime" 12 "syscall" 13 ) 14 15 // Writev wraps the writev system call. 16 func (fd *FD) Writev(v *[][]byte) (int64, error) { 17 if err := fd.writeLock(); err != nil { 18 return 0, err 19 } 20 defer fd.writeUnlock() 21 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 22 return 0, err 23 } 24 25 var iovecs []syscall.Iovec 26 if fd.iovecs != nil { 27 iovecs = *fd.iovecs 28 } 29 // TODO: read from sysconf(_SC_IOV_MAX)? The Linux default is 30 // 1024 and this seems conservative enough for now. Darwin's 31 // UIO_MAXIOV also seems to be 1024. 32 maxVec := 1024 33 if runtime.GOOS == "aix" || runtime.GOOS == "solaris" { 34 // IOV_MAX is set to XOPEN_IOV_MAX on AIX and Solaris. 35 maxVec = 16 36 } 37 38 var n int64 39 var err error 40 for len(*v) > 0 { 41 iovecs = iovecs[:0] 42 for _, chunk := range *v { 43 if len(chunk) == 0 { 44 continue 45 } 46 iovecs = append(iovecs, newIovecWithBase(&chunk[0])) 47 if fd.IsStream && len(chunk) > 1<<30 { 48 iovecs[len(iovecs)-1].SetLen(1 << 30) 49 break // continue chunk on next writev 50 } 51 iovecs[len(iovecs)-1].SetLen(len(chunk)) 52 if len(iovecs) == maxVec { 53 break 54 } 55 } 56 if len(iovecs) == 0 { 57 break 58 } 59 if fd.iovecs == nil { 60 fd.iovecs = new([]syscall.Iovec) 61 } 62 *fd.iovecs = iovecs // cache 63 64 var wrote uintptr 65 wrote, err = writev(fd.Sysfd, iovecs) 66 if wrote == ^uintptr(0) { 67 wrote = 0 68 } 69 TestHookDidWritev(int(wrote)) 70 n += int64(wrote) 71 consume(v, int64(wrote)) 72 for i := range iovecs { 73 iovecs[i] = syscall.Iovec{} 74 } 75 if err != nil { 76 if err == syscall.EINTR { 77 continue 78 } 79 if err == syscall.EAGAIN { 80 if err = fd.pd.waitWrite(fd.isFile); err == nil { 81 continue 82 } 83 } 84 break 85 } 86 if n == 0 { 87 err = io.ErrUnexpectedEOF 88 break 89 } 90 } 91 return n, err 92 }