Beispiel #1
0
/* Return value indicates whether anyone was signalled. */
static int IOMGR_CheckSignals() {
    if (!anySigsDelivered) return(FALSE);

    return(SignalSignals());
}
Beispiel #2
0
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();
    }