Skip to content

Commit 68684b8

Browse files
committed
srcu: Convert ->srcu_lock_count and ->srcu_unlock_count to atomic
NMI-safe variants of srcu_read_lock() and srcu_read_unlock() are needed by printk(), which on many architectures entails read-modify-write atomic operations. This commit prepares Tree SRCU for this change by making both ->srcu_lock_count and ->srcu_unlock_count by atomic_long_t. Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Paul E. McKenney <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: John Ogness <[email protected]> Cc: Petr Mladek <[email protected]>
1 parent 2f91146 commit 68684b8

File tree

2 files changed

+14
-14
lines changed

2 files changed

+14
-14
lines changed

include/linux/srcutree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ struct srcu_struct;
2323
*/
2424
struct srcu_data {
2525
/* Read-side state. */
26-
unsigned long srcu_lock_count[2]; /* Locks per CPU. */
27-
unsigned long srcu_unlock_count[2]; /* Unlocks per CPU. */
26+
atomic_long_t srcu_lock_count[2]; /* Locks per CPU. */
27+
atomic_long_t srcu_unlock_count[2]; /* Unlocks per CPU. */
2828

2929
/* Update-side state. */
3030
spinlock_t __private lock ____cacheline_internodealigned_in_smp;

kernel/rcu/srcutree.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ static unsigned long srcu_readers_lock_idx(struct srcu_struct *ssp, int idx)
417417
for_each_possible_cpu(cpu) {
418418
struct srcu_data *cpuc = per_cpu_ptr(ssp->sda, cpu);
419419

420-
sum += READ_ONCE(cpuc->srcu_lock_count[idx]);
420+
sum += atomic_long_read(&cpuc->srcu_lock_count[idx]);
421421
}
422422
return sum;
423423
}
@@ -434,7 +434,7 @@ static unsigned long srcu_readers_unlock_idx(struct srcu_struct *ssp, int idx)
434434
for_each_possible_cpu(cpu) {
435435
struct srcu_data *cpuc = per_cpu_ptr(ssp->sda, cpu);
436436

437-
sum += READ_ONCE(cpuc->srcu_unlock_count[idx]);
437+
sum += atomic_long_read(&cpuc->srcu_unlock_count[idx]);
438438
}
439439
return sum;
440440
}
@@ -503,10 +503,10 @@ static bool srcu_readers_active(struct srcu_struct *ssp)
503503
for_each_possible_cpu(cpu) {
504504
struct srcu_data *cpuc = per_cpu_ptr(ssp->sda, cpu);
505505

506-
sum += READ_ONCE(cpuc->srcu_lock_count[0]);
507-
sum += READ_ONCE(cpuc->srcu_lock_count[1]);
508-
sum -= READ_ONCE(cpuc->srcu_unlock_count[0]);
509-
sum -= READ_ONCE(cpuc->srcu_unlock_count[1]);
506+
sum += atomic_long_read(&cpuc->srcu_lock_count[0]);
507+
sum += atomic_long_read(&cpuc->srcu_lock_count[1]);
508+
sum -= atomic_long_read(&cpuc->srcu_unlock_count[0]);
509+
sum -= atomic_long_read(&cpuc->srcu_unlock_count[1]);
510510
}
511511
return sum;
512512
}
@@ -636,7 +636,7 @@ int __srcu_read_lock(struct srcu_struct *ssp)
636636
int idx;
637637

638638
idx = READ_ONCE(ssp->srcu_idx) & 0x1;
639-
this_cpu_inc(ssp->sda->srcu_lock_count[idx]);
639+
this_cpu_inc(ssp->sda->srcu_lock_count[idx].counter);
640640
smp_mb(); /* B */ /* Avoid leaking the critical section. */
641641
return idx;
642642
}
@@ -650,7 +650,7 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock);
650650
void __srcu_read_unlock(struct srcu_struct *ssp, int idx)
651651
{
652652
smp_mb(); /* C */ /* Avoid leaking the critical section. */
653-
this_cpu_inc(ssp->sda->srcu_unlock_count[idx]);
653+
this_cpu_inc(ssp->sda->srcu_unlock_count[idx].counter);
654654
}
655655
EXPORT_SYMBOL_GPL(__srcu_read_unlock);
656656

@@ -1687,17 +1687,17 @@ void srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf)
16871687
struct srcu_data *sdp;
16881688

16891689
sdp = per_cpu_ptr(ssp->sda, cpu);
1690-
u0 = data_race(sdp->srcu_unlock_count[!idx]);
1691-
u1 = data_race(sdp->srcu_unlock_count[idx]);
1690+
u0 = data_race(sdp->srcu_unlock_count[!idx].counter);
1691+
u1 = data_race(sdp->srcu_unlock_count[idx].counter);
16921692

16931693
/*
16941694
* Make sure that a lock is always counted if the corresponding
16951695
* unlock is counted.
16961696
*/
16971697
smp_rmb();
16981698

1699-
l0 = data_race(sdp->srcu_lock_count[!idx]);
1700-
l1 = data_race(sdp->srcu_lock_count[idx]);
1699+
l0 = data_race(sdp->srcu_lock_count[!idx].counter);
1700+
l1 = data_race(sdp->srcu_lock_count[idx].counter);
17011701

17021702
c0 = l0 - u0;
17031703
c1 = l1 - u1;

0 commit comments

Comments
 (0)