@@ -535,12 +535,21 @@
go_mime_files = \
go/mime/type.go
+if LIBGO_IS_RTEMS
+go_net_fd_os_file = go/net/fd_rtems.go
+go_net_newpollserver_file = go/net/newpollserver_rtems.go
+else
+go_net_fd_os_file = go/net/fd_linux.go
+go_net_newpollserver_file = go/net/newpollserver.go
+endif
+
go_net_files = \
go/net/dnsclient.go \
go/net/dnsconfig.go \
go/net/dnsmsg.go \
+ $(go_net_newpollserver_file) \
go/net/fd.go \
- go/net/fd_linux.go \
+ $(go_net_fd_os_file) \
go/net/hosts.go \
go/net/ip.go \
go/net/iprawsock.go \
@@ -93,37 +93,6 @@
deadline int64 // next deadline (nsec since 1970)
}
-func newPollServer() (s *pollServer, err os.Error) {
- s = new(pollServer)
- s.cr = make(chan *netFD, 1)
- s.cw = make(chan *netFD, 1)
- if s.pr, s.pw, err = os.Pipe(); err != nil {
- return nil, err
- }
- var e int
- if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 {
- Errno:
- err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)}
- Error:
- s.pr.Close()
- s.pw.Close()
- return nil, err
- }
- if e = syscall.SetNonblock(s.pw.Fd(), true); e != 0 {
- goto Errno
- }
- if s.poll, err = newpollster(); err != nil {
- goto Error
- }
- if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
- s.poll.Close()
- goto Error
- }
- s.pending = make(map[int]*netFD)
- go s.Run()
- return s, nil
-}
-
func (s *pollServer) AddFD(fd *netFD, mode int) {
intfd := fd.sysfd
if intfd < 0 {
@@ -0,0 +1,138 @@
+// 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.
+
+// Waiting for FDs via select(2).
+
+package net
+
+import (
+ "os"
+ "syscall"
+ //"fmt"
+)
+
+type pollster struct {
+ readFds, writeFds, repeatFds *syscall.FdSet_t
+ maxFd int
+ readyReadFds, readyWriteFds *syscall.FdSet_t
+ nReady int
+ lastFd int
+}
+
+func newpollster() (p *pollster, err os.Error) {
+ p = new(pollster)
+ p.readFds = new(syscall.FdSet_t)
+ p.writeFds = new(syscall.FdSet_t)
+ p.repeatFds = new(syscall.FdSet_t)
+ p.readyReadFds = new(syscall.FdSet_t)
+ p.readyWriteFds = new(syscall.FdSet_t)
+ p.maxFd = -1
+ p.nReady = 0
+ p.lastFd = 0
+ return p, nil
+}
+
+func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
+ if mode == 'r' {
+ syscall.FDSet(fd, p.readFds)
+ } else {
+ syscall.FDSet(fd, p.writeFds)
+ }
+
+ if repeat {
+ syscall.FDSet(fd, p.repeatFds)
+ }
+
+ if fd > p.maxFd {
+ p.maxFd = fd
+ }
+
+ return nil
+}
+
+func (p *pollster) DelFD(fd int, mode int) {
+ if mode == 'r' {
+ if !syscall.FDIsSet(fd, p.readFds) {
+ print("Select unexpected fd=", fd, " for read\n")
+ return
+ }
+ syscall.FDClr(fd, p.readFds)
+ } else {
+ if !syscall.FDIsSet(fd, p.writeFds) {
+ print("Select unexpected fd=", fd, " for write\n")
+ return
+ }
+ syscall.FDClr(fd, p.writeFds)
+ }
+
+ // Doesn't matter if not already present.
+ syscall.FDClr(fd, p.repeatFds)
+
+ // We don't worry about maxFd here.
+}
+
+func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) {
+ if p.nReady == 0 {
+ var timeout *syscall.Timeval
+ var tv syscall.Timeval
+ timeout = nil
+ if nsec > 0 {
+ tv = syscall.NsecToTimeval(nsec)
+ timeout = &tv
+ }
+
+ var n, e int
+ var tmpReadFds, tmpWriteFds syscall.FdSet_t
+ for {
+ // Temporary syscall.FdSet_ts into which the values are copied
+ // because select mutates the values.
+ tmpReadFds = *p.readFds
+ tmpWriteFds = *p.writeFds
+
+ n, e = syscall.Select(p.maxFd + 1, &tmpReadFds, &tmpWriteFds, nil, timeout)
+ if e != syscall.EINTR {
+ break
+ }
+ }
+ if e != 0 {
+ return -1, 0, os.NewSyscallError("select", e)
+ }
+ if n == 0 {
+ return -1, 0, nil
+ }
+
+ p.nReady = n
+ *p.readyReadFds = tmpReadFds
+ *p.readyWriteFds = tmpWriteFds
+ p.lastFd = 0
+ }
+
+ flag := false
+ for i := p.lastFd; i < p.maxFd + 1; i++ {
+ if syscall.FDIsSet(i, p.readyReadFds) {
+ flag = true
+ mode := 'r'
+ syscall.FDClr(i, p.readyReadFds)
+ } else if syscall.FDIsSet(i, p.readyWriteFds) {
+ flag = true
+ mode := 'w'
+ syscall.FDClr(i, p.readyWriteFds)
+ }
+ if flag {
+ if !syscall.FDIsSet(i, p.repeatFds) {
+ p.DelFD(i, mode)
+ }
+ p.nReady--
+ p.lastFd = i
+ return i, mode, nil
+ }
+ }
+
+ // Will not reach here. Just to shut up the compiler.
+ return -1, 0, nil
+}
+
+func (p *pollster) Close() os.Error {
+ return nil
+}
@@ -0,0 +1,41 @@
+// 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.
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func newPollServer() (s *pollServer, err os.Error) {
+ s = new(pollServer)
+ s.cr = make(chan *netFD, 1)
+ s.cw = make(chan *netFD, 1)
+ if s.pr, s.pw, err = os.Pipe(); err != nil {
+ return nil, err
+ }
+ var e int
+ if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 {
+ Errno:
+ err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)}
+ Error:
+ s.pr.Close()
+ s.pw.Close()
+ return nil, err
+ }
+ if e = syscall.SetNonblock(s.pw.Fd(), true); e != 0 {
+ goto Errno
+ }
+ if s.poll, err = newpollster(); err != nil {
+ goto Error
+ }
+ if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
+ s.poll.Close()
+ goto Error
+ }
+ s.pending = make(map[int]*netFD)
+ go s.Run()
+ return s, nil
+}
@@ -0,0 +1,78 @@
+// 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.
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func selfConnectedTCPSocket() (pr, pw *os.File, err os.Error) {
+ // See ../syscall/exec.go for description of ForkLock.
+ syscall.ForkLock.RLock()
+ sockfd, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
+ if e != 0 {
+ syscall.ForkLock.RUnlock()
+ return nil, nil, os.Errno(e)
+ }
+ syscall.CloseOnExec(sockfd)
+ syscall.ForkLock.RUnlock()
+
+ // Allow reuse of recently-used addresses.
+ syscall.SetsockoptInt(sockfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+
+ var laTCP *TCPAddr
+ var la syscall.Sockaddr
+ if laTCP, err = ResolveTCPAddr("127.0.0.1:0"); err != nil {
+ Error:
+ return nil, nil, err
+ }
+ if la, err = laTCP.sockaddr(syscall.AF_INET); err != nil {
+ goto Error
+ }
+ e = syscall.Bind(sockfd, la)
+ if e != 0 {
+ Errno:
+ syscall.Close(sockfd)
+ return nil, nil, os.Errno(e)
+ }
+
+ laddr, _ := syscall.Getsockname(sockfd)
+ e = syscall.Connect(sockfd, laddr)
+ if e != 0 {
+ goto Errno
+ }
+
+ fd := os.NewFile(sockfd, "wakeupSocket")
+ return fd, fd, nil
+}
+
+func newPollServer() (s *pollServer, err os.Error) {
+ s = new(pollServer)
+ s.cr = make(chan *netFD, 1)
+ s.cw = make(chan *netFD, 1)
+ // s.pr and s.pw are indistinguishable.
+ if s.pr, s.pw, err = selfConnectedTCPSocket(); err != nil {
+ return nil, err
+ }
+ var e int
+ if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 {
+ Errno:
+ err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)}
+ Error:
+ s.pr.Close()
+ return nil, err
+ }
+ if s.poll, err = newpollster(); err != nil {
+ goto Error
+ }
+ if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
+ s.poll.Close()
+ goto Error
+ }
+ s.pending = make(map[int]*netFD)
+ go s.Run()
+ return s, nil
+}