net: refactor poller into new internal/poll package

This will make it possible to use the poller with the os package.

This is a lot of code movement but the behavior is intended to be
unchanged.

Update #6817.
Update #7903.
Update #15021.
Update #18507.

Change-Id: I1413685928017c32df5654ded73a2643820977ae
Reviewed-on: https://go-review.googlesource.com/36799
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/src/cmd/dist/deps.go b/src/cmd/dist/deps.go
index c1c8b8f..641fe5d 100644
--- a/src/cmd/dist/deps.go
+++ b/src/cmd/dist/deps.go
@@ -5,68 +5,69 @@
 var builddeps = map[string][]string{
 	"bufio":                             {"bytes", "errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
 	"bytes":                             {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
-	"cmd/go/internal/base":              {"bufio", "bytes", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/bug":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/envcmd", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/web", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/buildid":           {"bufio", "bytes", "cmd/go/internal/cfg", "compress/flate", "compress/zlib", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/cfg":               {"bufio", "bytes", "errors", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/clean":             {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/doc":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/envcmd":            {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/fix":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "compress/flate", "compress/zlib", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/fmtcmd":            {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "compress/flate", "compress/zlib", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/generate":          {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/get":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/web", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "encoding/xml", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/help":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/list":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/load":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/str", "compress/flate", "compress/zlib", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/run":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/str":               {"bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/test":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/tool":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/version":           {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"cmd/go/internal/vet":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/base":              {"bufio", "bytes", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/bug":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/envcmd", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/web", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/buildid":           {"bufio", "bytes", "cmd/go/internal/cfg", "compress/flate", "compress/zlib", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/cfg":               {"bufio", "bytes", "errors", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/clean":             {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/doc":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/envcmd":            {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/fix":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "compress/flate", "compress/zlib", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/fmtcmd":            {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "compress/flate", "compress/zlib", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/generate":          {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/get":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/web", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "encoding/xml", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/help":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/list":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/load":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/str", "compress/flate", "compress/zlib", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/run":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/str":               {"bytes", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/test":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/tool":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/version":           {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/cfg", "cmd/go/internal/str", "context", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/vet":               {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
 	"cmd/go/internal/web":               {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
-	"cmd/go/internal/work":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"compress/flate":                    {"bufio", "bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"compress/zlib":                     {"bufio", "bytes", "compress/flate", "errors", "fmt", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go/internal/work":              {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/load", "cmd/go/internal/str", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding/binary", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"compress/flate":                    {"bufio", "bytes", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"compress/zlib":                     {"bufio", "bytes", "compress/flate", "errors", "fmt", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
 	"container/heap":                    {"errors", "internal/race", "math", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "unicode/utf8"},
-	"context":                           {"errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"context":                           {"errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
 	"crypto":                            {"errors", "hash", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
 	"crypto/sha1":                       {"crypto", "errors", "hash", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
-	"debug/dwarf":                       {"encoding/binary", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"debug/elf":                         {"bufio", "bytes", "compress/flate", "compress/zlib", "debug/dwarf", "encoding/binary", "errors", "fmt", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"debug/macho":                       {"bytes", "debug/dwarf", "encoding/binary", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"debug/dwarf":                       {"encoding/binary", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"debug/elf":                         {"bufio", "bytes", "compress/flate", "compress/zlib", "debug/dwarf", "encoding/binary", "errors", "fmt", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"debug/macho":                       {"bytes", "debug/dwarf", "encoding/binary", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
 	"encoding":                          {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
 	"encoding/base64":                   {"errors", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
 	"encoding/binary":                   {"errors", "internal/race", "io", "math", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
-	"encoding/json":                     {"bytes", "encoding", "encoding/base64", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"encoding/xml":                      {"bufio", "bytes", "encoding", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"encoding/json":                     {"bytes", "encoding", "encoding/base64", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"encoding/xml":                      {"bufio", "bytes", "encoding", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
 	"errors":                            {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
-	"flag":                              {"errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
-	"fmt":                               {"errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
-	"go/ast":                            {"bytes", "errors", "fmt", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"go/build":                          {"bufio", "bytes", "errors", "fmt", "go/ast", "go/doc", "go/parser", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"go/doc":                            {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"go/parser":                         {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"go/scanner":                        {"bytes", "errors", "fmt", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"go/token":                          {"errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"flag":                              {"errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"fmt":                               {"errors", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"go/ast":                            {"bytes", "errors", "fmt", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"go/build":                          {"bufio", "bytes", "errors", "fmt", "go/ast", "go/doc", "go/parser", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"go/doc":                            {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"go/parser":                         {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"go/scanner":                        {"bytes", "errors", "fmt", "go/token", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"go/token":                          {"errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
 	"hash":                              {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
 	"hash/adler32":                      {"errors", "hash", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
+	"internal/poll":                     {"errors", "internal/race", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16"},
 	"internal/race":                     {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
 	"internal/singleflight":             {"internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
 	"internal/syscall/windows":          {"errors", "internal/race", "internal/syscall/windows/sysdll", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
 	"internal/syscall/windows/registry": {"errors", "internal/race", "internal/syscall/windows/sysdll", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
 	"internal/syscall/windows/sysdll":   {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
 	"io":                      {"errors", "internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
-	"io/ioutil":               {"bytes", "errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"log":                     {"errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"io/ioutil":               {"bytes", "errors", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"log":                     {"errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
 	"math":                    {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
-	"net/url":                 {"bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"os":                      {"errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
-	"os/exec":                 {"bytes", "context", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"os/signal":               {"errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "os", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"net/url":                 {"bytes", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"os":                      {"errors", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"os/exec":                 {"bytes", "context", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"os/signal":               {"errors", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "os", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
 	"path":                    {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
-	"path/filepath":           {"errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"path/filepath":           {"errors", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
 	"reflect":                 {"errors", "internal/race", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
 	"regexp":                  {"bytes", "errors", "internal/race", "io", "math", "reflect", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
 	"regexp/syntax":           {"bytes", "errors", "internal/race", "io", "math", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
@@ -79,11 +80,11 @@
 	"sync":                    {"internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync/atomic"},
 	"sync/atomic":             {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
 	"syscall":                 {"errors", "internal/race", "internal/syscall/windows/sysdll", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode/utf16"},
-	"text/template":           {"bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "math", "net/url", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
-	"text/template/parse":     {"bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"text/template":           {"bytes", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "math", "net/url", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"text/template/parse":     {"bytes", "errors", "fmt", "internal/poll", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
 	"time":                    {"errors", "internal/race", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
 	"unicode":                 {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
 	"unicode/utf16":           {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
 	"unicode/utf8":            {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
-	"cmd/go":                  {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/bug", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/clean", "cmd/go/internal/doc", "cmd/go/internal/envcmd", "cmd/go/internal/fix", "cmd/go/internal/fmtcmd", "cmd/go/internal/generate", "cmd/go/internal/get", "cmd/go/internal/help", "cmd/go/internal/list", "cmd/go/internal/load", "cmd/go/internal/run", "cmd/go/internal/str", "cmd/go/internal/test", "cmd/go/internal/tool", "cmd/go/internal/version", "cmd/go/internal/vet", "cmd/go/internal/web", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "encoding/xml", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"cmd/go":                  {"bufio", "bytes", "cmd/go/internal/base", "cmd/go/internal/bug", "cmd/go/internal/buildid", "cmd/go/internal/cfg", "cmd/go/internal/clean", "cmd/go/internal/doc", "cmd/go/internal/envcmd", "cmd/go/internal/fix", "cmd/go/internal/fmtcmd", "cmd/go/internal/generate", "cmd/go/internal/get", "cmd/go/internal/help", "cmd/go/internal/list", "cmd/go/internal/load", "cmd/go/internal/run", "cmd/go/internal/str", "cmd/go/internal/test", "cmd/go/internal/tool", "cmd/go/internal/version", "cmd/go/internal/vet", "cmd/go/internal/web", "cmd/go/internal/work", "compress/flate", "compress/zlib", "container/heap", "context", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "encoding/xml", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/poll", "internal/race", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "internal/syscall/windows/sysdll", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
 }
diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go
index 2ed4d6b..a395176 100644
--- a/src/cmd/go/internal/work/build.go
+++ b/src/cmd/go/internal/work/build.go
@@ -2180,7 +2180,7 @@
 	extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.FFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
 	if p.Standard {
 		switch p.ImportPath {
-		case "bytes", "net", "os", "runtime/pprof", "sync", "time":
+		case "bytes", "internal/poll", "net", "os", "runtime/pprof", "sync", "time":
 			extFiles++
 		}
 	}
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 1ee23ed..e6804e7 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -150,7 +150,8 @@
 		"syscall",
 	},
 
-	"os":            {"L1", "os", "syscall", "time", "internal/syscall/windows"},
+	"internal/poll": {"L0", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"os":            {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows"},
 	"path/filepath": {"L2", "os", "syscall"},
 	"io/ioutil":     {"L2", "os", "path/filepath", "time"},
 	"os/exec":       {"L2", "os", "context", "path/filepath", "syscall"},
@@ -300,7 +301,7 @@
 	"net": {
 		"L0", "CGO",
 		"context", "math/rand", "os", "sort", "syscall", "time",
-		"internal/nettrace",
+		"internal/nettrace", "internal/poll",
 		"internal/syscall/windows", "internal/singleflight", "internal/race",
 		"golang_org/x/net/lif", "golang_org/x/net/route",
 	},
diff --git a/src/internal/poll/export_test.go b/src/internal/poll/export_test.go
new file mode 100644
index 0000000..ec658fd
--- /dev/null
+++ b/src/internal/poll/export_test.go
@@ -0,0 +1,39 @@
+// Copyright 2010 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.
+
+// Export guts for testing.
+// Since testing imports os and os imports internal/poll,
+// the internal/poll tests can not be in package poll.
+
+package poll
+
+var Consume = consume
+
+type FDMutex struct {
+	fdMutex
+}
+
+func (mu *FDMutex) Incref() bool {
+	return mu.incref()
+}
+
+func (mu *FDMutex) IncrefAndClose() bool {
+	return mu.increfAndClose()
+}
+
+func (mu *FDMutex) Decref() bool {
+	return mu.decref()
+}
+
+func (mu *FDMutex) RWLock(read bool) bool {
+	return mu.rwlock(read)
+}
+
+func (mu *FDMutex) RWUnlock(read bool) bool {
+	return mu.rwunlock(read)
+}
+
+func (fd *FD) EOFError(n int, err error) error {
+	return fd.eofError(n, err)
+}
diff --git a/src/internal/poll/fd.go b/src/internal/poll/fd.go
new file mode 100644
index 0000000..0752876
--- /dev/null
+++ b/src/internal/poll/fd.go
@@ -0,0 +1,44 @@
+// Copyright 2017 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 poll supports non-blocking I/O on file descriptors with polling.
+// This supports I/O operations that block only a goroutine, not a thread.
+// This is used by the net and os packages.
+// It uses a poller built into the runtime, with support from the
+// runtime scheduler.
+package poll
+
+import (
+	"errors"
+)
+
+// ErrClosing is returned when a descriptor is used after it has been closed.
+var ErrClosing = errors.New("use of closed file or network connection")
+
+// ErrTimeout is returned for an expired deadline.
+var ErrTimeout error = &TimeoutError{}
+
+// TimeoutError is returned for an expired deadline.
+type TimeoutError struct{}
+
+// Implement the net.Error interface.
+func (e *TimeoutError) Error() string   { return "i/o timeout" }
+func (e *TimeoutError) Timeout() bool   { return true }
+func (e *TimeoutError) Temporary() bool { return true }
+
+// consume removes data from a slice of byte slices, for writev.
+func consume(v *[][]byte, n int64) {
+	for len(*v) > 0 {
+		ln0 := int64(len((*v)[0]))
+		if ln0 > n {
+			(*v)[0] = (*v)[0][n:]
+			return
+		}
+		n -= ln0
+		*v = (*v)[1:]
+	}
+}
+
+// TestHookDidWritev is a hook for testing writev.
+var TestHookDidWritev = func(wrote int) {}
diff --git a/src/net/fd_io_plan9.go b/src/internal/poll/fd_io_plan9.go
similarity index 91%
rename from src/net/fd_io_plan9.go
rename to src/internal/poll/fd_io_plan9.go
index 76da0c5..287d11b 100644
--- a/src/net/fd_io_plan9.go
+++ b/src/internal/poll/fd_io_plan9.go
@@ -2,10 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package net
+package poll
 
 import (
-	"os"
 	"runtime"
 	"sync"
 	"syscall"
@@ -49,7 +48,7 @@
 		// Go runtime.
 		runtime.LockOSThread()
 		runtime_ignoreHangup()
-		aio.pid = os.Getpid()
+		aio.pid = syscall.Getpid()
 		aio.mu.Unlock()
 
 		n, err := fn(b)
@@ -64,8 +63,6 @@
 	return aio
 }
 
-var hangupNote os.Signal = syscall.Note("hangup")
-
 // Cancel interrupts the I/O operation, causing
 // the Wait function to return.
 func (aio *asyncIO) Cancel() {
@@ -74,11 +71,12 @@
 	if aio.pid == -1 {
 		return
 	}
-	proc, err := os.FindProcess(aio.pid)
-	if err != nil {
+	f, e := syscall.Open("/proc/"+itoa(aio.pid)+"/note", syscall.O_WRONLY)
+	if e != nil {
 		return
 	}
-	proc.Signal(hangupNote)
+	syscall.Write(f, []byte("hangup"))
+	syscall.Close(f)
 }
 
 // Wait for the I/O operation to complete.
diff --git a/src/net/fd_mutex.go b/src/internal/poll/fd_mutex.go
similarity index 93%
rename from src/net/fd_mutex.go
rename to src/internal/poll/fd_mutex.go
index 4591fd1..2b76053 100644
--- a/src/net/fd_mutex.go
+++ b/src/internal/poll/fd_mutex.go
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package net
+package poll
 
 import "sync/atomic"
 
 // fdMutex is a specialized synchronization primitive that manages
 // lifetime of an fd and serializes access to Read, Write and Close
-// methods on netFD.
+// methods on FD.
 type fdMutex struct {
 	state uint64
 	rsema uint32
@@ -16,7 +16,7 @@
 }
 
 // fdMutex.state is organized as follows:
-// 1 bit - whether netFD is closed, if set all subsequent lock operations will fail.
+// 1 bit - whether FD is closed, if set all subsequent lock operations will fail.
 // 1 bit - lock for read operations.
 // 1 bit - lock for write operations.
 // 20 bits - total number of references (read+write+misc).
@@ -196,9 +196,9 @@
 
 // incref adds a reference to fd.
 // It returns an error when fd cannot be used.
-func (fd *netFD) incref() error {
+func (fd *FD) incref() error {
 	if !fd.fdmu.incref() {
-		return errClosing
+		return ErrClosing
 	}
 	return nil
 }
@@ -206,17 +206,18 @@
 // decref removes a reference from fd.
 // It also closes fd when the state of fd is set to closed and there
 // is no remaining reference.
-func (fd *netFD) decref() {
+func (fd *FD) decref() error {
 	if fd.fdmu.decref() {
-		fd.destroy()
+		return fd.destroy()
 	}
+	return nil
 }
 
 // readLock adds a reference to fd and locks fd for reading.
 // It returns an error when fd cannot be used for reading.
-func (fd *netFD) readLock() error {
+func (fd *FD) readLock() error {
 	if !fd.fdmu.rwlock(true) {
-		return errClosing
+		return ErrClosing
 	}
 	return nil
 }
@@ -224,7 +225,7 @@
 // readUnlock removes a reference from fd and unlocks fd for reading.
 // It also closes fd when the state of fd is set to closed and there
 // is no remaining reference.
-func (fd *netFD) readUnlock() {
+func (fd *FD) readUnlock() {
 	if fd.fdmu.rwunlock(true) {
 		fd.destroy()
 	}
@@ -232,9 +233,9 @@
 
 // writeLock adds a reference to fd and locks fd for writing.
 // It returns an error when fd cannot be used for writing.
-func (fd *netFD) writeLock() error {
+func (fd *FD) writeLock() error {
 	if !fd.fdmu.rwlock(false) {
-		return errClosing
+		return ErrClosing
 	}
 	return nil
 }
@@ -242,7 +243,7 @@
 // writeUnlock removes a reference from fd and unlocks fd for writing.
 // It also closes fd when the state of fd is set to closed and there
 // is no remaining reference.
-func (fd *netFD) writeUnlock() {
+func (fd *FD) writeUnlock() {
 	if fd.fdmu.rwunlock(false) {
 		fd.destroy()
 	}
diff --git a/src/net/fd_mutex_test.go b/src/internal/poll/fd_mutex_test.go
similarity index 67%
rename from src/net/fd_mutex_test.go
rename to src/internal/poll/fd_mutex_test.go
index 3542c70..bab81c6 100644
--- a/src/net/fd_mutex_test.go
+++ b/src/internal/poll/fd_mutex_test.go
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package net
+package poll_test
 
 import (
+	. "internal/poll"
 	"math/rand"
 	"runtime"
 	"testing"
@@ -12,57 +13,57 @@
 )
 
 func TestMutexLock(t *testing.T) {
-	var mu fdMutex
+	var mu FDMutex
 
-	if !mu.incref() {
+	if !mu.Incref() {
 		t.Fatal("broken")
 	}
-	if mu.decref() {
+	if mu.Decref() {
 		t.Fatal("broken")
 	}
 
-	if !mu.rwlock(true) {
+	if !mu.RWLock(true) {
 		t.Fatal("broken")
 	}
-	if mu.rwunlock(true) {
+	if mu.RWUnlock(true) {
 		t.Fatal("broken")
 	}
 
-	if !mu.rwlock(false) {
+	if !mu.RWLock(false) {
 		t.Fatal("broken")
 	}
-	if mu.rwunlock(false) {
+	if mu.RWUnlock(false) {
 		t.Fatal("broken")
 	}
 }
 
 func TestMutexClose(t *testing.T) {
-	var mu fdMutex
-	if !mu.increfAndClose() {
+	var mu FDMutex
+	if !mu.IncrefAndClose() {
 		t.Fatal("broken")
 	}
 
-	if mu.incref() {
+	if mu.Incref() {
 		t.Fatal("broken")
 	}
-	if mu.rwlock(true) {
+	if mu.RWLock(true) {
 		t.Fatal("broken")
 	}
-	if mu.rwlock(false) {
+	if mu.RWLock(false) {
 		t.Fatal("broken")
 	}
-	if mu.increfAndClose() {
+	if mu.IncrefAndClose() {
 		t.Fatal("broken")
 	}
 }
 
 func TestMutexCloseUnblock(t *testing.T) {
 	c := make(chan bool)
-	var mu fdMutex
-	mu.rwlock(true)
+	var mu FDMutex
+	mu.RWLock(true)
 	for i := 0; i < 4; i++ {
 		go func() {
-			if mu.rwlock(true) {
+			if mu.RWLock(true) {
 				t.Error("broken")
 				return
 			}
@@ -76,7 +77,7 @@
 		t.Fatal("broken")
 	default:
 	}
-	mu.increfAndClose() // Must unblock the readers.
+	mu.IncrefAndClose() // Must unblock the readers.
 	for i := 0; i < 4; i++ {
 		select {
 		case <-c:
@@ -84,10 +85,10 @@
 			t.Fatal("broken")
 		}
 	}
-	if mu.decref() {
+	if mu.Decref() {
 		t.Fatal("broken")
 	}
-	if !mu.rwunlock(true) {
+	if !mu.RWUnlock(true) {
 		t.Fatal("broken")
 	}
 }
@@ -102,22 +103,22 @@
 		f()
 	}
 
-	var mu fdMutex
-	ensurePanics(func() { mu.decref() })
-	ensurePanics(func() { mu.rwunlock(true) })
-	ensurePanics(func() { mu.rwunlock(false) })
+	var mu FDMutex
+	ensurePanics(func() { mu.Decref() })
+	ensurePanics(func() { mu.RWUnlock(true) })
+	ensurePanics(func() { mu.RWUnlock(false) })
 
-	ensurePanics(func() { mu.incref(); mu.decref(); mu.decref() })
-	ensurePanics(func() { mu.rwlock(true); mu.rwunlock(true); mu.rwunlock(true) })
-	ensurePanics(func() { mu.rwlock(false); mu.rwunlock(false); mu.rwunlock(false) })
+	ensurePanics(func() { mu.Incref(); mu.Decref(); mu.Decref() })
+	ensurePanics(func() { mu.RWLock(true); mu.RWUnlock(true); mu.RWUnlock(true) })
+	ensurePanics(func() { mu.RWLock(false); mu.RWUnlock(false); mu.RWUnlock(false) })
 
 	// ensure that it's still not broken
-	mu.incref()
-	mu.decref()
-	mu.rwlock(true)
-	mu.rwunlock(true)
-	mu.rwlock(false)
-	mu.rwunlock(false)
+	mu.Incref()
+	mu.Decref()
+	mu.RWLock(true)
+	mu.RWUnlock(true)
+	mu.RWLock(false)
+	mu.RWUnlock(false)
 }
 
 func TestMutexStress(t *testing.T) {
@@ -129,7 +130,7 @@
 	}
 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
 	done := make(chan bool)
-	var mu fdMutex
+	var mu FDMutex
 	var readState [2]uint64
 	var writeState [2]uint64
 	for p := 0; p < P; p++ {
@@ -138,16 +139,16 @@
 			for i := 0; i < N; i++ {
 				switch r.Intn(3) {
 				case 0:
-					if !mu.incref() {
+					if !mu.Incref() {
 						t.Error("broken")
 						return
 					}
-					if mu.decref() {
+					if mu.Decref() {
 						t.Error("broken")
 						return
 					}
 				case 1:
-					if !mu.rwlock(true) {
+					if !mu.RWLock(true) {
 						t.Error("broken")
 						return
 					}
@@ -158,12 +159,12 @@
 					}
 					readState[0]++
 					readState[1]++
-					if mu.rwunlock(true) {
+					if mu.RWUnlock(true) {
 						t.Error("broken")
 						return
 					}
 				case 2:
-					if !mu.rwlock(false) {
+					if !mu.RWLock(false) {
 						t.Error("broken")
 						return
 					}
@@ -174,7 +175,7 @@
 					}
 					writeState[0]++
 					writeState[1]++
-					if mu.rwunlock(false) {
+					if mu.RWUnlock(false) {
 						t.Error("broken")
 						return
 					}
@@ -186,10 +187,10 @@
 	for p := 0; p < P; p++ {
 		<-done
 	}
-	if !mu.increfAndClose() {
+	if !mu.IncrefAndClose() {
 		t.Fatal("broken")
 	}
-	if !mu.decref() {
+	if !mu.Decref() {
 		t.Fatal("broken")
 	}
 }
diff --git a/src/internal/poll/fd_plan9.go b/src/internal/poll/fd_plan9.go
new file mode 100644
index 0000000..fa9e566
--- /dev/null
+++ b/src/internal/poll/fd_plan9.go
@@ -0,0 +1,180 @@
+// Copyright 2009 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 poll
+
+import (
+	"io"
+	"sync/atomic"
+	"time"
+)
+
+type atomicBool int32
+
+func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
+func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
+func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
+
+type FD struct {
+	// Lock sysfd and serialize access to Read and Write methods.
+	fdmu fdMutex
+
+	Destroy func()
+
+	// deadlines
+	raio      *asyncIO
+	waio      *asyncIO
+	rtimer    *time.Timer
+	wtimer    *time.Timer
+	rtimedout atomicBool // set true when read deadline has been reached
+	wtimedout atomicBool // set true when write deadline has been reached
+}
+
+// We need this to close out a file descriptor when it is unlocked,
+// but the real implementation has to live in the net package because
+// it uses os.File's.
+func (fd *FD) destroy() error {
+	if fd.Destroy != nil {
+		fd.Destroy()
+	}
+	return nil
+}
+
+// Close handles the locking for closing an FD. The real operation
+// is in the net package.
+func (fd *FD) Close() error {
+	if !fd.fdmu.increfAndClose() {
+		return ErrClosing
+	}
+	return nil
+}
+
+func (fd *FD) Read(fn func([]byte) (int, error), b []byte) (n int, err error) {
+	if fd.rtimedout.isSet() {
+		return 0, ErrTimeout
+	}
+	if err := fd.readLock(); err != nil {
+		return 0, err
+	}
+	defer fd.readUnlock()
+	if len(b) == 0 {
+		return 0, nil
+	}
+	fd.raio = newAsyncIO(fn, b)
+	n, err = fd.raio.Wait()
+	fd.raio = nil
+	if isHangup(err) {
+		err = io.EOF
+	}
+	if isInterrupted(err) {
+		err = ErrTimeout
+	}
+	return
+}
+
+func (fd *FD) Write(fn func([]byte) (int, error), b []byte) (n int, err error) {
+	if fd.wtimedout.isSet() {
+		return 0, ErrTimeout
+	}
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	fd.waio = newAsyncIO(fn, b)
+	n, err = fd.waio.Wait()
+	fd.waio = nil
+	if isInterrupted(err) {
+		err = ErrTimeout
+	}
+	return
+}
+
+func (fd *FD) SetDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'r'+'w')
+}
+
+func (fd *FD) SetReadDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'r')
+}
+
+func (fd *FD) SetWriteDeadline(t time.Time) error {
+	return setDeadlineImpl(fd, t, 'w')
+}
+
+func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
+	d := t.Sub(time.Now())
+	if mode == 'r' || mode == 'r'+'w' {
+		fd.rtimedout.setFalse()
+	}
+	if mode == 'w' || mode == 'r'+'w' {
+		fd.wtimedout.setFalse()
+	}
+	if t.IsZero() || d < 0 {
+		// Stop timer
+		if mode == 'r' || mode == 'r'+'w' {
+			if fd.rtimer != nil {
+				fd.rtimer.Stop()
+			}
+			fd.rtimer = nil
+		}
+		if mode == 'w' || mode == 'r'+'w' {
+			if fd.wtimer != nil {
+				fd.wtimer.Stop()
+			}
+			fd.wtimer = nil
+		}
+	} else {
+		// Interrupt I/O operation once timer has expired
+		if mode == 'r' || mode == 'r'+'w' {
+			fd.rtimer = time.AfterFunc(d, func() {
+				fd.rtimedout.setTrue()
+				if fd.raio != nil {
+					fd.raio.Cancel()
+				}
+			})
+		}
+		if mode == 'w' || mode == 'r'+'w' {
+			fd.wtimer = time.AfterFunc(d, func() {
+				fd.wtimedout.setTrue()
+				if fd.waio != nil {
+					fd.waio.Cancel()
+				}
+			})
+		}
+	}
+	if !t.IsZero() && d < 0 {
+		// Interrupt current I/O operation
+		if mode == 'r' || mode == 'r'+'w' {
+			fd.rtimedout.setTrue()
+			if fd.raio != nil {
+				fd.raio.Cancel()
+			}
+		}
+		if mode == 'w' || mode == 'r'+'w' {
+			fd.wtimedout.setTrue()
+			if fd.waio != nil {
+				fd.waio.Cancel()
+			}
+		}
+	}
+	return nil
+}
+
+// On Plan 9 only, expose the locking for the net code.
+
+func (fd *FD) ReadLock() error {
+	return fd.readLock()
+}
+
+func (fd *FD) ReadUnlock() {
+	fd.readUnlock()
+}
+
+func isHangup(err error) bool {
+	return err != nil && stringsHasSuffix(err.Error(), "Hangup")
+}
+
+func isInterrupted(err error) bool {
+	return err != nil && stringsHasSuffix(err.Error(), "interrupted")
+}
diff --git a/src/net/fd_poll_nacl.go b/src/internal/poll/fd_poll_nacl.go
similarity index 66%
rename from src/net/fd_poll_nacl.go
rename to src/internal/poll/fd_poll_nacl.go
index 8398760..69c728d 100644
--- a/src/net/fd_poll_nacl.go
+++ b/src/internal/poll/fd_poll_nacl.go
@@ -2,34 +2,32 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package net
+package poll
 
 import (
-	"runtime"
 	"syscall"
 	"time"
 )
 
 type pollDesc struct {
-	fd      *netFD
+	fd      *FD
 	closing bool
 }
 
-func (pd *pollDesc) init(fd *netFD) error { pd.fd = fd; return nil }
+func (pd *pollDesc) init(fd *FD) error { pd.fd = fd; return nil }
 
 func (pd *pollDesc) close() {}
 
 func (pd *pollDesc) evict() {
 	pd.closing = true
 	if pd.fd != nil {
-		syscall.StopIO(pd.fd.sysfd)
-		runtime.KeepAlive(pd.fd)
+		syscall.StopIO(pd.fd.Sysfd)
 	}
 }
 
 func (pd *pollDesc) prepare(mode int) error {
 	if pd.closing {
-		return errClosing
+		return ErrClosing
 	}
 	return nil
 }
@@ -40,9 +38,9 @@
 
 func (pd *pollDesc) wait(mode int) error {
 	if pd.closing {
-		return errClosing
+		return ErrClosing
 	}
-	return errTimeout
+	return ErrTimeout
 }
 
 func (pd *pollDesc) waitRead() error { return pd.wait('r') }
@@ -55,19 +53,19 @@
 
 func (pd *pollDesc) waitCanceledWrite() {}
 
-func (fd *netFD) setDeadline(t time.Time) error {
+func (fd *FD) SetDeadline(t time.Time) error {
 	return setDeadlineImpl(fd, t, 'r'+'w')
 }
 
-func (fd *netFD) setReadDeadline(t time.Time) error {
+func (fd *FD) SetReadDeadline(t time.Time) error {
 	return setDeadlineImpl(fd, t, 'r')
 }
 
-func (fd *netFD) setWriteDeadline(t time.Time) error {
+func (fd *FD) SetWriteDeadline(t time.Time) error {
 	return setDeadlineImpl(fd, t, 'w')
 }
 
-func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
+func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
 	d := t.UnixNano()
 	if t.IsZero() {
 		d = 0
@@ -77,12 +75,12 @@
 	}
 	switch mode {
 	case 'r':
-		syscall.SetReadDeadline(fd.sysfd, d)
+		syscall.SetReadDeadline(fd.Sysfd, d)
 	case 'w':
-		syscall.SetWriteDeadline(fd.sysfd, d)
+		syscall.SetWriteDeadline(fd.Sysfd, d)
 	case 'r' + 'w':
-		syscall.SetReadDeadline(fd.sysfd, d)
-		syscall.SetWriteDeadline(fd.sysfd, d)
+		syscall.SetReadDeadline(fd.Sysfd, d)
+		syscall.SetWriteDeadline(fd.Sysfd, d)
 	}
 	fd.decref()
 	return nil
diff --git a/src/net/fd_poll_runtime.go b/src/internal/poll/fd_poll_runtime.go
similarity index 79%
rename from src/net/fd_poll_runtime.go
rename to src/internal/poll/fd_poll_runtime.go
index 62b69fc..f0d7a22 100644
--- a/src/net/fd_poll_runtime.go
+++ b/src/internal/poll/fd_poll_runtime.go
@@ -4,10 +4,10 @@
 
 // +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
 
-package net
+package poll
 
 import (
-	"runtime"
+	"errors"
 	"sync"
 	"syscall"
 	"time"
@@ -31,11 +31,14 @@
 
 var serverInit sync.Once
 
-func (pd *pollDesc) init(fd *netFD) error {
+func (pd *pollDesc) init(fd *FD) error {
 	serverInit.Do(runtime_pollServerInit)
-	ctx, errno := runtime_pollOpen(uintptr(fd.sysfd))
-	runtime.KeepAlive(fd)
+	ctx, errno := runtime_pollOpen(uintptr(fd.Sysfd))
 	if errno != 0 {
+		if ctx != 0 {
+			runtime_pollUnblock(ctx)
+			runtime_pollClose(ctx)
+		}
 		return syscall.Errno(errno)
 	}
 	pd.runtimeCtx = ctx
@@ -59,6 +62,9 @@
 }
 
 func (pd *pollDesc) prepare(mode int) error {
+	if pd.runtimeCtx == 0 {
+		return nil
+	}
 	res := runtime_pollReset(pd.runtimeCtx, mode)
 	return convertErr(res)
 }
@@ -72,6 +78,9 @@
 }
 
 func (pd *pollDesc) wait(mode int) error {
+	if pd.runtimeCtx == 0 {
+		return errors.New("waiting for unsupported file type")
+	}
 	res := runtime_pollWait(pd.runtimeCtx, mode)
 	return convertErr(res)
 }
@@ -85,6 +94,9 @@
 }
 
 func (pd *pollDesc) waitCanceled(mode int) {
+	if pd.runtimeCtx == 0 {
+		return
+	}
 	runtime_pollWaitCanceled(pd.runtimeCtx, mode)
 }
 
@@ -101,27 +113,27 @@
 	case 0:
 		return nil
 	case 1:
-		return errClosing
+		return ErrClosing
 	case 2:
-		return errTimeout
+		return ErrTimeout
 	}
 	println("unreachable: ", res)
 	panic("unreachable")
 }
 
-func (fd *netFD) setDeadline(t time.Time) error {
+func (fd *FD) SetDeadline(t time.Time) error {
 	return setDeadlineImpl(fd, t, 'r'+'w')
 }
 
-func (fd *netFD) setReadDeadline(t time.Time) error {
+func (fd *FD) SetReadDeadline(t time.Time) error {
 	return setDeadlineImpl(fd, t, 'r')
 }
 
-func (fd *netFD) setWriteDeadline(t time.Time) error {
+func (fd *FD) SetWriteDeadline(t time.Time) error {
 	return setDeadlineImpl(fd, t, 'w')
 }
 
-func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
+func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
 	diff := int64(time.Until(t))
 	d := runtimeNano() + diff
 	if d <= 0 && diff > 0 {
@@ -135,6 +147,9 @@
 	if err := fd.incref(); err != nil {
 		return err
 	}
+	if fd.pd.runtimeCtx == 0 {
+		return errors.New("file type does not support deadlines")
+	}
 	runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
 	fd.decref()
 	return nil
diff --git a/src/internal/poll/fd_posix.go b/src/internal/poll/fd_posix.go
new file mode 100644
index 0000000..e0e634c
--- /dev/null
+++ b/src/internal/poll/fd_posix.go
@@ -0,0 +1,57 @@
+// Copyright 2009 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package poll
+
+import (
+	"io"
+	"syscall"
+)
+
+// eofError returns io.EOF when fd is available for reading end of
+// file.
+func (fd *FD) eofError(n int, err error) error {
+	if n == 0 && err == nil && fd.ZeroReadIsEOF {
+		return io.EOF
+	}
+	return err
+}
+
+// Fchmod wraps syscall.Fchmod.
+func (fd *FD) Fchmod(mode uint32) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Fchmod(fd.Sysfd, mode)
+}
+
+// Fchown wraps syscall.Fchown.
+func (fd *FD) Fchown(uid, gid int) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Fchown(fd.Sysfd, uid, gid)
+}
+
+// Ftruncate wraps syscall.Ftruncate.
+func (fd *FD) Ftruncate(size int64) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Ftruncate(fd.Sysfd, size)
+}
+
+// Fsync wraps syscall.Fsync.
+func (fd *FD) Fsync() error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Fsync(fd.Sysfd)
+}
diff --git a/src/internal/poll/fd_posix_test.go b/src/internal/poll/fd_posix_test.go
new file mode 100644
index 0000000..edc2dcb
--- /dev/null
+++ b/src/internal/poll/fd_posix_test.go
@@ -0,0 +1,43 @@
+// Copyright 2012 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package poll_test
+
+import (
+	. "internal/poll"
+	"io"
+	"testing"
+)
+
+var eofErrorTests = []struct {
+	n        int
+	err      error
+	fd       *FD
+	expected error
+}{
+	{100, nil, &FD{ZeroReadIsEOF: true}, nil},
+	{100, io.EOF, &FD{ZeroReadIsEOF: true}, io.EOF},
+	{100, ErrClosing, &FD{ZeroReadIsEOF: true}, ErrClosing},
+	{0, nil, &FD{ZeroReadIsEOF: true}, io.EOF},
+	{0, io.EOF, &FD{ZeroReadIsEOF: true}, io.EOF},
+	{0, ErrClosing, &FD{ZeroReadIsEOF: true}, ErrClosing},
+
+	{100, nil, &FD{ZeroReadIsEOF: false}, nil},
+	{100, io.EOF, &FD{ZeroReadIsEOF: false}, io.EOF},
+	{100, ErrClosing, &FD{ZeroReadIsEOF: false}, ErrClosing},
+	{0, nil, &FD{ZeroReadIsEOF: false}, nil},
+	{0, io.EOF, &FD{ZeroReadIsEOF: false}, io.EOF},
+	{0, ErrClosing, &FD{ZeroReadIsEOF: false}, ErrClosing},
+}
+
+func TestEOFError(t *testing.T) {
+	for _, tt := range eofErrorTests {
+		actual := tt.fd.EOFError(tt.n, tt.err)
+		if actual != tt.expected {
+			t.Errorf("eofError(%v, %v, %v): expected %v, actual %v", tt.n, tt.err, tt.fd.ZeroReadIsEOF, tt.expected, actual)
+		}
+	}
+}
diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go
new file mode 100644
index 0000000..d97490a
--- /dev/null
+++ b/src/internal/poll/fd_unix.go
@@ -0,0 +1,398 @@
+// Copyright 2017 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package poll
+
+import (
+	"io"
+	"syscall"
+)
+
+// FD is a file descriptor. The net and os packages use this type as a
+// field of a larger type representing a network connection or OS file.
+type FD struct {
+	// Lock sysfd and serialize access to Read and Write methods.
+	fdmu fdMutex
+
+	// System file descriptor. Immutable until Close.
+	Sysfd int
+
+	// I/O poller.
+	pd pollDesc
+
+	// Writev cache.
+	iovecs *[]syscall.Iovec
+
+	// Whether this is a streaming descriptor, as opposed to a
+	// packet-based descriptor like a UDP socket. Immutable.
+	IsStream bool
+
+	// Whether a zero byte read indicates EOF. This is false for a
+	// message based socket connection.
+	ZeroReadIsEOF bool
+}
+
+// Init initializes the FD. The Sysfd field should already be set.
+// This can be called multiple times on a single FD.
+func (fd *FD) Init() error {
+	return fd.pd.init(fd)
+}
+
+// Destroy closes the file descriptor. This is called when there are
+// no remaining references.
+func (fd *FD) destroy() error {
+	// Poller may want to unregister fd in readiness notification mechanism,
+	// so this must be executed before CloseFunc.
+	fd.pd.close()
+	err := CloseFunc(fd.Sysfd)
+	fd.Sysfd = -1
+	return err
+}
+
+// Close closes the FD. The underlying file descriptor is closed by the
+// destroy method when there are no remaining references.
+func (fd *FD) Close() error {
+	if !fd.fdmu.increfAndClose() {
+		return ErrClosing
+	}
+	// Unblock any I/O.  Once it all unblocks and returns,
+	// so that it cannot be referring to fd.sysfd anymore,
+	// the final decref will close fd.sysfd. This should happen
+	// fairly quickly, since all the I/O is non-blocking, and any
+	// attempts to block in the pollDesc will return ErrClosing.
+	fd.pd.evict()
+	// The call to decref will call destroy if there are no other
+	// references.
+	return fd.decref()
+}
+
+// Shutdown wraps the shutdown call.
+func (fd *FD) Shutdown(how int) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Shutdown(fd.Sysfd, how)
+}
+
+// Darwin and FreeBSD can't read or write 2GB+ files at a time,
+// even on 64-bit systems.
+// The same is true of socket implementations on many systems.
+// See golang.org/issue/7812 and golang.org/issue/16266.
+// Use 1GB instead of, say, 2GB-1, to keep subsequent reads aligned.
+const maxRW = 1 << 30
+
+// Read implements io.Reader.
+func (fd *FD) Read(p []byte) (n int, err error) {
+	if err := fd.readLock(); err != nil {
+		return 0, err
+	}
+	defer fd.readUnlock()
+	if len(p) == 0 {
+		// If the caller wanted a zero byte read, return immediately
+		// without trying (but after acquiring the readLock).
+		// Otherwise syscall.Read returns 0, nil which looks like
+		// io.EOF.
+		// TODO(bradfitz): make it wait for readability? (Issue 15735)
+		return 0, nil
+	}
+	if err := fd.pd.prepareRead(); err != nil {
+		return 0, err
+	}
+	if fd.IsStream && len(p) > maxRW {
+		p = p[:maxRW]
+	}
+	for {
+		n, err = syscall.Read(fd.Sysfd, p)
+		if err != nil {
+			n = 0
+			if err == syscall.EAGAIN {
+				if err = fd.pd.waitRead(); err == nil {
+					continue
+				}
+			}
+		}
+		err = fd.eofError(n, err)
+		break
+	}
+	return
+}
+
+// Pread wraps the pread system call.
+func (fd *FD) Pread(p []byte, off int64) (n int, err error) {
+	if err := fd.readLock(); err != nil {
+		return 0, err
+	}
+	defer fd.readUnlock()
+	if err := fd.pd.prepareRead(); err != nil {
+		return 0, err
+	}
+	if fd.IsStream && len(p) > maxRW {
+		p = p[:maxRW]
+	}
+	for {
+		n, err = syscall.Pread(fd.Sysfd, p, off)
+		if err != nil {
+			n = 0
+			if err == syscall.EAGAIN {
+				if err = fd.pd.waitRead(); err == nil {
+					continue
+				}
+			}
+		}
+		err = fd.eofError(n, err)
+		break
+	}
+	return
+}
+
+// RecvFrom wraps the recvfrom network call.
+func (fd *FD) RecvFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
+	if err := fd.readLock(); err != nil {
+		return 0, nil, err
+	}
+	defer fd.readUnlock()
+	if err := fd.pd.prepareRead(); err != nil {
+		return 0, nil, err
+	}
+	for {
+		n, sa, err = syscall.Recvfrom(fd.Sysfd, p, 0)
+		if err != nil {
+			n = 0
+			if err == syscall.EAGAIN {
+				if err = fd.pd.waitRead(); err == nil {
+					continue
+				}
+			}
+		}
+		err = fd.eofError(n, err)
+		break
+	}
+	return
+}
+
+// ReadMsg wraps the recvmsg network call.
+func (fd *FD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
+	if err := fd.readLock(); err != nil {
+		return 0, 0, 0, nil, err
+	}
+	defer fd.readUnlock()
+	if err := fd.pd.prepareRead(); err != nil {
+		return 0, 0, 0, nil, err
+	}
+	for {
+		n, oobn, flags, sa, err = syscall.Recvmsg(fd.Sysfd, p, oob, 0)
+		if err != nil {
+			// TODO(dfc) should n and oobn be set to 0
+			if err == syscall.EAGAIN {
+				if err = fd.pd.waitRead(); err == nil {
+					continue
+				}
+			}
+		}
+		err = fd.eofError(n, err)
+		break
+	}
+	return
+}
+
+// Write implements io.Writer.
+func (fd *FD) Write(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
+	}
+	for {
+		var n int
+		max := len(p)
+		if fd.IsStream && max-nn > maxRW {
+			max = nn + maxRW
+		}
+		n, err = syscall.Write(fd.Sysfd, p[nn:max])
+		if n > 0 {
+			nn += n
+		}
+		if nn == len(p) {
+			break
+		}
+		if err == syscall.EAGAIN {
+			if err = fd.pd.waitWrite(); err == nil {
+				continue
+			}
+		}
+		if err != nil {
+			break
+		}
+		if n == 0 {
+			err = io.ErrUnexpectedEOF
+			break
+		}
+	}
+	return
+}
+
+// Pwrite wraps the pwrite system call.
+func (fd *FD) Pwrite(p []byte, off int64) (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
+	}
+	for {
+		var n int
+		max := len(p)
+		if fd.IsStream && max-nn > maxRW {
+			max = nn + maxRW
+		}
+		n, err = syscall.Pwrite(fd.Sysfd, p[nn:max], off+int64(nn))
+		if n > 0 {
+			nn += n
+		}
+		if nn == len(p) {
+			break
+		}
+		if err == syscall.EAGAIN {
+			if err = fd.pd.waitWrite(); err == nil {
+				continue
+			}
+		}
+		if err != nil {
+			break
+		}
+		if n == 0 {
+			err = io.ErrUnexpectedEOF
+			break
+		}
+	}
+	return
+}
+
+// WriteTo wraps the sendto network call.
+func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (n 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
+	}
+	for {
+		err = syscall.Sendto(fd.Sysfd, p, 0, sa)
+		if err == syscall.EAGAIN {
+			if err = fd.pd.waitWrite(); err == nil {
+				continue
+			}
+		}
+		break
+	}
+	if err == nil {
+		n = len(p)
+	}
+	return
+}
+
+// WriteMsg wraps the sendmsg network call.
+func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, 0, err
+	}
+	defer fd.writeUnlock()
+	if err := fd.pd.prepareWrite(); err != nil {
+		return 0, 0, err
+	}
+	for {
+		n, err = syscall.SendmsgN(fd.Sysfd, p, oob, sa, 0)
+		if err == syscall.EAGAIN {
+			if err = fd.pd.waitWrite(); err == nil {
+				continue
+			}
+		}
+		break
+	}
+	if err == nil {
+		oobn = len(oob)
+	}
+	return
+}
+
+// WaitWrite waits until data can be written to fd.
+func (fd *FD) WaitWrite() error {
+	return fd.pd.waitWrite()
+}
+
+// Accept wraps the accept network call.
+func (fd *FD) Accept() (newfd int, rsa syscall.Sockaddr, errcall string, err error) {
+	if err = fd.readLock(); err != nil {
+		return -1, nil, "", err
+	}
+	defer fd.readUnlock()
+
+	var s int
+	if err = fd.pd.prepareRead(); err != nil {
+		return -1, nil, "", err
+	}
+	for {
+		s, rsa, errcall, err = accept(fd.Sysfd)
+		if err == nil {
+			return s, rsa, "", err
+		}
+		switch err {
+		case syscall.EAGAIN:
+			if err = fd.pd.waitRead(); err == nil {
+				continue
+			}
+		case syscall.ECONNABORTED:
+			// This means that a socket on the listen
+			// queue was closed before we Accept()ed it;
+			// it's a silly error, so try again.
+			continue
+		}
+		return -1, nil, errcall, err
+	}
+}
+
+// Seek wraps syscall.Seek.
+func (fd *FD) Seek(offset int64, whence int) (ret int64, err error) {
+	if err := fd.incref(); err != nil {
+		return 0, err
+	}
+	defer fd.decref()
+	return syscall.Seek(fd.Sysfd, offset, whence)
+}
+
+// ReadDirent wraps syscall.ReadDirent.
+// We treat this like an ordinary system call rather than a call
+// that tries to fill the buffer.
+func (fd *FD) ReadDirent(buf []byte) (n int, err error) {
+	if err := fd.incref(); err != nil {
+		return 0, err
+	}
+	defer fd.decref()
+	return syscall.ReadDirent(fd.Sysfd, buf)
+}
+
+// Fchdir wraps syscall.Fchdir.
+func (fd *FD) Fchdir() error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Fchdir(fd.Sysfd)
+}
+
+// Fstat wraps syscall.Fstat
+func (fd *FD) Fstat(s *syscall.Stat_t) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Fstat(fd.Sysfd, s)
+}
diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go
new file mode 100644
index 0000000..33df876
--- /dev/null
+++ b/src/internal/poll/fd_windows.go
@@ -0,0 +1,816 @@
+// Copyright 2017 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 poll
+
+import (
+	"errors"
+	"internal/race"
+	"io"
+	"runtime"
+	"sync"
+	"syscall"
+	"unicode/utf16"
+	"unicode/utf8"
+	"unsafe"
+)
+
+var (
+	initErr error
+	ioSync  uint64
+)
+
+// CancelIo Windows API cancels all outstanding IO for a particular
+// socket on current thread. To overcome that limitation, we run
+// special goroutine, locked to OS single thread, that both starts
+// and cancels IO. It means, there are 2 unavoidable thread switches
+// for every IO.
+// Some newer versions of Windows has new CancelIoEx API, that does
+// not have that limitation and can be used from any thread. This
+// package uses CancelIoEx API, if present, otherwise it fallback
+// to CancelIo.
+
+var (
+	canCancelIO                               bool // determines if CancelIoEx API is present
+	skipSyncNotif                             bool
+	hasLoadSetFileCompletionNotificationModes bool
+)
+
+func init() {
+	var d syscall.WSAData
+	e := syscall.WSAStartup(uint32(0x202), &d)
+	if e != nil {
+		initErr = e
+	}
+	canCancelIO = syscall.LoadCancelIoEx() == nil
+	hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil
+	if hasLoadSetFileCompletionNotificationModes {
+		// It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed:
+		// http://support.microsoft.com/kb/2568167
+		skipSyncNotif = true
+		protos := [2]int32{syscall.IPPROTO_TCP, 0}
+		var buf [32]syscall.WSAProtocolInfo
+		len := uint32(unsafe.Sizeof(buf))
+		n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
+		if err != nil {
+			skipSyncNotif = false
+		} else {
+			for i := int32(0); i < n; i++ {
+				if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
+					skipSyncNotif = false
+					break
+				}
+			}
+		}
+	}
+}
+
+// operation contains superset of data necessary to perform all async IO.
+type operation struct {
+	// Used by IOCP interface, it must be first field
+	// of the struct, as our code rely on it.
+	o syscall.Overlapped
+
+	// fields used by runtime.netpoll
+	runtimeCtx uintptr
+	mode       int32
+	errno      int32
+	qty        uint32
+
+	// fields used only by net package
+	fd     *FD
+	errc   chan error
+	buf    syscall.WSABuf
+	sa     syscall.Sockaddr
+	rsa    *syscall.RawSockaddrAny
+	rsan   int32
+	handle syscall.Handle
+	flags  uint32
+	bufs   []syscall.WSABuf
+}
+
+func (o *operation) InitBuf(buf []byte) {
+	o.buf.Len = uint32(len(buf))
+	o.buf.Buf = nil
+	if len(buf) != 0 {
+		o.buf.Buf = &buf[0]
+	}
+}
+
+func (o *operation) InitBufs(buf *[][]byte) {
+	if o.bufs == nil {
+		o.bufs = make([]syscall.WSABuf, 0, len(*buf))
+	} else {
+		o.bufs = o.bufs[:0]
+	}
+	for _, b := range *buf {
+		var p *byte
+		if len(b) > 0 {
+			p = &b[0]
+		}
+		o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: p})
+	}
+}
+
+// ClearBufs clears all pointers to Buffers parameter captured
+// by InitBufs, so it can be released by garbage collector.
+func (o *operation) ClearBufs() {
+	for i := range o.bufs {
+		o.bufs[i].Buf = nil
+	}
+	o.bufs = o.bufs[:0]
+}
+
+// ioSrv executes net IO requests.
+type ioSrv struct {
+	req chan ioSrvReq
+}
+
+type ioSrvReq struct {
+	o      *operation
+	submit func(o *operation) error // if nil, cancel the operation
+}
+
+// ProcessRemoteIO will execute submit IO requests on behalf
+// of other goroutines, all on a single os thread, so it can
+// cancel them later. Results of all operations will be sent
+// back to their requesters via channel supplied in request.
+// It is used only when the CancelIoEx API is unavailable.
+func (s *ioSrv) ProcessRemoteIO() {
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+	for r := range s.req {
+		if r.submit != nil {
+			r.o.errc <- r.submit(r.o)
+		} else {
+			r.o.errc <- syscall.CancelIo(r.o.fd.Sysfd)
+		}
+	}
+}
+
+// ExecIO executes a single IO operation o. It submits and cancels
+// IO in the current thread for systems where Windows CancelIoEx API
+// is available. Alternatively, it passes the request onto
+// runtime netpoll and waits for completion or cancels request.
+func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) {
+	fd := o.fd
+	// Notify runtime netpoll about starting IO.
+	err := fd.pd.prepare(int(o.mode))
+	if err != nil {
+		return 0, err
+	}
+	// Start IO.
+	if canCancelIO {
+		err = submit(o)
+	} else {
+		// Send request to a special dedicated thread,
+		// so it can stop the IO with CancelIO later.
+		s.req <- ioSrvReq{o, submit}
+		err = <-o.errc
+	}
+	switch err {
+	case nil:
+		// IO completed immediately
+		if o.fd.skipSyncNotif {
+			// No completion message will follow, so return immediately.
+			return int(o.qty), nil
+		}
+		// Need to get our completion message anyway.
+	case syscall.ERROR_IO_PENDING:
+		// IO started, and we have to wait for its completion.
+		err = nil
+	default:
+		return 0, err
+	}
+	// Wait for our request to complete.
+	err = fd.pd.wait(int(o.mode))
+	if err == nil {
+		// All is good. Extract our IO results and return.
+		if o.errno != 0 {
+			err = syscall.Errno(o.errno)
+			return 0, err
+		}
+		return int(o.qty), nil
+	}
+	// IO is interrupted by "close" or "timeout"
+	netpollErr := err
+	switch netpollErr {
+	case ErrClosing, ErrTimeout:
+		// will deal with those.
+	default:
+		panic("net: unexpected runtime.netpoll error: " + netpollErr.Error())
+	}
+	// Cancel our request.
+	if canCancelIO {
+		err := syscall.CancelIoEx(fd.Sysfd, &o.o)
+		// Assuming ERROR_NOT_FOUND is returned, if IO is completed.
+		if err != nil && err != syscall.ERROR_NOT_FOUND {
+			// TODO(brainman): maybe do something else, but panic.
+			panic(err)
+		}
+	} else {
+		s.req <- ioSrvReq{o, nil}
+		<-o.errc
+	}
+	// Wait for cancelation to complete.
+	fd.pd.waitCanceled(int(o.mode))
+	if o.errno != 0 {
+		err = syscall.Errno(o.errno)
+		if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
+			err = netpollErr
+		}
+		return 0, err
+	}
+	// We issued a cancelation request. But, it seems, IO operation succeeded
+	// before the cancelation request run. We need to treat the IO operation as
+	// succeeded (the bytes are actually sent/recv from network).
+	return int(o.qty), nil
+}
+
+// Start helper goroutines.
+var rsrv, wsrv *ioSrv
+var onceStartServer sync.Once
+
+func startServer() {
+	rsrv = new(ioSrv)
+	wsrv = new(ioSrv)
+	if !canCancelIO {
+		// Only CancelIo API is available. Lets start two special goroutines
+		// locked to an OS thread, that both starts and cancels IO. One will
+		// process read requests, while other will do writes.
+		rsrv.req = make(chan ioSrvReq)
+		go rsrv.ProcessRemoteIO()
+		wsrv.req = make(chan ioSrvReq)
+		go wsrv.ProcessRemoteIO()
+	}
+}
+
+// FD is a file descriptor. The net and os packages embed this type in
+// a larger type representing a network connection or OS file.
+type FD struct {
+	// Lock sysfd and serialize access to Read and Write methods.
+	fdmu fdMutex
+
+	// System file descriptor. Immutable until Close.
+	Sysfd syscall.Handle
+
+	// Read operation.
+	rop operation
+	// Write operation.
+	wop operation
+
+	// I/O poller.
+	pd pollDesc
+
+	// Used to implement pread/pwrite.
+	l sync.Mutex
+
+	// For console I/O.
+	isConsole      bool
+	lastbits       []byte   // first few bytes of the last incomplete rune in last write
+	readuint16     []uint16 // buffer to hold uint16s obtained with ReadConsole
+	readbyte       []byte   // buffer to hold decoding of readuint16 from utf16 to utf8
+	readbyteOffset int      // readbyte[readOffset:] is yet to be consumed with file.Read
+
+	skipSyncNotif bool
+
+	// Whether this is a streaming descriptor, as opposed to a
+	// packet-based descriptor like a UDP socket.
+	IsStream bool
+
+	// Whether a zero byte read indicates EOF. This is false for a
+	// message based socket connection.
+	ZeroReadIsEOF bool
+
+	// Whether this is a normal file.
+	isFile bool
+
+	// Whether this is a directory.
+	isDir bool
+}
+
+// Init initializes the FD. The Sysfd field should already be set.
+// This can be called multiple times on a single FD.
+// The net argument is a network name from the net package (e.g., "tcp"),
+// or "file" or "console" or "dir".
+func (fd *FD) Init(net string) (string, error) {
+	if initErr != nil {
+		return "", initErr
+	}
+	onceStartServer.Do(startServer)
+
+	switch net {
+	case "file":
+		fd.isFile = true
+	case "console":
+		fd.isConsole = true
+	case "dir":
+		fd.isDir = true
+	case "tcp", "tcp4", "tcp6":
+	case "udp", "udp4", "udp6":
+	case "ip", "ip4", "ip6":
+	case "unix", "unixgram", "unixpacket":
+	default:
+		return "", errors.New("internal error: unknown network type " + net)
+	}
+
+	if err := fd.pd.init(fd); err != nil {
+		return "", err
+	}
+	if hasLoadSetFileCompletionNotificationModes {
+		// We do not use events, so we can skip them always.
+		flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
+		// It's not safe to skip completion notifications for UDP:
+		// http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
+		if skipSyncNotif && (net == "tcp" || net == "file") {
+			flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
+		}
+		err := syscall.SetFileCompletionNotificationModes(fd.Sysfd, flags)
+		if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
+			fd.skipSyncNotif = true
+		}
+	}
+	// Disable SIO_UDP_CONNRESET behavior.
+	// http://support.microsoft.com/kb/263823
+	switch net {
+	case "udp", "udp4", "udp6":
+		ret := uint32(0)
+		flag := uint32(0)
+		size := uint32(unsafe.Sizeof(flag))
+		err := syscall.WSAIoctl(fd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
+		if err != nil {
+			return "wsaioctl", err
+		}
+	}
+	fd.rop.mode = 'r'
+	fd.wop.mode = 'w'
+	fd.rop.fd = fd
+	fd.wop.fd = fd
+	fd.rop.runtimeCtx = fd.pd.runtimeCtx
+	fd.wop.runtimeCtx = fd.pd.runtimeCtx
+	if !canCancelIO {
+		fd.rop.errc = make(chan error)
+		fd.wop.errc = make(chan error)
+	}
+	return "", nil
+}
+
+func (fd *FD) destroy() error {
+	if fd.Sysfd == syscall.InvalidHandle {
+		return syscall.EINVAL
+	}
+	// Poller may want to unregister fd in readiness notification mechanism,
+	// so this must be executed before fd.CloseFunc.
+	fd.pd.close()
+	var err error
+	if fd.isFile || fd.isConsole {
+		err = syscall.CloseHandle(fd.Sysfd)
+	} else if fd.isDir {
+		err = syscall.FindClose(fd.Sysfd)
+	} else {
+		// The net package uses the CloseFunc variable for testing.
+		err = CloseFunc(fd.Sysfd)
+	}
+	fd.Sysfd = syscall.InvalidHandle
+	return err
+}
+
+func (fd *FD) Close() error {
+	if !fd.fdmu.increfAndClose() {
+		return ErrClosing
+	}
+	// unblock pending reader and writer
+	fd.pd.evict()
+	return fd.decref()
+}
+
+func (fd *FD) Shutdown(how int) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Shutdown(fd.Sysfd, how)
+}
+
+func (fd *FD) Read(buf []byte) (int, error) {
+	if err := fd.readLock(); err != nil {
+		return 0, err
+	}
+	defer fd.readUnlock()
+
+	var n int
+	var err error
+	if fd.isFile || fd.isDir || fd.isConsole {
+		fd.l.Lock()
+		defer fd.l.Unlock()
+		if fd.isConsole {
+			n, err = fd.readConsole(buf)
+		} else {
+			n, err = syscall.Read(fd.Sysfd, buf)
+		}
+		if err != nil {
+			n = 0
+		}
+	} else {
+		o := &fd.rop
+		o.InitBuf(buf)
+		n, err = rsrv.ExecIO(o, "WSARecv", func(o *operation) error {
+			return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
+		})
+		if race.Enabled {
+			race.Acquire(unsafe.Pointer(&ioSync))
+		}
+	}
+	if len(buf) != 0 {
+		err = fd.eofError(n, err)
+	}
+	return n, err
+}
+
+var ReadConsole = syscall.ReadConsole // changed for testing
+
+// readConsole reads utf16 characters from console File,
+// encodes them into utf8 and stores them in buffer b.
+// It returns the number of utf8 bytes read and an error, if any.
+func (fd *FD) readConsole(b []byte) (n int, err error) {
+	if len(b) == 0 {
+		return 0, nil
+	}
+
+	if fd.readuint16 == nil {
+		// Note: syscall.ReadConsole fails for very large buffers.
+		// The limit is somewhere around (but not exactly) 16384.
+		// Stay well below.
+		fd.readuint16 = make([]uint16, 0, 10000)
+		fd.readbyte = make([]byte, 0, 4*cap(fd.readuint16))
+	}
+
+	for fd.readbyteOffset >= len(fd.readbyte) {
+		n := cap(fd.readuint16) - len(fd.readuint16)
+		if n > len(b) {
+			n = len(b)
+		}
+		var nw uint32
+		err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil)
+		if err != nil {
+			return 0, err
+		}
+		uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)]
+		fd.readuint16 = fd.readuint16[:0]
+		buf := fd.readbyte[:0]
+		for i := 0; i < len(uint16s); i++ {
+			r := rune(uint16s[i])
+			if utf16.IsSurrogate(r) {
+				if i+1 == len(uint16s) {
+					if nw > 0 {
+						// Save half surrogate pair for next time.
+						fd.readuint16 = fd.readuint16[:1]
+						fd.readuint16[0] = uint16(r)
+						break
+					}
+					r = utf8.RuneError
+				} else {
+					r = utf16.DecodeRune(r, rune(uint16s[i+1]))
+					if r != utf8.RuneError {
+						i++
+					}
+				}
+			}
+			n := utf8.EncodeRune(buf[len(buf):cap(buf)], r)
+			buf = buf[:len(buf)+n]
+		}
+		fd.readbyte = buf
+		fd.readbyteOffset = 0
+		if nw == 0 {
+			break
+		}
+	}
+
+	src := fd.readbyte[fd.readbyteOffset:]
+	var i int
+	for i = 0; i < len(src) && i < len(b); i++ {
+		x := src[i]
+		if x == 0x1A { // Ctrl-Z
+			if i == 0 {
+				fd.readbyteOffset++
+			}
+			break
+		}
+		b[i] = x
+	}
+	fd.readbyteOffset += i
+	return i, nil
+}
+
+func (fd *FD) Pread(b []byte, off int64) (n int, err error) {
+	if err := fd.readLock(); err != nil {
+		return 0, err
+	}
+	defer fd.readUnlock()
+
+	fd.l.Lock()
+	defer fd.l.Unlock()
+	curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
+	if e != nil {
+		return 0, e
+	}
+	defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
+	o := syscall.Overlapped{
+		OffsetHigh: uint32(off >> 32),
+		Offset:     uint32(off),
+	}
+	var done uint32
+	e = syscall.ReadFile(fd.Sysfd, b, &done, &o)
+	if e != nil {
+		if e == syscall.ERROR_HANDLE_EOF {
+			// end of file
+			return 0, nil
+		}
+		return 0, e
+	}
+	return int(done), nil
+}
+
+func (fd *FD) RecvFrom(buf []byte) (int, syscall.Sockaddr, error) {
+	if len(buf) == 0 {
+		return 0, nil, nil
+	}
+	if err := fd.readLock(); err != nil {
+		return 0, nil, err
+	}
+	defer fd.readUnlock()
+	o := &fd.rop
+	o.InitBuf(buf)
+	n, err := rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error {
+		if o.rsa == nil {
+			o.rsa = new(syscall.RawSockaddrAny)
+		}
+		o.rsan = int32(unsafe.Sizeof(*o.rsa))
+		return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
+	})
+	err = fd.eofError(n, err)
+	if err != nil {
+		return n, nil, err
+	}
+	sa, _ := o.rsa.Sockaddr()
+	return n, sa, nil
+}
+
+func (fd *FD) Write(buf []byte) (int, error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+
+	var n int
+	var err error
+	if fd.isFile || fd.isDir || fd.isConsole {
+		fd.l.Lock()
+		defer fd.l.Unlock()
+		if fd.isConsole {
+			n, err = fd.writeConsole(buf)
+		} else {
+			n, err = syscall.Write(fd.Sysfd, buf)
+		}
+		if err != nil {
+			n = 0
+		}
+	} else {
+		if race.Enabled {
+			race.ReleaseMerge(unsafe.Pointer(&ioSync))
+		}
+		o := &fd.wop
+		o.InitBuf(buf)
+		n, err = wsrv.ExecIO(o, "WSASend", func(o *operation) error {
+			return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
+		})
+	}
+	return n, err
+}
+
+// writeConsole writes len(b) bytes to the console File.
+// It returns the number of bytes written and an error, if any.
+func (fd *FD) writeConsole(b []byte) (n int, err error) {
+	n = len(b)
+	runes := make([]rune, 0, 256)
+	if len(fd.lastbits) > 0 {
+		b = append(fd.lastbits, b...)
+		fd.lastbits = nil
+
+	}
+	for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
+		r, l := utf8.DecodeRune(b)
+		runes = append(runes, r)
+		b = b[l:]
+	}
+	if len(b) > 0 {
+		fd.lastbits = make([]byte, len(b))
+		copy(fd.lastbits, b)
+	}
+	// syscall.WriteConsole seems to fail, if given large buffer.
+	// So limit the buffer to 16000 characters. This number was
+	// discovered by experimenting with syscall.WriteConsole.
+	const maxWrite = 16000
+	for len(runes) > 0 {
+		m := len(runes)
+		if m > maxWrite {
+			m = maxWrite
+		}
+		chunk := runes[:m]
+		runes = runes[m:]
+		uint16s := utf16.Encode(chunk)
+		for len(uint16s) > 0 {
+			var written uint32
+			err = syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil)
+			if err != nil {
+				return 0, nil
+			}
+			uint16s = uint16s[written:]
+		}
+	}
+	return n, nil
+}
+
+func (fd *FD) Pwrite(b []byte, off int64) (int, error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+
+	fd.l.Lock()
+	defer fd.l.Unlock()
+	curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
+	if e != nil {
+		return 0, e
+	}
+	defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
+	o := syscall.Overlapped{
+		OffsetHigh: uint32(off >> 32),
+		Offset:     uint32(off),
+	}
+	var done uint32
+	e = syscall.WriteFile(fd.Sysfd, b, &done, &o)
+	if e != nil {
+		return 0, e
+	}
+	return int(done), nil
+}
+
+func (fd *FD) Writev(buf *[][]byte) (int64, error) {
+	if len(*buf) == 0 {
+		return 0, nil
+	}
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	if race.Enabled {
+		race.ReleaseMerge(unsafe.Pointer(&ioSync))
+	}
+	o := &fd.wop
+	o.InitBufs(buf)
+	n, err := wsrv.ExecIO(o, "WSASend", func(o *operation) error {
+		return syscall.WSASend(o.fd.Sysfd, &o.bufs[0], uint32(len(*buf)), &o.qty, 0, &o.o, nil)
+	})
+	o.ClearBufs()
+	TestHookDidWritev(n)
+	consume(buf, int64(n))
+	return int64(n), err
+}
+
+func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
+	if len(buf) == 0 {
+		return 0, nil
+	}
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	o := &fd.wop
+	o.InitBuf(buf)
+	o.sa = sa
+	n, err := wsrv.ExecIO(o, "WSASendto", func(o *operation) error {
+		return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
+	})
+	return n, err
+}
+
+// Call ConnectEx. This doesn't need any locking, since it is only
+// called when the descriptor is first created. This is here rather
+// than in the net package so that it can use fd.wop.
+func (fd *FD) ConnectEx(ra syscall.Sockaddr) error {
+	o := &fd.wop
+	o.sa = ra
+	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
+		return ConnectExFunc(o.fd.Sysfd, o.sa, nil, 0, nil, &o.o)
+	})
+	return err
+}
+
+func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) (string, error) {
+	// Submit accept request.
+	o.handle = s
+	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
+	_, err := rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
+		return AcceptFunc(o.fd.Sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
+	})
+	if err != nil {
+		CloseFunc(s)
+		return "acceptex", err
+	}
+
+	// Inherit properties of the listening socket.
+	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd)))
+	if err != nil {
+		CloseFunc(s)
+		return "setsockopt", err
+	}
+
+	return "", nil
+}
+
+// Accept handles accepting a socket. The sysSocket parameter is used
+// to allocate the net socket.
+func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) {
+	if err := fd.readLock(); err != nil {
+		return syscall.InvalidHandle, nil, 0, "", err
+	}
+	defer fd.readUnlock()
+
+	o := &fd.rop
+	var rawsa [2]syscall.RawSockaddrAny
+	for {
+		s, err := sysSocket()
+		if err != nil {
+			return syscall.InvalidHandle, nil, 0, "", err
+		}
+
+		errcall, err := fd.acceptOne(s, rawsa[:], o)
+		if err == nil {
+			return s, rawsa[:], uint32(o.rsan), "", nil
+		}
+
+		// Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
+		// returned here. These happen if connection reset is received
+		// before AcceptEx could complete. These errors relate to new
+		// connection, not to AcceptEx, so ignore broken connection and
+		// try AcceptEx again for more connections.
+		errno, ok := err.(syscall.Errno)
+		if !ok {
+			return syscall.InvalidHandle, nil, 0, errcall, err
+		}
+		switch errno {
+		case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
+			// ignore these and try again
+		default:
+			return syscall.InvalidHandle, nil, 0, errcall, err
+		}
+	}
+}
+
+func (fd *FD) Seek(offset int64, whence int) (ret int64, err error) {
+	if err := fd.incref(); err != nil {
+		return 0, err
+	}
+	defer fd.decref()
+
+	fd.l.Lock()
+	defer fd.l.Unlock()
+
+	return syscall.Seek(fd.Sysfd, offset, whence)
+}
+
+// FindNextFile wraps syscall.FindNextFile.
+func (fd *FD) FindNextFile(data *syscall.Win32finddata) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.FindNextFile(fd.Sysfd, data)
+}
+
+// Fchdir wraps syscall.Fchdir.
+func (fd *FD) Fchdir() error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Fchdir(fd.Sysfd)
+}
+
+func (fd *FD) GetFileType() (uint32, error) {
+	if err := fd.incref(); err != nil {
+		return 0, err
+	}
+	defer fd.decref()
+	return syscall.GetFileType(fd.Sysfd)
+}
+
+func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.GetFileInformationByHandle(fd.Sysfd, data)
+}
diff --git a/src/internal/poll/hook_cloexec.go b/src/internal/poll/hook_cloexec.go
new file mode 100644
index 0000000..062c343
--- /dev/null
+++ b/src/internal/poll/hook_cloexec.go
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+// +build freebsd linux
+
+package poll
+
+import "syscall"
+
+// Accept4Func is used to hook the accept4 call.
+var Accept4Func func(int, int) (int, syscall.Sockaddr, error) = syscall.Accept4
diff --git a/src/internal/poll/hook_unix.go b/src/internal/poll/hook_unix.go
new file mode 100644
index 0000000..4a6ff6c
--- /dev/null
+++ b/src/internal/poll/hook_unix.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package poll
+
+import (
+	"syscall"
+)
+
+// CloseFunc is used to hook the close call.
+var CloseFunc func(int) error = syscall.Close
+
+// AcceptFunc is used to hook the accept call.
+var AcceptFunc func(int) (int, syscall.Sockaddr, error) = syscall.Accept
diff --git a/src/internal/poll/hook_windows.go b/src/internal/poll/hook_windows.go
new file mode 100644
index 0000000..9766555
--- /dev/null
+++ b/src/internal/poll/hook_windows.go
@@ -0,0 +1,18 @@
+// Copyright 2017 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 poll
+
+import (
+	"syscall"
+)
+
+// CloseFunc is used to hook the close call.
+var CloseFunc func(syscall.Handle) error = syscall.Closesocket
+
+// AcceptFunc is used to hook the accept call.
+var AcceptFunc func(syscall.Handle, syscall.Handle, *byte, uint32, uint32, uint32, *uint32, *syscall.Overlapped) error = syscall.AcceptEx
+
+// ConnectExFunc is used to hook the ConnectEx call.
+var ConnectExFunc func(syscall.Handle, syscall.Sockaddr, *byte, uint32, *uint32, *syscall.Overlapped) error = syscall.ConnectEx
diff --git a/src/internal/poll/sendfile_bsd.go b/src/internal/poll/sendfile_bsd.go
new file mode 100644
index 0000000..9f8b1a3
--- /dev/null
+++ b/src/internal/poll/sendfile_bsd.go
@@ -0,0 +1,51 @@
+// 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.
+
+// +build dragonfly freebsd
+
+package poll
+
+import "syscall"
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// SendFile wraps the sendfile system call.
+func SendFile(dstFD *FD, src int, pos, remain int64) (written int64, err error) {
+	if err := dstFD.writeLock(); err != nil {
+		return 0, err
+	}
+	defer dstFD.writeUnlock()
+	dst := int(dstFD.Sysfd)
+	for remain > 0 {
+		n := maxSendfileSize
+		if int64(n) > remain {
+			n = int(remain)
+		}
+		pos1 := pos
+		n, err1 := syscall.Sendfile(dst, src, &pos1, n)
+		if n > 0 {
+			pos += int64(n)
+			written += int64(n)
+			remain -= int64(n)
+		}
+		if n == 0 && err1 == nil {
+			break
+		}
+		if err1 == syscall.EAGAIN {
+			if err1 = dstFD.pd.waitWrite(); err1 == nil {
+				continue
+			}
+		}
+		if err1 != nil {
+			// This includes syscall.ENOSYS (no kernel
+			// support) and syscall.EINVAL (fd types which
+			// don't implement sendfile)
+			err = err1
+			break
+		}
+	}
+	return written, err
+}
diff --git a/src/internal/poll/sendfile_linux.go b/src/internal/poll/sendfile_linux.go
new file mode 100644
index 0000000..0bc7529
--- /dev/null
+++ b/src/internal/poll/sendfile_linux.go
@@ -0,0 +1,48 @@
+// 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 poll
+
+import "syscall"
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// SendFile wraps the sendfile system call.
+func SendFile(dstFD *FD, src int, remain int64) (written int64, err error) {
+	if err := dstFD.writeLock(); err != nil {
+		return 0, err
+	}
+	defer dstFD.writeUnlock()
+
+	dst := int(dstFD.Sysfd)
+	for remain > 0 {
+		n := maxSendfileSize
+		if int64(n) > remain {
+			n = int(remain)
+		}
+		n, err1 := syscall.Sendfile(dst, src, nil, n)
+		if n > 0 {
+			written += int64(n)
+			remain -= int64(n)
+		}
+		if n == 0 && err1 == nil {
+			break
+		}
+		if err1 == syscall.EAGAIN {
+			if err1 = dstFD.pd.waitWrite(); err1 == nil {
+				continue
+			}
+		}
+		if err1 != nil {
+			// This includes syscall.ENOSYS (no kernel
+			// support) and syscall.EINVAL (fd types which
+			// don't implement sendfile)
+			err = err1
+			break
+		}
+	}
+	return written, err
+}
diff --git a/src/internal/poll/sendfile_solaris.go b/src/internal/poll/sendfile_solaris.go
new file mode 100644
index 0000000..6d03ecc
--- /dev/null
+++ b/src/internal/poll/sendfile_solaris.go
@@ -0,0 +1,64 @@
+// Copyright 2015 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 poll
+
+import "syscall"
+
+// Not strictly needed, but very helpful for debugging, see issue #10221.
+//go:cgo_import_dynamic _ _ "libsendfile.so"
+//go:cgo_import_dynamic _ _ "libsocket.so"
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// SendFile wraps the sendfile system call.
+func SendFile(dstFD *FD, src int, pos, remain int64) (written int64, err error) {
+	if err := dstFD.writeLock(); err != nil {
+		return 0, err
+	}
+	defer dstFD.writeUnlock()
+
+	dst := int(dstFD.Sysfd)
+	for remain > 0 {
+		n := maxSendfileSize
+		if int64(n) > remain {
+			n = int(remain)
+		}
+		pos1 := pos
+		n, err1 := syscall.Sendfile(dst, src, &pos1, n)
+		if err1 == syscall.EAGAIN || err1 == syscall.EINTR {
+			// partial write may have occurred
+			if n = int(pos1 - pos); n == 0 {
+				// nothing more to write
+				err1 = nil
+			}
+		}
+		if n > 0 {
+			pos += int64(n)
+			written += int64(n)
+			remain -= int64(n)
+		}
+		if n == 0 && err1 == nil {
+			break
+		}
+		if err1 == syscall.EAGAIN {
+			if err1 = dstFD.pd.waitWrite(); err1 == nil {
+				continue
+			}
+		}
+		if err1 == syscall.EINTR {
+			continue
+		}
+		if err1 != nil {
+			// This includes syscall.ENOSYS (no kernel
+			// support) and syscall.EINVAL (fd types which
+			// don't implement sendfile)
+			err = err1
+			break
+		}
+	}
+	return written, err
+}
diff --git a/src/internal/poll/sendfile_windows.go b/src/internal/poll/sendfile_windows.go
new file mode 100644
index 0000000..762165a
--- /dev/null
+++ b/src/internal/poll/sendfile_windows.go
@@ -0,0 +1,23 @@
+// 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 poll
+
+import "syscall"
+
+// SendFile wraps the TransmitFile call.
+func SendFile(fd *FD, src syscall.Handle, n int64) (int64, error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+
+	o := &fd.wop
+	o.qty = uint32(n)
+	o.handle = src
+	done, err := wsrv.ExecIO(o, "TransmitFile", func(o *operation) error {
+		return syscall.TransmitFile(o.fd.Sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
+	})
+	return int64(done), err
+}
diff --git a/src/internal/poll/sock_cloexec.go b/src/internal/poll/sock_cloexec.go
new file mode 100644
index 0000000..28b950c3
--- /dev/null
+++ b/src/internal/poll/sock_cloexec.go
@@ -0,0 +1,52 @@
+// Copyright 2013 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.
+
+// This file implements sysSocket and accept for platforms that
+// provide a fast path for setting SetNonblock and CloseOnExec.
+
+// +build freebsd linux
+
+package poll
+
+import (
+	"syscall"
+)
+
+// Wrapper around the accept system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func accept(s int) (int, syscall.Sockaddr, string, error) {
+	ns, sa, err := Accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
+	// On Linux the accept4 system call was introduced in 2.6.28
+	// kernel and on FreeBSD it was introduced in 10 kernel. If we
+	// get an ENOSYS error on both Linux and FreeBSD, or EINVAL
+	// error on Linux, fall back to using accept.
+	switch err {
+	case nil:
+		return ns, sa, "", nil
+	default: // errors other than the ones listed
+		return -1, sa, "accept4", err
+	case syscall.ENOSYS: // syscall missing
+	case syscall.EINVAL: // some Linux use this instead of ENOSYS
+	case syscall.EACCES: // some Linux use this instead of ENOSYS
+	case syscall.EFAULT: // some Linux use this instead of ENOSYS
+	}
+
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	// It is probably okay to hold the lock across syscall.Accept
+	// because we have put fd.sysfd into non-blocking mode.
+	// However, a call to the File method will put it back into
+	// blocking mode. We can't take that risk, so no use of ForkLock here.
+	ns, sa, err = AcceptFunc(s)
+	if err == nil {
+		syscall.CloseOnExec(ns)
+	}
+	if err != nil {
+		return -1, nil, "accept", err
+	}
+	if err = syscall.SetNonblock(ns, true); err != nil {
+		CloseFunc(ns)
+		return -1, nil, "setnonblock", err
+	}
+	return ns, sa, "", nil
+}
diff --git a/src/internal/poll/sockopt.go b/src/internal/poll/sockopt.go
new file mode 100644
index 0000000..b841699
--- /dev/null
+++ b/src/internal/poll/sockopt.go
@@ -0,0 +1,38 @@
+// Copyright 2009 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package poll
+
+import (
+	"syscall"
+)
+
+// SetsockoptInt wraps the setsockopt network call with an int argument.
+func (fd *FD) SetsockoptInt(level, name, arg int) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.SetsockoptInt(fd.Sysfd, level, name, arg)
+}
+
+// SetsockoptInet4Addr wraps the setsockopt network call with an IPv4 address.
+func (fd *FD) SetsockoptInet4Addr(level, name int, arg [4]byte) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.SetsockoptInet4Addr(fd.Sysfd, level, name, arg)
+}
+
+// SetsockoptLinger wraps the setsockopt network call with a Linger argument.
+func (fd *FD) SetsockoptLinger(level, name int, l *syscall.Linger) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.SetsockoptLinger(fd.Sysfd, level, name, l)
+}
diff --git a/src/internal/poll/sockopt_linux.go b/src/internal/poll/sockopt_linux.go
new file mode 100644
index 0000000..ba616db
--- /dev/null
+++ b/src/internal/poll/sockopt_linux.go
@@ -0,0 +1,18 @@
+// 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 poll
+
+import (
+	"syscall"
+)
+
+// SetsockoptIPMreqn wraps the setsockopt network call with a IPMreqn argument.
+func (fd *FD) SetsockoptIPMreqn(level, name int, mreq *syscall.IPMreqn) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.SetsockoptIPMreqn(fd.Sysfd, level, name, mreq)
+}
diff --git a/src/internal/poll/sockopt_unix.go b/src/internal/poll/sockopt_unix.go
new file mode 100644
index 0000000..b33644d
--- /dev/null
+++ b/src/internal/poll/sockopt_unix.go
@@ -0,0 +1,18 @@
+// Copyright 2017 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package poll
+
+import "syscall"
+
+// SetsockoptByte wraps the setsockopt network call with a byte argument.
+func (fd *FD) SetsockoptByte(level, name int, arg byte) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.SetsockoptByte(fd.Sysfd, level, name, arg)
+}
diff --git a/src/internal/poll/sockopt_windows.go b/src/internal/poll/sockopt_windows.go
new file mode 100644
index 0000000..70501a0
--- /dev/null
+++ b/src/internal/poll/sockopt_windows.go
@@ -0,0 +1,27 @@
+// Copyright 2009 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 poll
+
+import (
+	"syscall"
+)
+
+// Setsockopt wraps the Windows setsockopt network call.
+func (fd *FD) Setsockopt(level, optname int32, optval *byte, optlen int32) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.Setsockopt(fd.Sysfd, level, optname, optval, optlen)
+}
+
+// WSAIoctl wraps the Windows WSAIoctl call.
+func (fd *FD) WSAIoctl(iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *syscall.Overlapped, completionRoutine uintptr) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.WSAIoctl(fd.Sysfd, iocc, inbuf, cbif, outbuf, cbob, cbbr, overlapped, completionRoutine)
+}
diff --git a/src/internal/poll/sockoptip.go b/src/internal/poll/sockoptip.go
new file mode 100644
index 0000000..28900eb
--- /dev/null
+++ b/src/internal/poll/sockoptip.go
@@ -0,0 +1,27 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
+
+package poll
+
+import "syscall"
+
+// SetsockoptIPMreq wraps the setsockopt network call with a IPMreq argument.
+func (fd *FD) SetsockoptIPMreq(level, name int, mreq *syscall.IPMreq) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.SetsockoptIPMreq(fd.Sysfd, level, name, mreq)
+}
+
+// SetsockoptIPv6Mreq wraps the setsockopt network call with a IPv6Mreq argument.
+func (fd *FD) SetsockoptIPv6Mreq(level, name int, mreq *syscall.IPv6Mreq) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return syscall.SetsockoptIPv6Mreq(fd.Sysfd, level, name, mreq)
+}
diff --git a/src/internal/poll/str.go b/src/internal/poll/str.go
new file mode 100644
index 0000000..2be35c7
--- /dev/null
+++ b/src/internal/poll/str.go
@@ -0,0 +1,39 @@
+// Copyright 2009 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.
+
+// Simple conversions to avoid depending on strconv.
+
+package poll
+
+// Convert integer to decimal string
+func itoa(val int) string {
+	if val < 0 {
+		return "-" + uitoa(uint(-val))
+	}
+	return uitoa(uint(val))
+}
+
+// Convert unsigned integer to decimal string
+func uitoa(val uint) string {
+	if val == 0 { // avoid string allocation
+		return "0"
+	}
+	var buf [20]byte // big enough for 64bit value base 10
+	i := len(buf) - 1
+	for val >= 10 {
+		q := val / 10
+		buf[i] = byte('0' + val - q*10)
+		i--
+		val = q
+	}
+	// val < 10
+	buf[i] = byte('0' + val)
+	return string(buf[i:])
+}
+
+// stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
+// suffix.
+func stringsHasSuffix(s, suffix string) bool {
+	return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
+}
diff --git a/src/internal/poll/sys_cloexec.go b/src/internal/poll/sys_cloexec.go
new file mode 100644
index 0000000..d001245
--- /dev/null
+++ b/src/internal/poll/sys_cloexec.go
@@ -0,0 +1,36 @@
+// Copyright 2013 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.
+
+// This file implements sysSocket and accept for platforms that do not
+// provide a fast path for setting SetNonblock and CloseOnExec.
+
+// +build darwin dragonfly nacl netbsd openbsd solaris
+
+package poll
+
+import (
+	"syscall"
+)
+
+// Wrapper around the accept system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func accept(s int) (int, syscall.Sockaddr, string, error) {
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	// It is probably okay to hold the lock across syscall.Accept
+	// because we have put fd.sysfd into non-blocking mode.
+	// However, a call to the File method will put it back into
+	// blocking mode. We can't take that risk, so no use of ForkLock here.
+	ns, sa, err := AcceptFunc(s)
+	if err == nil {
+		syscall.CloseOnExec(ns)
+	}
+	if err != nil {
+		return -1, nil, "accept", err
+	}
+	if err = syscall.SetNonblock(ns, true); err != nil {
+		CloseFunc(ns)
+		return -1, nil, "setnonblock", err
+	}
+	return ns, sa, "", nil
+}
diff --git a/src/internal/poll/writev.go b/src/internal/poll/writev.go
new file mode 100644
index 0000000..fcee388
--- /dev/null
+++ b/src/internal/poll/writev.go
@@ -0,0 +1,81 @@
+// Copyright 2016 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package poll
+
+import (
+	"io"
+	"syscall"
+	"unsafe"
+)
+
+// Writev wraps the writev system call.
+func (fd *FD) Writev(v *[][]byte) (n int64, err error) {
+	if err := fd.writeLock(); err != nil {
+		return 0, err
+	}
+	defer fd.writeUnlock()
+	if err := fd.pd.prepareWrite(); err != nil {
+		return 0, err
+	}
+
+	var iovecs []syscall.Iovec
+	if fd.iovecs != nil {
+		iovecs = *fd.iovecs
+	}
+	// TODO: read from sysconf(_SC_IOV_MAX)? The Linux default is
+	// 1024 and this seems conservative enough for now. Darwin's
+	// UIO_MAXIOV also seems to be 1024.
+	maxVec := 1024
+
+	for len(*v) > 0 {
+		iovecs = iovecs[:0]
+		for _, chunk := range *v {
+			if len(chunk) == 0 {
+				continue
+			}
+			iovecs = append(iovecs, syscall.Iovec{Base: &chunk[0]})
+			if fd.IsStream && len(chunk) > 1<<30 {
+				iovecs[len(iovecs)-1].SetLen(1 << 30)
+				break // continue chunk on next writev
+			}
+			iovecs[len(iovecs)-1].SetLen(len(chunk))
+			if len(iovecs) == maxVec {
+				break
+			}
+		}
+		if len(iovecs) == 0 {
+			break
+		}
+		fd.iovecs = &iovecs // cache
+
+		wrote, _, e0 := syscall.Syscall(syscall.SYS_WRITEV,
+			uintptr(fd.Sysfd),
+			uintptr(unsafe.Pointer(&iovecs[0])),
+			uintptr(len(iovecs)))
+		if wrote == ^uintptr(0) {
+			wrote = 0
+		}
+		TestHookDidWritev(int(wrote))
+		n += int64(wrote)
+		consume(v, int64(wrote))
+		if e0 == syscall.EAGAIN {
+			if err = fd.pd.waitWrite(); err == nil {
+				continue
+			}
+		} else if e0 != 0 {
+			err = syscall.Errno(e0)
+		}
+		if err != nil {
+			break
+		}
+		if n == 0 {
+			err = io.ErrUnexpectedEOF
+			break
+		}
+	}
+	return n, err
+}
diff --git a/src/internal/poll/writev_test.go b/src/internal/poll/writev_test.go
new file mode 100644
index 0000000..b46657c
--- /dev/null
+++ b/src/internal/poll/writev_test.go
@@ -0,0 +1,62 @@
+// Copyright 2016 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 poll_test
+
+import (
+	"internal/poll"
+	"reflect"
+	"testing"
+)
+
+func TestConsume(t *testing.T) {
+	tests := []struct {
+		in      [][]byte
+		consume int64
+		want    [][]byte
+	}{
+		{
+			in:      [][]byte{[]byte("foo"), []byte("bar")},
+			consume: 0,
+			want:    [][]byte{[]byte("foo"), []byte("bar")},
+		},
+		{
+			in:      [][]byte{[]byte("foo"), []byte("bar")},
+			consume: 2,
+			want:    [][]byte{[]byte("o"), []byte("bar")},
+		},
+		{
+			in:      [][]byte{[]byte("foo"), []byte("bar")},
+			consume: 3,
+			want:    [][]byte{[]byte("bar")},
+		},
+		{
+			in:      [][]byte{[]byte("foo"), []byte("bar")},
+			consume: 4,
+			want:    [][]byte{[]byte("ar")},
+		},
+		{
+			in:      [][]byte{nil, nil, nil, []byte("bar")},
+			consume: 1,
+			want:    [][]byte{[]byte("ar")},
+		},
+		{
+			in:      [][]byte{nil, nil, nil, []byte("foo")},
+			consume: 0,
+			want:    [][]byte{[]byte("foo")},
+		},
+		{
+			in:      [][]byte{nil, nil, nil},
+			consume: 0,
+			want:    [][]byte{},
+		},
+	}
+	for i, tt := range tests {
+		in := tt.in
+		poll.Consume(&in, tt.consume)
+		if !reflect.DeepEqual(in, tt.want) {
+			t.Errorf("%d. after consume(%d) = %+v, want %+v", i, tt.consume, in, tt.want)
+		}
+	}
+}
diff --git a/src/net/dial.go b/src/net/dial.go
index 50bba5a..0a7da40 100644
--- a/src/net/dial.go
+++ b/src/net/dial.go
@@ -7,6 +7,7 @@
 import (
 	"context"
 	"internal/nettrace"
+	"internal/poll"
 	"time"
 )
 
@@ -110,7 +111,7 @@
 	}
 	timeRemaining := deadline.Sub(now)
 	if timeRemaining <= 0 {
-		return time.Time{}, errTimeout
+		return time.Time{}, poll.ErrTimeout
 	}
 	// Tentatively allocate equal time to each remaining address.
 	timeout := timeRemaining / time.Duration(addrsRemaining)
diff --git a/src/net/dial_test.go b/src/net/dial_test.go
index 9919d72..9825bc9 100644
--- a/src/net/dial_test.go
+++ b/src/net/dial_test.go
@@ -7,6 +7,7 @@
 import (
 	"bufio"
 	"context"
+	"internal/poll"
 	"internal/testenv"
 	"io"
 	"net/internal/socktest"
@@ -94,7 +95,7 @@
 	default:
 		sw.Set(socktest.FilterConnect, func(so *socktest.Status) (socktest.AfterFilter, error) {
 			time.Sleep(2 * T)
-			return nil, errTimeout
+			return nil, poll.ErrTimeout
 		})
 		defer sw.Set(socktest.FilterConnect, nil)
 	}
@@ -585,8 +586,8 @@
 		{now, noDeadline, 1, noDeadline, nil},
 		// Step the clock forward and cross the deadline.
 		{now.Add(-1 * time.Millisecond), now, 1, now, nil},
-		{now.Add(0 * time.Millisecond), now, 1, noDeadline, errTimeout},
-		{now.Add(1 * time.Millisecond), now, 1, noDeadline, errTimeout},
+		{now.Add(0 * time.Millisecond), now, 1, noDeadline, poll.ErrTimeout},
+		{now.Add(1 * time.Millisecond), now, 1, noDeadline, poll.ErrTimeout},
 	}
 	for i, tt := range testCases {
 		deadline, err := partialDeadline(tt.now, tt.deadline, tt.addrs)
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 85267bb..4464804 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -9,6 +9,7 @@
 import (
 	"context"
 	"fmt"
+	"internal/poll"
 	"internal/testenv"
 	"io/ioutil"
 	"os"
@@ -767,7 +768,7 @@
 		if s == "192.0.2.1:53" {
 			deadline0 = deadline
 			time.Sleep(10 * time.Millisecond)
-			return nil, errTimeout
+			return nil, poll.ErrTimeout
 		}
 
 		if deadline == deadline0 {
diff --git a/src/net/error_posix.go b/src/net/error_posix.go
new file mode 100644
index 0000000..dd9754c
--- /dev/null
+++ b/src/net/error_posix.go
@@ -0,0 +1,21 @@
+// Copyright 2017 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+// wrapSyscallError takes an error and a syscall name. If the error is
+// a syscall.Errno, it wraps it in a os.SyscallError using the syscall name.
+func wrapSyscallError(name string, err error) error {
+	if _, ok := err.(syscall.Errno); ok {
+		err = os.NewSyscallError(name, err)
+	}
+	return err
+}
diff --git a/src/net/error_test.go b/src/net/error_test.go
index c23da49..61abfae 100644
--- a/src/net/error_test.go
+++ b/src/net/error_test.go
@@ -7,6 +7,7 @@
 import (
 	"context"
 	"fmt"
+	"internal/poll"
 	"io"
 	"io/ioutil"
 	"net/internal/socktest"
@@ -87,7 +88,7 @@
 		return nil
 	}
 	switch err := nestedErr.(type) {
-	case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *timeoutError, UnknownNetworkError:
+	case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
 		return nil
 	case *os.SyscallError:
 		nestedErr = err.Err
@@ -97,7 +98,7 @@
 		goto third
 	}
 	switch nestedErr {
-	case errCanceled, errClosing, errMissingAddress, errNoSuitableAddress,
+	case errCanceled, poll.ErrClosing, errMissingAddress, errNoSuitableAddress,
 		context.DeadlineExceeded, context.Canceled:
 		return nil
 	}
@@ -432,7 +433,7 @@
 		goto third
 	}
 	switch nestedErr {
-	case errClosing, errTimeout:
+	case poll.ErrClosing, poll.ErrTimeout:
 		return nil
 	}
 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
@@ -467,14 +468,14 @@
 		return nil
 	}
 	switch err := nestedErr.(type) {
-	case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *timeoutError, UnknownNetworkError:
+	case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
 		return nil
 	case *os.SyscallError:
 		nestedErr = err.Err
 		goto third
 	}
 	switch nestedErr {
-	case errCanceled, errClosing, errMissingAddress, errTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
+	case errCanceled, poll.ErrClosing, errMissingAddress, poll.ErrTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
 		return nil
 	}
 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
@@ -517,7 +518,7 @@
 		goto third
 	}
 	switch nestedErr {
-	case errClosing:
+	case poll.ErrClosing:
 		return nil
 	}
 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
@@ -613,7 +614,7 @@
 		goto third
 	}
 	switch nestedErr {
-	case errClosing, errTimeout:
+	case poll.ErrClosing, poll.ErrTimeout:
 		return nil
 	}
 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
@@ -692,7 +693,7 @@
 		goto third
 	}
 	switch nestedErr {
-	case errClosing:
+	case poll.ErrClosing:
 		return nil
 	}
 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
diff --git a/src/net/fd_plan9.go b/src/net/fd_plan9.go
index 300d8c4..7496e36 100644
--- a/src/net/fd_plan9.go
+++ b/src/net/fd_plan9.go
@@ -5,23 +5,15 @@
 package net
 
 import (
+	"internal/poll"
 	"io"
 	"os"
-	"sync/atomic"
 	"syscall"
-	"time"
 )
 
-type atomicBool int32
-
-func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
-func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
-func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
-
 // Network file descriptor.
 type netFD struct {
-	// locking/lifetime of sysfd + serialize access to Read and Write methods
-	fdmu fdMutex
+	pfd poll.FD
 
 	// immutable until Close
 	net               string
@@ -30,14 +22,6 @@
 	listen, ctl, data *os.File
 	laddr, raddr      Addr
 	isStream          bool
-
-	// deadlines
-	raio      *asyncIO
-	waio      *asyncIO
-	rtimer    *time.Timer
-	wtimer    *time.Timer
-	rtimedout atomicBool // set true when read deadline has been reached
-	wtimedout atomicBool // set true when write deadline has been reached
 }
 
 var (
@@ -49,7 +33,7 @@
 }
 
 func newFD(net, name string, listen, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
-	return &netFD{
+	ret := &netFD{
 		net:    net,
 		n:      name,
 		dir:    netdir + "/" + net + "/" + name,
@@ -57,7 +41,9 @@
 		ctl:    ctl, data: data,
 		laddr: laddr,
 		raddr: raddr,
-	}, nil
+	}
+	ret.pfd.Destroy = ret.destroy
+	return ret, nil
 }
 
 func (fd *netFD) init() error {
@@ -99,28 +85,10 @@
 }
 
 func (fd *netFD) Read(b []byte) (n int, err error) {
-	if fd.rtimedout.isSet() {
-		return 0, errTimeout
-	}
 	if !fd.ok() || fd.data == nil {
 		return 0, syscall.EINVAL
 	}
-	if err := fd.readLock(); err != nil {
-		return 0, err
-	}
-	defer fd.readUnlock()
-	if len(b) == 0 {
-		return 0, nil
-	}
-	fd.raio = newAsyncIO(fd.data.Read, b)
-	n, err = fd.raio.Wait()
-	fd.raio = nil
-	if isHangup(err) {
-		err = io.EOF
-	}
-	if isInterrupted(err) {
-		err = errTimeout
-	}
+	n, err = fd.pfd.Read(fd.data.Read, b)
 	if fd.net == "udp" && err == io.EOF {
 		n = 0
 		err = nil
@@ -129,23 +97,10 @@
 }
 
 func (fd *netFD) Write(b []byte) (n int, err error) {
-	if fd.wtimedout.isSet() {
-		return 0, errTimeout
-	}
 	if !fd.ok() || fd.data == nil {
 		return 0, syscall.EINVAL
 	}
-	if err := fd.writeLock(); err != nil {
-		return 0, err
-	}
-	defer fd.writeUnlock()
-	fd.waio = newAsyncIO(fd.data.Write, b)
-	n, err = fd.waio.Wait()
-	fd.waio = nil
-	if isInterrupted(err) {
-		err = errTimeout
-	}
-	return
+	return fd.pfd.Write(fd.data.Write, b)
 }
 
 func (fd *netFD) closeRead() error {
@@ -163,8 +118,8 @@
 }
 
 func (fd *netFD) Close() error {
-	if !fd.fdmu.increfAndClose() {
-		return errClosing
+	if err := fd.pfd.Close(); err != nil {
+		return err
 	}
 	if !fd.ok() {
 		return syscall.EINVAL
@@ -216,77 +171,6 @@
 	return os.NewFile(uintptr(dfd), s), nil
 }
 
-func (fd *netFD) setDeadline(t time.Time) error {
-	return setDeadlineImpl(fd, t, 'r'+'w')
-}
-
-func (fd *netFD) setReadDeadline(t time.Time) error {
-	return setDeadlineImpl(fd, t, 'r')
-}
-
-func (fd *netFD) setWriteDeadline(t time.Time) error {
-	return setDeadlineImpl(fd, t, 'w')
-}
-
-func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
-	d := t.Sub(time.Now())
-	if mode == 'r' || mode == 'r'+'w' {
-		fd.rtimedout.setFalse()
-	}
-	if mode == 'w' || mode == 'r'+'w' {
-		fd.wtimedout.setFalse()
-	}
-	if t.IsZero() || d < 0 {
-		// Stop timer
-		if mode == 'r' || mode == 'r'+'w' {
-			if fd.rtimer != nil {
-				fd.rtimer.Stop()
-			}
-			fd.rtimer = nil
-		}
-		if mode == 'w' || mode == 'r'+'w' {
-			if fd.wtimer != nil {
-				fd.wtimer.Stop()
-			}
-			fd.wtimer = nil
-		}
-	} else {
-		// Interrupt I/O operation once timer has expired
-		if mode == 'r' || mode == 'r'+'w' {
-			fd.rtimer = time.AfterFunc(d, func() {
-				fd.rtimedout.setTrue()
-				if fd.raio != nil {
-					fd.raio.Cancel()
-				}
-			})
-		}
-		if mode == 'w' || mode == 'r'+'w' {
-			fd.wtimer = time.AfterFunc(d, func() {
-				fd.wtimedout.setTrue()
-				if fd.waio != nil {
-					fd.waio.Cancel()
-				}
-			})
-		}
-	}
-	if !t.IsZero() && d < 0 {
-		// Interrupt current I/O operation
-		if mode == 'r' || mode == 'r'+'w' {
-			fd.rtimedout.setTrue()
-			if fd.raio != nil {
-				fd.raio.Cancel()
-			}
-		}
-		if mode == 'w' || mode == 'r'+'w' {
-			fd.wtimedout.setTrue()
-			if fd.waio != nil {
-				fd.waio.Cancel()
-			}
-		}
-	}
-	return nil
-}
-
 func setReadBuffer(fd *netFD, bytes int) error {
 	return syscall.EPLAN9
 }
@@ -294,11 +178,3 @@
 func setWriteBuffer(fd *netFD, bytes int) error {
 	return syscall.EPLAN9
 }
-
-func isHangup(err error) bool {
-	return err != nil && stringsHasSuffix(err.Error(), "Hangup")
-}
-
-func isInterrupted(err error) bool {
-	return err != nil && stringsHasSuffix(err.Error(), "interrupted")
-}
diff --git a/src/net/fd_posix.go b/src/net/fd_posix.go
deleted file mode 100644
index b4b908a..0000000
--- a/src/net/fd_posix.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2009 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.
-
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
-
-package net
-
-import (
-	"io"
-	"syscall"
-)
-
-// eofError returns io.EOF when fd is available for reading end of
-// file.
-func (fd *netFD) eofError(n int, err error) error {
-	if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW {
-		return io.EOF
-	}
-	return err
-}
diff --git a/src/net/fd_posix_test.go b/src/net/fd_posix_test.go
deleted file mode 100644
index 85711ef..0000000
--- a/src/net/fd_posix_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2012 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.
-
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
-
-package net
-
-import (
-	"io"
-	"syscall"
-	"testing"
-)
-
-var eofErrorTests = []struct {
-	n        int
-	err      error
-	fd       *netFD
-	expected error
-}{
-	{100, nil, &netFD{sotype: syscall.SOCK_STREAM}, nil},
-	{100, io.EOF, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
-	{100, errClosing, &netFD{sotype: syscall.SOCK_STREAM}, errClosing},
-	{0, nil, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
-	{0, io.EOF, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
-	{0, errClosing, &netFD{sotype: syscall.SOCK_STREAM}, errClosing},
-
-	{100, nil, &netFD{sotype: syscall.SOCK_DGRAM}, nil},
-	{100, io.EOF, &netFD{sotype: syscall.SOCK_DGRAM}, io.EOF},
-	{100, errClosing, &netFD{sotype: syscall.SOCK_DGRAM}, errClosing},
-	{0, nil, &netFD{sotype: syscall.SOCK_DGRAM}, nil},
-	{0, io.EOF, &netFD{sotype: syscall.SOCK_DGRAM}, io.EOF},
-	{0, errClosing, &netFD{sotype: syscall.SOCK_DGRAM}, errClosing},
-
-	{100, nil, &netFD{sotype: syscall.SOCK_SEQPACKET}, nil},
-	{100, io.EOF, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
-	{100, errClosing, &netFD{sotype: syscall.SOCK_SEQPACKET}, errClosing},
-	{0, nil, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
-	{0, io.EOF, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
-	{0, errClosing, &netFD{sotype: syscall.SOCK_SEQPACKET}, errClosing},
-
-	{100, nil, &netFD{sotype: syscall.SOCK_RAW}, nil},
-	{100, io.EOF, &netFD{sotype: syscall.SOCK_RAW}, io.EOF},
-	{100, errClosing, &netFD{sotype: syscall.SOCK_RAW}, errClosing},
-	{0, nil, &netFD{sotype: syscall.SOCK_RAW}, nil},
-	{0, io.EOF, &netFD{sotype: syscall.SOCK_RAW}, io.EOF},
-	{0, errClosing, &netFD{sotype: syscall.SOCK_RAW}, errClosing},
-}
-
-func TestEOFError(t *testing.T) {
-	for _, tt := range eofErrorTests {
-		actual := tt.fd.eofError(tt.n, tt.err)
-		if actual != tt.expected {
-			t.Errorf("eofError(%v, %v, %v): expected %v, actual %v", tt.n, tt.err, tt.fd.sotype, tt.expected, actual)
-		}
-	}
-}
diff --git a/src/net/fd_unix.go b/src/net/fd_unix.go
index 3c95fc0..9f36069 100644
--- a/src/net/fd_unix.go
+++ b/src/net/fd_unix.go
@@ -8,7 +8,7 @@
 
 import (
 	"context"
-	"io"
+	"internal/poll"
 	"os"
 	"runtime"
 	"sync/atomic"
@@ -17,38 +17,36 @@
 
 // Network file descriptor.
 type netFD struct {
-	// locking/lifetime of sysfd + serialize access to Read and Write methods
-	fdmu fdMutex
+	pfd poll.FD
 
 	// immutable until Close
-	sysfd       int
 	family      int
 	sotype      int
-	isStream    bool
 	isConnected bool
 	net         string
 	laddr       Addr
 	raddr       Addr
-
-	// writev cache.
-	iovecs *[]syscall.Iovec
-
-	// wait server
-	pd pollDesc
 }
 
 func sysInit() {
 }
 
 func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
-	return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net, isStream: sotype == syscall.SOCK_STREAM}, nil
+	ret := &netFD{
+		pfd: poll.FD{
+			Sysfd:         sysfd,
+			IsStream:      sotype == syscall.SOCK_STREAM,
+			ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
+		},
+		family: family,
+		sotype: sotype,
+		net:    net,
+	}
+	return ret, nil
 }
 
 func (fd *netFD) init() error {
-	if err := fd.pd.init(fd); err != nil {
-		return err
-	}
-	return nil
+	return fd.pfd.Init()
 }
 
 func (fd *netFD) setAddr(laddr, raddr Addr) {
@@ -72,7 +70,7 @@
 	// Do not need to call fd.writeLock here,
 	// because fd is not yet accessible to user,
 	// so no concurrent operations are possible.
-	switch err := connectFunc(fd.sysfd, ra); err {
+	switch err := connectFunc(fd.pfd.Sysfd, ra); err {
 	case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
 	case nil, syscall.EISCONN:
 		select {
@@ -80,9 +78,10 @@
 			return mapErr(ctx.Err())
 		default:
 		}
-		if err := fd.init(); err != nil {
+		if err := fd.pfd.Init(); err != nil {
 			return err
 		}
+		runtime.KeepAlive(fd)
 		return nil
 	case syscall.EINVAL:
 		// On Solaris we can see EINVAL if the socket has
@@ -97,12 +96,12 @@
 	default:
 		return os.NewSyscallError("connect", err)
 	}
-	if err := fd.init(); err != nil {
+	if err := fd.pfd.Init(); err != nil {
 		return err
 	}
 	if deadline, _ := ctx.Deadline(); !deadline.IsZero() {
-		fd.setWriteDeadline(deadline)
-		defer fd.setWriteDeadline(noDeadline)
+		fd.pfd.SetWriteDeadline(deadline)
+		defer fd.pfd.SetWriteDeadline(noDeadline)
 	}
 
 	// Start the "interrupter" goroutine, if this context might be canceled.
@@ -119,7 +118,7 @@
 		defer func() {
 			close(done)
 			if ctxErr := <-interruptRes; ctxErr != nil && ret == nil {
-				// The interrupter goroutine called setWriteDeadline,
+				// The interrupter goroutine called SetWriteDeadline,
 				// but the connect code below had returned from
 				// waitWrite already and did a successful connect (ret
 				// == nil). Because we've now poisoned the connection
@@ -135,7 +134,7 @@
 				// Force the runtime's poller to immediately give up
 				// waiting for writability, unblocking waitWrite
 				// below.
-				fd.setWriteDeadline(aLongTimeAgo)
+				fd.pfd.SetWriteDeadline(aLongTimeAgo)
 				testHookCanceledDial()
 				interruptRes <- ctx.Err()
 			case <-done:
@@ -153,7 +152,7 @@
 		// SO_ERROR socket option to see if the connection
 		// succeeded or failed. See issue 7474 for further
 		// details.
-		if err := fd.pd.waitWrite(); err != nil {
+		if err := fd.pfd.WaitWrite(); err != nil {
 			select {
 			case <-ctx.Done():
 				return mapErr(ctx.Err())
@@ -161,7 +160,7 @@
 			}
 			return err
 		}
-		nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
+		nerr, err := getsockoptIntFunc(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
 		if err != nil {
 			return os.NewSyscallError("getsockopt", err)
 		}
@@ -174,45 +173,26 @@
 			// See golang.org/issue/14548.
 			// On Darwin, multiple connect system calls on
 			// a non-blocking socket never harm SO_ERROR.
-			switch err := connectFunc(fd.sysfd, ra); err {
+			switch err := connectFunc(fd.pfd.Sysfd, ra); err {
 			case nil, syscall.EISCONN:
 				return nil
 			}
 		default:
 			return os.NewSyscallError("getsockopt", err)
 		}
+		runtime.KeepAlive(fd)
 	}
 }
 
-func (fd *netFD) destroy() {
-	// Poller may want to unregister fd in readiness notification mechanism,
-	// so this must be executed before closeFunc.
-	fd.pd.close()
-	closeFunc(fd.sysfd)
-	fd.sysfd = -1
-	runtime.SetFinalizer(fd, nil)
-}
-
 func (fd *netFD) Close() error {
-	if !fd.fdmu.increfAndClose() {
-		return errClosing
-	}
-	// Unblock any I/O.  Once it all unblocks and returns,
-	// so that it cannot be referring to fd.sysfd anymore,
-	// the final decref will close fd.sysfd. This should happen
-	// fairly quickly, since all the I/O is non-blocking, and any
-	// attempts to block in the pollDesc will return errClosing.
-	fd.pd.evict()
-	fd.decref()
-	return nil
+	runtime.SetFinalizer(fd, nil)
+	return fd.pfd.Close()
 }
 
 func (fd *netFD) shutdown(how int) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("shutdown", syscall.Shutdown(fd.sysfd, how))
+	err := fd.pfd.Shutdown(how)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("shutdown", err)
 }
 
 func (fd *netFD) closeRead() error {
@@ -224,233 +204,59 @@
 }
 
 func (fd *netFD) Read(p []byte) (n int, err error) {
-	if err := fd.readLock(); err != nil {
-		return 0, err
-	}
-	defer fd.readUnlock()
-	if len(p) == 0 {
-		// If the caller wanted a zero byte read, return immediately
-		// without trying. (But after acquiring the readLock.) Otherwise
-		// syscall.Read returns 0, nil and eofError turns that into
-		// io.EOF.
-		// TODO(bradfitz): make it wait for readability? (Issue 15735)
-		return 0, nil
-	}
-	if err := fd.pd.prepareRead(); err != nil {
-		return 0, err
-	}
-	if fd.isStream && len(p) > 1<<30 {
-		p = p[:1<<30]
-	}
-	for {
-		n, err = syscall.Read(fd.sysfd, p)
-		if err != nil {
-			n = 0
-			if err == syscall.EAGAIN {
-				if err = fd.pd.waitRead(); err == nil {
-					continue
-				}
-			}
-		}
-		err = fd.eofError(n, err)
-		break
-	}
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("read", err)
-	}
-	return
+	n, err = fd.pfd.Read(p)
+	runtime.KeepAlive(fd)
+	return n, wrapSyscallError("read", err)
 }
 
 func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
-	if err := fd.readLock(); err != nil {
-		return 0, nil, err
-	}
-	defer fd.readUnlock()
-	if err := fd.pd.prepareRead(); err != nil {
-		return 0, nil, err
-	}
-	for {
-		n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
-		if err != nil {
-			n = 0
-			if err == syscall.EAGAIN {
-				if err = fd.pd.waitRead(); err == nil {
-					continue
-				}
-			}
-		}
-		err = fd.eofError(n, err)
-		break
-	}
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("recvfrom", err)
-	}
-	return
+	n, sa, err = fd.pfd.RecvFrom(p)
+	runtime.KeepAlive(fd)
+	return n, sa, wrapSyscallError("recvfrom", err)
 }
 
 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
-	if err := fd.readLock(); err != nil {
-		return 0, 0, 0, nil, err
-	}
-	defer fd.readUnlock()
-	if err := fd.pd.prepareRead(); err != nil {
-		return 0, 0, 0, nil, err
-	}
-	for {
-		n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
-		if err != nil {
-			// TODO(dfc) should n and oobn be set to 0
-			if err == syscall.EAGAIN {
-				if err = fd.pd.waitRead(); err == nil {
-					continue
-				}
-			}
-		}
-		err = fd.eofError(n, err)
-		break
-	}
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("recvmsg", err)
-	}
-	return
+	n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob)
+	runtime.KeepAlive(fd)
+	return n, oobn, flags, sa, wrapSyscallError("recvmsg", err)
 }
 
 func (fd *netFD) Write(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
-	}
-	for {
-		var n int
-		max := len(p)
-		if fd.isStream && max-nn > 1<<30 {
-			max = nn + 1<<30
-		}
-		n, err = syscall.Write(fd.sysfd, p[nn:max])
-		if n > 0 {
-			nn += n
-		}
-		if nn == len(p) {
-			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
+	nn, err = fd.pfd.Write(p)
+	runtime.KeepAlive(fd)
+	return nn, wrapSyscallError("write", err)
 }
 
 func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n 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
-	}
-	for {
-		err = syscall.Sendto(fd.sysfd, p, 0, sa)
-		if err == syscall.EAGAIN {
-			if err = fd.pd.waitWrite(); err == nil {
-				continue
-			}
-		}
-		break
-	}
-	if err == nil {
-		n = len(p)
-	}
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("sendto", err)
-	}
-	return
+	n, err = fd.pfd.WriteTo(p, sa)
+	runtime.KeepAlive(fd)
+	return n, wrapSyscallError("sendto", err)
 }
 
 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
-	if err := fd.writeLock(); err != nil {
-		return 0, 0, err
-	}
-	defer fd.writeUnlock()
-	if err := fd.pd.prepareWrite(); err != nil {
-		return 0, 0, err
-	}
-	for {
-		n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0)
-		if err == syscall.EAGAIN {
-			if err = fd.pd.waitWrite(); err == nil {
-				continue
-			}
-		}
-		break
-	}
-	if err == nil {
-		oobn = len(oob)
-	}
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("sendmsg", err)
-	}
-	return
+	n, oobn, err = fd.pfd.WriteMsg(p, oob, sa)
+	runtime.KeepAlive(fd)
+	return n, oobn, wrapSyscallError("sendmsg", err)
 }
 
 func (fd *netFD) accept() (netfd *netFD, err error) {
-	if err := fd.readLock(); err != nil {
-		return nil, err
-	}
-	defer fd.readUnlock()
-
-	var s int
-	var rsa syscall.Sockaddr
-	if err = fd.pd.prepareRead(); err != nil {
-		return nil, err
-	}
-	for {
-		s, rsa, err = accept(fd.sysfd)
-		if err != nil {
-			nerr, ok := err.(*os.SyscallError)
-			if !ok {
-				return nil, err
-			}
-			switch nerr.Err {
-			case syscall.EAGAIN:
-				if err = fd.pd.waitRead(); err == nil {
-					continue
-				}
-			case syscall.ECONNABORTED:
-				// This means that a socket on the
-				// listen queue was closed before we
-				// Accept()ed it; it's a silly error,
-				// so try again.
-				continue
-			}
-			return nil, err
+	d, rsa, errcall, err := fd.pfd.Accept()
+	if err != nil {
+		if errcall != "" {
+			err = wrapSyscallError(errcall, err)
 		}
-		break
+		return nil, err
 	}
 
-	if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
-		closeFunc(s)
+	if netfd, err = newFD(d, fd.family, fd.sotype, fd.net); err != nil {
+		poll.CloseFunc(d)
 		return nil, err
 	}
 	if err = netfd.init(); err != nil {
 		fd.Close()
 		return nil, err
 	}
-	lsa, _ := syscall.Getsockname(netfd.sysfd)
+	lsa, _ := syscall.Getsockname(netfd.pfd.Sysfd)
 	netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
 	return netfd, nil
 }
@@ -503,7 +309,7 @@
 }
 
 func (fd *netFD) dup() (f *os.File, err error) {
-	ns, err := dupCloseOnExec(fd.sysfd)
+	ns, err := dupCloseOnExec(fd.pfd.Sysfd)
 	if err != nil {
 		return nil, err
 	}
diff --git a/src/net/fd_windows.go b/src/net/fd_windows.go
index a976f2a..2182b73 100644
--- a/src/net/fd_windows.go
+++ b/src/net/fd_windows.go
@@ -6,62 +6,14 @@
 
 import (
 	"context"
-	"internal/race"
+	"internal/poll"
 	"os"
 	"runtime"
-	"sync"
 	"syscall"
 	"unsafe"
 )
 
-var (
-	initErr error
-	ioSync  uint64
-)
-
-// CancelIo Windows API cancels all outstanding IO for a particular
-// socket on current thread. To overcome that limitation, we run
-// special goroutine, locked to OS single thread, that both starts
-// and cancels IO. It means, there are 2 unavoidable thread switches
-// for every IO.
-// Some newer versions of Windows has new CancelIoEx API, that does
-// not have that limitation and can be used from any thread. This
-// package uses CancelIoEx API, if present, otherwise it fallback
-// to CancelIo.
-
-var (
-	canCancelIO                               bool // determines if CancelIoEx API is present
-	skipSyncNotif                             bool
-	hasLoadSetFileCompletionNotificationModes bool
-)
-
 func sysInit() {
-	var d syscall.WSAData
-	e := syscall.WSAStartup(uint32(0x202), &d)
-	if e != nil {
-		initErr = os.NewSyscallError("wsastartup", e)
-	}
-	canCancelIO = syscall.LoadCancelIoEx() == nil
-	hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil
-	if hasLoadSetFileCompletionNotificationModes {
-		// It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed:
-		// http://support.microsoft.com/kb/2568167
-		skipSyncNotif = true
-		protos := [2]int32{syscall.IPPROTO_TCP, 0}
-		var buf [32]syscall.WSAProtocolInfo
-		len := uint32(unsafe.Sizeof(buf))
-		n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
-		if err != nil {
-			skipSyncNotif = false
-		} else {
-			for i := int32(0); i < n; i++ {
-				if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
-					skipSyncNotif = false
-					break
-				}
-			}
-		}
-	}
 }
 
 // canUseConnectEx reports whether we can use the ConnectEx Windows API call
@@ -75,257 +27,39 @@
 	return false
 }
 
-// operation contains superset of data necessary to perform all async IO.
-type operation struct {
-	// Used by IOCP interface, it must be first field
-	// of the struct, as our code rely on it.
-	o syscall.Overlapped
-
-	// fields used by runtime.netpoll
-	runtimeCtx uintptr
-	mode       int32
-	errno      int32
-	qty        uint32
-
-	// fields used only by net package
-	fd     *netFD
-	errc   chan error
-	buf    syscall.WSABuf
-	sa     syscall.Sockaddr
-	rsa    *syscall.RawSockaddrAny
-	rsan   int32
-	handle syscall.Handle
-	flags  uint32
-	bufs   []syscall.WSABuf
-}
-
-func (o *operation) InitBuf(buf []byte) {
-	o.buf.Len = uint32(len(buf))
-	o.buf.Buf = nil
-	if len(buf) != 0 {
-		o.buf.Buf = &buf[0]
-	}
-}
-
-func (o *operation) InitBufs(buf *Buffers) {
-	if o.bufs == nil {
-		o.bufs = make([]syscall.WSABuf, 0, len(*buf))
-	} else {
-		o.bufs = o.bufs[:0]
-	}
-	for _, b := range *buf {
-		var p *byte
-		if len(b) > 0 {
-			p = &b[0]
-		}
-		o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: p})
-	}
-}
-
-// ClearBufs clears all pointers to Buffers parameter captured
-// by InitBufs, so it can be released by garbage collector.
-func (o *operation) ClearBufs() {
-	for i := range o.bufs {
-		o.bufs[i].Buf = nil
-	}
-	o.bufs = o.bufs[:0]
-}
-
-// ioSrv executes net IO requests.
-type ioSrv struct {
-	req chan ioSrvReq
-}
-
-type ioSrvReq struct {
-	o      *operation
-	submit func(o *operation) error // if nil, cancel the operation
-}
-
-// ProcessRemoteIO will execute submit IO requests on behalf
-// of other goroutines, all on a single os thread, so it can
-// cancel them later. Results of all operations will be sent
-// back to their requesters via channel supplied in request.
-// It is used only when the CancelIoEx API is unavailable.
-func (s *ioSrv) ProcessRemoteIO() {
-	runtime.LockOSThread()
-	defer runtime.UnlockOSThread()
-	for r := range s.req {
-		if r.submit != nil {
-			r.o.errc <- r.submit(r.o)
-		} else {
-			r.o.errc <- syscall.CancelIo(r.o.fd.sysfd)
-		}
-	}
-}
-
-// ExecIO executes a single IO operation o. It submits and cancels
-// IO in the current thread for systems where Windows CancelIoEx API
-// is available. Alternatively, it passes the request onto
-// runtime netpoll and waits for completion or cancels request.
-func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) {
-	fd := o.fd
-	// Notify runtime netpoll about starting IO.
-	err := fd.pd.prepare(int(o.mode))
-	if err != nil {
-		return 0, err
-	}
-	// Start IO.
-	if canCancelIO {
-		err = submit(o)
-	} else {
-		// Send request to a special dedicated thread,
-		// so it can stop the IO with CancelIO later.
-		s.req <- ioSrvReq{o, submit}
-		err = <-o.errc
-	}
-	switch err {
-	case nil:
-		// IO completed immediately
-		if o.fd.skipSyncNotif {
-			// No completion message will follow, so return immediately.
-			return int(o.qty), nil
-		}
-		// Need to get our completion message anyway.
-	case syscall.ERROR_IO_PENDING:
-		// IO started, and we have to wait for its completion.
-		err = nil
-	default:
-		return 0, err
-	}
-	// Wait for our request to complete.
-	err = fd.pd.wait(int(o.mode))
-	if err == nil {
-		// All is good. Extract our IO results and return.
-		if o.errno != 0 {
-			err = syscall.Errno(o.errno)
-			return 0, err
-		}
-		return int(o.qty), nil
-	}
-	// IO is interrupted by "close" or "timeout"
-	netpollErr := err
-	switch netpollErr {
-	case errClosing, errTimeout:
-		// will deal with those.
-	default:
-		panic("net: unexpected runtime.netpoll error: " + netpollErr.Error())
-	}
-	// Cancel our request.
-	if canCancelIO {
-		err := syscall.CancelIoEx(fd.sysfd, &o.o)
-		// Assuming ERROR_NOT_FOUND is returned, if IO is completed.
-		if err != nil && err != syscall.ERROR_NOT_FOUND {
-			// TODO(brainman): maybe do something else, but panic.
-			panic(err)
-		}
-	} else {
-		s.req <- ioSrvReq{o, nil}
-		<-o.errc
-	}
-	// Wait for cancelation to complete.
-	fd.pd.waitCanceled(int(o.mode))
-	if o.errno != 0 {
-		err = syscall.Errno(o.errno)
-		if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
-			err = netpollErr
-		}
-		return 0, err
-	}
-	// We issued a cancelation request. But, it seems, IO operation succeeded
-	// before the cancelation request run. We need to treat the IO operation as
-	// succeeded (the bytes are actually sent/recv from network).
-	return int(o.qty), nil
-}
-
-// Start helper goroutines.
-var rsrv, wsrv *ioSrv
-var onceStartServer sync.Once
-
-func startServer() {
-	rsrv = new(ioSrv)
-	wsrv = new(ioSrv)
-	if !canCancelIO {
-		// Only CancelIo API is available. Lets start two special goroutines
-		// locked to an OS thread, that both starts and cancels IO. One will
-		// process read requests, while other will do writes.
-		rsrv.req = make(chan ioSrvReq)
-		go rsrv.ProcessRemoteIO()
-		wsrv.req = make(chan ioSrvReq)
-		go wsrv.ProcessRemoteIO()
-	}
-}
-
 // Network file descriptor.
 type netFD struct {
-	// locking/lifetime of sysfd + serialize access to Read and Write methods
-	fdmu fdMutex
+	pfd poll.FD
 
 	// immutable until Close
-	sysfd         syscall.Handle
-	family        int
-	sotype        int
-	isStream      bool
-	isConnected   bool
-	skipSyncNotif bool
-	net           string
-	laddr         Addr
-	raddr         Addr
-
-	rop operation // read operation
-	wop operation // write operation
-
-	// wait server
-	pd pollDesc
+	family      int
+	sotype      int
+	isConnected bool
+	net         string
+	laddr       Addr
+	raddr       Addr
 }
 
 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
-	if initErr != nil {
-		return nil, initErr
+	ret := &netFD{
+		pfd: poll.FD{
+			Sysfd:         sysfd,
+			IsStream:      sotype == syscall.SOCK_STREAM,
+			ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
+		},
+		family: family,
+		sotype: sotype,
+		net:    net,
 	}
-	onceStartServer.Do(startServer)
-	return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net, isStream: sotype == syscall.SOCK_STREAM}, nil
+	return ret, nil
 }
 
 func (fd *netFD) init() error {
-	if err := fd.pd.init(fd); err != nil {
-		return err
+	errcall, err := fd.pfd.Init(fd.net)
+	if errcall != "" {
+		err = wrapSyscallError(errcall, err)
 	}
-	if hasLoadSetFileCompletionNotificationModes {
-		// We do not use events, so we can skip them always.
-		flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
-		// It's not safe to skip completion notifications for UDP:
-		// http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
-		if skipSyncNotif && fd.net == "tcp" {
-			flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
-		}
-		err := syscall.SetFileCompletionNotificationModes(fd.sysfd, flags)
-		if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
-			fd.skipSyncNotif = true
-		}
-	}
-	// Disable SIO_UDP_CONNRESET behavior.
-	// http://support.microsoft.com/kb/263823
-	switch fd.net {
-	case "udp", "udp4", "udp6":
-		ret := uint32(0)
-		flag := uint32(0)
-		size := uint32(unsafe.Sizeof(flag))
-		err := syscall.WSAIoctl(fd.sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
-		if err != nil {
-			return os.NewSyscallError("wsaioctl", err)
-		}
-	}
-	fd.rop.mode = 'r'
-	fd.wop.mode = 'w'
-	fd.rop.fd = fd
-	fd.wop.fd = fd
-	fd.rop.runtimeCtx = fd.pd.runtimeCtx
-	fd.wop.runtimeCtx = fd.pd.runtimeCtx
-	if !canCancelIO {
-		fd.rop.errc = make(chan error)
-		fd.wop.errc = make(chan error)
-	}
-	return nil
+	return err
 }
 
 func (fd *netFD) setAddr(laddr, raddr Addr) {
@@ -342,11 +76,11 @@
 		return err
 	}
 	if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
-		fd.setWriteDeadline(deadline)
-		defer fd.setWriteDeadline(noDeadline)
+		fd.pfd.SetWriteDeadline(deadline)
+		defer fd.pfd.SetWriteDeadline(noDeadline)
 	}
 	if !canUseConnectEx(fd.net) {
-		err := connectFunc(fd.sysfd, ra)
+		err := connectFunc(fd.pfd.Sysfd, ra)
 		return os.NewSyscallError("connect", err)
 	}
 	// ConnectEx windows API requires an unconnected, previously bound socket.
@@ -359,13 +93,10 @@
 		default:
 			panic("unexpected type in connect")
 		}
-		if err := syscall.Bind(fd.sysfd, la); err != nil {
+		if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
 			return os.NewSyscallError("bind", err)
 		}
 	}
-	// Call ConnectEx API.
-	o := &fd.wop
-	o.sa = ra
 
 	// Wait for the goroutine converting context.Done into a write timeout
 	// to exist, otherwise our caller might cancel the context and
@@ -377,16 +108,14 @@
 		case <-ctx.Done():
 			// Force the runtime's poller to immediately give
 			// up waiting for writability.
-			fd.setWriteDeadline(aLongTimeAgo)
+			fd.pfd.SetWriteDeadline(aLongTimeAgo)
 			<-done
 		case <-done:
 		}
 	}()
 
-	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
-		return connectExFunc(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
-	})
-	if err != nil {
+	// Call ConnectEx API.
+	if err := fd.pfd.ConnectEx(ra); err != nil {
 		select {
 		case <-ctx.Done():
 			return mapErr(ctx.Err())
@@ -398,38 +127,18 @@
 		}
 	}
 	// Refresh socket properties.
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))))
-}
-
-func (fd *netFD) destroy() {
-	if fd.sysfd == syscall.InvalidHandle {
-		return
-	}
-	// Poller may want to unregister fd in readiness notification mechanism,
-	// so this must be executed before closeFunc.
-	fd.pd.close()
-	closeFunc(fd.sysfd)
-	fd.sysfd = syscall.InvalidHandle
-	// no need for a finalizer anymore
-	runtime.SetFinalizer(fd, nil)
+	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.pfd.Sysfd)), int32(unsafe.Sizeof(fd.pfd.Sysfd))))
 }
 
 func (fd *netFD) Close() error {
-	if !fd.fdmu.increfAndClose() {
-		return errClosing
-	}
-	// unblock pending reader and writer
-	fd.pd.evict()
-	fd.decref()
-	return nil
+	runtime.SetFinalizer(fd, nil)
+	return fd.pfd.Close()
 }
 
 func (fd *netFD) shutdown(how int) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return syscall.Shutdown(fd.sysfd, how)
+	err := fd.pfd.Shutdown(how)
+	runtime.KeepAlive(fd)
+	return err
 }
 
 func (fd *netFD) closeRead() error {
@@ -441,72 +150,21 @@
 }
 
 func (fd *netFD) Read(buf []byte) (int, error) {
-	if err := fd.readLock(); err != nil {
-		return 0, err
-	}
-	defer fd.readUnlock()
-	o := &fd.rop
-	o.InitBuf(buf)
-	n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error {
-		return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
-	})
-	if race.Enabled {
-		race.Acquire(unsafe.Pointer(&ioSync))
-	}
-	if len(buf) != 0 {
-		err = fd.eofError(n, err)
-	}
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("wsarecv", err)
-	}
-	return n, err
+	n, err := fd.pfd.Read(buf)
+	runtime.KeepAlive(fd)
+	return n, wrapSyscallError("wsarecv", err)
 }
 
 func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
-	if len(buf) == 0 {
-		return 0, nil, nil
-	}
-	if err := fd.readLock(); err != nil {
-		return 0, nil, err
-	}
-	defer fd.readUnlock()
-	o := &fd.rop
-	o.InitBuf(buf)
-	n, err := rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error {
-		if o.rsa == nil {
-			o.rsa = new(syscall.RawSockaddrAny)
-		}
-		o.rsan = int32(unsafe.Sizeof(*o.rsa))
-		return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
-	})
-	err = fd.eofError(n, err)
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("wsarecvfrom", err)
-	}
-	if err != nil {
-		return n, nil, err
-	}
-	sa, _ := o.rsa.Sockaddr()
-	return n, sa, nil
+	n, sa, err := fd.pfd.RecvFrom(buf)
+	runtime.KeepAlive(fd)
+	return n, sa, wrapSyscallError("wsarecvfrom", err)
 }
 
 func (fd *netFD) Write(buf []byte) (int, error) {
-	if err := fd.writeLock(); err != nil {
-		return 0, err
-	}
-	defer fd.writeUnlock()
-	if race.Enabled {
-		race.ReleaseMerge(unsafe.Pointer(&ioSync))
-	}
-	o := &fd.wop
-	o.InitBuf(buf)
-	n, err := wsrv.ExecIO(o, "WSASend", func(o *operation) error {
-		return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
-	})
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("wsasend", err)
-	}
-	return n, err
+	n, err := fd.pfd.Write(buf)
+	runtime.KeepAlive(fd)
+	return n, wrapSyscallError("wsasend", err)
 }
 
 func (c *conn) writeBuffers(v *Buffers) (int64, error) {
@@ -521,61 +179,33 @@
 }
 
 func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
-	if len(*buf) == 0 {
-		return 0, nil
-	}
-	if err := fd.writeLock(); err != nil {
-		return 0, err
-	}
-	defer fd.writeUnlock()
-	if race.Enabled {
-		race.ReleaseMerge(unsafe.Pointer(&ioSync))
-	}
-	o := &fd.wop
-	o.InitBufs(buf)
-	n, err := wsrv.ExecIO(o, "WSASend", func(o *operation) error {
-		return syscall.WSASend(o.fd.sysfd, &o.bufs[0], uint32(len(*buf)), &o.qty, 0, &o.o, nil)
-	})
-	o.ClearBufs()
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("wsasend", err)
-	}
-	testHookDidWritev(n)
-	buf.consume(int64(n))
-	return int64(n), err
+	n, err := fd.pfd.Writev((*[][]byte)(buf))
+	runtime.KeepAlive(fd)
+	return n, wrapSyscallError("wsasend", err)
 }
 
 func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
-	if len(buf) == 0 {
-		return 0, nil
-	}
-	if err := fd.writeLock(); err != nil {
-		return 0, err
-	}
-	defer fd.writeUnlock()
-	o := &fd.wop
-	o.InitBuf(buf)
-	o.sa = sa
-	n, err := wsrv.ExecIO(o, "WSASendto", func(o *operation) error {
-		return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
-	})
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("wsasendto", err)
-	}
-	return n, err
+	n, err := fd.pfd.WriteTo(buf, sa)
+	runtime.KeepAlive(fd)
+	return n, wrapSyscallError("wsasendto", err)
 }
 
-func (fd *netFD) acceptOne(rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
-	// Get new socket.
-	s, err := sysSocket(fd.family, fd.sotype, 0)
+func (fd *netFD) accept() (*netFD, error) {
+	s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
+		return sysSocket(fd.family, fd.sotype, 0)
+	})
+
 	if err != nil {
+		if errcall != "" {
+			err = wrapSyscallError(errcall, err)
+		}
 		return nil, err
 	}
 
 	// Associate our new socket with IOCP.
 	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
 	if err != nil {
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return nil, err
 	}
 	if err := netfd.init(); err != nil {
@@ -583,71 +213,11 @@
 		return nil, err
 	}
 
-	// Submit accept request.
-	o.handle = s
-	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
-	_, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
-		return acceptFunc(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
-	})
-	if err != nil {
-		netfd.Close()
-		if _, ok := err.(syscall.Errno); ok {
-			err = os.NewSyscallError("acceptex", err)
-		}
-		return nil, err
-	}
-
-	// Inherit properties of the listening socket.
-	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
-	if err != nil {
-		netfd.Close()
-		return nil, os.NewSyscallError("setsockopt", err)
-	}
-	runtime.KeepAlive(fd)
-	return netfd, nil
-}
-
-func (fd *netFD) accept() (*netFD, error) {
-	if err := fd.readLock(); err != nil {
-		return nil, err
-	}
-	defer fd.readUnlock()
-
-	o := &fd.rop
-	var netfd *netFD
-	var err error
-	var rawsa [2]syscall.RawSockaddrAny
-	for {
-		netfd, err = fd.acceptOne(rawsa[:], o)
-		if err == nil {
-			break
-		}
-		// Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
-		// returned here. These happen if connection reset is received
-		// before AcceptEx could complete. These errors relate to new
-		// connection, not to AcceptEx, so ignore broken connection and
-		// try AcceptEx again for more connections.
-		nerr, ok := err.(*os.SyscallError)
-		if !ok {
-			return nil, err
-		}
-		errno, ok := nerr.Err.(syscall.Errno)
-		if !ok {
-			return nil, err
-		}
-		switch errno {
-		case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
-			// ignore these and try again
-		default:
-			return nil, err
-		}
-	}
-
 	// Get local and peer addr out of AcceptEx buffer.
 	var lrsa, rrsa *syscall.RawSockaddrAny
 	var llen, rlen int32
 	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
-		0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen)
+		0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
 	lsa, _ := lrsa.Sockaddr()
 	rsa, _ := rrsa.Sockaddr()
 
diff --git a/src/net/file_unix.go b/src/net/file_unix.go
index 9e581fc..d67dff8 100644
--- a/src/net/file_unix.go
+++ b/src/net/file_unix.go
@@ -7,6 +7,7 @@
 package net
 
 import (
+	"internal/poll"
 	"os"
 	"syscall"
 )
@@ -17,7 +18,7 @@
 		return -1, err
 	}
 	if err := syscall.SetNonblock(s, true); err != nil {
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return -1, os.NewSyscallError("setnonblock", err)
 	}
 	return s, nil
@@ -31,7 +32,7 @@
 	family := syscall.AF_UNSPEC
 	sotype, err := syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE)
 	if err != nil {
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return nil, os.NewSyscallError("getsockopt", err)
 	}
 	lsa, _ := syscall.Getsockname(s)
@@ -44,12 +45,12 @@
 	case *syscall.SockaddrUnix:
 		family = syscall.AF_UNIX
 	default:
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return nil, syscall.EPROTONOSUPPORT
 	}
 	fd, err := newFD(s, family, sotype, "")
 	if err != nil {
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return nil, err
 	}
 	laddr := fd.addrFunc()(lsa)
diff --git a/src/net/hook_cloexec.go b/src/net/hook_cloexec.go
deleted file mode 100644
index 870f0d7..0000000
--- a/src/net/hook_cloexec.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2015 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.
-
-// +build freebsd linux
-
-package net
-
-import "syscall"
-
-var (
-	// Placeholders for socket system calls.
-	accept4Func func(int, int) (int, syscall.Sockaddr, error) = syscall.Accept4
-)
diff --git a/src/net/hook_unix.go b/src/net/hook_unix.go
index cf52567..fee62a9 100644
--- a/src/net/hook_unix.go
+++ b/src/net/hook_unix.go
@@ -13,10 +13,8 @@
 	testHookCanceledDial = func() {} // for golang.org/issue/16523
 
 	// Placeholders for socket system calls.
-	socketFunc        func(int, int, int) (int, error)         = syscall.Socket
-	closeFunc         func(int) error                          = syscall.Close
-	connectFunc       func(int, syscall.Sockaddr) error        = syscall.Connect
-	listenFunc        func(int, int) error                     = syscall.Listen
-	acceptFunc        func(int) (int, syscall.Sockaddr, error) = syscall.Accept
-	getsockoptIntFunc func(int, int, int) (int, error)         = syscall.GetsockoptInt
+	socketFunc        func(int, int, int) (int, error)  = syscall.Socket
+	connectFunc       func(int, syscall.Sockaddr) error = syscall.Connect
+	listenFunc        func(int, int) error              = syscall.Listen
+	getsockoptIntFunc func(int, int, int) (int, error)  = syscall.GetsockoptInt
 )
diff --git a/src/net/hook_windows.go b/src/net/hook_windows.go
index 63ea35a..4e64dce 100644
--- a/src/net/hook_windows.go
+++ b/src/net/hook_windows.go
@@ -13,10 +13,7 @@
 	testHookDialChannel = func() { time.Sleep(time.Millisecond) } // see golang.org/issue/5349
 
 	// Placeholders for socket system calls.
-	socketFunc    func(int, int, int) (syscall.Handle, error)                                                             = syscall.Socket
-	closeFunc     func(syscall.Handle) error                                                                              = syscall.Closesocket
-	connectFunc   func(syscall.Handle, syscall.Sockaddr) error                                                            = syscall.Connect
-	connectExFunc func(syscall.Handle, syscall.Sockaddr, *byte, uint32, *uint32, *syscall.Overlapped) error               = syscall.ConnectEx
-	listenFunc    func(syscall.Handle, int) error                                                                         = syscall.Listen
-	acceptFunc    func(syscall.Handle, syscall.Handle, *byte, uint32, uint32, uint32, *uint32, *syscall.Overlapped) error = syscall.AcceptEx
+	socketFunc  func(int, int, int) (syscall.Handle, error)  = syscall.Socket
+	connectFunc func(syscall.Handle, syscall.Sockaddr) error = syscall.Connect
+	listenFunc  func(syscall.Handle, int) error              = syscall.Listen
 )
diff --git a/src/net/ipsock_plan9.go b/src/net/ipsock_plan9.go
index b7fd344..1cd8fa2 100644
--- a/src/net/ipsock_plan9.go
+++ b/src/net/ipsock_plan9.go
@@ -249,10 +249,10 @@
 
 func (fd *netFD) acceptPlan9() (nfd *netFD, err error) {
 	defer func() { fixErr(err) }()
-	if err := fd.readLock(); err != nil {
+	if err := fd.pfd.ReadLock(); err != nil {
 		return nil, err
 	}
-	defer fd.readUnlock()
+	defer fd.pfd.ReadUnlock()
 	listen, err := os.Open(fd.dir + "/listen")
 	if err != nil {
 		return nil, err
diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go
index ff280c3..5cb85f8 100644
--- a/src/net/ipsock_posix.go
+++ b/src/net/ipsock_posix.go
@@ -8,6 +8,7 @@
 
 import (
 	"context"
+	"internal/poll"
 	"runtime"
 	"syscall"
 )
@@ -18,7 +19,7 @@
 	case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
 		return false
 	case nil:
-		closeFunc(s)
+		poll.CloseFunc(s)
 	}
 	return true
 }
@@ -68,7 +69,7 @@
 		if err != nil {
 			continue
 		}
-		defer closeFunc(s)
+		defer poll.CloseFunc(s)
 		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value)
 		sa, err := probes[i].laddr.sockaddr(syscall.AF_INET6)
 		if err != nil {
diff --git a/src/net/main_cloexec_test.go b/src/net/main_cloexec_test.go
index 7903819..ade71a9 100644
--- a/src/net/main_cloexec_test.go
+++ b/src/net/main_cloexec_test.go
@@ -6,6 +6,8 @@
 
 package net
 
+import "internal/poll"
+
 func init() {
 	extraTestHookInstallers = append(extraTestHookInstallers, installAccept4TestHook)
 	extraTestHookUninstallers = append(extraTestHookUninstallers, uninstallAccept4TestHook)
@@ -13,13 +15,13 @@
 
 var (
 	// Placeholders for saving original socket system calls.
-	origAccept4 = accept4Func
+	origAccept4 = poll.Accept4Func
 )
 
 func installAccept4TestHook() {
-	accept4Func = sw.Accept4
+	poll.Accept4Func = sw.Accept4
 }
 
 func uninstallAccept4TestHook() {
-	accept4Func = origAccept4
+	poll.Accept4Func = origAccept4
 }
diff --git a/src/net/main_unix_test.go b/src/net/main_unix_test.go
index 0cc129f..9cfbc8e 100644
--- a/src/net/main_unix_test.go
+++ b/src/net/main_unix_test.go
@@ -6,13 +6,15 @@
 
 package net
 
+import "internal/poll"
+
 var (
 	// Placeholders for saving original socket system calls.
 	origSocket        = socketFunc
-	origClose         = closeFunc
+	origClose         = poll.CloseFunc
 	origConnect       = connectFunc
 	origListen        = listenFunc
-	origAccept        = acceptFunc
+	origAccept        = poll.AcceptFunc
 	origGetsockoptInt = getsockoptIntFunc
 
 	extraTestHookInstallers   []func()
@@ -21,10 +23,10 @@
 
 func installTestHooks() {
 	socketFunc = sw.Socket
-	closeFunc = sw.Close
+	poll.CloseFunc = sw.Close
 	connectFunc = sw.Connect
 	listenFunc = sw.Listen
-	acceptFunc = sw.Accept
+	poll.AcceptFunc = sw.Accept
 	getsockoptIntFunc = sw.GetsockoptInt
 
 	for _, fn := range extraTestHookInstallers {
@@ -34,10 +36,10 @@
 
 func uninstallTestHooks() {
 	socketFunc = origSocket
-	closeFunc = origClose
+	poll.CloseFunc = origClose
 	connectFunc = origConnect
 	listenFunc = origListen
-	acceptFunc = origAccept
+	poll.AcceptFunc = origAccept
 	getsockoptIntFunc = origGetsockoptInt
 
 	for _, fn := range extraTestHookUninstallers {
@@ -48,6 +50,6 @@
 // forceCloseSockets must be called only from TestMain.
 func forceCloseSockets() {
 	for s := range sw.Sockets() {
-		closeFunc(s)
+		poll.CloseFunc(s)
 	}
 }
diff --git a/src/net/main_windows_test.go b/src/net/main_windows_test.go
index 6ea318c..f38a3a0 100644
--- a/src/net/main_windows_test.go
+++ b/src/net/main_windows_test.go
@@ -4,37 +4,39 @@
 
 package net
 
+import "internal/poll"
+
 var (
 	// Placeholders for saving original socket system calls.
 	origSocket      = socketFunc
-	origClosesocket = closeFunc
+	origClosesocket = poll.CloseFunc
 	origConnect     = connectFunc
-	origConnectEx   = connectExFunc
+	origConnectEx   = poll.ConnectExFunc
 	origListen      = listenFunc
-	origAccept      = acceptFunc
+	origAccept      = poll.AcceptFunc
 )
 
 func installTestHooks() {
 	socketFunc = sw.Socket
-	closeFunc = sw.Closesocket
+	poll.CloseFunc = sw.Closesocket
 	connectFunc = sw.Connect
-	connectExFunc = sw.ConnectEx
+	poll.ConnectExFunc = sw.ConnectEx
 	listenFunc = sw.Listen
-	acceptFunc = sw.AcceptEx
+	poll.AcceptFunc = sw.AcceptEx
 }
 
 func uninstallTestHooks() {
 	socketFunc = origSocket
-	closeFunc = origClosesocket
+	poll.CloseFunc = origClosesocket
 	connectFunc = origConnect
-	connectExFunc = origConnectEx
+	poll.ConnectExFunc = origConnectEx
 	listenFunc = origListen
-	acceptFunc = origAccept
+	poll.AcceptFunc = origAccept
 }
 
 // forceCloseSockets must be called only from TestMain.
 func forceCloseSockets() {
 	for s := range sw.Sockets() {
-		closeFunc(s)
+		poll.CloseFunc(s)
 	}
 }
diff --git a/src/net/net.go b/src/net/net.go
index 81206ea..9c27f1b 100644
--- a/src/net/net.go
+++ b/src/net/net.go
@@ -81,6 +81,7 @@
 import (
 	"context"
 	"errors"
+	"internal/poll"
 	"io"
 	"os"
 	"syscall"
@@ -234,7 +235,7 @@
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	if err := c.fd.setDeadline(t); err != nil {
+	if err := c.fd.pfd.SetDeadline(t); err != nil {
 		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
 	}
 	return nil
@@ -245,7 +246,7 @@
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	if err := c.fd.setReadDeadline(t); err != nil {
+	if err := c.fd.pfd.SetReadDeadline(t); err != nil {
 		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
 	}
 	return nil
@@ -256,7 +257,7 @@
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	if err := c.fd.setWriteDeadline(t); err != nil {
+	if err := c.fd.pfd.SetWriteDeadline(t); err != nil {
 		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
 	}
 	return nil
@@ -391,10 +392,8 @@
 	errMissingAddress = errors.New("missing address")
 
 	// For both read and write operations.
-	errTimeout          error = &timeoutError{}
-	errCanceled               = errors.New("operation was canceled")
-	errClosing                = errors.New("use of closed network connection")
-	ErrWriteToConnected       = errors.New("use of WriteTo with pre-connected connection")
+	errCanceled         = errors.New("operation was canceled")
+	ErrWriteToConnected = errors.New("use of WriteTo with pre-connected connection")
 )
 
 // mapErr maps from the context errors to the historical internal net
@@ -407,7 +406,7 @@
 	case context.Canceled:
 		return errCanceled
 	case context.DeadlineExceeded:
-		return errTimeout
+		return poll.ErrTimeout
 	default:
 		return err
 	}
@@ -502,12 +501,6 @@
 	return ok && t.Temporary()
 }
 
-type timeoutError struct{}
-
-func (e *timeoutError) Error() string   { return "i/o timeout" }
-func (e *timeoutError) Timeout() bool   { return true }
-func (e *timeoutError) Temporary() bool { return true }
-
 // A ParseError is the error type of literal network address parsers.
 type ParseError struct {
 	// Type is the type of string that was expected, such as
@@ -632,8 +625,6 @@
 	writeBuffers(*Buffers) (int64, error)
 }
 
-var testHookDidWritev = func(wrote int) {}
-
 // Buffers contains zero or more runs of bytes to write.
 //
 // On certain machines, for certain types of connections, this is
diff --git a/src/net/sendfile_bsd.go b/src/net/sendfile_bsd.go
index 67e80c9..7a2b48c 100644
--- a/src/net/sendfile_bsd.go
+++ b/src/net/sendfile_bsd.go
@@ -7,15 +7,11 @@
 package net
 
 import (
+	"internal/poll"
 	"io"
 	"os"
-	"syscall"
 )
 
-// maxSendfileSize is the largest chunk size we ask the kernel to copy
-// at a time.
-const maxSendfileSize int = 4 << 20
-
 // sendFile copies the contents of r to c using the sendfile
 // system call to minimize copies.
 //
@@ -62,49 +58,10 @@
 		return 0, err, false
 	}
 
-	if err := c.writeLock(); err != nil {
-		return 0, err, true
-	}
-	defer c.writeUnlock()
+	written, err = poll.SendFile(&c.pfd, int(f.Fd()), pos, remain)
 
-	dst := c.sysfd
-	src := int(f.Fd())
-	for remain > 0 {
-		n := maxSendfileSize
-		if int64(n) > remain {
-			n = int(remain)
-		}
-		pos1 := pos
-		n, err1 := syscall.Sendfile(dst, src, &pos1, n)
-		if n > 0 {
-			pos += int64(n)
-			written += int64(n)
-			remain -= int64(n)
-		}
-		if n == 0 && err1 == nil {
-			break
-		}
-		if err1 == syscall.EAGAIN {
-			if err1 = c.pd.waitWrite(); err1 == nil {
-				continue
-			}
-		}
-		if err1 == syscall.EINTR {
-			continue
-		}
-		if err1 != nil {
-			// This includes syscall.ENOSYS (no kernel
-			// support) and syscall.EINVAL (fd types which
-			// don't implement sendfile)
-			err = err1
-			break
-		}
-	}
 	if lr != nil {
-		lr.N = remain
+		lr.N = remain - written
 	}
-	if err != nil {
-		err = os.NewSyscallError("sendfile", err)
-	}
-	return written, err, written > 0
+	return written, wrapSyscallError("sendfile", err), written > 0
 }
diff --git a/src/net/sendfile_linux.go b/src/net/sendfile_linux.go
index 7e741f9..c537ea6 100644
--- a/src/net/sendfile_linux.go
+++ b/src/net/sendfile_linux.go
@@ -5,15 +5,11 @@
 package net
 
 import (
+	"internal/poll"
 	"io"
 	"os"
-	"syscall"
 )
 
-// maxSendfileSize is the largest chunk size we ask the kernel to copy
-// at a time.
-const maxSendfileSize int = 4 << 20
-
 // sendFile copies the contents of r to c using the sendfile
 // system call to minimize copies.
 //
@@ -36,44 +32,10 @@
 		return 0, nil, false
 	}
 
-	if err := c.writeLock(); err != nil {
-		return 0, err, true
-	}
-	defer c.writeUnlock()
+	written, err = poll.SendFile(&c.pfd, int(f.Fd()), remain)
 
-	dst := c.sysfd
-	src := int(f.Fd())
-	for remain > 0 {
-		n := maxSendfileSize
-		if int64(n) > remain {
-			n = int(remain)
-		}
-		n, err1 := syscall.Sendfile(dst, src, nil, n)
-		if n > 0 {
-			written += int64(n)
-			remain -= int64(n)
-		}
-		if n == 0 && err1 == nil {
-			break
-		}
-		if err1 == syscall.EAGAIN {
-			if err1 = c.pd.waitWrite(); err1 == nil {
-				continue
-			}
-		}
-		if err1 != nil {
-			// This includes syscall.ENOSYS (no kernel
-			// support) and syscall.EINVAL (fd types which
-			// don't implement sendfile)
-			err = err1
-			break
-		}
-	}
 	if lr != nil {
-		lr.N = remain
+		lr.N = remain - written
 	}
-	if err != nil {
-		err = os.NewSyscallError("sendfile", err)
-	}
-	return written, err, written > 0
+	return written, wrapSyscallError("sendfile", err), written > 0
 }
diff --git a/src/net/sendfile_solaris.go b/src/net/sendfile_solaris.go
index add70c3..63ca9d4 100644
--- a/src/net/sendfile_solaris.go
+++ b/src/net/sendfile_solaris.go
@@ -5,19 +5,11 @@
 package net
 
 import (
+	"internal/poll"
 	"io"
 	"os"
-	"syscall"
 )
 
-// Not strictly needed, but very helpful for debugging, see issue #10221.
-//go:cgo_import_dynamic _ _ "libsendfile.so"
-//go:cgo_import_dynamic _ _ "libsocket.so"
-
-// maxSendfileSize is the largest chunk size we ask the kernel to copy
-// at a time.
-const maxSendfileSize int = 4 << 20
-
 // sendFile copies the contents of r to c using the sendfile
 // system call to minimize copies.
 //
@@ -62,56 +54,10 @@
 		return 0, err, false
 	}
 
-	if err := c.writeLock(); err != nil {
-		return 0, err, true
-	}
-	defer c.writeUnlock()
+	written, err = poll.SendFile(&c.pfd, int(f.Fd()), pos, remain)
 
-	dst := c.sysfd
-	src := int(f.Fd())
-	for remain > 0 {
-		n := maxSendfileSize
-		if int64(n) > remain {
-			n = int(remain)
-		}
-		pos1 := pos
-		n, err1 := syscall.Sendfile(dst, src, &pos1, n)
-		if err1 == syscall.EAGAIN || err1 == syscall.EINTR {
-			// partial write may have occurred
-			if n = int(pos1 - pos); n == 0 {
-				// nothing more to write
-				err1 = nil
-			}
-		}
-		if n > 0 {
-			pos += int64(n)
-			written += int64(n)
-			remain -= int64(n)
-		}
-		if n == 0 && err1 == nil {
-			break
-		}
-		if err1 == syscall.EAGAIN {
-			if err1 = c.pd.waitWrite(); err1 == nil {
-				continue
-			}
-		}
-		if err1 == syscall.EINTR {
-			continue
-		}
-		if err1 != nil {
-			// This includes syscall.ENOSYS (no kernel
-			// support) and syscall.EINVAL (fd types which
-			// don't implement sendfile)
-			err = err1
-			break
-		}
-	}
 	if lr != nil {
-		lr.N = remain
+		lr.N = remain - written
 	}
-	if err != nil {
-		err = os.NewSyscallError("sendfile", err)
-	}
-	return written, err, written > 0
+	return written, wrapSyscallError("sendfile", err), written > 0
 }
diff --git a/src/net/sendfile_windows.go b/src/net/sendfile_windows.go
index bc0b7fb..bccd8b1 100644
--- a/src/net/sendfile_windows.go
+++ b/src/net/sendfile_windows.go
@@ -5,6 +5,7 @@
 package net
 
 import (
+	"internal/poll"
 	"io"
 	"os"
 	"syscall"
@@ -34,19 +35,10 @@
 		return 0, nil, false
 	}
 
-	if err := fd.writeLock(); err != nil {
-		return 0, err, true
-	}
-	defer fd.writeUnlock()
+	done, err := poll.SendFile(&fd.pfd, syscall.Handle(f.Fd()), n)
 
-	o := &fd.wop
-	o.qty = uint32(n)
-	o.handle = syscall.Handle(f.Fd())
-	done, err := wsrv.ExecIO(o, "TransmitFile", func(o *operation) error {
-		return syscall.TransmitFile(o.fd.sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
-	})
 	if err != nil {
-		return 0, os.NewSyscallError("transmitfile", err), false
+		return 0, wrapSyscallError("transmitfile", err), false
 	}
 	if lr != nil {
 		lr.N -= int64(done)
diff --git a/src/net/sock_cloexec.go b/src/net/sock_cloexec.go
index 616a101..3f5be2d 100644
--- a/src/net/sock_cloexec.go
+++ b/src/net/sock_cloexec.go
@@ -10,6 +10,7 @@
 package net
 
 import (
+	"internal/poll"
 	"os"
 	"syscall"
 )
@@ -42,46 +43,8 @@
 		return -1, os.NewSyscallError("socket", err)
 	}
 	if err = syscall.SetNonblock(s, true); err != nil {
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return -1, os.NewSyscallError("setnonblock", err)
 	}
 	return s, nil
 }
-
-// Wrapper around the accept system call that marks the returned file
-// descriptor as nonblocking and close-on-exec.
-func accept(s int) (int, syscall.Sockaddr, error) {
-	ns, sa, err := accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
-	// On Linux the accept4 system call was introduced in 2.6.28
-	// kernel and on FreeBSD it was introduced in 10 kernel. If we
-	// get an ENOSYS error on both Linux and FreeBSD, or EINVAL
-	// error on Linux, fall back to using accept.
-	switch err {
-	case nil:
-		return ns, sa, nil
-	default: // errors other than the ones listed
-		return -1, sa, os.NewSyscallError("accept4", err)
-	case syscall.ENOSYS: // syscall missing
-	case syscall.EINVAL: // some Linux use this instead of ENOSYS
-	case syscall.EACCES: // some Linux use this instead of ENOSYS
-	case syscall.EFAULT: // some Linux use this instead of ENOSYS
-	}
-
-	// See ../syscall/exec_unix.go for description of ForkLock.
-	// It is probably okay to hold the lock across syscall.Accept
-	// because we have put fd.sysfd into non-blocking mode.
-	// However, a call to the File method will put it back into
-	// blocking mode. We can't take that risk, so no use of ForkLock here.
-	ns, sa, err = acceptFunc(s)
-	if err == nil {
-		syscall.CloseOnExec(ns)
-	}
-	if err != nil {
-		return -1, nil, os.NewSyscallError("accept", err)
-	}
-	if err = syscall.SetNonblock(ns, true); err != nil {
-		closeFunc(ns)
-		return -1, nil, os.NewSyscallError("setnonblock", err)
-	}
-	return ns, sa, nil
-}
diff --git a/src/net/sock_posix.go b/src/net/sock_posix.go
index 16351e1..8985f8f 100644
--- a/src/net/sock_posix.go
+++ b/src/net/sock_posix.go
@@ -8,6 +8,7 @@
 
 import (
 	"context"
+	"internal/poll"
 	"os"
 	"syscall"
 )
@@ -43,11 +44,11 @@
 		return nil, err
 	}
 	if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return nil, err
 	}
 	if fd, err = newFD(s, family, sotype, net); err != nil {
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return nil, err
 	}
 
@@ -127,7 +128,7 @@
 		if lsa, err = laddr.sockaddr(fd.family); err != nil {
 			return err
 		} else if lsa != nil {
-			if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+			if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
 				return os.NewSyscallError("bind", err)
 			}
 		}
@@ -146,8 +147,8 @@
 			return err
 		}
 	}
-	lsa, _ = syscall.Getsockname(fd.sysfd)
-	if rsa, _ = syscall.Getpeername(fd.sysfd); rsa != nil {
+	lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
+	if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil {
 		fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
 	} else {
 		fd.setAddr(fd.addrFunc()(lsa), raddr)
@@ -156,23 +157,23 @@
 }
 
 func (fd *netFD) listenStream(laddr sockaddr, backlog int) error {
-	if err := setDefaultListenerSockopts(fd.sysfd); err != nil {
+	if err := setDefaultListenerSockopts(fd.pfd.Sysfd); err != nil {
 		return err
 	}
 	if lsa, err := laddr.sockaddr(fd.family); err != nil {
 		return err
 	} else if lsa != nil {
-		if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+		if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
 			return os.NewSyscallError("bind", err)
 		}
 	}
-	if err := listenFunc(fd.sysfd, backlog); err != nil {
+	if err := listenFunc(fd.pfd.Sysfd, backlog); err != nil {
 		return os.NewSyscallError("listen", err)
 	}
 	if err := fd.init(); err != nil {
 		return err
 	}
-	lsa, _ := syscall.Getsockname(fd.sysfd)
+	lsa, _ := syscall.Getsockname(fd.pfd.Sysfd)
 	fd.setAddr(fd.addrFunc()(lsa), nil)
 	return nil
 }
@@ -188,7 +189,7 @@
 		// multiple UDP listeners that listen on the same UDP
 		// port to join the same group address.
 		if addr.IP != nil && addr.IP.IsMulticast() {
-			if err := setDefaultMulticastSockopts(fd.sysfd); err != nil {
+			if err := setDefaultMulticastSockopts(fd.pfd.Sysfd); err != nil {
 				return err
 			}
 			addr := *addr
@@ -204,14 +205,14 @@
 	if lsa, err := laddr.sockaddr(fd.family); err != nil {
 		return err
 	} else if lsa != nil {
-		if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+		if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
 			return os.NewSyscallError("bind", err)
 		}
 	}
 	if err := fd.init(); err != nil {
 		return err
 	}
-	lsa, _ := syscall.Getsockname(fd.sysfd)
+	lsa, _ := syscall.Getsockname(fd.pfd.Sysfd)
 	fd.setAddr(fd.addrFunc()(lsa), nil)
 	return nil
 }
diff --git a/src/net/sockopt_posix.go b/src/net/sockopt_posix.go
index cd3d562..e8af84f 100644
--- a/src/net/sockopt_posix.go
+++ b/src/net/sockopt_posix.go
@@ -7,7 +7,7 @@
 package net
 
 import (
-	"os"
+	"runtime"
 	"syscall"
 )
 
@@ -101,27 +101,21 @@
 }
 
 func setReadBuffer(fd *netFD, bytes int) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes))
+	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func setWriteBuffer(fd *netFD, bytes int) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
+	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func setKeepAlive(fd *netFD, keepalive bool) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
+	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func setLinger(fd *netFD, sec int) error {
@@ -133,9 +127,7 @@
 		l.Onoff = 0
 		l.Linger = 0
 	}
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))
+	err := fd.pfd.SetsockoptLinger(syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/sockoptip_bsd.go b/src/net/sockoptip_bsd.go
index b15c639..b11f3a4 100644
--- a/src/net/sockoptip_bsd.go
+++ b/src/net/sockoptip_bsd.go
@@ -7,28 +7,24 @@
 package net
 
 import (
-	"os"
+	"runtime"
 	"syscall"
 )
 
 func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
 	ip, err := interfaceToIPv4Addr(ifi)
 	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
+		return wrapSyscallError("setsockopt", err)
 	}
 	var a [4]byte
 	copy(a[:], ip.To4())
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, a))
+	err = fd.pfd.SetsockoptInet4Addr(syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, a)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func setIPv4MulticastLoopback(fd *netFD, v bool) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v))))
+	err := fd.pfd.SetsockoptByte(syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/sockoptip_linux.go b/src/net/sockoptip_linux.go
index c1dcc91..bd7d834 100644
--- a/src/net/sockoptip_linux.go
+++ b/src/net/sockoptip_linux.go
@@ -5,7 +5,7 @@
 package net
 
 import (
-	"os"
+	"runtime"
 	"syscall"
 )
 
@@ -15,17 +15,13 @@
 		v = int32(ifi.Index)
 	}
 	mreq := &syscall.IPMreqn{Ifindex: v}
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq))
+	err := fd.pfd.SetsockoptIPMreqn(syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func setIPv4MulticastLoopback(fd *netFD, v bool) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)))
+	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/sockoptip_posix.go b/src/net/sockoptip_posix.go
index d508860..4e10f2a 100644
--- a/src/net/sockoptip_posix.go
+++ b/src/net/sockoptip_posix.go
@@ -7,7 +7,7 @@
 package net
 
 import (
-	"os"
+	"runtime"
 	"syscall"
 )
 
@@ -16,11 +16,9 @@
 	if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
 		return err
 	}
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
+	err := fd.pfd.SetsockoptIPMreq(syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
@@ -28,19 +26,15 @@
 	if ifi != nil {
 		v = ifi.Index
 	}
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v))
+	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func setIPv6MulticastLoopback(fd *netFD, v bool) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v)))
+	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
@@ -49,9 +43,7 @@
 	if ifi != nil {
 		mreq.Interface = uint32(ifi.Index)
 	}
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
+	err := fd.pfd.SetsockoptIPv6Mreq(syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/sockoptip_windows.go b/src/net/sockoptip_windows.go
index 916debe..6267603 100644
--- a/src/net/sockoptip_windows.go
+++ b/src/net/sockoptip_windows.go
@@ -6,6 +6,7 @@
 
 import (
 	"os"
+	"runtime"
 	"syscall"
 	"unsafe"
 )
@@ -17,17 +18,13 @@
 	}
 	var a [4]byte
 	copy(a[:], ip.To4())
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, (*byte)(unsafe.Pointer(&a[0])), 4))
+	err = fd.pfd.Setsockopt(syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, (*byte)(unsafe.Pointer(&a[0])), 4)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
 
 func setIPv4MulticastLoopback(fd *netFD, v bool) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)))
+	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/sys_cloexec.go b/src/net/sys_cloexec.go
index ba266e6..b7a8425 100644
--- a/src/net/sys_cloexec.go
+++ b/src/net/sys_cloexec.go
@@ -10,6 +10,7 @@
 package net
 
 import (
+	"internal/poll"
 	"os"
 	"syscall"
 )
@@ -28,30 +29,8 @@
 		return -1, os.NewSyscallError("socket", err)
 	}
 	if err = syscall.SetNonblock(s, true); err != nil {
-		closeFunc(s)
+		poll.CloseFunc(s)
 		return -1, os.NewSyscallError("setnonblock", err)
 	}
 	return s, nil
 }
