]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/blob - rt-patches/0130-rcu-Merge-RCU-bh-into-RCU-preempt.patch
WAR:media:i2c:ov5693: add flip and mirror setting
[hercules2020/nv-tegra/linux-4.4.git] / rt-patches / 0130-rcu-Merge-RCU-bh-into-RCU-preempt.patch
1 From fdb99949a781d0c3d919eb30189de91650c02641 Mon Sep 17 00:00:00 2001
2 From: Thomas Gleixner <tglx@linutronix.de>
3 Date: Wed, 5 Oct 2011 11:59:38 -0700
4 Subject: [PATCH 130/365] rcu: Merge RCU-bh into RCU-preempt
5
6 The Linux kernel has long RCU-bh read-side critical sections that
7 intolerably increase scheduling latency under mainline's RCU-bh rules,
8 which include RCU-bh read-side critical sections being non-preemptible.
9 This patch therefore arranges for RCU-bh to be implemented in terms of
10 RCU-preempt for CONFIG_PREEMPT_RT_FULL=y.
11
12 This has the downside of defeating the purpose of RCU-bh, namely,
13 handling the case where the system is subjected to a network-based
14 denial-of-service attack that keeps at least one CPU doing full-time
15 softirq processing.  This issue will be fixed by a later commit.
16
17 The current commit will need some work to make it appropriate for
18 mainline use, for example, it needs to be extended to cover Tiny RCU.
19
20 [ paulmck: Added a useful changelog ]
21
22 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
23 Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
24 Link: http://lkml.kernel.org/r/20111005185938.GA20403@linux.vnet.ibm.com
25 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
26 ---
27  include/linux/rcupdate.h | 23 +++++++++++++++++++++++
28  include/linux/rcutree.h  | 18 ++++++++++++++++--
29  kernel/rcu/tree.c        | 16 ++++++++++++++++
30  kernel/rcu/update.c      |  2 ++
31  4 files changed, 57 insertions(+), 2 deletions(-)
32
33 diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
34 index 1eef045..ddacc7e 100644
35 --- a/include/linux/rcupdate.h
36 +++ b/include/linux/rcupdate.h
37 @@ -169,6 +169,9 @@ void call_rcu(struct rcu_head *head,
38  
39  #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
40  
41 +#ifdef CONFIG_PREEMPT_RT_FULL
42 +#define call_rcu_bh    call_rcu
43 +#else
44  /**
45   * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
46   * @head: structure to be used for queueing the RCU updates.
47 @@ -192,6 +195,7 @@ void call_rcu(struct rcu_head *head,
48   */
49  void call_rcu_bh(struct rcu_head *head,
50                  rcu_callback_t func);
51 +#endif
52  
53  /**
54   * call_rcu_sched() - Queue an RCU for invocation after sched grace period.
55 @@ -330,7 +334,11 @@ static inline int rcu_preempt_depth(void)
56  void rcu_init(void);
57  void rcu_end_inkernel_boot(void);
58  void rcu_sched_qs(void);
59 +#ifdef CONFIG_PREEMPT_RT_FULL
60 +static inline void rcu_bh_qs(void) { }
61 +#else
62  void rcu_bh_qs(void);
63 +#endif
64  void rcu_check_callbacks(int user);
65  struct notifier_block;
66  int rcu_cpu_notify(struct notifier_block *self,
67 @@ -496,7 +504,14 @@ extern struct lockdep_map rcu_callback_map;
68  int debug_lockdep_rcu_enabled(void);
69  
70  int rcu_read_lock_held(void);
71 +#ifdef CONFIG_PREEMPT_RT_FULL
72 +static inline int rcu_read_lock_bh_held(void)
73 +{
74 +       return rcu_read_lock_held();
75 +}
76 +#else
77  int rcu_read_lock_bh_held(void);
78 +#endif
79  
80  /**
81   * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
82 @@ -944,10 +959,14 @@ static inline void rcu_read_unlock(void)
83  static inline void rcu_read_lock_bh(void)
84  {
85         local_bh_disable();
86 +#ifdef CONFIG_PREEMPT_RT_FULL
87 +       rcu_read_lock();
88 +#else
89         __acquire(RCU_BH);
90         rcu_lock_acquire(&rcu_bh_lock_map);
91         RCU_LOCKDEP_WARN(!rcu_is_watching(),
92                          "rcu_read_lock_bh() used illegally while idle");
93 +#endif
94  }
95  
96  /*
97 @@ -957,10 +976,14 @@ static inline void rcu_read_lock_bh(void)
98   */
99  static inline void rcu_read_unlock_bh(void)
100  {
101 +#ifdef CONFIG_PREEMPT_RT_FULL
102 +       rcu_read_unlock();
103 +#else
104         RCU_LOCKDEP_WARN(!rcu_is_watching(),
105                          "rcu_read_unlock_bh() used illegally while idle");
106         rcu_lock_release(&rcu_bh_lock_map);
107         __release(RCU_BH);
108 +#endif
109         local_bh_enable();
110  }
111  
112 diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
113 index 60d15a0..436c9e6 100644
114 --- a/include/linux/rcutree.h
115 +++ b/include/linux/rcutree.h
116 @@ -44,7 +44,11 @@ static inline void rcu_virt_note_context_switch(int cpu)
117         rcu_note_context_switch();
118  }
119  
120 +#ifdef CONFIG_PREEMPT_RT_FULL
121 +# define synchronize_rcu_bh    synchronize_rcu
122 +#else
123  void synchronize_rcu_bh(void);
124 +#endif
125  void synchronize_sched_expedited(void);
126  void synchronize_rcu_expedited(void);
127  
128 @@ -72,7 +76,11 @@ static inline void synchronize_rcu_bh_expedited(void)
129  }
130  
131  void rcu_barrier(void);
132 +#ifdef CONFIG_PREEMPT_RT_FULL
133 +# define rcu_barrier_bh                rcu_barrier
134 +#else
135  void rcu_barrier_bh(void);
136 +#endif
137  void rcu_barrier_sched(void);
138  unsigned long get_state_synchronize_rcu(void);
139  void cond_synchronize_rcu(unsigned long oldstate);
140 @@ -85,12 +93,10 @@ unsigned long rcu_batches_started(void);
141  unsigned long rcu_batches_started_bh(void);
142  unsigned long rcu_batches_started_sched(void);
143  unsigned long rcu_batches_completed(void);
144 -unsigned long rcu_batches_completed_bh(void);
145  unsigned long rcu_batches_completed_sched(void);
146  void show_rcu_gp_kthreads(void);
147  
148  void rcu_force_quiescent_state(void);
149 -void rcu_bh_force_quiescent_state(void);
150  void rcu_sched_force_quiescent_state(void);
151  
152  void rcu_idle_enter(void);
153 @@ -105,6 +111,14 @@ extern int rcu_scheduler_active __read_mostly;
154  
155  bool rcu_is_watching(void);
156  
157 +#ifndef CONFIG_PREEMPT_RT_FULL
158 +void rcu_bh_force_quiescent_state(void);
159 +unsigned long rcu_batches_completed_bh(void);
160 +#else
161 +# define rcu_bh_force_quiescent_state  rcu_force_quiescent_state
162 +# define rcu_batches_completed_bh      rcu_batches_completed
163 +#endif
164 +
165  void rcu_all_qs(void);
166  
167  #endif /* __LINUX_RCUTREE_H */
168 diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
169 index f07343b..d52db2c 100644
170 --- a/kernel/rcu/tree.c
171 +++ b/kernel/rcu/tree.c
172 @@ -266,6 +266,7 @@ void rcu_sched_qs(void)
173         }
174  }
175  
176 +#ifndef CONFIG_PREEMPT_RT_FULL
177  void rcu_bh_qs(void)
178  {
179         if (__this_cpu_read(rcu_bh_data.cpu_no_qs.s)) {
180 @@ -275,6 +276,7 @@ void rcu_bh_qs(void)
181                 __this_cpu_write(rcu_bh_data.cpu_no_qs.b.norm, false);
182         }
183  }
184 +#endif
185  
186  static DEFINE_PER_CPU(int, rcu_sched_qs_mask);
187  
188 @@ -459,6 +461,7 @@ unsigned long rcu_batches_completed_sched(void)
189  }
190  EXPORT_SYMBOL_GPL(rcu_batches_completed_sched);
191  
192 +#ifndef CONFIG_PREEMPT_RT_FULL
193  /*
194   * Return the number of RCU BH batches completed thus far for debug & stats.
195   */
196 @@ -486,6 +489,13 @@ void rcu_bh_force_quiescent_state(void)
197  }
198  EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
199  
200 +#else
201 +void rcu_force_quiescent_state(void)
202 +{
203 +}
204 +EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);
205 +#endif
206 +
207  /*
208   * Force a quiescent state for RCU-sched.
209   */
210 @@ -3114,6 +3124,7 @@ void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
211  }
212  EXPORT_SYMBOL_GPL(call_rcu_sched);
213  
214 +#ifndef CONFIG_PREEMPT_RT_FULL
215  /*
216   * Queue an RCU callback for invocation after a quicker grace period.
217   */
218 @@ -3122,6 +3133,7 @@ void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
219         __call_rcu(head, func, &rcu_bh_state, -1, 0);
220  }
221  EXPORT_SYMBOL_GPL(call_rcu_bh);
222 +#endif
223  
224  /*
225   * Queue an RCU callback for lazy invocation after a grace period.
226 @@ -3213,6 +3225,7 @@ void synchronize_sched(void)
227  }
228  EXPORT_SYMBOL_GPL(synchronize_sched);
229  
230 +#ifndef CONFIG_PREEMPT_RT_FULL
231  /**
232   * synchronize_rcu_bh - wait until an rcu_bh grace period has elapsed.
233   *
234 @@ -3239,6 +3252,7 @@ void synchronize_rcu_bh(void)
235                 wait_rcu_gp(call_rcu_bh);
236  }
237  EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
238 +#endif
239  
240  /**
241   * get_state_synchronize_rcu - Snapshot current RCU state
242 @@ -4101,6 +4115,7 @@ static void _rcu_barrier(struct rcu_state *rsp)
243         mutex_unlock(&rsp->barrier_mutex);
244  }
245  
246 +#ifndef CONFIG_PREEMPT_RT_FULL
247  /**
248   * rcu_barrier_bh - Wait until all in-flight call_rcu_bh() callbacks complete.
249   */
250 @@ -4109,6 +4124,7 @@ void rcu_barrier_bh(void)
251         _rcu_barrier(&rcu_bh_state);
252  }
253  EXPORT_SYMBOL_GPL(rcu_barrier_bh);
254 +#endif
255  
256  /**
257   * rcu_barrier_sched - Wait for in-flight call_rcu_sched() callbacks.
258 diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
259 index 5f748c5..9a39046 100644
260 --- a/kernel/rcu/update.c
261 +++ b/kernel/rcu/update.c
262 @@ -276,6 +276,7 @@ int rcu_read_lock_held(void)
263  }
264  EXPORT_SYMBOL_GPL(rcu_read_lock_held);
265  
266 +#ifndef CONFIG_PREEMPT_RT_FULL
267  /**
268   * rcu_read_lock_bh_held() - might we be in RCU-bh read-side critical section?
269   *
270 @@ -302,6 +303,7 @@ int rcu_read_lock_bh_held(void)
271         return in_softirq() || irqs_disabled();
272  }
273  EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held);
274 +#endif
275  
276  #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
277  
278 -- 
279 2.7.4
280