int CopyAndComputeViceSHA(int infd, int outfd, unsigned char sha[SHA_DIGEST_LENGTH]) { /* ComputeViceSHA() takes an open file and returns its SHA value in a Vice SHA structure. If outfd is not -1, we copy the while computing the SHA. Returns 0 on success, and -1 on any kind of failure */ int bytes_out, bytes_in = 0; int i = 0; SHA_CTX cx; #define SHACHUNKSIZE 4096 /* might be better to set to fs block size? */ unsigned char shachunk[SHACHUNKSIZE]; SHA1_Init(&cx); while (1) { /* make sure we yield to other threads once in a while */ if ((++i % SHA_YIELD_INTERVAL) == 0) LWP_DispatchProcess(); bytes_in = read (infd, shachunk, SHACHUNKSIZE); if (bytes_in <= 0) break; SHA1_Update(&cx, shachunk, bytes_in); if (outfd != -1) { bytes_out = write(outfd, shachunk, bytes_in); if (bytes_out < bytes_in) return -1; } } SHA1_Final(sha, &cx); return (bytes_in < 0 ? -1 : 0); }
void rpc2_SocketListener(void *dummy) { int fd; /* just once, at RPC2_Init time, to be nice */ LWP_DispatchProcess(); /* The funny if-do construct below assures the following: 1. All packets in the socket buffer are processed before expiring events 2. The number of select() system calls is kept to bare minimum */ while (1) { /* block until we receive packets, or the next event timeout triggers */ fd = PacketCame(); if (fd == -1) { /* some timeout elapsed, handle it and go back to waiting for the * next packet or timeout event */ rpc2_ExpireEvents(); continue; } /* we received a packet, process any packets that have been queued * in the socket buffers */ do { rpc2_ProcessPacket(fd); fd = rpc2_MorePackets(); } while (fd != -1); } }
static void OtherProcess(void *arg) { PROCESS parent = (PROCESS)arg; for (;;) { /* we just yield */ #if 0 LWP_DispatchProcess(); #else LWP_QSignal(parent); LWP_QWait(); #endif } }
int mnode_find (const AFSFid *fid, struct mnode **node) { struct mnode ptr, *res = NULL; ptr.fid = *fid; while (res == NULL) { res = hashtabsearch (mnode_htab, &ptr); if (res) { if (res->flags.removedp == TRUE) return ENOENT; if (res->li) listdel (mnode_lru, res->li); if (res->ref == 0) mnode_numfree--; res->ref++; } else if (mnode_numfree != 0) { res = listdeltail (mnode_lru); assert (res); assert (res->ref == 0); hashtabdel (mnode_htab, res); reset_node (res, fid); hashtabadd (mnode_htab, res); res->ref++; } else { /* XXX */ mlog_log (MDEBWARN, "mnode_find: no free nodes, had to malloc()"); res = malloc(sizeof(struct mnode)); if (res == NULL) { mlog_log (MDEBWARN, "mnode_find: malloc() failed"); LWP_DispatchProcess(); /* Yield */ continue; } reset_node (res, fid); hashtabadd (mnode_htab, res); res->ref++; } } assert(res->flags.removedp == FALSE); *node = res; res->li = listaddhead (mnode_lru, *node); return 0; }
static void ListenerBody(void *arg) { long i; RPC2_RequestFilter reqfilter; RPC2_PacketBuffer *InBuff; RPC2_NewConnectionBody *newconnbody; RPC2_Handle newcid; LWP_DispatchProcess(); /* initial courtesy to parent */ reqfilter.FromWhom = ONESUBSYS; reqfilter.ConnOrSubsys.SubsysId = SUBSYS_SRV; assert(reqfilter.ConnOrSubsys.SubsysId != -1); reqfilter.OldOrNew = NEW; InBuff = NULL; while (1) { RanDelay(MaxListenPause); if (InBuff != NULL) RPC2_FreeBuffer(&InBuff); i = RPC2_GetRequest(&reqfilter, &newcid, &InBuff, NULL, GetPasswd, RPC2_XOR, NULL); if (i != RPC2_SUCCESS) { printf("Listener error: "); WhatHappened(i); } switch(InBuff->Header.Opcode) { case RPC2_NEWCONNECTION: /* new connection */ { newconnbody = (RPC2_NewConnectionBody *)InBuff->Body; if (VerboseFlag) fprintf(stderr, "Newconn: %#x \"%s\" at %s", newcid, (char*)&newconnbody->ClientIdent_SeqBody, TimeNow()); RPC2_Enable(newcid); /* unfreeze the connection */ break; } default: /* unknown opcode */ assert(InBuff->Header.Opcode == RPC2_NEWCONNECTION); break; } } }
static void AlarmHandler(int sig, int code, struct sigcontext *scp) #endif { if (PRE_Block == 0 && lwp_cpptr->level == 0) { PRE_BeginCritical(); #if HAVE_SIGACTION && defined(SA_SIGINFO) sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL); #else sigsetmask(scp->sc_mask); #endif LWP_DispatchProcess(); PRE_EndCritical(); } }
void RPC2_DispatchProcess() { struct timeval tv; int fd; while ((fd = rpc2_MorePackets()) != -1) rpc2_ProcessPacket(fd); /* keep current time from being too inaccurate */ (void)FT_GetTimeOfDay(&tv, (struct timezone *)0); /* also check for timed-out events, using current time */ rpc2_ExpireEvents(); LWP_DispatchProcess(); }
int main(int argc, char **argv) { struct timeval t1, t2; PROCESS pid, otherpid; long i, count, x; static char c[] = "OtherProcess"; count = argc > 1 ? atoi(argv[1]) : 10000; cont_sw_threshold.tv_sec = 0; cont_sw_threshold.tv_usec = 10000; last_context_switch.tv_sec = 0; last_context_switch.tv_usec = 0; assert(LWP_Init(LWP_VERSION, 0, &pid) == LWP_SUCCESS); assert(LWP_CreateProcess(OtherProcess, 16384, 0, (char *)pid, c, &otherpid) == LWP_SUCCESS); assert(IOMGR_Initialize() == LWP_SUCCESS); gettimeofday(&t1, NULL); for (i = 0; i < count; i++) { #if 0 LWP_DispatchProcess(); #else LWP_QSignal(otherpid); LWP_QWait(); #endif } gettimeofday(&t2, NULL); if (count) { x = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec); printf("%ld milliseconds for %ld Yields (%f usec per Yield)\n", x / 1000, count, (float)(x / count)); } LWP_TerminateProcessSupport(); exit(EXIT_SUCCESS); }
void BrainSurgeon() { bool rc; LogMsg(1000,LogLevel,LogFile,"Starting Brain Surgeon thread"); if (lobotomy == mfalse) LWP_WaitProcess(DoLobotomy); /* we only get here if a lobotomy has been arranged */ LogMsg(0,LogLevel,LogFile, "***** Lobotomizing"); extern bbuf *buffer; buffer->flush_the_tank(); while((rc = buffer->empty()) != mtrue) { LWP_DispatchProcess(); } /* ** if we've gotten here, we know that no new requests have ** entered the buffer, and the buffer is empty, so die ** gracefully. */ Data_Done(); Log_Done(); RestoreSignals(); exit(0); }
int main(void) { long go; GetRoot(); /* Also creates a child process for transcribing stdout */ GetParms(); MakeFiles(); /* in test directory */ InitRPC(); MakeWorkers(); GetConns(); GetVar(&go, "Say when: "); DoBindings(); MakeClients(); /* wait for all clients to get ready */ while (ClientsReady < Clients) LWP_DispatchProcess(); LWP_NoYieldSignal((char *)&ClientsReady); LWP_WaitProcess((char *)main); /* infinite wait */ return 0; /* make compiler happy */ }
static void ClientBody(void *arg) { RPC2_Handle thisconn; RPC2_Integer thisopcode; RPC2_PacketBuffer *request, *reply; long retcode, rpctime = 0; struct timeval t1, t2; char myprivatefile[256]; char myhashmark; RPC2_BindParms bp; SE_Descriptor sed; #define MakeTimedCall(whichse)\ if (VerboseFlag) gettimeofday(&t1, 0);\ retcode = RPC2_MakeRPC(ConnVector[thisconn].ConnHandle, request, whichse, &reply, NULL, 0);\ if (VerboseFlag) gettimeofday(&t2, 0);\ if (VerboseFlag) rpctime = ((t2.tv_sec - t1.tv_sec)*1000) + ((t2.tv_usec - t1.tv_usec)/1000); memset(&sed, 0, sizeof(SE_Descriptor)); sed.Tag = SMARTFTP; strcpy(myprivatefile, MakeName(LWP_Name())); myhashmark = NextHashMark++; LWP_DispatchProcess(); /* initial courtesy to parent */ RPC2_AllocBuffer(1000, &request); reply = NULL; ClientsReady++; LWP_WaitProcess((char *)&ClientsReady); /* wait for main() to tap me on shoulder */ while(1) { if (reply) RPC2_FreeBuffer(&reply); RanDelay(MaxThinkTime); SelectParms(&thisconn, &thisopcode); ConnVector[thisconn].Status = BUSY; request->Header.Opcode = thisopcode; if (VerboseFlag) fprintf(stderr, "Making request %d to %s for %s\n", thisopcode, ConnVector[thisconn].RemoteHost.Value.Name, ConnVector[thisconn].NameBuf); switch(thisopcode) { case 1: /* return Unix epoch time */ { request->Header.BodyLength = 0; MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) fprintf(stderr, "Time on %s is %s (%ld msecs)\n", ConnVector[thisconn].RemoteHost.Value.Name, reply->Body, rpctime); break; } else HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); } case 2: /* square the input integer */ { uint32_t *op = (uint32_t *)request->Body; uint32_t x = (uint32_t)random() % 100; op[0] = htonl(x); request->Header.BodyLength = sizeof(uint32_t); MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) { uint32_t *ip = (uint32_t *)reply->Body; fprintf(stderr, " %s says square of %u is %u (%ld msecs)\n", ConnVector[thisconn].RemoteHost.Value.Name, x, ntohl(ip[0]), rpctime); } break; } else HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } case 3: /* cube the input integer */ { uint32_t *op = (uint32_t *)request->Body; uint32_t x = (uint32_t)random() % 100; op[0] = htonl(x); request->Header.BodyLength = sizeof(uint32_t); MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) { uint32_t *ip = (uint32_t *)reply->Body; fprintf(stderr, "%s says cube of %d is %u (%ld msecs)\n", ConnVector[thisconn].RemoteHost.Value.Name, x, ntohl(ip[0]), rpctime); } break; } else HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } case 4: /* Return your machine name */ { request->Header.BodyLength = 0; MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) fprintf(stderr, "%s says its name is \"%s\" (%ld msecs)\n", ConnVector[thisconn].RemoteHost.Value.Name, reply->Body, rpctime); break; } else HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } case 5: /* Fetch a random file */ { if (AvoidBulk) { ConnVector[thisconn].Status = SFREE; continue; } request->Header.BodyLength = 0; sed.Value.SmartFTPD.TransmissionDirection = SERVERTOCLIENT; sed.Value.SmartFTPD.FileInfo.ByName.ProtectionBits = 0644; sed.Value.SmartFTPD.SeekOffset = 0; sed.Value.SmartFTPD.Tag = FILEBYNAME; strcpy(sed.Value.SmartFTPD.FileInfo.ByName.LocalFileName, myprivatefile); if (VerboseFlag) sed.Value.SmartFTPD.hashmark = myhashmark; else sed.Value.SmartFTPD.hashmark = 0; MakeTimedCall(&sed); if (retcode != RPC2_SUCCESS) { HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } else if (VerboseFlag) fprintf(stderr, "%ld bytes transferred\n", sed.Value.SmartFTPD.BytesTransferred); break; } case 6: /* Store a random file */ { uint32_t randval; if (AvoidBulk) { ConnVector[thisconn].Status = SFREE; continue; } request->Header.BodyLength = 0; sed.Value.SmartFTPD.TransmissionDirection = CLIENTTOSERVER; sed.Value.SmartFTPD.SeekOffset = 0; sed.Value.SmartFTPD.Tag = FILEBYNAME; randval = (uint32_t)random(); strcpy(sed.Value.SmartFTPD.FileInfo.ByName.LocalFileName, SysFiles[randval % SysFileCount]); if (VerboseFlag) sed.Value.SmartFTPD.hashmark = myhashmark; else sed.Value.SmartFTPD.hashmark = 0; MakeTimedCall(&sed); if (retcode != RPC2_SUCCESS) { HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } else if (VerboseFlag) fprintf(stderr, "%ld bytes transferred\n", sed.Value.SmartFTPD.BytesTransferred); break; } case 7: /* Unbind */ { request->Header.BodyLength = 0; MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) fprintf(stderr, "Unbound connection to %s for %s after %ld calls\n", ConnVector[thisconn].RemoteHost.Value.Name, ConnVector[thisconn].Identity.SeqBody, ConnVector[thisconn].CallsMade); assert(RPC2_Unbind(ConnVector[thisconn].ConnHandle) == RPC2_SUCCESS); } else {HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode));} ConnVector[thisconn].Status = UNBOUND; break; } case 8: /* Rebind */ { bp.SecurityLevel = ConnVector[thisconn].SecurityLevel; bp.EncryptionType = RPC2_XOR; bp.SideEffectType = SMARTFTP; bp.ClientIdent = &ConnVector[thisconn].Identity; bp.SharedSecret = &ConnVector[thisconn].Password; retcode = RPC2_NewBinding(&ConnVector[thisconn].RemoteHost, &PortId, &SubsysId, &bp, &ConnVector[thisconn].ConnHandle); if (retcode < RPC2_ELIMIT) { HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); } else { if (VerboseFlag) fprintf(stderr, "Rebound connection to %s for %s\n", ConnVector[thisconn].RemoteHost.Value.Name, ConnVector[thisconn].Identity.SeqBody); } break; } case 999: /* Quit */ { } default: /* unknown opcode */ printf("Arrrgggghhh .... bogus opcode\n"); abort(); break; } if (ConnVector[thisconn].Status == BUSY) ConnVector[thisconn].Status = SFREE; if (retcode == RPC2_CONNBUSY) continue; /* you didn't really do it */ /* Indicate progress */ ConnVector[thisconn].CallsMade++; if(ConnVector[thisconn].CallsMade % Announce == 1) { struct CVEntry *ce = &ConnVector[thisconn]; printf("\n%ld successful calls to %s for %s at %s", ce->CallsMade, ce->RemoteHost.Value.Name, ce->NameBuf, TimeNow()); PrintStats(); } else { int xx; xx = (1.0*Announce)/100.0 + 0.5; /* ceiling */ if (xx == 0 || ConnVector[thisconn].CallsMade % xx == 1) printf("%c", myhashmark); } } }
static void WorkerBody(void *arg) { long i, rc; RPC2_RequestFilter reqfilter; RPC2_PacketBuffer *InBuff, *OutBuff; RPC2_Handle workercid; char myprivatefile[256]; char myhashmark; SE_Descriptor sed; memset(&sed, 0, sizeof(SE_Descriptor)); sed.Tag = SMARTFTP; strcpy(myprivatefile, MakeName(LWP_Name())); myhashmark = NextHashMark++; LWP_DispatchProcess(); /* initial courtesy to parent */ reqfilter.FromWhom = ONESUBSYS; reqfilter.ConnOrSubsys.SubsysId = SUBSYS_SRV; assert(reqfilter.ConnOrSubsys.SubsysId != -1); reqfilter.OldOrNew = OLD; RPC2_AllocBuffer(1000, &OutBuff); InBuff = NULL; while (1) { RanDelay(MaxComputeTime); if (InBuff != NULL) RPC2_FreeBuffer(&InBuff); i = RPC2_GetRequest(&reqfilter, &workercid, &InBuff, NULL, NULL, 0, NULL); if (i != RPC2_SUCCESS) { printf("\n%s: GetRequest failed (%s) at %s", MYNAME, RPC2_ErrorMsg(i), TimeNow()); DumpAndQuit(0); } switch(InBuff->Header.Opcode) { case 1: /* return Unix epoch time */ { strcpy((char *)OutBuff->Body, TimeNow()); OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = sizeof(struct RPC2_PacketHeader) + strlen((char *)OutBuff->Body) + 1; break; } case 2: /* square the input integer */ { uint32_t *ip = (uint32_t *)InBuff->Body; uint32_t *op = (uint32_t *)OutBuff->Body; uint32_t x = ntohl(*ip); *op = htonl(x * x); OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = sizeof(RPC2_Integer); break; } case 3: /* cube the input integer */ { uint32_t *ip = (uint32_t *)InBuff->Body; uint32_t *op = (uint32_t *)OutBuff->Body; uint32_t x = ntohl(*ip); *op = htonl(x*x*x); OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = sizeof(RPC2_Integer); break; } case 4: /* Return your machine name */ { gethostname((char *)OutBuff->Body, 100); OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = strlen((char *)OutBuff->Body) + 1; break; } case 5: /* Fetch a random file */ { uint32_t randval; if (VerboseFlag) sed.Value.SmartFTPD.hashmark = myhashmark; else sed.Value.SmartFTPD.hashmark = 0; randval = (uint32_t)random(); strcpy(sed.Value.SmartFTPD.FileInfo.ByName.LocalFileName, SysFiles[randval % SysFileCount]); sed.Value.SmartFTPD.TransmissionDirection = SERVERTOCLIENT; sed.Value.SmartFTPD.SeekOffset = 0; sed.Value.SmartFTPD.Tag = FILEBYNAME; if ((rc = RPC2_InitSideEffect(workercid, &sed)) != RPC2_SUCCESS) { BulkErr(workercid, &sed, rc, InBuff->Header.Opcode); assert(RPC2_Unbind(workercid) == RPC2_SUCCESS); continue; } if ((rc = RPC2_CheckSideEffect(workercid, &sed, SE_AWAITLOCALSTATUS)) != RPC2_SUCCESS) { BulkErr(workercid, &sed, rc, InBuff->Header.Opcode); assert(RPC2_Unbind(workercid) == RPC2_SUCCESS); continue; } else if (VerboseFlag) fprintf(stderr, "%ld bytes transferred\n", sed.Value.SmartFTPD.BytesTransferred); OutBuff->Header.ReturnCode = (long)sed.LocalStatus; OutBuff->Header.BodyLength = 0; break; } case 6: /* Store a random file */ { if (VerboseFlag) sed.Value.SmartFTPD.hashmark = myhashmark; else sed.Value.SmartFTPD.hashmark = 0; strcpy(sed.Value.SmartFTPD.FileInfo.ByName.LocalFileName, myprivatefile); sed.Value.SmartFTPD.FileInfo.ByName.ProtectionBits = 0644; sed.Value.SmartFTPD.TransmissionDirection = CLIENTTOSERVER; sed.Value.SmartFTPD.SeekOffset = 0; sed.Value.SmartFTPD.Tag = FILEBYNAME; if ((rc = RPC2_InitSideEffect(workercid, &sed)) != RPC2_SUCCESS) { BulkErr(workercid, &sed, rc, InBuff->Header.Opcode); } if ((rc = RPC2_CheckSideEffect(workercid, &sed, SE_AWAITLOCALSTATUS)) != RPC2_SUCCESS) { BulkErr(workercid, &sed, rc, InBuff->Header.Opcode); } else if (VerboseFlag) fprintf(stderr, "%ld bytes transferred\n", sed.Value.SmartFTPD.BytesTransferred); OutBuff->Header.ReturnCode = (long)sed.LocalStatus; OutBuff->Header.BodyLength = 0; break; } case 7: /* Unbind */ { OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = 0; break; } case 999: /* Quit */ { OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = 0; break; } default: /* unknown opcode */ OutBuff->Header.ReturnCode = RPC2_FAIL; OutBuff->Header.BodyLength = 1 + strlen("Get your act together"); strcpy((char *)OutBuff->Body, "Get your act together"); break; } i = RPC2_SendResponse(workercid, OutBuff); if (i != RPC2_SUCCESS) { printf ("\n%s: response for opcode %d on connection %#x failed (%s) at %s", MYNAME, InBuff->Header.Opcode, workercid, RPC2_ErrorMsg(i), TimeNow()); DumpAndQuit(InBuff->Header.Opcode); } if (InBuff->Header.Opcode == 7) assert(RPC2_Unbind(workercid) == RPC2_SUCCESS); } }
static void *IOMGR(void *dummy) { for (;;) { int code; struct TM_Elem *earliest; struct timeval timeout, junk; bool woke_someone; FD_ZERO(&IOMGR_readfds); FD_ZERO(&IOMGR_writefds); FD_ZERO(&IOMGR_exceptfds); IOMGR_nfds = 0; /* Wake up anyone who has expired or who has received a Unix signal between executions. Keep going until we run out. */ do { woke_someone = FALSE; /* Wake up anyone waiting on signals. */ /* Note: SignalSignals() may yield! */ if (anySigsDelivered && SignalSignals ()) woke_someone = TRUE; FT_GetTimeOfDay(&junk, 0); /* force accurate time check */ TM_Rescan(Requests); for (;;) { struct IoRequest *req; struct TM_Elem *expired; expired = TM_GetExpired(Requests); if (expired == NULL) break; woke_someone = TRUE; req = (struct IoRequest *) expired -> BackPointer; #ifdef DEBUG if (lwp_debug != 0) puts("[Polling SELECT]"); #endif /* DEBUG */ /* no data ready */ if (req->readfds) FD_N_ZERO(req->nfds, req->readfds); if (req->writefds) FD_N_ZERO(req->nfds, req->writefds); if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds); req->nfds = 0; req->result = 0; /* no fds ready */ TM_Remove(Requests, &req->timeout); #ifdef DEBUG req -> timeout.Next = (struct TM_Elem *) 2; req -> timeout.Prev = (struct TM_Elem *) 2; #endif /* DEBUG */ LWP_QSignal(req->pid); req->pid->iomgrRequest = 0; } if (woke_someone) LWP_DispatchProcess(); } while (woke_someone); /* Collect requests & update times */ FD_ZERO(&IOMGR_readfds); FD_ZERO(&IOMGR_writefds); FD_ZERO(&IOMGR_exceptfds); IOMGR_nfds = 0; FOR_ALL_ELTS(r, Requests, { struct IoRequest *req; req = (struct IoRequest *) r -> BackPointer; FDSetSet(req->nfds, &IOMGR_readfds, req->readfds); FDSetSet(req->nfds, &IOMGR_writefds, req->writefds); FDSetSet(req->nfds, &IOMGR_exceptfds, req->exceptfds); if (req->nfds > IOMGR_nfds) IOMGR_nfds = req->nfds; }) earliest = TM_GetEarliest(Requests); if (earliest != NULL) { timeout = earliest -> TimeLeft; /* Do select */ #ifdef DEBUG if (lwp_debug != 0) { #ifdef AFS_NT40_ENV int idbg; printf("[Read Select:"); if (IOMGR_readfds.fd_count == 0) printf(" none]\n"); else { for (idbg=0; idbg<IOMGR_readfds.fd_count; idbg++) printf(" %d", IOMGR_readfds.fd_array[idbg]); printf("]\n"); } printf("[Write Select:"); if (IOMGR_writefds.fd_count == 0) printf(" none]\n"); else { for (idbg=0; idbg<IOMGR_writefds.fd_count; idbg++) printf(" %d", IOMGR_writefds.fd_array[idbg]); printf("]\n"); } printf("[Except Select:"); if (IOMGR_exceptfds.fd_count == 0) printf(" none]\n"); else { for (idbg=0; idbg<IOMGR_exceptfds.fd_count; idbg++) printf(" %d", IOMGR_exceptfds.fd_array[idbg]); printf("]\n"); } #else /* Only prints first 32. */ printf("[select(%d, 0x%x, 0x%x, 0x%x, ", IOMGR_nfds, *(int*)&IOMGR_readfds, *(int*)&IOMGR_writefds, *(int*)&IOMGR_exceptfds); #endif /* AFS_NT40_ENV */ if (timeout.tv_sec == -1 && timeout.tv_usec == -1) puts("INFINITE)]"); else printf("<%d, %d>)]\n", timeout.tv_sec, timeout.tv_usec); } #endif /* DEBUG */ iomgr_timeout = timeout; if (timeout.tv_sec == -1 && timeout.tv_usec == -1) { /* infinite, sort of */ iomgr_timeout.tv_sec = 100000000; iomgr_timeout.tv_usec = 0; } #if defined(AFS_NT40_ENV) || defined(AFS_LINUX24_ENV) /* On NT, signals don't interrupt a select call. So this can potentially * lead to long wait times before a signal is honored. To avoid this we * dont do select() for longer than IOMGR_MAXWAITTIME (5 secs) */ /* Whereas Linux seems to sometimes "lose" signals */ if (iomgr_timeout.tv_sec > (IOMGR_MAXWAITTIME - 1)) { iomgr_timeout.tv_sec = IOMGR_MAXWAITTIME; iomgr_timeout.tv_usec = 0; } #endif /* NT40 */ /* Check one last time for a signal delivery. If one comes after this, the signal handler will set iomgr_timeout to zero, causing the select to return immediately. The timer package won't return a zero timeval because all of those guys were handled above. I'm assuming that the kernel masks signals while it's picking up the parameters to select. This may a bad assumption. -DN */ if (anySigsDelivered) continue; /* go to the top and handle them. */ #ifdef AFS_NT40_ENV if (IOMGR_readfds.fd_count == 0 && IOMGR_writefds.fd_count == 0 && IOMGR_exceptfds.fd_count == 0) { DWORD stime; code = 0; if (iomgr_timeout.tv_sec || iomgr_timeout.tv_usec) { stime = iomgr_timeout.tv_sec * 1000 + iomgr_timeout.tv_usec/1000; if (!stime) stime = 1; Sleep(stime); } } else #endif { /* select runs much faster if 0's are passed instead of &0s */ code = select(IOMGR_nfds, (FDSetEmpty(IOMGR_nfds, &IOMGR_readfds)) ? (fd_set*)0 : &IOMGR_readfds, (FDSetEmpty(IOMGR_nfds, &IOMGR_writefds)) ? (fd_set*)0 : &IOMGR_writefds, (FDSetEmpty(IOMGR_nfds, &IOMGR_exceptfds)) ? (fd_set*)0 : &IOMGR_exceptfds, &iomgr_timeout); } if (code < 0) { int e=1; #if defined(AFS_SUN_ENV) /* Tape drives on Sun boxes do not support select and return ENXIO */ if (errno == ENXIO) e=0, code=1; #endif #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV) /* For SGI and SVR4 - poll & select can return EAGAIN ... */ if (errno == EAGAIN) e=0; #endif #if defined(AFS_SUN5_ENV) /* On sun4x_55, select doesn't block signal. It could be interupted by a signal that changes iomgr_timeout, and then select returns with EINVAL. In this case, we need to retry. */ if (errno==EINVAL && anySigsDelivered) e = 0; #endif /* AFS_SUN5_ENV */ if ((errno != EINTR) && e) { #ifndef AFS_NT40_ENV int i; for(i=0; i<FD_SETSIZE; i++) { if (fcntl(i, F_GETFD, 0) < 0 && errno == EBADF) FD_SET(i, &openMask); } #endif iomgr_errno = errno; opr_abort(); } } /* See what happened */ if (code > 0) { /* Action -- wake up everyone involved */ SignalIO(IOMGR_nfds, &IOMGR_readfds, &IOMGR_writefds, &IOMGR_exceptfds, code); } else if (code == 0 && (iomgr_timeout.tv_sec != 0 || iomgr_timeout.tv_usec != 0)) { /* Real timeout only if signal handler hasn't set iomgr_timeout to zero. */ #if defined(AFS_NT40_ENV) || defined(AFS_LINUX24_ENV) /* On NT, real timeout only if above and if iomgr_timeout * interval is equal to timeout interval (i.e., not adjusted * to check for pseudo-signals). */ /* And also for Linux as above */ if (iomgr_timeout.tv_sec != timeout.tv_sec || iomgr_timeout.tv_usec != timeout.tv_usec) { /* signal check interval timed out; not real timeout */ continue; } #endif /* AFS_NT40_ENV */ FT_GetTimeOfDay(&junk, 0); SignalTimeout(code, &timeout); } } LWP_DispatchProcess(); }