diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2010-01-04 18:09:00 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-01-13 03:06:01 -0500 |
commit | f96e9232e04856c781d4f71923a46dd3f7b429fa (patch) | |
tree | 3c320a0a2bc03f54fea5c115b6c0fa1e4bcc7e27 /kernel/rcutree.c | |
parent | 7284ce6c9f6153d1777df5f310c959724d1bd446 (diff) |
rcu: Adjust force_quiescent_state() locking, step 1
This causes rnp->lock to be held on entry to
force_quiescent_state()'s switch statement. This is a first
step towards prohibiting starting grace periods while
force_quiescent_state() is executing, which will reduce the
number and complexity of races that force_quiescent_state() is
involved in.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: laijs@cn.fujitsu.com
Cc: dipankar@in.ibm.com
Cc: mathieu.desnoyers@polymtl.ca
Cc: josh@joshtriplett.org
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: peterz@infradead.org
Cc: rostedt@goodmis.org
Cc: Valdis.Kletnieks@vt.edu
Cc: dhowells@redhat.com
LKML-Reference: <12626465501455-git-send-email->
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r-- | kernel/rcutree.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 53ae9598f798..eae331da6bee 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -1204,7 +1204,7 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1204 | } | 1204 | } |
1205 | if (relaxed && | 1205 | if (relaxed && |
1206 | (long)(rsp->jiffies_force_qs - jiffies) >= 0) | 1206 | (long)(rsp->jiffies_force_qs - jiffies) >= 0) |
1207 | goto unlock_ret; /* no emergency and done recently. */ | 1207 | goto unlock_fqs_ret; /* no emergency and done recently. */ |
1208 | rsp->n_force_qs++; | 1208 | rsp->n_force_qs++; |
1209 | spin_lock(&rnp->lock); | 1209 | spin_lock(&rnp->lock); |
1210 | lastcomp = rsp->gpnum - 1; | 1210 | lastcomp = rsp->gpnum - 1; |
@@ -1213,31 +1213,32 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1213 | if(!rcu_gp_in_progress(rsp)) { | 1213 | if(!rcu_gp_in_progress(rsp)) { |
1214 | rsp->n_force_qs_ngp++; | 1214 | rsp->n_force_qs_ngp++; |
1215 | spin_unlock(&rnp->lock); | 1215 | spin_unlock(&rnp->lock); |
1216 | goto unlock_ret; /* no GP in progress, time updated. */ | 1216 | goto unlock_fqs_ret; /* no GP in progress, time updated. */ |
1217 | } | 1217 | } |
1218 | spin_unlock(&rnp->lock); | ||
1219 | switch (signaled) { | 1218 | switch (signaled) { |
1220 | case RCU_GP_IDLE: | 1219 | case RCU_GP_IDLE: |
1221 | case RCU_GP_INIT: | 1220 | case RCU_GP_INIT: |
1222 | 1221 | ||
1222 | spin_unlock(&rnp->lock); | ||
1223 | break; /* grace period idle or initializing, ignore. */ | 1223 | break; /* grace period idle or initializing, ignore. */ |
1224 | 1224 | ||
1225 | case RCU_SAVE_DYNTICK: | 1225 | case RCU_SAVE_DYNTICK: |
1226 | 1226 | ||
1227 | spin_unlock(&rnp->lock); | ||
1227 | if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK) | 1228 | if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK) |
1228 | break; /* So gcc recognizes the dead code. */ | 1229 | break; /* So gcc recognizes the dead code. */ |
1229 | 1230 | ||
1230 | /* Record dyntick-idle state. */ | 1231 | /* Record dyntick-idle state. */ |
1231 | if (rcu_process_dyntick(rsp, lastcomp, | 1232 | if (rcu_process_dyntick(rsp, lastcomp, |
1232 | dyntick_save_progress_counter)) | 1233 | dyntick_save_progress_counter)) |
1233 | goto unlock_ret; | 1234 | goto unlock_fqs_ret; |
1235 | spin_lock(&rnp->lock); | ||
1234 | /* fall into next case. */ | 1236 | /* fall into next case. */ |
1235 | 1237 | ||
1236 | case RCU_SAVE_COMPLETED: | 1238 | case RCU_SAVE_COMPLETED: |
1237 | 1239 | ||
1238 | /* Update state, record completion counter. */ | 1240 | /* Update state, record completion counter. */ |
1239 | forcenow = 0; | 1241 | forcenow = 0; |
1240 | spin_lock(&rnp->lock); | ||
1241 | if (lastcomp + 1 == rsp->gpnum && | 1242 | if (lastcomp + 1 == rsp->gpnum && |
1242 | lastcomp == rsp->completed && | 1243 | lastcomp == rsp->completed && |
1243 | rsp->signaled == signaled) { | 1244 | rsp->signaled == signaled) { |
@@ -1245,23 +1246,31 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1245 | rsp->completed_fqs = lastcomp; | 1246 | rsp->completed_fqs = lastcomp; |
1246 | forcenow = signaled == RCU_SAVE_COMPLETED; | 1247 | forcenow = signaled == RCU_SAVE_COMPLETED; |
1247 | } | 1248 | } |
1248 | spin_unlock(&rnp->lock); | 1249 | if (!forcenow) { |
1249 | if (!forcenow) | 1250 | spin_unlock(&rnp->lock); |
1250 | break; | 1251 | break; |
1252 | } | ||
1251 | /* fall into next case. */ | 1253 | /* fall into next case. */ |
1252 | 1254 | ||
1253 | case RCU_FORCE_QS: | 1255 | case RCU_FORCE_QS: |
1254 | 1256 | ||
1255 | /* Check dyntick-idle state, send IPI to laggarts. */ | 1257 | /* Check dyntick-idle state, send IPI to laggarts. */ |
1258 | spin_unlock(&rnp->lock); | ||
1256 | if (rcu_process_dyntick(rsp, rsp->completed_fqs, | 1259 | if (rcu_process_dyntick(rsp, rsp->completed_fqs, |
1257 | rcu_implicit_dynticks_qs)) | 1260 | rcu_implicit_dynticks_qs)) |
1258 | goto unlock_ret; | 1261 | goto unlock_fqs_ret; |
1259 | 1262 | ||
1260 | /* Leave state in case more forcing is required. */ | 1263 | /* Leave state in case more forcing is required. */ |
1261 | 1264 | ||
1262 | break; | 1265 | break; |
1266 | |||
1267 | default: | ||
1268 | |||
1269 | spin_unlock(&rnp->lock); | ||
1270 | WARN_ON_ONCE(1); | ||
1271 | break; | ||
1263 | } | 1272 | } |
1264 | unlock_ret: | 1273 | unlock_fqs_ret: |
1265 | spin_unlock_irqrestore(&rsp->fqslock, flags); | 1274 | spin_unlock_irqrestore(&rsp->fqslock, flags); |
1266 | } | 1275 | } |
1267 | 1276 | ||