...

Source file src/internal/poll/writev.go

     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	}
    85	

View as plain text