]> Cypherpunks repositories - gostls13.git/commitdiff
net: Sendfile for win32.
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Sat, 11 Jun 2011 03:24:48 +0000 (13:24 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Sat, 11 Jun 2011 03:24:48 +0000 (13:24 +1000)
implement using TransmitFile().

R=bsiegert, bradfitz, alex.brainman, rsc, go.peter.90
CC=golang-dev
https://golang.org/cl/4536076

src/pkg/net/Makefile
src/pkg/net/sendfile_windows.go [new file with mode: 0644]
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/zsyscall_windows_386.go
src/pkg/syscall/ztypes_windows_386.go

index 5472df39257a7cb936be8352eb531bfdb0d26bd1..c762122f2d2e5ff9359f3cc70adc1bcad9208493 100644 (file)
@@ -82,7 +82,7 @@ GOFILES_windows=\
        file_windows.go\
        interface_stub.go\
        resolv_windows.go\
-       sendfile_stub.go\
+       sendfile_windows.go\
        sock_windows.go\
 
 GOFILES+=$(GOFILES_$(GOOS))
diff --git a/src/pkg/net/sendfile_windows.go b/src/pkg/net/sendfile_windows.go
new file mode 100644 (file)
index 0000000..34abc54
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+       "io"
+       "os"
+       "syscall"
+)
+
+type sendfileOp struct {
+       anOp
+       src int32 // source
+       n   uint32
+}
+
+func (o *sendfileOp) Submit() (errno int) {
+       return syscall.TransmitFile(int32(o.fd.sysfd), o.src, o.n, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
+}
+
+func (o *sendfileOp) Name() string {
+       return "TransmitFile"
+}
+
+// sendFile copies the contents of r to c using the TransmitFile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+//
+// Note that sendfile for windows does not suppport >2GB file.
+func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool) {
+       var n int64 = 0 // by default, copy until EOF
+
+       lr, ok := r.(*io.LimitedReader)
+       if ok {
+               n, r = lr.N, lr.R
+               if n <= 0 {
+                       return 0, nil, true
+               }
+       }
+       f, ok := r.(*os.File)
+       if !ok {
+               return 0, nil, false
+       }
+
+       c.wio.Lock()
+       defer c.wio.Unlock()
+       c.incref()
+       defer c.decref()
+
+       var o sendfileOp
+       o.Init(c)
+       o.n = uint32(n)
+       o.src = int32(f.Fd())
+       done, err := iosrv.ExecIO(&o, 0)
+       if err != nil {
+               return 0, err, false
+       }
+       if lr != nil {
+               lr.N -= int64(done)
+       }
+       return int64(done), nil, true
+}
index d01664d126c032957b6081049ad068a18cf008f4..c9bcb37ecb9bc3bc0a7dc709c1deefc40dbe976f 100644 (file)
@@ -173,6 +173,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno
 //sys  FlushViewOfFile(addr uintptr, length uintptr) (errno int)
 //sys  VirtualLock(addr uintptr, length uintptr) (errno int)
 //sys  VirtualUnlock(addr uintptr, length uintptr) (errno int)
+//sys  TransmitFile(s int32, handle int32, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (errno int) = wsock32.TransmitFile
 
 // syscall interface implementation for other packages
 
index 447b09043e91baccf22bab4cf5e81743e27e10bf..c72cf7351c350065d1934fa18d00e9b12ecc0dd3 100644 (file)
@@ -77,6 +77,7 @@ var (
        procFlushViewOfFile            = getSysProcAddr(modkernel32, "FlushViewOfFile")
        procVirtualLock                = getSysProcAddr(modkernel32, "VirtualLock")
        procVirtualUnlock              = getSysProcAddr(modkernel32, "VirtualUnlock")
+       procTransmitFile               = getSysProcAddr(modwsock32, "TransmitFile")
        procWSAStartup                 = getSysProcAddr(modwsock32, "WSAStartup")
        procWSACleanup                 = getSysProcAddr(modwsock32, "WSACleanup")
        procsocket                     = getSysProcAddr(modwsock32, "socket")
@@ -1008,6 +1009,20 @@ func VirtualUnlock(addr uintptr, length uintptr) (errno int) {
        return
 }
 
+func TransmitFile(s int32, handle int32, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (errno int) {
+       r1, _, e1 := Syscall9(procTransmitFile, 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0)
+       if int(r1) == 0 {
+               if e1 != 0 {
+                       errno = int(e1)
+               } else {
+                       errno = EINVAL
+               }
+       } else {
+               errno = 0
+       }
+       return
+}
+
 func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) {
        r0, _, _ := Syscall(procWSAStartup, 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
        sockerrno = int(r0)
index b04fea5766cc00155099d550740857961777a64e..30939f58f772452526a7d42a70a0ee10c3a6e941 100644 (file)
@@ -545,3 +545,19 @@ type DNSRecord struct {
        Reserved uint32
        Data     [40]byte
 }
+
+const (
+       TF_DISCONNECT         = 1
+       TF_REUSE_SOCKET       = 2
+       TF_WRITE_BEHIND       = 4
+       TF_USE_DEFAULT_WORKER = 0
+       TF_USE_SYSTEM_THREAD  = 16
+       TF_USE_KERNEL_APC     = 32
+)
+
+type TransmitFileBuffers struct {
+       Head       uintptr
+       HeadLength uint32
+       Tail       uintptr
+       TailLength uint32
+}