Add cv_timedwait_interruptible() function

The cv_timedwait() function by definition must wait unconditionally
for cv_signal()/cv_broadcast() before waking.  This causes processes
to go in the D state which increases the load average.  The load
average is the summation of processes in D state and run queue.

To avoid this it can be desirable to sleep interruptibly.  These
processes do not count against the load average but may be woken by
a signal.  It is up to the caller to determine why the process
was woken it may be for one of three reasons.

  1) cv_signal()/cv_broadcast()
  2) the timeout expired
  3) a signal was received

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
Neependra Khare 2010-12-06 17:05:58 +05:30 committed by Brian Behlendorf
parent 6bf4d76f47
commit 3f688a8c38
2 changed files with 33 additions and 16 deletions

View File

@ -53,6 +53,8 @@ extern void __cv_destroy(kcondvar_t *cvp);
extern void __cv_wait(kcondvar_t *cvp, kmutex_t *mp);
extern void __cv_wait_interruptible(kcondvar_t *cvp, kmutex_t *mp);
extern clock_t __cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time);
extern clock_t __cv_timedwait_interruptible(kcondvar_t *cvp, kmutex_t *mp,
clock_t exp_time);
extern void __cv_signal(kcondvar_t *cvp);
extern void __cv_broadcast(kcondvar_t *cvp);
@ -67,6 +69,8 @@ extern void __cv_broadcast(kcondvar_t *cvp);
#define cv_wait(cvp, mp) __cv_wait(cvp, mp)
#define cv_wait_interruptible(cvp, mp) __cv_wait_interruptible(cvp,mp)
#define cv_timedwait(cvp, mp, t) __cv_timedwait(cvp, mp, t)
#define cv_timedwait_interruptible(cvp, mp, t) \
__cv_timedwait_interruptible(cvp, mp, t)
#define cv_signal(cvp) __cv_signal(cvp)
#define cv_broadcast(cvp) __cv_broadcast(cvp)

View File

@ -135,8 +135,9 @@ EXPORT_SYMBOL(__cv_wait_interruptible);
/* 'expire_time' argument is an absolute wall clock time in jiffies.
* Return value is time left (expire_time - now) or -1 if timeout occurred.
*/
clock_t
__cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t expire_time)
static clock_t
__cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp,
clock_t expire_time, int state)
{
DEFINE_WAIT(wait);
clock_t time_left;
@ -158,8 +159,7 @@ __cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t expire_time)
if (time_left <= 0)
SRETURN(-1);
prepare_to_wait_exclusive(&cvp->cv_event, &wait,
TASK_UNINTERRUPTIBLE);
prepare_to_wait_exclusive(&cvp->cv_event, &wait, state);
atomic_inc(&cvp->cv_waiters);
/* Mutex should be dropped after prepare_to_wait() this
@ -177,8 +177,21 @@ __cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t expire_time)
SRETURN(time_left > 0 ? time_left : -1);
}
clock_t
__cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time)
{
return __cv_timedwait_common(cvp, mp, exp_time, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(__cv_timedwait);
clock_t
__cv_timedwait_interruptible(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time)
{
return __cv_timedwait_common(cvp, mp, exp_time, TASK_INTERRUPTIBLE);
}
EXPORT_SYMBOL(__cv_timedwait_interruptible);
void
__cv_signal(kcondvar_t *cvp)
{