Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Nov 2004 09:24:12 -0500
From:      John Baldwin <jhb@FreeBSD.org>
To:        Don Lewis <truckman@FreeBSD.org>
Cc:        das@FreeBSD.org
Subject:   Re: cvs commit: src/sys/vm vm_zeroidle.c
Message-ID:  <200411100924.12039.jhb@FreeBSD.org>
In-Reply-To: <200411090049.iA90nOmC055719@gw.catspoiler.org>
References:  <200411090049.iA90nOmC055719@gw.catspoiler.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Monday 08 November 2004 07:49 pm, Don Lewis wrote:
> On  8 Nov, John Baldwin wrote:
> > It is no longer required to hold the mutex over cv_wait() and
> > cv_signal().  I intentionally changed that so that you can do:
> >
> > 	lock()
> > 	blah()
> > 	unlock()
> > 	cv_signal()
> >
> > and reduce the number of context switches if you preempt in cv_signal().
>
> cv_wait() unlocks and relocks the mutex, so it is necessary to hold the
> mutex before calling cv_wait().  It is also likely that the mutex would
> have to be held to avoid having the condition being waited on going away
> after the mutex was dropped and before the cv_wait() call, which could
> cause the thread to miss a wakeup and sleep forever.

Ok, this is fairly standard practice and nothing new here.  Even spl() on 4.x 
required you to keep the spl raised when you called tsleep() which is 
similar.  (That is when sleeping you should generally do:

	mtx_lock()
	while (still_need_to_sleep())
		cv_wait()
	do_stuff
	mtx_unlock()

> If the caller holds the mutex across the call to cv_signal(), the caller
> may be able to avoid calls to cv_signal() if it knows that there are no
> waiters.  In most cases, the caller will want to release the mutex when
> it calls cv_signal().  A version of cv_signal() that releases the mutex
> after calling sleepq_lock() and before calling sleepq_signal() or
> sleepq_release() would allow unnecessary calls to sleepq_signal() to be
> optimized out, while avoiding the extra context switches that could be
> caused by holding the mutex until after cv_signal().

You can already do this by just dropping the lock before cv_signal() now, 
i.e.:

	mtx_lock();
	update_some_stuff;
	if (wakeup_needed)
		need_wakeup = 1;
	else
		need_wakeup = 0;
	mtx_unlock();
	if (need_wakeup)
		cv_signal()

cv_signal() itself has some optimizations so that for most cases when there 
are no waiters it won't bother do a sleepq_signal() but instead will just 
lock the spin mutex, check the waiters count, and then bail.

-- 
John Baldwin <jhb@FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200411100924.12039.jhb>