lkml.org 
[lkml]   [2017]   [Sep]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 1/7] sched/wait: Add swq_has_sleepers()
    Date
    Which is the equivalent of what we have in regular waitqueues.
    I'm not crazy about the name, but this also helps us get both
    apis closer -- which iirc comes originally from the -net folks.

    We also duplicate the comments for the lockless swait_active(),
    from wait.h. Future users will make use of this interface.

    Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
    ---
    include/linux/swait.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++++--
    1 file changed, 56 insertions(+), 2 deletions(-)

    diff --git a/include/linux/swait.h b/include/linux/swait.h
    index 4a4e180d0a35..73e97a08d3d0 100644
    --- a/include/linux/swait.h
    +++ b/include/linux/swait.h
    @@ -79,9 +79,63 @@ extern void __init_swait_queue_head(struct swait_queue_head *q, const char *name
    DECLARE_SWAIT_QUEUE_HEAD(name)
    #endif

    -static inline int swait_active(struct swait_queue_head *q)
    +/**
    + * swait_active -- locklessly test for waiters on the queue
    + * @wq: the waitqueue to test for waiters
    + *
    + * returns true if the wait list is not empty
    + *
    + * NOTE: this function is lockless and requires care, incorrect usage _will_
    + * lead to sporadic and non-obvious failure.
    + *
    + * NOTE2: this function has the same above implications as regular waitqueues.
    + *
    + * Use either while holding swait_queue_head::lock or when used for wakeups
    + * with an extra smp_mb() like:
    + *
    + * CPU0 - waker CPU1 - waiter
    + *
    + * for (;;) {
    + * @cond = true; prepare_to_swait(&wq_head, &wait, state);
    + * smp_mb(); // smp_mb() from set_current_state()
    + * if (swait_active(wq_head)) if (@cond)
    + * wake_up(wq_head); break;
    + * schedule();
    + * }
    + * finish_swait(&wq_head, &wait);
    + *
    + * Because without the explicit smp_mb() it's possible for the
    + * swait_active() load to get hoisted over the @cond store such that we'll
    + * observe an empty wait list while the waiter might not observe @cond.
    + * This, in turn, can trigger missing wakeups.
    + *
    + * Also note that this 'optimization' trades a spin_lock() for an smp_mb(),
    + * which (when the lock is uncontended) are of roughly equal cost.
    + */
    +static inline int swait_active(struct swait_queue_head *wq)
    +{
    + return !list_empty(&wq->task_list);
    +}
    +
    +/**
    + * swq_has_sleeper - check if there are any waiting processes
    + * @wq: the waitqueue to test for waiters
    + *
    + * Returns true if @wq has waiting processes
    + *
    + * Please refer to the comment for swait_active.
    + */
    +static inline bool swq_has_sleeper(struct swait_queue_head *wq)
    {
    - return !list_empty(&q->task_list);
    + /*
    + * We need to be sure we are in sync with the list_add()
    + * modifications to the wait queue (task_list).
    + *
    + * This memory barrier should be paired with one on the
    + * waiting side.
    + */
    + smp_mb();
    + return swait_active(wq);
    }

    extern void swake_up(struct swait_queue_head *q);
    --
    2.12.0
    \
     
     \ /
      Last update: 2017-09-13 22:10    [W:2.801 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site