Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'rcu.release.v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rcu/linux

Pull RCU updates from Frederic Weisbecker:
"SRCU:

- Properly handle SRCU readers within IRQ disabled sections in tiny
SRCU

- Preparation to reimplement RCU Tasks Trace on top of SRCU fast:

- Introduce API to expedite a grace period and test it through
rcutorture

- Split srcu-fast in two flavours: SRCU-fast and SRCU-fast-updown.

Both are still targeted toward faster readers (without full
barriers on LOCK and UNLOCK) at the expense of heavier write
side (using full RCU grace period ordering instead of simply
full ordering) as compared to "traditional" non-fast SRCU. But
those srcu-fast flavours are going to be optimized in two
different ways:

- SRCU-fast will become the reimplementation basis for
RCU-TASK-TRACE for consolidation. Since RCU-TASK-TRACE must
be NMI safe, SRCU-fast must be as well.

- SRCU-fast-updown will be needed for uretprobes code in order
to get rid of the read-side memory barriers while still
allowing entering the reader at task level while exiting it
in a timer handler. It is considered semaphore-like in that
it can have different owners between LOCK and UNLOCK.
However it is not NMI-safe.

The actual optimizations are work in progress for the next
cycle. Only the new interfaces are added for now, along with
related torture and scalability test code.

- Create/document/debug/torture new proper initializers for RCU fast:
DEFINE_SRCU_FAST() and init_srcu_struct_fast()

This allows for using right away the proper ordering on the write
side (either full ordering or full RCU grace period ordering)
without waiting for the read side to tell which to use.

This also optimizes the read side altogether with moving flavour
debug checks under debug config and with removing a costly RmW
operation on their first call.

- Make some diagnostic functions tracing safe

Refscale:

- Add performance testing for common context synchronizations
(Preemption, IRQ, Softirq) and per-cpu increments. Those are
relevant comparisons against SRCU-fast read side APIs, especially
as they are planned to synchronize further tracing fast-path code

Miscellanous:

- In order to prepare the layout for nohz_full work deferral to user
exit, the context tracking state must shrink the counter of
transitions to/from RCU not watching. The only possible hazard is
to trigger wrap-around more easily, delaying a bit grace periods
when that happens. This should be a rare event though. Yet add
debugging and torture code to test that assumption

- Fix memory leak on locktorture module

- Annotate accesses in rculist_nulls.h to prevent from KCSAN
warnings. On recent discussions, we also concluded that all those
WRITE_ONCE() and READ_ONCE() on list APIs deserve appropriate
comments. Something to be expected for the next cycle

- Provide a script to apply several configs to several commits with
torture

- Allow torture to reuse a build directory in order to save needless
rebuild time

- Various cleanups"

* tag 'rcu.release.v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rcu/linux: (29 commits)
refscale: Add SRCU-fast-updown readers
refscale: Exercise DEFINE_STATIC_SRCU_FAST() and init_srcu_struct_fast()
rcutorture: Make srcu{,d}_torture_init() announce the SRCU type
srcu: Create an SRCU-fast-updown API
refscale: Do not disable interrupts for tests involving local_bh_enable()
refscale: Add non-atomic per-CPU increment readers
refscale: Add this_cpu_inc() readers
refscale: Add preempt_disable() readers
refscale: Add local_bh_disable() readers
refscale: Add local_irq_disable() and local_irq_save() readers
torture: Permit negative kvm.sh --kconfig numberic arguments
srcu: Add SRCU_READ_FLAVOR_FAST_UPDOWN CPP macro
rcu: Mark diagnostic functions as notrace
rcutorture: Make TREE04 use CONFIG_RCU_DYNTICKS_TORTURE
rcutorture: Remove redundant rcutorture_one_extend() from rcu_torture_one_read()
rcutorture: Permit kvm-again.sh to re-use the build directory
torture: Add kvm-series.sh to test commit/scenario combination
rcu: use WRITE_ONCE() for ->next and ->pprev of hlist_nulls
locktorture: Fix memory leak in param_set_cpumask()
doc: Update for SRCU-fast definitions and initialization
...

