Skip to content

Commit 98e7dcb

Browse files
committed
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 ...
2 parents b687034 + 9a08942 commit 98e7dcb

21 files changed

Lines changed: 1041 additions & 142 deletions

File tree

Documentation/RCU/Design/Requirements/Requirements.rst

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,15 +2637,16 @@ synchronize_srcu() for some other domain ``ss1``, and if an
26372637
that was held across as ``ss``-domain synchronize_srcu(), deadlock
26382638
would again be possible. Such a deadlock cycle could extend across an
26392639
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.
26412642

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.
26492650

26502651
Also unlike other RCU flavors, synchronize_srcu() may **not** be
26512652
invoked from CPU-hotplug notifiers, due to the fact that SRCU grace
@@ -2681,15 +2682,15 @@ run some tests first. SRCU just might need a few adjustment to deal with
26812682
that sort of load. Of course, your mileage may vary based on the speed
26822683
of your CPUs and the size of your memory.
26832684

2684-
The `SRCU
2685-
API <https://lwn.net/Articles/609973/#RCU%20Per-Flavor%20API%20Table>`__
2685+
The `SRCU API
2686+
<https://lwn.net/Articles/609973/#RCU%20Per-Flavor%20API%20Table>`__
26862687
includes srcu_read_lock(), srcu_read_unlock(),
2687-
srcu_dereference(), srcu_dereference_check(),
2688-
synchronize_srcu(), synchronize_srcu_expedited(),
2689-
call_srcu(), srcu_barrier(), and srcu_read_lock_held(). It
2690-
also includes DEFINE_SRCU(), DEFINE_STATIC_SRCU(), and
2691-
init_srcu_struct() APIs for defining and initializing
2692-
``srcu_struct`` structures.
2688+
srcu_dereference(), srcu_dereference_check(), synchronize_srcu(),
2689+
synchronize_srcu_expedited(), call_srcu(), srcu_barrier(),
2690+
and srcu_read_lock_held(). It also includes DEFINE_SRCU(),
2691+
DEFINE_STATIC_SRCU(), DEFINE_SRCU_FAST(), DEFINE_STATIC_SRCU_FAST(),
2692+
init_srcu_struct(), and init_srcu_struct_fast() APIs for defining and
2693+
initializing ``srcu_struct`` structures.
26932694

26942695
More recently, the SRCU API has added polling interfaces:
26952696

Documentation/RCU/checklist.rst

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,11 +417,13 @@ over a rather long period of time, but improvements are always welcome!
417417
you should be using RCU rather than SRCU, because RCU is almost
418418
always faster and easier to use than is SRCU.
419419

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
425427
SRCU domain. Once initialized, the srcu_struct is passed
426428
to srcu_read_lock(), srcu_read_unlock() synchronize_srcu(),
427429
synchronize_srcu_expedited(), and call_srcu(). A given

Documentation/RCU/whatisRCU.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,7 +1227,10 @@ SRCU: Initialization/cleanup/ordering::
12271227

12281228
DEFINE_SRCU
12291229
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
12301232
init_srcu_struct
1233+
init_srcu_struct_fast
12311234
cleanup_srcu_struct
12321235
smp_mb__after_srcu_read_unlock
12331236

