From 3f688a8c381d298062467a318994bb5849b1c8c1 Mon Sep 17 00:00:00 2001 From: Neependra Khare Date: Mon, 6 Dec 2010 17:05:58 +0530 Subject: [PATCH] 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 --- include/sys/condvar.h | 28 ++++++++++++++++------------ module/spl/spl-condvar.c | 21 +++++++++++++++++---- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/include/sys/condvar.h b/include/sys/condvar.h index 18e5a6fcf..7566daed7 100644 --- a/include/sys/condvar.h +++ b/include/sys/condvar.h @@ -53,21 +53,25 @@ 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); -#define cv_init(cvp, name, type, arg) \ -({ \ - if ((name) == NULL) \ - __cv_init(cvp, #cvp, type, arg); \ - else \ - __cv_init(cvp, name, type, arg); \ +#define cv_init(cvp, name, type, arg) \ +({ \ + if ((name) == NULL) \ + __cv_init(cvp, #cvp, type, arg); \ + else \ + __cv_init(cvp, name, type, arg); \ }) -#define cv_destroy(cvp) __cv_destroy(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_signal(cvp) __cv_signal(cvp) -#define cv_broadcast(cvp) __cv_broadcast(cvp) +#define cv_destroy(cvp) __cv_destroy(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) #endif /* _SPL_CONDVAR_H */ diff --git a/module/spl/spl-condvar.c b/module/spl/spl-condvar.c index edf048bb7..421f8806b 100644 --- a/module/spl/spl-condvar.c +++ b/module/spl/spl-condvar.c @@ -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) { -- 2.40.0