summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <koverstreet@google.com>2012-12-20 21:24:46 -0800
committerKent Overstreet <koverstreet@google.com>2012-12-20 23:17:36 -0800
commit468327c90a746c26fcb26584561bd4f6b37abeea (patch)
tree1cc41969a285772c76c3103f8f428a60daa849fc
parentf8bc2a7fd7bccb9dbd816a8310d6cf566c702a45 (diff)
wait_event() consolidation
-rw-r--r--include/linux/sched.h11
-rw-r--r--include/linux/wait.h224
-rw-r--r--kernel/timer.c4
-rw-r--r--kernel/wait.c12
4 files changed, 87 insertions, 164 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0dd42a02df2e..635860d49d41 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -317,11 +317,20 @@ extern char __sched_text_start[], __sched_text_end[];
extern int in_sched_functions(unsigned long addr);
#define MAX_SCHEDULE_TIMEOUT LONG_MAX
-extern signed long schedule_timeout(signed long timeout);
+extern signed long __schedule_timeout(signed long timeout);
extern signed long schedule_timeout_interruptible(signed long timeout);
extern signed long schedule_timeout_killable(signed long timeout);
extern signed long schedule_timeout_uninterruptible(signed long timeout);
asmlinkage void schedule(void);
+
+static inline signed long schedule_timeout(signed long timeout)
+{
+ if (timeout != MAX_SCHEDULE_TIMEOUT)
+ return __schedule_timeout(timeout);
+ schedule();
+ return MAX_SCHEDULE_TIMEOUT;
+}
+
extern void schedule_preempt_disabled(void);
extern int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner);
diff --git a/include/linux/wait.h b/include/linux/wait.h
index c2920d50afa4..7f6937836910 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -173,19 +173,47 @@ wait_queue_head_t *bit_waitqueue(void *, int);
#define wake_up_interruptible_sync_poll(x, m) \
__wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, (void *) (m))
-#define __wait_event(wq, condition) \
+#define ___wait_event_timeout(wq, condition, state, exclusive, __ret) \
do { \
+ __label__ finish; \
DEFINE_WAIT(__wait); \
+ if (exclusive) \
+ __wait.flags |= WQ_FLAG_EXCLUSIVE; \
\
for (;;) { \
- prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
+ __prepare_to_wait(&wq, &__wait, state); \
if (condition) \
+ goto finish; \
+ if (signal_pending(current) && \
+ (state == TASK_INTERRUPTIBLE || \
+ (state == TASK_KILLABLE && \
+ __fatal_signal_pending(current)))) { \
+ __ret = -ERESTARTSYS; \
+ break; \
+ } \
+ __ret = schedule_timeout(__ret); \
+ if (!__ret) \
break; \
- schedule(); \
} \
- finish_wait(&wq, &__wait); \
+ if (exclusive) { \
+ abort_exclusive_wait(&wq, &__wait, state, NULL); \
+ } else { \
+finish: \
+ finish_wait(&wq, &__wait); \
+ } \
} while (0)
+#define __wait_event_timeout(wq, condition, state, exclusive, timeout) \
+({ \
+ long __ret = timeout; \
+ if (!(condition)) \
+ ___wait_event_timeout(wq, condition, state, exclusive, __ret);\
+ __ret; \
+})
+
+#define __wait_event(wq, condition, state) \
+ __wait_event_timeout(wq, condition, state, false, MAX_SCHEDULE_TIMEOUT)
+
/**
* wait_event - sleep until a condition gets true
* @wq: the waitqueue to wait on
@@ -198,112 +226,45 @@ do { \
* wake_up() has to be called after changing any variable that could
* change the result of the wait condition.
*/
-#define wait_event(wq, condition) \
-do { \
- if (condition) \
- break; \
- __wait_event(wq, condition); \
-} while (0)
-
-#define __wait_event_timeout(wq, condition, ret) \
-do { \
- DEFINE_WAIT(__wait); \
- \
- for (;;) { \
- prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
- if (condition) \
- break; \
- ret = schedule_timeout(ret); \
- if (!ret) \
- break; \
- } \
- finish_wait(&wq, &__wait); \
-} while (0)
+#define wait_event(wq, condition) \
+ __wait_event(wq, condition, TASK_UNINTERRUPTIBLE)
/**
- * wait_event_timeout - sleep until a condition gets true or a timeout elapses
+ * wait_event_interruptible - sleep until a condition gets true
* @wq: the waitqueue to wait on
* @condition: a C expression for the event to wait for
- * @timeout: timeout, in jiffies
*
- * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
- * @condition evaluates to true. The @condition is checked each time
- * the waitqueue @wq is woken up.
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or a signal is received.
+ * The @condition is checked each time the waitqueue @wq is woken up.
*
* wake_up() has to be called after changing any variable that could
* change the result of the wait condition.
*
- * The function returns 0 if the @timeout elapsed, and the remaining
- * jiffies if the condition evaluated to true before the timeout elapsed.
+ * The function will return -ERESTARTSYS if it was interrupted by a
+ * signal and 0 if @condition evaluated to true.
*/
-#define wait_event_timeout(wq, condition, timeout) \
-({ \
- long __ret = timeout; \
- if (!(condition)) \
- __wait_event_timeout(wq, condition, __ret); \
- __ret; \
-})
-
-#define __wait_event_interruptible(wq, condition, ret) \
-do { \
- DEFINE_WAIT(__wait); \
- \
- for (;;) { \
- prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \
- if (condition) \
- break; \
- if (!signal_pending(current)) { \
- schedule(); \
- continue; \
- } \
- ret = -ERESTARTSYS; \
- break; \
- } \
- finish_wait(&wq, &__wait); \
-} while (0)
+#define wait_event_interruptible(wq, condition) \
+ __wait_event(wq, condition, TASK_INTERRUPTIBLE)
/**
- * wait_event_interruptible - sleep until a condition gets true
+ * wait_event_timeout - sleep until a condition gets true or a timeout elapses
* @wq: the waitqueue to wait on
* @condition: a C expression for the event to wait for
+ * @timeout: timeout, in jiffies
*
- * The process is put to sleep (TASK_INTERRUPTIBLE) until the
- * @condition evaluates to true or a signal is received.
- * The @condition is checked each time the waitqueue @wq is woken up.
+ * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
+ * @condition evaluates to true. The @condition is checked each time
+ * the waitqueue @wq is woken up.
*
* wake_up() has to be called after changing any variable that could
* change the result of the wait condition.
*
- * The function will return -ERESTARTSYS if it was interrupted by a
- * signal and 0 if @condition evaluated to true.
+ * The function returns 0 if the @timeout elapsed, and the remaining
+ * jiffies if the condition evaluated to true before the timeout elapsed.
*/
-#define wait_event_interruptible(wq, condition) \
-({ \
- int __ret = 0; \
- if (!(condition)) \
- __wait_event_interruptible(wq, condition, __ret); \
- __ret; \
-})
-
-#define __wait_event_interruptible_timeout(wq, condition, ret) \
-do { \
- DEFINE_WAIT(__wait); \
- \
- for (;;) { \
- prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \
- if (condition) \
- break; \
- if (!signal_pending(current)) { \
- ret = schedule_timeout(ret); \
- if (!ret) \
- break; \
- continue; \
- } \
- ret = -ERESTARTSYS; \
- break; \
- } \
- finish_wait(&wq, &__wait); \
-} while (0)
+#define wait_event_timeout(wq, condition, timeout) \
+ __wait_event_timeout(wq, condition, TASK_UNINTERRUPTIBLE, false, timeout)
/**
* wait_event_interruptible_timeout - sleep until a condition gets true or a timeout elapses
@@ -323,14 +284,9 @@ do { \
* if the condition evaluated to true before the timeout elapsed.
*/
#define wait_event_interruptible_timeout(wq, condition, timeout) \
-({ \
- long __ret = timeout; \
- if (!(condition)) \
- __wait_event_interruptible_timeout(wq, condition, __ret); \
- __ret; \
-})
+ __wait_event_timeout(wq, condition, TASK_INTERRUPTIBLE, false, timeout)
-#define __wait_event_hrtimeout(wq, condition, timeout, state) \
+#define ___wait_event_hrtimeout(wq, condition, state, timeout) \
({ \
int __ret = 0; \
DEFINE_WAIT(__wait); \
@@ -366,54 +322,23 @@ do { \
__ret; \
})
-#define wait_event_hrtimeout(wq, condition, timeout) \
+#define __wait_event_hrtimeout(wq, condition, state, timeout) \
({ \
int __ret = 0; \
if (!(condition)) \
- __ret = __wait_event_hrtimeout(wq, condition, timeout, \
- TASK_UNINTERRUPTIBLE); \
- __ret; \
-})
-
-#define wait_event_interruptible_hrtimeout(wq, condition, timeout) \
-({ \
- long __ret = 0; \
- if (!(condition)) \
- __ret = __wait_event_hrtimeout(wq, condition, timeout, \
- TASK_INTERRUPTIBLE); \
+ __ret = ___wait_event_hrtimeout(wq, condition, state, timeout);\
__ret; \
})
+#define wait_event_hrtimeout(wq, condition, timeout) \
+ __wait_event_hrtimeout(wq, condition, TASK_UNINTERRUPTIBLE, timeout)
-#define __wait_event_interruptible_exclusive(wq, condition, ret) \
-do { \
- DEFINE_WAIT(__wait); \
- \
- for (;;) { \
- prepare_to_wait_exclusive(&wq, &__wait, \
- TASK_INTERRUPTIBLE); \
- if (condition) { \
- finish_wait(&wq, &__wait); \
- break; \
- } \
- if (!signal_pending(current)) { \
- schedule(); \
- continue; \
- } \
- ret = -ERESTARTSYS; \
- abort_exclusive_wait(&wq, &__wait, \
- TASK_INTERRUPTIBLE, NULL); \
- break; \
- } \
-} while (0)
+#define wait_event_interruptible_hrtimeout(wq, condition, timeout) \
+ __wait_event_hrtimeout(wq, condition, TASK_INTERRUPTIBLE, timeout)
#define wait_event_interruptible_exclusive(wq, condition) \
-({ \
- int __ret = 0; \
- if (!(condition)) \
- __wait_event_interruptible_exclusive(wq, condition, __ret);\
- __ret; \
-})
+ __wait_event_timeout(wq, condition, TASK_INTERRUPTIBLE, \
+ true, MAX_SCHEDULE_TIMEOUT)
#define __wait_event_interruptible_locked(wq, condition, exclusive, irq) \
@@ -563,25 +488,6 @@ do { \
? 0 : __wait_event_interruptible_locked(wq, condition, 1, 1))
-
-#define __wait_event_killable(wq, condition, ret) \
-do { \
- DEFINE_WAIT(__wait); \
- \
- for (;;) { \
- prepare_to_wait(&wq, &__wait, TASK_KILLABLE); \
- if (condition) \
- break; \
- if (!fatal_signal_pending(current)) { \
- schedule(); \
- continue; \
- } \
- ret = -ERESTARTSYS; \
- break; \
- } \
- finish_wait(&wq, &__wait); \
-} while (0)
-
/**
* wait_event_killable - sleep until a condition gets true
* @wq: the waitqueue to wait on
@@ -598,12 +504,7 @@ do { \
* signal and 0 if @condition evaluated to true.
*/
#define wait_event_killable(wq, condition) \
-({ \
- int __ret = 0; \
- if (!(condition)) \
- __wait_event_killable(wq, condition, __ret); \
- __ret; \
-})
+ __wait_event(wq, condition, TASK_KILLABLE)
/*
* These are the old interfaces to sleep waiting for an event.
@@ -622,6 +523,7 @@ extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,
*/
void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state);
+void __prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
unsigned int mode, void *key);
diff --git a/kernel/timer.c b/kernel/timer.c
index 367d00858482..b016c04ed33a 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1481,7 +1481,7 @@ static void process_timeout(unsigned long __data)
*
* In all cases the return value is guaranteed to be non-negative.
*/
-signed long __sched schedule_timeout(signed long timeout)
+signed long __sched __schedule_timeout(signed long timeout)
{
struct timer_list timer;
unsigned long expire;
@@ -1530,7 +1530,7 @@ signed long __sched schedule_timeout(signed long timeout)
out:
return timeout < 0 ? 0 : timeout;
}
-EXPORT_SYMBOL(schedule_timeout);
+EXPORT_SYMBOL(__schedule_timeout);
/*
* We can use __set_current_state() here because schedule_timeout() calls
diff --git a/kernel/wait.c b/kernel/wait.c
index 7fdd9eaca2c3..c8ff7c78a4d5 100644
--- a/kernel/wait.c
+++ b/kernel/wait.c
@@ -92,6 +92,18 @@ prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
}
EXPORT_SYMBOL(prepare_to_wait_exclusive);
+void __prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&q->lock, flags);
+ if (list_empty(&wait->task_list))
+ __add_wait_queue_tail(q, wait);
+ set_current_state(state);
+ spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL(__prepare_to_wait);
+
/**
* finish_wait - clean up after waiting in a queue
* @q: waitqueue waited on