[PATCH] rcu: join rcu_ctrlblk and rcu_state

This patch moves rcu_state into the rcu_ctrlblk. I think there
are no reasons why we should have 2 different variables to control
rcu state. Every user of rcu_state has also "rcu_ctrlblk *rcp" in
the parameter list.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Acked-by: Paul E. McKenney <paulmck@us.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Oleg Nesterov and committed by
Linus Torvalds
69a0b315 c0400dc5

+42 -44
+4
include/linux/rcupdate.h
··· 65 long cur; /* Current batch number. */ 66 long completed; /* Number of the last completed batch */ 67 int next_pending; /* Is the next batch already waiting? */ 68 } ____cacheline_internodealigned_in_smp; 69 70 /* Is batch a before batch b ? */
··· 65 long cur; /* Current batch number. */ 66 long completed; /* Number of the last completed batch */ 67 int next_pending; /* Is the next batch already waiting? */ 68 + 69 + spinlock_t lock ____cacheline_internodealigned_in_smp; 70 + cpumask_t cpumask; /* CPUs that need to switch in order */ 71 + /* for current batch to proceed. */ 72 } ____cacheline_internodealigned_in_smp; 73 74 /* Is batch a before batch b ? */
+38 -44
kernel/rcupdate.c
··· 49 #include <linux/cpu.h> 50 51 /* Definition for rcupdate control block. */ 52 - struct rcu_ctrlblk rcu_ctrlblk = 53 - { .cur = -300, .completed = -300 }; 54 - struct rcu_ctrlblk rcu_bh_ctrlblk = 55 - { .cur = -300, .completed = -300 }; 56 - 57 - /* Bookkeeping of the progress of the grace period */ 58 - struct rcu_state { 59 - spinlock_t lock; /* Guard this struct and writes to rcu_ctrlblk */ 60 - cpumask_t cpumask; /* CPUs that need to switch in order */ 61 - /* for current batch to proceed. */ 62 }; 63 - 64 - static struct rcu_state rcu_state ____cacheline_internodealigned_in_smp = 65 - {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE }; 66 - static struct rcu_state rcu_bh_state ____cacheline_internodealigned_in_smp = 67 - {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE }; 68 69 DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L }; 70 DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L }; ··· 216 * This is done by rcu_start_batch. The start is not broadcasted to 217 * all cpus, they must pick this up by comparing rcp->cur with 218 * rdp->quiescbatch. All cpus are recorded in the 219 - * rcu_state.cpumask bitmap. 220 * - All cpus must go through a quiescent state. 221 * Since the start of the grace period is not broadcasted, at least two 222 * calls to rcu_check_quiescent_state are required: 223 * The first call just notices that a new grace period is running. The 224 * following calls check if there was a quiescent state since the beginning 225 - * of the grace period. If so, it updates rcu_state.cpumask. If 226 * the bitmap is empty, then the grace period is completed. 227 * rcu_check_quiescent_state calls rcu_start_batch(0) to start the next grace 228 * period (if necessary). ··· 230 /* 231 * Register a new batch of callbacks, and start it up if there is currently no 232 * active batch and the batch to be registered has not already occurred. 233 - * Caller must hold rcu_state.lock. 234 */ 235 - static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp) 236 { 237 if (rcp->next_pending && 238 rcp->completed == rcp->cur) { ··· 247 /* 248 * Accessing nohz_cpu_mask before incrementing rcp->cur needs a 249 * Barrier Otherwise it can cause tickless idle CPUs to be 250 - * included in rsp->cpumask, which will extend graceperiods 251 * unnecessarily. 252 */ 253 smp_mb(); 254 - cpus_andnot(rsp->cpumask, cpu_online_map, nohz_cpu_mask); 255 256 } 257 } ··· 261 * Clear it from the cpu mask and complete the grace period if it was the last 262 * cpu. Start another grace period if someone has further entries pending 263 */ 264 - static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp) 265 { 266 - cpu_clear(cpu, rsp->cpumask); 267 - if (cpus_empty(rsp->cpumask)) { 268 /* batch completed ! */ 269 rcp->completed = rcp->cur; 270 - rcu_start_batch(rcp, rsp); 271 } 272 } 273 ··· 277 * quiescent cycle, then indicate that it has done so. 278 */ 279 static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, 280 - struct rcu_state *rsp, struct rcu_data *rdp) 281 { 282 if (rdp->quiescbatch != rcp->cur) { 283 /* start new grace period: */ ··· 302 return; 303 rdp->qs_pending = 0; 304 305 - spin_lock(&rsp->lock); 306 /* 307 * rdp->quiescbatch/rcp->cur and the cpu bitmap can come out of sync 308 * during cpu startup. Ignore the quiescent state. 309 */ 310 if (likely(rdp->quiescbatch == rcp->cur)) 311 - cpu_quiet(rdp->cpu, rcp, rsp); 312 313 - spin_unlock(&rsp->lock); 314 } 315 316 ··· 331 } 332 333 static void __rcu_offline_cpu(struct rcu_data *this_rdp, 334 - struct rcu_ctrlblk *rcp, struct rcu_state *rsp, struct rcu_data *rdp) 335 { 336 /* if the cpu going offline owns the grace period 337 * we can block indefinitely waiting for it, so flush 338 * it here 339 */ 340 - spin_lock_bh(&rsp->lock); 341 if (rcp->cur != rcp->completed) 342 - cpu_quiet(rdp->cpu, rcp, rsp); 343 - spin_unlock_bh(&rsp->lock); 344 rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail); 345 rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail); 346 ··· 350 struct rcu_data *this_rdp = &get_cpu_var(rcu_data); 351 struct rcu_data *this_bh_rdp = &get_cpu_var(rcu_bh_data); 352 353 - __rcu_offline_cpu(this_rdp, &rcu_ctrlblk, &rcu_state, 354 &per_cpu(rcu_data, cpu)); 355 - __rcu_offline_cpu(this_bh_rdp, &rcu_bh_ctrlblk, &rcu_bh_state, 356 &per_cpu(rcu_bh_data, cpu)); 357 put_cpu_var(rcu_data); 358 put_cpu_var(rcu_bh_data); ··· 371 * This does the RCU processing work from tasklet context. 372 */ 373 static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, 374 - struct rcu_state *rsp, struct rcu_data *rdp) 375 { 376 if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) { 377 *rdp->donetail = rdp->curlist; ··· 401 402 if (!rcp->next_pending) { 403 /* and start it/schedule start if it's a new batch */ 404 - spin_lock(&rsp->lock); 405 rcp->next_pending = 1; 406 - rcu_start_batch(rcp, rsp); 407 - spin_unlock(&rsp->lock); 408 } 409 } else { 410 local_irq_enable(); 411 } 412 - rcu_check_quiescent_state(rcp, rsp, rdp); 413 if (rdp->donelist) 414 rcu_do_batch(rdp); 415 } 416 417 static void rcu_process_callbacks(unsigned long unused) 418 { 419 - __rcu_process_callbacks(&rcu_ctrlblk, &rcu_state, 420 - &__get_cpu_var(rcu_data)); 421 - __rcu_process_callbacks(&rcu_bh_ctrlblk, &rcu_bh_state, 422 - &__get_cpu_var(rcu_bh_data)); 423 } 424 425 static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp)
··· 49 #include <linux/cpu.h> 50 51 /* Definition for rcupdate control block. */ 52 + struct rcu_ctrlblk rcu_ctrlblk = { 53 + .cur = -300, 54 + .completed = -300, 55 + .lock = SPIN_LOCK_UNLOCKED, 56 + .cpumask = CPU_MASK_NONE, 57 }; 58 + struct rcu_ctrlblk rcu_bh_ctrlblk = { 59 + .cur = -300, 60 + .completed = -300, 61 + .lock = SPIN_LOCK_UNLOCKED, 62 + .cpumask = CPU_MASK_NONE, 63 + }; 64 65 DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L }; 66 DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L }; ··· 220 * This is done by rcu_start_batch. The start is not broadcasted to 221 * all cpus, they must pick this up by comparing rcp->cur with 222 * rdp->quiescbatch. All cpus are recorded in the 223 + * rcu_ctrlblk.cpumask bitmap. 224 * - All cpus must go through a quiescent state. 225 * Since the start of the grace period is not broadcasted, at least two 226 * calls to rcu_check_quiescent_state are required: 227 * The first call just notices that a new grace period is running. The 228 * following calls check if there was a quiescent state since the beginning 229 + * of the grace period. If so, it updates rcu_ctrlblk.cpumask. If 230 * the bitmap is empty, then the grace period is completed. 231 * rcu_check_quiescent_state calls rcu_start_batch(0) to start the next grace 232 * period (if necessary). ··· 234 /* 235 * Register a new batch of callbacks, and start it up if there is currently no 236 * active batch and the batch to be registered has not already occurred. 237 + * Caller must hold rcu_ctrlblk.lock. 238 */ 239 + static void rcu_start_batch(struct rcu_ctrlblk *rcp) 240 { 241 if (rcp->next_pending && 242 rcp->completed == rcp->cur) { ··· 251 /* 252 * Accessing nohz_cpu_mask before incrementing rcp->cur needs a 253 * Barrier Otherwise it can cause tickless idle CPUs to be 254 + * included in rcp->cpumask, which will extend graceperiods 255 * unnecessarily. 256 */ 257 smp_mb(); 258 + cpus_andnot(rcp->cpumask, cpu_online_map, nohz_cpu_mask); 259 260 } 261 } ··· 265 * Clear it from the cpu mask and complete the grace period if it was the last 266 * cpu. Start another grace period if someone has further entries pending 267 */ 268 + static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp) 269 { 270 + cpu_clear(cpu, rcp->cpumask); 271 + if (cpus_empty(rcp->cpumask)) { 272 /* batch completed ! */ 273 rcp->completed = rcp->cur; 274 + rcu_start_batch(rcp); 275 } 276 } 277 ··· 281 * quiescent cycle, then indicate that it has done so. 282 */ 283 static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, 284 + struct rcu_data *rdp) 285 { 286 if (rdp->quiescbatch != rcp->cur) { 287 /* start new grace period: */ ··· 306 return; 307 rdp->qs_pending = 0; 308 309 + spin_lock(&rcp->lock); 310 /* 311 * rdp->quiescbatch/rcp->cur and the cpu bitmap can come out of sync 312 * during cpu startup. Ignore the quiescent state. 313 */ 314 if (likely(rdp->quiescbatch == rcp->cur)) 315 + cpu_quiet(rdp->cpu, rcp); 316 317 + spin_unlock(&rcp->lock); 318 } 319 320 ··· 335 } 336 337 static void __rcu_offline_cpu(struct rcu_data *this_rdp, 338 + struct rcu_ctrlblk *rcp, struct rcu_data *rdp) 339 { 340 /* if the cpu going offline owns the grace period 341 * we can block indefinitely waiting for it, so flush 342 * it here 343 */ 344 + spin_lock_bh(&rcp->lock); 345 if (rcp->cur != rcp->completed) 346 + cpu_quiet(rdp->cpu, rcp); 347 + spin_unlock_bh(&rcp->lock); 348 rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail); 349 rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail); 350 ··· 354 struct rcu_data *this_rdp = &get_cpu_var(rcu_data); 355 struct rcu_data *this_bh_rdp = &get_cpu_var(rcu_bh_data); 356 357 + __rcu_offline_cpu(this_rdp, &rcu_ctrlblk, 358 &per_cpu(rcu_data, cpu)); 359 + __rcu_offline_cpu(this_bh_rdp, &rcu_bh_ctrlblk, 360 &per_cpu(rcu_bh_data, cpu)); 361 put_cpu_var(rcu_data); 362 put_cpu_var(rcu_bh_data); ··· 375 * This does the RCU processing work from tasklet context. 376 */ 377 static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, 378 + struct rcu_data *rdp) 379 { 380 if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) { 381 *rdp->donetail = rdp->curlist; ··· 405 406 if (!rcp->next_pending) { 407 /* and start it/schedule start if it's a new batch */ 408 + spin_lock(&rcp->lock); 409 rcp->next_pending = 1; 410 + rcu_start_batch(rcp); 411 + spin_unlock(&rcp->lock); 412 } 413 } else { 414 local_irq_enable(); 415 } 416 + rcu_check_quiescent_state(rcp, rdp); 417 if (rdp->donelist) 418 rcu_do_batch(rdp); 419 } 420 421 static void rcu_process_callbacks(unsigned long unused) 422 { 423 + __rcu_process_callbacks(&rcu_ctrlblk, &__get_cpu_var(rcu_data)); 424 + __rcu_process_callbacks(&rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data)); 425 } 426 427 static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp)