On Tue, Oct 08, 2013 at 12:25:10PM +0200, Peter Zijlstra wrote:
> From: Oleg Nesterov <o...@redhat.com>
> 
> It would be nice to validate that the caller of rcu_sync_is_idle()
> holds the corresponding type of RCU read-side lock. Add the new
> rcu_sync_ops->held() method and change rcu_sync_is_idle() to
> WARN() if it returns false.
> 
> This obviously penalizes the readers (fast-path), but only if
> CONFIG_PROVE_RCU.
> 
> Suggested-by: "Paul E. McKenney" <paul...@linux.vnet.ibm.com>
> Signed-off-by: Oleg Nesterov <o...@redhat.com>
> Signed-off-by: Peter Zijlstra <pet...@infradead.org>

Reviewed-by: Paul E. McKenney <paul...@linux.vnet.ibm.com>

> Link: http://lkml.kernel.org/r/20131004184633.ga17...@redhat.com
> ---
>  include/linux/rcusync.h |    6 ++++++
>  kernel/rcusync.c        |   21 +++++++++++++++++++++
>  2 files changed, 27 insertions(+)
> 
> --- a/include/linux/rcusync.h
> +++ b/include/linux/rcusync.h
> @@ -17,9 +17,15 @@ struct rcu_sync_struct {
>       enum rcu_sync_type      gp_type;
>  };
> 
> +extern bool __rcu_sync_is_idle(struct rcu_sync_struct *);
> +
>  static inline bool rcu_sync_is_idle(struct rcu_sync_struct *rss)
>  {
> +#ifdef CONFIG_PROVE_RCU
> +     return __rcu_sync_is_idle(rss);
> +#else
>       return !rss->gp_state; /* GP_IDLE */
> +#endif
>  }
> 
>  extern void rcu_sync_init(struct rcu_sync_struct *, enum rcu_sync_type);
> --- a/kernel/rcusync.c
> +++ b/kernel/rcusync.c
> @@ -1,21 +1,33 @@
>  #include <linux/rcusync.h>
>  #include <linux/sched.h>
> 
> +#ifdef CONFIG_PROVE_RCU
> +#define __INIT_HELD(func)    .held = func,
> +#else
> +#define __INIT_HELD(func)
> +#endif
> +
>  static const struct {
>       void (*sync)(void);
>       void (*call)(struct rcu_head *, void (*)(struct rcu_head *));
> +#ifdef CONFIG_PROVE_RCU
> +     int  (*held)(void);
> +#endif
>  } gp_ops[] = {
>       [RCU_SYNC] = {
>               .sync = synchronize_rcu,
>               .call = call_rcu,
> +             __INIT_HELD(rcu_read_lock_held)
>       },
>       [RCU_SCHED_SYNC] = {
>               .sync = synchronize_sched,
>               .call = call_rcu_sched,
> +             __INIT_HELD(rcu_read_lock_sched_held)
>       },
>       [RCU_BH_SYNC] = {
>               .sync = synchronize_rcu_bh,
>               .call = call_rcu_bh,
> +             __INIT_HELD(rcu_read_lock_bh_held)
>       },
>  };
> 
> @@ -24,6 +36,15 @@ enum { CB_IDLE = 0, CB_PENDING, CB_REPLA
> 
>  #define      rss_lock        gp_wait.lock
> 
> +#ifdef CONFIG_PROVE_RCU
> +bool __rcu_sync_is_idle(struct rcu_sync_struct *rss)
> +{
> +     WARN_ON(!gp_ops[rss->gp_type].held());
> +     return rss->gp_state == GP_IDLE;
> +}
> +EXPORT_SYMBOL_GPL(__rcu_sync_is_idle);
> +#endif
> +
>  void rcu_sync_init(struct rcu_sync_struct *rss, enum rcu_sync_type type)
>  {
>       memset(rss, 0, sizeof(*rss));
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to