Commit bd0f9b35 authored by Linus Torvalds's avatar Linus Torvalds

sched/headers: fix up header file dependency on <linux/sched/signal.h>

The scheduler header file split and cleanups ended up exposing a few
nasty header file dependencies, and in particular it showed how we in
<linux/wait.h> ended up depending on "signal_pending()", which now comes
from <linux/sched/signal.h>.

That's a very subtle and annoying dependency, which already caused a
semantic merge conflict (see commit e58bc927 "Pull overlayfs updates
from Miklos Szeredi", which added that fixup in the merge commit).

It turns out that we can avoid this dependency _and_ improve code
generation by moving the guts of the fairly nasty helper #define
__wait_event_interruptible_locked() to out-of-line code.  The code that
includes the signal_pending() check is all in the slow-path where we
actually go to sleep waiting for the event anyway, so using a helper
function is the right thing to do.

Using a helper function is also what we already did for the non-locked
versions, see the "__wait_event*()" macros and the "prepare_to_wait*()"
set of helper functions.

We might want to try to unify all these macro games, we have a _lot_ of
subtly different wait-event loops.  But this is the minimal patch to fix
the annoying header dependency.
Acked-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ec3b93ae
...@@ -620,30 +620,19 @@ do { \ ...@@ -620,30 +620,19 @@ do { \
__ret; \ __ret; \
}) })
extern int do_wait_intr(wait_queue_head_t *, wait_queue_t *);
extern int do_wait_intr_irq(wait_queue_head_t *, wait_queue_t *);
#define __wait_event_interruptible_locked(wq, condition, exclusive, irq) \ #define __wait_event_interruptible_locked(wq, condition, exclusive, fn) \
({ \ ({ \
int __ret = 0; \ int __ret; \
DEFINE_WAIT(__wait); \ DEFINE_WAIT(__wait); \
if (exclusive) \ if (exclusive) \
__wait.flags |= WQ_FLAG_EXCLUSIVE; \ __wait.flags |= WQ_FLAG_EXCLUSIVE; \
do { \ do { \
if (likely(list_empty(&__wait.task_list))) \ __ret = fn(&(wq), &__wait); \
__add_wait_queue_tail(&(wq), &__wait); \ if (__ret) \
set_current_state(TASK_INTERRUPTIBLE); \
if (signal_pending(current)) { \
__ret = -ERESTARTSYS; \
break; \ break; \
} \
if (irq) \
spin_unlock_irq(&(wq).lock); \
else \
spin_unlock(&(wq).lock); \
schedule(); \
if (irq) \
spin_lock_irq(&(wq).lock); \
else \
spin_lock(&(wq).lock); \
} while (!(condition)); \ } while (!(condition)); \
__remove_wait_queue(&(wq), &__wait); \ __remove_wait_queue(&(wq), &__wait); \
__set_current_state(TASK_RUNNING); \ __set_current_state(TASK_RUNNING); \
...@@ -676,7 +665,7 @@ do { \ ...@@ -676,7 +665,7 @@ do { \
*/ */
#define wait_event_interruptible_locked(wq, condition) \ #define wait_event_interruptible_locked(wq, condition) \
((condition) \ ((condition) \
? 0 : __wait_event_interruptible_locked(wq, condition, 0, 0)) ? 0 : __wait_event_interruptible_locked(wq, condition, 0, do_wait_intr))
/** /**
* wait_event_interruptible_locked_irq - sleep until a condition gets true * wait_event_interruptible_locked_irq - sleep until a condition gets true
...@@ -703,7 +692,7 @@ do { \ ...@@ -703,7 +692,7 @@ do { \
*/ */
#define wait_event_interruptible_locked_irq(wq, condition) \ #define wait_event_interruptible_locked_irq(wq, condition) \
((condition) \ ((condition) \
? 0 : __wait_event_interruptible_locked(wq, condition, 0, 1)) ? 0 : __wait_event_interruptible_locked(wq, condition, 0, do_wait_intr_irq))
/** /**
* wait_event_interruptible_exclusive_locked - sleep exclusively until a condition gets true * wait_event_interruptible_exclusive_locked - sleep exclusively until a condition gets true
...@@ -734,7 +723,7 @@ do { \ ...@@ -734,7 +723,7 @@ do { \
*/ */
#define wait_event_interruptible_exclusive_locked(wq, condition) \ #define wait_event_interruptible_exclusive_locked(wq, condition) \
((condition) \ ((condition) \
? 0 : __wait_event_interruptible_locked(wq, condition, 1, 0)) ? 0 : __wait_event_interruptible_locked(wq, condition, 1, do_wait_intr))
/** /**
* wait_event_interruptible_exclusive_locked_irq - sleep until a condition gets true * wait_event_interruptible_exclusive_locked_irq - sleep until a condition gets true
...@@ -765,7 +754,7 @@ do { \ ...@@ -765,7 +754,7 @@ do { \
*/ */
#define wait_event_interruptible_exclusive_locked_irq(wq, condition) \ #define wait_event_interruptible_exclusive_locked_irq(wq, condition) \
((condition) \ ((condition) \
? 0 : __wait_event_interruptible_locked(wq, condition, 1, 1)) ? 0 : __wait_event_interruptible_locked(wq, condition, 1, do_wait_intr_irq))
#define __wait_event_killable(wq, condition) \ #define __wait_event_killable(wq, condition) \
......
...@@ -242,6 +242,45 @@ long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state) ...@@ -242,6 +242,45 @@ long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
} }
EXPORT_SYMBOL(prepare_to_wait_event); EXPORT_SYMBOL(prepare_to_wait_event);
/*
* Note! These two wait functions are entered with the
* wait-queue lock held (and interrupts off in the _irq
* case), so there is no race with testing the wakeup
* condition in the caller before they add the wait
* entry to the wake queue.
*/
int do_wait_intr(wait_queue_head_t *wq, wait_queue_t *wait)
{
if (likely(list_empty(&wait->task_list)))
__add_wait_queue_tail(wq, wait);
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
return -ERESTARTSYS;
spin_unlock(&wq->lock);
schedule();
spin_lock(&wq->lock);
return 0;
}
EXPORT_SYMBOL(do_wait_intr);
int do_wait_intr_irq(wait_queue_head_t *wq, wait_queue_t *wait)
{
if (likely(list_empty(&wait->task_list)))
__add_wait_queue_tail(wq, wait);
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
return -ERESTARTSYS;
spin_unlock_irq(&wq->lock);
schedule();
spin_lock_irq(&wq->lock);
return 0;
}
EXPORT_SYMBOL(do_wait_intr_irq);
/** /**
* finish_wait - clean up after waiting in a queue * finish_wait - clean up after waiting in a queue
* @q: waitqueue waited on * @q: waitqueue waited on
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment