diff options
Diffstat (limited to 'kernel/rcu/tree_plugin.h')
-rw-r--r-- | kernel/rcu/tree_plugin.h | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index b023e5407111..752ffaa0d681 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h | |||
@@ -2104,7 +2104,8 @@ bool rcu_is_nocb_cpu(int cpu) | |||
2104 | static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | 2104 | static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, |
2105 | struct rcu_head *rhp, | 2105 | struct rcu_head *rhp, |
2106 | struct rcu_head **rhtp, | 2106 | struct rcu_head **rhtp, |
2107 | int rhcount, int rhcount_lazy) | 2107 | int rhcount, int rhcount_lazy, |
2108 | unsigned long flags) | ||
2108 | { | 2109 | { |
2109 | int len; | 2110 | int len; |
2110 | struct rcu_head **old_rhpp; | 2111 | struct rcu_head **old_rhpp; |
@@ -2125,9 +2126,16 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | |||
2125 | } | 2126 | } |
2126 | len = atomic_long_read(&rdp->nocb_q_count); | 2127 | len = atomic_long_read(&rdp->nocb_q_count); |
2127 | if (old_rhpp == &rdp->nocb_head) { | 2128 | if (old_rhpp == &rdp->nocb_head) { |
2128 | wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */ | 2129 | if (!irqs_disabled_flags(flags)) { |
2130 | wake_up(&rdp->nocb_wq); /* ... if queue was empty ... */ | ||
2131 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2132 | TPS("WakeEmpty")); | ||
2133 | } else { | ||
2134 | rdp->nocb_defer_wakeup = true; | ||
2135 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2136 | TPS("WakeEmptyIsDeferred")); | ||
2137 | } | ||
2129 | rdp->qlen_last_fqs_check = 0; | 2138 | rdp->qlen_last_fqs_check = 0; |
2130 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeEmpty")); | ||
2131 | } else if (len > rdp->qlen_last_fqs_check + qhimark) { | 2139 | } else if (len > rdp->qlen_last_fqs_check + qhimark) { |
2132 | wake_up_process(t); /* ... or if many callbacks queued. */ | 2140 | wake_up_process(t); /* ... or if many callbacks queued. */ |
2133 | rdp->qlen_last_fqs_check = LONG_MAX / 2; | 2141 | rdp->qlen_last_fqs_check = LONG_MAX / 2; |
@@ -2148,12 +2156,12 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | |||
2148 | * "rcuo" kthread can find it. | 2156 | * "rcuo" kthread can find it. |
2149 | */ | 2157 | */ |
2150 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, | 2158 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, |
2151 | bool lazy) | 2159 | bool lazy, unsigned long flags) |
2152 | { | 2160 | { |
2153 | 2161 | ||
2154 | if (!rcu_is_nocb_cpu(rdp->cpu)) | 2162 | if (!rcu_is_nocb_cpu(rdp->cpu)) |
2155 | return 0; | 2163 | return 0; |
2156 | __call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy); | 2164 | __call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy, flags); |
2157 | if (__is_kfree_rcu_offset((unsigned long)rhp->func)) | 2165 | if (__is_kfree_rcu_offset((unsigned long)rhp->func)) |
2158 | trace_rcu_kfree_callback(rdp->rsp->name, rhp, | 2166 | trace_rcu_kfree_callback(rdp->rsp->name, rhp, |
2159 | (unsigned long)rhp->func, | 2167 | (unsigned long)rhp->func, |
@@ -2171,7 +2179,8 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, | |||
2171 | * not a no-CBs CPU. | 2179 | * not a no-CBs CPU. |
2172 | */ | 2180 | */ |
2173 | static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, | 2181 | static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, |
2174 | struct rcu_data *rdp) | 2182 | struct rcu_data *rdp, |
2183 | unsigned long flags) | ||
2175 | { | 2184 | { |
2176 | long ql = rsp->qlen; | 2185 | long ql = rsp->qlen; |
2177 | long qll = rsp->qlen_lazy; | 2186 | long qll = rsp->qlen_lazy; |
@@ -2185,14 +2194,14 @@ static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, | |||
2185 | /* First, enqueue the donelist, if any. This preserves CB ordering. */ | 2194 | /* First, enqueue the donelist, if any. This preserves CB ordering. */ |
2186 | if (rsp->orphan_donelist != NULL) { | 2195 | if (rsp->orphan_donelist != NULL) { |
2187 | __call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist, | 2196 | __call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist, |
2188 | rsp->orphan_donetail, ql, qll); | 2197 | rsp->orphan_donetail, ql, qll, flags); |
2189 | ql = qll = 0; | 2198 | ql = qll = 0; |
2190 | rsp->orphan_donelist = NULL; | 2199 | rsp->orphan_donelist = NULL; |
2191 | rsp->orphan_donetail = &rsp->orphan_donelist; | 2200 | rsp->orphan_donetail = &rsp->orphan_donelist; |
2192 | } | 2201 | } |
2193 | if (rsp->orphan_nxtlist != NULL) { | 2202 | if (rsp->orphan_nxtlist != NULL) { |
2194 | __call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist, | 2203 | __call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist, |
2195 | rsp->orphan_nxttail, ql, qll); | 2204 | rsp->orphan_nxttail, ql, qll, flags); |
2196 | ql = qll = 0; | 2205 | ql = qll = 0; |
2197 | rsp->orphan_nxtlist = NULL; | 2206 | rsp->orphan_nxtlist = NULL; |
2198 | rsp->orphan_nxttail = &rsp->orphan_nxtlist; | 2207 | rsp->orphan_nxttail = &rsp->orphan_nxtlist; |
@@ -2314,6 +2323,22 @@ static int rcu_nocb_kthread(void *arg) | |||
2314 | return 0; | 2323 | return 0; |
2315 | } | 2324 | } |
2316 | 2325 | ||
2326 | /* Is a deferred wakeup of rcu_nocb_kthread() required? */ | ||
2327 | static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp) | ||
2328 | { | ||
2329 | return ACCESS_ONCE(rdp->nocb_defer_wakeup); | ||
2330 | } | ||
2331 | |||
2332 | /* Do a deferred wakeup of rcu_nocb_kthread(). */ | ||
2333 | static void do_nocb_deferred_wakeup(struct rcu_data *rdp) | ||
2334 | { | ||
2335 | if (!rcu_nocb_need_deferred_wakeup(rdp)) | ||
2336 | return; | ||
2337 | ACCESS_ONCE(rdp->nocb_defer_wakeup) = false; | ||
2338 | wake_up(&rdp->nocb_wq); | ||
2339 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("DeferredWakeEmpty")); | ||
2340 | } | ||
2341 | |||
2317 | /* Initialize per-rcu_data variables for no-CBs CPUs. */ | 2342 | /* Initialize per-rcu_data variables for no-CBs CPUs. */ |
2318 | static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) | 2343 | static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) |
2319 | { | 2344 | { |
@@ -2369,13 +2394,14 @@ static void rcu_init_one_nocb(struct rcu_node *rnp) | |||
2369 | } | 2394 | } |
2370 | 2395 | ||
2371 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, | 2396 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, |
2372 | bool lazy) | 2397 | bool lazy, unsigned long flags) |
2373 | { | 2398 | { |
2374 | return 0; | 2399 | return 0; |
2375 | } | 2400 | } |
2376 | 2401 | ||
2377 | static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, | 2402 | static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, |
2378 | struct rcu_data *rdp) | 2403 | struct rcu_data *rdp, |
2404 | unsigned long flags) | ||
2379 | { | 2405 | { |
2380 | return 0; | 2406 | return 0; |
2381 | } | 2407 | } |
@@ -2384,6 +2410,15 @@ static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) | |||
2384 | { | 2410 | { |
2385 | } | 2411 | } |
2386 | 2412 | ||
2413 | static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp) | ||
2414 | { | ||
2415 | return false; | ||
2416 | } | ||
2417 | |||
2418 | static void do_nocb_deferred_wakeup(struct rcu_data *rdp) | ||
2419 | { | ||
2420 | } | ||
2421 | |||
2387 | static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp) | 2422 | static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp) |
2388 | { | 2423 | { |
2389 | } | 2424 | } |