|
@@ -3267,7 +3267,8 @@ void complete_all(struct completion *x)
|
|
|
EXPORT_SYMBOL(complete_all);
|
|
|
|
|
|
static inline long __sched
|
|
|
-do_wait_for_common(struct completion *x, long timeout, int state)
|
|
|
+do_wait_for_common(struct completion *x,
|
|
|
+ long (*action)(long), long timeout, int state)
|
|
|
{
|
|
|
if (!x->done) {
|
|
|
DECLARE_WAITQUEUE(wait, current);
|
|
@@ -3280,7 +3281,7 @@ do_wait_for_common(struct completion *x, long timeout, int state)
|
|
|
}
|
|
|
__set_current_state(state);
|
|
|
spin_unlock_irq(&x->wait.lock);
|
|
|
- timeout = schedule_timeout(timeout);
|
|
|
+ timeout = action(timeout);
|
|
|
spin_lock_irq(&x->wait.lock);
|
|
|
} while (!x->done && timeout);
|
|
|
__remove_wait_queue(&x->wait, &wait);
|
|
@@ -3291,17 +3292,30 @@ do_wait_for_common(struct completion *x, long timeout, int state)
|
|
|
return timeout ?: 1;
|
|
|
}
|
|
|
|
|
|
-static long __sched
|
|
|
-wait_for_common(struct completion *x, long timeout, int state)
|
|
|
+static inline long __sched
|
|
|
+__wait_for_common(struct completion *x,
|
|
|
+ long (*action)(long), long timeout, int state)
|
|
|
{
|
|
|
might_sleep();
|
|
|
|
|
|
spin_lock_irq(&x->wait.lock);
|
|
|
- timeout = do_wait_for_common(x, timeout, state);
|
|
|
+ timeout = do_wait_for_common(x, action, timeout, state);
|
|
|
spin_unlock_irq(&x->wait.lock);
|
|
|
return timeout;
|
|
|
}
|
|
|
|
|
|
+static long __sched
|
|
|
+wait_for_common(struct completion *x, long timeout, int state)
|
|
|
+{
|
|
|
+ return __wait_for_common(x, schedule_timeout, timeout, state);
|
|
|
+}
|
|
|
+
|
|
|
+static long __sched
|
|
|
+wait_for_common_io(struct completion *x, long timeout, int state)
|
|
|
+{
|
|
|
+ return __wait_for_common(x, io_schedule_timeout, timeout, state);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* wait_for_completion: - waits for completion of a task
|
|
|
* @x: holds the state of this particular completion
|
|
@@ -3337,6 +3351,39 @@ wait_for_completion_timeout(struct completion *x, unsigned long timeout)
|
|
|
}
|
|
|
EXPORT_SYMBOL(wait_for_completion_timeout);
|
|
|
|
|
|
+/**
|
|
|
+ * wait_for_completion_io: - waits for completion of a task
|
|
|
+ * @x: holds the state of this particular completion
|
|
|
+ *
|
|
|
+ * This waits to be signaled for completion of a specific task. It is NOT
|
|
|
+ * interruptible and there is no timeout. The caller is accounted as waiting
|
|
|
+ * for IO.
|
|
|
+ */
|
|
|
+void __sched wait_for_completion_io(struct completion *x)
|
|
|
+{
|
|
|
+ wait_for_common_io(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(wait_for_completion_io);
|
|
|
+
|
|
|
+/**
|
|
|
+ * wait_for_completion_io_timeout: - waits for completion of a task (w/timeout)
|
|
|
+ * @x: holds the state of this particular completion
|
|
|
+ * @timeout: timeout value in jiffies
|
|
|
+ *
|
|
|
+ * This waits for either a completion of a specific task to be signaled or for a
|
|
|
+ * specified timeout to expire. The timeout is in jiffies. It is not
|
|
|
+ * interruptible. The caller is accounted as waiting for IO.
|
|
|
+ *
|
|
|
+ * The return value is 0 if timed out, and positive (at least 1, or number of
|
|
|
+ * jiffies left till timeout) if completed.
|
|
|
+ */
|
|
|
+unsigned long __sched
|
|
|
+wait_for_completion_io_timeout(struct completion *x, unsigned long timeout)
|
|
|
+{
|
|
|
+ return wait_for_common_io(x, timeout, TASK_UNINTERRUPTIBLE);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(wait_for_completion_io_timeout);
|
|
|
+
|
|
|
/**
|
|
|
* wait_for_completion_interruptible: - waits for completion of a task (w/intr)
|
|
|
* @x: holds the state of this particular completion
|