include/linux/context_tracking_state.h

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@ enum ctx_state {
1818
CT_STATE_MAX = 4,
1919
};
2020

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-
2721
struct context_tracking {
2822
#ifdef CONFIG_CONTEXT_TRACKING_USER
2923
/*
@@ -44,9 +38,45 @@ struct context_tracking {
4438
#endif
4539
};
4640

41+
/*
42+
* We cram two different things within the same atomic variable:
43+
*
44+
* CT_RCU_WATCHING_START CT_STATE_START
45+
* | |
46+
* v v
47+
* MSB [ RCU watching counter ][ context_state ] LSB
48+
* ^ ^
49+
* | |
50+
* CT_RCU_WATCHING_END CT_STATE_END
51+
*
52+
* Bits are used from the LSB upwards, so unused bits (if any) will always be in
53+
* upper bits of the variable.
54+
*/
4755
#ifdef CONFIG_CONTEXT_TRACKING
56+
#define CT_SIZE (sizeof(((struct context_tracking *)0)->state) * BITS_PER_BYTE)
57+
58+
#define CT_STATE_WIDTH bits_per(CT_STATE_MAX - 1)
59+
#define CT_STATE_START 0
60+
#define CT_STATE_END (CT_STATE_START + CT_STATE_WIDTH - 1)
61+
62+
#define CT_RCU_WATCHING_MAX_WIDTH (CT_SIZE - CT_STATE_WIDTH)
63+
#define CT_RCU_WATCHING_WIDTH (IS_ENABLED(CONFIG_RCU_DYNTICKS_TORTURE) ? 2 : CT_RCU_WATCHING_MAX_WIDTH)
64+
#define CT_RCU_WATCHING_START (CT_STATE_END + 1)
65+
#define CT_RCU_WATCHING_END (CT_RCU_WATCHING_START + CT_RCU_WATCHING_WIDTH - 1)
66+
#define CT_RCU_WATCHING BIT(CT_RCU_WATCHING_START)
67+
68+
#define CT_STATE_MASK GENMASK(CT_STATE_END, CT_STATE_START)
69+
#define CT_RCU_WATCHING_MASK GENMASK(CT_RCU_WATCHING_END, CT_RCU_WATCHING_START)
70+
71+
#define CT_UNUSED_WIDTH (CT_RCU_WATCHING_MAX_WIDTH - CT_RCU_WATCHING_WIDTH)
72+
73+
static_assert(CT_STATE_WIDTH +
74+
CT_RCU_WATCHING_WIDTH +
75+
CT_UNUSED_WIDTH ==
76+
CT_SIZE);
77+
4878
DECLARE_PER_CPU(struct context_tracking, context_tracking);
49-
#endif
79+
#endif /* CONFIG_CONTEXT_TRACKING */
5080

5181
#ifdef CONFIG_CONTEXT_TRACKING_USER
5282
static __always_inline int __ct_state(void)

include/linux/notifier.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
109109
.mutex = __MUTEX_INITIALIZER(name.mutex), \
110110
.head = NULL, \
111111
.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), \
113113
}
114114

115115
#define ATOMIC_NOTIFIER_HEAD(name) \

include/linux/rculist_nulls.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n,
138138

139139
if (last) {
140140
WRITE_ONCE(n->next, last->next);
141-
n->pprev = &last->next;
141+
WRITE_ONCE(n->pprev, &last->next);
142142
rcu_assign_pointer(hlist_nulls_next_rcu(last), n);
143143
} else {
144144
hlist_nulls_add_head_rcu(n, h);
@@ -148,8 +148,8 @@ static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n,
148148
/* after that hlist_nulls_del will work */
149149
static inline void hlist_nulls_add_fake(struct hlist_nulls_node *n)
150150
{
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));
153153
}
154154

