int nfds;
int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)#endif{    int i;    int nfds;    int npds;    void *pollset;    PRPollDesc *pd;    PRFileDesc *prfd;    PRFilePrivate *secret;    PRIntervalTime timeout;    int retVal;#if defined(HPUX9) || defined(AIX4_1)    fd_set *rd = (fd_set*) rl;    fd_set *wr = (fd_set*) wl;    fd_set *ex = (fd_set*) el;#endif    fd_set r, w, x;#if 0    /*     * Easy special case: zero timeout.  Simply call the native     * select() with no fear of blocking.     */    if (tv != NULL && tv->tv_sec == 0 && tv->tv_usec == 0) {#if defined(HPUX9) || defined(AIX4_1)        return _MD_SELECT(width, rl, wl, el, tv);#else        return _MD_SELECT(width, rd, wr, ex, tv);#endif    }#endif	if (!_pr_initialized)		_PR_ImplicitInitialization();		#ifndef _PR_LOCAL_THREADS_ONLY    if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) {	nfds = _MD_SELECT(width, rd, wr, ex, tv);		return(nfds);    }#endif    if (width < 0 || width > FD_SETSIZE) {	errno = EINVAL;	return -1;    }    /* Compute timeout */    if (tv) {	/*	 * These acceptable ranges for t_sec and t_usec are taken	 * from the select() man pages.	 */	if (tv->tv_sec < 0 || tv->tv_sec > 100000000		|| tv->tv_usec < 0 || tv->tv_usec >= 1000000) {	    errno = EINVAL;	    return -1;	}	/* Convert microseconds to ticks */	timeout = PR_MicrosecondsToInterval(1000000*tv->tv_sec + tv->tv_usec);    } else {	/* tv being a NULL pointer means blocking indefinitely */	timeout = PR_INTERVAL_NO_TIMEOUT;    }    /* Check for no descriptors case (just doing a timeout) */    if ((!rd && !wr && !ex) || !width) {	PR_Sleep(timeout);	return 0;    }    if (rd) { COPY_SET(&r, rd, width); }    if (wr) { COPY_SET(&w, wr, width); }    if (ex) { COPY_SET(&x, ex, width); }    /*     * Set up for PR_Poll().  The PRPollDesc array is allocated     * dynamically.  If this turns out to have high performance     * penalty, one can change to use a large PRPollDesc array     * on the stack, and allocate dynamically only when it turns     * out to be not large enough.     *     * I allocate an array of size 'width', which is the maximum     * number of fds we may need to poll.     */    pollset = PR_CALLOC(width *        (sizeof(PRPollDesc) + sizeof(PRFileDesc) + sizeof(PRFilePrivate)));    if (!pollset) {        errno = ENOMEM;        return -1;    }    pd = (PRPollDesc*)pollset;    prfd = (PRFileDesc*)(&pd[width]);    secret = (PRFilePrivate*)(&prfd[width]);    for (npds = 0, i = 0; i < width; i++) {	    int in_flags = 0;	    if (rd && FD_ISSET(i, &r)) {	        in_flags |= PR_POLL_READ;	    }	    if (wr && FD_ISSET(i, &w)) {	        in_flags |= PR_POLL_WRITE;	    }	    if (ex && FD_ISSET(i, &x)) {	        in_flags |= PR_POLL_EXCEPT;	    }	    if (in_flags) {	        prfd[npds].secret = &secret[npds];	        prfd[npds].secret->state = _PR_FILEDESC_OPEN;	        prfd[npds].secret->md.osfd = i;	        prfd[npds].methods = &_pr_fileMethods;	        pd[npds].fd = &prfd[npds];	        pd[npds].in_flags = in_flags;	        pd[npds].out_flags = 0;            npds += 1;	    }    }  /* see comments in ns/cmd/xfe/mozilla.c (look for "PR_XGetXtHackFD") */    {	     int needToLockXAgain;      needToLockXAgain = 0;     if (rd && (_pr_xt_hack_fd != -1) && 		FD_ISSET(_pr_xt_hack_fd, &r) && PR_XIsLocked() &&		(!_pr_xt_hack_okayToReleaseXLock || _pr_xt_hack_okayToReleaseXLock())) { 	PR_XUnlock(); 	needToLockXAgain = 1;     }    /* This is the potentially blocking step */    retVal = PR_Poll(pd, npds, timeout);     if (needToLockXAgain) { 	PR_XLock();     }   }    if (retVal > 0)    {        /* Compute select results */        if (rd) ZAP_SET(rd, width);        if (wr) ZAP_SET(wr, width);        if (ex) ZAP_SET(ex, width);        /*         * The return value can be either the number of ready file         * descriptors or the number of set bits in the three fd_set's.         */        retVal = 0;  /* we're going to recompute */        for (i = 0; i < npds; ++i, pd++)        {	        if (pd->out_flags) {	            int nbits = 0;  /* The number of set bits on for this fd */	            if (pd->out_flags & PR_POLL_NVAL) {		            errno = EBADF;		            PR_LOG(_pr_io_lm, PR_LOG_ERROR,		                   ("select returns EBADF for %d", pd->fd));		            retVal = -1;		            break;	            }	            if (rd && (pd->out_flags & PR_POLL_READ)) {		            FD_SET(pd->fd->secret->md.osfd, rd);		            nbits++;	            }	                if (wr && (pd->out_flags & PR_POLL_WRITE)) {		            FD_SET(pd->fd->secret->md.osfd, wr);		            nbits++;	            }	                if (ex && (pd->out_flags & PR_POLL_EXCEPT)) {		            FD_SET(pd->fd->secret->md.osfd, ex);		            nbits++;	            }	            PR_ASSERT(nbits > 0);#if defined(HPUX) || defined(SOLARIS) || defined(SUNOS4) || defined(OSF1) || defined(AIX)                retVal += nbits;#else /* IRIX */                retVal += 1;#endif	        }        }    }    PR_ASSERT(tv || retVal != 0);    PR_LOG(_pr_io_lm, PR_LOG_MIN, ("select returns %d", retVal));    PR_DELETE(pollset);    return retVal;}