diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-11-14 20:15:04 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-11-14 20:15:04 +0000 |
commit | 03a231f7521b62a593fd7a4ce7067102288bd28f (patch) | |
tree | 8d7245531a5a7415aca8d276ddcd1dde96652404 /libgo/runtime | |
parent | 7d608db296739dfbbb9dfa65d796b82691158e53 (diff) | |
download | gcc-03a231f7521b62a593fd7a4ce7067102288bd28f.zip gcc-03a231f7521b62a593fd7a4ce7067102288bd28f.tar.gz gcc-03a231f7521b62a593fd7a4ce7067102288bd28f.tar.bz2 |
runtime: Add netpoll code that uses select.
Required for Solaris support.
From-SVN: r204817
Diffstat (limited to 'libgo/runtime')
-rw-r--r-- | libgo/runtime/malloc.h | 1 | ||||
-rw-r--r-- | libgo/runtime/mgc0.c | 1 | ||||
-rw-r--r-- | libgo/runtime/netpoll_epoll.c | 7 | ||||
-rw-r--r-- | libgo/runtime/netpoll_kqueue.c | 10 | ||||
-rw-r--r-- | libgo/runtime/netpoll_select.c | 223 | ||||
-rw-r--r-- | libgo/runtime/netpoll_stub.c | 7 |
6 files changed, 247 insertions, 2 deletions
diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h index 45c4c09..e1a5be9 100644 --- a/libgo/runtime/malloc.h +++ b/libgo/runtime/malloc.h @@ -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)); diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c index 3edcee9..865f193 100644 --- a/libgo/runtime/mgc0.c +++ b/libgo/runtime/mgc0.c @@ -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; diff --git a/libgo/runtime/netpoll_epoll.c b/libgo/runtime/netpoll_epoll.c index b98aa81..2acbca3 100644 --- a/libgo/runtime/netpoll_epoll.c +++ b/libgo/runtime/netpoll_epoll.c @@ -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); +} diff --git a/libgo/runtime/netpoll_kqueue.c b/libgo/runtime/netpoll_kqueue.c index 7890161..5d3f856 100644 --- a/libgo/runtime/netpoll_kqueue.c +++ b/libgo/runtime/netpoll_kqueue.c @@ -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 index 0000000..c330f28 --- /dev/null +++ b/libgo/runtime/netpoll_select.c @@ -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 --git a/libgo/runtime/netpoll_stub.c b/libgo/runtime/netpoll_stub.c index 84eef75..a88c9f5 100644 --- a/libgo/runtime/netpoll_stub.c +++ b/libgo/runtime/netpoll_stub.c @@ -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); +} |