-
-// Wrapper around the accept system call that marks the returned file
-// descriptor as nonblocking and close-on-exec.
-func accept(s int) (int, syscall.Sockaddr, error) {
-	// See ../syscall/exec_unix.go for description of ForkLock.
-	// It is probably okay to hold the lock across syscall.Accept
-	// because we have put fd.sysfd into non-blocking mode.
-	// However, a call to the File method will put it back into
-	// blocking mode. We can't take that risk, so no use of ForkLock here.
-	ns, sa, err := acceptFunc(s)
-	if err == nil {
-		syscall.CloseOnExec(ns)
-	}
-	if err != nil {
-		return -1, nil, os.NewSyscallError("accept", err)
-	}
-	if err = syscall.SetNonblock(ns, true); err != nil {
-		closeFunc(ns)
-		return -1, nil, os.NewSyscallError("setnonblock", err)
-	}
-	return ns, sa, nil
-}
diff --git a/src/net/tcpsock.go b/src/net/tcpsock.go
index 69731eb..a544a5b 100644
--- a/src/net/tcpsock.go
+++ b/src/net/tcpsock.go
@@ -255,7 +255,7 @@
 	if !l.ok() {
 		return syscall.EINVAL
 	}
-	if err := l.fd.setDeadline(t); err != nil {
+	if err := l.fd.pfd.SetDeadline(t); err != nil {
 		return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
 	}
 	return nil
diff --git a/src/net/tcpsockopt_darwin.go b/src/net/tcpsockopt_darwin.go
index 0d1310e..7415c76 100644
--- a/src/net/tcpsockopt_darwin.go
+++ b/src/net/tcpsockopt_darwin.go
@@ -5,7 +5,7 @@
 package net
 
 import (
-	"os"
+	"runtime"
 	"syscall"
 	"time"
 )
@@ -13,17 +13,15 @@
 const sysTCP_KEEPINTVL = 0x101
 
 func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
 	// The kernel expects seconds so round to next highest second.
 	d += (time.Second - time.Nanosecond)
 	secs := int(d.Seconds())
-	switch err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err {
+	switch err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err {
 	case nil, syscall.ENOPROTOOPT: // OS X 10.7 and earlier don't support this option
 	default:
-		return os.NewSyscallError("setsockopt", err)
+		return wrapSyscallError("setsockopt", err)
 	}
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs))
+	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/tcpsockopt_posix.go b/src/net/tcpsockopt_posix.go
index 805b56b..9cef434 100644
--- a/src/net/tcpsockopt_posix.go
+++ b/src/net/tcpsockopt_posix.go
@@ -7,14 +7,12 @@
 package net
 
 import (
-	"os"
+	"runtime"
 	"syscall"
 )
 
 func setNoDelay(fd *netFD, noDelay bool) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
