Skip to content

Commit d8dfba2

Browse files
author
Frederic Weisbecker
committed
Merge branches 'rcu/fixes', 'rcu/nocb', 'rcu/torture', 'rcu/stall' and 'rcu/srcu' into rcu/dev
5 parents a23da88 + 2996980 + c229d57 + 9650edd + 9407f5c commit d8dfba2

File tree

20 files changed

+410
-170
lines changed

20 files changed

+410
-170
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5421,6 +5421,14 @@
54215421
The delay, in seconds, between successive
54225422
read-then-exit testing episodes.
54235423

5424+
rcutorture.reader_flavor= [KNL]
5425+
A bit mask indicating which readers to use.
5426+
If there is more than one bit set, the readers
5427+
are entered from low-order bit up, and are
5428+
exited in the opposite order. For SRCU, the
5429+
0x1 bit is normal readers, 0x2 NMI-safe readers,
5430+
and 0x4 light-weight readers.
5431+
54245432
rcutorture.shuffle_interval= [KNL]
54255433
Set task-shuffle interval (s). Shuffling tasks
54265434
allows some CPUs to go into dyntick-idle mode

include/linux/rcutiny.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ static inline bool rcu_inkernel_boot_has_ended(void) { return true; }
165165
static inline bool rcu_is_watching(void) { return true; }
166166
static inline void rcu_momentary_eqs(void) { }
167167
static inline void kfree_rcu_scheduler_running(void) { }
168-
static inline bool rcu_gp_might_be_stalled(void) { return false; }
169168

170169
/* Avoid RCU read-side critical sections leaking across. */
171170
static inline void rcu_all_qs(void) { barrier(); }

include/linux/rcutree.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ void kvfree_rcu_barrier(void);
4040
void rcu_barrier(void);
4141
void rcu_momentary_eqs(void);
4242
void kfree_rcu_scheduler_running(void);
43-
bool rcu_gp_might_be_stalled(void);
4443

4544
struct rcu_gp_oldstate {
4645
unsigned long rgos_norm;

include/linux/srcu.h

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ void call_srcu(struct srcu_struct *ssp, struct rcu_head *head,
5656
void cleanup_srcu_struct(struct srcu_struct *ssp);
5757
int __srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp);
5858
void __srcu_read_unlock(struct srcu_struct *ssp, int idx) __releases(ssp);
59+
#ifdef CONFIG_TINY_SRCU
60+
#define __srcu_read_lock_lite __srcu_read_lock
61+
#define __srcu_read_unlock_lite __srcu_read_unlock
62+
#else // #ifdef CONFIG_TINY_SRCU
63+
int __srcu_read_lock_lite(struct srcu_struct *ssp) __acquires(ssp);
64+
void __srcu_read_unlock_lite(struct srcu_struct *ssp, int idx) __releases(ssp);
65+
#endif // #else // #ifdef CONFIG_TINY_SRCU
5966
void synchronize_srcu(struct srcu_struct *ssp);
6067

6168
#define SRCU_GET_STATE_COMPLETED 0x1
@@ -176,17 +183,6 @@ static inline int srcu_read_lock_held(const struct srcu_struct *ssp)
176183

177184
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
178185

179-
#define SRCU_NMI_UNKNOWN 0x0
180-
#define SRCU_NMI_UNSAFE 0x1
181-
#define SRCU_NMI_SAFE 0x2
182-
183-
#if defined(CONFIG_PROVE_RCU) && defined(CONFIG_TREE_SRCU)
184-
void srcu_check_nmi_safety(struct srcu_struct *ssp, bool nmi_safe);
185-
#else
186-
static inline void srcu_check_nmi_safety(struct srcu_struct *ssp,
187-
bool nmi_safe) { }
188-
#endif
189-
190186

191187
/**
192188
* srcu_dereference_check - fetch SRCU-protected pointer for later dereferencing
@@ -236,33 +232,67 @@ static inline void srcu_check_nmi_safety(struct srcu_struct *ssp,
236232
* a mutex that is held elsewhere while calling synchronize_srcu() or
237233
* synchronize_srcu_expedited().
238234
*
239-
* Note that srcu_read_lock() and the matching srcu_read_unlock() must
240-
* occur in the same context, for example, it is illegal to invoke
241-
* srcu_read_unlock() in an irq handler if the matching srcu_read_lock()
242-
* was invoked in process context.
235+
* The return value from srcu_read_lock() must be passed unaltered
236+
* to the matching srcu_read_unlock(). Note that srcu_read_lock() and
237+
* the matching srcu_read_unlock() must occur in the same context, for
238+
* example, it is illegal to invoke srcu_read_unlock() in an irq handler
239+
* if the matching srcu_read_lock() was invoked in process context. Or,
240+
* for that matter to invoke srcu_read_unlock() from one task and the
241+
* matching srcu_read_lock() from another.
243242
*/
244243
static inline int srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp)
245244
{
246245
int retval;
247246

248-
srcu_check_nmi_safety(ssp, false);
247+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
249248
retval = __srcu_read_lock(ssp);
250249
srcu_lock_acquire(&ssp->dep_map);
251250
return retval;
252251
}
253252

