This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Recent Go patch broke Solaris bootstrap
- From: Ian Lance Taylor <iant at google dot com>
- To: Rainer Orth <ro at cebitec dot uni-bielefeld dot de>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>, "gofrontend-dev at googlegroups dot com" <gofrontend-dev at googlegroups dot com>
- Date: Thu, 14 Nov 2013 12:15:07 -0800
- Subject: Re: Recent Go patch broke Solaris bootstrap
- Authentication-results: sourceware.org; auth=none
- References: <ydd8uwzp0ey dot fsf at lokon dot CeBiTec dot Uni-Bielefeld dot DE>
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 -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);
+}