diff options
Diffstat (limited to 'kernel/rcu/tree_plugin.h')
-rw-r--r-- | kernel/rcu/tree_plugin.h | 302 |
1 files changed, 243 insertions, 59 deletions
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 02ac0fb186b8..00dc411e9676 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define RCU_KTHREAD_PRIO 1 | 33 | #define RCU_KTHREAD_PRIO 1 |
34 | 34 | ||
35 | #ifdef CONFIG_RCU_BOOST | 35 | #ifdef CONFIG_RCU_BOOST |
36 | #include "../locking/rtmutex_common.h" | ||
36 | #define RCU_BOOST_PRIO CONFIG_RCU_BOOST_PRIO | 37 | #define RCU_BOOST_PRIO CONFIG_RCU_BOOST_PRIO |
37 | #else | 38 | #else |
38 | #define RCU_BOOST_PRIO RCU_KTHREAD_PRIO | 39 | #define RCU_BOOST_PRIO RCU_KTHREAD_PRIO |
@@ -336,7 +337,7 @@ void rcu_read_unlock_special(struct task_struct *t) | |||
336 | unsigned long flags; | 337 | unsigned long flags; |
337 | struct list_head *np; | 338 | struct list_head *np; |
338 | #ifdef CONFIG_RCU_BOOST | 339 | #ifdef CONFIG_RCU_BOOST |
339 | struct rt_mutex *rbmp = NULL; | 340 | bool drop_boost_mutex = false; |
340 | #endif /* #ifdef CONFIG_RCU_BOOST */ | 341 | #endif /* #ifdef CONFIG_RCU_BOOST */ |
341 | struct rcu_node *rnp; | 342 | struct rcu_node *rnp; |
342 | int special; | 343 | int special; |
@@ -398,11 +399,8 @@ void rcu_read_unlock_special(struct task_struct *t) | |||
398 | #ifdef CONFIG_RCU_BOOST | 399 | #ifdef CONFIG_RCU_BOOST |
399 | if (&t->rcu_node_entry == rnp->boost_tasks) | 400 | if (&t->rcu_node_entry == rnp->boost_tasks) |
400 | rnp->boost_tasks = np; | 401 | rnp->boost_tasks = np; |
401 | /* Snapshot/clear ->rcu_boost_mutex with rcu_node lock held. */ | 402 | /* Snapshot ->boost_mtx ownership with rcu_node lock held. */ |
402 | if (t->rcu_boost_mutex) { | 403 | drop_boost_mutex = rt_mutex_owner(&rnp->boost_mtx) == t; |
403 | rbmp = t->rcu_boost_mutex; | ||
404 | t->rcu_boost_mutex = NULL; | ||
405 | } | ||
406 | #endif /* #ifdef CONFIG_RCU_BOOST */ | 404 | #endif /* #ifdef CONFIG_RCU_BOOST */ |
407 | 405 | ||
408 | /* | 406 | /* |
@@ -427,8 +425,10 @@ void rcu_read_unlock_special(struct task_struct *t) | |||
427 | 425 | ||
428 | #ifdef CONFIG_RCU_BOOST | 426 | #ifdef CONFIG_RCU_BOOST |
429 | /* Unboost if we were boosted. */ | 427 | /* Unboost if we were boosted. */ |
430 | if (rbmp) | 428 | if (drop_boost_mutex) { |
431 | rt_mutex_unlock(rbmp); | 429 | rt_mutex_unlock(&rnp->boost_mtx); |
430 | complete(&rnp->boost_completion); | ||
431 | } | ||
432 | #endif /* #ifdef CONFIG_RCU_BOOST */ | 432 | #endif /* #ifdef CONFIG_RCU_BOOST */ |
433 | 433 | ||
434 | /* | 434 | /* |
@@ -988,6 +988,7 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp) | |||
988 | 988 | ||
989 | /* Because preemptible RCU does not exist, no quieting of tasks. */ | 989 | /* Because preemptible RCU does not exist, no quieting of tasks. */ |
990 | static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) | 990 | static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) |
991 | __releases(rnp->lock) | ||
991 | { | 992 | { |
992 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 993 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
993 | } | 994 | } |
@@ -1149,7 +1150,6 @@ static void rcu_wake_cond(struct task_struct *t, int status) | |||
1149 | static int rcu_boost(struct rcu_node *rnp) | 1150 | static int rcu_boost(struct rcu_node *rnp) |
1150 | { | 1151 | { |
1151 | unsigned long flags; | 1152 | unsigned long flags; |
1152 | struct rt_mutex mtx; | ||
1153 | struct task_struct *t; | 1153 | struct task_struct *t; |
1154 | struct list_head *tb; | 1154 | struct list_head *tb; |
1155 | 1155 | ||
@@ -1200,11 +1200,15 @@ static int rcu_boost(struct rcu_node *rnp) | |||
1200 | * section. | 1200 | * section. |
1201 | */ | 1201 | */ |
1202 | t = container_of(tb, struct task_struct, rcu_node_entry); | 1202 | t = container_of(tb, struct task_struct, rcu_node_entry); |
1203 | rt_mutex_init_proxy_locked(&mtx, t); | 1203 | rt_mutex_init_proxy_locked(&rnp->boost_mtx, t); |
1204 | t->rcu_boost_mutex = &mtx; | 1204 | init_completion(&rnp->boost_completion); |
1205 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 1205 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
1206 | rt_mutex_lock(&mtx); /* Side effect: boosts task t's priority. */ | 1206 | /* Lock only for side effect: boosts task t's priority. */ |
1207 | rt_mutex_unlock(&mtx); /* Keep lockdep happy. */ | 1207 | rt_mutex_lock(&rnp->boost_mtx); |
1208 | rt_mutex_unlock(&rnp->boost_mtx); /* Then keep lockdep happy. */ | ||
1209 | |||
1210 | /* Wait for boostee to be done w/boost_mtx before reinitializing. */ | ||
1211 | wait_for_completion(&rnp->boost_completion); | ||
1208 | 1212 | ||
1209 | return ACCESS_ONCE(rnp->exp_tasks) != NULL || | 1213 | return ACCESS_ONCE(rnp->exp_tasks) != NULL || |
1210 | ACCESS_ONCE(rnp->boost_tasks) != NULL; | 1214 | ACCESS_ONCE(rnp->boost_tasks) != NULL; |
@@ -1256,6 +1260,7 @@ static int rcu_boost_kthread(void *arg) | |||
1256 | * about it going away. | 1260 | * about it going away. |
1257 | */ | 1261 | */ |
1258 | static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) | 1262 | static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) |
1263 | __releases(rnp->lock) | ||
1259 | { | 1264 | { |
1260 | struct task_struct *t; | 1265 | struct task_struct *t; |
1261 | 1266 | ||
@@ -1491,6 +1496,7 @@ static void rcu_prepare_kthreads(int cpu) | |||
1491 | #else /* #ifdef CONFIG_RCU_BOOST */ | 1496 | #else /* #ifdef CONFIG_RCU_BOOST */ |
1492 | 1497 | ||
1493 | static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) | 1498 | static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) |
1499 | __releases(rnp->lock) | ||
1494 | { | 1500 | { |
1495 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 1501 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
1496 | } | 1502 | } |
@@ -2060,6 +2066,22 @@ bool rcu_is_nocb_cpu(int cpu) | |||
2060 | #endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */ | 2066 | #endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */ |
2061 | 2067 | ||
2062 | /* | 2068 | /* |
2069 | * Kick the leader kthread for this NOCB group. | ||
2070 | */ | ||
2071 | static void wake_nocb_leader(struct rcu_data *rdp, bool force) | ||
2072 | { | ||
2073 | struct rcu_data *rdp_leader = rdp->nocb_leader; | ||
2074 | |||
2075 | if (!ACCESS_ONCE(rdp_leader->nocb_kthread)) | ||
2076 | return; | ||
2077 | if (!ACCESS_ONCE(rdp_leader->nocb_leader_wake) || force) { | ||
2078 | /* Prior xchg orders against prior callback enqueue. */ | ||
2079 | ACCESS_ONCE(rdp_leader->nocb_leader_wake) = true; | ||
2080 | wake_up(&rdp_leader->nocb_wq); | ||
2081 | } | ||
2082 | } | ||
2083 | |||
2084 | /* | ||
2063 | * Enqueue the specified string of rcu_head structures onto the specified | 2085 | * Enqueue the specified string of rcu_head structures onto the specified |
2064 | * CPU's no-CBs lists. The CPU is specified by rdp, the head of the | 2086 | * CPU's no-CBs lists. The CPU is specified by rdp, the head of the |
2065 | * string by rhp, and the tail of the string by rhtp. The non-lazy/lazy | 2087 | * string by rhp, and the tail of the string by rhtp. The non-lazy/lazy |
@@ -2093,7 +2115,8 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | |||
2093 | len = atomic_long_read(&rdp->nocb_q_count); | 2115 | len = atomic_long_read(&rdp->nocb_q_count); |
2094 | if (old_rhpp == &rdp->nocb_head) { | 2116 | if (old_rhpp == &rdp->nocb_head) { |
2095 | if (!irqs_disabled_flags(flags)) { | 2117 | if (!irqs_disabled_flags(flags)) { |
2096 | wake_up(&rdp->nocb_wq); /* ... if queue was empty ... */ | 2118 | /* ... if queue was empty ... */ |
2119 | wake_nocb_leader(rdp, false); | ||
2097 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | 2120 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, |
2098 | TPS("WakeEmpty")); | 2121 | TPS("WakeEmpty")); |
2099 | } else { | 2122 | } else { |
@@ -2103,7 +2126,8 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | |||
2103 | } | 2126 | } |
2104 | rdp->qlen_last_fqs_check = 0; | 2127 | rdp->qlen_last_fqs_check = 0; |
2105 | } else if (len > rdp->qlen_last_fqs_check + qhimark) { | 2128 | } else if (len > rdp->qlen_last_fqs_check + qhimark) { |
2106 | wake_up_process(t); /* ... or if many callbacks queued. */ | 2129 | /* ... or if many callbacks queued. */ |
2130 | wake_nocb_leader(rdp, true); | ||
2107 | rdp->qlen_last_fqs_check = LONG_MAX / 2; | 2131 | rdp->qlen_last_fqs_check = LONG_MAX / 2; |
2108 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeOvf")); | 2132 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeOvf")); |
2109 | } else { | 2133 | } else { |
@@ -2213,13 +2237,150 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) | |||
2213 | } | 2237 | } |
2214 | 2238 | ||
2215 | /* | 2239 | /* |
2240 | * Leaders come here to wait for additional callbacks to show up. | ||
2241 | * This function does not return until callbacks appear. | ||
2242 | */ | ||
2243 | static void nocb_leader_wait(struct rcu_data *my_rdp) | ||
2244 | { | ||
2245 | bool firsttime = true; | ||
2246 | bool gotcbs; | ||
2247 | struct rcu_data *rdp; | ||
2248 | struct rcu_head **tail; | ||
2249 | |||
2250 | wait_again: | ||
2251 | |||
2252 | /* Wait for callbacks to appear. */ | ||
2253 | if (!rcu_nocb_poll) { | ||
2254 | trace_rcu_nocb_wake(my_rdp->rsp->name, my_rdp->cpu, "Sleep"); | ||
2255 | wait_event_interruptible(my_rdp->nocb_wq, | ||
2256 | ACCESS_ONCE(my_rdp->nocb_leader_wake)); | ||
2257 | /* Memory barrier handled by smp_mb() calls below and repoll. */ | ||
2258 | } else if (firsttime) { | ||
2259 | firsttime = false; /* Don't drown trace log with "Poll"! */ | ||
2260 | trace_rcu_nocb_wake(my_rdp->rsp->name, my_rdp->cpu, "Poll"); | ||
2261 | } | ||
2262 | |||
2263 | /* | ||
2264 | * Each pass through the following loop checks a follower for CBs. | ||
2265 | * We are our own first follower. Any CBs found are moved to | ||
2266 | * nocb_gp_head, where they await a grace period. | ||
2267 | */ | ||
2268 | gotcbs = false; | ||
2269 | for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower) { | ||
2270 | rdp->nocb_gp_head = ACCESS_ONCE(rdp->nocb_head); | ||
2271 | if (!rdp->nocb_gp_head) | ||
2272 | continue; /* No CBs here, try next follower. */ | ||
2273 | |||
2274 | /* Move callbacks to wait-for-GP list, which is empty. */ | ||
2275 | ACCESS_ONCE(rdp->nocb_head) = NULL; | ||
2276 | rdp->nocb_gp_tail = xchg(&rdp->nocb_tail, &rdp->nocb_head); | ||
2277 | rdp->nocb_gp_count = atomic_long_xchg(&rdp->nocb_q_count, 0); | ||
2278 | rdp->nocb_gp_count_lazy = | ||
2279 | atomic_long_xchg(&rdp->nocb_q_count_lazy, 0); | ||
2280 | gotcbs = true; | ||
2281 | } | ||
2282 | |||
2283 | /* | ||
2284 | * If there were no callbacks, sleep a bit, rescan after a | ||
2285 | * memory barrier, and go retry. | ||
2286 | */ | ||
2287 | if (unlikely(!gotcbs)) { | ||
2288 | if (!rcu_nocb_poll) | ||
2289 | trace_rcu_nocb_wake(my_rdp->rsp->name, my_rdp->cpu, | ||
2290 | "WokeEmpty"); | ||
2291 | flush_signals(current); | ||
2292 | schedule_timeout_interruptible(1); | ||
2293 | |||
2294 | /* Rescan in case we were a victim of memory ordering. */ | ||
2295 | my_rdp->nocb_leader_wake = false; | ||
2296 | smp_mb(); /* Ensure _wake false before scan. */ | ||
2297 | for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower) | ||
2298 | if (ACCESS_ONCE(rdp->nocb_head)) { | ||
2299 | /* Found CB, so short-circuit next wait. */ | ||
2300 | my_rdp->nocb_leader_wake = true; | ||
2301 | break; | ||
2302 | } | ||
2303 | goto wait_again; | ||
2304 | } | ||
2305 | |||
2306 | /* Wait for one grace period. */ | ||
2307 | rcu_nocb_wait_gp(my_rdp); | ||
2308 | |||
2309 | /* | ||
2310 | * We left ->nocb_leader_wake set to reduce cache thrashing. | ||
2311 | * We clear it now, but recheck for new callbacks while | ||
2312 | * traversing our follower list. | ||
2313 | */ | ||
2314 | my_rdp->nocb_leader_wake = false; | ||
2315 | smp_mb(); /* Ensure _wake false before scan of ->nocb_head. */ | ||
2316 | |||
2317 | /* Each pass through the following loop wakes a follower, if needed. */ | ||
2318 | for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower) { | ||
2319 | if (ACCESS_ONCE(rdp->nocb_head)) | ||
2320 | my_rdp->nocb_leader_wake = true; /* No need to wait. */ | ||
2321 | if (!rdp->nocb_gp_head) | ||
2322 | continue; /* No CBs, so no need to wake follower. */ | ||
2323 | |||
2324 | /* Append callbacks to follower's "done" list. */ | ||
2325 | tail = xchg(&rdp->nocb_follower_tail, rdp->nocb_gp_tail); | ||
2326 | *tail = rdp->nocb_gp_head; | ||
2327 | atomic_long_add(rdp->nocb_gp_count, &rdp->nocb_follower_count); | ||
2328 | atomic_long_add(rdp->nocb_gp_count_lazy, | ||
2329 | &rdp->nocb_follower_count_lazy); | ||
2330 | if (rdp != my_rdp && tail == &rdp->nocb_follower_head) { | ||
2331 | /* | ||
2332 | * List was empty, wake up the follower. | ||
2333 | * Memory barriers supplied by atomic_long_add(). | ||
2334 | */ | ||
2335 | wake_up(&rdp->nocb_wq); | ||
2336 | } | ||
2337 | } | ||
2338 | |||
2339 | /* If we (the leader) don't have CBs, go wait some more. */ | ||
2340 | if (!my_rdp->nocb_follower_head) | ||
2341 | goto wait_again; | ||
2342 | } | ||
2343 | |||
2344 | /* | ||
2345 | * Followers come here to wait for additional callbacks to show up. | ||
2346 | * This function does not return until callbacks appear. | ||
2347 | */ | ||
2348 | static void nocb_follower_wait(struct rcu_data *rdp) | ||
2349 | { | ||
2350 | bool firsttime = true; | ||
2351 | |||
2352 | for (;;) { | ||
2353 | if (!rcu_nocb_poll) { | ||
2354 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2355 | "FollowerSleep"); | ||
2356 | wait_event_interruptible(rdp->nocb_wq, | ||
2357 | ACCESS_ONCE(rdp->nocb_follower_head)); | ||
2358 | } else if (firsttime) { | ||
2359 | /* Don't drown trace log with "Poll"! */ | ||
2360 | firsttime = false; | ||
2361 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, "Poll"); | ||
2362 | } | ||
2363 | if (smp_load_acquire(&rdp->nocb_follower_head)) { | ||
2364 | /* ^^^ Ensure CB invocation follows _head test. */ | ||
2365 | return; | ||
2366 | } | ||
2367 | if (!rcu_nocb_poll) | ||
2368 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2369 | "WokeEmpty"); | ||
2370 | flush_signals(current); | ||
2371 | schedule_timeout_interruptible(1); | ||
2372 | } | ||
2373 | } | ||
2374 | |||
2375 | /* | ||
2216 | * Per-rcu_data kthread, but only for no-CBs CPUs. Each kthread invokes | 2376 | * Per-rcu_data kthread, but only for no-CBs CPUs. Each kthread invokes |
2217 | * callbacks queued by the corresponding no-CBs CPU. | 2377 | * callbacks queued by the corresponding no-CBs CPU, however, there is |
2378 | * an optional leader-follower relationship so that the grace-period | ||
2379 | * kthreads don't have to do quite so many wakeups. | ||
2218 | */ | 2380 | */ |
2219 | static int rcu_nocb_kthread(void *arg) | 2381 | static int rcu_nocb_kthread(void *arg) |
2220 | { | 2382 | { |
2221 | int c, cl; | 2383 | int c, cl; |
2222 | bool firsttime = 1; | ||
2223 | struct rcu_head *list; | 2384 | struct rcu_head *list; |
2224 | struct rcu_head *next; | 2385 | struct rcu_head *next; |
2225 | struct rcu_head **tail; | 2386 | struct rcu_head **tail; |
@@ -2227,41 +2388,22 @@ static int rcu_nocb_kthread(void *arg) | |||
2227 | 2388 | ||
2228 | /* Each pass through this loop invokes one batch of callbacks */ | 2389 | /* Each pass through this loop invokes one batch of callbacks */ |
2229 | for (;;) { | 2390 | for (;;) { |
2230 | /* If not polling, wait for next batch of callbacks. */ | 2391 | /* Wait for callbacks. */ |
2231 | if (!rcu_nocb_poll) { | 2392 | if (rdp->nocb_leader == rdp) |
2232 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | 2393 | nocb_leader_wait(rdp); |
2233 | TPS("Sleep")); | 2394 | else |
2234 | wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); | 2395 | nocb_follower_wait(rdp); |
2235 | /* Memory barrier provide by xchg() below. */ | 2396 | |
2236 | } else if (firsttime) { | 2397 | /* Pull the ready-to-invoke callbacks onto local list. */ |
2237 | firsttime = 0; | 2398 | list = ACCESS_ONCE(rdp->nocb_follower_head); |
2238 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | 2399 | BUG_ON(!list); |
2239 | TPS("Poll")); | 2400 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, "WokeNonEmpty"); |
2240 | } | 2401 | ACCESS_ONCE(rdp->nocb_follower_head) = NULL; |
2241 | list = ACCESS_ONCE(rdp->nocb_head); | 2402 | tail = xchg(&rdp->nocb_follower_tail, &rdp->nocb_follower_head); |
2242 | if (!list) { | 2403 | c = atomic_long_xchg(&rdp->nocb_follower_count, 0); |
2243 | if (!rcu_nocb_poll) | 2404 | cl = atomic_long_xchg(&rdp->nocb_follower_count_lazy, 0); |
2244 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | 2405 | rdp->nocb_p_count += c; |
2245 | TPS("WokeEmpty")); | 2406 | rdp->nocb_p_count_lazy += cl; |
2246 | schedule_timeout_interruptible(1); | ||
2247 | flush_signals(current); | ||
2248 | continue; | ||
2249 | } | ||
2250 | firsttime = 1; | ||
2251 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2252 | TPS("WokeNonEmpty")); | ||
2253 | |||
2254 | /* | ||
2255 | * Extract queued callbacks, update counts, and wait | ||
2256 | * for a grace period to elapse. | ||
2257 | */ | ||
2258 | ACCESS_ONCE(rdp->nocb_head) = NULL; | ||
2259 | tail = xchg(&rdp->nocb_tail, &rdp->nocb_head); | ||
2260 | c = atomic_long_xchg(&rdp->nocb_q_count, 0); | ||
2261 | cl = atomic_long_xchg(&rdp->nocb_q_count_lazy, 0); | ||
2262 | ACCESS_ONCE(rdp->nocb_p_count) += c; | ||
2263 | ACCESS_ONCE(rdp->nocb_p_count_lazy) += cl; | ||
2264 | rcu_nocb_wait_gp(rdp); | ||
2265 | 2407 | ||
2266 | /* Each pass through the following loop invokes a callback. */ | 2408 | /* Each pass through the following loop invokes a callback. */ |
2267 | trace_rcu_batch_start(rdp->rsp->name, cl, c, -1); | 2409 | trace_rcu_batch_start(rdp->rsp->name, cl, c, -1); |
@@ -2305,7 +2447,7 @@ static void do_nocb_deferred_wakeup(struct rcu_data *rdp) | |||
2305 | if (!rcu_nocb_need_deferred_wakeup(rdp)) | 2447 | if (!rcu_nocb_need_deferred_wakeup(rdp)) |
2306 | return; | 2448 | return; |
2307 | ACCESS_ONCE(rdp->nocb_defer_wakeup) = false; | 2449 | ACCESS_ONCE(rdp->nocb_defer_wakeup) = false; |
2308 | wake_up(&rdp->nocb_wq); | 2450 | wake_nocb_leader(rdp, false); |
2309 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("DeferredWakeEmpty")); | 2451 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("DeferredWakeEmpty")); |
2310 | } | 2452 | } |
2311 | 2453 | ||
@@ -2314,19 +2456,57 @@ static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) | |||
2314 | { | 2456 | { |
2315 | rdp->nocb_tail = &rdp->nocb_head; | 2457 | rdp->nocb_tail = &rdp->nocb_head; |
2316 | init_waitqueue_head(&rdp->nocb_wq); | 2458 | init_waitqueue_head(&rdp->nocb_wq); |
2459 | rdp->nocb_follower_tail = &rdp->nocb_follower_head; | ||
2317 | } | 2460 | } |
2318 | 2461 | ||
2319 | /* Create a kthread for each RCU flavor for each no-CBs CPU. */ | 2462 | /* How many follower CPU IDs per leader? Default of -1 for sqrt(nr_cpu_ids). */ |
2463 | static int rcu_nocb_leader_stride = -1; | ||
2464 | module_param(rcu_nocb_leader_stride, int, 0444); | ||
2465 | |||
2466 | /* | ||
2467 | * Create a kthread for each RCU flavor for each no-CBs CPU. | ||
2468 | * Also initialize leader-follower relationships. | ||
2469 | */ | ||
2320 | static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp) | 2470 | static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp) |
2321 | { | 2471 | { |
2322 | int cpu; | 2472 | int cpu; |
2473 | int ls = rcu_nocb_leader_stride; | ||
2474 | int nl = 0; /* Next leader. */ | ||
2323 | struct rcu_data *rdp; | 2475 | struct rcu_data *rdp; |
2476 | struct rcu_data *rdp_leader = NULL; /* Suppress misguided gcc warn. */ | ||
2477 | struct rcu_data *rdp_prev = NULL; | ||
2324 | struct task_struct *t; | 2478 | struct task_struct *t; |
2325 | 2479 | ||
2326 | if (rcu_nocb_mask == NULL) | 2480 | if (rcu_nocb_mask == NULL) |
2327 | return; | 2481 | return; |
2482 | #if defined(CONFIG_NO_HZ_FULL) && !defined(CONFIG_NO_HZ_FULL_ALL) | ||
2483 | if (tick_nohz_full_running) | ||
2484 | cpumask_or(rcu_nocb_mask, rcu_nocb_mask, tick_nohz_full_mask); | ||
2485 | #endif /* #if defined(CONFIG_NO_HZ_FULL) && !defined(CONFIG_NO_HZ_FULL_ALL) */ | ||
2486 | if (ls == -1) { | ||
2487 | ls = int_sqrt(nr_cpu_ids); | ||
2488 | rcu_nocb_leader_stride = ls; | ||
2489 | } | ||
2490 | |||
2491 | /* | ||
2492 | * Each pass through this loop sets up one rcu_data structure and | ||
2493 | * spawns one rcu_nocb_kthread(). | ||
2494 | */ | ||
2328 | for_each_cpu(cpu, rcu_nocb_mask) { | 2495 | for_each_cpu(cpu, rcu_nocb_mask) { |
2329 | rdp = per_cpu_ptr(rsp->rda, cpu); | 2496 | rdp = per_cpu_ptr(rsp->rda, cpu); |
2497 | if (rdp->cpu >= nl) { | ||
2498 | /* New leader, set up for followers & next leader. */ | ||
2499 | nl = DIV_ROUND_UP(rdp->cpu + 1, ls) * ls; | ||
2500 | rdp->nocb_leader = rdp; | ||
2501 | rdp_leader = rdp; | ||
2502 | } else { | ||
2503 | /* Another follower, link to previous leader. */ | ||
2504 | rdp->nocb_leader = rdp_leader; | ||
2505 | rdp_prev->nocb_next_follower = rdp; | ||
2506 | } | ||
2507 | rdp_prev = rdp; | ||
2508 | |||
2509 | /* Spawn the kthread for this CPU. */ | ||
2330 | t = kthread_run(rcu_nocb_kthread, rdp, | 2510 | t = kthread_run(rcu_nocb_kthread, rdp, |
2331 | "rcuo%c/%d", rsp->abbr, cpu); | 2511 | "rcuo%c/%d", rsp->abbr, cpu); |
2332 | BUG_ON(IS_ERR(t)); | 2512 | BUG_ON(IS_ERR(t)); |
@@ -2843,12 +3023,16 @@ static bool rcu_nohz_full_cpu(struct rcu_state *rsp) | |||
2843 | */ | 3023 | */ |
2844 | static void rcu_bind_gp_kthread(void) | 3024 | static void rcu_bind_gp_kthread(void) |
2845 | { | 3025 | { |
2846 | #ifdef CONFIG_NO_HZ_FULL | 3026 | int __maybe_unused cpu; |
2847 | int cpu = ACCESS_ONCE(tick_do_timer_cpu); | ||
2848 | 3027 | ||
2849 | if (cpu < 0 || cpu >= nr_cpu_ids) | 3028 | if (!tick_nohz_full_enabled()) |
2850 | return; | 3029 | return; |
2851 | if (raw_smp_processor_id() != cpu) | 3030 | #ifdef CONFIG_NO_HZ_FULL_SYSIDLE |
3031 | cpu = tick_do_timer_cpu; | ||
3032 | if (cpu >= 0 && cpu < nr_cpu_ids && raw_smp_processor_id() != cpu) | ||
2852 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | 3033 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); |
2853 | #endif /* #ifdef CONFIG_NO_HZ_FULL */ | 3034 | #else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ |
3035 | if (!is_housekeeping_cpu(raw_smp_processor_id())) | ||
3036 | housekeeping_affine(current); | ||
3037 | #endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ | ||
2854 | } | 3038 | } |