+	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/tcpsockopt_solaris.go b/src/net/tcpsockopt_solaris.go
index 76285e5..019fe34 100644
--- a/src/net/tcpsockopt_solaris.go
+++ b/src/net/tcpsockopt_solaris.go
@@ -5,16 +5,12 @@
 package net
 
 import (
-	"os"
+	"runtime"
 	"syscall"
 	"time"
 )
 
 func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
 	// The kernel expects milliseconds so round to next highest
 	// millisecond.
 	d += (time.Millisecond - time.Nanosecond)
@@ -31,5 +27,7 @@
 	// allocate a constant with a different meaning for the value of
 	// TCP_KEEPINTVL on illumos.
 
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE_THRESHOLD, msecs))
+	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE_THRESHOLD, msecs)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/tcpsockopt_unix.go b/src/net/tcpsockopt_unix.go
index 8d44fb2..c1df660 100644
--- a/src/net/tcpsockopt_unix.go
+++ b/src/net/tcpsockopt_unix.go
@@ -7,21 +7,19 @@
 package net
 
 import (
-	"os"
+	"runtime"
 	"syscall"
 	"time"
 )
 
 func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
 	// The kernel expects seconds so round to next highest second.
 	d += (time.Second - time.Nanosecond)
 	secs := int(d.Seconds())