253+
/**
254+
* srcu_read_lock_lite - register a new reader for an SRCU-protected structure.
255+
* @ssp: srcu_struct in which to register the new reader.
256+
*
257+
* Enter an SRCU read-side critical section, but for a light-weight
258+
* smp_mb()-free reader. See srcu_read_lock() for more information.
259+
*
260+
* If srcu_read_lock_lite() is ever used on an srcu_struct structure,
261+
* then none of the other flavors may be used, whether before, during,
262+
* or after. Note that grace-period auto-expediting is disabled for _lite
263+
* srcu_struct structures because auto-expedited grace periods invoke
264+
* synchronize_rcu_expedited(), IPIs and all.
265+
*
266+
* Note that srcu_read_lock_lite() can be invoked only from those contexts
267+
* where RCU is watching, that is, from contexts where it would be legal
268+
* to invoke rcu_read_lock(). Otherwise, lockdep will complain.
269+
*/
270+
static inline int srcu_read_lock_lite(struct srcu_struct *ssp) __acquires(ssp)
271+
{
272+
int retval;
273+
274+
srcu_check_read_flavor_lite(ssp);
275+
retval = __srcu_read_lock_lite(ssp);
276+
rcu_try_lock_acquire(&ssp->dep_map);
277+
return retval;
278+
}
279+
254280
/**
255281
* srcu_read_lock_nmisafe - register a new reader for an SRCU-protected structure.
256282
* @ssp: srcu_struct in which to register the new reader.
257283
*
258284
* Enter an SRCU read-side critical section, but in an NMI-safe manner.
259285
* See srcu_read_lock() for more information.
286+
*
287+
* If srcu_read_lock_nmisafe() is ever used on an srcu_struct structure,
288+
* then none of the other flavors may be used, whether before, during,
289+
* or after.
260290
*/
261291
static inline int srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp)
262292
{
263293
int retval;
264294

265-
srcu_check_nmi_safety(ssp, true);
295+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NMI);
266296
retval = __srcu_read_lock_nmisafe(ssp);
267297
rcu_try_lock_acquire(&ssp->dep_map);
268298
return retval;
@@ -274,7 +304,7 @@ srcu_read_lock_notrace(struct srcu_struct *ssp) __acquires(ssp)
274304
{
275305
int retval;
276306

277-
srcu_check_nmi_safety(ssp, false);
307+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
278308
retval = __srcu_read_lock(ssp);
279309
return retval;
280310
}
@@ -303,7 +333,7 @@ srcu_read_lock_notrace(struct srcu_struct *ssp) __acquires(ssp)
303333
static inline int srcu_down_read(struct srcu_struct *ssp) __acquires(ssp)
304334
{
305335
WARN_ON_ONCE(in_nmi());
306-
srcu_check_nmi_safety(ssp, false);
336+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
307337
return __srcu_read_lock(ssp);
308338
}
309339

@@ -318,11 +348,27 @@ static inline void srcu_read_unlock(struct srcu_struct *ssp, int idx)
318348
__releases(ssp)
319349
{
320350
WARN_ON_ONCE(idx & ~0x1);
321-
srcu_check_nmi_safety(ssp, false);
351+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
322352
srcu_lock_release(&ssp->dep_map);
323353
__srcu_read_unlock(ssp, idx);
324354
}
325355