155155
/**

include/linux/srcu.h

Lines changed: 119 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ struct srcu_struct;
2525

2626
#ifdef CONFIG_DEBUG_LOCK_ALLOC
2727

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
3034

3135
#define init_srcu_struct(ssp) \
3236
({ \
@@ -35,22 +39,42 @@ int __init_srcu_struct(struct srcu_struct *ssp, const char *name,
3539
__init_srcu_struct((ssp), #ssp, &__srcu_key); \
3640
})
3741

42+
#define init_srcu_struct_fast(ssp) \
43+
({ \
44+
static struct lock_class_key __srcu_key; \
45+
\
46+
__init_srcu_struct_fast((ssp), #ssp, &__srcu_key); \
47+
})
48+
49+
#define init_srcu_struct_fast_updown(ssp) \
50+
({ \
51+
static struct lock_class_key __srcu_key; \
52+
\
53+
__init_srcu_struct_fast_updown((ssp), #ssp, &__srcu_key); \
54+
})
55+
3856
#define __SRCU_DEP_MAP_INIT(srcu_name) .dep_map = { .name = #srcu_name },
3957
#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
4058

4159
int init_srcu_struct(struct srcu_struct *ssp);
60+
#ifndef CONFIG_TINY_SRCU
61+
int init_srcu_struct_fast(struct srcu_struct *ssp);
62+
int init_srcu_struct_fast_updown(struct srcu_struct *ssp);
63+
#endif // #ifndef CONFIG_TINY_SRCU
4264

4365
#define __SRCU_DEP_MAP_INIT(srcu_name)
4466
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
4567

4668
/* Values for SRCU Tree srcu_data ->srcu_reader_flavor, but also used by rcutorture. */
47-
#define SRCU_READ_FLAVOR_NORMAL 0x1 // srcu_read_lock().
48-
#define SRCU_READ_FLAVOR_NMI 0x2 // srcu_read_lock_nmisafe().
49-
// 0x4 // SRCU-lite is no longer with us.
50-
#define SRCU_READ_FLAVOR_FAST 0x8 // srcu_read_lock_fast().
51-
#define SRCU_READ_FLAVOR_ALL (SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_NMI | \
52-
SRCU_READ_FLAVOR_FAST) // All of the above.
53-
#define SRCU_READ_FLAVOR_SLOWGP SRCU_READ_FLAVOR_FAST
69+
#define SRCU_READ_FLAVOR_NORMAL 0x1 // srcu_read_lock().
70+
#define SRCU_READ_FLAVOR_NMI 0x2 // srcu_read_lock_nmisafe().
71+
// 0x4 // SRCU-lite is no longer with us.
72+
#define SRCU_READ_FLAVOR_FAST 0x4 // srcu_read_lock_fast().
73+
#define SRCU_READ_FLAVOR_FAST_UPDOWN 0x8 // srcu_read_lock_fast().
74+
#define SRCU_READ_FLAVOR_ALL (SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_NMI | \
75+
SRCU_READ_FLAVOR_FAST | SRCU_READ_FLAVOR_FAST_UPDOWN)
76+
// All of the above.
77+
#define SRCU_READ_FLAVOR_SLOWGP (SRCU_READ_FLAVOR_FAST | SRCU_READ_FLAVOR_FAST_UPDOWN)
5478
// Flavors requiring synchronize_rcu()
5579
// instead of smp_mb().
5680
void __srcu_read_unlock(struct srcu_struct *ssp, int idx) __releases(ssp);
@@ -259,29 +283,78 @@ static inline int srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp)
259283
* @ssp: srcu_struct in which to register the new reader.
260284
*
261285
* Enter an SRCU read-side critical section, but for a light-weight
262-
* smp_mb()-free reader. See srcu_read_lock() for more information.
263-
*
264-
* If srcu_read_lock_fast() is ever used on an srcu_struct structure,
265-
* then none of the other flavors may be used, whether before, during,
266-
* or after. Note that grace-period auto-expediting is disabled for _fast
267-
* srcu_struct structures because auto-expedited grace periods invoke
268-
* synchronize_rcu_expedited(), IPIs and all.
269-
*
270-
* Note that srcu_read_lock_fast() can be invoked only from those contexts
271-
* where RCU is watching, that is, from contexts where it would be legal
272-
* to invoke rcu_read_lock(). Otherwise, lockdep will complain.
286+
* smp_mb()-free reader. See srcu_read_lock() for more information. This
287+
* function is NMI-safe, in a manner similar to srcu_read_lock_nmisafe().
288+
*
289+
* For srcu_read_lock_fast() to be used on an srcu_struct structure,
290+
* that structure must have been defined using either DEFINE_SRCU_FAST()
291+
* or DEFINE_STATIC_SRCU_FAST() on the one hand or initialized with
292+
* init_srcu_struct_fast() on the other. Such an srcu_struct structure
293+
* cannot be passed to any non-fast variant of srcu_read_{,un}lock() or
294+
* srcu_{down,up}_read(). In kernels built with CONFIG_PROVE_RCU=y,
295+
* __srcu_check_read_flavor() will complain bitterly if you ignore this
296+
* restriction.
297+
*
298+
* Grace-period auto-expediting is disabled for SRCU-fast srcu_struct
299+
* structures because SRCU-fast expedited grace periods invoke
300+
* synchronize_rcu_expedited(), IPIs and all. If you need expedited
301+
* SRCU-fast grace periods, use synchronize_srcu_expedited().
302+
*
303+
* The srcu_read_lock_fast() function can be invoked only from those
304+
* contexts where RCU is watching, that is, from contexts where it would
305+
* be legal to invoke rcu_read_lock(). Otherwise, lockdep will complain.
273306
*/
274307
static inline struct srcu_ctr __percpu *srcu_read_lock_fast(struct srcu_struct *ssp) __acquires(ssp)
275308
{
276309
struct srcu_ctr __percpu *retval;
277310

278311
RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_read_lock_fast().");
279-
srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_FAST);
312+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST);
280313
retval = __srcu_read_lock_fast(ssp);
281314
rcu_try_lock_acquire(&ssp->dep_map);
282315
return retval;
283316
}
284317

