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
This commit is contained in:
Ian Lance Taylor 2014-01-08 00:42:45 +00:00
parent 06f4627b30
commit 2da4a7611b

View file

@ -118,10 +118,15 @@ runtime_netpollclose(uintptr fd)
return 0; return 0;
} }
/* Used to avoid using too much stack memory. */
static bool inuse;
static fd_set grfds, gwfds, gefds, gtfds;
G* G*
runtime_netpoll(bool block) runtime_netpoll(bool block)
{ {
fd_set rfds, wfds, efds, tfds; fd_set *prfds, *pwfds, *pefds, *ptfds;
bool allocatedfds;
struct timeval timeout; struct timeval timeout;
struct timeval *pt; struct timeval *pt;
int max, c, i; int max, c, i;
@ -140,37 +145,52 @@ runtime_netpoll(bool block)
return nil; 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); runtime_unlock(&selectlock);
__builtin_memcpy(&wfds, &rfds, sizeof fds); __builtin_memcpy(pwfds, prfds, sizeof fds);
FD_CLR(rdwake, &wfds); FD_CLR(rdwake, pwfds);
__builtin_memcpy(&efds, &wfds, sizeof fds); __builtin_memcpy(pefds, pwfds, sizeof fds);
__builtin_memcpy(&tfds, &wfds, sizeof fds); __builtin_memcpy(ptfds, pwfds, sizeof fds);
__builtin_memset(&timeout, 0, sizeof timeout); __builtin_memset(&timeout, 0, sizeof timeout);
pt = &timeout; pt = &timeout;
if(block) if(block)
pt = nil; pt = nil;
c = select(max, &rfds, &wfds, &efds, pt); c = select(max, prfds, pwfds, pefds, pt);
if(c < 0) { if(c < 0) {
if(errno == EBADF) { if(errno == EBADF) {
// Some file descriptor has been closed. // Some file descriptor has been closed.
// Check each one, and treat each closed // Check each one, and treat each closed
// descriptor as ready for read/write. // descriptor as ready for read/write.
c = 0; c = 0;
FD_ZERO(&rfds); FD_ZERO(prfds);
FD_ZERO(&wfds); FD_ZERO(pwfds);
FD_ZERO(&efds); FD_ZERO(pefds);
for(i = 0; i < max; i++) { for(i = 0; i < max; i++) {
if(FD_ISSET(i, &tfds) if(FD_ISSET(i, ptfds)
&& fstat(i, &st) < 0 && fstat(i, &st) < 0
&& errno == EBADF) { && errno == EBADF) {
FD_SET(i, &rfds); FD_SET(i, prfds);
FD_SET(i, &wfds); FD_SET(i, pwfds);
c += 2; c += 2;
} }
} }
@ -184,15 +204,15 @@ runtime_netpoll(bool block)
gp = nil; gp = nil;
for(i = 0; i < max && c > 0; i++) { for(i = 0; i < max && c > 0; i++) {
mode = 0; mode = 0;
if(FD_ISSET(i, &rfds)) { if(FD_ISSET(i, prfds)) {
mode += 'r'; mode += 'r';
--c; --c;
} }
if(FD_ISSET(i, &wfds)) { if(FD_ISSET(i, pwfds)) {
mode += 'w'; mode += 'w';
--c; --c;
} }
if(FD_ISSET(i, &efds)) { if(FD_ISSET(i, pefds)) {
mode = 'r' + 'w'; mode = 'r' + 'w';
--c; --c;
} }
@ -213,6 +233,15 @@ runtime_netpoll(bool block)
} }
if(block && gp == nil) if(block && gp == nil)
goto retry; goto retry;
if(allocatedfds) {
runtime_SysFree(prfds, 4 * sizeof fds, &mstats.other_sys);
} else {
runtime_lock(&selectlock);
inuse = false;
runtime_unlock(&selectlock);
}
return gp; return gp;
} }