aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime/netpoll_select.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2014-01-08 00:42:45 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-01-08 00:42:45 +0000
commit2da4a7611b2b68bb446f6138bd474c426006444c (patch)
treede5d458286ae1d045a6d4c6c5f2f049e2a99b65f /libgo/runtime/netpoll_select.c
parent06f4627b30d21952b56df4642872df5a637f93f4 (diff)
downloadgcc-2da4a7611b2b68bb446f6138bd474c426006444c.zip
gcc-2da4a7611b2b68bb446f6138bd474c426006444c.tar.gz
gcc-2da4a7611b2b68bb446f6138bd474c426006444c.tar.bz2
re PR go/59433 (Many 64-bit Go tests SEGV on Solaris)
PR go/59433 net: Don't use stack space for fd_sets when using select. From-SVN: r206411
Diffstat (limited to 'libgo/runtime/netpoll_select.c')
-rw-r--r--libgo/runtime/netpoll_select.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/libgo/runtime/netpoll_select.c b/libgo/runtime/netpoll_select.c
index c330f28..788d19f 100644
--- a/libgo/runtime/netpoll_select.c
+++ b/libgo/runtime/netpoll_select.c
@@ -118,10 +118,15 @@ runtime_netpollclose(uintptr fd)
return 0;
}
+/* Used to avoid using too much stack memory. */
+static bool inuse;
+static fd_set grfds, gwfds, gefds, gtfds;
+
G*
runtime_netpoll(bool block)
{
- fd_set rfds, wfds, efds, tfds;
+ fd_set *prfds, *pwfds, *pefds, *ptfds;
+ bool allocatedfds;
struct timeval timeout;
struct timeval *pt;
int max, c, i;
@@ -140,37 +145,52 @@ runtime_netpoll(bool block)
return nil;
}
- __builtin_memcpy(&rfds, &fds, sizeof fds);
+ if(inuse) {
+ prfds = runtime_SysAlloc(4 * sizeof fds, &mstats.other_sys);
+ pwfds = prfds + 1;
+ pefds = pwfds + 1;
+ ptfds = pefds + 1;
+ allocatedfds = true;
+ } else {
+ prfds = &grfds;
+ pwfds = &gwfds;
+ pefds = &gefds;
+ ptfds = &gtfds;
+ inuse = true;
+ allocatedfds = false;
+ }
+
+ __builtin_memcpy(prfds, &fds, sizeof fds);
runtime_unlock(&selectlock);
- __builtin_memcpy(&wfds, &rfds, sizeof fds);
- FD_CLR(rdwake, &wfds);
- __builtin_memcpy(&efds, &wfds, sizeof fds);
+ __builtin_memcpy(pwfds, prfds, sizeof fds);
+ FD_CLR(rdwake, pwfds);
+ __builtin_memcpy(pefds, pwfds, sizeof fds);
- __builtin_memcpy(&tfds, &wfds, sizeof fds);
+ __builtin_memcpy(ptfds, pwfds, sizeof fds);
__builtin_memset(&timeout, 0, sizeof timeout);
pt = &timeout;
if(block)
pt = nil;
- c = select(max, &rfds, &wfds, &efds, pt);
+ c = select(max, prfds, pwfds, pefds, 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);
+ FD_ZERO(prfds);
+ FD_ZERO(pwfds);
+ FD_ZERO(pefds);
for(i = 0; i < max; i++) {
- if(FD_ISSET(i, &tfds)
+ if(FD_ISSET(i, ptfds)
&& fstat(i, &st) < 0
&& errno == EBADF) {
- FD_SET(i, &rfds);
- FD_SET(i, &wfds);
+ FD_SET(i, prfds);
+ FD_SET(i, pwfds);
c += 2;
}
}
@@ -184,15 +204,15 @@ runtime_netpoll(bool block)
gp = nil;
for(i = 0; i < max && c > 0; i++) {
mode = 0;
- if(FD_ISSET(i, &rfds)) {
+ if(FD_ISSET(i, prfds)) {
mode += 'r';
--c;
}
- if(FD_ISSET(i, &wfds)) {
+ if(FD_ISSET(i, pwfds)) {
mode += 'w';
--c;
}
- if(FD_ISSET(i, &efds)) {
+ if(FD_ISSET(i, pefds)) {
mode = 'r' + 'w';
--c;
}
@@ -213,6 +233,15 @@ runtime_netpoll(bool block)
}
if(block && gp == nil)
goto retry;
+
+ if(allocatedfds) {
+ runtime_SysFree(prfds, 4 * sizeof fds, &mstats.other_sys);
+ } else {
+ runtime_lock(&selectlock);
+ inuse = false;
+ runtime_unlock(&selectlock);
+ }
+
return gp;
}