github.com/FISCO-BCOS/crypto@v0.0.0-20200202032121-bd8ab0b5d4f1/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 // +build darwin dragonfly freebsd linux netbsd openbsd 6 7 package poll 8 9 import ( 10 "io" 11 "syscall" 12 ) 13 14 // Writev wraps the writev system call. 15 func (fd *FD) Writev(v *[][]byte) (int64, error) { 16 if err := fd.writeLock(); err != nil { 17 return 0, err 18 } 19 defer fd.writeUnlock() 20 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 21 return 0, err 22 } 23 24 var iovecs []syscall.Iovec 25 if fd.iovecs != nil { 26 iovecs = *fd.iovecs 27 } 28 // TODO: read from sysconf(_SC_IOV_MAX)? The Linux default is 29 // 1024 and this seems conservative enough for now. Darwin's 30 // UIO_MAXIOV also seems to be 1024. 31 maxVec := 1024 32 33 var n int64 34 var err error 35 for len(*v) > 0 { 36 iovecs = iovecs[:0] 37 for _, chunk := range *v { 38 if len(chunk) == 0 { 39 continue 40 } 41 iovecs = append(iovecs, syscall.Iovec{Base: &chunk[0]}) 42 if fd.IsStream && len(chunk) > 1<<30 { 43 iovecs[len(iovecs)-1].SetLen(1 << 30) 44 break // continue chunk on next writev 45 } 46 iovecs[len(iovecs)-1].SetLen(len(chunk)) 47 if len(iovecs) == maxVec { 48 break 49 } 50 } 51 if len(iovecs) == 0 { 52 break 53 } 54 if fd.iovecs == nil { 55 fd.iovecs = new([]syscall.Iovec) 56 } 57 *fd.iovecs = iovecs // cache 58 59 var wrote uintptr 60 wrote, err = writev(fd.Sysfd, iovecs) 61 if wrote == ^uintptr(0) { 62 wrote = 0 63 } 64 TestHookDidWritev(int(wrote)) 65 n += int64(wrote) 66 consume(v, int64(wrote)) 67 for i := range iovecs { 68 iovecs[i] = syscall.Iovec{} 69 } 70 if err != nil { 71 if err.(syscall.Errno) == syscall.EAGAIN { 72 if err = fd.pd.waitWrite(fd.isFile); err == nil { 73 continue 74 } 75 } 76 break 77 } 78 if n == 0 { 79 err = io.ErrUnexpectedEOF 80 break 81 } 82 } 83 return n, err 84 }