Skip to content

Commit bd0f9b3

Browse files
committed
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 e58bc92 "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: Ingo Molnar <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent ec3b93a commit bd0f9b3

File tree

2 files changed

+49
-21
lines changed

2 files changed

+49
-21
lines changed

include/linux/wait.h

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -620,30 +620,19 @@ do { \
620620
__ret; \
621621
})
622622

623+
extern int do_wait_intr(wait_queue_head_t *, wait_queue_t *);
624+
extern int do_wait_intr_irq(wait_queue_head_t *, wait_queue_t *);
623625

624-
#define __wait_event_interruptible_locked(wq, condition, exclusive, irq) \
626+
#define __wait_event_interruptible_locked(wq, condition, exclusive, fn) \
625627
({ \
626-
int __ret = 0; \
628+
int __ret; \
627629
DEFINE_WAIT(__wait); \
628630
if (exclusive) \
629631
__wait.flags |= WQ_FLAG_EXCLUSIVE; \
630632
do { \
631-
if (likely(list_empty(&__wait.task_list))) \
632-
__add_wait_queue_tail(&(wq), &__wait); \
633-
set_current_state(TASK_INTERRUPTIBLE); \
634-
if (signal_pending(current)) { \
635-
__ret = -ERESTARTSYS; \
633+
__ret = fn(&(wq), &__wait); \
634+
if (__ret) \
636635
break; \
637-
} \
638-
if (irq) \
639-
spin_unlock_irq(&(wq).lock); \
640-
else \
641-
spin_unlock(&(wq).lock); \
642-
schedule(); \
643-
if (irq) \
644-
spin_lock_irq(&(wq).lock); \
645-
else \
646-
spin_lock(&(wq).lock); \
647636
} while (!(condition)); \
648637
__remove_wait_queue(&(wq), &__wait); \
649638
__set_current_state(TASK_RUNNING); \
@@ -676,7 +665,7 @@ do { \
676665
*/
677666
#define wait_event_interruptible_locked(wq, condition) \
678667
((condition) \
679-
? 0 : __wait_event_interruptible_locked(wq, condition, 0, 0))
668+
? 0 : __wait_event_interruptible_locked(wq, condition, 0, do_wait_intr))
680669

681670
/**
682671
* wait_event_interruptible_locked_irq - sleep until a condition gets true
@@ -703,7 +692,7 @@ do { \
703692
*/
704693
#define wait_event_interruptible_locked_irq(wq, condition) \
705694
((condition) \
706-
? 0 : __wait_event_interruptible_locked(wq, condition, 0, 1))
695+
? 0 : __wait_event_interruptible_locked(wq, condition, 0, do_wait_intr_irq))
707696

708697
/**
709698
* wait_event_interruptible_exclusive_locked - sleep exclusively until a condition gets true
@@ -734,7 +723,7 @@ do { \
734723
*/
735724
#define wait_event_interruptible_exclusive_locked(wq, condition) \
736725
((condition) \
737-
? 0 : __wait_event_interruptible_locked(wq, condition, 1, 0))
726+
? 0 : __wait_event_interruptible_locked(wq, condition, 1, do_wait_intr))
738727

739728
/**
740729
* wait_event_interruptible_exclusive_locked_irq - sleep until a condition gets true
@@ -765,7 +754,7 @@ do { \
765754
*/
766755
#define wait_event_interruptible_exclusive_locked_irq(wq, condition) \
767756
((condition) \
768-
? 0 : __wait_event_interruptible_locked(wq, condition, 1, 1))
757+
? 0 : __wait_event_interruptible_locked(wq, condition, 1, do_wait_intr_irq))
769758

770759

771760
#define __wait_event_killable(wq, condition) \

kernel/sched/wait.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,45 @@ long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
242242
}
243243
EXPORT_SYMBOL(prepare_to_wait_event);
244244

245+
/*
246+
* Note! These two wait functions are entered with the
247+
* wait-queue lock held (and interrupts off in the _irq
248+
* case), so there is no race with testing the wakeup
249+
* condition in the caller before they add the wait
250+
* entry to the wake queue.
251+
*/
252+
int do_wait_intr(wait_queue_head_t *wq, wait_queue_t *wait)
253+
{
254+
if (likely(list_empty(&wait->task_list)))
255+
__add_wait_queue_tail(wq, wait);
256+
257+
set_current_state(TASK_INTERRUPTIBLE);
258+
if (signal_pending(current))
259+
return -ERESTARTSYS;
260+
261+
spin_unlock(&wq->lock);
262+
schedule();
263+
spin_lock(&wq->lock);
264+
return 0;
265+
}
266+
EXPORT_SYMBOL(do_wait_intr);
267+
268+
int do_wait_intr_irq(wait_queue_head_t *wq, wait_queue_t *wait)
269+
{
270+
if (likely(list_empty(&wait->task_list)))
271+
__add_wait_queue_tail(wq, wait);
272+
273+
set_current_state(TASK_INTERRUPTIBLE);
274+
if (signal_pending(current))
275+
return -ERESTARTSYS;
276+
277+
spin_unlock_irq(&wq->lock);
278+
schedule();
279+
spin_lock_irq(&wq->lock);
280+
return 0;
281+
}
282+
EXPORT_SYMBOL(do_wait_intr_irq);
283+
245284
/**
246285
* finish_wait - clean up after waiting in a queue
247286
* @q: waitqueue waited on

0 commit comments

Comments
 (0)