⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unix.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (-1 == rv) {        PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());        return PR_FAILURE;    }    return PR_SUCCESS;}void _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported){    if (imported) {        fd->secret->inheritable = _PR_TRI_UNKNOWN;    } else {        /* By default, a Unix fd is not closed on exec. */#ifdef DEBUG        {            int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);            PR_ASSERT(0 == flags);        }#endif        fd->secret->inheritable = _PR_TRI_TRUE;    }}/************************************************************************/#if !defined(_PR_USE_POLL)/*** Scan through io queue and find any bad fd's that triggered the error** from _MD_SELECT*/static void FindBadFDs(void){    PRCList *q;    PRThread *me = _MD_CURRENT_THREAD();    PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));    q = (_PR_IOQ(me->cpu)).next;    _PR_IOQ_MAX_OSFD(me->cpu) = -1;    _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;    while (q != &_PR_IOQ(me->cpu)) {        PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);        PRBool notify = PR_FALSE;        _PRUnixPollDesc *pds = pq->pds;        _PRUnixPollDesc *epds = pds + pq->npds;        PRInt32 pq_max_osfd = -1;        q = q->next;        for (; pds < epds; pds++) {            PRInt32 osfd = pds->osfd;            pds->out_flags = 0;            PR_ASSERT(osfd >= 0 || pds->in_flags == 0);            if (pds->in_flags == 0) {                continue;  /* skip this fd */            }            if (fcntl(osfd, F_GETFL, 0) == -1) {                /* Found a bad descriptor, remove it from the fd_sets. */                PR_LOG(_pr_io_lm, PR_LOG_MAX,                    ("file descriptor %d is bad", osfd));                pds->out_flags = _PR_UNIX_POLL_NVAL;                notify = PR_TRUE;            }            if (osfd > pq_max_osfd) {                pq_max_osfd = osfd;            }        }        if (notify) {            PRIntn pri;            PR_REMOVE_LINK(&pq->links);            pq->on_ioq = PR_FALSE;            /*         * Decrement the count of descriptors for each desciptor/event         * because this I/O request is being removed from the         * ioq         */            pds = pq->pds;            for (; pds < epds; pds++) {                PRInt32 osfd = pds->osfd;                PRInt16 in_flags = pds->in_flags;                PR_ASSERT(osfd >= 0 || in_flags == 0);                if (in_flags & _PR_UNIX_POLL_READ) {                    if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)                        FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));                }                if (in_flags & _PR_UNIX_POLL_WRITE) {                    if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)                        FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));                }                if (in_flags & _PR_UNIX_POLL_EXCEPT) {                    if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)                        FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));                }            }            _PR_THREAD_LOCK(pq->thr);            if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {                _PRCPU *cpu = pq->thr->cpu;                _PR_SLEEPQ_LOCK(pq->thr->cpu);                _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);                _PR_SLEEPQ_UNLOCK(pq->thr->cpu);				if (pq->thr->flags & _PR_SUSPENDING) {				    /*				     * set thread state to SUSPENDED;				     * a Resume operation on the thread				     * will move it to the runQ				     */				    pq->thr->state = _PR_SUSPENDED;				    _PR_MISCQ_LOCK(pq->thr->cpu);				    _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);				    _PR_MISCQ_UNLOCK(pq->thr->cpu);				} else {				    pri = pq->thr->priority;				    pq->thr->state = _PR_RUNNABLE;				    _PR_RUNQ_LOCK(cpu);				    _PR_ADD_RUNQ(pq->thr, cpu, pri);				    _PR_RUNQ_UNLOCK(cpu);				}            }            _PR_THREAD_UNLOCK(pq->thr);        } else {            if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))                _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;            if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)                _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;        }    }    if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {        if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])            _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];    }}#endif  /* !defined(_PR_USE_POLL) *//************************************************************************//*** Called by the scheduler when there is nothing to do. This means that** all threads are blocked on some monitor somewhere.**** Note: this code doesn't release the scheduler lock.*//*** Pause the current CPU. longjmp to the cpu's pause stack**** This must be called with the scheduler locked*/void _MD_PauseCPU(PRIntervalTime ticks){    PRThread *me = _MD_CURRENT_THREAD();#ifdef _PR_USE_POLL    int timeout;    struct pollfd *pollfds;    /* an array of pollfd structures */    struct pollfd *pollfdPtr;    /* a pointer that steps through the array */    unsigned long npollfds;     /* number of pollfd structures in array */    unsigned long pollfds_size;    int nfd;                    /* to hold the return value of poll() */#else    struct timeval timeout, *tvp;    fd_set r, w, e;    fd_set *rp, *wp, *ep;    PRInt32 max_osfd, nfd;#endif  /* _PR_USE_POLL */    PRInt32 rv;    PRCList *q;    PRUint32 min_timeout;    sigset_t oldset;#ifdef IRIXextern sigset_t ints_off;#endif    PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);    _PR_MD_IOQ_LOCK();#ifdef _PR_USE_POLL    /* Build up the pollfd structure array to wait on */    /* Find out how many pollfd structures are needed */    npollfds = _PR_IOQ_OSFD_CNT(me->cpu);    PR_ASSERT(npollfds >= 0);    /*     * We use a pipe to wake up a native thread.  An fd is needed     * for the pipe and we poll it for reading.     */    if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {        npollfds++;#ifdef	IRIX		/*		 * On Irix, a second pipe is used to cause the primordial cpu to		 * wakeup and exit, when the process is exiting because of a call		 * to exit/PR_ProcessExit.		 */		if (me->cpu->id == 0) {        	npollfds++;		}#endif	}    /*     * if the cpu's pollfd array is not big enough, release it and allocate a new one     */    if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) {        if (_PR_IOQ_POLLFDS(me->cpu) != NULL)            PR_DELETE(_PR_IOQ_POLLFDS(me->cpu));        pollfds_size =  PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds);        pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd));        _PR_IOQ_POLLFDS(me->cpu) = pollfds;        _PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size;    } else {        pollfds = _PR_IOQ_POLLFDS(me->cpu);    }    pollfdPtr = pollfds;    /*     * If we need to poll the pipe for waking up a native thread,     * the pipe's fd is the first element in the pollfds array.     */    if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {        pollfdPtr->fd = _pr_md_pipefd[0];        pollfdPtr->events = POLLIN;        pollfdPtr++;#ifdef	IRIX		/*		 * On Irix, the second element is the exit pipe		 */		if (me->cpu->id == 0) {			pollfdPtr->fd = _pr_irix_primoridal_cpu_fd[0];			pollfdPtr->events = POLLIN;			pollfdPtr++;		}#endif    }    min_timeout = PR_INTERVAL_NO_TIMEOUT;    for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {        PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);        _PRUnixPollDesc *pds = pq->pds;        _PRUnixPollDesc *epds = pds + pq->npds;        if (pq->timeout < min_timeout) {            min_timeout = pq->timeout;        }        for (; pds < epds; pds++, pollfdPtr++) {            /*         * Assert that the pollfdPtr pointer does not go         * beyond the end of the pollfds array         */            PR_ASSERT(pollfdPtr < pollfds + npollfds);            pollfdPtr->fd = pds->osfd;            /* direct copy of poll flags */            pollfdPtr->events = pds->in_flags;        }    }    _PR_IOQ_TIMEOUT(me->cpu) = min_timeout;#else    /*     * assigment of fd_sets     */    r = _PR_FD_READ_SET(me->cpu);    w = _PR_FD_WRITE_SET(me->cpu);    e = _PR_FD_EXCEPTION_SET(me->cpu);    rp = &r;    wp = &w;    ep = &e;    max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;    min_timeout = _PR_IOQ_TIMEOUT(me->cpu);#endif  /* _PR_USE_POLL */    /*    ** Compute the minimum timeout value: make it the smaller of the    ** timeouts specified by the i/o pollers or the timeout of the first    ** sleeping thread.    */    q = _PR_SLEEPQ(me->cpu).next;    if (q != &_PR_SLEEPQ(me->cpu)) {        PRThread *t = _PR_THREAD_PTR(q);        if (t->sleep < min_timeout) {            min_timeout = t->sleep;        }    }    if (min_timeout > ticks) {        min_timeout = ticks;    }#ifdef _PR_USE_POLL    if (min_timeout == PR_INTERVAL_NO_TIMEOUT)        timeout = -1;    else        timeout = PR_IntervalToMilliseconds(min_timeout);#else    if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {        tvp = NULL;    } else {        timeout.tv_sec = PR_IntervalToSeconds(min_timeout);        timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)            % PR_USEC_PER_SEC;        tvp = &timeout;    }#endif  /* _PR_USE_POLL */    _PR_MD_IOQ_UNLOCK();    _MD_CHECK_FOR_EXIT();    /*     * check for i/o operations     */#ifndef _PR_NO_CLOCK_TIMER    /*     * Disable the clock interrupts while we are in select, if clock interrupts     * are enabled. Otherwise, when the select/poll calls are interrupted, the     * timer value starts ticking from zero again when the system call is restarted.     */#ifdef IRIX    /*     * SIGCHLD signal is used on Irix to detect he termination of an     * sproc by SIGSEGV, SIGBUS or SIGABRT signals when     * _nspr_terminate_on_error is set.     */    if ((!_nspr_noclock) || (_nspr_terminate_on_error))#else        if (!_nspr_noclock)#endif    /* IRIX */#ifdef IRIX    sigprocmask(SIG_BLOCK, &ints_off, &oldset);#else    PR_ASSERT(sigismember(&timer_set, SIGALRM));    sigprocmask(SIG_BLOCK, &timer_set, &oldset);#endif    /* IRIX */#endif  /* !_PR_NO_CLOCK_TIMER */#ifndef _PR_USE_POLL    PR_ASSERT(FD_ISSET(_pr_md_pipefd[0],rp));    nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);#else    nfd = _MD_POLL(pollfds, npollfds, timeout);#endif  /* !_PR_USE_POLL */#ifndef _PR_NO_CLOCK_TIMER#ifdef IRIX    if ((!_nspr_noclock) || (_nspr_terminate_on_error))#else        if (!_nspr_noclock)#endif    /* IRIX */    sigprocmask(SIG_SETMASK, &oldset, 0);#endif  /* !_PR_NO_CLOCK_TIMER */    _MD_CHECK_FOR_EXIT();#ifdef IRIX	_PR_MD_primordial_cpu();#endif    _PR_MD_IOQ_LOCK();    /*    ** Notify monitors that are associated with the selected descriptors.    */#ifdef _PR_USE_POLL    if (nfd > 0) {        pollfdPtr = pollfds;        if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {            /*			 * Assert that the pipe is the first element in the			 * pollfds array.			 */            PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]);            if ((pollfds[0].revents & POLLIN) && (nfd == 1)) {                /*				 * woken up by another thread; read all the data				 * in the pipe to empty the pipe				 */                while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf,                    PIPE_BUF)) == PIPE_BUF){                }                PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN)));            }            pollfdPtr++;#ifdef	IRIX			/*			 * On Irix, check to see if the primordial cpu needs to exit			 * to cause the process to terminate			 */			if (me->cpu->id == 0) {            	PR_ASSERT(pollfds[1].fd == _pr_irix_primoridal_cpu_fd[0]);				if (pollfdPtr->revents & POLLIN) {					if (_pr_irix_process_exit) {						/*						 * process exit due to a call to PR_ProcessExit						 */						prctl(PR_SETEXITSIG, SIGKILL);						_exit(_pr_irix_process_exit_code);					} else {						while ((rv = read(_pr_irix_primoridal_cpu_fd[0],							_pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) {						}						PR_ASSERT(rv > 0);					}				}				pollfdPtr++;			}#endif        }        for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {            PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);            PRBool notify = PR_FALSE;            _PRUnixPollDesc *pds = pq->pds;            _PRUnixPollDesc *epds = pds + pq->npds;            for (; pds < epds; pds++, pollfdPtr++) {                /*                  * Assert that the pollfdPtr pointer does not go beyond                  * the end of the pollfds array.                  */                PR_ASSERT(pollfdPtr < pollfds + npollfds);                /*                 * Assert that the fd's in the pollfds array (stepped                 * through by pollfdPtr) are in the same order as                 * the fd's in _PR_IOQ() (stepped through by q and pds).                 * This is how the pollfds array was created earlier.                 */                PR_ASSERT(pollfdPtr->fd == pds->osfd);                pds->out_flags = pollfdPtr->revents;                /* Negative fd's are ignored by poll() */                if (pds->osfd >= 0 && pds->out_flags) {                    notify = PR_TRUE;                }            }            if (notify) {                PRIntn pri;                PRThread *thred;                PR_REMOVE_LINK(&pq->links);                pq->on_ioq = PR_FALSE;                thred = pq->thr;                _PR_THREAD_LOCK(thred);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -