diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sched/core.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 257002c13bb0..d6fdcdcbb9b1 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -3267,7 +3267,8 @@ void complete_all(struct completion *x) | |||
3267 | EXPORT_SYMBOL(complete_all); | 3267 | EXPORT_SYMBOL(complete_all); |
3268 | 3268 | ||
3269 | static inline long __sched | 3269 | static inline long __sched |
3270 | do_wait_for_common(struct completion *x, long timeout, int state) | 3270 | do_wait_for_common(struct completion *x, |
3271 | long (*action)(long), long timeout, int state) | ||
3271 | { | 3272 | { |
3272 | if (!x->done) { | 3273 | if (!x->done) { |
3273 | DECLARE_WAITQUEUE(wait, current); | 3274 | DECLARE_WAITQUEUE(wait, current); |
@@ -3280,7 +3281,7 @@ do_wait_for_common(struct completion *x, long timeout, int state) | |||
3280 | } | 3281 | } |
3281 | __set_current_state(state); | 3282 | __set_current_state(state); |
3282 | spin_unlock_irq(&x->wait.lock); | 3283 | spin_unlock_irq(&x->wait.lock); |
3283 | timeout = schedule_timeout(timeout); | 3284 | timeout = action(timeout); |
3284 | spin_lock_irq(&x->wait.lock); | 3285 | spin_lock_irq(&x->wait.lock); |
3285 | } while (!x->done && timeout); | 3286 | } while (!x->done && timeout); |
3286 | __remove_wait_queue(&x->wait, &wait); | 3287 | __remove_wait_queue(&x->wait, &wait); |
@@ -3291,17 +3292,30 @@ do_wait_for_common(struct completion *x, long timeout, int state) | |||
3291 | return timeout ?: 1; | 3292 | return timeout ?: 1; |
3292 | } | 3293 | } |
3293 | 3294 | ||
3294 | static long __sched | 3295 | static inline long __sched |
3295 | wait_for_common(struct completion *x, long timeout, int state) | 3296 | __wait_for_common(struct completion *x, |
3297 | long (*action)(long), long timeout, int state) | ||
3296 | { | 3298 | { |
3297 | might_sleep(); | 3299 | might_sleep(); |
3298 | 3300 | ||
3299 | spin_lock_irq(&x->wait.lock); | 3301 | spin_lock_irq(&x->wait.lock); |
3300 | timeout = do_wait_for_common(x, timeout, state); | 3302 | timeout = do_wait_for_common(x, action, timeout, state); |
3301 | spin_unlock_irq(&x->wait.lock); | 3303 | spin_unlock_irq(&x->wait.lock); |
3302 | return timeout; | 3304 | return timeout; |
3303 | } | 3305 | } |
3304 | 3306 | ||
3307 | static long __sched | ||
3308 | wait_for_common(struct completion *x, long timeout, int state) | ||
3309 | { | ||
3310 | return __wait_for_common(x, schedule_timeout, timeout, state); | ||
3311 | } | ||
3312 | |||
3313 | static long __sched | ||
3314 | wait_for_common_io(struct completion *x, long timeout, int state) | ||
3315 | { | ||
3316 | return __wait_for_common(x, io_schedule_timeout, timeout, state); | ||
3317 | } | ||
3318 | |||
3305 | /** | 3319 | /** |
3306 | * wait_for_completion: - waits for completion of a task | 3320 | * wait_for_completion: - waits for completion of a task |
3307 | * @x: holds the state of this particular completion | 3321 | * @x: holds the state of this particular completion |
@@ -3338,6 +3352,39 @@ wait_for_completion_timeout(struct completion *x, unsigned long timeout) | |||
3338 | EXPORT_SYMBOL(wait_for_completion_timeout); | 3352 | EXPORT_SYMBOL(wait_for_completion_timeout); |
3339 | 3353 | ||
3340 | /** | 3354 | /** |
3355 | * wait_for_completion_io: - waits for completion of a task | ||
3356 | * @x: holds the state of this particular completion | ||
3357 | * | ||
3358 | * This waits to be signaled for completion of a specific task. It is NOT | ||
3359 | * interruptible and there is no timeout. The caller is accounted as waiting | ||
3360 | * for IO. | ||
3361 | */ | ||
3362 | void __sched wait_for_completion_io(struct completion *x) | ||
3363 | { | ||
3364 | wait_for_common_io(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); | ||
3365 | } | ||
3366 | EXPORT_SYMBOL(wait_for_completion_io); | ||
3367 | |||
3368 | /** | ||
3369 | * wait_for_completion_io_timeout: - waits for completion of a task (w/timeout) | ||
3370 | * @x: holds the state of this particular completion | ||
3371 | * @timeout: timeout value in jiffies | ||
3372 | * | ||
3373 | * This waits for either a completion of a specific task to be signaled or for a | ||
3374 | * specified timeout to expire. The timeout is in jiffies. It is not | ||
3375 | * interruptible. The caller is accounted as waiting for IO. | ||
3376 | * | ||
3377 | * The return value is 0 if timed out, and positive (at least 1, or number of | ||
3378 | * jiffies left till timeout) if completed. | ||
3379 | */ | ||
3380 | unsigned long __sched | ||
3381 | wait_for_completion_io_timeout(struct completion *x, unsigned long timeout) | ||
3382 | { | ||
3383 | return wait_for_common_io(x, timeout, TASK_UNINTERRUPTIBLE); | ||
3384 | } | ||
3385 | EXPORT_SYMBOL(wait_for_completion_io_timeout); | ||
3386 | |||
3387 | /** | ||
3341 | * wait_for_completion_interruptible: - waits for completion of a task (w/intr) | 3388 | * wait_for_completion_interruptible: - waits for completion of a task (w/intr) |
3342 | * @x: holds the state of this particular completion | 3389 | * @x: holds the state of this particular completion |
3343 | * | 3390 | * |