All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Paul E. McKenney" <paulmck@linux.ibm.com>
To: tglx@linutronix.de, bigeasy@linutronix.de
Cc: linux-rt-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: rcu: Merge RCU-bh into RCU-preempt
Date: Thu, 1 Nov 2018 16:18:04 -0700	[thread overview]
Message-ID: <20181101231804.GA11280@linux.ibm.com> (raw)

> The Linux kernel has long RCU-bh read-side critical sections that
> intolerably increase scheduling latency under mainline's RCU-bh rules,
> which include RCU-bh read-side critical sections being non-preemptible.
> This patch therefore arranges for RCU-bh to be implemented in terms of
> RCU-preempt for CONFIG_PREEMPT_RT_FULL=y.
> 
> This has the downside of defeating the purpose of RCU-bh, namely,
> handling the case where the system is subjected to a network-based
> denial-of-service attack that keeps at least one CPU doing full-time
> softirq processing.  This issue will be fixed by a later commit.
> 
> The current commit will need some work to make it appropriate for
> mainline use, for example, it needs to be extended to cover Tiny RCU.

The need for this goes away as of the current merge window because
RCU-bh has gone away.  (Aside from still being able to do things
like rcu_read_lock_bh() as a documentation device.)

							Thanx, Paul

> [ paulmck: Added a useful changelog ]
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> Link: http://lkml.kernel.org/r/20111005185938.GA20403@linux.vnet.ibm.com
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> 
> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> index 63cd0a1a99a0..60a9b5feefe2 100644
> --- a/include/linux/rcupdate.h
> +++ b/include/linux/rcupdate.h
> @@ -56,7 +56,11 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func);
>  #define	call_rcu	call_rcu_sched
>  #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
>  
> +#ifdef CONFIG_PREEMPT_RT_FULL
> +#define call_rcu_bh	call_rcu
> +#else
>  void call_rcu_bh(struct rcu_head *head, rcu_callback_t func);
> +#endif
>  void call_rcu_sched(struct rcu_head *head, rcu_callback_t func);
>  void synchronize_sched(void);
>  void rcu_barrier_tasks(void);
> @@ -263,7 +267,14 @@ extern struct lockdep_map rcu_sched_lock_map;
>  extern struct lockdep_map rcu_callback_map;
>  int debug_lockdep_rcu_enabled(void);
>  int rcu_read_lock_held(void);
> +#ifdef CONFIG_PREEMPT_RT_FULL
> +static inline int rcu_read_lock_bh_held(void)
> +{
> +	return rcu_read_lock_held();
> +}
> +#else
>  int rcu_read_lock_bh_held(void);
> +#endif
>  int rcu_read_lock_sched_held(void);
>  
>  #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
> @@ -663,10 +674,14 @@ static inline void rcu_read_unlock(void)
>  static inline void rcu_read_lock_bh(void)
>  {
>  	local_bh_disable();
> +#ifdef CONFIG_PREEMPT_RT_FULL
> +	rcu_read_lock();
> +#else
>  	__acquire(RCU_BH);
>  	rcu_lock_acquire(&rcu_bh_lock_map);
>  	RCU_LOCKDEP_WARN(!rcu_is_watching(),
>  			 "rcu_read_lock_bh() used illegally while idle");
> +#endif
>  }
>  
>  /*
> @@ -676,10 +691,14 @@ static inline void rcu_read_lock_bh(void)
>   */
>  static inline void rcu_read_unlock_bh(void)
>  {
> +#ifdef CONFIG_PREEMPT_RT_FULL
> +	rcu_read_unlock();
> +#else
>  	RCU_LOCKDEP_WARN(!rcu_is_watching(),
>  			 "rcu_read_unlock_bh() used illegally while idle");
>  	rcu_lock_release(&rcu_bh_lock_map);
>  	__release(RCU_BH);
> +#endif
>  	local_bh_enable();
>  }
>  
> diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
> index 914655848ef6..462ce061bac7 100644
> --- a/include/linux/rcutree.h
> +++ b/include/linux/rcutree.h
> @@ -44,7 +44,11 @@ static inline void rcu_virt_note_context_switch(int cpu)
>  	rcu_note_context_switch(false);
>  }
>  
> +#ifdef CONFIG_PREEMPT_RT_FULL
> +# define synchronize_rcu_bh	synchronize_rcu
> +#else
>  void synchronize_rcu_bh(void);
> +#endif
>  void synchronize_sched_expedited(void);
>  void synchronize_rcu_expedited(void);
>  
> @@ -72,7 +76,11 @@ static inline void synchronize_rcu_bh_expedited(void)
>  }
>  
>  void rcu_barrier(void);
> +#ifdef CONFIG_PREEMPT_RT_FULL
> +# define rcu_barrier_bh		rcu_barrier
> +#else
>  void rcu_barrier_bh(void);
> +#endif
>  void rcu_barrier_sched(void);
>  bool rcu_eqs_special_set(int cpu);
>  unsigned long get_state_synchronize_rcu(void);
> diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
> index 4d04683c31b2..808cce9a5d43 100644
> --- a/kernel/rcu/rcu.h
> +++ b/kernel/rcu/rcu.h
> @@ -528,7 +528,6 @@ static inline void show_rcu_gp_kthreads(void) { }
>  static inline int rcu_get_gp_kthreads_prio(void) { return 0; }
>  #else /* #ifdef CONFIG_TINY_RCU */
>  unsigned long rcu_get_gp_seq(void);
> -unsigned long rcu_bh_get_gp_seq(void);
>  unsigned long rcu_sched_get_gp_seq(void);
>  unsigned long rcu_exp_batches_completed(void);
>  unsigned long rcu_exp_batches_completed_sched(void);
> @@ -536,10 +535,18 @@ unsigned long srcu_batches_completed(struct srcu_struct *sp);
>  void show_rcu_gp_kthreads(void);
>  int rcu_get_gp_kthreads_prio(void);
>  void rcu_force_quiescent_state(void);
> -void rcu_bh_force_quiescent_state(void);
>  void rcu_sched_force_quiescent_state(void);
>  extern struct workqueue_struct *rcu_gp_wq;
>  extern struct workqueue_struct *rcu_par_gp_wq;
> +
> +#ifdef CONFIG_PREEMPT_RT_FULL
> +#define rcu_bh_get_gp_seq		rcu_get_gp_seq
> +#define rcu_bh_force_quiescent_state	rcu_force_quiescent_state
> +#else
> +unsigned long rcu_bh_get_gp_seq(void);
> +void rcu_bh_force_quiescent_state(void);
> +#endif
> +
>  #endif /* #else #ifdef CONFIG_TINY_RCU */
>  
>  #ifdef CONFIG_RCU_NOCB_CPU
> diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
> index c596c6f1e457..7d2a615601e7 100644
> --- a/kernel/rcu/rcutorture.c
> +++ b/kernel/rcu/rcutorture.c
> @@ -434,6 +434,7 @@ static struct rcu_torture_ops rcu_ops = {
>  	.name		= "rcu"
>  };
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  /*
>   * Definitions for rcu_bh torture testing.
>   */
> @@ -475,6 +476,12 @@ static struct rcu_torture_ops rcu_bh_ops = {
>  	.name		= "rcu_bh"
>  };
>  
> +#else
> +static struct rcu_torture_ops rcu_bh_ops = {
> +	.ttype		= INVALID_RCU_FLAVOR,
> +};
> +#endif
> +
>  /*
>   * Don't even think about trying any of these in real life!!!
>   * The names includes "busted", and they really means it!
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index 0b760c1369f7..197088cdb56e 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -244,6 +244,7 @@ void rcu_sched_qs(void)
>  			   this_cpu_ptr(&rcu_sched_data), true);
>  }
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  void rcu_bh_qs(void)
>  {
>  	RCU_LOCKDEP_WARN(preemptible(), "rcu_bh_qs() invoked with preemption enabled!!!");
> @@ -254,6 +255,7 @@ void rcu_bh_qs(void)
>  		__this_cpu_write(rcu_bh_data.cpu_no_qs.b.norm, false);
>  	}
>  }
> +#endif
>  
>  /*
>   * Steal a bit from the bottom of ->dynticks for idle entry/exit
> @@ -568,6 +570,7 @@ unsigned long rcu_sched_get_gp_seq(void)
>  }
>  EXPORT_SYMBOL_GPL(rcu_sched_get_gp_seq);
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  /*
>   * Return the number of RCU-bh GPs completed thus far for debug & stats.
>   */
> @@ -576,6 +579,7 @@ unsigned long rcu_bh_get_gp_seq(void)
>  	return READ_ONCE(rcu_bh_state.gp_seq);
>  }
>  EXPORT_SYMBOL_GPL(rcu_bh_get_gp_seq);
> +#endif
>  
>  /*
>   * Return the number of RCU expedited batches completed thus far for
> @@ -599,6 +603,7 @@ unsigned long rcu_exp_batches_completed_sched(void)
>  }
>  EXPORT_SYMBOL_GPL(rcu_exp_batches_completed_sched);
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  /*
>   * Force a quiescent state.
>   */
> @@ -617,6 +622,13 @@ void rcu_bh_force_quiescent_state(void)
>  }
>  EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
>  
> +#else
> +void rcu_force_quiescent_state(void)
> +{
> +}
> +EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);
> +#endif
> +
>  /*
>   * Force a quiescent state for RCU-sched.
>   */
> @@ -674,9 +686,11 @@ void rcutorture_get_gp_data(enum rcutorture_type test_type, int *flags,
>  	case RCU_FLAVOR:
>  		rsp = rcu_state_p;
>  		break;
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  	case RCU_BH_FLAVOR:
>  		rsp = &rcu_bh_state;
>  		break;
> +#endif
>  	case RCU_SCHED_FLAVOR:
>  		rsp = &rcu_sched_state;
>  		break;
> @@ -3040,6 +3054,7 @@ void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
>  }
>  EXPORT_SYMBOL_GPL(call_rcu_sched);
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  /**
>   * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
>   * @head: structure to be used for queueing the RCU updates.
> @@ -3067,6 +3082,7 @@ void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
>  	__call_rcu(head, func, &rcu_bh_state, -1, 0);
>  }
>  EXPORT_SYMBOL_GPL(call_rcu_bh);
> +#endif
>  
>  /*
>   * Queue an RCU callback for lazy invocation after a grace period.
> @@ -3152,6 +3168,7 @@ void synchronize_sched(void)
>  }
>  EXPORT_SYMBOL_GPL(synchronize_sched);
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  /**
>   * synchronize_rcu_bh - wait until an rcu_bh grace period has elapsed.
>   *
> @@ -3178,6 +3195,7 @@ void synchronize_rcu_bh(void)
>  		wait_rcu_gp(call_rcu_bh);
>  }
>  EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
> +#endif
>  
>  /**
>   * get_state_synchronize_rcu - Snapshot current RCU state
> @@ -3485,6 +3503,7 @@ static void _rcu_barrier(struct rcu_state *rsp)
>  	mutex_unlock(&rsp->barrier_mutex);
>  }
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  /**
>   * rcu_barrier_bh - Wait until all in-flight call_rcu_bh() callbacks complete.
>   */
> @@ -3493,6 +3512,7 @@ void rcu_barrier_bh(void)
>  	_rcu_barrier(&rcu_bh_state);
>  }
>  EXPORT_SYMBOL_GPL(rcu_barrier_bh);
> +#endif
>  
>  /**
>   * rcu_barrier_sched - Wait for in-flight call_rcu_sched() callbacks.
> @@ -4140,7 +4160,9 @@ void __init rcu_init(void)
>  
>  	rcu_bootup_announce();
>  	rcu_init_geometry();
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  	rcu_init_one(&rcu_bh_state);
> +#endif
>  	rcu_init_one(&rcu_sched_state);
>  	if (dump_tree)
>  		rcu_dump_rcu_node_tree(&rcu_sched_state);
> diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
> index 4e74df768c57..fbbff7c21148 100644
> --- a/kernel/rcu/tree.h
> +++ b/kernel/rcu/tree.h
> @@ -413,7 +413,9 @@ extern struct list_head rcu_struct_flavors;
>   */
>  extern struct rcu_state rcu_sched_state;
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  extern struct rcu_state rcu_bh_state;
> +#endif
>  
>  #ifdef CONFIG_PREEMPT_RCU
>  extern struct rcu_state rcu_preempt_state;
> diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
> index 39cb23d22109..f56c0fbdf22e 100644
> --- a/kernel/rcu/update.c
> +++ b/kernel/rcu/update.c
> @@ -286,6 +286,7 @@ int rcu_read_lock_held(void)
>  }
>  EXPORT_SYMBOL_GPL(rcu_read_lock_held);
>  
> +#ifndef CONFIG_PREEMPT_RT_FULL
>  /**
>   * rcu_read_lock_bh_held() - might we be in RCU-bh read-side critical section?
>   *
> @@ -312,6 +313,7 @@ int rcu_read_lock_bh_held(void)
>  	return in_softirq() || irqs_disabled();
>  }
>  EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held);
> +#endif
>  
>  #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
>  

             reply	other threads:[~2018-11-01 23:18 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-01 23:18 Paul E. McKenney [this message]
2018-11-08 16:02 ` rcu: Merge RCU-bh into RCU-preempt Sebastian Andrzej Siewior
2018-11-08 16:42   ` Paul E. McKenney
2018-11-08 17:15     ` Sebastian Andrzej Siewior
2018-11-08 17:35       ` Paul E. McKenney
2018-11-08 17:48         ` Sebastian Andrzej Siewior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181101231804.GA11280@linux.ibm.com \
    --to=paulmck@linux.ibm.com \
    --cc=bigeasy@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.