diff mbox

Recent Go patch broke Solaris bootstrap

Message ID CAKOQZ8zJAaSJ2_R31pT_rk1bfpw_a+ez2pxSBEqksZRXwNA78w@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor Nov. 14, 2013, 8:15 p.m. UTC
On Fri, Nov 8, 2013 at 4:01 AM, Rainer Orth <ro@cebitec.uni-bielefeld.de> wrote:
> The recent Go patch (couldn't find the submission on gcc-patches) broke
> Solaris bootstrap: on Solaris 10/x86 I get
>
> /vol/gcc/src/hg/trunk/local/libgo/go/net/fd_select.go:90:30: error: use of undefined type 'pollServer'
>  func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
>                               ^
> /vol/gcc/src/hg/trunk/local/libgo/go/net/fd_select.go:113:5: error: reference to field 'Unlock' in object which has no fields or methods
>     s.Unlock()
>      ^
> /vol/gcc/src/hg/trunk/local/libgo/go/net/fd_select.go:115:5: error: reference to field 'Lock' in object which has no fields or methods
>     s.Lock()

Network polling is different and more efficient in the updated
library.  This patch adds the select-based polling that Solaris has to
use to the new system.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu both using the select polling and using the
default epoll polling.  Committed to mainline.

Ian
diff mbox

Patch

diff -r 0ba9f772ad41 libgo/Makefile.am
--- a/libgo/Makefile.am	Thu Nov 14 12:03:31 2013 -0800
+++ b/libgo/Makefile.am	Thu Nov 14 12:09:04 2013 -0800
@@ -413,12 +413,12 @@ 
 endif
 
 if LIBGO_IS_LINUX
-runtime_netpoll_files = netpoll.c runtime/netpoll_epoll.c
+runtime_netpoll_files = runtime/netpoll_epoll.c
 else
-if LIBGO_IS_DARWIN
-runtime_netpoll_files = netpoll.c runtime/netpoll_kqueue.c
+if LIBGO_IS_SOLARIS
+runtime_netpoll_files = runtime/netpoll_select.c
 else
-runtime_netpoll_files = runtime/netpoll_stub.c
+runtime_netpoll_files = runtime/netpoll_kqueue.c
 endif
 endif
 
@@ -515,6 +515,7 @@ 
 	malloc.c \
 	map.c \
 	mprof.c \
+	netpoll.c \
 	reflect.c \
 	runtime1.c \
 	sema.c \
@@ -670,26 +671,6 @@ 
 	go/mime/type.go \
 	go/mime/type_unix.go
 
-if LIBGO_IS_RTEMS
-go_net_fd_os_file = go/net/fd_select.go
-go_net_newpollserver_file = go/net/newpollserver_rtems.go
-else # !LIBGO_IS_RTEMS
-if LIBGO_IS_LINUX
-go_net_fd_os_file =
-go_net_newpollserver_file =
-else # !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS
-if LIBGO_IS_NETBSD
-go_net_fd_os_file =
-go_net_newpollserver_file =
-else # !LIBGO_IS_NETBSD && !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS
-# By default use select with pipes.  Most systems should have
-# something better.
-go_net_fd_os_file = go/net/fd_select.go
-go_net_newpollserver_file =
-endif # !LIBGO_IS_NETBSD
-endif # !LIBGO_IS_LINUX
-endif # !LIBGO_IS_RTEMS
-
 if LIBGO_IS_LINUX
 go_net_cgo_file = go/net/cgo_linux.go
 go_net_sock_file = go/net/sock_linux.go
@@ -787,10 +768,8 @@ 
 	go/net/dnsclient_unix.go \
 	go/net/dnsconfig_unix.go \
 	go/net/dnsmsg.go \
-	$(go_net_newpollserver_file) \
 	go/net/fd_mutex.go \
 	go/net/fd_unix.go \
-	$(go_net_fd_os_file) \
 	go/net/file_unix.go \
 	go/net/hosts.go \
 	go/net/interface.go \
diff -r 0ba9f772ad41 libgo/runtime/malloc.h
--- a/libgo/runtime/malloc.h	Thu Nov 14 12:03:31 2013 -0800
+++ b/libgo/runtime/malloc.h	Thu Nov 14 12:09:04 2013 -0800
@@ -515,3 +515,4 @@ 
 
 void	runtime_proc_scan(void (*)(Obj));
 void	runtime_time_scan(void (*)(Obj));
+void	runtime_netpoll_scan(void (*)(Obj));
diff -r 0ba9f772ad41 libgo/runtime/mgc0.c
--- a/libgo/runtime/mgc0.c	Thu Nov 14 12:03:31 2013 -0800
+++ b/libgo/runtime/mgc0.c	Thu Nov 14 12:09:04 2013 -0800
@@ -1491,6 +1491,7 @@ 
 	runtime_proc_scan(addroot);
 	runtime_MProf_Mark(addroot);
 	runtime_time_scan(addroot);
+	runtime_netpoll_scan(addroot);
 
 	// MSpan.types
 	allspans = runtime_mheap.allspans;
diff -r 0ba9f772ad41 libgo/runtime/netpoll_epoll.c
--- a/libgo/runtime/netpoll_epoll.c	Thu Nov 14 12:03:31 2013 -0800
+++ b/libgo/runtime/netpoll_epoll.c	Thu Nov 14 12:09:04 2013 -0800
@@ -11,6 +11,7 @@ 
 
 #include "runtime.h"
 #include "defs.h"
+#include "malloc.h"
 
 #ifndef EPOLLRDHUP
 #define EPOLLRDHUP 0x2000
@@ -156,3 +157,9 @@ 
 		goto retry;
 	return gp;
 }
