diff options
Diffstat (limited to 'kernel/srcu.c')
| -rw-r--r-- | kernel/srcu.c | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/kernel/srcu.c b/kernel/srcu.c index b0aeeaf22ce4..818d7d9aa03c 100644 --- a/kernel/srcu.c +++ b/kernel/srcu.c | |||
| @@ -49,6 +49,7 @@ int init_srcu_struct(struct srcu_struct *sp) | |||
| 49 | sp->per_cpu_ref = alloc_percpu(struct srcu_struct_array); | 49 | sp->per_cpu_ref = alloc_percpu(struct srcu_struct_array); |
| 50 | return (sp->per_cpu_ref ? 0 : -ENOMEM); | 50 | return (sp->per_cpu_ref ? 0 : -ENOMEM); |
| 51 | } | 51 | } |
| 52 | EXPORT_SYMBOL_GPL(init_srcu_struct); | ||
| 52 | 53 | ||
| 53 | /* | 54 | /* |
| 54 | * srcu_readers_active_idx -- returns approximate number of readers | 55 | * srcu_readers_active_idx -- returns approximate number of readers |
| @@ -97,6 +98,7 @@ void cleanup_srcu_struct(struct srcu_struct *sp) | |||
| 97 | free_percpu(sp->per_cpu_ref); | 98 | free_percpu(sp->per_cpu_ref); |
| 98 | sp->per_cpu_ref = NULL; | 99 | sp->per_cpu_ref = NULL; |
| 99 | } | 100 | } |
| 101 | EXPORT_SYMBOL_GPL(cleanup_srcu_struct); | ||
| 100 | 102 | ||
| 101 | /** | 103 | /** |
| 102 | * srcu_read_lock - register a new reader for an SRCU-protected structure. | 104 | * srcu_read_lock - register a new reader for an SRCU-protected structure. |
| @@ -118,6 +120,7 @@ int srcu_read_lock(struct srcu_struct *sp) | |||
| 118 | preempt_enable(); | 120 | preempt_enable(); |
| 119 | return idx; | 121 | return idx; |
| 120 | } | 122 | } |
| 123 | EXPORT_SYMBOL_GPL(srcu_read_lock); | ||
| 121 | 124 | ||
| 122 | /** | 125 | /** |
| 123 | * srcu_read_unlock - unregister a old reader from an SRCU-protected structure. | 126 | * srcu_read_unlock - unregister a old reader from an SRCU-protected structure. |
| @@ -136,22 +139,12 @@ void srcu_read_unlock(struct srcu_struct *sp, int idx) | |||
| 136 | per_cpu_ptr(sp->per_cpu_ref, smp_processor_id())->c[idx]--; | 139 | per_cpu_ptr(sp->per_cpu_ref, smp_processor_id())->c[idx]--; |
| 137 | preempt_enable(); | 140 | preempt_enable(); |
| 138 | } | 141 | } |
| 142 | EXPORT_SYMBOL_GPL(srcu_read_unlock); | ||
| 139 | 143 | ||
| 140 | /** | 144 | /* |
| 141 | * synchronize_srcu - wait for prior SRCU read-side critical-section completion | 145 | * Helper function for synchronize_srcu() and synchronize_srcu_expedited(). |
| 142 | * @sp: srcu_struct with which to synchronize. | ||
| 143 | * | ||
| 144 | * Flip the completed counter, and wait for the old count to drain to zero. | ||
| 145 | * As with classic RCU, the updater must use some separate means of | ||
| 146 | * synchronizing concurrent updates. Can block; must be called from | ||
| 147 | * process context. | ||
| 148 | * | ||
| 149 | * Note that it is illegal to call synchornize_srcu() from the corresponding | ||
| 150 | * SRCU read-side critical section; doing so will result in deadlock. | ||
| 151 | * However, it is perfectly legal to call synchronize_srcu() on one | ||
| 152 | * srcu_struct from some other srcu_struct's read-side critical section. | ||
| 153 | */ | 146 | */ |
| 154 | void synchronize_srcu(struct srcu_struct *sp) | 147 | void __synchronize_srcu(struct srcu_struct *sp, void (*sync_func)(void)) |
| 155 | { | 148 | { |
| 156 | int idx; | 149 | int idx; |
| 157 | 150 | ||
| @@ -173,7 +166,7 @@ void synchronize_srcu(struct srcu_struct *sp) | |||
| 173 | return; | 166 | return; |
| 174 | } | 167 | } |
| 175 | 168 | ||
| 176 | synchronize_sched(); /* Force memory barrier on all CPUs. */ | 169 | sync_func(); /* Force memory barrier on all CPUs. */ |
| 177 | 170 | ||
| 178 | /* | 171 | /* |
| 179 | * The preceding synchronize_sched() ensures that any CPU that | 172 | * The preceding synchronize_sched() ensures that any CPU that |
| @@ -190,7 +183,7 @@ void synchronize_srcu(struct srcu_struct *sp) | |||
| 190 | idx = sp->completed & 0x1; | 183 | idx = sp->completed & 0x1; |
| 191 | sp->completed++; | 184 | sp->completed++; |
| 192 | 185 | ||
| 193 | synchronize_sched(); /* Force memory barrier on all CPUs. */ | 186 | sync_func(); /* Force memory barrier on all CPUs. */ |
| 194 | 187 | ||
| 195 | /* | 188 | /* |
| 196 | * At this point, because of the preceding synchronize_sched(), | 189 | * At this point, because of the preceding synchronize_sched(), |
| @@ -203,7 +196,7 @@ void synchronize_srcu(struct srcu_struct *sp) | |||
| 203 | while (srcu_readers_active_idx(sp, idx)) | 196 | while (srcu_readers_active_idx(sp, idx)) |
| 204 | schedule_timeout_interruptible(1); | 197 | schedule_timeout_interruptible(1); |
| 205 | 198 | ||
| 206 | synchronize_sched(); /* Force memory barrier on all CPUs. */ | 199 | sync_func(); /* Force memory barrier on all CPUs. */ |
| 207 | 200 | ||
| 208 | /* | 201 | /* |
| 209 | * The preceding synchronize_sched() forces all srcu_read_unlock() | 202 | * The preceding synchronize_sched() forces all srcu_read_unlock() |
| @@ -237,6 +230,47 @@ void synchronize_srcu(struct srcu_struct *sp) | |||
| 237 | } | 230 | } |
| 238 | 231 | ||
| 239 | /** | 232 | /** |
| 233 | * synchronize_srcu - wait for prior SRCU read-side critical-section completion | ||
| 234 | * @sp: srcu_struct with which to synchronize. | ||
| 235 | * | ||
| 236 | * Flip the completed counter, and wait for the old count to drain to zero. | ||
| 237 | * As with classic RCU, the updater must use some separate means of | ||
| 238 | * synchronizing concurrent updates. Can block; must be called from | ||
| 239 | * process context. | ||
| 240 | * | ||
| 241 | * Note that it is illegal to call synchronize_srcu() from the corresponding | ||
| 242 | * SRCU read-side critical section; doing so will result in deadlock. | ||
| 243 | * However, it is perfectly legal to call synchronize_srcu() on one | ||
| 244 | * srcu_struct from some other srcu_struct's read-side critical section. | ||
| 245 | */ | ||
| 246 | void synchronize_srcu(struct srcu_struct *sp) | ||
| 247 | { | ||
| 248 | __synchronize_srcu(sp, synchronize_sched); | ||
| 249 | } | ||
| 250 | EXPORT_SYMBOL_GPL(synchronize_srcu); | ||
| 251 | |||
| 252 | /** | ||
| 253 | * synchronize_srcu_expedited - like synchronize_srcu, but less patient | ||
| 254 | * @sp: srcu_struct with which to synchronize. | ||
| 255 | * | ||
| 256 | * Flip the completed counter, and wait for the old count to drain to zero. | ||
| 257 | * As with classic RCU, the updater must use some separate means of | ||
| 258 | * synchronizing concurrent updates. Can block; must be called from | ||
| 259 | * process context. | ||
| 260 | * | ||
| 261 | * Note that it is illegal to call synchronize_srcu_expedited() | ||
| 262 | * from the corresponding SRCU read-side critical section; doing so | ||
| 263 | * will result in deadlock. However, it is perfectly legal to call | ||
| 264 | * synchronize_srcu_expedited() on one srcu_struct from some other | ||
| 265 | * srcu_struct's read-side critical section. | ||
| 266 | */ | ||
| 267 | void synchronize_srcu_expedited(struct srcu_struct *sp) | ||
| 268 | { | ||
| 269 | __synchronize_srcu(sp, synchronize_sched_expedited); | ||
| 270 | } | ||
| 271 | EXPORT_SYMBOL_GPL(synchronize_srcu_expedited); | ||
| 272 | |||
| 273 | /** | ||
| 240 | * srcu_batches_completed - return batches completed. | 274 | * srcu_batches_completed - return batches completed. |
| 241 | * @sp: srcu_struct on which to report batch completion. | 275 | * @sp: srcu_struct on which to report batch completion. |
| 242 | * | 276 | * |
| @@ -248,10 +282,4 @@ long srcu_batches_completed(struct srcu_struct *sp) | |||
| 248 | { | 282 | { |
| 249 | return sp->completed; | 283 | return sp->completed; |
| 250 | } | 284 | } |
| 251 | |||
| 252 | EXPORT_SYMBOL_GPL(init_srcu_struct); | ||
| 253 | EXPORT_SYMBOL_GPL(cleanup_srcu_struct); | ||
| 254 | EXPORT_SYMBOL_GPL(srcu_read_lock); | ||
| 255 | EXPORT_SYMBOL_GPL(srcu_read_unlock); | ||
| 256 | EXPORT_SYMBOL_GPL(synchronize_srcu); | ||
| 257 | EXPORT_SYMBOL_GPL(srcu_batches_completed); | 285 | EXPORT_SYMBOL_GPL(srcu_batches_completed); |