+1040 -141
+17 -16
Documentation/RCU/Design/Requirements/Requirements.rst
··· 2637 2637 that was held across as ``ss``-domain synchronize_srcu(), deadlock 2638 2638 would again be possible. Such a deadlock cycle could extend across an 2639 2639 arbitrarily large number of different SRCU domains. Again, with great 2640 - power comes great responsibility. 2640 + power comes great responsibility, though lockdep is now able to detect 2641 + this sort of deadlock. 2641 2642 2642 - Unlike the other RCU flavors, SRCU read-side critical sections can run 2643 - on idle and even offline CPUs. This ability requires that 2644 - srcu_read_lock() and srcu_read_unlock() contain memory barriers, 2645 - which means that SRCU readers will run a bit slower than would RCU 2646 - readers. It also motivates the smp_mb__after_srcu_read_unlock() API, 2647 - which, in combination with srcu_read_unlock(), guarantees a full 2648 - memory barrier. 2643 + Unlike the other RCU flavors, SRCU read-side critical sections can run on 2644 + idle and even offline CPUs, with the exception of srcu_read_lock_fast() 2645 + and friends. This ability requires that srcu_read_lock() and 2646 + srcu_read_unlock() contain memory barriers, which means that SRCU 2647 + readers will run a bit slower than would RCU readers. It also motivates 2648 + the smp_mb__after_srcu_read_unlock() API, which, in combination with 2649 + srcu_read_unlock(), guarantees a full memory barrier. 2649 2650 2650 2651 Also unlike other RCU flavors, synchronize_srcu() may **not** be 2651 2652 invoked from CPU-hotplug notifiers, due to the fact that SRCU grace ··· 2682 2681 that sort of load. Of course, your mileage may vary based on the speed 2683 2682 of your CPUs and the size of your memory. 2684 2683 2685 - The `SRCU 2686 - API <https://lwn.net/Articles/609973/#RCU%20Per-Flavor%20API%20Table>`__ 2684 + The `SRCU API 2685 + <https://lwn.net/Articles/609973/#RCU%20Per-Flavor%20API%20Table>`__ 2687 2686 includes srcu_read_lock(), srcu_read_unlock(), 2688 - srcu_dereference(), srcu_dereference_check(), 2689 - synchronize_srcu(), synchronize_srcu_expedited(), 2690 - call_srcu(), srcu_barrier(), and srcu_read_lock_held(). It 2691 - also includes DEFINE_SRCU(), DEFINE_STATIC_SRCU(), and 2692 - init_srcu_struct() APIs for defining and initializing 2693 - ``srcu_struct`` structures. 2687 + srcu_dereference(), srcu_dereference_check(), synchronize_srcu(), 2688 + synchronize_srcu_expedited(), call_srcu(), srcu_barrier(), 2689 + and srcu_read_lock_held(). It also includes DEFINE_SRCU(), 2690 + DEFINE_STATIC_SRCU(), DEFINE_SRCU_FAST(), DEFINE_STATIC_SRCU_FAST(), 2691 + init_srcu_struct(), and init_srcu_struct_fast() APIs for defining and 2692 + initializing ``srcu_struct`` structures. 2694 2693 2695 2694 More recently, the SRCU API has added polling interfaces: 2696 2695
+7 -5
Documentation/RCU/checklist.rst
··· 417 417 you should be using RCU rather than SRCU, because RCU is almost 418 418 always faster and easier to use than is SRCU. 419 419 420 - Also unlike other forms of RCU, explicit initialization and 421 - cleanup is required either at build time via DEFINE_SRCU() 422 - or DEFINE_STATIC_SRCU() or at runtime via init_srcu_struct() 423 - and cleanup_srcu_struct(). These last two are passed a 424 - "struct srcu_struct" that defines the scope of a given 420 + Also unlike other forms of RCU, explicit initialization 421 + and cleanup is required either at build time via 422 + DEFINE_SRCU(), DEFINE_STATIC_SRCU(), DEFINE_SRCU_FAST(), 423 + or DEFINE_STATIC_SRCU_FAST() or at runtime via either 424 + init_srcu_struct() or init_srcu_struct_fast() and 425 + cleanup_srcu_struct(). These last three are passed a 426 + `struct srcu_struct` that defines the scope of a given 425 427 SRCU domain. Once initialized, the srcu_struct is passed 426 428 to srcu_read_lock(), srcu_read_unlock() synchronize_srcu(), 427 429 synchronize_srcu_expedited(), and call_srcu(). A given
+3
Documentation/RCU/whatisRCU.rst
··· 1227 1227 1228 1228 DEFINE_SRCU 1229 1229 DEFINE_STATIC_SRCU 1230 + DEFINE_SRCU_FAST // for srcu_read_lock_fast() and friends 1231 + DEFINE_STATIC_SRCU_FAST // for srcu_read_lock_fast() and friends 1230 1232 init_srcu_struct 1233 + init_srcu_struct_fast 1231 1234 cleanup_srcu_struct 1232 1235 smp_mb__after_srcu_read_unlock 1233 1236
+37 -7
include/linux/context_tracking_state.h
··· 18 18 CT_STATE_MAX = 4, 19 19 }; 20 20 21 - /* Odd value for watching, else even. */ 22 - #define CT_RCU_WATCHING CT_STATE_MAX 23 - 24 - #define CT_STATE_MASK (CT_STATE_MAX - 1) 25 - #define CT_RCU_WATCHING_MASK (~CT_STATE_MASK) 26 - 27 21 struct context_tracking { 28 22 #ifdef CONFIG_CONTEXT_TRACKING_USER 29 23 /* ··· 38 44 #endif 39 45 }; 40 46 47 + /* 48 + * We cram two different things within the same atomic variable: 49 + * 50 + * CT_RCU_WATCHING_START CT_STATE_START 51 + * | | 52 + * v v 53 + * MSB [ RCU watching counter ][ context_state ] LSB 54 + * ^ ^ 55 + * | | 56 + * CT_RCU_WATCHING_END CT_STATE_END 57 + * 58 + * Bits are used from the LSB upwards, so unused bits (if any) will always be in 59 + * upper bits of the variable. 60 + */ 41 61 #ifdef CONFIG_CONTEXT_TRACKING 62 + #define CT_SIZE (sizeof(((struct context_tracking *)0)->state) * BITS_PER_BYTE) 63 + 64 + #define CT_STATE_WIDTH bits_per(CT_STATE_MAX - 1) 65 + #define CT_STATE_START 0 66 + #define CT_STATE_END (CT_STATE_START + CT_STATE_WIDTH - 1) 67 + 68 + #define CT_RCU_WATCHING_MAX_WIDTH (CT_SIZE - CT_STATE_WIDTH) 69 + #define CT_RCU_WATCHING_WIDTH (IS_ENABLED(CONFIG_RCU_DYNTICKS_TORTURE) ? 2 : CT_RCU_WATCHING_MAX_WIDTH) 70 + #define CT_RCU_WATCHING_START (CT_STATE_END + 1) 71 + #define CT_RCU_WATCHING_END (CT_RCU_WATCHING_START + CT_RCU_WATCHING_WIDTH - 1) 72 + #define CT_RCU_WATCHING BIT(CT_RCU_WATCHING_START) 73 + 74 + #define CT_STATE_MASK GENMASK(CT_STATE_END, CT_STATE_START) 75 + #define CT_RCU_WATCHING_MASK GENMASK(CT_RCU_WATCHING_END, CT_RCU_WATCHING_START) 76 + 77 + #define CT_UNUSED_WIDTH (CT_RCU_WATCHING_MAX_WIDTH - CT_RCU_WATCHING_WIDTH) 78 + 79 + static_assert(CT_STATE_WIDTH + 80 + CT_RCU_WATCHING_WIDTH + 81 + CT_UNUSED_WIDTH == 82 + CT_SIZE); 83 + 42 84 DECLARE_PER_CPU(struct context_tracking, context_tracking); 43 - #endif 85 + #endif /* CONFIG_CONTEXT_TRACKING */ 44 86 45 87 #ifdef CONFIG_CONTEXT_TRACKING_USER 46 88 static __always_inline int __ct_state(void)
+1 -1
include/linux/notifier.h
··· 109 109 .mutex = __MUTEX_INITIALIZER(name.mutex), \ 110 110 .head = NULL, \ 111 111 .srcuu = __SRCU_USAGE_INIT(name.srcuu), \ 112 - .srcu = __SRCU_STRUCT_INIT(name.srcu, name.srcuu, pcpu), \ 112 + .srcu = __SRCU_STRUCT_INIT(name.srcu, name.srcuu, pcpu, 0), \ 113 113 } 114 114 115 115 #define ATOMIC_NOTIFIER_HEAD(name) \
+3 -3
include/linux/rculist_nulls.h
··· 138 138 139 139 if (last) { 140 140 WRITE_ONCE(n->next, last->next); 141 - n->pprev = &last->next; 141 + WRITE_ONCE(n->pprev, &last->next); 142 142 rcu_assign_pointer(hlist_nulls_next_rcu(last), n); 143 143 } else { 144 144 hlist_nulls_add_head_rcu(n, h); ··· 148 148 /* after that hlist_nulls_del will work */ 149 149 static inline void hlist_nulls_add_fake(struct hlist_nulls_node *n) 150 150 { 151 - n->pprev = &n->next; 152 - n->next = (struct hlist_nulls_node *)NULLS_MARKER(NULL); 151 + WRITE_ONCE(n->pprev, &n->next); 152 + WRITE_ONCE(n->next, (struct hlist_nulls_node *)NULLS_MARKER(NULL)); 153 153 } 154 154 155 155 /**
+117 -26
include/linux/srcu.h
··· 25 25 26 26 #ifdef CONFIG_DEBUG_LOCK_ALLOC 27 27 28 - int __init_srcu_struct(struct srcu_struct *ssp, const char *name, 29 - struct lock_class_key *key); 28 + int __init_srcu_struct(struct srcu_struct *ssp, const char *name, struct lock_class_key *key); 29 + #ifndef CONFIG_TINY_SRCU 30 + int __init_srcu_struct_fast(struct srcu_struct *ssp, const char *name, struct lock_class_key *key); 31 + int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name, 32 + struct lock_class_key *key); 33 + #endif // #ifndef CONFIG_TINY_SRCU 30 34 31 35 #define init_srcu_struct(ssp) \ 32 36 ({ \ ··· 39 35 __init_srcu_struct((ssp), #ssp, &__srcu_key); \ 40 36 }) 41 37 38 + #define init_srcu_struct_fast(ssp) \ 39 + ({ \ 40 + static struct lock_class_key __srcu_key; \ 41 + \ 42 + __init_srcu_struct_fast((ssp), #ssp, &__srcu_key); \ 43 + }) 44 + 45 + #define init_srcu_struct_fast_updown(ssp) \ 46 + ({ \ 47 + static struct lock_class_key __srcu_key; \ 48 + \ 49 + __init_srcu_struct_fast_updown((ssp), #ssp, &__srcu_key); \ 50 + }) 51 + 42 52 #define __SRCU_DEP_MAP_INIT(srcu_name) .dep_map = { .name = #srcu_name }, 43 53 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 44 54 45 55 int init_srcu_struct(struct srcu_struct *ssp); 56 + #ifndef CONFIG_TINY_SRCU 57 + int init_srcu_struct_fast(struct srcu_struct *ssp); 58 + int init_srcu_struct_fast_updown(struct srcu_struct *ssp); 59 + #endif // #ifndef CONFIG_TINY_SRCU 46 60 47 61 #define __SRCU_DEP_MAP_INIT(srcu_name) 48 62 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 49 63 50 64 /* Values for SRCU Tree srcu_data ->srcu_reader_flavor, but also used by rcutorture. */ 51 - #define SRCU_READ_FLAVOR_NORMAL 0x1 // srcu_read_lock(). 52 - #define SRCU_READ_FLAVOR_NMI 0x2 // srcu_read_lock_nmisafe(). 53 - // 0x4 // SRCU-lite is no longer with us. 54 - #define SRCU_READ_FLAVOR_FAST 0x8 // srcu_read_lock_fast(). 55 - #define SRCU_READ_FLAVOR_ALL (SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_NMI | \ 56 - SRCU_READ_FLAVOR_FAST) // All of the above. 57 - #define SRCU_READ_FLAVOR_SLOWGP SRCU_READ_FLAVOR_FAST 65 + #define SRCU_READ_FLAVOR_NORMAL 0x1 // srcu_read_lock(). 66 + #define SRCU_READ_FLAVOR_NMI 0x2 // srcu_read_lock_nmisafe(). 67 + // 0x4 // SRCU-lite is no longer with us. 68 + #define SRCU_READ_FLAVOR_FAST 0x4 // srcu_read_lock_fast(). 69 + #define SRCU_READ_FLAVOR_FAST_UPDOWN 0x8 // srcu_read_lock_fast(). 70 + #define SRCU_READ_FLAVOR_ALL (SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_NMI | \ 71 + SRCU_READ_FLAVOR_FAST | SRCU_READ_FLAVOR_FAST_UPDOWN) 72 + // All of the above. 73 + #define SRCU_READ_FLAVOR_SLOWGP (SRCU_READ_FLAVOR_FAST | SRCU_READ_FLAVOR_FAST_UPDOWN) 58 74 // Flavors requiring synchronize_rcu() 59 75 // instead of smp_mb(). 60 76 void __srcu_read_unlock(struct srcu_struct *ssp, int idx) __releases(ssp); ··· 283 259 * @ssp: srcu_struct in which to register the new reader. 284 260 * 285 261 * Enter an SRCU read-side critical section, but for a light-weight 286 - * smp_mb()-free reader. See srcu_read_lock() for more information. 262 + * smp_mb()-free reader. See srcu_read_lock() for more information. This 263 + * function is NMI-safe, in a manner similar to srcu_read_lock_nmisafe(). 287 264 * 288 - * If srcu_read_lock_fast() is ever used on an srcu_struct structure, 289 - * then none of the other flavors may be used, whether before, during, 290 - * or after. Note that grace-period auto-expediting is disabled for _fast 291 - * srcu_struct structures because auto-expedited grace periods invoke 292 - * synchronize_rcu_expedited(), IPIs and all. 265 + * For srcu_read_lock_fast() to be used on an srcu_struct structure, 266 + * that structure must have been defined using either DEFINE_SRCU_FAST() 267 + * or DEFINE_STATIC_SRCU_FAST() on the one hand or initialized with 268 + * init_srcu_struct_fast() on the other. Such an srcu_struct structure 269 + * cannot be passed to any non-fast variant of srcu_read_{,un}lock() or 270 + * srcu_{down,up}_read(). In kernels built with CONFIG_PROVE_RCU=y, 271 + * __srcu_check_read_flavor() will complain bitterly if you ignore this 272 + * restriction. 293 273 * 294 - * Note that srcu_read_lock_fast() can be invoked only from those contexts 295 - * where RCU is watching, that is, from contexts where it would be legal 296 - * to invoke rcu_read_lock(). Otherwise, lockdep will complain. 274 + * Grace-period auto-expediting is disabled for SRCU-fast srcu_struct 275 + * structures because SRCU-fast expedited grace periods invoke 276 + * synchronize_rcu_expedited(), IPIs and all. If you need expedited 277 + * SRCU-fast grace periods, use synchronize_srcu_expedited(). 278 + * 279 + * The srcu_read_lock_fast() function can be invoked only from those 280 + * contexts where RCU is watching, that is, from contexts where it would 281 + * be legal to invoke rcu_read_lock(). Otherwise, lockdep will complain. 297 282 */ 298 283 static inline struct srcu_ctr __percpu *srcu_read_lock_fast(struct srcu_struct *ssp) __acquires(ssp) 299 284 { 300 285 struct srcu_ctr __percpu *retval; 301 286 302 287 RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_read_lock_fast()."); 303 - srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_FAST); 288 + srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST); 304 289 retval = __srcu_read_lock_fast(ssp); 290 + rcu_try_lock_acquire(&ssp->dep_map); 291 + return retval; 292 + } 293 + 294 + /** 295 + * srcu_read_lock_fast_updown - register a new reader for an SRCU-fast-updown structure. 296 + * @ssp: srcu_struct in which to register the new reader. 297 + * 298 + * Enter an SRCU read-side critical section, but for a light-weight 299 + * smp_mb()-free reader. See srcu_read_lock() for more information. 300 + * This function is compatible with srcu_down_read_fast(), but is not 301 + * NMI-safe. 302 + * 303 + * For srcu_read_lock_fast_updown() to be used on an srcu_struct 304 + * structure, that structure must have been defined using either 305 + * DEFINE_SRCU_FAST_UPDOWN() or DEFINE_STATIC_SRCU_FAST_UPDOWN() on the one 306 + * hand or initialized with init_srcu_struct_fast_updown() on the other. 307 + * Such an srcu_struct structure cannot be passed to any non-fast-updown 308 + * variant of srcu_read_{,un}lock() or srcu_{down,up}_read(). In kernels 309 + * built with CONFIG_PROVE_RCU=y, __srcu_check_read_flavor() will complain 310 + * bitterly if you ignore this * restriction. 311 + * 312 + * Grace-period auto-expediting is disabled for SRCU-fast-updown 313 + * srcu_struct structures because SRCU-fast-updown expedited grace periods 314 + * invoke synchronize_rcu_expedited(), IPIs and all. If you need expedited 315 + * SRCU-fast-updown grace periods, use synchronize_srcu_expedited(). 316 + * 317 + * The srcu_read_lock_fast_updown() function can be invoked only from 318 + * those contexts where RCU is watching, that is, from contexts where 319 + * it would be legal to invoke rcu_read_lock(). Otherwise, lockdep will 320 + * complain. 321 + */ 322 + static inline struct srcu_ctr __percpu *srcu_read_lock_fast_updown(struct srcu_struct *ssp) 323 + __acquires(ssp) 324 + { 325 + struct srcu_ctr __percpu *retval; 326 + 327 + RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_read_lock_fast_updown()."); 328 + srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST_UPDOWN); 329 + retval = __srcu_read_lock_fast_updown(ssp); 305 330 rcu_try_lock_acquire(&ssp->dep_map); 306 331 return retval; 307 332 } ··· 364 291 { 365 292 struct srcu_ctr __percpu *retval; 366 293 367 - srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_FAST); 294 + srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST); 368 295 retval = __srcu_read_lock_fast(ssp); 369 296 return retval; 370 297 } ··· 378 305 * srcu_down_read() for more information. 379 306 * 380 307 * The same srcu_struct may be used concurrently by srcu_down_read_fast() 381 - * and srcu_read_lock_fast(). 308 + * and srcu_read_lock_fast(). However, the same definition/initialization 309 + * requirements called out for srcu_read_lock_safe() apply. 382 310 */ 383 311 static inline struct srcu_ctr __percpu *srcu_down_read_fast(struct srcu_struct *ssp) __acquires(ssp) 384 312 { 385 313 WARN_ON_ONCE(IS_ENABLED(CONFIG_PROVE_RCU) && in_nmi()); 386 314 RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_down_read_fast()."); 387 - srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_FAST); 388 - return __srcu_read_lock_fast(ssp); 315 + srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST_UPDOWN); 316 + return __srcu_read_lock_fast_updown(ssp); 389 317 } 390 318 391 319 /** ··· 482 408 RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_read_unlock_fast()."); 483 409 } 484 410 411 + /** 412 + * srcu_read_unlock_fast_updown - unregister a old reader from an SRCU-fast-updown structure. 413 + * @ssp: srcu_struct in which to unregister the old reader. 414 + * @scp: return value from corresponding srcu_read_lock_fast_updown(). 415 + * 416 + * Exit an SRCU-fast-updown read-side critical section. 417 + */ 418 + static inline void 419 + srcu_read_unlock_fast_updown(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp) __releases(ssp) 420 + { 421 + srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST_UPDOWN); 422 + srcu_lock_release(&ssp->dep_map); 423 + __srcu_read_unlock_fast_updown(ssp, scp); 424 + RCU_LOCKDEP_WARN(!rcu_is_watching(), 425 + "RCU must be watching srcu_read_unlock_fast_updown()."); 426 + } 427 + 485 428 /* 486 429 * Used by tracing, cannot be traced and cannot call lockdep. 487 430 * See srcu_read_unlock_fast() for more information. ··· 522 431 __releases(ssp) 523 432 { 524 433 WARN_ON_ONCE(IS_ENABLED(CONFIG_PROVE_RCU) && in_nmi()); 525 - srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST); 526 - __srcu_read_unlock_fast(ssp, scp); 527 - RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_up_read_fast()."); 434 + srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST_UPDOWN); 435 + __srcu_read_unlock_fast_updown(ssp, scp); 436 + RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_up_read_fast_updown()."); 528 437 } 529 438 530 439 /**
+27 -4
include/linux/srcutiny.h
··· 31 31 32 32 void srcu_drive_gp(struct work_struct *wp); 33 33 34 - #define __SRCU_STRUCT_INIT(name, __ignored, ___ignored) \ 34 + #define __SRCU_STRUCT_INIT(name, __ignored, ___ignored, ____ignored) \ 35 35 { \ 36 36 .srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq), \ 37 37 .srcu_cb_tail = &name.srcu_cb_head, \ ··· 44 44 * Tree SRCU, which needs some per-CPU data. 45 45 */ 46 46 #define DEFINE_SRCU(name) \ 47 - struct srcu_struct name = __SRCU_STRUCT_INIT(name, name, name) 47 + struct srcu_struct name = __SRCU_STRUCT_INIT(name, name, name, name) 48 48 #define DEFINE_STATIC_SRCU(name) \ 49 - static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name, name) 49 + static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name, name, name) 50 + #define DEFINE_SRCU_FAST(name) DEFINE_SRCU(name) 51 + #define DEFINE_STATIC_SRCU_FAST(name) \ 52 + static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name, name, name) 53 + #define DEFINE_SRCU_FAST_UPDOWN(name) DEFINE_SRCU(name) 54 + #define DEFINE_STATIC_SRCU_FAST_UPDOWN(name) \ 55 + static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name, name, name) 50 56 51 57 // Dummy structure for srcu_notifier_head. 52 58 struct srcu_usage { }; 53 59 #define __SRCU_USAGE_INIT(name) { } 60 + #define __init_srcu_struct_fast __init_srcu_struct 61 + #define __init_srcu_struct_fast_updown __init_srcu_struct 62 + #ifndef CONFIG_DEBUG_LOCK_ALLOC 63 + #define init_srcu_struct_fast init_srcu_struct 64 + #define init_srcu_struct_fast_updown init_srcu_struct 65 + #endif // #ifndef CONFIG_DEBUG_LOCK_ALLOC 54 66 55 67 void synchronize_srcu(struct srcu_struct *ssp); 56 68 ··· 105 93 __srcu_read_unlock(ssp, __srcu_ptr_to_ctr(ssp, scp)); 106 94 } 107 95 96 + static inline struct srcu_ctr __percpu *__srcu_read_lock_fast_updown(struct srcu_struct *ssp) 97 + { 98 + return __srcu_ctr_to_ptr(ssp, __srcu_read_lock(ssp)); 99 + } 100 + 101 + static inline 102 + void __srcu_read_unlock_fast_updown(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp) 103 + { 104 + __srcu_read_unlock(ssp, __srcu_ptr_to_ctr(ssp, scp)); 105 + } 106 + 108 107 static inline void synchronize_srcu_expedited(struct srcu_struct *ssp) 109 108 { 110 109 synchronize_srcu(ssp); ··· 126 103 synchronize_srcu(ssp); 127 104 } 128 105 106 + static inline void srcu_expedite_current(struct srcu_struct *ssp) { } 129 107 #define srcu_check_read_flavor(ssp, read_flavor) do { } while (0) 130 - #define srcu_check_read_flavor_force(ssp, read_flavor) do { } while (0) 131 108 132 109 /* Defined here to avoid size increase for non-torture kernels. */ 133 110 static inline void srcu_torture_stats_print(struct srcu_struct *ssp,
+77 -24
include/linux/srcutree.h
··· 42 42 struct timer_list delay_work; /* Delay for CB invoking */ 43 43 struct work_struct work; /* Context for CB invoking. */ 44 44 struct rcu_head srcu_barrier_head; /* For srcu_barrier() use. */ 45 + struct rcu_head srcu_ec_head; /* For srcu_expedite_current() use. */ 46 + int srcu_ec_state; /* State for srcu_expedite_current(). */ 45 47 struct srcu_node *mynode; /* Leaf srcu_node. */ 46 48 unsigned long grpmask; /* Mask for leaf srcu_node */ 47 49 /* ->srcu_data_have_cbs[]. */ ··· 104 102 struct srcu_struct { 105 103 struct srcu_ctr __percpu *srcu_ctrp; 106 104 struct srcu_data __percpu *sda; /* Per-CPU srcu_data array. */ 105 + u8 srcu_reader_flavor; 107 106 struct lockdep_map dep_map; 108 107 struct srcu_usage *srcu_sup; /* Update-side data. */ 109 108 }; ··· 138 135 #define SRCU_STATE_SCAN1 1 139 136 #define SRCU_STATE_SCAN2 2 140 137 138 + /* Values for srcu_expedite_current() state (->srcu_ec_state). */ 139 + #define SRCU_EC_IDLE 0 140 + #define SRCU_EC_PENDING 1 141 + #define SRCU_EC_REPOST 2 142 + 141 143 /* 142 144 * Values for initializing gp sequence fields. Higher values allow wrap arounds to 143 145 * occur earlier. ··· 163 155 .work = __DELAYED_WORK_INITIALIZER(name.work, NULL, 0), \ 164 156 } 165 157 166 - #define __SRCU_STRUCT_INIT_COMMON(name, usage_name) \ 158 + #define __SRCU_STRUCT_INIT_COMMON(name, usage_name, fast) \ 167 159 .srcu_sup = &usage_name, \ 160 + .srcu_reader_flavor = fast, \ 168 161 __SRCU_DEP_MAP_INIT(name) 169 162 170 - #define __SRCU_STRUCT_INIT_MODULE(name, usage_name) \ 163 + #define __SRCU_STRUCT_INIT_MODULE(name, usage_name, fast) \ 171 164 { \ 172 - __SRCU_STRUCT_INIT_COMMON(name, usage_name) \ 165 + __SRCU_STRUCT_INIT_COMMON(name, usage_name, fast) \ 173 166 } 174 167 175 - #define __SRCU_STRUCT_INIT(name, usage_name, pcpu_name) \ 168 + #define __SRCU_STRUCT_INIT(name, usage_name, pcpu_name, fast) \ 176 169 { \ 177 170 .sda = &pcpu_name, \ 178 171 .srcu_ctrp = &pcpu_name.srcu_ctrs[0], \ 179 - __SRCU_STRUCT_INIT_COMMON(name, usage_name) \ 172 + __SRCU_STRUCT_INIT_COMMON(name, usage_name, fast) \ 180 173 } 181 174 182 175 /* ··· 198 189 * init_srcu_struct(&my_srcu); 199 190 * 200 191 * See include/linux/percpu-defs.h for the rules on per-CPU variables. 192 + * 193 + * DEFINE_SRCU_FAST() and DEFINE_STATIC_SRCU_FAST create an srcu_struct 194 + * and associated structures whose readers must be of the SRCU-fast variety. 195 + * DEFINE_SRCU_FAST_UPDOWN() and DEFINE_STATIC_SRCU_FAST_UPDOWN() create 196 + * an srcu_struct and associated structures whose readers must be of the 197 + * SRCU-fast-updown variety. The key point (aside from error checking) with 198 + * both varieties is that the grace periods must use synchronize_rcu() 199 + * instead of smp_mb(), and given that the first (for example) 200 + * srcu_read_lock_fast() might race with the first synchronize_srcu(), 201 + * this different must be specified at initialization time. 201 202 */ 202 203 #ifdef MODULE 203 - # define __DEFINE_SRCU(name, is_static) \ 204 + # define __DEFINE_SRCU(name, fast, is_static) \ 204 205 static struct srcu_usage name##_srcu_usage = __SRCU_USAGE_INIT(name##_srcu_usage); \ 205 - is_static struct srcu_struct name = __SRCU_STRUCT_INIT_MODULE(name, name##_srcu_usage); \ 206 + is_static struct srcu_struct name = __SRCU_STRUCT_INIT_MODULE(name, name##_srcu_usage, \ 207 + fast); \ 206 208 extern struct srcu_struct * const __srcu_struct_##name; \ 207 209 struct srcu_struct * const __srcu_struct_##name \ 208 210 __section("___srcu_struct_ptrs") = &name 209 211 #else 210 - # define __DEFINE_SRCU(name, is_static) \ 212 + # define __DEFINE_SRCU(name, fast, is_static) \ 211 213 static DEFINE_PER_CPU(struct srcu_data, name##_srcu_data); \ 212 214 static struct srcu_usage name##_srcu_usage = __SRCU_USAGE_INIT(name##_srcu_usage); \ 213 215 is_static struct srcu_struct name = \ 214 - __SRCU_STRUCT_INIT(name, name##_srcu_usage, name##_srcu_data) 216 + __SRCU_STRUCT_INIT(name, name##_srcu_usage, name##_srcu_data, fast) 215 217 #endif 216 - #define DEFINE_SRCU(name) __DEFINE_SRCU(name, /* not static */) 217 - #define DEFINE_STATIC_SRCU(name) __DEFINE_SRCU(name, static) 218 + #define DEFINE_SRCU(name) __DEFINE_SRCU(name, 0, /* not static */) 219 + #define DEFINE_STATIC_SRCU(name) __DEFINE_SRCU(name, 0, static) 220 + #define DEFINE_SRCU_FAST(name) __DEFINE_SRCU(name, SRCU_READ_FLAVOR_FAST, /* not static */) 221 + #define DEFINE_STATIC_SRCU_FAST(name) __DEFINE_SRCU(name, SRCU_READ_FLAVOR_FAST, static) 222 + #define DEFINE_SRCU_FAST_UPDOWN(name) __DEFINE_SRCU(name, SRCU_READ_FLAVOR_FAST_UPDOWN, \ 223 + /* not static */) 224 + #define DEFINE_STATIC_SRCU_FAST_UPDOWN(name) \ 225 + __DEFINE_SRCU(name, SRCU_READ_FLAVOR_FAST_UPDOWN, static) 218 226 219 227 int __srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp); 220 228 void synchronize_srcu_expedited(struct srcu_struct *ssp); 221 229 void srcu_barrier(struct srcu_struct *ssp); 230 + void srcu_expedite_current(struct srcu_struct *ssp); 222 231 void srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf); 223 232 224 233 // Converts a per-CPU pointer to an ->srcu_ctrs[] array element to that ··· 316 289 atomic_long_inc(raw_cpu_ptr(&scp->srcu_unlocks)); // Z, and implicit RCU reader. 317 290 } 318 291 319 - void __srcu_check_read_flavor(struct srcu_struct *ssp, int read_flavor); 320 - 321 - // Record reader usage even for CONFIG_PROVE_RCU=n kernels. This is 322 - // needed only for flavors that require grace-period smp_mb() calls to be 323 - // promoted to synchronize_rcu(). 324 - static inline void srcu_check_read_flavor_force(struct srcu_struct *ssp, int read_flavor) 292 + /* 293 + * Counts the new reader in the appropriate per-CPU element of the 294 + * srcu_struct. Returns a pointer that must be passed to the matching 295 + * srcu_read_unlock_fast_updown(). This type of reader is compatible 296 + * with srcu_down_read_fast() and srcu_up_read_fast(). 297 + * 298 + * See the __srcu_read_lock_fast() comment for more details. 299 + */ 300 + static inline 301 + struct srcu_ctr __percpu notrace *__srcu_read_lock_fast_updown(struct srcu_struct *ssp) 325 302 { 326 - struct srcu_data *sdp = raw_cpu_ptr(ssp->sda); 303 + struct srcu_ctr __percpu *scp = READ_ONCE(ssp->srcu_ctrp); 327 304 328 - if (likely(READ_ONCE(sdp->srcu_reader_flavor) & read_flavor)) 329 - return; 330 - 331 - // Note that the cmpxchg() in __srcu_check_read_flavor() is fully ordered. 332 - __srcu_check_read_flavor(ssp, read_flavor); 305 + if (!IS_ENABLED(CONFIG_NEED_SRCU_NMI_SAFE)) 306 + this_cpu_inc(scp->srcu_locks.counter); // Y, and implicit RCU reader. 307 + else 308 + atomic_long_inc(raw_cpu_ptr(&scp->srcu_locks)); // Y, and implicit RCU reader. 309 + barrier(); /* Avoid leaking the critical section. */ 310 + return scp; 333 311 } 334 312 335 - // Record non-_lite() usage only for CONFIG_PROVE_RCU=y kernels. 313 + /* 314 + * Removes the count for the old reader from the appropriate 315 + * per-CPU element of the srcu_struct. Note that this may well be a 316 + * different CPU than that which was incremented by the corresponding 317 + * srcu_read_lock_fast(), but it must be within the same task. 318 + * 319 + * Please see the __srcu_read_lock_fast() function's header comment for 320 + * information on implicit RCU readers and NMI safety. 321 + */ 322 + static inline void notrace 323 + __srcu_read_unlock_fast_updown(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp) 324 + { 325 + barrier(); /* Avoid leaking the critical section. */ 326 + if (!IS_ENABLED(CONFIG_NEED_SRCU_NMI_SAFE)) 327 + this_cpu_inc(scp->srcu_unlocks.counter); // Z, and implicit RCU reader. 328 + else 329 + atomic_long_inc(raw_cpu_ptr(&scp->srcu_unlocks)); // Z, and implicit RCU reader. 330 + } 331 + 332 + void __srcu_check_read_flavor(struct srcu_struct *ssp, int read_flavor); 333 + 334 + // Record SRCU-reader usage type only for CONFIG_PROVE_RCU=y kernels. 336 335 static inline void srcu_check_read_flavor(struct srcu_struct *ssp, int read_flavor) 337 336 { 338 337 if (IS_ENABLED(CONFIG_PROVE_RCU))
+6 -2
kernel/locking/locktorture.c
··· 103 103 .get = param_get_cpumask, 104 104 }; 105 105 106 - module_param_cb(bind_readers, &lt_bind_ops, &bind_readers, 0644); 107 - module_param_cb(bind_writers, &lt_bind_ops, &bind_writers, 0644); 106 + module_param_cb(bind_readers, &lt_bind_ops, &bind_readers, 0444); 107 + module_param_cb(bind_writers, &lt_bind_ops, &bind_writers, 0444); 108 108 109 109 long torture_sched_setaffinity(pid_t pid, const struct cpumask *in_mask, bool dowarn); 110 110 ··· 1211 1211 cxt.cur_ops->exit(); 1212 1212 cxt.init_called = false; 1213 1213 } 1214 + 1215 + free_cpumask_var(bind_readers); 1216 + free_cpumask_var(bind_writers); 1217 + 1214 1218 torture_cleanup_end(); 1215 1219 } 1216 1220
+15
kernel/rcu/Kconfig.debug
··· 213 213 when looking for certain types of RCU usage bugs, for example, 214 214 too-short RCU read-side critical sections. 215 215 216 + 217 + config RCU_DYNTICKS_TORTURE 218 + bool "Minimize RCU dynticks counter size" 219 + depends on RCU_EXPERT && !COMPILE_TEST 220 + default n 221 + help 222 + This option sets the width of the dynticks counter to its 223 + minimum usable value. This minimum width greatly increases 224 + the probability of flushing out bugs involving counter wrap, 225 + but it also increases the probability of extending grace period 226 + durations. This Kconfig option should therefore be avoided in 227 + production due to the consequent increased probability of OOMs. 228 + 229 + This has no value for production and is only for testing. 230 + 216 231 endmenu # "RCU Debugging"
+64 -12
kernel/rcu/rcutorture.c
··· 389 389 void (*deferred_free)(struct rcu_torture *p); 390 390 void (*sync)(void); 391 391 void (*exp_sync)(void); 392 + void (*exp_current)(void); 392 393 unsigned long (*get_gp_state_exp)(void); 393 394 unsigned long (*start_gp_poll_exp)(void); 394 395 void (*start_gp_poll_exp_full)(struct rcu_gp_oldstate *rgosp); ··· 692 691 */ 693 692 694 693 DEFINE_STATIC_SRCU(srcu_ctl); 694 + DEFINE_STATIC_SRCU_FAST(srcu_ctlf); 695 + DEFINE_STATIC_SRCU_FAST_UPDOWN(srcu_ctlfud); 695 696 static struct srcu_struct srcu_ctld; 696 697 static struct srcu_struct *srcu_ctlp = &srcu_ctl; 697 698 static struct rcu_torture_ops srcud_ops; 699 + 700 + static void srcu_torture_init(void) 701 + { 702 + rcu_sync_torture_init(); 703 + if (!reader_flavor || (reader_flavor & SRCU_READ_FLAVOR_NORMAL)) 704 + VERBOSE_TOROUT_STRING("srcu_torture_init normal SRCU"); 705 + if (reader_flavor & SRCU_READ_FLAVOR_NMI) 706 + VERBOSE_TOROUT_STRING("srcu_torture_init NMI-safe SRCU"); 707 + if (reader_flavor & SRCU_READ_FLAVOR_FAST) { 708 + srcu_ctlp = &srcu_ctlf; 709 + VERBOSE_TOROUT_STRING("srcu_torture_init fast SRCU"); 710 + } 711 + if (reader_flavor & SRCU_READ_FLAVOR_FAST_UPDOWN) { 712 + srcu_ctlp = &srcu_ctlfud; 713 + VERBOSE_TOROUT_STRING("srcu_torture_init fast-up/down SRCU"); 714 + } 715 + } 698 716 699 717 static void srcu_get_gp_data(int *flags, unsigned long *gp_seq) 700 718 { ··· 740 720 } 741 721 if (reader_flavor & SRCU_READ_FLAVOR_FAST) { 742 722 scp = srcu_read_lock_fast(srcu_ctlp); 723 + idx = __srcu_ptr_to_ctr(srcu_ctlp, scp); 724 + WARN_ON_ONCE(idx & ~0x1); 725 + ret += idx << 2; 726 + } 727 + if (reader_flavor & SRCU_READ_FLAVOR_FAST_UPDOWN) { 728 + scp = srcu_read_lock_fast_updown(srcu_ctlp); 743 729 idx = __srcu_ptr_to_ctr(srcu_ctlp, scp); 744 730 WARN_ON_ONCE(idx & ~0x1); 745 731 ret += idx << 3; ··· 775 749 static void srcu_torture_read_unlock(int idx) 776 750 { 777 751 WARN_ON_ONCE((reader_flavor && (idx & ~reader_flavor)) || (!reader_flavor && (idx & ~0x1))); 752 + if (reader_flavor & SRCU_READ_FLAVOR_FAST_UPDOWN) 753 + srcu_read_unlock_fast_updown(srcu_ctlp, 754 + __srcu_ctr_to_ptr(srcu_ctlp, (idx & 0x8) >> 3)); 778 755 if (reader_flavor & SRCU_READ_FLAVOR_FAST) 779 - srcu_read_unlock_fast(srcu_ctlp, __srcu_ctr_to_ptr(srcu_ctlp, (idx & 0x8) >> 3)); 756 + srcu_read_unlock_fast(srcu_ctlp, __srcu_ctr_to_ptr(srcu_ctlp, (idx & 0x4) >> 2)); 780 757 if (reader_flavor & SRCU_READ_FLAVOR_NMI) 781 758 srcu_read_unlock_nmisafe(srcu_ctlp, (idx & 0x2) >> 1); 782 759 if ((reader_flavor & SRCU_READ_FLAVOR_NORMAL) || !(reader_flavor & SRCU_READ_FLAVOR_ALL)) ··· 813 784 WARN_ON_ONCE(idx & ~0x1); 814 785 return idx; 815 786 } 816 - if (reader_flavor & SRCU_READ_FLAVOR_FAST) { 787 + if (reader_flavor & SRCU_READ_FLAVOR_FAST_UPDOWN) { 817 788 scp = srcu_down_read_fast(srcu_ctlp); 818 789 idx = __srcu_ptr_to_ctr(srcu_ctlp, scp); 819 790 WARN_ON_ONCE(idx & ~0x1); ··· 826 797 static void srcu_torture_up_read(int idx) 827 798 { 828 799 WARN_ON_ONCE((reader_flavor && (idx & ~reader_flavor)) || (!reader_flavor && (idx & ~0x1))); 829 - if (reader_flavor & SRCU_READ_FLAVOR_FAST) 800 + if (reader_flavor & SRCU_READ_FLAVOR_FAST_UPDOWN) 830 801 srcu_up_read_fast(srcu_ctlp, __srcu_ctr_to_ptr(srcu_ctlp, (idx & 0x8) >> 3)); 831 802 else if ((reader_flavor & SRCU_READ_FLAVOR_NORMAL) || 832 803 !(reader_flavor & SRCU_READ_FLAVOR_ALL)) ··· 886 857 synchronize_srcu_expedited(srcu_ctlp); 887 858 } 888 859 860 + static void srcu_torture_expedite_current(void) 861 + { 862 + srcu_expedite_current(srcu_ctlp); 863 + } 864 + 889 865 static struct rcu_torture_ops srcu_ops = { 890 866 .ttype = SRCU_FLAVOR, 891 - .init = rcu_sync_torture_init, 867 + .init = srcu_torture_init, 892 868 .readlock = srcu_torture_read_lock, 893 869 .read_delay = srcu_read_delay, 894 870 .readunlock = srcu_torture_read_unlock, ··· 905 871 .deferred_free = srcu_torture_deferred_free, 906 872 .sync = srcu_torture_synchronize, 907 873 .exp_sync = srcu_torture_synchronize_expedited, 874 + .exp_current = srcu_torture_expedite_current, 908 875 .same_gp_state = same_state_synchronize_srcu, 909 876 .get_comp_state = get_completed_synchronize_srcu, 910 877 .get_gp_state = srcu_torture_get_gp_state, ··· 921 886 .no_pi_lock = IS_ENABLED(CONFIG_TINY_SRCU), 922 887 .debug_objects = 1, 923 888 .have_up_down = IS_ENABLED(CONFIG_TINY_SRCU) 924 - ? 0 : SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_FAST, 889 + ? 0 : SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_FAST_UPDOWN, 925 890 .name = "srcu" 926 891 }; 927 892 928 - static void srcu_torture_init(void) 893 + static void srcud_torture_init(void) 929 894 { 930 895 rcu_sync_torture_init(); 931 - WARN_ON(init_srcu_struct(&srcu_ctld)); 896 + if (!reader_flavor || (reader_flavor & SRCU_READ_FLAVOR_NORMAL)) { 897 + WARN_ON(init_srcu_struct(&srcu_ctld)); 898 + VERBOSE_TOROUT_STRING("srcud_torture_init normal SRCU"); 899 + } else if (reader_flavor & SRCU_READ_FLAVOR_NMI) { 900 + WARN_ON(init_srcu_struct(&srcu_ctld)); 901 + VERBOSE_TOROUT_STRING("srcud_torture_init NMI-safe SRCU"); 902 + } else if (reader_flavor & SRCU_READ_FLAVOR_FAST) { 903 + WARN_ON(init_srcu_struct_fast(&srcu_ctld)); 904 + VERBOSE_TOROUT_STRING("srcud_torture_init fast SRCU"); 905 + } else if (reader_flavor & SRCU_READ_FLAVOR_FAST_UPDOWN) { 906 + WARN_ON(init_srcu_struct_fast_updown(&srcu_ctld)); 907 + VERBOSE_TOROUT_STRING("srcud_torture_init fast-up/down SRCU"); 908 + } else { 909 + WARN_ON(init_srcu_struct(&srcu_ctld)); 910 + } 932 911 srcu_ctlp = &srcu_ctld; 933 912 } 934 913 ··· 955 906 /* As above, but dynamically allocated. */ 956 907 static struct rcu_torture_ops srcud_ops = { 957 908 .ttype = SRCU_FLAVOR, 958 - .init = srcu_torture_init, 909 + .init = srcud_torture_init, 959 910 .cleanup = srcu_torture_cleanup, 960 911 .readlock = srcu_torture_read_lock, 961 912 .read_delay = srcu_read_delay, ··· 968 919 .deferred_free = srcu_torture_deferred_free, 969 920 .sync = srcu_torture_synchronize, 970 921 .exp_sync = srcu_torture_synchronize_expedited, 922 + .exp_current = srcu_torture_expedite_current, 971 923 .same_gp_state = same_state_synchronize_srcu, 972 924 .get_comp_state = get_completed_synchronize_srcu, 973 925 .get_gp_state = srcu_torture_get_gp_state, ··· 984 934 .no_pi_lock = IS_ENABLED(CONFIG_TINY_SRCU), 985 935 .debug_objects = 1, 986 936 .have_up_down = IS_ENABLED(CONFIG_TINY_SRCU) 987 - ? 0 : SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_FAST, 937 + ? 0 : SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_FAST_UPDOWN, 988 938 .name = "srcud" 989 939 }; 990 940 ··· 1750 1700 ulo[i] = cur_ops->get_comp_state(); 1751 1701 gp_snap = cur_ops->start_gp_poll(); 1752 1702 rcu_torture_writer_state = RTWS_POLL_WAIT; 1703 + if (cur_ops->exp_current && !torture_random(&rand) % 0xff) 1704 + cur_ops->exp_current(); 1753 1705 while (!cur_ops->poll_gp_state(gp_snap)) { 1754 1706 gp_snap1 = cur_ops->get_gp_state(); 1755 1707 for (i = 0; i < ulo_size; i++) ··· 1772 1720 cur_ops->get_comp_state_full(&rgo[i]); 1773 1721 cur_ops->start_gp_poll_full(&gp_snap_full); 1774 1722 rcu_torture_writer_state = RTWS_POLL_WAIT_FULL; 1723 + if (cur_ops->exp_current && !torture_random(&rand) % 0xff) 1724 + cur_ops->exp_current(); 1775 1725 while (!cur_ops->poll_gp_state_full(&gp_snap_full)) { 1776 1726 cur_ops->get_gp_state_full(&gp_snap1_full); 1777 1727 for (i = 0; i < rgo_size; i++) ··· 2438 2384 newstate = rcutorture_extend_mask(rtors.readstate, trsp); 2439 2385 WARN_ON_ONCE(newstate & RCUTORTURE_RDR_UPDOWN); 2440 2386 rcutorture_one_extend(&rtors.readstate, newstate, trsp, rtors.rtrsp++); 2441 - if (!rcu_torture_one_read_start(&rtors, trsp, myid)) { 2442 - rcutorture_one_extend(&rtors.readstate, 0, trsp, rtors.rtrsp); 2387 + if (!rcu_torture_one_read_start(&rtors, trsp, myid)) 2443 2388 return false; 2444 - } 2445 2389 rtors.rtrsp = rcutorture_loop_extend(&rtors.readstate, trsp, rtors.rtrsp); 2446 2390 rcu_torture_one_read_end(&rtors, trsp); 2447 2391 return true;
+368 -11
kernel/rcu/refscale.c
··· 136 136 void (*cleanup)(void); 137 137 void (*readsection)(const int nloops); 138 138 void (*delaysection)(const int nloops, const int udl, const int ndl); 139 + bool enable_irqs; 139 140 const char *name; 140 141 }; 141 142 ··· 185 184 186 185 // Definitions for SRCU ref scale testing. 187 186 DEFINE_STATIC_SRCU(srcu_refctl_scale); 187 + DEFINE_STATIC_SRCU_FAST(srcu_fast_refctl_scale); 188 + DEFINE_STATIC_SRCU_FAST_UPDOWN(srcu_fast_updown_refctl_scale); 188 189 static struct srcu_struct *srcu_ctlp = &srcu_refctl_scale; 189 190 190 191 static void srcu_ref_scale_read_section(const int nloops) ··· 219 216 .name = "srcu" 220 217 }; 221 218 219 + static bool srcu_fast_sync_scale_init(void) 220 + { 221 + srcu_ctlp = &srcu_fast_refctl_scale; 222 + return true; 223 + } 224 + 222 225 static void srcu_fast_ref_scale_read_section(const int nloops) 223 226 { 224 227 int i; ··· 249 240 } 250 241 251 242 static const struct ref_scale_ops srcu_fast_ops = { 252 - .init = rcu_sync_scale_init, 243 + .init = srcu_fast_sync_scale_init, 253 244 .readsection = srcu_fast_ref_scale_read_section, 254 245 .delaysection = srcu_fast_ref_scale_delay_section, 255 246 .name = "srcu-fast" 247 + }; 248 + 249 + static bool srcu_fast_updown_sync_scale_init(void) 250 + { 251 + srcu_ctlp = &srcu_fast_updown_refctl_scale; 252 + return true; 253 + } 254 + 255 + static void srcu_fast_updown_ref_scale_read_section(const int nloops) 256 + { 257 + int i; 258 + struct srcu_ctr __percpu *scp; 259 + 260 + for (i = nloops; i >= 0; i--) { 261 + scp = srcu_read_lock_fast_updown(srcu_ctlp); 262 + srcu_read_unlock_fast_updown(srcu_ctlp, scp); 263 + } 264 + } 265 + 266 + static void srcu_fast_updown_ref_scale_delay_section(const int nloops, const int udl, const int ndl) 267 + { 268 + int i; 269 + struct srcu_ctr __percpu *scp; 270 + 271 + for (i = nloops; i >= 0; i--) { 272 + scp = srcu_read_lock_fast_updown(srcu_ctlp); 273 + un_delay(udl, ndl); 274 + srcu_read_unlock_fast_updown(srcu_ctlp, scp); 275 + } 276 + } 277 + 278 + static const struct ref_scale_ops srcu_fast_updown_ops = { 279 + .init = srcu_fast_updown_sync_scale_init, 280 + .readsection = srcu_fast_updown_ref_scale_read_section, 281 + .delaysection = srcu_fast_updown_ref_scale_delay_section, 282 + .name = "srcu-fast-updown" 256 283 }; 257 284 258 285 #ifdef CONFIG_TASKS_RCU ··· 368 323 // Definitions for reference count 369 324 static atomic_t refcnt; 370 325 326 + // Definitions acquire-release. 327 + static DEFINE_PER_CPU(unsigned long, test_acqrel); 328 + 371 329 static void ref_refcnt_section(const int nloops) 372 330 { 373 331 int i; ··· 397 349 .readsection = ref_refcnt_section, 398 350 .delaysection = ref_refcnt_delay_section, 399 351 .name = "refcnt" 352 + }; 353 + 354 + static void ref_percpuinc_section(const int nloops) 355 + { 356 + int i; 357 + 358 + for (i = nloops; i >= 0; i--) { 359 + this_cpu_inc(test_acqrel); 360 + this_cpu_dec(test_acqrel); 361 + } 362 + } 363 + 364 + static void ref_percpuinc_delay_section(const int nloops, const int udl, const int ndl) 365 + { 366 + int i; 367 + 368 + for (i = nloops; i >= 0; i--) { 369 + this_cpu_inc(test_acqrel); 370 + un_delay(udl, ndl); 371 + this_cpu_dec(test_acqrel); 372 + } 373 + } 374 + 375 + static const struct ref_scale_ops percpuinc_ops = { 376 + .init = rcu_sync_scale_init, 377 + .readsection = ref_percpuinc_section, 378 + .delaysection = ref_percpuinc_delay_section, 379 + .name = "percpuinc" 380 + }; 381 + 382 + // Note that this can lose counts in preemptible kernels. 383 + static void ref_incpercpu_section(const int nloops) 384 + { 385 + int i; 386 + 387 + for (i = nloops; i >= 0; i--) { 388 + unsigned long *tap = this_cpu_ptr(&test_acqrel); 389 + 390 + WRITE_ONCE(*tap, READ_ONCE(*tap) + 1); 391 + WRITE_ONCE(*tap, READ_ONCE(*tap) - 1); 392 + } 393 + } 394 + 395 + static void ref_incpercpu_delay_section(const int nloops, const int udl, const int ndl) 396 + { 397 + int i; 398 + 399 + for (i = nloops; i >= 0; i--) { 400 + unsigned long *tap = this_cpu_ptr(&test_acqrel); 401 + 402 + WRITE_ONCE(*tap, READ_ONCE(*tap) + 1); 403 + un_delay(udl, ndl); 404 + WRITE_ONCE(*tap, READ_ONCE(*tap) - 1); 405 + } 406 + } 407 + 408 + static const struct ref_scale_ops incpercpu_ops = { 409 + .init = rcu_sync_scale_init, 410 + .readsection = ref_incpercpu_section, 411 + .delaysection = ref_incpercpu_delay_section, 412 + .name = "incpercpu" 413 + }; 414 + 415 + static void ref_incpercpupreempt_section(const int nloops) 416 + { 417 + int i; 418 + 419 + for (i = nloops; i >= 0; i--) { 420 + unsigned long *tap; 421 + 422 + preempt_disable(); 423 + tap = this_cpu_ptr(&test_acqrel); 424 + WRITE_ONCE(*tap, READ_ONCE(*tap) + 1); 425 + WRITE_ONCE(*tap, READ_ONCE(*tap) - 1); 426 + preempt_enable(); 427 + } 428 + } 429 + 430 + static void ref_incpercpupreempt_delay_section(const int nloops, const int udl, const int ndl) 431 + { 432 + int i; 433 + 434 + for (i = nloops; i >= 0; i--) { 435 + unsigned long *tap; 436 + 437 + preempt_disable(); 438 + tap = this_cpu_ptr(&test_acqrel); 439 + WRITE_ONCE(*tap, READ_ONCE(*tap) + 1); 440 + un_delay(udl, ndl); 441 + WRITE_ONCE(*tap, READ_ONCE(*tap) - 1); 442 + preempt_enable(); 443 + } 444 + } 445 + 446 + static const struct ref_scale_ops incpercpupreempt_ops = { 447 + .init = rcu_sync_scale_init, 448 + .readsection = ref_incpercpupreempt_section, 449 + .delaysection = ref_incpercpupreempt_delay_section, 450 + .name = "incpercpupreempt" 451 + }; 452 + 453 + static void ref_incpercpubh_section(const int nloops) 454 + { 455 + int i; 456 + 457 + for (i = nloops; i >= 0; i--) { 458 + unsigned long *tap; 459 + 460 + local_bh_disable(); 461 + tap = this_cpu_ptr(&test_acqrel); 462 + WRITE_ONCE(*tap, READ_ONCE(*tap) + 1); 463 + WRITE_ONCE(*tap, READ_ONCE(*tap) - 1); 464 + local_bh_enable(); 465 + } 466 + } 467 + 468 + static void ref_incpercpubh_delay_section(const int nloops, const int udl, const int ndl) 469 + { 470 + int i; 471 + 472 + for (i = nloops; i >= 0; i--) { 473 + unsigned long *tap; 474 + 475 + local_bh_disable(); 476 + tap = this_cpu_ptr(&test_acqrel); 477 + WRITE_ONCE(*tap, READ_ONCE(*tap) + 1); 478 + un_delay(udl, ndl); 479 + WRITE_ONCE(*tap, READ_ONCE(*tap) - 1); 480 + local_bh_enable(); 481 + } 482 + } 483 + 484 + static const struct ref_scale_ops incpercpubh_ops = { 485 + .init = rcu_sync_scale_init, 486 + .readsection = ref_incpercpubh_section, 487 + .delaysection = ref_incpercpubh_delay_section, 488 + .enable_irqs = true, 489 + .name = "incpercpubh" 490 + }; 491 + 492 + static void ref_incpercpuirqsave_section(const int nloops) 493 + { 494 + int i; 495 + unsigned long flags; 496 + 497 + for (i = nloops; i >= 0; i--) { 498 + unsigned long *tap; 499 + 500 + local_irq_save(flags); 501 + tap = this_cpu_ptr(&test_acqrel); 502 + WRITE_ONCE(*tap, READ_ONCE(*tap) + 1); 503 + WRITE_ONCE(*tap, READ_ONCE(*tap) - 1); 504 + local_irq_restore(flags); 505 + } 506 + } 507 + 508 + static void ref_incpercpuirqsave_delay_section(const int nloops, const int udl, const int ndl) 509 + { 510 + int i; 511 + unsigned long flags; 512 + 513 + for (i = nloops; i >= 0; i--) { 514 + unsigned long *tap; 515 + 516 + local_irq_save(flags); 517 + tap = this_cpu_ptr(&test_acqrel); 518 + WRITE_ONCE(*tap, READ_ONCE(*tap) + 1); 519 + un_delay(udl, ndl); 520 + WRITE_ONCE(*tap, READ_ONCE(*tap) - 1); 521 + local_irq_restore(flags); 522 + } 523 + } 524 + 525 + static const struct ref_scale_ops incpercpuirqsave_ops = { 526 + .init = rcu_sync_scale_init, 527 + .readsection = ref_incpercpuirqsave_section, 528 + .delaysection = ref_incpercpuirqsave_delay_section, 529 + .name = "incpercpuirqsave" 400 530 }; 401 531 402 532 // Definitions for rwlock ··· 720 494 .name = "lock-irq" 721 495 }; 722 496 723 - // Definitions acquire-release. 724 - static DEFINE_PER_CPU(unsigned long, test_acqrel); 725 - 726 497 static void ref_acqrel_section(const int nloops) 727 498 { 728 499 unsigned long x; ··· 850 627 .readsection = ref_jiffies_section, 851 628 .delaysection = ref_jiffies_delay_section, 852 629 .name = "jiffies" 630 + }; 631 + 632 + static void ref_preempt_section(const int nloops) 633 + { 634 + int i; 635 + 636 + migrate_disable(); 637 + for (i = nloops; i >= 0; i--) { 638 + preempt_disable(); 639 + preempt_enable(); 640 + } 641 + migrate_enable(); 642 + } 643 + 644 + static void ref_preempt_delay_section(const int nloops, const int udl, const int ndl) 645 + { 646 + int i; 647 + 648 + migrate_disable(); 649 + for (i = nloops; i >= 0; i--) { 650 + preempt_disable(); 651 + un_delay(udl, ndl); 652 + preempt_enable(); 653 + } 654 + migrate_enable(); 655 + } 656 + 657 + static const struct ref_scale_ops preempt_ops = { 658 + .readsection = ref_preempt_section, 659 + .delaysection = ref_preempt_delay_section, 660 + .name = "preempt" 661 + }; 662 + 663 + static void ref_bh_section(const int nloops) 664 + { 665 + int i; 666 + 667 + preempt_disable(); 668 + for (i = nloops; i >= 0; i--) { 669 + local_bh_disable(); 670 + local_bh_enable(); 671 + } 672 + preempt_enable(); 673 + } 674 + 675 + static void ref_bh_delay_section(const int nloops, const int udl, const int ndl) 676 + { 677 + int i; 678 + 679 + preempt_disable(); 680 + for (i = nloops; i >= 0; i--) { 681 + local_bh_disable(); 682 + un_delay(udl, ndl); 683 + local_bh_enable(); 684 + } 685 + preempt_enable(); 686 + } 687 + 688 + static const struct ref_scale_ops bh_ops = { 689 + .readsection = ref_bh_section, 690 + .delaysection = ref_bh_delay_section, 691 + .enable_irqs = true, 692 + .name = "bh" 693 + }; 694 + 695 + static void ref_irq_section(const int nloops) 696 + { 697 + int i; 698 + 699 + preempt_disable(); 700 + for (i = nloops; i >= 0; i--) { 701 + local_irq_disable(); 702 + local_irq_enable(); 703 + } 704 + preempt_enable(); 705 + } 706 + 707 + static void ref_irq_delay_section(const int nloops, const int udl, const int ndl) 708 + { 709 + int i; 710 + 711 + preempt_disable(); 712 + for (i = nloops; i >= 0; i--) { 713 + local_irq_disable(); 714 + un_delay(udl, ndl); 715 + local_irq_enable(); 716 + } 717 + preempt_enable(); 718 + } 719 + 720 + static const struct ref_scale_ops irq_ops = { 721 + .readsection = ref_irq_section, 722 + .delaysection = ref_irq_delay_section, 723 + .name = "irq" 724 + }; 725 + 726 + static void ref_irqsave_section(const int nloops) 727 + { 728 + unsigned long flags; 729 + int i; 730 + 731 + preempt_disable(); 732 + for (i = nloops; i >= 0; i--) { 733 + local_irq_save(flags); 734 + local_irq_restore(flags); 735 + } 736 + preempt_enable(); 737 + } 738 + 739 + static void ref_irqsave_delay_section(const int nloops, const int udl, const int ndl) 740 + { 741 + unsigned long flags; 742 + int i; 743 + 744 + preempt_disable(); 745 + for (i = nloops; i >= 0; i--) { 746 + local_irq_save(flags); 747 + un_delay(udl, ndl); 748 + local_irq_restore(flags); 749 + } 750 + preempt_enable(); 751 + } 752 + 753 + static const struct ref_scale_ops irqsave_ops = { 754 + .readsection = ref_irqsave_section, 755 + .delaysection = ref_irqsave_delay_section, 756 + .name = "irqsave" 853 757 }; 854 758 855 759 //////////////////////////////////////////////////////////////////////// ··· 1274 924 if (!atomic_dec_return(&n_warmedup)) 1275 925 while (atomic_read_acquire(&n_warmedup)) 1276 926 rcu_scale_one_reader(); 1277 - // Also keep interrupts disabled. This also has the effect 1278 - // of preventing entries into slow path for rcu_read_unlock(). 1279 - local_irq_save(flags); 927 + // Also keep interrupts disabled when it is safe to do so, which 928 + // it is not for local_bh_enable(). This also has the effect of 929 + // preventing entries into slow path for rcu_read_unlock(). 930 + if (!cur_ops->enable_irqs) 931 + local_irq_save(flags); 1280 932 start = ktime_get_mono_fast_ns(); 1281 933 1282 934 rcu_scale_one_reader(); 1283 935 1284 936 duration = ktime_get_mono_fast_ns() - start; 1285 - local_irq_restore(flags); 937 + if (!cur_ops->enable_irqs) 938 + local_irq_restore(flags); 1286 939 1287 940 rt->last_duration_ns = WARN_ON_ONCE(duration < 0) ? 0 : duration; 1288 941 // To reduce runtime-skew noise, do maintain-load invocations until ··· 1516 1163 long i; 1517 1164 int firsterr = 0; 1518 1165 static const struct ref_scale_ops *scale_ops[] = { 1519 - &rcu_ops, &srcu_ops, &srcu_fast_ops, RCU_TRACE_OPS RCU_TASKS_OPS 1520 - &refcnt_ops, &rwlock_ops, &rwsem_ops, &lock_ops, &lock_irq_ops, 1521 - &acqrel_ops, &sched_clock_ops, &clock_ops, &jiffies_ops, 1166 + &rcu_ops, &srcu_ops, &srcu_fast_ops, &srcu_fast_updown_ops, 1167 + RCU_TRACE_OPS RCU_TASKS_OPS 1168 + &refcnt_ops, &percpuinc_ops, &incpercpu_ops, &incpercpupreempt_ops, 1169 + &incpercpubh_ops, &incpercpuirqsave_ops, 1170 + &rwlock_ops, &rwsem_ops, &lock_ops, &lock_irq_ops, &acqrel_ops, 1171 + &sched_clock_ops, &clock_ops, &jiffies_ops, 1172 + &preempt_ops, &bh_ops, &irq_ops, &irqsave_ops, 1522 1173 &typesafe_ref_ops, &typesafe_lock_ops, &typesafe_seqlock_ops, 1523 1174 }; 1524 1175
+9 -4
kernel/rcu/srcutiny.c
··· 106 106 newval = READ_ONCE(ssp->srcu_lock_nesting[idx]) - 1; 107 107 WRITE_ONCE(ssp->srcu_lock_nesting[idx], newval); 108 108 preempt_enable(); 109 - if (!newval && READ_ONCE(ssp->srcu_gp_waiting) && in_task()) 109 + if (!newval && READ_ONCE(ssp->srcu_gp_waiting) && in_task() && !irqs_disabled()) 110 110 swake_up_one(&ssp->srcu_wq); 111 111 } 112 112 EXPORT_SYMBOL_GPL(__srcu_read_unlock); 113 113 114 114 /* 115 115 * Workqueue handler to drive one grace period and invoke any callbacks 116 - * that become ready as a result. Single-CPU and !PREEMPTION operation 117 - * means that we get away with murder on synchronization. ;-) 116 + * that become ready as a result. Single-CPU operation and preemption 117 + * disabling mean that we get away with murder on synchronization. ;-) 118 118 */ 119 119 void srcu_drive_gp(struct work_struct *wp) 120 120 { ··· 141 141 WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); 142 142 WRITE_ONCE(ssp->srcu_gp_waiting, true); /* srcu_read_unlock() wakes! */ 143 143 preempt_enable(); 144 - swait_event_exclusive(ssp->srcu_wq, !READ_ONCE(ssp->srcu_lock_nesting[idx])); 144 + do { 145 + // Deadlock issues prevent __srcu_read_unlock() from 146 + // doing an unconditional wakeup, so polling is required. 147 + swait_event_timeout_exclusive(ssp->srcu_wq, 148 + !READ_ONCE(ssp->srcu_lock_nesting[idx]), HZ / 10); 149 + } while (READ_ONCE(ssp->srcu_lock_nesting[idx])); 145 150 preempt_disable(); // Needed for PREEMPT_LAZY 146 151 WRITE_ONCE(ssp->srcu_gp_waiting, false); /* srcu_read_unlock() cheap. */ 147 152 WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1);
+126 -4
kernel/rcu/srcutree.c
··· 286 286 287 287 #ifdef CONFIG_DEBUG_LOCK_ALLOC 288 288 289 - int __init_srcu_struct(struct srcu_struct *ssp, const char *name, 290 - struct lock_class_key *key) 289 + static int 290 + __init_srcu_struct_common(struct srcu_struct *ssp, const char *name, struct lock_class_key *key) 291 291 { 292 292 /* Don't re-initialize a lock while it is held. */ 293 293 debug_check_no_locks_freed((void *)ssp, sizeof(*ssp)); 294 294 lockdep_init_map(&ssp->dep_map, name, key, 0); 295 295 return init_srcu_struct_fields(ssp, false); 296 296 } 297 + 298 + int __init_srcu_struct(struct srcu_struct *ssp, const char *name, struct lock_class_key *key) 299 + { 300 + ssp->srcu_reader_flavor = 0; 301 + return __init_srcu_struct_common(ssp, name, key); 302 + } 297 303 EXPORT_SYMBOL_GPL(__init_srcu_struct); 304 + 305 + int __init_srcu_struct_fast(struct srcu_struct *ssp, const char *name, struct lock_class_key *key) 306 + { 307 + ssp->srcu_reader_flavor = SRCU_READ_FLAVOR_FAST; 308 + return __init_srcu_struct_common(ssp, name, key); 309 + } 310 + EXPORT_SYMBOL_GPL(__init_srcu_struct_fast); 311 + 312 + int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name, 313 + struct lock_class_key *key) 314 + { 315 + ssp->srcu_reader_flavor = SRCU_READ_FLAVOR_FAST_UPDOWN; 316 + return __init_srcu_struct_common(ssp, name, key); 317 + } 318 + EXPORT_SYMBOL_GPL(__init_srcu_struct_fast_updown); 298 319 299 320 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 300 321 ··· 323 302 * init_srcu_struct - initialize a sleep-RCU structure 324 303 * @ssp: structure to initialize. 325 304 * 326 - * Must invoke this on a given srcu_struct before passing that srcu_struct 305 + * Use this in place of DEFINE_SRCU() and DEFINE_STATIC_SRCU() 306 + * for non-static srcu_struct structures that are to be passed to 307 + * srcu_read_lock(), srcu_read_lock_nmisafe(), and friends. It is necessary 308 + * to invoke this on a given srcu_struct before passing that srcu_struct 327 309 * to any other function. Each srcu_struct represents a separate domain 328 310 * of SRCU protection. 329 311 */ 330 312 int init_srcu_struct(struct srcu_struct *ssp) 331 313 { 314 + ssp->srcu_reader_flavor = 0; 332 315 return init_srcu_struct_fields(ssp, false); 333 316 } 334 317 EXPORT_SYMBOL_GPL(init_srcu_struct); 318 + 319 + /** 320 + * init_srcu_struct_fast - initialize a fast-reader sleep-RCU structure 321 + * @ssp: structure to initialize. 322 + * 323 + * Use this in place of DEFINE_SRCU_FAST() and DEFINE_STATIC_SRCU_FAST() 324 + * for non-static srcu_struct structures that are to be passed to 325 + * srcu_read_lock_fast() and friends. It is necessary to invoke this on a 326 + * given srcu_struct before passing that srcu_struct to any other function. 327 + * Each srcu_struct represents a separate domain of SRCU protection. 328 + */ 329 + int init_srcu_struct_fast(struct srcu_struct *ssp) 330 + { 331 + ssp->srcu_reader_flavor = SRCU_READ_FLAVOR_FAST; 332 + return init_srcu_struct_fields(ssp, false); 333 + } 334 + EXPORT_SYMBOL_GPL(init_srcu_struct_fast); 335 + 336 + /** 337 + * init_srcu_struct_fast_updown - initialize a fast-reader up/down sleep-RCU structure 338 + * @ssp: structure to initialize. 339 + * 340 + * Use this function in place of DEFINE_SRCU_FAST_UPDOWN() and 341 + * DEFINE_STATIC_SRCU_FAST_UPDOWN() for non-static srcu_struct 342 + * structures that are to be passed to srcu_read_lock_fast_updown(), 343 + * srcu_down_read_fast(), and friends. It is necessary to invoke this on a 344 + * given srcu_struct before passing that srcu_struct to any other function. 345 + * Each srcu_struct represents a separate domain of SRCU protection. 346 + */ 347 + int init_srcu_struct_fast_updown(struct srcu_struct *ssp) 348 + { 349 + ssp->srcu_reader_flavor = SRCU_READ_FLAVOR_FAST_UPDOWN; 350 + return init_srcu_struct_fields(ssp, false); 351 + } 352 + EXPORT_SYMBOL_GPL(init_srcu_struct_fast_updown); 335 353 336 354 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 337 355 ··· 521 461 static unsigned long srcu_readers_unlock_idx(struct srcu_struct *ssp, int idx, unsigned long *rdm) 522 462 { 523 463 int cpu; 524 - unsigned long mask = 0; 464 + unsigned long mask = ssp->srcu_reader_flavor; 525 465 unsigned long sum = 0; 526 466 527 467 for_each_possible_cpu(cpu) { ··· 794 734 795 735 sdp = raw_cpu_ptr(ssp->sda); 796 736 old_read_flavor = READ_ONCE(sdp->srcu_reader_flavor); 737 + WARN_ON_ONCE(ssp->srcu_reader_flavor && read_flavor != ssp->srcu_reader_flavor); 738 + WARN_ON_ONCE(old_read_flavor && ssp->srcu_reader_flavor && 739 + old_read_flavor != ssp->srcu_reader_flavor); 740 + WARN_ON_ONCE(read_flavor == SRCU_READ_FLAVOR_FAST && !ssp->srcu_reader_flavor); 797 741 if (!old_read_flavor) { 798 742 old_read_flavor = cmpxchg(&sdp->srcu_reader_flavor, 0, read_flavor); 799 743 if (!old_read_flavor) ··· 1751 1687 mutex_unlock(&ssp->srcu_sup->srcu_barrier_mutex); 1752 1688 } 1753 1689 EXPORT_SYMBOL_GPL(srcu_barrier); 1690 + 1691 + /* Callback for srcu_expedite_current() usage. */ 1692 + static void srcu_expedite_current_cb(struct rcu_head *rhp) 1693 + { 1694 + unsigned long flags; 1695 + bool needcb = false; 1696 + struct srcu_data *sdp = container_of(rhp, struct srcu_data, srcu_ec_head); 1697 + 1698 + spin_lock_irqsave_sdp_contention(sdp, &flags); 1699 + if (sdp->srcu_ec_state == SRCU_EC_IDLE) { 1700 + WARN_ON_ONCE(1); 1701 + } else if (sdp->srcu_ec_state == SRCU_EC_PENDING) { 1702 + sdp->srcu_ec_state = SRCU_EC_IDLE; 1703 + } else { 1704 + WARN_ON_ONCE(sdp->srcu_ec_state != SRCU_EC_REPOST); 1705 + sdp->srcu_ec_state = SRCU_EC_PENDING; 1706 + needcb = true; 1707 + } 1708 + spin_unlock_irqrestore_rcu_node(sdp, flags); 1709 + // If needed, requeue ourselves as an expedited SRCU callback. 1710 + if (needcb) 1711 + __call_srcu(sdp->ssp, &sdp->srcu_ec_head, srcu_expedite_current_cb, false); 1712 + } 1713 + 1714 + /** 1715 + * srcu_expedite_current - Expedite the current SRCU grace period 1716 + * @ssp: srcu_struct to expedite. 1717 + * 1718 + * Cause the current SRCU grace period to become expedited. The grace 1719 + * period following the current one might also be expedited. If there is 1720 + * no current grace period, one might be created. If the current grace 1721 + * period is currently sleeping, that sleep will complete before expediting 1722 + * will take effect. 1723 + */ 1724 + void srcu_expedite_current(struct srcu_struct *ssp) 1725 + { 1726 + unsigned long flags; 1727 + bool needcb = false; 1728 + struct srcu_data *sdp; 1729 + 1730 + migrate_disable(); 1731 + sdp = this_cpu_ptr(ssp->sda); 1732 + spin_lock_irqsave_sdp_contention(sdp, &flags); 1733 + if (sdp->srcu_ec_state == SRCU_EC_IDLE) { 1734 + sdp->srcu_ec_state = SRCU_EC_PENDING; 1735 + needcb = true; 1736 + } else if (sdp->srcu_ec_state == SRCU_EC_PENDING) { 1737 + sdp->srcu_ec_state = SRCU_EC_REPOST; 1738 + } else { 1739 + WARN_ON_ONCE(sdp->srcu_ec_state != SRCU_EC_REPOST); 1740 + } 1741 + spin_unlock_irqrestore_rcu_node(sdp, flags); 1742 + // If needed, queue an expedited SRCU callback. 1743 + if (needcb) 1744 + __call_srcu(ssp, &sdp->srcu_ec_head, srcu_expedite_current_cb, false); 1745 + migrate_enable(); 1746 + } 1747 + EXPORT_SYMBOL_GPL(srcu_expedite_current); 1754 1748 1755 1749 /** 1756 1750 * srcu_batches_completed - return batches completed.
+1 -1
kernel/rcu/tree.c
··· 4017 4017 * RCU on an offline processor during initial boot, hence the check for 4018 4018 * rcu_scheduler_fully_active. 4019 4019 */ 4020 - bool rcu_lockdep_current_cpu_online(void) 4020 + bool notrace rcu_lockdep_current_cpu_online(void) 4021 4021 { 4022 4022 struct rcu_data *rdp; 4023 4023 bool ret = false;
+4 -4
kernel/rcu/update.c
··· 117 117 return false; 118 118 } 119 119 120 - int rcu_read_lock_sched_held(void) 120 + int notrace rcu_read_lock_sched_held(void) 121 121 { 122 122 bool ret; 123 123 ··· 342 342 * Note that rcu_read_lock() is disallowed if the CPU is either idle or 343 343 * offline from an RCU perspective, so check for those as well. 344 344 */ 345 - int rcu_read_lock_held(void) 345 + int notrace rcu_read_lock_held(void) 346 346 { 347 347 bool ret; 348 348 ··· 367 367 * Note that rcu_read_lock_bh() is disallowed if the CPU is either idle or 368 368 * offline from an RCU perspective, so check for those as well. 369 369 */ 370 - int rcu_read_lock_bh_held(void) 370 + int notrace rcu_read_lock_bh_held(void) 371 371 { 372 372 bool ret; 373 373 ··· 377 377 } 378 378 EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held); 379 379 380 - int rcu_read_lock_any_held(void) 380 + int notrace rcu_read_lock_any_held(void) 381 381 { 382 382 bool ret; 383 383
+40 -16
tools/testing/selftests/rcutorture/bin/kvm-again.sh
··· 31 31 if ! cp "$oldrun/scenarios" $T/scenarios.oldrun 32 32 then 33 33 # Later on, can reconstitute this from console.log files. 34 - echo Prior run batches file does not exist: $oldrun/batches 34 + echo Prior run scenarios file does not exist: $oldrun/scenarios 35 35 exit 1 36 36 fi 37 37 ··· 68 68 echo " --datestamp string" 69 69 echo " --dryrun" 70 70 echo " --duration minutes | <seconds>s | <hours>h | <days>d" 71 - echo " --link hard|soft|copy" 71 + echo " --link hard|soft|copy|inplace|inplace-force" 72 72 echo " --remote" 73 73 echo " --rundir /new/res/path" 74 74 echo "Command line: $scriptname $args" ··· 121 121 shift 122 122 ;; 123 123 --link) 124 - checkarg --link "hard|soft|copy" "$#" "$2" 'hard\|soft\|copy' '^--' 124 + checkarg --link "hard|soft|copy|inplace|inplace-force" "$#" "$2" 'hard\|soft\|copy\|inplace\|inplace-force' '^--' 125 125 case "$2" in 126 126 copy) 127 127 arg_link="cp -R" ··· 131 131 ;; 132 132 soft) 133 133 arg_link="cp -Rs" 134 + ;; 135 + inplace) 136 + arg_link="inplace" 137 + rundir="$oldrun" 138 + ;; 139 + inplace-force) 140 + arg_link="inplace-force" 141 + rundir="$oldrun" 134 142 ;; 135 143 esac 136 144 shift ··· 180 172 181 173 echo ---- Re-run results directory: $rundir 182 174 183 - # Copy old run directory tree over and adjust. 184 - mkdir -p "`dirname "$rundir"`" 185 - if ! $arg_link "$oldrun" "$rundir" 175 + if test "$oldrun" != "$rundir" 186 176 then 187 - echo "Cannot copy from $oldrun to $rundir." 188 - usage 177 + # Copy old run directory tree over and adjust. 178 + mkdir -p "`dirname "$rundir"`" 179 + if ! $arg_link "$oldrun" "$rundir" 180 + then 181 + echo "Cannot copy from $oldrun to $rundir." 182 + usage 183 + fi 184 + rm -f "$rundir"/*/{console.log,console.log.diags,qemu_pid,qemu-pid,qemu-retval,Warnings,kvm-test-1-run.sh.out,kvm-test-1-run-qemu.sh.out,vmlinux} "$rundir"/log 185 + touch "$rundir/log" 186 + echo $scriptname $args | tee -a "$rundir/log" 187 + echo $oldrun > "$rundir/re-run" 188 + if ! test -d "$rundir/../../bin" 189 + then 190 + $arg_link "$oldrun/../../bin" "$rundir/../.." 191 + fi 192 + else 193 + # Check for a run having already happened. 194 + find "$rundir" -name console.log -print > $T/oldrun-console.log 195 + if test -s $T/oldrun-console.log 196 + then 197 + echo Run already took place in $rundir 198 + if test "$arg_link" = inplace 199 + then 200 + usage 201 + fi 202 + fi 189 203 fi 190 - rm -f "$rundir"/*/{console.log,console.log.diags,qemu_pid,qemu-pid,qemu-retval,Warnings,kvm-test-1-run.sh.out,kvm-test-1-run-qemu.sh.out,vmlinux} "$rundir"/log 191 - touch "$rundir/log" 192 - echo $scriptname $args | tee -a "$rundir/log" 193 - echo $oldrun > "$rundir/re-run" 194 - if ! test -d "$rundir/../../bin" 195 - then 196 - $arg_link "$oldrun/../../bin" "$rundir/../.." 197 - fi 204 + 205 + # Find runs to be done based on their qemu-cmd files. 198 206 for i in $rundir/*/qemu-cmd 199 207 do 200 208 cp "$i" $T
+116
tools/testing/selftests/rcutorture/bin/kvm-series.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Usage: kvm-series.sh config-list commit-id-list [ kvm.sh parameters ] 5 + # 6 + # Tests the specified list of unadorned configs ("TREE01 SRCU-P" but not 7 + # "CFLIST" or "3*TRACE01") and an indication of a set of commits to test, 8 + # then runs each commit through the specified list of commits using kvm.sh. 9 + # The runs are grouped into a -series/config/commit directory tree. 10 + # Each run defaults to a duration of one minute. 11 + # 12 + # Run in top-level Linux source directory. Please note that this is in 13 + # no way a replacement for "git bisect"!!! 14 + # 15 + # This script is intended to replace kvm-check-branches.sh by providing 16 + # ease of use and faster execution. 17 + 18 + T="`mktemp -d ${TMPDIR-/tmp}/kvm-series.sh.XXXXXX`" 19 + trap 'rm -rf $T' 0 20 + 21 + scriptname=$0 22 + args="$*" 23 + 24 + config_list="${1}" 25 + if test -z "${config_list}" 26 + then 27 + echo "$0: Need a quoted list of --config arguments for first argument." 28 + exit 1 29 + fi 30 + if test -z "${config_list}" || echo "${config_list}" | grep -q '\*' 31 + then 32 + echo "$0: Repetition ('*') not allowed in config list." 33 + exit 1 34 + fi 35 + 36 + commit_list="${2}" 37 + if test -z "${commit_list}" 38 + then 39 + echo "$0: Need a list of commits (e.g., HEAD^^^..) for second argument." 40 + exit 2 41 + fi 42 + git log --pretty=format:"%h" "${commit_list}" > $T/commits 43 + ret=$? 44 + if test "${ret}" -ne 0 45 + then 46 + echo "$0: Invalid commit list ('${commit_list}')." 47 + exit 2 48 + fi 49 + sha1_list=`cat $T/commits` 50 + 51 + shift 52 + shift 53 + 54 + RCUTORTURE="`pwd`/tools/testing/selftests/rcutorture"; export RCUTORTURE 55 + PATH=${RCUTORTURE}/bin:$PATH; export PATH 56 + . functions.sh 57 + 58 + ret=0 59 + nfail=0 60 + nsuccess=0 61 + faillist= 62 + successlist= 63 + cursha1="`git rev-parse --abbrev-ref HEAD`" 64 + ds="`date +%Y.%m.%d-%H.%M.%S`-series" 65 + startdate="`date`" 66 + starttime="`get_starttime`" 67 + 68 + echo " --- " $scriptname $args | tee -a $T/log 69 + echo " --- Results directory: " $ds | tee -a $T/log 70 + 71 + for config in ${config_list} 72 + do 73 + sha_n=0 74 + for sha in ${sha1_list} 75 + do 76 + sha1=${sha_n}.${sha} # Enable "sort -k1nr" to list commits in order. 77 + echo Starting ${config}/${sha1} at `date` | tee -a $T/log 78 + git checkout "${sha}" 79 + time tools/testing/selftests/rcutorture/bin/kvm.sh --configs "$config" --datestamp "$ds/${config}/${sha1}" --duration 1 "$@" 80 + curret=$? 81 + if test "${curret}" -ne 0 82 + then 83 + nfail=$((nfail+1)) 84 + faillist="$faillist ${config}/${sha1}(${curret})" 85 + else 86 + nsuccess=$((nsuccess+1)) 87 + successlist="$successlist ${config}/${sha1}" 88 + # Successful run, so remove large files. 89 + rm -f ${RCUTORTURE}/$ds/${config}/${sha1}/{vmlinux,bzImage,System.map,Module.symvers} 90 + fi 91 + if test "${ret}" -eq 0 92 + then 93 + ret=${curret} 94 + fi 95 + sha_n=$((sha_n+1)) 96 + done 97 + done 98 + git checkout "${cursha1}" 99 + 100 + echo ${nsuccess} SUCCESSES: | tee -a $T/log 101 + echo ${successlist} | fmt | tee -a $T/log 102 + echo | tee -a $T/log 103 + echo ${nfail} FAILURES: | tee -a $T/log 104 + echo ${faillist} | fmt | tee -a $T/log 105 + if test -n "${faillist}" 106 + then 107 + echo | tee -a $T/log 108 + echo Failures across commits: | tee -a $T/log 109 + echo ${faillist} | tr ' ' '\012' | sed -e 's,^[^/]*/,,' -e 's/([0-9]*)//' | 110 + sort | uniq -c | sort -k2n | tee -a $T/log 111 + fi 112 + echo Started at $startdate, ended at `date`, duration `get_starttime_duration $starttime`. | tee -a $T/log 113 + echo Summary: Successes: ${nsuccess} Failures: ${nfail} | tee -a $T/log 114 + cp $T/log tools/testing/selftests/rcutorture/res/${ds} 115 + 116 + exit "${ret}"
+1 -1
tools/testing/selftests/rcutorture/bin/kvm.sh
··· 199 199 fi 200 200 ;; 201 201 --kconfig|--kconfigs) 202 - checkarg --kconfig "(Kconfig options)" $# "$2" '^\(#CHECK#\)\?CONFIG_[A-Z0-9_]\+=\([ynm]\|[0-9]\+\|"[^"]*"\)\( \+\(#CHECK#\)\?CONFIG_[A-Z0-9_]\+=\([ynm]\|[0-9]\+\|"[^"]*"\)\)* *$' '^error$' 202 + checkarg --kconfig "(Kconfig options)" $# "$2" '^\(#CHECK#\)\?CONFIG_[A-Z0-9_]\+=\([ynm]\|-\?[0-9]\+\|"[^"]*"\)\( \+\(#CHECK#\)\?CONFIG_[A-Z0-9_]\+=\([ynm]\|-\?[0-9]\+\|"[^"]*"\)\)* *$' '^error$' 203 203 TORTURE_KCONFIG_ARG="`echo "$TORTURE_KCONFIG_ARG $2" | sed -e 's/^ *//' -e 's/ *$//'`" 204 204 shift 205 205 ;;
+1
tools/testing/selftests/rcutorture/configs/rcu/TREE04
··· 16 16 CONFIG_RCU_EXPERT=y 17 17 CONFIG_RCU_EQS_DEBUG=y 18 18 CONFIG_RCU_LAZY=y 19 + CONFIG_RCU_DYNTICKS_TORTURE=y