Messages in this thread Patch in this message | | | From | Peter Xu <> | Subject | [PATCH 1/2] sched/swait: allow swake_up() to return | Date | Thu, 9 Nov 2017 17:18:53 +0800 |
| |
Let swake_up() to return whether any of the waiters is waked up. One use case of it would be:
if (swait_active(wq)) { swake_up(wq); // do something when waiter is waked up waked_up++; }
Logically it's possible that when reaching swake_up() the wait queue is not active any more, and here doing something like waked_up++ would be inaccurate. To correct it, we need an atomic version of it.
With this patch, we can simply re-write it into:
if (swake_up(wq)) { // do something when waiter is waked up waked_up++; }
After all we are checking swait_active() inside swake_up() too.
CC: Ingo Molnar <mingo@redhat.com> CC: Peter Zijlstra <peterz@infradead.org> CC: Peter Xu <peterx@redhat.com> CC: linux-kernel@vger.kernel.org Signed-off-by: Peter Xu <peterx@redhat.com> --- include/linux/swait.h | 4 ++-- kernel/sched/swait.c | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/include/linux/swait.h b/include/linux/swait.h index c1f9c62a8a50..c55171280ac8 100644 --- a/include/linux/swait.h +++ b/include/linux/swait.h @@ -84,9 +84,9 @@ static inline int swait_active(struct swait_queue_head *q) return !list_empty(&q->task_list); } -extern void swake_up(struct swait_queue_head *q); +extern bool swake_up(struct swait_queue_head *q); extern void swake_up_all(struct swait_queue_head *q); -extern void swake_up_locked(struct swait_queue_head *q); +extern bool swake_up_locked(struct swait_queue_head *q); extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait); extern void prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait, int state); diff --git a/kernel/sched/swait.c b/kernel/sched/swait.c index 3d5610dcce11..31f8d677c690 100644 --- a/kernel/sched/swait.c +++ b/kernel/sched/swait.c @@ -16,29 +16,40 @@ EXPORT_SYMBOL(__init_swait_queue_head); * If for some reason it would return 0, that means the previously waiting * task is already running, so it will observe condition true (or has already). */ -void swake_up_locked(struct swait_queue_head *q) +bool swake_up_locked(struct swait_queue_head *q) { struct swait_queue *curr; if (list_empty(&q->task_list)) - return; + return false; curr = list_first_entry(&q->task_list, typeof(*curr), task_list); wake_up_process(curr->task); list_del_init(&curr->task_list); + return true; } EXPORT_SYMBOL(swake_up_locked); -void swake_up(struct swait_queue_head *q) +/** + * swake_up - Wake up one process on the waiting list + * @q: the waitqueue to wake up + * + * Returns true if some process is waked up, otherwise false if there + * is no waiter to wake up. + */ +bool swake_up(struct swait_queue_head *q) { + bool ret; unsigned long flags; if (!swait_active(q)) - return; + return false; raw_spin_lock_irqsave(&q->lock, flags); - swake_up_locked(q); + ret = swake_up_locked(q); raw_spin_unlock_irqrestore(&q->lock, flags); + + return ret; } EXPORT_SYMBOL(swake_up); -- 2.13.6
| |