]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
runtime: Add netpoll code that uses select.
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 14 Nov 2013 20:15:04 +0000 (20:15 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 14 Nov 2013 20:15:04 +0000 (20:15 +0000)
Required for Solaris support.

From-SVN: r204817

libgo/Makefile.am
libgo/Makefile.in
libgo/runtime/malloc.h
libgo/runtime/mgc0.c
libgo/runtime/netpoll_epoll.c
libgo/runtime/netpoll_kqueue.c
libgo/runtime/netpoll_select.c [new file with mode: 0644]
libgo/runtime/netpoll_stub.c

index 489eafd66764599bbc7dbd300b8c71381b97a30d..052cded183b65cbdf32eeedcc9a97d7863c0e312 100644 (file)
@@ -413,12 +413,12 @@ endif
 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 @@ runtime_files = \
        malloc.c \
        map.c \
        mprof.c \
+       netpoll.c \
        reflect.c \
        runtime1.c \
        sema.c \
@@ -670,26 +671,6 @@ go_mime_files = \
        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_files = \
        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 \
index 20caecabfec420b9bbfbcb495d60453cd13882f8..e633b60ecf37550a9f70bfc7dc040b5d8fbdd388 100644 (file)
@@ -179,12 +179,9 @@ libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 @LIBGO_IS_LINUX_TRUE@am__objects_1 = lock_futex.lo thread-linux.lo
 @HAVE_SYS_MMAN_H_FALSE@am__objects_2 = mem_posix_memalign.lo
 @HAVE_SYS_MMAN_H_TRUE@am__objects_2 = mem.lo
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_LINUX_FALSE@am__objects_3 =  \
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_LINUX_FALSE@  netpoll_stub.lo
-@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_3 =  \
-@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@   netpoll.lo \
-@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@   netpoll_kqueue.lo
-@LIBGO_IS_LINUX_TRUE@am__objects_3 = netpoll.lo netpoll_epoll.lo
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = netpoll_kqueue.lo
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_3 = netpoll_select.lo
+@LIBGO_IS_LINUX_TRUE@am__objects_3 = netpoll_epoll.lo
 @LIBGO_IS_RTEMS_TRUE@am__objects_4 = rtems-task-variable-add.lo
 @LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-none.lo
 @LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-bsd.lo
@@ -220,8 +217,9 @@ am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \
        mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo \
        $(am__objects_3) panic.lo parfor.lo print.lo proc.lo \
        runtime.lo signal_unix.lo thread.lo yield.lo $(am__objects_4) \
-       iface.lo malloc.lo map.lo mprof.lo reflect.lo runtime1.lo \
-       sema.lo sigqueue.lo string.lo time.lo $(am__objects_5)
+       iface.lo malloc.lo map.lo mprof.lo netpoll.lo reflect.lo \
+       runtime1.lo sema.lo sigqueue.lo string.lo time.lo \
+       $(am__objects_5)
 am_libgo_la_OBJECTS = $(am__objects_6)
 libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
 libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -752,9 +750,9 @@ toolexeclibgounicode_DATA = \
 @LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-irix.c
 @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
 @LIBGO_IS_LINUX_TRUE@runtime_getncpu_file = runtime/getncpu-linux.c
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_LINUX_FALSE@runtime_netpoll_files = runtime/netpoll_stub.c
-@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_netpoll_files = netpoll.c runtime/netpoll_kqueue.c
-@LIBGO_IS_LINUX_TRUE@runtime_netpoll_files = netpoll.c runtime/netpoll_epoll.c
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_netpoll_files = runtime/netpoll_kqueue.c
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@runtime_netpoll_files = runtime/netpoll_select.c
+@LIBGO_IS_LINUX_TRUE@runtime_netpoll_files = runtime/netpoll_epoll.c
 runtime_files = \
        runtime/go-append.c \
        runtime/go-assert.c \
@@ -848,6 +846,7 @@ runtime_files = \
        malloc.c \
        map.c \
        mprof.c \
+       netpoll.c \
        reflect.c \
        runtime1.c \
        sema.c \
@@ -962,16 +961,6 @@ go_mime_files = \
        go/mime/type.go \
        go/mime/type_unix.go
 
-# By default use select with pipes.  Most systems should have
-# something better.
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = go/net/fd_select.go
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = 
-@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = 
-@LIBGO_IS_RTEMS_TRUE@go_net_fd_os_file = go/net/fd_select.go
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = 
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = 
-@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = 
-@LIBGO_IS_RTEMS_TRUE@go_net_newpollserver_file = go/net/newpollserver_rtems.go
 @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
 @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_netbsd.go
 @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
@@ -1019,10 +1008,8 @@ go_net_files = \
        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 \
@@ -2483,7 +2470,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_epoll.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_kqueue.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_stub.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_select.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panic.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parfor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@
@@ -3111,13 +3098,6 @@ msize.lo: runtime/msize.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msize.lo `test -f 'runtime/msize.c' || echo '$(srcdir)/'`runtime/msize.c
 
-netpoll_stub.lo: runtime/netpoll_stub.c
-@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_stub.lo -MD -MP -MF $(DEPDIR)/netpoll_stub.Tpo -c -o netpoll_stub.lo `test -f 'runtime/netpoll_stub.c' || echo '$(srcdir)/'`runtime/netpoll_stub.c
-@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/netpoll_stub.Tpo $(DEPDIR)/netpoll_stub.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='runtime/netpoll_stub.c' object='netpoll_stub.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_stub.lo `test -f 'runtime/netpoll_stub.c' || echo '$(srcdir)/'`runtime/netpoll_stub.c
-
 netpoll_kqueue.lo: runtime/netpoll_kqueue.c
 @am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_kqueue.lo -MD -MP -MF $(DEPDIR)/netpoll_kqueue.Tpo -c -o netpoll_kqueue.lo `test -f 'runtime/netpoll_kqueue.c' || echo '$(srcdir)/'`runtime/netpoll_kqueue.c
 @am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/netpoll_kqueue.Tpo $(DEPDIR)/netpoll_kqueue.Plo
@@ -3125,6 +3105,13 @@ netpoll_kqueue.lo: runtime/netpoll_kqueue.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_kqueue.lo `test -f 'runtime/netpoll_kqueue.c' || echo '$(srcdir)/'`runtime/netpoll_kqueue.c
 
+netpoll_select.lo: runtime/netpoll_select.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_select.lo -MD -MP -MF $(DEPDIR)/netpoll_select.Tpo -c -o netpoll_select.lo `test -f 'runtime/netpoll_select.c' || echo '$(srcdir)/'`runtime/netpoll_select.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/netpoll_select.Tpo $(DEPDIR)/netpoll_select.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='runtime/netpoll_select.c' object='netpoll_select.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_select.lo `test -f 'runtime/netpoll_select.c' || echo '$(srcdir)/'`runtime/netpoll_select.c
+
 netpoll_epoll.lo: runtime/netpoll_epoll.c
 @am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_epoll.lo -MD -MP -MF $(DEPDIR)/netpoll_epoll.Tpo -c -o netpoll_epoll.lo `test -f 'runtime/netpoll_epoll.c' || echo '$(srcdir)/'`runtime/netpoll_epoll.c
 @am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/netpoll_epoll.Tpo $(DEPDIR)/netpoll_epoll.Plo
index 45c4c09c1474c73c006b22db8b2959af7b9725ff..e1a5be9991920cc6351c0391d31be28447e90785 100644 (file)
@@ -515,3 +515,4 @@ void        runtime_memorydump(void);
 
 void   runtime_proc_scan(void (*)(Obj));
 void   runtime_time_scan(void (*)(Obj));
+void   runtime_netpoll_scan(void (*)(Obj));
index 3edcee9c397b620786d2ca2f51a68157cb6dd284..865f19304892da39e28e1b3811dbd51d2dfbd81c 100644 (file)
@@ -1491,6 +1491,7 @@ addroots(void)
        runtime_proc_scan(addroot);
        runtime_MProf_Mark(addroot);
        runtime_time_scan(addroot);
+       runtime_netpoll_scan(addroot);
 
        // MSpan.types
        allspans = runtime_mheap.allspans;
index b98aa818c89a24395877a437d817b8fb8c2a10d6..2acbca32322151c38ae30106c22fecac2801d2fb 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "runtime.h"
 #include "defs.h"
+#include "malloc.h"
 
 #ifndef EPOLLRDHUP
 #define EPOLLRDHUP 0x2000
@@ -156,3 +157,9 @@ retry:
                goto retry;
        return gp;
 }
+
+void
+runtime_netpoll_scan(void (*addroot)(Obj))
+{
+       USED(addroot);
+}
index 78901611884d2c8c5585305eb2637772ada6c9f1..5d3f85617b6d1325d9c7aa61563bd14b9946c493 100644 (file)
@@ -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 @@ retry:
                goto retry;
        return gp;
 }
+
+void
+runtime_netpoll_scan(void (*addroot)(Obj))
+{
+       USED(addroot);
+}
diff --git a/libgo/runtime/netpoll_select.c b/libgo/runtime/netpoll_select.c
new file mode 100644 (file)
index 0000000..c330f28
--- /dev/null
@@ -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});
+}
index 84eef754c8db62d9c502b95e912bb760bf35ed22..a88c9f5b9c2d4bd1bfb7ece1370818ef70177af6 100644 (file)
@@ -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 @@ runtime_netpoll(bool block)
        USED(block);
        return nil;
 }
+
+void
+runtime_netpoll_scan(void (*addroot)(Obj))
+{
+       USED(addroot);
+}