mirror of
https://github.com/golang/go
synced 2024-11-25 08:47:56 -07:00
net: Sendfile for win32.
implement using TransmitFile(). R=bsiegert, bradfitz, alex.brainman, rsc, go.peter.90 CC=golang-dev https://golang.org/cl/4536076
This commit is contained in:
parent
968afa0e8c
commit
1374097381
@ -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))
|
||||
|
68
src/pkg/net/sendfile_windows.go
Normal file
68
src/pkg/net/sendfile_windows.go
Normal file
@ -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
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user