splice_linux.mx raw

   1  // Copyright 2018 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  package net
   6  
   7  import (
   8  	"internal/poll"
   9  	"io"
  10  )
  11  
  12  var pollSplice = poll.Splice
  13  
  14  // spliceFrom transfers data from r to c using the splice system call to minimize
  15  // copies from and to userspace. c must be a TCP connection.
  16  // Currently, spliceFrom is only enabled if r is a TCP or a stream-oriented Unix connection.
  17  //
  18  // If spliceFrom returns handled == false, it has performed no work.
  19  func spliceFrom(c *netFD, r io.Reader) (written int64, err error, handled bool) {
  20  	var remain int64 = 1<<63 - 1 // by default, copy until EOF
  21  	lr, ok := r.(*io.LimitedReader)
  22  	if ok {
  23  		remain, r = lr.N, lr.R
  24  		if remain <= 0 {
  25  			return 0, nil, true
  26  		}
  27  	}
  28  
  29  	var s *netFD
  30  	switch v := r.(type) {
  31  	case *TCPConn:
  32  		s = v.fd
  33  	case tcpConnWithoutWriteTo:
  34  		s = v.fd
  35  	case *UnixConn:
  36  		if v.fd.net != "unix" {
  37  			return 0, nil, false
  38  		}
  39  		s = v.fd
  40  	default:
  41  		return 0, nil, false
  42  	}
  43  
  44  	written, handled, err = pollSplice(&c.pfd, &s.pfd, remain)
  45  	if lr != nil {
  46  		lr.N -= written
  47  	}
  48  	return written, wrapSyscallError("splice", err), handled
  49  }
  50  
  51  // spliceTo transfers data from c to w using the splice system call to minimize
  52  // copies from and to userspace. c must be a TCP connection.
  53  // Currently, spliceTo is only enabled if w is a stream-oriented Unix connection.
  54  //
  55  // If spliceTo returns handled == false, it has performed no work.
  56  func spliceTo(w io.Writer, c *netFD) (written int64, err error, handled bool) {
  57  	uc, ok := w.(*UnixConn)
  58  	if !ok || uc.fd.net != "unix" {
  59  		return
  60  	}
  61  
  62  	written, handled, err = pollSplice(&uc.fd.pfd, &c.pfd, 1<<63-1)
  63  	return written, wrapSyscallError("splice", err), handled
  64  }
  65