Index: sys/kern/kern_condvar.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_condvar.c,v retrieving revision 1.52 diff -u -r1.52 kern_condvar.c --- sys/kern/kern_condvar.c 12 Oct 2004 18:36:19 -0000 1.52 +++ sys/kern/kern_condvar.c 24 Feb 2006 04:29:49 -0000 @@ -147,7 +147,7 @@ { struct thread *td; struct proc *p; - int rval, sig; + int rval; WITNESS_SAVE_DECL(mp); td = curthread; @@ -173,28 +173,13 @@ sleepq_lock(cvp); - /* - * Don't bother sleeping if we are exiting and not the exiting - * thread or if our thread is marked as interrupted. - */ - mtx_lock_spin(&sched_lock); - rval = thread_sleep_check(td); - mtx_unlock_spin(&sched_lock); - if (rval != 0) { - sleepq_release(cvp); - return (rval); - } - cvp->cv_waiters++; DROP_GIANT(); mtx_unlock(mp); sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR | SLEEPQ_INTERRUPTIBLE); - sig = sleepq_catch_signals(cvp); rval = sleepq_wait_sig(cvp); - if (rval == 0) - rval = sleepq_calc_signal_retval(sig); #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) @@ -273,7 +258,6 @@ struct thread *td; struct proc *p; int rval; - int sig; WITNESS_SAVE_DECL(mp); td = curthread; @@ -300,18 +284,6 @@ sleepq_lock(cvp); - /* - * Don't bother sleeping if we are exiting and not the exiting - * thread or if our thread is marked as interrupted. - */ - mtx_lock_spin(&sched_lock); - rval = thread_sleep_check(td); - mtx_unlock_spin(&sched_lock); - if (rval != 0) { - sleepq_release(cvp); - return (rval); - } - cvp->cv_waiters++; DROP_GIANT(); mtx_unlock(mp); @@ -319,10 +291,7 @@ sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR | SLEEPQ_INTERRUPTIBLE); sleepq_set_timeout(cvp, timo); - sig = sleepq_catch_signals(cvp); - rval = sleepq_timedwait_sig(cvp, sig != 0); - if (rval == 0) - rval = sleepq_calc_signal_retval(sig); + rval = sleepq_timedwait_sig(cvp); #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) Index: sys/kern/kern_kse.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_kse.c,v retrieving revision 1.214.2.4 diff -u -r1.214.2.4 kern_kse.c --- sys/kern/kern_kse.c 6 Oct 2005 18:24:24 -0000 1.214.2.4 +++ sys/kern/kern_kse.c 24 Feb 2006 04:29:52 -0000 @@ -223,7 +223,7 @@ else td2->td_intrval = ERESTART; if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR)) - sleepq_abort(td2); + sleepq_abort(td2, td2->td_intrval); mtx_unlock_spin(&sched_lock); } PROC_UNLOCK(p); Index: sys/kern/kern_sig.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_sig.c,v retrieving revision 1.306.2.1 diff -u -r1.306.2.1 kern_sig.c --- sys/kern/kern_sig.c 7 Jan 2006 11:53:49 -0000 1.306.2.1 +++ sys/kern/kern_sig.c 24 Feb 2006 04:30:00 -0000 @@ -85,7 +85,8 @@ static int killpg1(struct thread *td, int sig, int pgid, int all); static int issignal(struct thread *p); static int sigprop(int sig); -static void tdsigwakeup(struct thread *td, int sig, sig_t action); +static void tdsigwakeup(struct thread *, int, sig_t, int); +static void sig_suspend_threads(struct thread *, struct proc *, int); static int filt_sigattach(struct knote *kn); static void filt_sigdetach(struct knote *kn); static int filt_signal(struct knote *kn, long hint); @@ -866,35 +867,38 @@ } } -again: +restart: for (i = 1; i <= _SIG_MAXSIG; ++i) { if (!SIGISMEMBER(waitset, i)) continue; - if (SIGISMEMBER(td->td_siglist, i)) { - SIGFILLSET(td->td_sigmask); - SIG_CANTMASK(td->td_sigmask); - SIGDELSET(td->td_sigmask, i); - mtx_lock(&ps->ps_mtx); - sig = cursig(td); - i = 0; - mtx_unlock(&ps->ps_mtx); - } else if (SIGISMEMBER(p->p_siglist, i)) { - if (p->p_flag & P_SA) { - p->p_flag |= P_SIGEVENT; - wakeup(&p->p_siglist); - } - SIGDELSET(p->p_siglist, i); - SIGADDSET(td->td_siglist, i); - SIGFILLSET(td->td_sigmask); - SIG_CANTMASK(td->td_sigmask); - SIGDELSET(td->td_sigmask, i); - mtx_lock(&ps->ps_mtx); - sig = cursig(td); - i = 0; - mtx_unlock(&ps->ps_mtx); + if (!SIGISMEMBER(td->td_siglist, i)) { + if (SIGISMEMBER(p->p_siglist, i)) { + if (p->p_flag & P_SA) { + p->p_flag |= P_SIGEVENT; + wakeup(&p->p_siglist); + } + SIGDELSET(p->p_siglist, i); + SIGADDSET(td->td_siglist, i); + } else + continue; } + + SIGFILLSET(td->td_sigmask); + SIG_CANTMASK(td->td_sigmask); + SIGDELSET(td->td_sigmask, i); + mtx_lock(&ps->ps_mtx); + sig = cursig(td); + mtx_unlock(&ps->ps_mtx); if (sig) goto out; + else { + /* + * Because cursig() may have stopped current thread, + * after it is resumed, things may have already been + * changed, it should rescan any pending signals. + */ + goto restart; + } } if (error) goto out; @@ -933,28 +937,35 @@ error = 0; } } - goto again; + goto restart; out: td->td_sigmask = savedmask; signotify(td); if (sig) { - sig_t action; - + SIGDELSET(td->td_siglist, sig); + bzero(info, sizeof(*info)); + info->si_signo = sig; + info->si_code = 0; error = 0; - mtx_lock(&ps->ps_mtx); - action = ps->ps_sigact[_SIG_IDX(sig)]; - mtx_unlock(&ps->ps_mtx); + #ifdef KTRACE - if (KTRPOINT(td, KTR_PSIG)) + if (KTRPOINT(td, KTR_PSIG)) { + sig_t action; + + mtx_lock(&ps->ps_mtx); + action = ps->ps_sigact[_SIG_IDX(sig)]; + mtx_unlock(&ps->ps_mtx); ktrpsig(sig, action, &td->td_sigmask, 0); + } #endif _STOPEVENT(p, S_SIG, sig); - SIGDELSET(td->td_siglist, sig); - bzero(info, sizeof(*info)); - info->si_signo = sig; - info->si_code = 0; + if (sig == SIGKILL) { + p->p_code = 0; + p->p_sig = sig; + sigexit(td, sig); + } } PROC_UNLOCK(p); return (error); @@ -1663,6 +1674,7 @@ struct thread *td0; register int prop; struct sigacts *ps; + int intrval; if (!_SIG_VALID(sig)) panic("do_tdsignal(): invalid signal"); @@ -1708,6 +1720,10 @@ action = SIG_CATCH; else action = SIG_DFL; + if (SIGISMEMBER(ps->ps_sigintr, sig)) + intrval = EINTR; + else + intrval = ERESTART; mtx_unlock(&ps->ps_mtx); if (prop & SA_CONT) { @@ -1850,7 +1866,7 @@ */ mtx_lock_spin(&sched_lock); if (TD_ON_SLEEPQ(td) && (td->td_flags & TDF_SINTR)) - sleepq_abort(td); + sleepq_abort(td, intrval); mtx_unlock_spin(&sched_lock); goto out; /* @@ -1860,7 +1876,7 @@ } else if (p->p_state == PRS_NORMAL) { if (p->p_flag & P_TRACED || action == SIG_CATCH) { mtx_lock_spin(&sched_lock); - tdsigwakeup(td, sig, action); + tdsigwakeup(td, sig, action, intrval); mtx_unlock_spin(&sched_lock); goto out; } @@ -1873,15 +1889,7 @@ p->p_flag |= P_STOPPED_SIG; p->p_xstat = sig; mtx_lock_spin(&sched_lock); - FOREACH_THREAD_IN_PROC(p, td0) { - if (TD_IS_SLEEPING(td0) && - (td0->td_flags & TDF_SINTR) && - !TD_IS_SUSPENDED(td0)) { - thread_suspend_one(td0); - } else if (td != td0) { - td0->td_flags |= TDF_ASTPENDING; - } - } + sig_suspend_threads(td, p, 1); thread_stopped(p); if (p->p_numthreads == p->p_suspcount) { SIGDELSET(p->p_siglist, p->p_xstat); @@ -1907,7 +1915,7 @@ runfast: mtx_lock_spin(&sched_lock); - tdsigwakeup(td, sig, action); + tdsigwakeup(td, sig, action, intrval); thread_unsuspend(p); mtx_unlock_spin(&sched_lock); out: @@ -1921,7 +1929,7 @@ * out of any sleep it may be in etc. */ static void -tdsigwakeup(struct thread *td, int sig, sig_t action) +tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval) { struct proc *p = td->td_proc; register int prop; @@ -1971,7 +1979,7 @@ if (td->td_priority > PUSER) sched_prio(td, PUSER); - sleepq_abort(td); + sleepq_abort(td, intrval); } else { /* * Other states do nothing with the signal immediately, @@ -1985,11 +1993,34 @@ } } +static void +sig_suspend_threads(struct thread *td, struct proc *p, int sending) +{ + struct thread *td2; + + PROC_LOCK_ASSERT(p, MA_OWNED); + mtx_assert(&sched_lock, MA_OWNED); + + FOREACH_THREAD_IN_PROC(p, td2) { + if ((TD_IS_SLEEPING(td2) || TD_IS_SWAPPED(td2)) && + (td2->td_flags & TDF_SINTR) && + !TD_IS_SUSPENDED(td2)) { + thread_suspend_one(td2); + } else { + if (sending || td != td2) + td2->td_flags |= TDF_ASTPENDING; +#ifdef SMP + if (TD_IS_RUNNING(td2) && td2 != td) + forward_signal(td2); +#endif + } + } +} + int ptracestop(struct thread *td, int sig) { struct proc *p = td->td_proc; - struct thread *td0; PROC_LOCK_ASSERT(p, MA_OWNED); WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, @@ -2014,15 +2045,7 @@ p->p_xthread = td; p->p_flag |= (P_STOPPED_SIG|P_STOPPED_TRACE); mtx_lock_spin(&sched_lock); - FOREACH_THREAD_IN_PROC(p, td0) { - if (TD_IS_SLEEPING(td0) && - (td0->td_flags & TDF_SINTR) && - !TD_IS_SUSPENDED(td0)) { - thread_suspend_one(td0); - } else if (td != td0) { - td0->td_flags |= TDF_ASTPENDING; - } - } + sig_suspend_threads(td, p, 0); stopme: thread_stopped(p); thread_suspend_one(td); @@ -2064,7 +2087,6 @@ struct sigacts *ps; sigset_t sigpending; int sig, prop, newsig; - struct thread *td0; p = td->td_proc; ps = p->p_sigacts; @@ -2179,15 +2201,7 @@ p->p_flag |= P_STOPPED_SIG; p->p_xstat = sig; mtx_lock_spin(&sched_lock); - FOREACH_THREAD_IN_PROC(p, td0) { - if (TD_IS_SLEEPING(td0) && - (td0->td_flags & TDF_SINTR) && - !TD_IS_SUSPENDED(td0)) { - thread_suspend_one(td0); - } else if (td != td0) { - td0->td_flags |= TDF_ASTPENDING; - } - } + sig_suspend_threads(td, p, 0); thread_stopped(p); thread_suspend_one(td); PROC_UNLOCK(p); Index: sys/kern/kern_synch.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_synch.c,v retrieving revision 1.270.2.1 diff -u -r1.270.2.1 kern_synch.c --- sys/kern/kern_synch.c 5 Dec 2005 20:14:40 -0000 1.270.2.1 +++ sys/kern/kern_synch.c 24 Feb 2006 04:30:00 -0000 @@ -124,7 +124,7 @@ { struct thread *td; struct proc *p; - int catch, rval, sig, flags; + int catch, rval, flags; WITNESS_SAVE_DECL(mtx); td = curthread; @@ -164,22 +164,11 @@ if (TD_ON_SLEEPQ(td)) sleepq_remove(td, td->td_wchan); + flags = SLEEPQ_MSLEEP; + if (catch) + flags |= SLEEPQ_INTERRUPTIBLE; + sleepq_lock(ident); - if (catch) { - /* - * Don't bother sleeping if we are exiting and not the exiting - * thread or if our thread is marked as interrupted. - */ - mtx_lock_spin(&sched_lock); - rval = thread_sleep_check(td); - mtx_unlock_spin(&sched_lock); - if (rval != 0) { - sleepq_release(ident); - if (mtx != NULL && priority & PDROP) - mtx_unlock(mtx); - return (rval); - } - } CTR5(KTR_PROC, "msleep: thread %p (pid %ld, %s) on %s (%p)", (void *)td, (long)p->p_pid, p->p_comm, wmesg, ident); @@ -199,16 +188,9 @@ * stopped, then td will no longer be on a sleep queue upon * return from cursig(). */ - flags = SLEEPQ_MSLEEP; - if (catch) - flags |= SLEEPQ_INTERRUPTIBLE; sleepq_add(ident, mtx, wmesg, flags); if (timo) sleepq_set_timeout(ident, timo); - if (catch) { - sig = sleepq_catch_signals(ident); - } else - sig = 0; /* * Adjust this thread's priority. @@ -218,7 +200,7 @@ mtx_unlock_spin(&sched_lock); if (timo && catch) - rval = sleepq_timedwait_sig(ident, sig != 0); + rval = sleepq_timedwait_sig(ident); else if (timo) rval = sleepq_timedwait(ident); else if (catch) @@ -227,8 +209,6 @@ sleepq_wait(ident); rval = 0; } - if (rval == 0 && catch) - rval = sleepq_calc_signal_retval(sig); #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) ktrcsw(0, 0); Index: sys/kern/kern_thr.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_thr.c,v retrieving revision 1.34.2.2 diff -u -r1.34.2.2 kern_thr.c --- sys/kern/kern_thr.c 16 Jan 2006 06:25:32 -0000 1.34.2.2 +++ sys/kern/kern_thr.c 24 Feb 2006 04:30:01 -0000 @@ -289,6 +289,7 @@ * call exit() in the trampoline when it returns. */ if (p->p_numthreads != 1) { + thread_stopped(p); thread_exit(); /* NOTREACHED */ } Index: sys/kern/kern_thread.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_thread.c,v retrieving revision 1.216.2.1 diff -u -r1.216.2.1 kern_thread.c --- sys/kern/kern_thread.c 4 Oct 2005 22:53:56 -0000 1.216.2.1 +++ sys/kern/kern_thread.c 24 Feb 2006 04:30:02 -0000 @@ -741,7 +741,7 @@ thread_unsuspend_one(td2); if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR)) - sleepq_abort(td2); + sleepq_abort(td2, EINTR); break; case SINGLE_BOUNDARY: if (TD_IS_SUSPENDED(td2) && @@ -749,7 +749,7 @@ thread_unsuspend_one(td2); if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR)) - sleepq_abort(td2); + sleepq_abort(td2, ERESTART); break; default: if (TD_IS_SUSPENDED(td2)) @@ -764,6 +764,11 @@ break; } } +#ifdef SMP + else if (TD_IS_RUNNING(td2) && td != td2) { + forward_signal(td2); + } +#endif } if (mode == SINGLE_EXIT) remaining = p->p_numthreads; @@ -868,12 +873,12 @@ return (0); /* Exempt from stopping. */ } if ((p->p_flag & P_SINGLE_EXIT) && return_instead) - return (1); + return (EINTR); /* Should we goto user boundary if we didn't come from there? */ if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE && (p->p_flag & P_SINGLE_BOUNDARY) && return_instead) - return (1); + return (ERESTART); mtx_lock_spin(&sched_lock); thread_stopped(p); Index: sys/kern/subr_sleepqueue.c =================================================================== RCS file: /home/ncvs/src/sys/kern/subr_sleepqueue.c,v retrieving revision 1.18.2.1 diff -u -r1.18.2.1 subr_sleepqueue.c --- sys/kern/subr_sleepqueue.c 26 Sep 2005 19:43:37 -0000 1.18.2.1 +++ sys/kern/subr_sleepqueue.c 24 Feb 2006 04:30:06 -0000 @@ -313,8 +313,10 @@ mtx_lock_spin(&sched_lock); td->td_wchan = wchan; td->td_wmesg = wmesg; - if (flags & SLEEPQ_INTERRUPTIBLE) + if (flags & SLEEPQ_INTERRUPTIBLE) { td->td_flags |= TDF_SINTR; + td->td_flags &= ~TDF_SLEEPABORT; + } mtx_unlock_spin(&sched_lock); } @@ -340,55 +342,74 @@ /* * Marks the pending sleep of the current thread as interruptible and * makes an initial check for pending signals before putting a thread - * to sleep. + * to sleep. Return with sleep queue and scheduler lock held. */ -int +static int sleepq_catch_signals(void *wchan) { struct sleepqueue_chain *sc; struct sleepqueue *sq; struct thread *td; struct proc *p; - int sig; + struct sigacts *ps; + int sig, ret; td = curthread; - p = td->td_proc; + p = curproc; sc = SC_LOOKUP(wchan); mtx_assert(&sc->sc_lock, MA_OWNED); - MPASS(td->td_sleepqueue == NULL); MPASS(wchan != NULL); CTR3(KTR_PROC, "sleepq catching signals: thread %p (pid %ld, %s)", - (void *)td, (long)p->p_pid, p->p_comm); + (void *)td, (long)p->p_pid, p->p_comm); - /* Mark thread as being in an interruptible sleep. */ MPASS(td->td_flags & TDF_SINTR); - MPASS(TD_ON_SLEEPQ(td)); - sleepq_release(wchan); + mtx_unlock_spin(&sc->sc_lock); /* See if there are any pending signals for this thread. */ PROC_LOCK(p); - mtx_lock(&p->p_sigacts->ps_mtx); + ps = p->p_sigacts; + mtx_lock(&ps->ps_mtx); sig = cursig(td); - mtx_unlock(&p->p_sigacts->ps_mtx); - if (sig == 0 && thread_suspend_check(1)) - sig = SIGSTOP; - PROC_UNLOCK(p); + if (sig == 0) { + mtx_unlock(&ps->ps_mtx); + ret = thread_suspend_check(1); + MPASS(ret == 0 || ret == EINTR || ret == ERESTART); + } else { + if (SIGISMEMBER(ps->ps_sigintr, sig)) + ret = EINTR; + else + ret = ERESTART; + mtx_unlock(&ps->ps_mtx); + } + if (ret == 0) { + mtx_lock_spin(&sc->sc_lock); + /* + * Lock sched_lock before unlocking proc lock, + * without this, we could lose a race. + */ + mtx_lock_spin(&sched_lock); + PROC_UNLOCK(p); + if (!(td->td_flags & TDF_INTERRUPT)) + return (0); + /* KSE threads tried unblocking us. */ + ret = td->td_intrval; + mtx_unlock_spin(&sched_lock); + MPASS(ret == EINTR || ret == ERESTART); + } else { + PROC_UNLOCK(p); + mtx_lock_spin(&sc->sc_lock); + } /* - * If there were pending signals and this thread is still on - * the sleep queue, remove it from the sleep queue. If the - * thread was removed from the sleep queue while we were blocked - * above, then clear TDF_SINTR before returning. + * There were pending signals and this thread is still + * on the sleep queue, remove it from the sleep queue. */ - sleepq_lock(wchan); sq = sleepq_lookup(wchan); mtx_lock_spin(&sched_lock); - if (TD_ON_SLEEPQ(td) && sig != 0) + if (TD_ON_SLEEPQ(td)) sleepq_resume_thread(sq, td, -1); - else if (!TD_ON_SLEEPQ(td) && sig == 0) - td->td_flags &= ~TDF_SINTR; - mtx_unlock_spin(&sched_lock); - return (sig); + td->td_flags &= ~TDF_SINTR; + return (ret); } /* @@ -404,6 +425,7 @@ td = curthread; sc = SC_LOOKUP(wchan); mtx_assert(&sc->sc_lock, MA_OWNED); + mtx_assert(&sched_lock, MA_OWNED); /* * If we have a sleep queue, then we've already been woken up, so @@ -412,16 +434,13 @@ if (td->td_sleepqueue != NULL) { MPASS(!TD_ON_SLEEPQ(td)); mtx_unlock_spin(&sc->sc_lock); - mtx_lock_spin(&sched_lock); return; } /* * Otherwise, actually go to sleep. */ - mtx_lock_spin(&sched_lock); mtx_unlock_spin(&sc->sc_lock); - sched_sleep(td); TD_SET_SLEEPING(td); mi_switch(SW_VOL, NULL); @@ -480,52 +499,19 @@ mtx_assert(&sched_lock, MA_OWNED); td = curthread; - /* - * If TDF_SINTR is clear, then we were awakened while executing - * sleepq_catch_signals(). - */ - if (!(td->td_flags & TDF_SINTR)) - return (0); - /* We are no longer in an interruptible sleep. */ - td->td_flags &= ~TDF_SINTR; + if (td->td_flags & TDF_SINTR) + td->td_flags &= ~TDF_SINTR; - if (td->td_flags & TDF_INTERRUPT) + if (td->td_flags & TDF_SLEEPABORT) { + td->td_flags &= ~TDF_SLEEPABORT; return (td->td_intrval); - return (0); -} + } -/* - * If we were in an interruptible sleep and we weren't interrupted and - * didn't timeout, check to see if there are any pending signals and - * which return value we should use if so. The return value from an - * earlier call to sleepq_catch_signals() should be passed in as the - * argument. - */ -int -sleepq_calc_signal_retval(int sig) -{ - struct thread *td; - struct proc *p; - int rval; + if (td->td_flags & TDF_INTERRUPT) + return (td->td_intrval); - td = curthread; - p = td->td_proc; - PROC_LOCK(p); - mtx_lock(&p->p_sigacts->ps_mtx); - /* XXX: Should we always be calling cursig()? */ - if (sig == 0) - sig = cursig(td); - if (sig != 0) { - if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig)) - rval = EINTR; - else - rval = ERESTART; - } else - rval = 0; - mtx_unlock(&p->p_sigacts->ps_mtx); - PROC_UNLOCK(p); - return (rval); + return (0); } /* @@ -536,6 +522,7 @@ { MPASS(!(curthread->td_flags & TDF_SINTR)); + mtx_lock_spin(&sched_lock); sleepq_switch(wchan); mtx_unlock_spin(&sched_lock); } @@ -547,11 +534,18 @@ int sleepq_wait_sig(void *wchan) { + int rcatch; int rval; - sleepq_switch(wchan); + rcatch = sleepq_catch_signals(wchan); + if (rcatch == 0) + sleepq_switch(wchan); + else + sleepq_release(wchan); rval = sleepq_check_signals(); mtx_unlock_spin(&sched_lock); + if (rcatch) + return (rcatch); return (rval); } @@ -565,6 +559,7 @@ int rval; MPASS(!(curthread->td_flags & TDF_SINTR)); + mtx_lock_spin(&sched_lock); sleepq_switch(wchan); rval = sleepq_check_timeout(); mtx_unlock_spin(&sched_lock); @@ -576,18 +571,23 @@ * it is interrupted by a signal, or it times out waiting to be awakened. */ int -sleepq_timedwait_sig(void *wchan, int signal_caught) +sleepq_timedwait_sig(void *wchan) { - int rvalt, rvals; + int rcatch, rvalt, rvals; - sleepq_switch(wchan); + rcatch = sleepq_catch_signals(wchan); + if (rcatch == 0) + sleepq_switch(wchan); + else + sleepq_release(wchan); rvalt = sleepq_check_timeout(); rvals = sleepq_check_signals(); mtx_unlock_spin(&sched_lock); - if (signal_caught || rvalt == 0) + if (rcatch) + return (rcatch); + if (rvals) return (rvals); - else - return (rvalt); + return (rvalt); } /* @@ -820,13 +820,14 @@ * Also, whatever the signal code does... */ void -sleepq_abort(struct thread *td) +sleepq_abort(struct thread *td, int intrval) { void *wchan; mtx_assert(&sched_lock, MA_OWNED); MPASS(TD_ON_SLEEPQ(td)); MPASS(td->td_flags & TDF_SINTR); + MPASS(intrval == EINTR || intrval == ERESTART); /* * If the TDF_TIMEOUT flag is set, just leave. A @@ -838,6 +839,10 @@ CTR3(KTR_PROC, "sleepq_abort: thread %p (pid %ld, %s)", (void *)td, (long)td->td_proc->p_pid, (void *)td->td_proc->p_comm); wchan = td->td_wchan; + if (wchan != NULL) { + td->td_intrval = intrval; + td->td_flags |= TDF_SLEEPABORT; + } mtx_unlock_spin(&sched_lock); sleepq_remove(td, wchan); mtx_lock_spin(&sched_lock); Index: sys/kern/vfs_aio.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_aio.c,v retrieving revision 1.195.2.2 diff -u -r1.195.2.2 vfs_aio.c --- sys/kern/vfs_aio.c 8 Nov 2005 16:08:40 -0000 1.195.2.2 +++ sys/kern/vfs_aio.c 24 Feb 2006 04:30:12 -0000 @@ -1070,6 +1070,9 @@ return (error); } + if (vp->v_bufobj.bo_bsize == 0) + return (-1); + if (cb->aio_nbytes % vp->v_bufobj.bo_bsize) return (-1); Index: sys/sys/proc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.432.2.2 diff -u -r1.432.2.2 proc.h --- sys/sys/proc.h 4 Oct 2005 04:41:26 -0000 1.432.2.2 +++ sys/sys/proc.h 24 Feb 2006 04:30:33 -0000 @@ -334,7 +334,7 @@ #define TDF_TIMEOUT 0x00000010 /* Timing out during sleep. */ #define TDF_IDLETD 0x00000020 /* This is a per-CPU idle thread. */ #define TDF_SELECT 0x00000040 /* Selecting; wakeup/waiting danger. */ -#define TDF_UNUSED7 0x00000080 /* --available -- */ +#define TDF_SLEEPABORT 0x00000080 /* sleepq_abort was called. */ #define TDF_TSNOBLOCK 0x00000100 /* Don't block on a turnstile due to race. */ #define TDF_UNUSED9 0x00000200 /* --available -- */ #define TDF_BOUNDARY 0x00000400 /* Thread suspended at user boundary */ Index: sys/sys/sleepqueue.h =================================================================== RCS file: /home/ncvs/src/sys/sys/sleepqueue.h,v retrieving revision 1.6 diff -u -r1.6 sleepqueue.h --- sys/sys/sleepqueue.h 7 Jan 2005 02:29:24 -0000 1.6 +++ sys/sys/sleepqueue.h 24 Feb 2006 04:30:33 -0000 @@ -87,12 +87,10 @@ #define SLEEPQ_INTERRUPTIBLE 0x100 /* Sleep is interruptible. */ void init_sleepqueues(void); -void sleepq_abort(struct thread *td); +void sleepq_abort(struct thread *td, int intrval); void sleepq_add(void *, struct mtx *, const char *, int); struct sleepqueue *sleepq_alloc(void); void sleepq_broadcast(void *, int, int); -int sleepq_calc_signal_retval(int sig); -int sleepq_catch_signals(void *wchan); void sleepq_free(struct sleepqueue *); void sleepq_lock(void *); struct sleepqueue *sleepq_lookup(void *); @@ -101,7 +99,7 @@ void sleepq_signal(void *, int, int); void sleepq_set_timeout(void *wchan, int timo); int sleepq_timedwait(void *wchan); -int sleepq_timedwait_sig(void *wchan, int signal_caught); +int sleepq_timedwait_sig(void *wchan); void sleepq_wait(void *); int sleepq_wait_sig(void *wchan);