kern_condvar.c revision 72200
171088Sjasone/*-
271088Sjasone * Copyright (c) 2000 Jake Burkholder <jake@freebsd.org>.
371088Sjasone * All rights reserved.
471088Sjasone *
571088Sjasone * Redistribution and use in source and binary forms, with or without
671088Sjasone * modification, are permitted provided that the following conditions
771088Sjasone * are met:
871088Sjasone * 1. Redistributions of source code must retain the above copyright
971088Sjasone *    notice, this list of conditions and the following disclaimer.
1071088Sjasone * 2. Redistributions in binary form must reproduce the above copyright
1171088Sjasone *    notice, this list of conditions and the following disclaimer in the
1271088Sjasone *    documentation and/or other materials provided with the distribution.
1371088Sjasone *
1471088Sjasone * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1571088Sjasone * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1671088Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1771088Sjasone * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1871088Sjasone * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1971088Sjasone * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2071088Sjasone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2171088Sjasone * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2271088Sjasone * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2371088Sjasone * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2471088Sjasone * SUCH DAMAGE.
2571088Sjasone *
2671088Sjasone * $FreeBSD: head/sys/kern/kern_condvar.c 72200 2001-02-09 06:11:45Z bmilekic $
2771088Sjasone */
2871088Sjasone
2971088Sjasone#include "opt_ktrace.h"
3071088Sjasone
3171088Sjasone#include <sys/param.h>
3271088Sjasone#include <sys/systm.h>
3371088Sjasone#include <sys/proc.h>
3471088Sjasone#include <sys/kernel.h>
3571088Sjasone#include <sys/ktr.h>
3671088Sjasone#include <sys/condvar.h>
3771088Sjasone#include <sys/mutex.h>
3871088Sjasone#include <sys/signalvar.h>
3971088Sjasone#include <sys/resourcevar.h>
4071088Sjasone#ifdef KTRACE
4171088Sjasone#include <sys/uio.h>
4271088Sjasone#include <sys/ktrace.h>
4371088Sjasone#endif
4471088Sjasone
4571088Sjasone/*
4671088Sjasone * Common sanity checks for cv_wait* functions.
4771088Sjasone */
4871088Sjasone#define	CV_ASSERT(cvp, mp, p) do {					\
4971088Sjasone	KASSERT((p) != NULL, ("%s: curproc NULL", __FUNCTION__));	\
5071088Sjasone	KASSERT((p)->p_stat == SRUN, ("%s: not SRUN", __FUNCTION__));	\
5171088Sjasone	KASSERT((cvp) != NULL, ("%s: cvp NULL", __FUNCTION__));		\
5271088Sjasone	KASSERT((mp) != NULL, ("%s: mp NULL", __FUNCTION__));		\
5371088Sjasone	mtx_assert((mp), MA_OWNED | MA_NOTRECURSED);			\
5471088Sjasone} while (0)
5571088Sjasone
5671088Sjasone#ifdef CV_DEBUG
5771088Sjasone#define	CV_WAIT_VALIDATE(cvp, mp) do {					\
5871088Sjasone	if (TAILQ_EMPTY(&(cvp)->cv_waitq)) {				\
5971088Sjasone		/* Only waiter. */					\
6071088Sjasone		(cvp)->cv_mtx = (mp);					\
6171088Sjasone	} else {							\
6271088Sjasone		/*							\
6371088Sjasone		 * Other waiter; assert that we're using the		\
6471088Sjasone		 * same mutex.						\
6571088Sjasone		 */							\
6671088Sjasone		KASSERT((cvp)->cv_mtx == (mp),				\
6771088Sjasone		    ("%s: Multiple mutexes", __FUNCTION__));		\
6871088Sjasone	}								\
6971088Sjasone} while (0)
7071088Sjasone#define	CV_SIGNAL_VALIDATE(cvp) do {					\
7171088Sjasone	if (!TAILQ_EMPTY(&(cvp)->cv_waitq)) {				\
7271088Sjasone		KASSERT(mtx_owned((cvp)->cv_mtx),			\
7371088Sjasone		    ("%s: Mutex not owned", __FUNCTION__));		\
7471088Sjasone	}								\
7571088Sjasone} while (0)
7671088Sjasone#else
7771088Sjasone#define	CV_WAIT_VALIDATE(cvp, mp)
7871088Sjasone#define	CV_SIGNAL_VALIDATE(cvp)
7971088Sjasone#endif
8071088Sjasone
8171088Sjasonestatic void cv_timedwait_end(void *arg);
8271088Sjasone
8371088Sjasone/*
8471088Sjasone * Initialize a condition variable.  Must be called before use.
8571088Sjasone */
8671088Sjasonevoid
8771088Sjasonecv_init(struct cv *cvp, const char *desc)
8871088Sjasone{
8971088Sjasone
9071088Sjasone	TAILQ_INIT(&cvp->cv_waitq);
9171088Sjasone	cvp->cv_mtx = NULL;
9271088Sjasone	cvp->cv_description = desc;
9371088Sjasone}
9471088Sjasone
9571088Sjasone/*
9671088Sjasone * Destroy a condition variable.  The condition variable must be re-initialized
9771088Sjasone * in order to be re-used.
9871088Sjasone */
9971088Sjasonevoid
10071088Sjasonecv_destroy(struct cv *cvp)
10171088Sjasone{
10271088Sjasone
10371088Sjasone	KASSERT(cv_waitq_empty(cvp), ("%s: cv_waitq non-empty", __FUNCTION__));
10471088Sjasone}
10571088Sjasone
10671088Sjasone/*
10771088Sjasone * Common code for cv_wait* functions.  All require sched_lock.
10871088Sjasone */
10971088Sjasone
11071088Sjasone/*
11171088Sjasone * Switch context.
11271088Sjasone */
11371088Sjasonestatic __inline void
11471088Sjasonecv_switch(struct proc *p)
11571088Sjasone{
11671088Sjasone
11771088Sjasone	p->p_stat = SSLEEP;
11871088Sjasone	p->p_stats->p_ru.ru_nvcsw++;
11971088Sjasone	mi_switch();
12071088Sjasone	CTR3(KTR_PROC, "cv_switch: resume proc %p (pid %d, %s)", p, p->p_pid,
12171088Sjasone	    p->p_comm);
12271088Sjasone}
12371088Sjasone
12471088Sjasone/*
12571088Sjasone * Switch context, catching signals.
12671088Sjasone */
12771088Sjasonestatic __inline int
12871088Sjasonecv_switch_catch(struct proc *p)
12971088Sjasone{
13071088Sjasone	int sig;
13171088Sjasone
13271088Sjasone	/*
13371088Sjasone	 * We put ourselves on the sleep queue and start our timeout before
13471088Sjasone	 * calling CURSIG, as we could stop there, and a wakeup or a SIGCONT (or
13571088Sjasone	 * both) could occur while we were stopped.  A SIGCONT would cause us to
13671088Sjasone	 * be marked as SSLEEP without resuming us, thus we must be ready for
13771088Sjasone	 * sleep when CURSIG is called.  If the wakeup happens while we're
13871088Sjasone	 * stopped, p->p_wchan will be 0 upon return from CURSIG.
13971088Sjasone	 */
14071557Sjhb	p->p_sflag |= PS_SINTR;
14172200Sbmilekic	mtx_unlock_spin(&sched_lock);
14271088Sjasone	sig = CURSIG(p);
14372200Sbmilekic	mtx_lock_spin(&sched_lock);
14471088Sjasone	if (sig != 0) {
14571088Sjasone		if (p->p_wchan != NULL)
14671088Sjasone			cv_waitq_remove(p);
14771088Sjasone		p->p_stat = SRUN;
14871088Sjasone	} else if (p->p_wchan != NULL) {
14971088Sjasone		cv_switch(p);
15071088Sjasone	}
15171557Sjhb	p->p_sflag &= ~PS_SINTR;
15271088Sjasone
15371088Sjasone	return sig;
15471088Sjasone}
15571088Sjasone
15671088Sjasone/*
15771088Sjasone * Add a process to the wait queue of a condition variable.
15871088Sjasone */
15971088Sjasonestatic __inline void
16071088Sjasonecv_waitq_add(struct cv *cvp, struct proc *p)
16171088Sjasone{
16271088Sjasone
16371088Sjasone	/*
16471088Sjasone	 * Process may be sitting on a slpque if asleep() was called, remove it
16571088Sjasone	 * before re-adding.
16671088Sjasone	 */
16771088Sjasone	if (p->p_wchan != NULL)
16871088Sjasone		unsleep(p);
16971088Sjasone
17071557Sjhb	p->p_sflag |= PS_CVWAITQ;
17171088Sjasone	p->p_wchan = cvp;
17271088Sjasone	p->p_wmesg = cvp->cv_description;
17371088Sjasone	p->p_slptime = 0;
17471088Sjasone	p->p_nativepri = p->p_priority;
17571088Sjasone	CTR3(KTR_PROC, "cv_waitq_add: proc %p (pid %d, %s)", p, p->p_pid,
17671088Sjasone	    p->p_comm);
17771088Sjasone	TAILQ_INSERT_TAIL(&cvp->cv_waitq, p, p_slpq);
17871088Sjasone}
17971088Sjasone
18071088Sjasone/*
18171088Sjasone * Wait on a condition variable.  The current process is placed on the condition
18271088Sjasone * variable's wait queue and suspended.  A cv_signal or cv_broadcast on the same
18371088Sjasone * condition variable will resume the process.  The mutex is released before
18471088Sjasone * sleeping and will be held on return.  It is recommended that the mutex be
18571088Sjasone * held when cv_signal or cv_broadcast are called.
18671088Sjasone */
18771088Sjasonevoid
18871088Sjasonecv_wait(struct cv *cvp, struct mtx *mp)
18971088Sjasone{
19071088Sjasone	struct proc *p;
19171088Sjasone	WITNESS_SAVE_DECL(mp);
19271088Sjasone
19371088Sjasone	p = CURPROC;
19471088Sjasone#ifdef KTRACE
19571088Sjasone	if (p && KTRPOINT(p, KTR_CSW))
19671088Sjasone		ktrcsw(p->p_tracep, 1, 0);
19771088Sjasone#endif
19871088Sjasone	CV_ASSERT(cvp, mp, p);
19971088Sjasone	WITNESS_SLEEP(0, mp);
20071088Sjasone	WITNESS_SAVE(mp, mp);
20171088Sjasone
20272200Sbmilekic	mtx_lock_spin(&sched_lock);
20371088Sjasone	if (cold || panicstr) {
20471088Sjasone		/*
20571088Sjasone		 * After a panic, or during autoconfiguration, just give
20671088Sjasone		 * interrupts a chance, then just return; don't run any other
20771088Sjasone		 * procs or panic below, in case this is the idle process and
20871088Sjasone		 * already asleep.
20971088Sjasone		 */
21072200Sbmilekic		mtx_unlock_spin(&sched_lock);
21171088Sjasone		return;
21271088Sjasone	}
21371088Sjasone	CV_WAIT_VALIDATE(cvp, mp);
21471088Sjasone
21571088Sjasone	DROP_GIANT_NOSWITCH();
21672200Sbmilekic	mtx_unlock_flags(mp, MTX_NOSWITCH);
21771088Sjasone
21871088Sjasone	cv_waitq_add(cvp, p);
21971088Sjasone	cv_switch(p);
22071088Sjasone	curpriority = p->p_usrpri;
22171088Sjasone
22272200Sbmilekic	mtx_unlock_spin(&sched_lock);
22371088Sjasone#ifdef KTRACE
22471088Sjasone	if (KTRPOINT(p, KTR_CSW))
22571088Sjasone		ktrcsw(p->p_tracep, 0, 0);
22671088Sjasone#endif
22771088Sjasone	PICKUP_GIANT();
22872200Sbmilekic	mtx_lock(mp);
22971088Sjasone	WITNESS_RESTORE(mp, mp);
23071088Sjasone}
23171088Sjasone
23271088Sjasone/*
23371088Sjasone * Wait on a condition variable, allowing interruption by signals.  Return 0 if
23471088Sjasone * the process was resumed with cv_signal or cv_broadcast, EINTR or ERESTART if
23571088Sjasone * a signal was caught.  If ERESTART is returned the system call should be
23671088Sjasone * restarted if possible.
23771088Sjasone */
23871088Sjasoneint
23971088Sjasonecv_wait_sig(struct cv *cvp, struct mtx *mp)
24071088Sjasone{
24171088Sjasone	struct proc *p;
24271088Sjasone	int rval;
24371088Sjasone	int sig;
24471088Sjasone	WITNESS_SAVE_DECL(mp);
24571088Sjasone
24671088Sjasone	p = CURPROC;
24771088Sjasone	rval = 0;
24871088Sjasone#ifdef KTRACE
24971088Sjasone	if (p && KTRPOINT(p, KTR_CSW))
25071088Sjasone		ktrcsw(p->p_tracep, 1, 0);
25171088Sjasone#endif
25271088Sjasone	CV_ASSERT(cvp, mp, p);
25371088Sjasone	WITNESS_SLEEP(0, mp);
25471088Sjasone	WITNESS_SAVE(mp, mp);
25571088Sjasone
25672200Sbmilekic	mtx_lock_spin(&sched_lock);
25771088Sjasone	if (cold || panicstr) {
25871088Sjasone		/*
25971088Sjasone		 * After a panic, or during autoconfiguration, just give
26071088Sjasone		 * interrupts a chance, then just return; don't run any other
26171088Sjasone		 * procs or panic below, in case this is the idle process and
26271088Sjasone		 * already asleep.
26371088Sjasone		 */
26472200Sbmilekic		mtx_unlock_spin(&sched_lock);
26571088Sjasone		return 0;
26671088Sjasone	}
26771088Sjasone	CV_WAIT_VALIDATE(cvp, mp);
26871088Sjasone
26971088Sjasone	DROP_GIANT_NOSWITCH();
27072200Sbmilekic	mtx_unlock_flags(mp, MTX_NOSWITCH);
27171088Sjasone
27271088Sjasone	cv_waitq_add(cvp, p);
27371088Sjasone	sig = cv_switch_catch(p);
27471088Sjasone	curpriority = p->p_usrpri;
27571088Sjasone
27672200Sbmilekic	mtx_unlock_spin(&sched_lock);
27771088Sjasone	PICKUP_GIANT();
27871088Sjasone
27971088Sjasone	/* proc_lock(p); */
28071088Sjasone	if (sig == 0)
28171088Sjasone		sig = CURSIG(p);
28271088Sjasone	if (sig != 0) {
28371088Sjasone		if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig))
28471088Sjasone			rval = EINTR;
28571088Sjasone		else
28671088Sjasone			rval = ERESTART;
28771088Sjasone	}
28871088Sjasone	/* proc_unlock(p); */
28971088Sjasone
29071088Sjasone#ifdef KTRACE
29171088Sjasone	if (KTRPOINT(p, KTR_CSW))
29271088Sjasone		ktrcsw(p->p_tracep, 0, 0);
29371088Sjasone#endif
29472200Sbmilekic	mtx_lock(mp);
29571088Sjasone	WITNESS_RESTORE(mp, mp);
29671088Sjasone
29771088Sjasone	return (rval);
29871088Sjasone}
29971088Sjasone
30071088Sjasone/*
30171088Sjasone * Wait on a condition variable for at most timo/hz seconds.  Returns 0 if the
30271088Sjasone * process was resumed by cv_signal or cv_broadcast, EWOULDBLOCK if the timeout
30371088Sjasone * expires.
30471088Sjasone */
30571088Sjasoneint
30671088Sjasonecv_timedwait(struct cv *cvp, struct mtx *mp, int timo)
30771088Sjasone{
30871088Sjasone	struct proc *p;
30971088Sjasone	int rval;
31071088Sjasone	WITNESS_SAVE_DECL(mp);
31171088Sjasone
31271088Sjasone	p = CURPROC;
31371088Sjasone	rval = 0;
31471088Sjasone#ifdef KTRACE
31571088Sjasone	if (p && KTRPOINT(p, KTR_CSW))
31671088Sjasone		ktrcsw(p->p_tracep, 1, 0);
31771088Sjasone#endif
31871088Sjasone	CV_ASSERT(cvp, mp, p);
31971088Sjasone	WITNESS_SLEEP(0, mp);
32071088Sjasone	WITNESS_SAVE(mp, mp);
32171088Sjasone
32272200Sbmilekic	mtx_lock_spin(&sched_lock);
32371088Sjasone	if (cold || panicstr) {
32471088Sjasone		/*
32571088Sjasone		 * After a panic, or during autoconfiguration, just give
32671088Sjasone		 * interrupts a chance, then just return; don't run any other
32771088Sjasone		 * procs or panic below, in case this is the idle process and
32871088Sjasone		 * already asleep.
32971088Sjasone		 */
33072200Sbmilekic		mtx_unlock_spin(&sched_lock);
33171088Sjasone		return 0;
33271088Sjasone	}
33371088Sjasone	CV_WAIT_VALIDATE(cvp, mp);
33471088Sjasone
33571088Sjasone	DROP_GIANT_NOSWITCH();
33672200Sbmilekic	mtx_unlock_flags(mp, MTX_NOSWITCH);
33771088Sjasone
33871088Sjasone	cv_waitq_add(cvp, p);
33971088Sjasone	callout_reset(&p->p_slpcallout, timo, cv_timedwait_end, p);
34071088Sjasone	cv_switch(p);
34171088Sjasone	curpriority = p->p_usrpri;
34271088Sjasone
34371557Sjhb	if (p->p_sflag & PS_TIMEOUT) {
34471557Sjhb		p->p_sflag &= ~PS_TIMEOUT;
34571088Sjasone		rval = EWOULDBLOCK;
34671088Sjasone	} else
34771088Sjasone		callout_stop(&p->p_slpcallout);
34871088Sjasone
34972200Sbmilekic	mtx_unlock_spin(&sched_lock);
35071088Sjasone#ifdef KTRACE
35171088Sjasone	if (KTRPOINT(p, KTR_CSW))
35271088Sjasone		ktrcsw(p->p_tracep, 0, 0);
35371088Sjasone#endif
35471088Sjasone	PICKUP_GIANT();
35572200Sbmilekic	mtx_lock(mp);
35671088Sjasone	WITNESS_RESTORE(mp, mp);
35771088Sjasone
35871088Sjasone	return (rval);
35971088Sjasone}
36071088Sjasone
36171088Sjasone/*
36271088Sjasone * Wait on a condition variable for at most timo/hz seconds, allowing
36371088Sjasone * interruption by signals.  Returns 0 if the process was resumed by cv_signal
36471088Sjasone * or cv_broadcast, EWOULDBLOCK if the timeout expires, and EINTR or ERESTART if
36571088Sjasone * a signal was caught.
36671088Sjasone */
36771088Sjasoneint
36871088Sjasonecv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo)
36971088Sjasone{
37071088Sjasone	struct proc *p;
37171088Sjasone	int rval;
37271088Sjasone	int sig;
37371088Sjasone	WITNESS_SAVE_DECL(mp);
37471088Sjasone
37571088Sjasone	p = CURPROC;
37671088Sjasone	rval = 0;
37771088Sjasone#ifdef KTRACE
37871088Sjasone	if (p && KTRPOINT(p, KTR_CSW))
37971088Sjasone		ktrcsw(p->p_tracep, 1, 0);
38071088Sjasone#endif
38171088Sjasone	CV_ASSERT(cvp, mp, p);
38271088Sjasone	WITNESS_SLEEP(0, mp);
38371088Sjasone	WITNESS_SAVE(mp, mp);
38471088Sjasone
38572200Sbmilekic	mtx_lock_spin(&sched_lock);
38671088Sjasone	if (cold || panicstr) {
38771088Sjasone		/*
38871088Sjasone		 * After a panic, or during autoconfiguration, just give
38971088Sjasone		 * interrupts a chance, then just return; don't run any other
39071088Sjasone		 * procs or panic below, in case this is the idle process and
39171088Sjasone		 * already asleep.
39271088Sjasone		 */
39372200Sbmilekic		mtx_unlock_spin(&sched_lock);
39471088Sjasone		return 0;
39571088Sjasone	}
39671088Sjasone	CV_WAIT_VALIDATE(cvp, mp);
39771088Sjasone
39871088Sjasone	DROP_GIANT_NOSWITCH();
39972200Sbmilekic	mtx_unlock_flags(mp, MTX_NOSWITCH);
40071088Sjasone
40171088Sjasone	cv_waitq_add(cvp, p);
40271088Sjasone	callout_reset(&p->p_slpcallout, timo, cv_timedwait_end, p);
40371088Sjasone	sig = cv_switch_catch(p);
40471088Sjasone	curpriority = p->p_usrpri;
40571088Sjasone
40671557Sjhb	if (p->p_sflag & PS_TIMEOUT) {
40771557Sjhb		p->p_sflag &= ~PS_TIMEOUT;
40871088Sjasone		rval = EWOULDBLOCK;
40971088Sjasone	} else
41071088Sjasone		callout_stop(&p->p_slpcallout);
41171088Sjasone
41272200Sbmilekic	mtx_unlock_spin(&sched_lock);
41371088Sjasone	PICKUP_GIANT();
41471088Sjasone
41571088Sjasone	/* proc_lock(p); */
41671088Sjasone	if (sig == 0)
41771088Sjasone		sig = CURSIG(p);
41871088Sjasone	if (sig != 0) {
41971088Sjasone		if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig))
42071088Sjasone			rval = EINTR;
42171088Sjasone		else
42271088Sjasone			rval = ERESTART;
42371088Sjasone	}
42471088Sjasone	/* proc_unlock(p); */
42571088Sjasone
42671088Sjasone#ifdef KTRACE
42771088Sjasone	if (KTRPOINT(p, KTR_CSW))
42871088Sjasone		ktrcsw(p->p_tracep, 0, 0);
42971088Sjasone#endif
43072200Sbmilekic	mtx_lock(mp);
43171088Sjasone	WITNESS_RESTORE(mp, mp);
43271088Sjasone
43371088Sjasone	return (rval);
43471088Sjasone}
43571088Sjasone
43671088Sjasone/*
43771088Sjasone * Common code for signal and broadcast.  Assumes waitq is not empty.  Must be
43871088Sjasone * called with sched_lock held.
43971088Sjasone */
44071088Sjasonestatic __inline void
44171088Sjasonecv_wakeup(struct cv *cvp)
44271088Sjasone{
44371088Sjasone	struct proc *p;
44471088Sjasone
44571557Sjhb	mtx_assert(&sched_lock, MA_OWNED);
44671088Sjasone	p = TAILQ_FIRST(&cvp->cv_waitq);
44771088Sjasone	KASSERT(p->p_wchan == cvp, ("%s: bogus wchan", __FUNCTION__));
44871557Sjhb	KASSERT(p->p_sflag & PS_CVWAITQ, ("%s: not on waitq", __FUNCTION__));
44971088Sjasone	TAILQ_REMOVE(&cvp->cv_waitq, p, p_slpq);
45071557Sjhb	p->p_sflag &= ~PS_CVWAITQ;
45171088Sjasone	p->p_wchan = 0;
45271088Sjasone	if (p->p_stat == SSLEEP) {
45371088Sjasone		/* OPTIMIZED EXPANSION OF setrunnable(p); */
45471088Sjasone		CTR3(KTR_PROC, "cv_signal: proc %p (pid %d, %s)",
45571088Sjasone		    p, p->p_pid, p->p_comm);
45671088Sjasone		if (p->p_slptime > 1)
45771088Sjasone			updatepri(p);
45871088Sjasone		p->p_slptime = 0;
45971088Sjasone		p->p_stat = SRUN;
46071557Sjhb		if (p->p_sflag & PS_INMEM) {
46171088Sjasone			setrunqueue(p);
46271088Sjasone			maybe_resched(p);
46371088Sjasone		} else {
46471557Sjhb			p->p_sflag |= PS_SWAPINREQ;
46571088Sjasone			wakeup(&proc0);
46671088Sjasone		}
46771088Sjasone		/* END INLINE EXPANSION */
46871088Sjasone	}
46971088Sjasone}
47071088Sjasone
47171088Sjasone/*
47271088Sjasone * Signal a condition variable, wakes up one waiting process.  Will also wakeup
47371088Sjasone * the swapper if the process is not in memory, so that it can bring the
47471088Sjasone * sleeping process in.  Note that this may also result in additional processes
47571088Sjasone * being made runnable.  Should be called with the same mutex as was passed to
47671088Sjasone * cv_wait held.
47771088Sjasone */
47871088Sjasonevoid
47971088Sjasonecv_signal(struct cv *cvp)
48071088Sjasone{
48171088Sjasone
48271088Sjasone	KASSERT(cvp != NULL, ("%s: cvp NULL", __FUNCTION__));
48372200Sbmilekic	mtx_lock_spin(&sched_lock);
48471088Sjasone	if (!TAILQ_EMPTY(&cvp->cv_waitq)) {
48571088Sjasone		CV_SIGNAL_VALIDATE(cvp);
48671088Sjasone		cv_wakeup(cvp);
48771088Sjasone	}
48872200Sbmilekic	mtx_unlock_spin(&sched_lock);
48971088Sjasone}
49071088Sjasone
49171088Sjasone/*
49271088Sjasone * Broadcast a signal to a condition variable.  Wakes up all waiting processes.
49371088Sjasone * Should be called with the same mutex as was passed to cv_wait held.
49471088Sjasone */
49571088Sjasonevoid
49671088Sjasonecv_broadcast(struct cv *cvp)
49771088Sjasone{
49871088Sjasone
49971088Sjasone	KASSERT(cvp != NULL, ("%s: cvp NULL", __FUNCTION__));
50072200Sbmilekic	mtx_lock_spin(&sched_lock);
50171088Sjasone	CV_SIGNAL_VALIDATE(cvp);
50271088Sjasone	while (!TAILQ_EMPTY(&cvp->cv_waitq))
50371088Sjasone		cv_wakeup(cvp);
50472200Sbmilekic	mtx_unlock_spin(&sched_lock);
50571088Sjasone}
50671088Sjasone
50771088Sjasone/*
50871088Sjasone * Remove a process from the wait queue of its condition variable.  This may be
50971088Sjasone * called externally.
51071088Sjasone */
51171088Sjasonevoid
51271088Sjasonecv_waitq_remove(struct proc *p)
51371088Sjasone{
51471088Sjasone	struct cv *cvp;
51571088Sjasone
51672200Sbmilekic	mtx_lock_spin(&sched_lock);
51771557Sjhb	if ((cvp = p->p_wchan) != NULL && p->p_sflag & PS_CVWAITQ) {
51871088Sjasone		TAILQ_REMOVE(&cvp->cv_waitq, p, p_slpq);
51971557Sjhb		p->p_sflag &= ~PS_CVWAITQ;
52071088Sjasone		p->p_wchan = NULL;
52171088Sjasone	}
52272200Sbmilekic	mtx_unlock_spin(&sched_lock);
52371088Sjasone}
52471088Sjasone
52571088Sjasone/*
52671088Sjasone * Timeout function for cv_timedwait.  Put the process on the runqueue and set
52771088Sjasone * its timeout flag.
52871088Sjasone */
52971088Sjasonestatic void
53071088Sjasonecv_timedwait_end(void *arg)
53171088Sjasone{
53271088Sjasone	struct proc *p;
53371088Sjasone
53471088Sjasone	p = arg;
53571088Sjasone	CTR3(KTR_PROC, "cv_timedwait_end: proc %p (pid %d, %s)", p, p->p_pid,
53671088Sjasone	    p->p_comm);
53772200Sbmilekic	mtx_lock_spin(&sched_lock);
53871088Sjasone	if (p->p_wchan != NULL) {
53971088Sjasone		if (p->p_stat == SSLEEP)
54071088Sjasone			setrunnable(p);
54171088Sjasone		else
54271088Sjasone			cv_waitq_remove(p);
54371557Sjhb		p->p_sflag |= PS_TIMEOUT;
54471088Sjasone	}
54572200Sbmilekic	mtx_unlock_spin(&sched_lock);
54671088Sjasone}
547