+
+void
+runtime_netpoll_scan(void (*addroot)(Obj))
+{
+	USED(addroot);
+}
diff -r 0ba9f772ad41 libgo/runtime/netpoll_kqueue.c
--- a/libgo/runtime/netpoll_kqueue.c	Thu Nov 14 12:03:31 2013 -0800
+++ b/libgo/runtime/netpoll_kqueue.c	Thu Nov 14 12:09:04 2013 -0800
@@ -5,8 +5,8 @@ 
 // +build darwin dragonfly freebsd netbsd openbsd
 
 #include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
+#include "defs.h"
+#include "malloc.h"
 
 // Integrated network poller (kqueue-based implementation).
 
@@ -102,3 +102,9 @@ 
 		goto retry;
 	return gp;
 }
+
+void
+runtime_netpoll_scan(void (*addroot)(Obj))
+{
+	USED(addroot);
+}
diff -r 0ba9f772ad41 libgo/runtime/netpoll_select.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/runtime/netpoll_select.c	Thu Nov 14 12:09:04 2013 -0800
@@ -0,0 +1,223 @@ 
+// 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.
+
+// +build solaris
+
+#include "config.h"
+
+#include <errno.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "runtime.h"
+#include "malloc.h"
+
+static Lock selectlock;
+static int rdwake;
+static int wrwake;
+static fd_set fds;
+static PollDesc **data;
+static int allocated;
+
+void
+runtime_netpollinit(void)
+{
+	int p[2];
+	int fl;
+
+	FD_ZERO(&fds);
+	allocated = 128;
+	data = runtime_mallocgc(allocated * sizeof(PollDesc *), 0,
+				FlagNoScan|FlagNoProfiling|FlagNoInvokeGC);
+
+	if(pipe(p) < 0)
+		runtime_throw("netpollinit: failed to create pipe");
+	rdwake = p[0];
+	wrwake = p[1];
+
+	fl = fcntl(rdwake, F_GETFL);
+	if(fl < 0)
+		runtime_throw("netpollinit: fcntl failed");
+	fl |= O_NONBLOCK;
+	if(fcntl(rdwake, F_SETFL, fl))
+		 runtime_throw("netpollinit: fcntl failed");
+	fcntl(rdwake, F_SETFD, FD_CLOEXEC);
+
+	fl = fcntl(wrwake, F_GETFL);
+	if(fl < 0)
+		runtime_throw("netpollinit: fcntl failed");
+	fl |= O_NONBLOCK;
+	if(fcntl(wrwake, F_SETFL, fl))
+		 runtime_throw("netpollinit: fcntl failed");
+	fcntl(wrwake, F_SETFD, FD_CLOEXEC);
+
+	FD_SET(rdwake, &fds);
+}
+
+int32
+runtime_netpollopen(uintptr fd, PollDesc *pd)
+{
+	byte b;
+
+	runtime_lock(&selectlock);
+
+	if((int)fd >= allocated) {
+		int c;
+		PollDesc **n;
+
+		c = allocated;
+
+		runtime_unlock(&selectlock);
+
+		while((int)fd >= c)
+			c *= 2;
+		n = runtime_mallocgc(c * sizeof(PollDesc *), 0,
+				     FlagNoScan|FlagNoProfiling|FlagNoInvokeGC);
+
+		runtime_lock(&selectlock);
+
+		if(c > allocated) {
+			__builtin_memcpy(n, data, allocated * sizeof(PollDesc *));
+			allocated = c;
+			data = n;
+		}
+	}
+	FD_SET(fd, &fds);
+	data[fd] = pd;
+
+	runtime_unlock(&selectlock);
+
+	b = 0;
+	write(wrwake, &b, sizeof b);
+
+	return 0;
+}
+
+int32
+runtime_netpollclose(uintptr fd)
+{
+	byte b;
+
+	runtime_lock(&selectlock);
+
+	FD_CLR(fd, &fds);
+	data[fd] = nil;
+
+	runtime_unlock(&selectlock);
+
+	b = 0;
+	write(wrwake, &b, sizeof b);
+
+	return 0;
+}
+
+G*
+runtime_netpoll(bool block)
+{
+	fd_set rfds, wfds, efds, tfds;
+	struct timeval timeout;
+	struct timeval *pt;
+	int max, c, i;
+	G *gp;
+	int32 mode;
+	byte b;
+	struct stat st;
+
+ retry:
+	runtime_lock(&selectlock);
+
+	max = allocated;
+
+	if(max == 0) {
+		runtime_unlock(&selectlock);
+		return nil;
+	}
+
+	__builtin_memcpy(&rfds, &fds, sizeof fds);
+
+	runtime_unlock(&selectlock);
+
+	__builtin_memcpy(&wfds, &rfds, sizeof fds);
+	FD_CLR(rdwake, &wfds);
+	__builtin_memcpy(&efds, &wfds, sizeof fds);
+
+	__builtin_memcpy(&tfds, &wfds, sizeof fds);
+
+	__builtin_memset(&timeout, 0, sizeof timeout);
+	pt = &timeout;
+	if(block)
+		pt = nil;
+
+	c = select(max, &rfds, &wfds, &efds, pt);
+	if(c < 0) {
+		if(errno == EBADF) {
+			// Some file descriptor has been closed.
+			// Check each one, and treat each closed
+			// descriptor as ready for read/write.
+			c = 0;
+			FD_ZERO(&rfds);
+			FD_ZERO(&wfds);
+			FD_ZERO(&efds);
+			for(i = 0; i < max; i++) {
+				if(FD_ISSET(i, &tfds)
+				   && fstat(i, &st) < 0
+				   && errno == EBADF) {
+					FD_SET(i, &rfds);
+					FD_SET(i, &wfds);
+					c += 2;
+				}
+			}
+		}
+		else {
+			if(errno != EINTR)
+				runtime_printf("runtime: select failed with %d\n", errno);
+			goto retry;
+		}
+	}
+	gp = nil;
+	for(i = 0; i < max && c > 0; i++) {
+		mode = 0;
+		if(FD_ISSET(i, &rfds)) {
+			mode += 'r';
+			--c;
+		}
+		if(FD_ISSET(i, &wfds)) {
+			mode += 'w';
+			--c;
+		}
+		if(FD_ISSET(i, &efds)) {
+			mode = 'r' + 'w';
+			--c;
+		}
+		if(i == rdwake) {
+			while(read(rdwake, &b, sizeof b) > 0)
+				;
+			continue;
+		}
+		if(mode) {
+			PollDesc *pd;
+
+			runtime_lock(&selectlock);
+			pd = data[i];
+			runtime_unlock(&selectlock);
+			if(pd != nil)
+				runtime_netpollready(&gp, pd, mode);
+		}
+	}
+	if(block && gp == nil)
+		goto retry;
+	return gp;
+}
+
+void
+runtime_netpoll_scan(void (*addroot)(Obj))
+{
+	addroot((Obj){(byte*)&data, sizeof data, 0});
+}
diff -r 0ba9f772ad41 libgo/runtime/netpoll_stub.c
--- a/libgo/runtime/netpoll_stub.c	Thu Nov 14 12:03:31 2013 -0800
+++ b/libgo/runtime/netpoll_stub.c	Thu Nov 14 12:09:04 2013 -0800
@@ -5,6 +5,7 @@ 
 // +build plan9
 
 #include "runtime.h"
+#include "malloc.h"
 
 // Polls for ready network connections.
 // Returns list of goroutines that become runnable.
@@ -16,3 +17,9 @@ 
 	USED(block);
 	return nil;
 }
+
+void
+runtime_netpoll_scan(void (*addroot)(Obj))
+{
+	USED(addroot);
+}