Patchwork libgo patch committed: Fix fd_select.go

login
register
mail settings
Submitter Ian Taylor
Date March 28, 2011, 6:35 p.m.
Message ID <mcrtyenay9f.fsf@google.com>
Download mbox | patch
Permalink /patch/88652/
State New
Headers show

Comments

Ian Taylor - March 28, 2011, 6:35 p.m.
This patch fixes fd_select.go for the changes in FD handling in the
latest libgo update.  The code in libgo now takes advantage of the fact
that if you change the set of descriptors used by epoll, it is not
necessary to wake up the thread waiting in epoll_wait.  That is not true
of select: if you change the set of descriptors, you do have to wake up
the select.  This patch implements that.  Bootstrapped on
x86_64-unknown-linux-gnu.  Ran Go testsuite using fd_select.go instead
of fd_linux.go.  Committed to mainline.  This fixes PR go/48312.

Ian

Patch

diff -r 056f7c9c13f8 libgo/go/net/fd.go
--- a/libgo/go/net/fd.go	Mon Mar 28 11:28:45 2011 -0700
+++ b/libgo/go/net/fd.go	Mon Mar 28 11:30:46 2011 -0700
@@ -122,9 +122,13 @@ 
 		doWakeup = true
 	}
 
-	if err := s.poll.AddFD(intfd, mode, false); err != nil {
+	wake, err := s.poll.AddFD(intfd, mode, false)
+	if err != nil {
 		panic("pollServer AddFD " + err.String())
 	}
+	if wake {
+		doWakeup = true
+	}
 
 	s.Unlock()
 
diff -r 056f7c9c13f8 libgo/go/net/fd_linux.go
--- a/libgo/go/net/fd_linux.go	Mon Mar 28 11:28:45 2011 -0700
+++ b/libgo/go/net/fd_linux.go	Mon Mar 28 11:30:46 2011 -0700
@@ -47,7 +47,7 @@ 
 	return p, nil
 }
 
-func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
 	// pollServer is locked.
 
 	var already bool
@@ -69,10 +69,10 @@ 
 		op = syscall.EPOLL_CTL_ADD
 	}
 	if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != 0 {
-		return os.NewSyscallError("epoll_ctl", e)
+		return false, os.NewSyscallError("epoll_ctl", e)
 	}
 	p.events[fd] = p.ctlEvent.Events
-	return nil
+	return false, nil
 }
 
 func (p *pollster) StopWaiting(fd int, bits uint) {
diff -r 056f7c9c13f8 libgo/go/net/fd_select.go
--- a/libgo/go/net/fd_select.go	Mon Mar 28 11:28:45 2011 -0700
+++ b/libgo/go/net/fd_select.go	Mon Mar 28 11:30:46 2011 -0700
@@ -32,7 +32,9 @@ 
 	return p, nil
 }
 
-func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
+	// pollServer is locked.
+
 	if mode == 'r' {
 		syscall.FDSet(fd, p.readFds)
 	} else {
@@ -47,10 +49,12 @@ 
 		p.maxFd = fd
 	}
 
-	return nil
+	return true, nil
 }
 
 func (p *pollster) DelFD(fd int, mode int) {
+	// pollServer is locked.
+
 	if mode == 'r' {
 		if !syscall.FDIsSet(fd, p.readFds) {
 			print("Select unexpected fd=", fd, " for read\n")
@@ -71,7 +75,7 @@ 
 	// We don't worry about maxFd here.
 }
 
-func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) {
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
 	if p.nReady == 0 {
 		var timeout *syscall.Timeval
 		var tv syscall.Timeval
@@ -89,7 +93,10 @@ 
 			tmpReadFds = *p.readFds
 			tmpWriteFds = *p.writeFds
 
+			s.Unlock()
 			n, e = syscall.Select(p.maxFd + 1, &tmpReadFds, &tmpWriteFds, nil, timeout)
+			s.Lock()
+
 			if e != syscall.EINTR {
 				break
 			}
diff -r 056f7c9c13f8 libgo/go/net/newpollserver.go
--- a/libgo/go/net/newpollserver.go	Mon Mar 28 11:28:45 2011 -0700
+++ b/libgo/go/net/newpollserver.go	Mon Mar 28 11:30:46 2011 -0700
@@ -31,7 +31,7 @@ 
 	if s.poll, err = newpollster(); err != nil {
 		goto Error
 	}
-	if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
+	if _, err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
 		s.poll.Close()
 		goto Error
 	}
diff -r 056f7c9c13f8 libgo/go/net/newpollserver_rtems.go
--- a/libgo/go/net/newpollserver_rtems.go	Mon Mar 28 11:28:45 2011 -0700
+++ b/libgo/go/net/newpollserver_rtems.go	Mon Mar 28 11:30:46 2011 -0700
@@ -68,7 +68,7 @@ 
 	if s.poll, err = newpollster(); err != nil {
 		goto Error
 	}
-	if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
+	if _, err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
 		s.poll.Close()
 		goto Error
 	}