lkml.org 
[lkml]   [2009]   [Dec]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:sched/urgent] sched: Teach might_sleep() about preemptible RCU
    Commit-ID:  234da7bcdc7aaa935846534c3b726dbc79a9cdd5
    Gitweb: http://git.kernel.org/tip/234da7bcdc7aaa935846534c3b726dbc79a9cdd5
    Author: Frederic Weisbecker <fweisbec@gmail.com>
    AuthorDate: Wed, 16 Dec 2009 20:21:05 +0100
    Committer: Ingo Molnar <mingo@elte.hu>
    CommitDate: Thu, 17 Dec 2009 09:46:44 +0100

    sched: Teach might_sleep() about preemptible RCU

    In practice, it is harmless to voluntarily sleep in a
    rcu_read_lock() section if we are running under preempt rcu, but
    it is illegal if we build a kernel running non-preemptable rcu.

    Currently, might_sleep() doesn't notice sleepable operations
    under rcu_read_lock() sections if we are running under
    preemptable rcu because preempt_count() is left untouched after
    rcu_read_lock() in this case. But we want developers who test
    their changes under such config to notice the "sleeping while
    atomic" issues.

    So we add rcu_read_lock_nesting to prempt_count() in
    might_sleep() checks.

    [ v2: Handle rcu-tiny ]
    Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
    Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    LKML-Reference: <1260991265-8451-1-git-send-regression-fweisbec@gmail.com>
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    ---
    include/linux/rcutiny.h | 5 +++++
    include/linux/rcutree.h | 11 +++++++++++
    kernel/sched.c | 2 +-
    3 files changed, 17 insertions(+), 1 deletions(-)

    diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
    index c4ba9a7..96cc307 100644
    --- a/include/linux/rcutiny.h
    +++ b/include/linux/rcutiny.h
    @@ -101,4 +101,9 @@ static inline void exit_rcu(void)
    {
    }

    +static inline int rcu_preempt_depth(void)
    +{
    + return 0;
    +}
    +
    #endif /* __LINUX_RCUTINY_H */
    diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
    index c93eee5..8044b1b 100644
    --- a/include/linux/rcutree.h
    +++ b/include/linux/rcutree.h
    @@ -45,6 +45,12 @@ extern void __rcu_read_unlock(void);
    extern void synchronize_rcu(void);
    extern void exit_rcu(void);

    +/*
    + * Defined as macro as it is a very low level header
    + * included from areas that don't even know about current
    + */
    +#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
    +
    #else /* #ifdef CONFIG_TREE_PREEMPT_RCU */

    static inline void __rcu_read_lock(void)
    @@ -63,6 +69,11 @@ static inline void exit_rcu(void)
    {
    }

    +static inline int rcu_preempt_depth(void)
    +{
    + return 0;
    +}
    +
    #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */

    static inline void __rcu_read_lock_bh(void)
    diff --git a/kernel/sched.c b/kernel/sched.c
    index af7dfa7..7be88a7 100644
    --- a/kernel/sched.c
    +++ b/kernel/sched.c
    @@ -9682,7 +9682,7 @@ void __init sched_init(void)
    #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
    static inline int preempt_count_equals(int preempt_offset)
    {
    - int nested = preempt_count() & ~PREEMPT_ACTIVE;
    + int nested = (preempt_count() & ~PREEMPT_ACTIVE) + rcu_preempt_depth();

    return (nested == PREEMPT_INATOMIC_BASE + preempt_offset);
    }

    \
     
     \ /
      Last update: 2009-12-17 11:55    [W:0.026 / U:60.128 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site