]> granicus.if.org Git - zfs/commitdiff
Add cv_timedwait_interruptible() function
authorNeependra Khare <neependra@kqinfotech.com>
Mon, 6 Dec 2010 11:35:58 +0000 (17:05 +0530)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 11 Jan 2011 20:14:48 +0000 (12:14 -0800)
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>
include/sys/condvar.h
module/spl/spl-condvar.c

index 18e5a6fcf08e43d6cb7049dff36174f032bd695e..7566daed7533168b2da0f267f09dc0d15355107e 100644 (file)
@@ -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 */
index edf048bb7a619394437c5b7cf63d2239f2850907..421f8806b006285facbb462af41ca89fd5d7dc50 100644 (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)
 {