-	if err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs); err != nil {
-		return os.NewSyscallError("setsockopt", err)
+	if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs); err != nil {
+		return wrapSyscallError("setsockopt", err)
 	}
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs))
+	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs)
+	runtime.KeepAlive(fd)
+	return wrapSyscallError("setsockopt", err)
 }
diff --git a/src/net/tcpsockopt_windows.go b/src/net/tcpsockopt_windows.go
index 45a4dca..73dead1 100644
--- a/src/net/tcpsockopt_windows.go
+++ b/src/net/tcpsockopt_windows.go
@@ -6,16 +6,13 @@
 
 import (
 	"os"
+	"runtime"
 	"syscall"
 	"time"
 	"unsafe"
 )
 
 func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
-	if err := fd.incref(); err != nil {
-		return err
-	}
-	defer fd.decref()
 	// The kernel expects milliseconds so round to next highest
 	// millisecond.
 	d += (time.Millisecond - time.Nanosecond)
@@ -27,6 +24,7 @@
 	}
 	ret := uint32(0)
 	size := uint32(unsafe.Sizeof(ka))
-	err := syscall.WSAIoctl(fd.sysfd, syscall.SIO_KEEPALIVE_VALS, (*byte)(unsafe.Pointer(&ka)), size, nil, 0, &ret, nil, 0)
+	err := fd.pfd.WSAIoctl(syscall.SIO_KEEPALIVE_VALS, (*byte)(unsafe.Pointer(&ka)), size, nil, 0, &ret, nil, 0)
+	runtime.KeepAlive(fd)
 	return os.NewSyscallError("wsaioctl", err)
 }
diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go
index 55bbf44..9de7801 100644
--- a/src/net/timeout_test.go
+++ b/src/net/timeout_test.go
@@ -6,6 +6,7 @@
 
 import (
 	"fmt"
+	"internal/poll"
 	"internal/testenv"
 	"io"
 	"io/ioutil"
@@ -145,9 +146,9 @@
 }{
 	// Tests that accept deadlines in the past work, even if
 	// there's incoming connections available.
-	{-5 * time.Second, [2]error{errTimeout, errTimeout}},
+	{-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}},
 
-	{50 * time.Millisecond, [2]error{nil, errTimeout}},
+	{50 * time.Millisecond, [2]error{nil, poll.ErrTimeout}},
 }
 
 func TestAcceptTimeout(t *testing.T) {
@@ -299,9 +300,9 @@
 }{
 	// Tests that read deadlines work, even if there's data ready
 	// to be read.
-	{-5 * time.Second, [2]error{errTimeout, errTimeout}},
+	{-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}},
 
-	{50 * time.Millisecond, [2]error{nil, errTimeout}},
+	{50 * time.Millisecond, [2]error{nil, poll.ErrTimeout}},
 }
 
 func TestReadTimeout(t *testing.T) {
@@ -423,9 +424,9 @@
 }{
 	// Tests that read deadlines work, even if there's data ready
 	// to be read.
-	{-5 * time.Second, [2]error{errTimeout, errTimeout}},
+	{-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}},
 
