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.
5 // +build darwin dragonfly freebsd linux netbsd openbsd
15 // Writev wraps the writev system call.
16 func (fd
*FD
) Writev(v
*[][]byte) (int64, error
) {
17 if err
:= fd
.writeLock(); err
!= nil {
20 defer fd
.writeUnlock()
21 if err
:= fd
.pd
.prepareWrite(fd
.isFile
); err
!= nil {
25 var iovecs
[]syscall
.Iovec
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.
38 for _
, chunk
:= range *v
{
42 iovecs
= append(iovecs
, syscall
.Iovec
{Base
: &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
47 iovecs
[len(iovecs
)-1].SetLen(len(chunk
))
48 if len(iovecs
) == maxVec
{
55 fd
.iovecs
= &iovecs
// cache
57 wrote
, _
, e0
:= syscall
.Syscall(syscall
.SYS_WRITEV
,
59 uintptr(unsafe
.Pointer(&iovecs
[0])),
61 if wrote
== ^uintptr(0) {
64 TestHookDidWritev(int(wrote
))
66 consume(v
, int64(wrote
))
67 if e0
== syscall
.EAGAIN
{
68 if err
= fd
.pd
.waitWrite(fd
.isFile
); err
== nil {
72 err
= syscall
.Errno(e0
)
78 err
= io
.ErrUnexpectedEOF