.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0+ */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Read-Copy Update definitions shared among RCU implementations. |
---|
3 | 4 | * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License as published by |
---|
6 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
7 | | - * (at your option) any later version. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope that it will be useful, |
---|
10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | | - * GNU General Public License for more details. |
---|
13 | | - * |
---|
14 | | - * You should have received a copy of the GNU General Public License |
---|
15 | | - * along with this program; if not, you can access it online at |
---|
16 | | - * http://www.gnu.org/licenses/gpl-2.0.html. |
---|
17 | | - * |
---|
18 | 5 | * Copyright IBM Corporation, 2011 |
---|
19 | 6 | * |
---|
20 | | - * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> |
---|
| 7 | + * Author: Paul E. McKenney <paulmck@linux.ibm.com> |
---|
21 | 8 | */ |
---|
22 | 9 | |
---|
23 | 10 | #ifndef __LINUX_RCU_H |
---|
24 | 11 | #define __LINUX_RCU_H |
---|
25 | 12 | |
---|
26 | 13 | #include <trace/events/rcu.h> |
---|
27 | | -#ifdef CONFIG_RCU_TRACE |
---|
28 | | -#define RCU_TRACE(stmt) stmt |
---|
29 | | -#else /* #ifdef CONFIG_RCU_TRACE */ |
---|
30 | | -#define RCU_TRACE(stmt) |
---|
31 | | -#endif /* #else #ifdef CONFIG_RCU_TRACE */ |
---|
32 | 14 | |
---|
33 | | -/* Offset to allow for unmatched rcu_irq_{enter,exit}(). */ |
---|
| 15 | +/* Offset to allow distinguishing irq vs. task-based idle entry/exit. */ |
---|
34 | 16 | #define DYNTICK_IRQ_NONIDLE ((LONG_MAX / 2) + 1) |
---|
35 | 17 | |
---|
36 | 18 | |
---|
.. | .. |
---|
176 | 158 | |
---|
177 | 159 | /* |
---|
178 | 160 | * debug_rcu_head_queue()/debug_rcu_head_unqueue() are used internally |
---|
179 | | - * by call_rcu() and rcu callback execution, and are therefore not part of the |
---|
180 | | - * RCU API. Leaving in rcupdate.h because they are used by all RCU flavors. |
---|
| 161 | + * by call_rcu() and rcu callback execution, and are therefore not part |
---|
| 162 | + * of the RCU API. These are in rcupdate.h because they are used by all |
---|
| 163 | + * RCU implementations. |
---|
181 | 164 | */ |
---|
182 | 165 | |
---|
183 | 166 | #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD |
---|
184 | 167 | # define STATE_RCU_HEAD_READY 0 |
---|
185 | 168 | # define STATE_RCU_HEAD_QUEUED 1 |
---|
186 | 169 | |
---|
187 | | -extern struct debug_obj_descr rcuhead_debug_descr; |
---|
| 170 | +extern const struct debug_obj_descr rcuhead_debug_descr; |
---|
188 | 171 | |
---|
189 | 172 | static inline int debug_rcu_head_queue(struct rcu_head *head) |
---|
190 | 173 | { |
---|
.. | .. |
---|
215 | 198 | } |
---|
216 | 199 | #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ |
---|
217 | 200 | |
---|
218 | | -void kfree(const void *); |
---|
| 201 | +extern int rcu_cpu_stall_suppress_at_boot; |
---|
219 | 202 | |
---|
220 | | -/* |
---|
221 | | - * Reclaim the specified callback, either by invoking it (non-lazy case) |
---|
222 | | - * or freeing it directly (lazy case). Return true if lazy, false otherwise. |
---|
223 | | - */ |
---|
224 | | -static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head) |
---|
| 203 | +static inline bool rcu_stall_is_suppressed_at_boot(void) |
---|
225 | 204 | { |
---|
226 | | - unsigned long offset = (unsigned long)head->func; |
---|
227 | | - |
---|
228 | | - rcu_lock_acquire(&rcu_callback_map); |
---|
229 | | - if (__is_kfree_rcu_offset(offset)) { |
---|
230 | | - RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset);) |
---|
231 | | - kfree((void *)head - offset); |
---|
232 | | - rcu_lock_release(&rcu_callback_map); |
---|
233 | | - return true; |
---|
234 | | - } else { |
---|
235 | | - RCU_TRACE(trace_rcu_invoke_callback(rn, head);) |
---|
236 | | - head->func(head); |
---|
237 | | - rcu_lock_release(&rcu_callback_map); |
---|
238 | | - return false; |
---|
239 | | - } |
---|
| 205 | + return rcu_cpu_stall_suppress_at_boot && !rcu_inkernel_boot_has_ended(); |
---|
240 | 206 | } |
---|
241 | 207 | |
---|
242 | 208 | #ifdef CONFIG_RCU_STALL_COMMON |
---|
243 | 209 | |
---|
| 210 | +extern int rcu_cpu_stall_ftrace_dump; |
---|
244 | 211 | extern int rcu_cpu_stall_suppress; |
---|
| 212 | +extern int rcu_cpu_stall_timeout; |
---|
245 | 213 | int rcu_jiffies_till_stall_check(void); |
---|
| 214 | + |
---|
| 215 | +static inline bool rcu_stall_is_suppressed(void) |
---|
| 216 | +{ |
---|
| 217 | + return rcu_stall_is_suppressed_at_boot() || rcu_cpu_stall_suppress; |
---|
| 218 | +} |
---|
246 | 219 | |
---|
247 | 220 | #define rcu_ftrace_dump_stall_suppress() \ |
---|
248 | 221 | do { \ |
---|
.. | .. |
---|
257 | 230 | } while (0) |
---|
258 | 231 | |
---|
259 | 232 | #else /* #endif #ifdef CONFIG_RCU_STALL_COMMON */ |
---|
| 233 | + |
---|
| 234 | +static inline bool rcu_stall_is_suppressed(void) |
---|
| 235 | +{ |
---|
| 236 | + return rcu_stall_is_suppressed_at_boot(); |
---|
| 237 | +} |
---|
260 | 238 | #define rcu_ftrace_dump_stall_suppress() |
---|
261 | 239 | #define rcu_ftrace_dump_stall_unsuppress() |
---|
262 | 240 | #endif /* #ifdef CONFIG_RCU_STALL_COMMON */ |
---|
.. | .. |
---|
293 | 271 | */ |
---|
294 | 272 | extern void resched_cpu(int cpu); |
---|
295 | 273 | |
---|
296 | | -#if defined(SRCU) || !defined(TINY_RCU) |
---|
| 274 | +#if defined(CONFIG_SRCU) || !defined(CONFIG_TINY_RCU) |
---|
297 | 275 | |
---|
298 | 276 | #include <linux/rcu_node_tree.h> |
---|
299 | 277 | |
---|
.. | .. |
---|
311 | 289 | { |
---|
312 | 290 | int i; |
---|
313 | 291 | |
---|
| 292 | + for (i = 0; i < RCU_NUM_LVLS; i++) |
---|
| 293 | + levelspread[i] = INT_MIN; |
---|
314 | 294 | if (rcu_fanout_exact) { |
---|
315 | 295 | levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf; |
---|
316 | 296 | for (i = rcu_num_lvls - 2; i >= 0; i--) |
---|
.. | .. |
---|
328 | 308 | } |
---|
329 | 309 | } |
---|
330 | 310 | |
---|
331 | | -/* Returns first leaf rcu_node of the specified RCU flavor. */ |
---|
332 | | -#define rcu_first_leaf_node(rsp) ((rsp)->level[rcu_num_lvls - 1]) |
---|
| 311 | +extern void rcu_init_geometry(void); |
---|
| 312 | + |
---|
| 313 | +/* Returns a pointer to the first leaf rcu_node structure. */ |
---|
| 314 | +#define rcu_first_leaf_node() (rcu_state.level[rcu_num_lvls - 1]) |
---|
333 | 315 | |
---|
334 | 316 | /* Is this rcu_node a leaf? */ |
---|
335 | 317 | #define rcu_is_leaf_node(rnp) ((rnp)->level == rcu_num_lvls - 1) |
---|
336 | 318 | |
---|
337 | 319 | /* Is this rcu_node the last leaf? */ |
---|
338 | | -#define rcu_is_last_leaf_node(rsp, rnp) ((rnp) == &(rsp)->node[rcu_num_nodes - 1]) |
---|
| 320 | +#define rcu_is_last_leaf_node(rnp) ((rnp) == &rcu_state.node[rcu_num_nodes - 1]) |
---|
339 | 321 | |
---|
340 | 322 | /* |
---|
341 | | - * Do a full breadth-first scan of the rcu_node structures for the |
---|
342 | | - * specified rcu_state structure. |
---|
| 323 | + * Do a full breadth-first scan of the {s,}rcu_node structures for the |
---|
| 324 | + * specified state structure (for SRCU) or the only rcu_state structure |
---|
| 325 | + * (for RCU). |
---|
343 | 326 | */ |
---|
344 | | -#define rcu_for_each_node_breadth_first(rsp, rnp) \ |
---|
345 | | - for ((rnp) = &(rsp)->node[0]; \ |
---|
346 | | - (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++) |
---|
| 327 | +#define srcu_for_each_node_breadth_first(sp, rnp) \ |
---|
| 328 | + for ((rnp) = &(sp)->node[0]; \ |
---|
| 329 | + (rnp) < &(sp)->node[rcu_num_nodes]; (rnp)++) |
---|
| 330 | +#define rcu_for_each_node_breadth_first(rnp) \ |
---|
| 331 | + srcu_for_each_node_breadth_first(&rcu_state, rnp) |
---|
347 | 332 | |
---|
348 | 333 | /* |
---|
349 | | - * Do a breadth-first scan of the non-leaf rcu_node structures for the |
---|
350 | | - * specified rcu_state structure. Note that if there is a singleton |
---|
351 | | - * rcu_node tree with but one rcu_node structure, this loop is a no-op. |
---|
| 334 | + * Scan the leaves of the rcu_node hierarchy for the rcu_state structure. |
---|
| 335 | + * Note that if there is a singleton rcu_node tree with but one rcu_node |
---|
| 336 | + * structure, this loop -will- visit the rcu_node structure. It is still |
---|
| 337 | + * a leaf node, even if it is also the root node. |
---|
352 | 338 | */ |
---|
353 | | -#define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \ |
---|
354 | | - for ((rnp) = &(rsp)->node[0]; !rcu_is_leaf_node(rsp, rnp); (rnp)++) |
---|
355 | | - |
---|
356 | | -/* |
---|
357 | | - * Scan the leaves of the rcu_node hierarchy for the specified rcu_state |
---|
358 | | - * structure. Note that if there is a singleton rcu_node tree with but |
---|
359 | | - * one rcu_node structure, this loop -will- visit the rcu_node structure. |
---|
360 | | - * It is still a leaf node, even if it is also the root node. |
---|
361 | | - */ |
---|
362 | | -#define rcu_for_each_leaf_node(rsp, rnp) \ |
---|
363 | | - for ((rnp) = rcu_first_leaf_node(rsp); \ |
---|
364 | | - (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++) |
---|
| 339 | +#define rcu_for_each_leaf_node(rnp) \ |
---|
| 340 | + for ((rnp) = rcu_first_leaf_node(); \ |
---|
| 341 | + (rnp) < &rcu_state.node[rcu_num_nodes]; (rnp)++) |
---|
365 | 342 | |
---|
366 | 343 | /* |
---|
367 | 344 | * Iterate over all possible CPUs in a leaf RCU node. |
---|
368 | 345 | */ |
---|
369 | 346 | #define for_each_leaf_node_possible_cpu(rnp, cpu) \ |
---|
370 | | - for ((cpu) = cpumask_next((rnp)->grplo - 1, cpu_possible_mask); \ |
---|
| 347 | + for (WARN_ON_ONCE(!rcu_is_leaf_node(rnp)), \ |
---|
| 348 | + (cpu) = cpumask_next((rnp)->grplo - 1, cpu_possible_mask); \ |
---|
371 | 349 | (cpu) <= rnp->grphi; \ |
---|
372 | 350 | (cpu) = cpumask_next((cpu), cpu_possible_mask)) |
---|
373 | 351 | |
---|
.. | .. |
---|
377 | 355 | #define rcu_find_next_bit(rnp, cpu, mask) \ |
---|
378 | 356 | ((rnp)->grplo + find_next_bit(&(mask), BITS_PER_LONG, (cpu))) |
---|
379 | 357 | #define for_each_leaf_node_cpu_mask(rnp, cpu, mask) \ |
---|
380 | | - for ((cpu) = rcu_find_next_bit((rnp), 0, (mask)); \ |
---|
| 358 | + for (WARN_ON_ONCE(!rcu_is_leaf_node(rnp)), \ |
---|
| 359 | + (cpu) = rcu_find_next_bit((rnp), 0, (mask)); \ |
---|
381 | 360 | (cpu) <= rnp->grphi; \ |
---|
382 | 361 | (cpu) = rcu_find_next_bit((rnp), (cpu) + 1 - (rnp->grplo), (mask))) |
---|
383 | 362 | |
---|
.. | .. |
---|
433 | 412 | #define raw_lockdep_assert_held_rcu_node(p) \ |
---|
434 | 413 | lockdep_assert_held(&ACCESS_PRIVATE(p, lock)) |
---|
435 | 414 | |
---|
436 | | -#endif /* #if defined(SRCU) || !defined(TINY_RCU) */ |
---|
| 415 | +#endif /* #if defined(CONFIG_SRCU) || !defined(CONFIG_TINY_RCU) */ |
---|
| 416 | + |
---|
| 417 | +#ifdef CONFIG_SRCU |
---|
| 418 | +void srcu_init(void); |
---|
| 419 | +#else /* #ifdef CONFIG_SRCU */ |
---|
| 420 | +static inline void srcu_init(void) { } |
---|
| 421 | +#endif /* #else #ifdef CONFIG_SRCU */ |
---|
437 | 422 | |
---|
438 | 423 | #ifdef CONFIG_TINY_RCU |
---|
439 | 424 | /* Tiny RCU doesn't expedite, as its purpose in life is instead to be tiny. */ |
---|
.. | .. |
---|
448 | 433 | void rcu_expedite_gp(void); |
---|
449 | 434 | void rcu_unexpedite_gp(void); |
---|
450 | 435 | void rcupdate_announce_bootup_oddness(void); |
---|
| 436 | +void show_rcu_tasks_gp_kthreads(void); |
---|
451 | 437 | void rcu_request_urgent_qs_task(struct task_struct *t); |
---|
452 | 438 | #endif /* #else #ifdef CONFIG_TINY_RCU */ |
---|
453 | 439 | |
---|
.. | .. |
---|
457 | 443 | |
---|
458 | 444 | enum rcutorture_type { |
---|
459 | 445 | RCU_FLAVOR, |
---|
460 | | - RCU_BH_FLAVOR, |
---|
461 | | - RCU_SCHED_FLAVOR, |
---|
462 | 446 | RCU_TASKS_FLAVOR, |
---|
| 447 | + RCU_TASKS_RUDE_FLAVOR, |
---|
| 448 | + RCU_TASKS_TRACING_FLAVOR, |
---|
| 449 | + RCU_TRIVIAL_FLAVOR, |
---|
463 | 450 | SRCU_FLAVOR, |
---|
464 | 451 | INVALID_RCU_FLAVOR |
---|
465 | 452 | }; |
---|
466 | 453 | |
---|
467 | | -#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU) |
---|
| 454 | +#if defined(CONFIG_TREE_RCU) |
---|
468 | 455 | void rcutorture_get_gp_data(enum rcutorture_type test_type, int *flags, |
---|
469 | 456 | unsigned long *gp_seq); |
---|
470 | | -void rcutorture_record_progress(unsigned long vernum); |
---|
471 | 457 | void do_trace_rcu_torture_read(const char *rcutorturename, |
---|
472 | 458 | struct rcu_head *rhp, |
---|
473 | 459 | unsigned long secs, |
---|
474 | 460 | unsigned long c_old, |
---|
475 | 461 | unsigned long c); |
---|
| 462 | +void rcu_gp_set_torture_wait(int duration); |
---|
476 | 463 | #else |
---|
477 | 464 | static inline void rcutorture_get_gp_data(enum rcutorture_type test_type, |
---|
478 | 465 | int *flags, unsigned long *gp_seq) |
---|
.. | .. |
---|
480 | 467 | *flags = 0; |
---|
481 | 468 | *gp_seq = 0; |
---|
482 | 469 | } |
---|
483 | | -static inline void rcutorture_record_progress(unsigned long vernum) { } |
---|
484 | 470 | #ifdef CONFIG_RCU_TRACE |
---|
485 | 471 | void do_trace_rcu_torture_read(const char *rcutorturename, |
---|
486 | 472 | struct rcu_head *rhp, |
---|
.. | .. |
---|
491 | 477 | #define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \ |
---|
492 | 478 | do { } while (0) |
---|
493 | 479 | #endif |
---|
| 480 | +static inline void rcu_gp_set_torture_wait(int duration) { } |
---|
| 481 | +#endif |
---|
| 482 | + |
---|
| 483 | +#if IS_ENABLED(CONFIG_RCU_TORTURE_TEST) || IS_MODULE(CONFIG_RCU_TORTURE_TEST) |
---|
| 484 | +long rcutorture_sched_setaffinity(pid_t pid, const struct cpumask *in_mask); |
---|
494 | 485 | #endif |
---|
495 | 486 | |
---|
496 | 487 | #ifdef CONFIG_TINY_SRCU |
---|
.. | .. |
---|
514 | 505 | #endif |
---|
515 | 506 | |
---|
516 | 507 | #ifdef CONFIG_TINY_RCU |
---|
| 508 | +static inline bool rcu_dynticks_zero_in_eqs(int cpu, int *vp) { return false; } |
---|
517 | 509 | static inline unsigned long rcu_get_gp_seq(void) { return 0; } |
---|
518 | | -static inline unsigned long rcu_bh_get_gp_seq(void) { return 0; } |
---|
519 | | -static inline unsigned long rcu_sched_get_gp_seq(void) { return 0; } |
---|
520 | 510 | static inline unsigned long rcu_exp_batches_completed(void) { return 0; } |
---|
521 | | -static inline unsigned long rcu_exp_batches_completed_sched(void) { return 0; } |
---|
522 | 511 | static inline unsigned long |
---|
523 | 512 | srcu_batches_completed(struct srcu_struct *sp) { return 0; } |
---|
524 | 513 | static inline void rcu_force_quiescent_state(void) { } |
---|
525 | | -static inline void rcu_bh_force_quiescent_state(void) { } |
---|
526 | | -static inline void rcu_sched_force_quiescent_state(void) { } |
---|
527 | 514 | static inline void show_rcu_gp_kthreads(void) { } |
---|
528 | 515 | static inline int rcu_get_gp_kthreads_prio(void) { return 0; } |
---|
| 516 | +static inline void rcu_fwd_progress_check(unsigned long j) { } |
---|
529 | 517 | #else /* #ifdef CONFIG_TINY_RCU */ |
---|
| 518 | +bool rcu_dynticks_zero_in_eqs(int cpu, int *vp); |
---|
530 | 519 | unsigned long rcu_get_gp_seq(void); |
---|
531 | | -unsigned long rcu_bh_get_gp_seq(void); |
---|
532 | | -unsigned long rcu_sched_get_gp_seq(void); |
---|
533 | 520 | unsigned long rcu_exp_batches_completed(void); |
---|
534 | | -unsigned long rcu_exp_batches_completed_sched(void); |
---|
535 | 521 | unsigned long srcu_batches_completed(struct srcu_struct *sp); |
---|
536 | 522 | void show_rcu_gp_kthreads(void); |
---|
537 | 523 | int rcu_get_gp_kthreads_prio(void); |
---|
| 524 | +void rcu_fwd_progress_check(unsigned long j); |
---|
538 | 525 | void rcu_force_quiescent_state(void); |
---|
539 | | -void rcu_bh_force_quiescent_state(void); |
---|
540 | | -void rcu_sched_force_quiescent_state(void); |
---|
541 | 526 | extern struct workqueue_struct *rcu_gp_wq; |
---|
542 | 527 | extern struct workqueue_struct *rcu_par_gp_wq; |
---|
543 | 528 | #endif /* #else #ifdef CONFIG_TINY_RCU */ |
---|
544 | 529 | |
---|
545 | 530 | #ifdef CONFIG_RCU_NOCB_CPU |
---|
546 | 531 | bool rcu_is_nocb_cpu(int cpu); |
---|
| 532 | +void rcu_bind_current_to_nocb(void); |
---|
547 | 533 | #else |
---|
548 | 534 | static inline bool rcu_is_nocb_cpu(int cpu) { return false; } |
---|
| 535 | +static inline void rcu_bind_current_to_nocb(void) { } |
---|
549 | 536 | #endif |
---|
550 | 537 | |
---|
551 | 538 | #endif /* __LINUX_RCU_H */ |
---|