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
7package poll
8
9import (
10	"io"
11	"runtime"
12	"syscall"
13)
14
15// Writev wraps the writev system call.
16func (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		clear(iovecs)
73		if err != nil {
74			if err == syscall.EINTR {
75				continue
76			}
77			if err == syscall.EAGAIN {
78				if err = fd.pd.waitWrite(fd.isFile); err == nil {
79					continue
80				}
81			}
82			break
83		}
84		if n == 0 {
85			err = io.ErrUnexpectedEOF
86			break
87		}
88	}
89	return n, err
90}
91