Skip to content

implements the writev. #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: release-branch.go1.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/go1.5.txt
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,7 @@ pkg net/mail, type AddressParser struct, WordDecoder *mime.WordDecoder
pkg net/smtp, method (*Client) TLSConnectionState() (tls.ConnectionState, bool)
pkg net/url, method (*URL) EscapedPath() string
pkg net/url, type URL struct, RawPath string
pkg net, method (*TCPConn) Writev([][]uint8) (int, error)
pkg os, func LookupEnv(string) (string, bool)
pkg os/signal, func Ignore(...os.Signal)
pkg os/signal, func Reset(...os.Signal)
Expand Down
78 changes: 78 additions & 0 deletions src/net/fd_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"sync/atomic"
"syscall"
"time"
"unsafe"
//"fmt"
)

// Network file descriptor.
Expand All @@ -29,6 +31,9 @@ type netFD struct {
laddr Addr
raddr Addr

// writev cache.
iovecs []syscall.Iovec

// wait server
pd pollDesc
}
Expand Down Expand Up @@ -333,6 +338,79 @@ func (fd *netFD) Write(p []byte) (nn int, err error) {
return nn, err
}

func (fd *netFD) Writev(p [][]byte) (nn int, err error) {
if err := fd.writeLock(); err != nil {
return 0, err
}
defer fd.writeUnlock()
if err := fd.pd.PrepareWrite(); err != nil {
return 0, err
}
// convert to iovec for writev.
if cap(fd.iovecs) < len(p) {
fd.iovecs = make([]syscall.Iovec, 0, 2*len(p))
}
iovecs := fd.iovecs[0:len(p)]
// total bytes to sent.
var total int
for i, iovec := range p {
iovecs[i].Base = &iovec[0]
iovecs[i].Len = uint64(len(iovec))
total += len(iovec)
}
//fmt.Println(fmt.Sprintf("writev %v iovecs, total %v bytes", len(p), total))
for {
// send from last work point.
var index int
var left int = nn
for i, iov := range p {
if left = left - len(iov); left < 0 {
index = i
break
}
}
iovec := p[index][len(p[index])+left:]
iovecs[index].Base = &iovec[0]
iovecs[index].Len = uint64(len(iovec))
// to ptr and len.
ptr := uintptr(unsafe.Pointer(&iovecs[index]))
nbPtr := uintptr(len(iovecs) - index)
// max iovec to send is 1024
// TODO: FIXME: read from sysconf.
if int(nbPtr) > 1024 {
nbPtr = uintptr(1024)
}
var n int
r0, _, e0 := syscall.Syscall(syscall.SYS_WRITEV, uintptr(fd.sysfd), ptr, nbPtr)
if e0 != 0 {
err = syscall.Errno(e0)
}
if n = int(r0); n > 0 {
nn += n
}
//fmt.Println(fmt.Sprintf(" %v:%v:%v %v/%v %v", index, left, len(p[index]) - len(iovec), nn, total, err))
if nn == total {
break
}
if err == syscall.EAGAIN {
if err = fd.pd.WaitWrite(); err == nil {
continue
}
}
if err != nil {
break
}
if n == 0 {
err = io.ErrUnexpectedEOF
break
}
}
if _, ok := err.(syscall.Errno); ok {
err = os.NewSyscallError("write", err)
}
return nn, err
}

func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
if err := fd.writeLock(); err != nil {
return 0, err
Expand Down
11 changes: 11 additions & 0 deletions src/net/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,17 @@ func (c *conn) Write(b []byte) (int, error) {
return n, err
}

func (c *conn) writev(b [][]byte) (int, error) {
if !c.ok() {
return 0,syscall.EINVAL
}
n,err := c.fd.Writev(b)
if err != nil {
err = &OpError{Op: "writev", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
}
return n,err
}

// Close closes the connection.
func (c *conn) Close() error {
if !c.ok() {
Expand Down
4 changes: 4 additions & 0 deletions src/net/tcpsock_posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ func newTCPConn(fd *netFD) *TCPConn {
return c
}

func (c *TCPConn) Writev(b [][]byte) (n int, err error) {
return c.conn.writev(b)
}

// ReadFrom implements the io.ReaderFrom ReadFrom method.
func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
if n, err, handled := sendFile(c.fd, r); handled {
Expand Down