diff options
author | Paul E. McKenney <paul.mckenney@linaro.org> | 2012-12-30 18:21:01 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2013-03-26 11:04:57 -0400 |
commit | 0446be489795d8bb994125a916ef03211f539e54 (patch) | |
tree | 051b6bce04ab8f9e8b7ea6f42879bb350e306805 /kernel/rcutree_plugin.h | |
parent | 8b425aa8f1acfe48aed919c7aadff2ed290fe969 (diff) |
rcu: Abstract rcu_start_future_gp() from rcu_nocb_wait_gp()
CPUs going idle will need to record the need for a future grace
period, but won't actually need to block waiting on it. This commit
therefore splits rcu_start_future_gp(), which does the recording, from
rcu_nocb_wait_gp(), which now invokes rcu_start_future_gp() to do the
recording, after which rcu_nocb_wait_gp() does the waiting.
Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcutree_plugin.h')
-rw-r--r-- | kernel/rcutree_plugin.h | 104 |
1 files changed, 10 insertions, 94 deletions
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index f3f0020b5b58..723af5f707f0 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h | |||
@@ -2022,22 +2022,12 @@ static int rcu_nocb_needs_gp(struct rcu_state *rsp) | |||
2022 | } | 2022 | } |
2023 | 2023 | ||
2024 | /* | 2024 | /* |
2025 | * Clean up this rcu_node structure's no-CBs state at the end of | 2025 | * Wake up any no-CBs CPUs' kthreads that were waiting on the just-ended |
2026 | * a grace period, and also return whether any no-CBs CPU associated | 2026 | * grace period. |
2027 | * with this rcu_node structure needs another grace period. | ||
2028 | */ | 2027 | */ |
2029 | static int rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) | 2028 | static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) |
2030 | { | 2029 | { |
2031 | int c = rnp->completed; | 2030 | wake_up_all(&rnp->nocb_gp_wq[rnp->completed & 0x1]); |
2032 | int needmore; | ||
2033 | |||
2034 | wake_up_all(&rnp->nocb_gp_wq[c & 0x1]); | ||
2035 | rnp->need_future_gp[c & 0x1] = 0; | ||
2036 | needmore = rnp->need_future_gp[(c + 1) & 0x1]; | ||
2037 | trace_rcu_future_grace_period(rsp->name, rnp->gpnum, rnp->completed, | ||
2038 | c, rnp->level, rnp->grplo, rnp->grphi, | ||
2039 | needmore ? "CleanupMore" : "Cleanup"); | ||
2040 | return needmore; | ||
2041 | } | 2031 | } |
2042 | 2032 | ||
2043 | /* | 2033 | /* |
@@ -2175,84 +2165,16 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) | |||
2175 | bool d; | 2165 | bool d; |
2176 | unsigned long flags; | 2166 | unsigned long flags; |
2177 | struct rcu_node *rnp = rdp->mynode; | 2167 | struct rcu_node *rnp = rdp->mynode; |
2178 | struct rcu_node *rnp_root = rcu_get_root(rdp->rsp); | ||
2179 | 2168 | ||
2180 | raw_spin_lock_irqsave(&rnp->lock, flags); | 2169 | raw_spin_lock_irqsave(&rnp->lock, flags); |
2181 | c = rnp->completed + 2; | 2170 | c = rcu_start_future_gp(rnp, rdp); |
2182 | 2171 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | |
2183 | /* Count our request for a grace period. */ | ||
2184 | rnp->need_future_gp[c & 0x1]++; | ||
2185 | trace_rcu_future_grace_period(rdp->rsp->name, rnp->gpnum, | ||
2186 | rnp->completed, c, rnp->level, | ||
2187 | rnp->grplo, rnp->grphi, "Startleaf"); | ||
2188 | |||
2189 | if (rnp->gpnum != rnp->completed) { | ||
2190 | |||
2191 | /* | ||
2192 | * This rcu_node structure believes that a grace period | ||
2193 | * is in progress, so we are done. When this grace | ||
2194 | * period ends, our request will be acted upon. | ||
2195 | */ | ||
2196 | trace_rcu_future_grace_period(rdp->rsp->name, rnp->gpnum, | ||
2197 | rnp->completed, c, rnp->level, | ||
2198 | rnp->grplo, rnp->grphi, | ||
2199 | "Startedleaf"); | ||
2200 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | ||
2201 | |||
2202 | } else { | ||
2203 | |||
2204 | /* | ||
2205 | * Might not be a grace period, check root rcu_node | ||
2206 | * structure to see if we must start one. | ||
2207 | */ | ||
2208 | if (rnp != rnp_root) | ||
2209 | raw_spin_lock(&rnp_root->lock); /* irqs disabled. */ | ||
2210 | if (rnp_root->gpnum != rnp_root->completed) { | ||
2211 | trace_rcu_future_grace_period(rdp->rsp->name, | ||
2212 | rnp->gpnum, | ||
2213 | rnp->completed, | ||
2214 | c, rnp->level, | ||
2215 | rnp->grplo, rnp->grphi, | ||
2216 | "Startedleafroot"); | ||
2217 | raw_spin_unlock(&rnp_root->lock); /* irqs disabled. */ | ||
2218 | } else { | ||
2219 | |||
2220 | /* | ||
2221 | * No grace period, so we need to start one. | ||
2222 | * The good news is that we can wait for exactly | ||
2223 | * one grace period instead of part of the current | ||
2224 | * grace period and all of the next grace period. | ||
2225 | * Adjust counters accordingly and start the | ||
2226 | * needed grace period. | ||
2227 | */ | ||
2228 | rnp->need_future_gp[c & 0x1]--; | ||
2229 | c = rnp_root->completed + 1; | ||
2230 | rnp->need_future_gp[c & 0x1]++; | ||
2231 | rnp_root->need_future_gp[c & 0x1]++; | ||
2232 | trace_rcu_future_grace_period(rdp->rsp->name, | ||
2233 | rnp->gpnum, | ||
2234 | rnp->completed, | ||
2235 | c, rnp->level, | ||
2236 | rnp->grplo, rnp->grphi, | ||
2237 | "Startedroot"); | ||
2238 | rcu_start_gp(rdp->rsp); | ||
2239 | raw_spin_unlock(&rnp->lock); | ||
2240 | } | ||
2241 | |||
2242 | /* Clean up locking and irq state. */ | ||
2243 | if (rnp != rnp_root) | ||
2244 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | ||
2245 | else | ||
2246 | local_irq_restore(flags); | ||
2247 | } | ||
2248 | 2172 | ||
2249 | /* | 2173 | /* |
2250 | * Wait for the grace period. Do so interruptibly to avoid messing | 2174 | * Wait for the grace period. Do so interruptibly to avoid messing |
2251 | * up the load average. | 2175 | * up the load average. |
2252 | */ | 2176 | */ |
2253 | trace_rcu_future_grace_period(rdp->rsp->name, rnp->gpnum, | 2177 | trace_rcu_future_gp(rnp, rdp, c, "StartWait"); |
2254 | rnp->completed, c, rnp->level, | ||
2255 | rnp->grplo, rnp->grphi, "StartWait"); | ||
2256 | for (;;) { | 2178 | for (;;) { |
2257 | wait_event_interruptible( | 2179 | wait_event_interruptible( |
2258 | rnp->nocb_gp_wq[c & 0x1], | 2180 | rnp->nocb_gp_wq[c & 0x1], |
@@ -2260,14 +2182,9 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) | |||
2260 | if (likely(d)) | 2182 | if (likely(d)) |
2261 | break; | 2183 | break; |
2262 | flush_signals(current); | 2184 | flush_signals(current); |
2263 | trace_rcu_future_grace_period(rdp->rsp->name, | 2185 | trace_rcu_future_gp(rnp, rdp, c, "ResumeWait"); |
2264 | rnp->gpnum, rnp->completed, c, | ||
2265 | rnp->level, rnp->grplo, | ||
2266 | rnp->grphi, "ResumeWait"); | ||
2267 | } | 2186 | } |
2268 | trace_rcu_future_grace_period(rdp->rsp->name, rnp->gpnum, | 2187 | trace_rcu_future_gp(rnp, rdp, c, "EndWait"); |
2269 | rnp->completed, c, rnp->level, | ||
2270 | rnp->grplo, rnp->grphi, "EndWait"); | ||
2271 | smp_mb(); /* Ensure that CB invocation happens after GP end. */ | 2188 | smp_mb(); /* Ensure that CB invocation happens after GP end. */ |
2272 | } | 2189 | } |
2273 | 2190 | ||
@@ -2375,9 +2292,8 @@ static int rcu_nocb_needs_gp(struct rcu_state *rsp) | |||
2375 | return 0; | 2292 | return 0; |
2376 | } | 2293 | } |
2377 | 2294 | ||
2378 | static int rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) | 2295 | static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) |
2379 | { | 2296 | { |
2380 | return 0; | ||
2381 | } | 2297 | } |
2382 | 2298 | ||
2383 | static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq) | 2299 | static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq) |