-	{50 * time.Millisecond, [2]error{nil, errTimeout}},
+	{50 * time.Millisecond, [2]error{nil, poll.ErrTimeout}},
 }
 
 func TestReadFromTimeout(t *testing.T) {
@@ -496,9 +497,9 @@
 }{
 	// Tests that write deadlines work, even if there's buffer
 	// space available to write.
-	{-5 * time.Second, [2]error{errTimeout, errTimeout}},
+	{-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}},
 
-	{10 * time.Millisecond, [2]error{nil, errTimeout}},
+	{10 * time.Millisecond, [2]error{nil, poll.ErrTimeout}},
 }
 
 func TestWriteTimeout(t *testing.T) {
@@ -610,9 +611,9 @@
 }{
 	// Tests that write deadlines work, even if there's buffer
 	// space available to write.
-	{-5 * time.Second, [2]error{errTimeout, errTimeout}},
+	{-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}},
 
-	{10 * time.Millisecond, [2]error{nil, errTimeout}},
+	{10 * time.Millisecond, [2]error{nil, poll.ErrTimeout}},
 }
 
 func TestWriteToTimeout(t *testing.T) {
diff --git a/src/net/unixsock.go b/src/net/unixsock.go
index b25d492..d29514e 100644
--- a/src/net/unixsock.go
+++ b/src/net/unixsock.go
@@ -264,7 +264,7 @@
 	if !l.ok() {
 		return syscall.EINVAL
 	}
-	if err := l.fd.setDeadline(t); err != nil {
+	if err := l.fd.pfd.SetDeadline(t); err != nil {
 		return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
 	}
 	return nil
diff --git a/src/net/writev_test.go b/src/net/writev_test.go
index 7160d28..4c05be4 100644
--- a/src/net/writev_test.go
+++ b/src/net/writev_test.go
@@ -7,6 +7,7 @@
 import (
 	"bytes"
 	"fmt"
+	"internal/poll"
 	"io"
 	"io/ioutil"
 	"reflect"
@@ -99,13 +100,13 @@
 }
 
 func testBuffer_writeTo(t *testing.T, chunks int, useCopy bool) {
-	oldHook := testHookDidWritev
-	defer func() { testHookDidWritev = oldHook }()
+	oldHook := poll.TestHookDidWritev
+	defer func() { poll.TestHookDidWritev = oldHook }()
 	var writeLog struct {
 		sync.Mutex
 		log []int
 	}
-	testHookDidWritev = func(size int) {
+	poll.TestHookDidWritev = func(size int) {
 		writeLog.Lock()
 		writeLog.log = append(writeLog.log, size)
 		writeLog.Unlock()
diff --git a/src/net/writev_unix.go b/src/net/writev_unix.go
index 174e6bc..bf0fbf8 100644
--- a/src/net/writev_unix.go
+++ b/src/net/writev_unix.go
@@ -7,10 +7,8 @@
 package net
 
 import (
-	"io"
-	"os"
+	"runtime"
 	"syscall"
-	"unsafe"
 )
 
 func (c *conn) writeBuffers(v *Buffers) (int64, error) {
@@ -25,71 +23,7 @@
 }
 
 func (fd *netFD) writeBuffers(v *Buffers) (n int64, err error) {
-	if err := fd.writeLock(); err != nil {
-		return 0, err
-	}
-	defer fd.writeUnlock()
-	if err := fd.pd.prepareWrite(); err != nil {
-		return 0, err
-	}
-
-	var iovecs []syscall.Iovec
-	if fd.iovecs != nil {
-		iovecs = *fd.iovecs
-	}
-	// TODO: read from sysconf(_SC_IOV_MAX)? The Linux default is
-	// 1024 and this seems conservative enough for now. Darwin's
-	// UIO_MAXIOV also seems to be 1024.
-	maxVec := 1024
-
-	for len(*v) > 0 {
-		iovecs = iovecs[:0]
-		for _, chunk := range *v {
-			if len(chunk) == 0 {
-				continue
-			}
-			iovecs = append(iovecs, syscall.Iovec{Base: &chunk[0]})
-			if fd.isStream && len(chunk) > 1<<30 {
-				iovecs[len(iovecs)-1].SetLen(1 << 30)
-				break // continue chunk on next writev
-			}
-			iovecs[len(iovecs)-1].SetLen(len(chunk))
-			if len(iovecs) == maxVec {
-				break
-			}
-		}
-		if len(iovecs) == 0 {
-			break
-		}
-		fd.iovecs = &iovecs // cache
-
-		wrote, _, e0 := syscall.Syscall(syscall.SYS_WRITEV,
-			uintptr(fd.sysfd),
-			uintptr(unsafe.Pointer(&iovecs[0])),
-			uintptr(len(iovecs)))
-		if wrote == ^uintptr(0) {
-			wrote = 0
-		}
-		testHookDidWritev(int(wrote))
-		n += int64(wrote)
-		v.consume(int64(wrote))
-		if e0 == syscall.EAGAIN {
-			if err = fd.pd.waitWrite(); err == nil {
-				continue
-			}
-		} else if e0 != 0 {
-			err = syscall.Errno(e0)
-		}
-		if err != nil {
-			break
-		}
-		if n == 0 {
-			err = io.ErrUnexpectedEOF
-			break
-		}
-	}
-	if _, ok := err.(syscall.Errno); ok {
-		err = os.NewSyscallError("writev", err)
-	}
-	return n, err
+	n, err = fd.pfd.Writev((*[][]byte)(v))
+	runtime.KeepAlive(fd)
+	return n, wrapSyscallError("writev", err)
 }
diff --git a/src/runtime/net_plan9.go b/src/runtime/net_plan9.go
index 10fd089..b1ac7c7 100644
--- a/src/runtime/net_plan9.go
+++ b/src/runtime/net_plan9.go
@@ -8,12 +8,12 @@
 	_ "unsafe"
 )
 
-//go:linkname runtime_ignoreHangup net.runtime_ignoreHangup
+//go:linkname runtime_ignoreHangup internal/poll.runtime_ignoreHangup
 func runtime_ignoreHangup() {
 	getg().m.ignoreHangup = true
 }
 
-//go:linkname runtime_unignoreHangup net.runtime_unignoreHangup
+//go:linkname runtime_unignoreHangup internal/poll.runtime_unignoreHangup
 func runtime_unignoreHangup(sig string) {
 	getg().m.ignoreHangup = false
 }
diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go
index 10a3c88..ac8d071 100644
--- a/src/runtime/netpoll.go
+++ b/src/runtime/netpoll.go
@@ -81,8 +81,8 @@
 	pollcache     pollCache
 )
 
-//go:linkname net_runtime_pollServerInit net.runtime_pollServerInit
-func net_runtime_pollServerInit() {
+//go:linkname poll_runtime_pollServerInit internal/poll.runtime_pollServerInit
+func poll_runtime_pollServerInit() {
 	netpollinit()
 	atomic.Store(&netpollInited, 1)
 }
@@ -91,8 +91,8 @@
 	return atomic.Load(&netpollInited) != 0
 }
 
-//go:linkname net_runtime_pollOpen net.runtime_pollOpen
-func net_runtime_pollOpen(fd uintptr) (*pollDesc, int) {
+//go:linkname poll_runtime_pollOpen internal/poll.runtime_pollOpen
+func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) {
 	pd := pollcache.alloc()
 	lock(&pd.lock)
 	if pd.wg != 0 && pd.wg != pdReady {
@@ -115,8 +115,8 @@
 	return pd, int(errno)
 }
 
-//go:linkname net_runtime_pollClose net.runtime_pollClose
-func net_runtime_pollClose(pd *pollDesc) {
+//go:linkname poll_runtime_pollClose internal/poll.runtime_pollClose
+func poll_runtime_pollClose(pd *pollDesc) {
 	if !pd.closing {
 		throw("netpollClose: close w/o unblock")
 	}
@@ -137,8 +137,8 @@
 	unlock(&c.lock)
 }
 
-//go:linkname net_runtime_pollReset net.runtime_pollReset
-func net_runtime_pollReset(pd *pollDesc, mode int) int {
+//go:linkname poll_runtime_pollReset internal/poll.runtime_pollReset
+func poll_runtime_pollReset(pd *pollDesc, mode int) int {
 	err := netpollcheckerr(pd, int32(mode))
 	if err != 0 {
 		return err
@@ -151,8 +151,8 @@
 	return 0
 }
 
-//go:linkname net_runtime_pollWait net.runtime_pollWait
-func net_runtime_pollWait(pd *pollDesc, mode int) int {
+//go:linkname poll_runtime_pollWait internal/poll.runtime_pollWait
+func poll_runtime_pollWait(pd *pollDesc, mode int) int {
 	err := netpollcheckerr(pd, int32(mode))
 	if err != 0 {
 		return err
@@ -173,16 +173,16 @@
 	return 0
 }
 
-//go:linkname net_runtime_pollWaitCanceled net.runtime_pollWaitCanceled
-func net_runtime_pollWaitCanceled(pd *pollDesc, mode int) {
+//go:linkname poll_runtime_pollWaitCanceled internal/poll.runtime_pollWaitCanceled
+func poll_runtime_pollWaitCanceled(pd *pollDesc, mode int) {
 	// This function is used only on windows after a failed attempt to cancel
 	// a pending async IO operation. Wait for ioready, ignore closing or timeouts.
 	for !netpollblock(pd, int32(mode), true) {
 	}
 }
 
-//go:linkname net_runtime_pollSetDeadline net.runtime_pollSetDeadline
-func net_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
+//go:linkname poll_runtime_pollSetDeadline internal/poll.runtime_pollSetDeadline
+func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
 	lock(&pd.lock)
 	if pd.closing {
 		unlock(&pd.lock)
@@ -251,8 +251,8 @@
 	}
 }
 
-//go:linkname net_runtime_pollUnblock net.runtime_pollUnblock
-func net_runtime_pollUnblock(pd *pollDesc) {
+//go:linkname poll_runtime_pollUnblock internal/poll.runtime_pollUnblock
+func poll_runtime_pollUnblock(pd *pollDesc) {
 	lock(&pd.lock)
 	if pd.closing {
 		throw("netpollUnblock: already closing")
diff --git a/src/runtime/netpoll_windows.go b/src/runtime/netpoll_windows.go
index 7ad1158..32c120c 100644
--- a/src/runtime/netpoll_windows.go
+++ b/src/runtime/netpoll_windows.go
@@ -12,7 +12,8 @@
 
 const _INVALID_HANDLE_VALUE = ^uintptr(0)
 
-// net_op must be the same as beginning of net.operation. Keep these in sync.
+// net_op must be the same as beginning of internal/poll.operation.
+// Keep these in sync.
 type net_op struct {
 	// used by windows
 	o overlapped
diff --git a/src/runtime/sema.go b/src/runtime/sema.go
index 4046311..5b9a264 100644
--- a/src/runtime/sema.go
+++ b/src/runtime/sema.go
@@ -61,8 +61,8 @@
 	semacquire(addr, semaBlockProfile)
 }
 
-//go:linkname net_runtime_Semacquire net.runtime_Semacquire
-func net_runtime_Semacquire(addr *uint32) {
+//go:linkname poll_runtime_Semacquire internal/poll.runtime_Semacquire
+func poll_runtime_Semacquire(addr *uint32) {
 	semacquire(addr, semaBlockProfile)
 }
 
@@ -76,8 +76,8 @@
 	semacquire(addr, semaBlockProfile|semaMutexProfile)
 }
 
-//go:linkname net_runtime_Semrelease net.runtime_Semrelease
-func net_runtime_Semrelease(addr *uint32) {
+//go:linkname poll_runtime_Semrelease internal/poll.runtime_Semrelease
+func poll_runtime_Semrelease(addr *uint32) {
 	semrelease(addr)
 }
 
diff --git a/src/runtime/time.go b/src/runtime/time.go
index a095ec0..c296338 100644
--- a/src/runtime/time.go
+++ b/src/runtime/time.go
@@ -292,8 +292,8 @@
 
 // Entry points for net, time to call nanotime.
 
-//go:linkname net_runtimeNano net.runtimeNano
-func net_runtimeNano() int64 {
+//go:linkname poll_runtimeNano internal/poll.runtimeNano
+func poll_runtimeNano() int64 {
 	return nanotime()
 }
 
diff --git a/src/runtime/trace/trace_stack_test.go b/src/runtime/trace/trace_stack_test.go
index f8abf66..d6a3858 100644
--- a/src/runtime/trace/trace_stack_test.go
+++ b/src/runtime/trace/trace_stack_test.go
@@ -231,6 +231,7 @@
 	if runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
 		want = append(want, []eventDesc{
 			{trace.EvGoBlockNet, []frame{
+				{"internal/poll.(*FD).Accept", 0},
 				{"net.(*netFD).accept", 0},
 				{"net.(*TCPListener).accept", 0},
 				{"net.(*TCPListener).Accept", 0},