diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/rcupdate.c | 10 | ||||
-rw-r--r-- | kernel/rcutorture.c | 12 | ||||
-rw-r--r-- | kernel/srcu.c | 50 |
3 files changed, 53 insertions, 19 deletions
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 9b7fd4723878..033cb55c26df 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -50,6 +50,16 @@ static struct lock_class_key rcu_lock_key; | |||
50 | struct lockdep_map rcu_lock_map = | 50 | struct lockdep_map rcu_lock_map = |
51 | STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key); | 51 | STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key); |
52 | EXPORT_SYMBOL_GPL(rcu_lock_map); | 52 | EXPORT_SYMBOL_GPL(rcu_lock_map); |
53 | |||
54 | static struct lock_class_key rcu_bh_lock_key; | ||
55 | struct lockdep_map rcu_bh_lock_map = | ||
56 | STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_bh", &rcu_bh_lock_key); | ||
57 | EXPORT_SYMBOL_GPL(rcu_bh_lock_map); | ||
58 | |||
59 | static struct lock_class_key rcu_sched_lock_key; | ||
60 | struct lockdep_map rcu_sched_lock_map = | ||
61 | STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key); | ||
62 | EXPORT_SYMBOL_GPL(rcu_sched_lock_map); | ||
53 | #endif | 63 | #endif |
54 | 64 | ||
55 | /* | 65 | /* |
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index adda92bfafac..5f43f30fcd1d 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
@@ -796,7 +796,11 @@ static void rcu_torture_timer(unsigned long unused) | |||
796 | 796 | ||
797 | idx = cur_ops->readlock(); | 797 | idx = cur_ops->readlock(); |
798 | completed = cur_ops->completed(); | 798 | completed = cur_ops->completed(); |
799 | p = rcu_dereference(rcu_torture_current); | 799 | p = rcu_dereference_check(rcu_torture_current, |
800 | rcu_read_lock_held() || | ||
801 | rcu_read_lock_bh_held() || | ||
802 | rcu_read_lock_sched_held() || | ||
803 | srcu_read_lock_held(&srcu_ctl)); | ||
800 | if (p == NULL) { | 804 | if (p == NULL) { |
801 | /* Leave because rcu_torture_writer is not yet underway */ | 805 | /* Leave because rcu_torture_writer is not yet underway */ |
802 | cur_ops->readunlock(idx); | 806 | cur_ops->readunlock(idx); |
@@ -853,7 +857,11 @@ rcu_torture_reader(void *arg) | |||
853 | } | 857 | } |
854 | idx = cur_ops->readlock(); | 858 | idx = cur_ops->readlock(); |
855 | completed = cur_ops->completed(); | 859 | completed = cur_ops->completed(); |
856 | p = rcu_dereference(rcu_torture_current); | 860 | p = rcu_dereference_check(rcu_torture_current, |
861 | rcu_read_lock_held() || | ||
862 | rcu_read_lock_bh_held() || | ||
863 | rcu_read_lock_sched_held() || | ||
864 | srcu_read_lock_held(&srcu_ctl)); | ||
857 | if (p == NULL) { | 865 | if (p == NULL) { |
858 | /* Wait for rcu_torture_writer to get underway */ | 866 | /* Wait for rcu_torture_writer to get underway */ |
859 | cur_ops->readunlock(idx); | 867 | cur_ops->readunlock(idx); |
diff --git a/kernel/srcu.c b/kernel/srcu.c index 31b275b9c112..bde4295774c8 100644 --- a/kernel/srcu.c +++ b/kernel/srcu.c | |||
@@ -34,6 +34,30 @@ | |||
34 | #include <linux/smp.h> | 34 | #include <linux/smp.h> |
35 | #include <linux/srcu.h> | 35 | #include <linux/srcu.h> |
36 | 36 | ||
37 | static int init_srcu_struct_fields(struct srcu_struct *sp) | ||
38 | { | ||
39 | sp->completed = 0; | ||
40 | mutex_init(&sp->mutex); | ||
41 | sp->per_cpu_ref = alloc_percpu(struct srcu_struct_array); | ||
42 | return sp->per_cpu_ref ? 0 : -ENOMEM; | ||
43 | } | ||
44 | |||
45 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
46 | |||
47 | int __init_srcu_struct(struct srcu_struct *sp, const char *name, | ||
48 | struct lock_class_key *key) | ||
49 | { | ||
50 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
51 | /* Don't re-initialize a lock while it is held. */ | ||
52 | debug_check_no_locks_freed((void *)sp, sizeof(*sp)); | ||
53 | lockdep_init_map(&sp->dep_map, name, key, 0); | ||
54 | #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ | ||
55 | return init_srcu_struct_fields(sp); | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(__init_srcu_struct); | ||
58 | |||
59 | #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ | ||
60 | |||
37 | /** | 61 | /** |
38 | * init_srcu_struct - initialize a sleep-RCU structure | 62 | * init_srcu_struct - initialize a sleep-RCU structure |
39 | * @sp: structure to initialize. | 63 | * @sp: structure to initialize. |
@@ -44,13 +68,12 @@ | |||
44 | */ | 68 | */ |
45 | int init_srcu_struct(struct srcu_struct *sp) | 69 | int init_srcu_struct(struct srcu_struct *sp) |
46 | { | 70 | { |
47 | sp->completed = 0; | 71 | return init_srcu_struct_fields(sp); |
48 | mutex_init(&sp->mutex); | ||
49 | sp->per_cpu_ref = alloc_percpu(struct srcu_struct_array); | ||
50 | return (sp->per_cpu_ref ? 0 : -ENOMEM); | ||
51 | } | 72 | } |
52 | EXPORT_SYMBOL_GPL(init_srcu_struct); | 73 | EXPORT_SYMBOL_GPL(init_srcu_struct); |
53 | 74 | ||
75 | #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ | ||
76 | |||
54 | /* | 77 | /* |
55 | * srcu_readers_active_idx -- returns approximate number of readers | 78 | * srcu_readers_active_idx -- returns approximate number of readers |
56 | * active on the specified rank of per-CPU counters. | 79 | * active on the specified rank of per-CPU counters. |
@@ -100,15 +123,12 @@ void cleanup_srcu_struct(struct srcu_struct *sp) | |||
100 | } | 123 | } |
101 | EXPORT_SYMBOL_GPL(cleanup_srcu_struct); | 124 | EXPORT_SYMBOL_GPL(cleanup_srcu_struct); |
102 | 125 | ||
103 | /** | 126 | /* |
104 | * srcu_read_lock - register a new reader for an SRCU-protected structure. | ||
105 | * @sp: srcu_struct in which to register the new reader. | ||
106 | * | ||
107 | * Counts the new reader in the appropriate per-CPU element of the | 127 | * Counts the new reader in the appropriate per-CPU element of the |
108 | * srcu_struct. Must be called from process context. | 128 | * srcu_struct. Must be called from process context. |
109 | * Returns an index that must be passed to the matching srcu_read_unlock(). | 129 | * Returns an index that must be passed to the matching srcu_read_unlock(). |
110 | */ | 130 | */ |
111 | int srcu_read_lock(struct srcu_struct *sp) | 131 | int __srcu_read_lock(struct srcu_struct *sp) |
112 | { | 132 | { |
113 | int idx; | 133 | int idx; |
114 | 134 | ||
@@ -120,26 +140,22 @@ int srcu_read_lock(struct srcu_struct *sp) | |||
120 | preempt_enable(); | 140 | preempt_enable(); |
121 | return idx; | 141 | return idx; |
122 | } | 142 | } |
123 | EXPORT_SYMBOL_GPL(srcu_read_lock); | 143 | EXPORT_SYMBOL_GPL(__srcu_read_lock); |
124 | 144 | ||
125 | /** | 145 | /* |
126 | * srcu_read_unlock - unregister a old reader from an SRCU-protected structure. | ||
127 | * @sp: srcu_struct in which to unregister the old reader. | ||
128 | * @idx: return value from corresponding srcu_read_lock(). | ||
129 | * | ||
130 | * Removes the count for the old reader from the appropriate per-CPU | 146 | * Removes the count for the old reader from the appropriate per-CPU |
131 | * element of the srcu_struct. Note that this may well be a different | 147 | * element of the srcu_struct. Note that this may well be a different |
132 | * CPU than that which was incremented by the corresponding srcu_read_lock(). | 148 | * CPU than that which was incremented by the corresponding srcu_read_lock(). |
133 | * Must be called from process context. | 149 | * Must be called from process context. |
134 | */ | 150 | */ |
135 | void srcu_read_unlock(struct srcu_struct *sp, int idx) | 151 | void __srcu_read_unlock(struct srcu_struct *sp, int idx) |
136 | { | 152 | { |
137 | preempt_disable(); | 153 | preempt_disable(); |
138 | srcu_barrier(); /* ensure compiler won't misorder critical section. */ | 154 | srcu_barrier(); /* ensure compiler won't misorder critical section. */ |
139 | per_cpu_ptr(sp->per_cpu_ref, smp_processor_id())->c[idx]--; | 155 | per_cpu_ptr(sp->per_cpu_ref, smp_processor_id())->c[idx]--; |
140 | preempt_enable(); | 156 | preempt_enable(); |
141 | } | 157 | } |
142 | EXPORT_SYMBOL_GPL(srcu_read_unlock); | 158 | EXPORT_SYMBOL_GPL(__srcu_read_unlock); |
143 | 159 | ||
144 | /* | 160 | /* |
145 | * Helper function for synchronize_srcu() and synchronize_srcu_expedited(). | 161 | * Helper function for synchronize_srcu() and synchronize_srcu_expedited(). |