.. | .. |
---|
100 | 100 | static bool dump_tree; |
---|
101 | 101 | module_param(dump_tree, bool, 0444); |
---|
102 | 102 | /* By default, use RCU_SOFTIRQ instead of rcuc kthreads. */ |
---|
103 | | -static bool use_softirq = !IS_ENABLED(CONFIG_PREEMPT_RT); |
---|
104 | | -#ifndef CONFIG_PREEMPT_RT |
---|
| 103 | +static bool use_softirq = true; |
---|
105 | 104 | module_param(use_softirq, bool, 0444); |
---|
106 | | -#endif |
---|
107 | 105 | /* Control rcu_node-tree auto-balancing at boot time. */ |
---|
108 | 106 | static bool rcu_fanout_exact; |
---|
109 | 107 | module_param(rcu_fanout_exact, bool, 0444); |
---|
.. | .. |
---|
966 | 964 | } |
---|
967 | 965 | raw_spin_unlock_rcu_node(rdp->mynode); |
---|
968 | 966 | } |
---|
| 967 | +NOKPROBE_SYMBOL(__rcu_irq_enter_check_tick); |
---|
969 | 968 | #endif /* CONFIG_NO_HZ_FULL */ |
---|
970 | 969 | |
---|
971 | 970 | /** |
---|
.. | .. |
---|
1159 | 1158 | preempt_disable_notrace(); |
---|
1160 | 1159 | rdp = this_cpu_ptr(&rcu_data); |
---|
1161 | 1160 | rnp = rdp->mynode; |
---|
1162 | | - if (rdp->grpmask & rcu_rnp_online_cpus(rnp)) |
---|
| 1161 | + if (rdp->grpmask & rcu_rnp_online_cpus(rnp) || READ_ONCE(rnp->ofl_seq) & 0x1) |
---|
1163 | 1162 | ret = true; |
---|
1164 | 1163 | preempt_enable_notrace(); |
---|
1165 | 1164 | return ret; |
---|
.. | .. |
---|
1726 | 1725 | */ |
---|
1727 | 1726 | static bool rcu_gp_init(void) |
---|
1728 | 1727 | { |
---|
| 1728 | + unsigned long firstseq; |
---|
1729 | 1729 | unsigned long flags; |
---|
1730 | 1730 | unsigned long oldmask; |
---|
1731 | 1731 | unsigned long mask; |
---|
.. | .. |
---|
1769 | 1769 | */ |
---|
1770 | 1770 | rcu_state.gp_state = RCU_GP_ONOFF; |
---|
1771 | 1771 | rcu_for_each_leaf_node(rnp) { |
---|
| 1772 | + smp_mb(); // Pair with barriers used when updating ->ofl_seq to odd values. |
---|
| 1773 | + firstseq = READ_ONCE(rnp->ofl_seq); |
---|
| 1774 | + if (firstseq & 0x1) |
---|
| 1775 | + while (firstseq == READ_ONCE(rnp->ofl_seq)) |
---|
| 1776 | + schedule_timeout_idle(1); // Can't wake unless RCU is watching. |
---|
| 1777 | + smp_mb(); // Pair with barriers used when updating ->ofl_seq to even values. |
---|
1772 | 1778 | raw_spin_lock(&rcu_state.ofl_lock); |
---|
1773 | 1779 | raw_spin_lock_irq_rcu_node(rnp); |
---|
1774 | 1780 | if (rnp->qsmaskinit == rnp->qsmaskinitnext && |
---|
.. | .. |
---|
2652 | 2658 | struct rcu_node *rnp_old = NULL; |
---|
2653 | 2659 | |
---|
2654 | 2660 | /* Funnel through hierarchy to reduce memory contention. */ |
---|
2655 | | - rnp = __this_cpu_read(rcu_data.mynode); |
---|
| 2661 | + rnp = raw_cpu_read(rcu_data.mynode); |
---|
2656 | 2662 | for (; rnp != NULL; rnp = rnp->parent) { |
---|
2657 | 2663 | ret = (READ_ONCE(rcu_state.gp_flags) & RCU_GP_FLAG_FQS) || |
---|
2658 | 2664 | !raw_spin_trylock(&rnp->fqslock); |
---|
.. | .. |
---|
3275 | 3281 | } |
---|
3276 | 3282 | } |
---|
3277 | 3283 | |
---|
| 3284 | +static bool |
---|
| 3285 | +need_offload_krc(struct kfree_rcu_cpu *krcp) |
---|
| 3286 | +{ |
---|
| 3287 | + int i; |
---|
| 3288 | + |
---|
| 3289 | + for (i = 0; i < FREE_N_CHANNELS; i++) |
---|
| 3290 | + if (krcp->bkvhead[i]) |
---|
| 3291 | + return true; |
---|
| 3292 | + |
---|
| 3293 | + return !!krcp->head; |
---|
| 3294 | +} |
---|
| 3295 | + |
---|
| 3296 | +static bool |
---|
| 3297 | +need_wait_for_krwp_work(struct kfree_rcu_cpu_work *krwp) |
---|
| 3298 | +{ |
---|
| 3299 | + int i; |
---|
| 3300 | + |
---|
| 3301 | + for (i = 0; i < FREE_N_CHANNELS; i++) |
---|
| 3302 | + if (krwp->bkvhead_free[i]) |
---|
| 3303 | + return true; |
---|
| 3304 | + |
---|
| 3305 | + return !!krwp->head_free; |
---|
| 3306 | +} |
---|
| 3307 | + |
---|
3278 | 3308 | /* |
---|
3279 | 3309 | * Schedule the kfree batch RCU work to run in workqueue context after a GP. |
---|
3280 | 3310 | * |
---|
.. | .. |
---|
3292 | 3322 | for (i = 0; i < KFREE_N_BATCHES; i++) { |
---|
3293 | 3323 | krwp = &(krcp->krw_arr[i]); |
---|
3294 | 3324 | |
---|
3295 | | - /* |
---|
3296 | | - * Try to detach bkvhead or head and attach it over any |
---|
3297 | | - * available corresponding free channel. It can be that |
---|
3298 | | - * a previous RCU batch is in progress, it means that |
---|
3299 | | - * immediately to queue another one is not possible so |
---|
3300 | | - * return false to tell caller to retry. |
---|
3301 | | - */ |
---|
3302 | | - if ((krcp->bkvhead[0] && !krwp->bkvhead_free[0]) || |
---|
3303 | | - (krcp->bkvhead[1] && !krwp->bkvhead_free[1]) || |
---|
3304 | | - (krcp->head && !krwp->head_free)) { |
---|
| 3325 | + // Try to detach bulk_head or head and attach it, only when |
---|
| 3326 | + // all channels are free. Any channel is not free means at krwp |
---|
| 3327 | + // there is on-going rcu work to handle krwp's free business. |
---|
| 3328 | + if (need_wait_for_krwp_work(krwp)) |
---|
| 3329 | + continue; |
---|
| 3330 | + |
---|
| 3331 | + if (need_offload_krc(krcp)) { |
---|
3305 | 3332 | // Channel 1 corresponds to SLAB ptrs. |
---|
3306 | 3333 | // Channel 2 corresponds to vmalloc ptrs. |
---|
3307 | 3334 | for (j = 0; j < FREE_N_CHANNELS; j++) { |
---|
.. | .. |
---|
3328 | 3355 | */ |
---|
3329 | 3356 | queue_rcu_work(system_wq, &krwp->rcu_work); |
---|
3330 | 3357 | } |
---|
3331 | | - |
---|
3332 | | - // Repeat if any "free" corresponding channel is still busy. |
---|
3333 | | - if (krcp->bkvhead[0] || krcp->bkvhead[1] || krcp->head) |
---|
3334 | | - repeat = true; |
---|
3335 | 3358 | } |
---|
| 3359 | + |
---|
| 3360 | + // Repeat if any "free" corresponding channel is still busy. |
---|
| 3361 | + if (need_offload_krc(krcp)) |
---|
| 3362 | + repeat = true; |
---|
3336 | 3363 | |
---|
3337 | 3364 | return !repeat; |
---|
3338 | 3365 | } |
---|
.. | .. |
---|
4109 | 4136 | |
---|
4110 | 4137 | rnp = rdp->mynode; |
---|
4111 | 4138 | mask = rdp->grpmask; |
---|
| 4139 | + WRITE_ONCE(rnp->ofl_seq, rnp->ofl_seq + 1); |
---|
| 4140 | + WARN_ON_ONCE(!(rnp->ofl_seq & 0x1)); |
---|
| 4141 | + smp_mb(); // Pair with rcu_gp_cleanup()'s ->ofl_seq barrier(). |
---|
4112 | 4142 | raw_spin_lock_irqsave_rcu_node(rnp, flags); |
---|
4113 | 4143 | WRITE_ONCE(rnp->qsmaskinitnext, rnp->qsmaskinitnext | mask); |
---|
4114 | 4144 | newcpu = !(rnp->expmaskinitnext & mask); |
---|
.. | .. |
---|
4126 | 4156 | } else { |
---|
4127 | 4157 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); |
---|
4128 | 4158 | } |
---|
| 4159 | + smp_mb(); // Pair with rcu_gp_cleanup()'s ->ofl_seq barrier(). |
---|
| 4160 | + WRITE_ONCE(rnp->ofl_seq, rnp->ofl_seq + 1); |
---|
| 4161 | + WARN_ON_ONCE(rnp->ofl_seq & 0x1); |
---|
4129 | 4162 | smp_mb(); /* Ensure RCU read-side usage follows above initialization. */ |
---|
4130 | 4163 | } |
---|
4131 | 4164 | |
---|
.. | .. |
---|
4152 | 4185 | |
---|
4153 | 4186 | /* Remove outgoing CPU from mask in the leaf rcu_node structure. */ |
---|
4154 | 4187 | mask = rdp->grpmask; |
---|
| 4188 | + WRITE_ONCE(rnp->ofl_seq, rnp->ofl_seq + 1); |
---|
| 4189 | + WARN_ON_ONCE(!(rnp->ofl_seq & 0x1)); |
---|
| 4190 | + smp_mb(); // Pair with rcu_gp_cleanup()'s ->ofl_seq barrier(). |
---|
4155 | 4191 | raw_spin_lock(&rcu_state.ofl_lock); |
---|
4156 | 4192 | raw_spin_lock_irqsave_rcu_node(rnp, flags); /* Enforce GP memory-order guarantee. */ |
---|
4157 | 4193 | rdp->rcu_ofl_gp_seq = READ_ONCE(rcu_state.gp_seq); |
---|
.. | .. |
---|
4164 | 4200 | WRITE_ONCE(rnp->qsmaskinitnext, rnp->qsmaskinitnext & ~mask); |
---|
4165 | 4201 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); |
---|
4166 | 4202 | raw_spin_unlock(&rcu_state.ofl_lock); |
---|
| 4203 | + smp_mb(); // Pair with rcu_gp_cleanup()'s ->ofl_seq barrier(). |
---|
| 4204 | + WRITE_ONCE(rnp->ofl_seq, rnp->ofl_seq + 1); |
---|
| 4205 | + WARN_ON_ONCE(rnp->ofl_seq & 0x1); |
---|
4167 | 4206 | |
---|
4168 | 4207 | rdp->cpu_started = false; |
---|
4169 | 4208 | } |
---|