From 4ddd43debf264d8a8f82bfd0ec8cbac0d3678f69 Mon Sep 17 00:00:00 2001 From: Jim Date: Mon, 15 Aug 2011 17:11:28 -0400 Subject: [PATCH] Add async I/O code to devpnc, but disabled for now: there is a delay problem with remote terminal sessions: 1. netlink to remote Prime 2. a prirun 3. l (list directory) 4. displays a little, then a longish pause up to 30 seconds, then the rest Does a similar thing with stat us. Hitting Enter will cause it to finish, while typing characters does not. I suspect this is a problem with Prime's networking code, but not sure. Also, if async I/O is used, the QUIT. OK, message doesn't appear after ctrl-p. I think they are getting wiped out by Primenet's buffer flushes. All of this might be subtle timing problems because I changed the default clock rate from 250/330/500/whatever times per sec to 20 times per second in this rev 19 version of Primos. --- devpnc.h | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- em.c | 10 ++++++++-- 2 files changed, 53 insertions(+), 11 deletions(-) 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 */