318+
/**
319+
* srcu_read_lock_fast_updown - register a new reader for an SRCU-fast-updown structure.
320+
* @ssp: srcu_struct in which to register the new reader.
321+
*
322+
* Enter an SRCU read-side critical section, but for a light-weight
323+
* smp_mb()-free reader. See srcu_read_lock() for more information.
324+
* This function is compatible with srcu_down_read_fast(), but is not
325+
* NMI-safe.
326+
*
327+
* For srcu_read_lock_fast_updown() to be used on an srcu_struct
328+
* structure, that structure must have been defined using either
329+
* DEFINE_SRCU_FAST_UPDOWN() or DEFINE_STATIC_SRCU_FAST_UPDOWN() on the one
330+
* hand or initialized with init_srcu_struct_fast_updown() on the other.
331+
* Such an srcu_struct structure cannot be passed to any non-fast-updown
332+
* variant of srcu_read_{,un}lock() or srcu_{down,up}_read(). In kernels
333+
* built with CONFIG_PROVE_RCU=y, __srcu_check_read_flavor() will complain
334+
* bitterly if you ignore this * restriction.
335+
*
336+
* Grace-period auto-expediting is disabled for SRCU-fast-updown
337+
* srcu_struct structures because SRCU-fast-updown expedited grace periods
338+
* invoke synchronize_rcu_expedited(), IPIs and all. If you need expedited
339+
* SRCU-fast-updown grace periods, use synchronize_srcu_expedited().
340+
*
341+
* The srcu_read_lock_fast_updown() function can be invoked only from
342+
* those contexts where RCU is watching, that is, from contexts where
343+
* it would be legal to invoke rcu_read_lock(). Otherwise, lockdep will
344+
* complain.
345+
*/
346+
static inline struct srcu_ctr __percpu *srcu_read_lock_fast_updown(struct srcu_struct *ssp)
347+
__acquires(ssp)
348+
{
349+
struct srcu_ctr __percpu *retval;
350+
351+
RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_read_lock_fast_updown().");
352+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST_UPDOWN);
353+
retval = __srcu_read_lock_fast_updown(ssp);
354+
rcu_try_lock_acquire(&ssp->dep_map);
355+
return retval;
356+
}
357+
285358
/*
286359
* Used by tracing, cannot be traced and cannot call lockdep.
287360
* See srcu_read_lock_fast() for more information.
@@ -291,7 +364,7 @@ static inline struct srcu_ctr __percpu *srcu_read_lock_fast_notrace(struct srcu_
291364
{
292365
struct srcu_ctr __percpu *retval;
293366

294-
srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_FAST);
367+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST);
295368
retval = __srcu_read_lock_fast(ssp);
296369
return retval;
297370
}
@@ -305,14 +378,15 @@ static inline struct srcu_ctr __percpu *srcu_read_lock_fast_notrace(struct srcu_
305378
* srcu_down_read() for more information.
306379
*
307380
* The same srcu_struct may be used concurrently by srcu_down_read_fast()
308-
* and srcu_read_lock_fast().
381+
* and srcu_read_lock_fast(). However, the same definition/initialization
382+
* requirements called out for srcu_read_lock_safe() apply.
309383
*/
310384
static inline struct srcu_ctr __percpu *srcu_down_read_fast(struct srcu_struct *ssp) __acquires(ssp)
311385
{
312386
WARN_ON_ONCE(IS_ENABLED(CONFIG_PROVE_RCU) && in_nmi());
313387
RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_down_read_fast().");
314-
srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_FAST);
315-
return __srcu_read_lock_fast(ssp);
388+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST_UPDOWN);
389+
return __srcu_read_lock_fast_updown(ssp);
316390
}
317391

318392
/**
@@ -408,6 +482,23 @@ static inline void srcu_read_unlock_fast(struct srcu_struct *ssp, struct srcu_ct
408482
RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_read_unlock_fast().");
409483
}
410484

485+
/**
486+
* srcu_read_unlock_fast_updown - unregister a old reader from an SRCU-fast-updown structure.
487+
* @ssp: srcu_struct in which to unregister the old reader.
488+
* @scp: return value from corresponding srcu_read_lock_fast_updown().
489+
*
490+
* Exit an SRCU-fast-updown read-side critical section.
491+
*/
492+
static inline void
493+
srcu_read_unlock_fast_updown(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp) __releases(ssp)
494+
{
495+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST_UPDOWN);
496+
srcu_lock_release(&ssp->dep_map);
497+
__srcu_read_unlock_fast_updown(ssp, scp);
498+
RCU_LOCKDEP_WARN(!rcu_is_watching(),
499+
"RCU must be watching srcu_read_unlock_fast_updown().");
500+
}
501+
411502
/*
412503
* Used by tracing, cannot be traced and cannot call lockdep.
413504
* See srcu_read_unlock_fast() for more information.
@@ -431,9 +522,9 @@ static inline void srcu_up_read_fast(struct srcu_struct *ssp, struct srcu_ctr __
431522
__releases(ssp)
432523
{
433524
WARN_ON_ONCE(IS_ENABLED(CONFIG_PROVE_RCU) && in_nmi());
434-
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST);
435-
__srcu_read_unlock_fast(ssp, scp);
436-
RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_up_read_fast().");
525+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST_UPDOWN);
526+
__srcu_read_unlock_fast_updown(ssp, scp);
527+
RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_up_read_fast_updown().");
437528
}
438529

439530
/**

0 commit comments

Comments
 (0)