diff --git a/devpnc.h b/devpnc.h index 4d8569f..9cbd7a8 100644 --- a/devpnc.h +++ b/devpnc.h @@ -189,7 +189,7 @@ #ifndef HOBBY -/* PNC poll rate is 1/10th of a second */ +/* PNC poll rate in ms, mostly for connecting to new nodes */ #define PNCPOLL 100 @@ -304,6 +304,15 @@ typedef struct { } t_dma; static t_dma rcv, xmit; +static int sawsigio=0, olddevpoll; + +void pnchavedata(int s) { + if (sawsigio) return; + olddevpoll = devpoll[7]; + devpoll[7] = 1; + sawsigio = 1; +} + /* return pointer to a hex-formatted uid */ char * pnchexuid(char * uid) { @@ -371,14 +380,22 @@ pncinitfd(int fd) { perror("unable to get ts flags for PNC"); fatal(NULL); } - fdflags |= O_NONBLOCK; + optval = MAXPKTBYTES; + if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, &optval, sizeof(optval))) { + perror("setsockopt 2 failed for PNC"); + fatal(NULL); + } + if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval))) { + perror("setsockopt 3 failed for PNC"); + fatal(NULL); + } + fdflags |= O_NONBLOCK+O_ASYNC; if (fcntl(fd, F_SETFL, fdflags) == -1) { perror("unable to set fdflags for PNC"); fatal(NULL); } - optval = MAXPKTBYTES; - if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, &optval, sizeof(optval))) { - perror("setsockopt failed for PNC"); + if (fcntl(fd, F_SETOWN, getpid()) == -1) { + perror("unable to SETOWN for PNC"); fatal(NULL); } } @@ -872,6 +889,10 @@ int devpnc (int class, int func, int device) { perror("setsockopt failed for PNC listen"); fatal(NULL); } + if (setsockopt(pncfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval))) { + perror("setsockopt 1 failed for PNC"); + fatal(NULL); + } addr.sin_family = AF_INET; addr.sin_port = htons(nport); addr.sin_addr.s_addr = INADDR_ANY; @@ -885,6 +906,12 @@ int devpnc (int class, int func, int device) { } TRACE(T_RIO, "PNC configured\n"); devpoll[device] = PNCPOLL*gvp->instpermsec; +#ifdef ASYNCIO + if (signal(SIGIO, pnchavedata) == SIG_ERR) { + perror("installing SIGIO handler"); + fatal(NULL); + } +#endif return 0; case 0: @@ -1122,10 +1149,19 @@ int devpnc (int class, int func, int device) { case 4: TRACE(T_RIO, " POLL '%02o%02o\n", func, device); - devpoll[device] = PNCPOLL*gvp->instpermsec; - time(&timenow); - pncaccept(timenow); /* accept 1 new connection each poll */ - pncconnect(timenow); /* try to connect to a disconnected node */ + + /* on SIGPIPE, reset to the previous poll time and just do reads; + otherwise, a regularly scheduled poll */ + + if (sawsigio) { + devpoll[device] = olddevpoll; + sawsigio = 0; + } else { + devpoll[device] = PNCPOLL*gvp->instpermsec; + time(&timenow); + pncaccept(timenow); /* accept 1 new connection each poll */ + pncconnect(timenow); /* try to connect to a disconnected node */ + } intrexit: if (rcv.state == PNCBSRDY) diff --git a/em.c b/em.c index ae2936d..7620b8b 100644 --- a/em.c +++ b/em.c @@ -6628,12 +6628,18 @@ d_bdx: /* 0140734 */ if (delayusec > 1000) { if (gettimeofday(&tv0, NULL) != 0) fatal("em: gettimeofday 0 failed"); + + /* NOTE: on OSX, a signal (sigio for pnc) will interrupt usleep */ + usleep(delayusec); if (gettimeofday(&tv1, NULL) != 0) fatal("em: gettimeofday 1 failed"); actualmsec = (tv1.tv_sec-tv0.tv_sec-1)*1000 + (tv1.tv_usec+1000000-tv0.tv_usec)/1000; - // TRACEA(" BDX loop at %o/%o, remainder=%d, owner=%o, utempl=%d, wanted %d us, got %d ms\n", gvp->prevpc>>16, gvp->prevpc&0xffff, crs[X], crs[OWNERL], utempl, delayusec, actualusec); - +#if 0 + if (actualmsec > delayusec*1.2/1000) { + TRACEA(" BDX loop at %o/%o, remainder=%d, owner=%o, utempl=%d, wanted %d ms, got %d ms\n", gvp->prevpc>>16, gvp->prevpc&0xffff, crs[X], crs[OWNERL], utempl, delayusec/1000, actualmsec); + } +#endif /* do timer bookkeeping that would have occurred if we had actually looped on BDX utempl times */