📄 unix.c
字号:
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 + -