github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/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 darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd 6 // +build darwin dragonfly freebsd illumos linux netbsd openbsd 7 8 package poll 9 10 import ( 11 "io" 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 34 var n int64 35 var err error 36 for len(*v) > 0 { 37 iovecs = iovecs[:0] 38 for _, chunk := range *v { 39 if len(chunk) == 0 { 40 continue 41 } 42 iovecs = append(iovecs, newIovecWithBase(&chunk[0])) 43 if fd.IsStream && len(chunk) > 1<<30 { 44 iovecs[len(iovecs)-1].SetLen(1 << 30) 45 break // continue chunk on next writev 46 } 47 iovecs[len(iovecs)-1].SetLen(len(chunk)) 48 if len(iovecs) == maxVec { 49 break 50 } 51 } 52 if len(iovecs) == 0 { 53 break 54 } 55 if fd.iovecs == nil { 56 fd.iovecs = new([]syscall.Iovec) 57 } 58 *fd.iovecs = iovecs // cache 59 60 var wrote uintptr 61 wrote, err = writev(fd.Sysfd, iovecs) 62 if wrote == ^uintptr(0) { 63 wrote = 0 64 } 65 TestHookDidWritev(int(wrote)) 66 n += int64(wrote) 67 consume(v, int64(wrote)) 68 for i := range iovecs { 69 iovecs[i] = syscall.Iovec{} 70 } 71 if err != nil { 72 if err == syscall.EINTR { 73 continue 74 } 75 if err == syscall.EAGAIN { 76 if err = fd.pd.waitWrite(fd.isFile); err == nil { 77 continue 78 } 79 } 80 break 81 } 82 if n == 0 { 83 err = io.ErrUnexpectedEOF 84 break 85 } 86 } 87 return n, err 88 }