| 1 |
|
| 2 | |
| 3 | * Read-Copy Update definitions shared among RCU implementations.
|
| 4 | *
|
| 5 | * Copyright IBM Corporation, 2011
|
| 6 | *
|
| 7 | * Author: Paul E. McKenney <[email protected]>
|
| 8 |
|
| 9 |
|
| 10 | #ifndef __LINUX_RCU_H
|
| 11 | #define __LINUX_RCU_H
|
| 12 |
|
| 13 | #include <linux/slab.h>
|
| 14 | #include <trace/events/rcu.h>
|
| 15 |
|
| 16 | |
| 17 | * Grace-period counter management.
|
| 18 | *
|
| 19 | * The two least significant bits contain the control flags.
|
| 20 | * The most significant bits contain the grace-period sequence counter.
|
| 21 | *
|
| 22 | * When both control flags are zero, no grace period is in progress.
|
| 23 | * When either bit is non-zero, a grace period has started and is in
|
| 24 | * progress. When the grace period completes, the control flags are reset
|
| 25 | * to 0 and the grace-period sequence counter is incremented.
|
| 26 | *
|
| 27 | * However some specific RCU usages make use of custom values.
|
| 28 | *
|
| 29 | * SRCU special control values:
|
| 30 | *
|
| 31 | * SRCU_SNP_INIT_SEQ : Invalid/init value set when SRCU node
|
| 32 | * is initialized.
|
| 33 | *
|
| 34 | * SRCU_STATE_IDLE : No SRCU gp is in progress
|
| 35 | *
|
| 36 | * SRCU_STATE_SCAN1 : State set by rcu_seq_start(). Indicates
|
| 37 | * we are scanning the readers on the slot
|
| 38 | * defined as inactive (there might well
|
| 39 | * be pending readers that will use that
|
| 40 | * index, but their number is bounded).
|
| 41 | *
|
| 42 | * SRCU_STATE_SCAN2 : State set manually via rcu_seq_set_state()
|
| 43 | * Indicates we are flipping the readers
|
| 44 | * index and then scanning the readers on the
|
| 45 | * slot newly designated as inactive (again,
|
| 46 | * the number of pending readers that will use
|
| 47 | * this inactive index is bounded).
|
| 48 | *
|
| 49 | * RCU polled GP special control values:
|
| 50 | *
|
| 51 | * RCU_GET_STATE_COMPLETED : State value indicating an already-completed
|
| 52 | * polled GP has completed. This value covers
|
| 53 | * both the state and the counter of the
|
| 54 | * grace-period sequence number.
|
| 55 | *
|
| 56 | * RCU_GET_STATE_NOT_TRACKED : State value indicating that a GP component
|
| 57 | * is not tracked by this subsystem and should
|
| 58 | * not be checked. Used by SRCU and RCU Tasks
|
| 59 | * which do not track expedited GPs, to prevent
|
| 60 | * false-positive completion when their
|
| 61 | * gp_seq entries are checked via
|
| 62 | * poll_state_synchronize_rcu_full().
|
| 63 |
|
| 64 |
|
| 65 |
|
| 66 | #define RCU_GET_STATE_COMPLETED 0x1
|
| 67 | #define RCU_GET_STATE_NOT_TRACKED 0x2
|
| 68 |
|
| 69 |
|
| 70 | #define RCU_SEQ_GP (RCU_SEQ_STATE_MASK + 1)
|
| 71 |
|
| 72 | extern int sysctl_sched_rt_runtime;
|
| 73 |
|
| 74 | |
| 75 | * Return the counter portion of a sequence number previously returned
|
| 76 | * by rcu_seq_snap() or rcu_seq_current().
|
| 77 |
|
| 78 | static inline unsigned long rcu_seq_ctr(unsigned long s)
|
| 79 | {
|
| 80 | return s >> RCU_SEQ_CTR_SHIFT;
|
| 81 | }
|
| 82 |
|
| 83 | |
| 84 | * Return the state portion of a sequence number previously returned
|
| 85 | * by rcu_seq_snap() or rcu_seq_current().
|
| 86 |
|
| 87 | static inline int rcu_seq_state(unsigned long s)
|
| 88 | {
|
| 89 | return s & RCU_SEQ_STATE_MASK;
|
| 90 | }
|
| 91 |
|
| 92 | |
| 93 | * Set the state portion of the pointed-to sequence number.
|
| 94 | * The caller is responsible for preventing conflicting updates.
|
| 95 |
|
| 96 | static inline void rcu_seq_set_state(unsigned long *sp, int newstate)
|
| 97 | {
|
| 98 | WARN_ON_ONCE(newstate & ~RCU_SEQ_STATE_MASK);
|
| 99 | WRITE_ONCE(*sp, (*sp & ~RCU_SEQ_STATE_MASK) + newstate);
|
| 100 | }
|
| 101 |
|
| 102 |
|
| 103 | static inline void rcu_seq_start(unsigned long *sp)
|
| 104 | {
|
| 105 | WRITE_ONCE(*sp, *sp + 1);
|
| 106 | smp_mb();
|
| 107 | WARN_ON_ONCE(rcu_seq_state(*sp) != 1);
|
| 108 | }
|
| 109 |
|
| 110 |
|
| 111 | static inline unsigned long rcu_seq_endval(unsigned long *sp)
|
| 112 | {
|
| 113 | return (*sp | RCU_SEQ_STATE_MASK) + 1;
|
| 114 | }
|
| 115 |
|
| 116 |
|
| 117 | static inline void rcu_seq_end(unsigned long *sp)
|
| 118 | {
|
| 119 | smp_mb();
|
| 120 | WARN_ON_ONCE(!rcu_seq_state(*sp));
|
| 121 | WRITE_ONCE(*sp, rcu_seq_endval(sp));
|
| 122 | }
|
| 123 |
|
| 124 | |
| 125 | * rcu_seq_snap - Take a snapshot of the update side's sequence number.
|
| 126 | *
|
| 127 | * This function returns the earliest value of the grace-period sequence number
|
| 128 | * that will indicate that a full grace period has elapsed since the current
|
| 129 | * time. Once the grace-period sequence number has reached this value, it will
|
| 130 | * be safe to invoke all callbacks that have been registered prior to the
|
| 131 | * current time. This value is the current grace-period number plus two to the
|
| 132 | * power of the number of low-order bits reserved for state, then rounded up to
|
| 133 | * the next value in which the state bits are all zero.
|
| 134 |
|
| 135 | static inline unsigned long rcu_seq_snap(unsigned long *sp)
|
| 136 | {
|
| 137 | unsigned long s;
|
| 138 |
|
| 139 | s = (READ_ONCE(*sp) + 2 * RCU_SEQ_STATE_MASK + 1) & ~RCU_SEQ_STATE_MASK;
|
| 140 | smp_mb();
|
| 141 | return s;
|
| 142 | }
|
| 143 |
|
| 144 |
|
| 145 | static inline unsigned long rcu_seq_current(unsigned long *sp)
|
| 146 | {
|
| 147 | return READ_ONCE(*sp);
|
| 148 | }
|
| 149 |
|
| 150 | |
| 151 | * Given a snapshot from rcu_seq_snap(), determine whether or not the
|
| 152 | * corresponding update-side operation has started.
|
| 153 |
|
| 154 | static inline bool rcu_seq_started(unsigned long *sp, unsigned long s)
|
| 155 | {
|
| 156 | return ULONG_CMP_LT((s - 1) & ~RCU_SEQ_STATE_MASK, READ_ONCE(*sp));
|
| 157 | }
|
| 158 |
|
| 159 | |
| 160 | * Given a snapshot from rcu_seq_snap(), determine whether or not a
|
| 161 | * full update-side operation has occurred.
|
| 162 |
|
| 163 | static inline bool rcu_seq_done(unsigned long *sp, unsigned long s)
|
| 164 | {
|
| 165 | return ULONG_CMP_GE(READ_ONCE(*sp), s);
|
| 166 | }
|
| 167 |
|
| 168 | |
| 169 | * Given a snapshot from rcu_seq_snap(), determine whether or not a
|
| 170 | * full update-side operation has occurred, but do not allow the
|
| 171 | * (ULONG_MAX / 2) safety-factor/guard-band.
|
| 172 | *
|
| 173 | * The token returned by get_state_synchronize_rcu_full() is based on
|
| 174 | * rcu_state.gp_seq but it is tested in poll_state_synchronize_rcu_full()
|
| 175 | * against the root rnp->gp_seq. Since rcu_seq_start() is first called
|
| 176 | * on rcu_state.gp_seq and only later reflected on the root rnp->gp_seq,
|
| 177 | * it is possible that rcu_seq_snap(rcu_state.gp_seq) returns 2 full grace
|
| 178 | * periods ahead of the root rnp->gp_seq. To prevent false-positives with the
|
| 179 | * full polling API that a wrap around instantly completed the GP, when nothing
|
| 180 | * like that happened, adjust for the 2 GPs in the ULONG_CMP_LT().
|
| 181 |
|
| 182 | static inline bool rcu_seq_done_exact(unsigned long *sp, unsigned long s)
|
| 183 | {
|
| 184 | unsigned long cur_s = READ_ONCE(*sp);
|
| 185 |
|
| 186 | return ULONG_CMP_GE(cur_s, s) || ULONG_CMP_LT(cur_s, s - (2 * RCU_SEQ_GP));
|
| 187 | }
|
| 188 |
|
| 189 | |
| 190 | * Has a grace period completed since the time the old gp_seq was collected?
|
| 191 |
|
| 192 | static inline bool rcu_seq_completed_gp(unsigned long old, unsigned long new)
|
| 193 | {
|
| 194 | return ULONG_CMP_LT(old, new & ~RCU_SEQ_STATE_MASK);
|
| 195 | }
|
| 196 |
|
| 197 | |
| 198 | * Has a grace period started since the time the old gp_seq was collected?
|
| 199 |
|
| 200 | static inline bool rcu_seq_new_gp(unsigned long old, unsigned long new)
|
| 201 | {
|
| 202 | return ULONG_CMP_LT((old + RCU_SEQ_STATE_MASK) & ~RCU_SEQ_STATE_MASK,
|
| 203 | new);
|
| 204 | }
|
| 205 |
|
| 206 | |
| 207 | * Roughly how many full grace periods have elapsed between the collection
|
| 208 | * of the two specified grace periods?
|
| 209 |
|
| 210 | static inline unsigned long rcu_seq_diff(unsigned long new, unsigned long old)
|
| 211 | {
|
| 212 | unsigned long rnd_diff;
|
| 213 |
|
| 214 | if (old == new)
|
| 215 | return 0;
|
| 216 | |
| 217 | * Compute the number of grace periods (still shifted up), plus
|
| 218 | * one if either of new and old is not an exact grace period.
|
| 219 |
|
| 220 | rnd_diff = (new & ~RCU_SEQ_STATE_MASK) -
|
| 221 | ((old + RCU_SEQ_STATE_MASK) & ~RCU_SEQ_STATE_MASK) +
|
| 222 | ((new & RCU_SEQ_STATE_MASK) || (old & RCU_SEQ_STATE_MASK));
|
| 223 | if (ULONG_CMP_GE(RCU_SEQ_STATE_MASK, rnd_diff))
|
| 224 | return 1;
|
| 225 | return ((rnd_diff - RCU_SEQ_STATE_MASK - 1) >> RCU_SEQ_CTR_SHIFT) + 2;
|
| 226 | }
|
| 227 |
|
| 228 | |
| 229 | * debug_rcu_head_queue()/debug_rcu_head_unqueue() are used internally
|
| 230 | * by call_rcu() and rcu callback execution, and are therefore not part
|
| 231 | * of the RCU API. These are in rcupdate.h because they are used by all
|
| 232 | * RCU implementations.
|
| 233 |
|
| 234 |
|
| 235 | #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
|
| 236 | # define STATE_RCU_HEAD_READY 0
|
| 237 | # define STATE_RCU_HEAD_QUEUED 1
|
| 238 |
|
| 239 | extern const struct debug_obj_descr rcuhead_debug_descr;
|
| 240 |
|
| 241 | static inline int debug_rcu_head_queue(struct rcu_head *head)
|
| 242 | {
|
| 243 | int r1;
|
| 244 |
|
| 245 | r1 = debug_object_activate(head, &rcuhead_debug_descr);
|
| 246 | debug_object_active_state(head, &rcuhead_debug_descr,
|
| 247 | STATE_RCU_HEAD_READY,
|
| 248 | STATE_RCU_HEAD_QUEUED);
|
| 249 | return r1;
|
| 250 | }
|
| 251 |
|
| 252 | static inline void debug_rcu_head_unqueue(struct rcu_head *head)
|
| 253 | {
|
| 254 | debug_object_active_state(head, &rcuhead_debug_descr,
|
| 255 | STATE_RCU_HEAD_QUEUED,
|
| 256 | STATE_RCU_HEAD_READY);
|
| 257 | debug_object_deactivate(head, &rcuhead_debug_descr);
|
| 258 | }
|
| 259 | #else
|
| 260 | static inline int debug_rcu_head_queue(struct rcu_head *head)
|
| 261 | {
|
| 262 | return 0;
|
| 263 | }
|
| 264 |
|
| 265 | static inline void debug_rcu_head_unqueue(struct rcu_head *head)
|
| 266 | {
|
| 267 | }
|
| 268 | #endif
|
| 269 |
|
| 270 | static inline void debug_rcu_head_callback(struct rcu_head *rhp)
|
| 271 | {
|
| 272 | if (unlikely(!rhp->func))
|
| 273 | kmem_dump_obj(rhp);
|
| 274 | }
|
| 275 |
|
| 276 | static inline bool rcu_barrier_cb_is_done(struct rcu_head *rhp)
|
| 277 | {
|
| 278 | return rhp->next == rhp;
|
| 279 | }
|
| 280 |
|
| 281 | extern int rcu_cpu_stall_suppress_at_boot;
|
| 282 |
|
| 283 | static inline bool rcu_stall_is_suppressed_at_boot(void)
|
| 284 | {
|
| 285 | return rcu_cpu_stall_suppress_at_boot && !rcu_inkernel_boot_has_ended();
|
| 286 | }
|
| 287 |
|
| 288 | extern int rcu_cpu_stall_notifiers;
|
| 289 |
|
| 290 | #ifdef CONFIG_RCU_STALL_COMMON
|
| 291 |
|
| 292 | extern int rcu_cpu_stall_ftrace_dump;
|
| 293 | extern int rcu_cpu_stall_suppress;
|
| 294 | extern int rcu_cpu_stall_timeout;
|
| 295 | extern int rcu_exp_cpu_stall_timeout;
|
| 296 | extern int rcu_cpu_stall_cputime;
|
| 297 | extern bool rcu_exp_stall_task_details __read_mostly;
|
| 298 | int rcu_jiffies_till_stall_check(void);
|
| 299 | int rcu_exp_jiffies_till_stall_check(void);
|
| 300 |
|
| 301 | static inline bool rcu_stall_is_suppressed(void)
|
| 302 | {
|
| 303 | return rcu_stall_is_suppressed_at_boot() || rcu_cpu_stall_suppress;
|
| 304 | }
|
| 305 |
|
| 306 | #define rcu_ftrace_dump_stall_suppress() \
|
| 307 | do { \
|
| 308 | if (!rcu_cpu_stall_suppress) \
|
| 309 | rcu_cpu_stall_suppress = 3; \
|
| 310 | } while (0)
|
| 311 |
|
| 312 | #define rcu_ftrace_dump_stall_unsuppress() \
|
| 313 | do { \
|
| 314 | if (rcu_cpu_stall_suppress == 3) \
|
| 315 | rcu_cpu_stall_suppress = 0; \
|
| 316 | } while (0)
|
| 317 |
|
| 318 | #else
|
| 319 |
|
| 320 | static inline bool rcu_stall_is_suppressed(void)
|
| 321 | {
|
| 322 | return rcu_stall_is_suppressed_at_boot();
|
| 323 | }
|
| 324 | #define rcu_ftrace_dump_stall_suppress()
|
| 325 | #define rcu_ftrace_dump_stall_unsuppress()
|
| 326 | #endif
|
| 327 |
|
| 328 | |
| 329 | * Strings used in tracepoints need to be exported via the
|
| 330 | * tracing system such that tools like perf and trace-cmd can
|
| 331 | * translate the string address pointers to actual text.
|
| 332 |
|
| 333 | #define TPS(x) tracepoint_string(x)
|
| 334 |
|
| 335 | |
| 336 | * Dump the ftrace buffer, but only one time per callsite per boot.
|
| 337 |
|
| 338 | #define rcu_ftrace_dump(oops_dump_mode) \
|
| 339 | do { \
|
| 340 | static atomic_t ___rfd_beenhere = ATOMIC_INIT(0); \
|
| 341 | \
|
| 342 | if (!atomic_read(&___rfd_beenhere) && \
|
| 343 | !atomic_xchg(&___rfd_beenhere, 1)) { \
|
| 344 | tracing_off(); \
|
| 345 | rcu_ftrace_dump_stall_suppress(); \
|
| 346 | ftrace_dump(oops_dump_mode); \
|
| 347 | rcu_ftrace_dump_stall_unsuppress(); \
|
| 348 | } \
|
| 349 | } while (0)
|
| 350 |
|
| 351 | void rcu_early_boot_tests(void);
|
| 352 | void rcu_test_sync_prims(void);
|
| 353 |
|
| 354 | |
| 355 | * This function really isn't for public consumption, but RCU is special in
|
| 356 | * that context switches can allow the state machine to make progress.
|
| 357 |
|
| 358 | extern void resched_cpu(int cpu);
|
| 359 |
|
| 360 | #if !defined(CONFIG_TINY_RCU)
|
| 361 |
|
| 362 | #include <linux/rcu_node_tree.h>
|
| 363 |
|
| 364 | extern int rcu_num_lvls;
|
| 365 | extern int num_rcu_lvl[];
|
| 366 | extern int rcu_num_nodes;
|
| 367 | static bool rcu_fanout_exact;
|
| 368 | static int rcu_fanout_leaf;
|
| 369 |
|
| 370 | |
| 371 | * Compute the per-level fanout, either using the exact fanout specified
|
| 372 | * or balancing the tree, depending on the rcu_fanout_exact boot parameter.
|
| 373 |
|
| 374 | static inline void rcu_init_levelspread(int *levelspread, const int *levelcnt)
|
| 375 | {
|
| 376 | int i;
|
| 377 |
|
| 378 | for (i = 0; i < RCU_NUM_LVLS; i++)
|
| 379 | levelspread[i] = INT_MIN;
|
| 380 | if (rcu_fanout_exact) {
|
| 381 | levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf;
|
| 382 | for (i = rcu_num_lvls - 2; i >= 0; i--)
|
| 383 | levelspread[i] = RCU_FANOUT;
|
| 384 | } else {
|
| 385 | int ccur;
|
| 386 | int cprv;
|
| 387 |
|
| 388 | cprv = nr_cpu_ids;
|
| 389 | for (i = rcu_num_lvls - 1; i >= 0; i--) {
|
| 390 | ccur = levelcnt[i];
|
| 391 | levelspread[i] = (cprv + ccur - 1) / ccur;
|
| 392 | cprv = ccur;
|
| 393 | }
|
| 394 | }
|
| 395 | }
|
| 396 |
|
| 397 | extern void rcu_init_geometry(void);
|
| 398 |
|
| 399 |
|
| 400 | #define rcu_first_leaf_node() (rcu_state.level[rcu_num_lvls - 1])
|
| 401 |
|
| 402 |
|
| 403 | #define rcu_is_leaf_node(rnp) ((rnp)->level == rcu_num_lvls - 1)
|
| 404 |
|
| 405 |
|
| 406 | #define rcu_is_last_leaf_node(rnp) ((rnp) == &rcu_state.node[rcu_num_nodes - 1])
|
| 407 |
|
| 408 | |
| 409 | * Do a full breadth-first scan of the {s,}rcu_node structures for the
|
| 410 | * specified state structure (for SRCU) or the only rcu_state structure
|
| 411 | * (for RCU).
|
| 412 |
|
| 413 | #define _rcu_for_each_node_breadth_first(sp, rnp) \
|
| 414 | for ((rnp) = &(sp)->node[0]; \
|
| 415 | (rnp) < &(sp)->node[rcu_num_nodes]; (rnp)++)
|
| 416 | #define rcu_for_each_node_breadth_first(rnp) \
|
| 417 | _rcu_for_each_node_breadth_first(&rcu_state, rnp)
|
| 418 | #define srcu_for_each_node_breadth_first(ssp, rnp) \
|
| 419 | _rcu_for_each_node_breadth_first(ssp->srcu_sup, rnp)
|
| 420 |
|
| 421 | |
| 422 | * Scan the leaves of the rcu_node hierarchy for the rcu_state structure.
|
| 423 | * Note that if there is a singleton rcu_node tree with but one rcu_node
|
| 424 | * structure, this loop -will- visit the rcu_node structure. It is still
|
| 425 | * a leaf node, even if it is also the root node.
|
| 426 |
|
| 427 | #define rcu_for_each_leaf_node(rnp) \
|
| 428 | for ((rnp) = rcu_first_leaf_node(); \
|
| 429 | (rnp) < &rcu_state.node[rcu_num_nodes]; (rnp)++)
|
| 430 |
|
| 431 | |
| 432 | * Iterate over all possible CPUs in a leaf RCU node.
|
| 433 |
|
| 434 | #define for_each_leaf_node_possible_cpu(rnp, cpu) \
|
| 435 | for (WARN_ON_ONCE(!rcu_is_leaf_node(rnp)), \
|
| 436 | (cpu) = cpumask_next((rnp)->grplo - 1, cpu_possible_mask); \
|
| 437 | (cpu) <= rnp->grphi; \
|
| 438 | (cpu) = cpumask_next((cpu), cpu_possible_mask))
|
| 439 |
|
| 440 | |
| 441 | * Iterate over all CPUs in a leaf RCU node's specified mask.
|
| 442 |
|
| 443 | #define rcu_find_next_bit(rnp, cpu, mask) \
|
| 444 | ((rnp)->grplo + find_next_bit(&(mask), BITS_PER_LONG, (cpu)))
|
| 445 | #define for_each_leaf_node_cpu_mask(rnp, cpu, mask) \
|
| 446 | for (WARN_ON_ONCE(!rcu_is_leaf_node(rnp)), \
|
| 447 | (cpu) = rcu_find_next_bit((rnp), 0, (mask)); \
|
| 448 | (cpu) <= rnp->grphi; \
|
| 449 | (cpu) = rcu_find_next_bit((rnp), (cpu) + 1 - (rnp->grplo), (mask)))
|
| 450 |
|
| 451 | #endif
|
| 452 |
|
| 453 | #if !defined(CONFIG_TINY_RCU) || defined(CONFIG_TASKS_RCU_GENERIC)
|
| 454 |
|
| 455 | |
| 456 | * Wrappers for the rcu_node::lock acquire and release.
|
| 457 | *
|
| 458 | * Because the rcu_nodes form a tree, the tree traversal locking will observe
|
| 459 | * different lock values, this in turn means that an UNLOCK of one level
|
| 460 | * followed by a LOCK of another level does not imply a full memory barrier;
|
| 461 | * and most importantly transitivity is lost.
|
| 462 | *
|
| 463 | * In order to restore full ordering between tree levels, augment the regular
|
| 464 | * lock acquire functions with smp_mb__after_unlock_lock().
|
| 465 | *
|
| 466 | * As ->lock of struct rcu_node is a __private field, therefore one should use
|
| 467 | * these wrappers rather than directly call raw_spin_{lock,unlock}* on ->lock.
|
| 468 |
|
| 469 | #define raw_spin_lock_rcu_node(p) \
|
| 470 | do { \
|
| 471 | raw_spin_lock(&ACCESS_PRIVATE(p, lock)); \
|
| 472 | smp_mb__after_unlock_lock(); \
|
| 473 | } while (0)
|
| 474 |
|
| 475 | #define raw_spin_unlock_rcu_node(p) \
|
| 476 | do { \
|
| 477 | lockdep_assert_irqs_disabled(); \
|
| 478 | raw_spin_unlock(&ACCESS_PRIVATE(p, lock)); \
|
| 479 | } while (0)
|
| 480 |
|
| 481 | #define raw_spin_lock_irq_rcu_node(p) \
|
| 482 | do { \
|
| 483 | raw_spin_lock_irq(&ACCESS_PRIVATE(p, lock)); \
|
| 484 | smp_mb__after_unlock_lock(); \
|
| 485 | } while (0)
|
| 486 |
|
| 487 | #define raw_spin_unlock_irq_rcu_node(p) \
|
| 488 | do { \
|
| 489 | lockdep_assert_irqs_disabled(); \
|
| 490 | raw_spin_unlock_irq(&ACCESS_PRIVATE(p, lock)); \
|
| 491 | } while (0)
|
| 492 |
|
| 493 | #define raw_spin_lock_irqsave_rcu_node(p, flags) \
|
| 494 | do { \
|
| 495 | raw_spin_lock_irqsave(&ACCESS_PRIVATE(p, lock), flags); \
|
| 496 | smp_mb__after_unlock_lock(); \
|
| 497 | } while (0)
|
| 498 |
|
| 499 | #define raw_spin_unlock_irqrestore_rcu_node(p, flags) \
|
| 500 | do { \
|
| 501 | lockdep_assert_irqs_disabled(); \
|
| 502 | raw_spin_unlock_irqrestore(&ACCESS_PRIVATE(p, lock), flags); \
|
| 503 | } while (0)
|
| 504 |
|
| 505 | #define raw_spin_trylock_rcu_node(p) \
|
| 506 | ({ \
|
| 507 | bool ___locked = raw_spin_trylock(&ACCESS_PRIVATE(p, lock)); \
|
| 508 | \
|
| 509 | if (___locked) \
|
| 510 | smp_mb__after_unlock_lock(); \
|
| 511 | ___locked; \
|
| 512 | })
|
| 513 |
|
| 514 | #define raw_spin_trylock_irqsave_rcu_node(p, flags) \
|
| 515 | ({ \
|
| 516 | bool ___locked = raw_spin_trylock_irqsave(&ACCESS_PRIVATE(p, lock), flags); \
|
| 517 | \
|
| 518 | if (___locked) \
|
| 519 | smp_mb__after_unlock_lock(); \
|
| 520 | ___locked; \
|
| 521 | })
|
| 522 |
|
| 523 | #define raw_lockdep_assert_held_rcu_node(p) \
|
| 524 | lockdep_assert_held(&ACCESS_PRIVATE(p, lock))
|
| 525 |
|
| 526 | #endif |
| 527 |
|
| 528 | #ifdef CONFIG_TINY_RCU
|
| 529 |
|
| 530 | static inline bool rcu_gp_is_normal(void) { return true; }
|
| 531 | static inline bool rcu_gp_is_expedited(void) { return false; }
|
| 532 | static inline bool rcu_async_should_hurry(void) { return false; }
|
| 533 | static inline void rcu_expedite_gp(void) { }
|
| 534 | static inline void rcu_unexpedite_gp(void) { }
|
| 535 | static inline void rcu_async_hurry(void) { }
|
| 536 | static inline void rcu_async_relax(void) { }
|
| 537 | static inline bool rcu_cpu_online(int cpu) { return true; }
|
| 538 | #else
|
| 539 | bool rcu_gp_is_normal(void);
|
| 540 | bool rcu_gp_is_expedited(void);
|
| 541 | bool rcu_async_should_hurry(void);
|
| 542 | void rcu_expedite_gp(void);
|
| 543 | void rcu_unexpedite_gp(void);
|
| 544 | void rcu_async_hurry(void);
|
| 545 | void rcu_async_relax(void);
|
| 546 | void rcupdate_announce_bootup_oddness(void);
|
| 547 | bool rcu_cpu_online(int cpu);
|
| 548 | #ifdef CONFIG_TASKS_RCU_GENERIC
|
| 549 | void show_rcu_tasks_gp_kthreads(void);
|
| 550 | #else
|
| 551 | static inline void show_rcu_tasks_gp_kthreads(void) {}
|
| 552 | #endif
|
| 553 | #endif
|
| 554 |
|
| 555 | #ifdef CONFIG_TASKS_RCU
|
| 556 | struct task_struct *get_rcu_tasks_gp_kthread(void);
|
| 557 | void rcu_tasks_get_gp_data(int *flags, unsigned long *gp_seq);
|
| 558 | #endif |
| 559 |
|
| 560 | #ifdef CONFIG_TASKS_RUDE_RCU
|
| 561 | struct task_struct *get_rcu_tasks_rude_gp_kthread(void);
|
| 562 | void rcu_tasks_rude_get_gp_data(int *flags, unsigned long *gp_seq);
|
| 563 | #endif |
| 564 |
|
| 565 | #ifdef CONFIG_TASKS_RCU_GENERIC
|
| 566 | void tasks_cblist_init_generic(void);
|
| 567 | #else
|
| 568 | static inline void tasks_cblist_init_generic(void) { }
|
| 569 | #endif
|
| 570 |
|
| 571 | #define RCU_SCHEDULER_INACTIVE 0
|
| 572 | #define RCU_SCHEDULER_INIT 1
|
| 573 | #define RCU_SCHEDULER_RUNNING 2
|
| 574 |
|
| 575 | enum rcutorture_type {
|
| 576 | RCU_FLAVOR,
|
| 577 | RCU_TASKS_FLAVOR,
|
| 578 | RCU_TASKS_RUDE_FLAVOR,
|
| 579 | RCU_TASKS_TRACING_FLAVOR,
|
| 580 | RCU_TRIVIAL_FLAVOR,
|
| 581 | SRCU_FLAVOR,
|
| 582 | INVALID_RCU_FLAVOR
|
| 583 | };
|
| 584 |
|
| 585 | #if defined(CONFIG_RCU_LAZY)
|
| 586 | unsigned long rcu_get_jiffies_lazy_flush(void);
|
| 587 | void rcu_set_jiffies_lazy_flush(unsigned long j);
|
| 588 | #else
|
| 589 | static inline unsigned long rcu_get_jiffies_lazy_flush(void) { return 0; }
|
| 590 | static inline void rcu_set_jiffies_lazy_flush(unsigned long j) { }
|
| 591 | #endif
|
| 592 |
|
| 593 | #if defined(CONFIG_TREE_RCU)
|
| 594 | void rcutorture_get_gp_data(int *flags, unsigned long *gp_seq);
|
| 595 | void do_trace_rcu_torture_read(const char *rcutorturename,
|
| 596 | struct rcu_head *rhp,
|
| 597 | unsigned long secs,
|
| 598 | unsigned long c_old,
|
| 599 | unsigned long c);
|
| 600 | void rcu_gp_set_torture_wait(int duration);
|
| 601 | void rcu_set_gpwrap_lag(unsigned long lag);
|
| 602 | int rcu_get_gpwrap_count(int cpu);
|
| 603 | #else
|
| 604 | static inline void rcutorture_get_gp_data(int *flags, unsigned long *gp_seq)
|
| 605 | {
|
| 606 | *flags = 0;
|
| 607 | *gp_seq = 0;
|
| 608 | }
|
| 609 | #ifdef CONFIG_RCU_TRACE
|
| 610 | void do_trace_rcu_torture_read(const char *rcutorturename,
|
| 611 | struct rcu_head *rhp,
|
| 612 | unsigned long secs,
|
| 613 | unsigned long c_old,
|
| 614 | unsigned long c);
|
| 615 | #else
|
| 616 | #define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
|
| 617 | do { } while (0)
|
| 618 | #endif
|
| 619 | static inline void rcu_gp_set_torture_wait(int duration) { }
|
| 620 | static inline void rcu_set_gpwrap_lag(unsigned long lag) { }
|
| 621 | static inline int rcu_get_gpwrap_count(int cpu) { return 0; }
|
| 622 | #endif
|
| 623 | unsigned long long rcutorture_gather_gp_seqs(void);
|
| 624 | void rcutorture_format_gp_seqs(unsigned long long seqs, char *cp, size_t len);
|
| 625 |
|
| 626 | #ifdef CONFIG_TINY_SRCU
|
| 627 |
|
| 628 | static inline void srcutorture_get_gp_data(struct srcu_struct *sp, int *flags,
|
| 629 | unsigned long *gp_seq)
|
| 630 | {
|
| 631 | *flags = 0;
|
| 632 | *gp_seq = sp->srcu_idx;
|
| 633 | }
|
| 634 |
|
| 635 | #elif defined(CONFIG_TREE_SRCU)
|
| 636 |
|
| 637 | void srcutorture_get_gp_data(struct srcu_struct *sp, int *flags,
|
| 638 | unsigned long *gp_seq);
|
| 639 |
|
| 640 | #endif
|
| 641 |
|
| 642 | #ifdef CONFIG_TINY_RCU
|
| 643 | static inline bool rcu_watching_zero_in_eqs(int cpu, int *vp) { return false; }
|
| 644 | static inline unsigned long rcu_get_gp_seq(void) { return 0; }
|
| 645 | static inline unsigned long rcu_exp_batches_completed(void) { return 0; }
|
| 646 | static inline void rcu_force_quiescent_state(void) { }
|
| 647 | static inline bool rcu_check_boost_fail(unsigned long gp_state, int *cpup) { return true; }
|
| 648 | static inline void show_rcu_gp_kthreads(void) { }
|
| 649 | static inline int rcu_get_gp_kthreads_prio(void) { return 0; }
|
| 650 | static inline void rcu_fwd_progress_check(unsigned long j) { }
|
| 651 | static inline void rcu_gp_slow_register(atomic_t *rgssp) { }
|
| 652 | static inline void rcu_gp_slow_unregister(atomic_t *rgssp) { }
|
| 653 | #else
|
| 654 | bool rcu_watching_zero_in_eqs(int cpu, int *vp);
|
| 655 | unsigned long rcu_get_gp_seq(void);
|
| 656 | unsigned long rcu_exp_batches_completed(void);
|
| 657 | bool rcu_check_boost_fail(unsigned long gp_state, int *cpup);
|
| 658 | void show_rcu_gp_kthreads(void);
|
| 659 | int rcu_get_gp_kthreads_prio(void);
|
| 660 | void rcu_fwd_progress_check(unsigned long j);
|
| 661 | void rcu_force_quiescent_state(void);
|
| 662 | extern struct workqueue_struct *rcu_gp_wq;
|
| 663 | extern struct kthread_worker *rcu_exp_gp_kworker;
|
| 664 | void rcu_gp_slow_register(atomic_t *rgssp);
|
| 665 | void rcu_gp_slow_unregister(atomic_t *rgssp);
|
| 666 | #endif
|
| 667 |
|
| 668 | #ifdef CONFIG_TINY_SRCU
|
| 669 | static inline unsigned long srcu_batches_completed(struct srcu_struct *sp) { return 0; }
|
| 670 | #else
|
| 671 | unsigned long srcu_batches_completed(struct srcu_struct *sp);
|
| 672 | #endif |
| 673 |
|
| 674 | #ifdef CONFIG_RCU_NOCB_CPU
|
| 675 | void rcu_bind_current_to_nocb(void);
|
| 676 | #else
|
| 677 | static inline void rcu_bind_current_to_nocb(void) { }
|
| 678 | #endif
|
| 679 |
|
| 680 | #if !defined(CONFIG_TINY_RCU) && defined(CONFIG_TASKS_RCU)
|
| 681 | void show_rcu_tasks_classic_gp_kthread(void);
|
| 682 | #else
|
| 683 | static inline void show_rcu_tasks_classic_gp_kthread(void) {}
|
| 684 | #endif
|
| 685 | #if !defined(CONFIG_TINY_RCU) && defined(CONFIG_TASKS_RUDE_RCU)
|
| 686 | void show_rcu_tasks_rude_gp_kthread(void);
|
| 687 | #else
|
| 688 | static inline void show_rcu_tasks_rude_gp_kthread(void) {}
|
| 689 | #endif
|
| 690 |
|
| 691 | #ifdef CONFIG_TINY_RCU
|
| 692 | static inline bool rcu_cpu_beenfullyonline(int cpu) { return true; }
|
| 693 | #else
|
| 694 | bool rcu_cpu_beenfullyonline(int cpu);
|
| 695 | #endif
|
| 696 |
|
| 697 | #if defined(CONFIG_RCU_STALL_COMMON) && defined(CONFIG_RCU_CPU_STALL_NOTIFIER)
|
| 698 | int rcu_stall_notifier_call_chain(unsigned long val, void *v);
|
| 699 | #else
|
| 700 | static inline int rcu_stall_notifier_call_chain(unsigned long val, void *v) { return NOTIFY_DONE; }
|
| 701 | #endif |
| 702 |
|
| 703 | #ifdef CONFIG_TRIVIAL_PREEMPT_RCU
|
| 704 | void synchronize_rcu_trivial_preempt(void);
|
| 705 | #endif |
| 706 |
|
| 707 | #if defined(CONFIG_RCU_TORTURE_TEST) && defined(CONFIG_RCU_BOOST)
|
| 708 | bool rcu_is_task_rcu_boosted(void);
|
| 709 | #else
|
| 710 | static inline bool rcu_is_task_rcu_boosted(void) { return false; }
|
| 711 | #endif |
| 712 |
|
| 713 |
|
| 714 | #endif
|