356+
/**
357+
* srcu_read_unlock_lite - unregister a old reader from an SRCU-protected structure.
358+
* @ssp: srcu_struct in which to unregister the old reader.
359+
* @idx: return value from corresponding srcu_read_lock().
360+
*
361+
* Exit a light-weight SRCU read-side critical section.
362+
*/
363+
static inline void srcu_read_unlock_lite(struct srcu_struct *ssp, int idx)
364+
__releases(ssp)
365+
{
366+
WARN_ON_ONCE(idx & ~0x1);
367+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_LITE);
368+
srcu_lock_release(&ssp->dep_map);
369+
__srcu_read_unlock_lite(ssp, idx);
370+
}
371+
326372
/**
327373
* srcu_read_unlock_nmisafe - unregister a old reader from an SRCU-protected structure.
328374
* @ssp: srcu_struct in which to unregister the old reader.
@@ -334,7 +380,7 @@ static inline void srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx)
334380
__releases(ssp)
335381
{
336382
WARN_ON_ONCE(idx & ~0x1);
337-
srcu_check_nmi_safety(ssp, true);
383+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NMI);
338384
rcu_lock_release(&ssp->dep_map);
339385
__srcu_read_unlock_nmisafe(ssp, idx);
340386
}
@@ -343,7 +389,7 @@ static inline void srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx)
343389
static inline notrace void
344390
srcu_read_unlock_notrace(struct srcu_struct *ssp, int idx) __releases(ssp)
345391
{
346-
srcu_check_nmi_safety(ssp, false);
392+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
347393
__srcu_read_unlock(ssp, idx);
348394
}
349395

@@ -360,7 +406,7 @@ static inline void srcu_up_read(struct srcu_struct *ssp, int idx)
360406
{
361407
WARN_ON_ONCE(idx & ~0x1);
362408
WARN_ON_ONCE(in_nmi());
363-
srcu_check_nmi_safety(ssp, false);
409+
srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
364410
__srcu_read_unlock(ssp, idx);
365411
}
366412

include/linux/srcutiny.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ static inline void srcu_barrier(struct srcu_struct *ssp)
8181
synchronize_srcu(ssp);
8282
}
8383

84+
#define srcu_check_read_flavor(ssp, read_flavor) do { } while (0)
85+
#define srcu_check_read_flavor_lite(ssp) do { } while (0)
86+
8487
/* Defined here to avoid size increase for non-torture kernels. */
8588
static inline void srcu_torture_stats_print(struct srcu_struct *ssp,
8689
char *tt, char *tf)

include/linux/srcutree.h

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct srcu_data {
2525
/* Read-side state. */
2626
atomic_long_t srcu_lock_count[2]; /* Locks per CPU. */
2727
atomic_long_t srcu_unlock_count[2]; /* Unlocks per CPU. */
28-
int srcu_nmi_safety; /* NMI-safe srcu_struct structure? */
28+
int srcu_reader_flavor; /* Reader flavor for srcu_struct structure? */
2929

3030
/* Update-side state. */
3131
spinlock_t __private lock ____cacheline_internodealigned_in_smp;
@@ -43,6 +43,11 @@ struct srcu_data {
4343
struct srcu_struct *ssp;
4444
};
4545

46+
/* Values for ->srcu_reader_flavor. */
47+
#define SRCU_READ_FLAVOR_NORMAL 0x1 // srcu_read_lock().
48+
#define SRCU_READ_FLAVOR_NMI 0x2 // srcu_read_lock_nmisafe().
49+
#define SRCU_READ_FLAVOR_LITE 0x4 // srcu_read_lock_lite().
50+
4651
/*
4752
* Node in SRCU combining tree, similar in function to rcu_data.
4853
*/
@@ -204,4 +209,64 @@ void synchronize_srcu_expedited(struct srcu_struct *ssp);
204209
void srcu_barrier(struct srcu_struct *ssp);
205210
void srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf);
206211

