📄 unix.c
字号:
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); if (_pr_md_idle_cpus > 1) _PR_MD_WAKEUP_WAITER(thred); } } _PR_THREAD_UNLOCK(thred); _PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds; PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0); } } } else if (nfd == -1) { PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno)); }#else if (nfd > 0) { 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; PRInt16 in_flags = pds->in_flags; PRInt16 out_flags = 0; PR_ASSERT(osfd >= 0 || in_flags == 0); if ((in_flags & _PR_UNIX_POLL_READ) && FD_ISSET(osfd, rp)) { out_flags |= _PR_UNIX_POLL_READ; } if ((in_flags & _PR_UNIX_POLL_WRITE) && FD_ISSET(osfd, wp)) { out_flags |= _PR_UNIX_POLL_WRITE; } if ((in_flags & _PR_UNIX_POLL_EXCEPT) && FD_ISSET(osfd, ep)) { out_flags |= _PR_UNIX_POLL_EXCEPT; } pds->out_flags = out_flags; if (out_flags) { notify = PR_TRUE; } if (osfd > pq_max_osfd) { pq_max_osfd = osfd; } } if (notify == PR_TRUE) { PRIntn pri; PRThread *thred; 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)); } } /* * Because this thread can run on a different cpu right * after being added to the run queue, do not dereference * pq */ thred = pq->thr; _PR_THREAD_LOCK(thred); if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) { _PRCPU *cpu = thred->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; pq->thr->cpu = cpu; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(pq->thr, cpu, pri); _PR_RUNQ_UNLOCK(cpu); if (_pr_md_idle_cpus > 1) _PR_MD_WAKEUP_WAITER(thred); } } _PR_THREAD_UNLOCK(thred); } 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 ((FD_ISSET(_pr_md_pipefd[0], rp)) && (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))); } if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];#ifdef IRIX if ((me->cpu->id == 0) && (FD_ISSET(_pr_irix_primoridal_cpu_fd[0], rp))) { 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); } } if (me->cpu->id == 0) { if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_irix_primoridal_cpu_fd[0]) _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0]; }#endif } } else if (nfd < 0) { if (errno == EBADF) { FindBadFDs(); } else { PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d", errno)); } } else { PR_ASSERT(nfd == 0); /* * compute the new value of _PR_IOQ_TIMEOUT */ 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); _PRUnixPollDesc *pds = pq->pds; _PRUnixPollDesc *epds = pds + pq->npds; PRInt32 pq_max_osfd = -1; q = q->next; for (; pds < epds; pds++) { if (pds->osfd > pq_max_osfd) { pq_max_osfd = pds->osfd; } } 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 /* _PR_USE_POLL */ _PR_MD_IOQ_UNLOCK();}void _MD_Wakeup_CPUs(){ PRInt32 rv, data; data = 0; rv = write(_pr_md_pipefd[1], &data, 1); while ((rv < 0) && (errno == EAGAIN)) { /* * pipe full, read all data in pipe to empty it */ while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) { } PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN))); rv = write(_pr_md_pipefd[1], &data, 1); }}void _MD_InitCPUS(){ PRInt32 rv, flags; PRThread *me = _MD_CURRENT_THREAD(); rv = pipe(_pr_md_pipefd); PR_ASSERT(rv == 0); _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];#ifndef _PR_USE_POLL FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu));#endif flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0); fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK); flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0); fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK);}/*** Unix SIGALRM (clock) signal handler*/static void ClockInterruptHandler(){ int olderrno; PRUintn pri; _PRCPU *cpu = _PR_MD_CURRENT_CPU(); PRThread *me = _MD_CURRENT_THREAD();#ifdef SOLARIS if (!me || _PR_IS_NATIVE_THREAD(me)) { _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK; return; }#endif if (_PR_MD_GET_INTSOFF() != 0) { cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK; return; } _PR_MD_SET_INTSOFF(1); olderrno = errno; _PR_ClockInterrupt(); errno = olderrno; /* ** If the interrupt wants a resched or if some other thread at ** the same priority needs the cpu, reschedule. */ pri = me->priority; if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) {#ifdef _PR_NO_PREEMPT cpu->resched = PR_TRUE; if (pr_interruptSwitchHook) { (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg); }#else /* _PR_NO_PREEMPT */ /* ** Re-enable unix interrupts (so that we can use ** setjmp/longjmp for context switching without having to ** worry about the signal state) */ sigprocmask(SIG_SETMASK, &empty_set, 0); PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch")); if(!(me->flags & _PR_IDLE_THREAD)) { _PR_THREAD_LOCK(me); me->state = _PR_RUNNABLE; me->cpu = cpu; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(me, cpu, pri); _PR_RUNQ_UNLOCK(cpu); _PR_THREAD_UNLOCK(me); } else me->state = _PR_RUNNABLE; _MD_SWITCH_CONTEXT(me); PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch"));#endif /* _PR_NO_PREEMPT */ } /* * Because this thread could be running on a different cpu after * a context switch the current cpu should be accessed and the * value of the 'cpu' variable should not be used. */ _PR_MD_SET_INTSOFF(0);}/* * On HP-UX 9, we have to use the sigvector() interface to restart * interrupted system calls, because sigaction() does not have the * SA_RESTART flag. */#ifdef HPUX9static void HPUX9_ClockInterruptHandler( int sig, int code, struct sigcontext *scp){ ClockInterruptHandler(); scp->sc_syscall_action = SIG_RESTART;}#endif /* HPUX9 *//* # of milliseconds per clock tick that we will use */#define MSEC_PER_TICK 50void _MD_StartInterrupts(){ char *eval; if ((eval = getenv("NSPR_NOCLOCK")) != NULL) { if (atoi(eval) == 0) _nspr_noclock = 0; else _nspr_noclock = 1; }#ifndef _PR_NO_CLOCK_TIMER if (!_nspr_noclock) { _MD_EnableClockInterrupts(); }#endif}void _MD_StopInterrupts(){ sigprocmask(SIG_BLOCK, &timer_set, 0);}void _MD_EnableClockInterrupts(){ struct itimerval itval; extern PRUintn _pr_numCPU;#ifdef HPUX9 struct sigvec vec; vec.sv_handler = (void (*)()) HPUX9_ClockInterruptHandler; vec.sv_mask = 0; vec.sv_flags = 0; sigvector(SIGALRM, &vec, 0);#else struct sigaction vtact; vtact.sa_handler = (void (*)()) ClockInterruptHandler; sigemptyset(&vtact.sa_mask); vtact.sa_flags = SA_RESTART; sigaction(SIGALRM, &vtact, 0);#endif /* HPUX9 */ PR_ASSERT(_pr_numCPU == 1); itval.it_interval.tv_sec = 0; itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC; itval.it_value = itval.it_interval; setitimer(ITIMER_REAL, &itval, 0);}void _MD_DisableClockInterrupts(){ struct itimerval itval; extern PRUintn _pr_numCPU; PR_ASSERT(_pr_numCPU == 1); itval.it_interval.tv_sec = 0; itval.it_interval.tv_usec = 0; itval.it_value = itval.it_interval; setitimer(ITIMER_REAL, &itval, 0);}void _MD_BlockClockInterrupts(){ sigprocmask(SIG_BLOCK, &timer_set, 0);}void _MD_UnblockClockInterrupts(){ sigprocmask(SIG_UNBLOCK, &timer_set, 0);}void _MD_MakeNonblock(PRFileDesc *fd){ PRInt32 osfd = fd->secret->md.osfd; int flags; if (osfd <= 2) { /* Don't mess around with stdin, stdout or stderr */ return; } flags = fcntl(osfd, F_GETFL, 0); /* * Use O_NONBLOCK (POSIX-style non-blocking I/O) whenever possible. * On SunOS 4, we must use FNDELAY (BSD-style non-blocking I/O), * otherwise connect() still blocks and can be
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -