On Fri, Nov 8, 2013 at 4:01 AM, Rainer Orth <r...@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); +}