212+
/*
213+
* Counts the new reader in the appropriate per-CPU element of the
214+
* srcu_struct. Returns an index that must be passed to the matching
215+
* srcu_read_unlock_lite().
216+
*
217+
* Note that this_cpu_inc() is an RCU read-side critical section either
218+
* because it disables interrupts, because it is a single instruction,
219+
* or because it is a read-modify-write atomic operation, depending on
220+
* the whims of the architecture.
221+
*/
222+
static inline int __srcu_read_lock_lite(struct srcu_struct *ssp)
223+
{
224+
int idx;
225+
226+
RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_read_lock_lite().");
227+
idx = READ_ONCE(ssp->srcu_idx) & 0x1;
228+
this_cpu_inc(ssp->sda->srcu_lock_count[idx].counter); /* Y */
229+
barrier(); /* Avoid leaking the critical section. */
230+
return idx;
231+
}
232+
233+
/*
234+
* Removes the count for the old reader from the appropriate
235+
* per-CPU element of the srcu_struct. Note that this may well be a
236+
* different CPU than that which was incremented by the corresponding
237+
* srcu_read_lock_lite(), but it must be within the same task.
238+
*
239+
* Note that this_cpu_inc() is an RCU read-side critical section either
240+
* because it disables interrupts, because it is a single instruction,
241+
* or because it is a read-modify-write atomic operation, depending on
242+
* the whims of the architecture.
243+
*/
244+
static inline void __srcu_read_unlock_lite(struct srcu_struct *ssp, int idx)
245+
{
246+
barrier(); /* Avoid leaking the critical section. */
247+
this_cpu_inc(ssp->sda->srcu_unlock_count[idx].counter); /* Z */
248+
RCU_LOCKDEP_WARN(!rcu_is_watching(), "RCU must be watching srcu_read_unlock_lite().");
249+
}
250+
251+
void __srcu_check_read_flavor(struct srcu_struct *ssp, int read_flavor);
252+
253+
// Record _lite() usage even for CONFIG_PROVE_RCU=n kernels.
254+
static inline void srcu_check_read_flavor_lite(struct srcu_struct *ssp)
255+
{
256+
struct srcu_data *sdp = raw_cpu_ptr(ssp->sda);
257+
258+
if (likely(READ_ONCE(sdp->srcu_reader_flavor) & SRCU_READ_FLAVOR_LITE))
259+
return;
260+
261+
// Note that the cmpxchg() in srcu_check_read_flavor() is fully ordered.
262+
__srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_LITE);
263+
}
264+
265+
// Record non-_lite() usage only for CONFIG_PROVE_RCU=y kernels.
266+
static inline void srcu_check_read_flavor(struct srcu_struct *ssp, int read_flavor)
267+
{
268+
if (IS_ENABLED(CONFIG_PROVE_RCU))
269+
__srcu_check_read_flavor(ssp, read_flavor);
270+
}
271+
207272
#endif

kernel/rcu/rcu_segcblist.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ void rcu_segcblist_inc_len(struct rcu_segcblist *rsclp);
120120
void rcu_segcblist_add_len(struct rcu_segcblist *rsclp, long v);
121121
void rcu_segcblist_init(struct rcu_segcblist *rsclp);
122122
void rcu_segcblist_disable(struct rcu_segcblist *rsclp);
123-
void rcu_segcblist_offload(struct rcu_segcblist *rsclp, bool offload);
124123
bool rcu_segcblist_ready_cbs(struct rcu_segcblist *rsclp);
125124
bool rcu_segcblist_pend_cbs(struct rcu_segcblist *rsclp);
126125
struct rcu_head *rcu_segcblist_first_cb(struct rcu_segcblist *rsclp);

kernel/rcu/rcuscale.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -889,14 +889,14 @@ kfree_scale_init(void)
889889

890890
if (WARN_ON_ONCE(jiffies_at_lazy_cb - jif_start < 2 * HZ)) {
891891
pr_alert("ERROR: call_rcu() CBs are not being lazy as expected!\n");
892-
WARN_ON_ONCE(1);
893-
return -1;
892+
firsterr = -1;
893+
goto unwind;
894894
}
895895

896896
if (WARN_ON_ONCE(jiffies_at_lazy_cb - jif_start > 3 * HZ)) {
897897
pr_alert("ERROR: call_rcu() CBs are being too lazy!\n");
898-
WARN_ON_ONCE(1);
899-
return -1;
898+
firsterr = -1;
899+
goto unwind;
900900
}
901901
}
902902

0 commit comments

Comments
 (0)