diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-06-22 14:08:41 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-09-23 10:41:53 -0400 |
commit | 7fdefc10e1d730d4608cc59d386bc446f5b9ee99 (patch) | |
tree | 8365a35be3c92af654667a6ff8e73969abb1e000 /kernel/rcutree.c | |
parent | c856bafae7f5b3f59ac1d99279a9b99b3b36ad12 (diff) |
rcu: Break up rcu_gp_kthread() into subfunctions
Then rcu_gp_kthread() function is too large and furthermore needs to
have the force_quiescent_state() code pulled in. This commit therefore
breaks up rcu_gp_kthread() into rcu_gp_init() and rcu_gp_cleanup().
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r-- | kernel/rcutree.c | 250 |
1 files changed, 135 insertions, 115 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index ddc6acc85d26..f0c0c1b4b6d4 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -1028,95 +1028,159 @@ rcu_start_gp_per_cpu(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_dat | |||
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | /* | 1030 | /* |
1031 | * Body of kthread that handles grace periods. | 1031 | * Initialize a new grace period. |
1032 | */ | 1032 | */ |
1033 | static int __noreturn rcu_gp_kthread(void *arg) | 1033 | static int rcu_gp_init(struct rcu_state *rsp) |
1034 | { | 1034 | { |
1035 | unsigned long gp_duration; | ||
1036 | struct rcu_data *rdp; | 1035 | struct rcu_data *rdp; |
1037 | struct rcu_node *rnp; | 1036 | struct rcu_node *rnp = rcu_get_root(rsp); |
1038 | struct rcu_state *rsp = arg; | ||
1039 | 1037 | ||
1040 | for (;;) { | 1038 | raw_spin_lock_irq(&rnp->lock); |
1039 | rsp->gp_flags = 0; | ||
1041 | 1040 | ||
1042 | /* Handle grace-period start. */ | 1041 | if (rcu_gp_in_progress(rsp)) { |
1043 | rnp = rcu_get_root(rsp); | 1042 | /* Grace period already in progress, don't start another. */ |
1044 | for (;;) { | 1043 | raw_spin_unlock_irq(&rnp->lock); |
1045 | wait_event_interruptible(rsp->gp_wq, rsp->gp_flags); | 1044 | return 0; |
1046 | if (rsp->gp_flags) | 1045 | } |
1047 | break; | 1046 | |
1048 | flush_signals(current); | 1047 | if (rsp->fqs_active) { |
1049 | } | 1048 | /* |
1049 | * We need a grace period, but force_quiescent_state() | ||
1050 | * is running. Tell it to start one on our behalf. | ||
1051 | */ | ||
1052 | rsp->fqs_need_gp = 1; | ||
1053 | raw_spin_unlock_irq(&rnp->lock); | ||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
1057 | /* Advance to a new grace period and initialize state. */ | ||
1058 | rsp->gpnum++; | ||
1059 | trace_rcu_grace_period(rsp->name, rsp->gpnum, "start"); | ||
1060 | WARN_ON_ONCE(rsp->fqs_state == RCU_GP_INIT); | ||
1061 | rsp->fqs_state = RCU_GP_INIT; /* Stop force_quiescent_state. */ | ||
1062 | rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; | ||
1063 | record_gp_stall_check_time(rsp); | ||
1064 | raw_spin_unlock_irq(&rnp->lock); | ||
1065 | |||
1066 | /* Exclude any concurrent CPU-hotplug operations. */ | ||
1067 | get_online_cpus(); | ||
1068 | |||
1069 | /* | ||
1070 | * Set the quiescent-state-needed bits in all the rcu_node | ||
1071 | * structures for all currently online CPUs in breadth-first order, | ||
1072 | * starting from the root rcu_node structure, relying on the layout | ||
1073 | * of the tree within the rsp->node[] array. Note that other CPUs | ||
1074 | * will access only the leaves of the hierarchy, thus seeing that no | ||
1075 | * grace period is in progress, at least until the corresponding | ||
1076 | * leaf node has been initialized. In addition, we have excluded | ||
1077 | * CPU-hotplug operations. | ||
1078 | * | ||
1079 | * The grace period cannot complete until the initialization | ||
1080 | * process finishes, because this kthread handles both. | ||
1081 | */ | ||
1082 | rcu_for_each_node_breadth_first(rsp, rnp) { | ||
1050 | raw_spin_lock_irq(&rnp->lock); | 1083 | raw_spin_lock_irq(&rnp->lock); |
1051 | rsp->gp_flags = 0; | ||
1052 | rdp = this_cpu_ptr(rsp->rda); | 1084 | rdp = this_cpu_ptr(rsp->rda); |
1085 | rcu_preempt_check_blocked_tasks(rnp); | ||
1086 | rnp->qsmask = rnp->qsmaskinit; | ||
1087 | rnp->gpnum = rsp->gpnum; | ||
1088 | rnp->completed = rsp->completed; | ||
1089 | if (rnp == rdp->mynode) | ||
1090 | rcu_start_gp_per_cpu(rsp, rnp, rdp); | ||
1091 | rcu_preempt_boost_start_gp(rnp); | ||
1092 | trace_rcu_grace_period_init(rsp->name, rnp->gpnum, | ||
1093 | rnp->level, rnp->grplo, | ||
1094 | rnp->grphi, rnp->qsmask); | ||
1095 | raw_spin_unlock_irq(&rnp->lock); | ||
1096 | cond_resched(); | ||
1097 | } | ||
1053 | 1098 | ||
1054 | if (rcu_gp_in_progress(rsp)) { | 1099 | rnp = rcu_get_root(rsp); |
1055 | /* | 1100 | raw_spin_lock_irq(&rnp->lock); |
1056 | * A grace period is already in progress, so | 1101 | /* force_quiescent_state() now OK. */ |
1057 | * don't start another one. | 1102 | rsp->fqs_state = RCU_SIGNAL_INIT; |
1058 | */ | 1103 | raw_spin_unlock_irq(&rnp->lock); |
1059 | raw_spin_unlock_irq(&rnp->lock); | 1104 | put_online_cpus(); |
1060 | cond_resched(); | 1105 | return 1; |
1061 | continue; | 1106 | } |
1062 | } | ||
1063 | 1107 | ||
1064 | if (rsp->fqs_active) { | 1108 | /* |
1065 | /* | 1109 | * Clean up after the old grace period. |
1066 | * We need a grace period, but force_quiescent_state() | 1110 | */ |
1067 | * is running. Tell it to start one on our behalf. | 1111 | static int rcu_gp_cleanup(struct rcu_state *rsp) |
1068 | */ | 1112 | { |
1069 | rsp->fqs_need_gp = 1; | 1113 | unsigned long gp_duration; |
1070 | raw_spin_unlock_irq(&rnp->lock); | 1114 | struct rcu_data *rdp; |
1071 | cond_resched(); | 1115 | struct rcu_node *rnp = rcu_get_root(rsp); |
1072 | continue; | ||
1073 | } | ||
1074 | 1116 | ||
1075 | /* Advance to a new grace period and initialize state. */ | 1117 | raw_spin_lock_irq(&rnp->lock); |
1076 | rsp->gpnum++; | 1118 | gp_duration = jiffies - rsp->gp_start; |
1077 | trace_rcu_grace_period(rsp->name, rsp->gpnum, "start"); | 1119 | if (gp_duration > rsp->gp_max) |
1078 | WARN_ON_ONCE(rsp->fqs_state == RCU_GP_INIT); | 1120 | rsp->gp_max = gp_duration; |
1079 | rsp->fqs_state = RCU_GP_INIT; /* Stop force_quiescent_state. */ | ||
1080 | rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; | ||
1081 | record_gp_stall_check_time(rsp); | ||
1082 | raw_spin_unlock_irq(&rnp->lock); | ||
1083 | 1121 | ||
1084 | /* Exclude any concurrent CPU-hotplug operations. */ | 1122 | /* |
1085 | get_online_cpus(); | 1123 | * We know the grace period is complete, but to everyone else |
1124 | * it appears to still be ongoing. But it is also the case | ||
1125 | * that to everyone else it looks like there is nothing that | ||
1126 | * they can do to advance the grace period. It is therefore | ||
1127 | * safe for us to drop the lock in order to mark the grace | ||
1128 | * period as completed in all of the rcu_node structures. | ||
1129 | * | ||
1130 | * But if this CPU needs another grace period, it will take | ||
1131 | * care of this while initializing the next grace period. | ||
1132 | * We use RCU_WAIT_TAIL instead of the usual RCU_DONE_TAIL | ||
1133 | * because the callbacks have not yet been advanced: Those | ||
1134 | * callbacks are waiting on the grace period that just now | ||
1135 | * completed. | ||
1136 | */ | ||
1137 | rdp = this_cpu_ptr(rsp->rda); | ||
1138 | if (*rdp->nxttail[RCU_WAIT_TAIL] == NULL) { | ||
1139 | raw_spin_unlock_irq(&rnp->lock); | ||
1086 | 1140 | ||
1087 | /* | 1141 | /* |
1088 | * Set the quiescent-state-needed bits in all the rcu_node | 1142 | * Propagate new ->completed value to rcu_node |
1089 | * structures for all currently online CPUs in breadth-first | 1143 | * structures so that other CPUs don't have to |
1090 | * order, starting from the root rcu_node structure. | 1144 | * wait until the start of the next grace period |
1091 | * This operation relies on the layout of the hierarchy | 1145 | * to process their callbacks. |
1092 | * within the rsp->node[] array. Note that other CPUs will | ||
1093 | * access only the leaves of the hierarchy, which still | ||
1094 | * indicate that no grace period is in progress, at least | ||
1095 | * until the corresponding leaf node has been initialized. | ||
1096 | * In addition, we have excluded CPU-hotplug operations. | ||
1097 | */ | 1146 | */ |
1098 | rcu_for_each_node_breadth_first(rsp, rnp) { | 1147 | rcu_for_each_node_breadth_first(rsp, rnp) { |
1099 | raw_spin_lock_irq(&rnp->lock); | 1148 | raw_spin_lock_irq(&rnp->lock); |
1100 | rcu_preempt_check_blocked_tasks(rnp); | 1149 | rnp->completed = rsp->gpnum; |
1101 | rnp->qsmask = rnp->qsmaskinit; | ||
1102 | rnp->gpnum = rsp->gpnum; | ||
1103 | rnp->completed = rsp->completed; | ||
1104 | if (rnp == rdp->mynode) | ||
1105 | rcu_start_gp_per_cpu(rsp, rnp, rdp); | ||
1106 | rcu_preempt_boost_start_gp(rnp); | ||
1107 | trace_rcu_grace_period_init(rsp->name, rnp->gpnum, | ||
1108 | rnp->level, rnp->grplo, | ||
1109 | rnp->grphi, rnp->qsmask); | ||
1110 | raw_spin_unlock_irq(&rnp->lock); | 1150 | raw_spin_unlock_irq(&rnp->lock); |
1111 | cond_resched(); | 1151 | cond_resched(); |
1112 | } | 1152 | } |
1113 | |||
1114 | rnp = rcu_get_root(rsp); | 1153 | rnp = rcu_get_root(rsp); |
1115 | raw_spin_lock_irq(&rnp->lock); | 1154 | raw_spin_lock_irq(&rnp->lock); |
1116 | /* force_quiescent_state() now OK. */ | 1155 | } |
1117 | rsp->fqs_state = RCU_SIGNAL_INIT; | 1156 | |
1118 | raw_spin_unlock_irq(&rnp->lock); | 1157 | rsp->completed = rsp->gpnum; /* Declare grace period done. */ |
1119 | put_online_cpus(); | 1158 | trace_rcu_grace_period(rsp->name, rsp->completed, "end"); |
1159 | rsp->fqs_state = RCU_GP_IDLE; | ||
1160 | if (cpu_needs_another_gp(rsp, rdp)) | ||
1161 | rsp->gp_flags = 1; | ||
1162 | raw_spin_unlock_irq(&rnp->lock); | ||
1163 | return 1; | ||
1164 | } | ||
1165 | |||
1166 | /* | ||
1167 | * Body of kthread that handles grace periods. | ||
1168 | */ | ||
1169 | static int __noreturn rcu_gp_kthread(void *arg) | ||
1170 | { | ||
1171 | struct rcu_state *rsp = arg; | ||
1172 | struct rcu_node *rnp = rcu_get_root(rsp); | ||
1173 | |||
1174 | for (;;) { | ||
1175 | |||
1176 | /* Handle grace-period start. */ | ||
1177 | for (;;) { | ||
1178 | wait_event_interruptible(rsp->gp_wq, rsp->gp_flags); | ||
1179 | if (rsp->gp_flags && rcu_gp_init(rsp)) | ||
1180 | break; | ||
1181 | cond_resched(); | ||
1182 | flush_signals(current); | ||
1183 | } | ||
1120 | 1184 | ||
1121 | /* Handle grace-period end. */ | 1185 | /* Handle grace-period end. */ |
1122 | rnp = rcu_get_root(rsp); | 1186 | rnp = rcu_get_root(rsp); |
@@ -1125,56 +1189,12 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1125 | !ACCESS_ONCE(rnp->qsmask) && | 1189 | !ACCESS_ONCE(rnp->qsmask) && |
1126 | !rcu_preempt_blocked_readers_cgp(rnp)); | 1190 | !rcu_preempt_blocked_readers_cgp(rnp)); |
1127 | if (!ACCESS_ONCE(rnp->qsmask) && | 1191 | if (!ACCESS_ONCE(rnp->qsmask) && |
1128 | !rcu_preempt_blocked_readers_cgp(rnp)) | 1192 | !rcu_preempt_blocked_readers_cgp(rnp) && |
1193 | rcu_gp_cleanup(rsp)) | ||
1129 | break; | 1194 | break; |
1195 | cond_resched(); | ||
1130 | flush_signals(current); | 1196 | flush_signals(current); |
1131 | } | 1197 | } |
1132 | |||
1133 | raw_spin_lock_irq(&rnp->lock); | ||
1134 | gp_duration = jiffies - rsp->gp_start; | ||
1135 | if (gp_duration > rsp->gp_max) | ||
1136 | rsp->gp_max = gp_duration; | ||
1137 | |||
1138 | /* | ||
1139 | * We know the grace period is complete, but to everyone else | ||
1140 | * it appears to still be ongoing. But it is also the case | ||
1141 | * that to everyone else it looks like there is nothing that | ||
1142 | * they can do to advance the grace period. It is therefore | ||
1143 | * safe for us to drop the lock in order to mark the grace | ||
1144 | * period as completed in all of the rcu_node structures. | ||
1145 | * | ||
1146 | * But if this CPU needs another grace period, it will take | ||
1147 | * care of this while initializing the next grace period. | ||
1148 | * We use RCU_WAIT_TAIL instead of the usual RCU_DONE_TAIL | ||
1149 | * because the callbacks have not yet been advanced: Those | ||
1150 | * callbacks are waiting on the grace period that just now | ||
1151 | * completed. | ||
1152 | */ | ||
1153 | if (*rdp->nxttail[RCU_WAIT_TAIL] == NULL) { | ||
1154 | raw_spin_unlock_irq(&rnp->lock); | ||
1155 | |||
1156 | /* | ||
1157 | * Propagate new ->completed value to rcu_node | ||
1158 | * structures so that other CPUs don't have to | ||
1159 | * wait until the start of the next grace period | ||
1160 | * to process their callbacks. | ||
1161 | */ | ||
1162 | rcu_for_each_node_breadth_first(rsp, rnp) { | ||
1163 | raw_spin_lock_irq(&rnp->lock); | ||
1164 | rnp->completed = rsp->gpnum; | ||
1165 | raw_spin_unlock_irq(&rnp->lock); | ||
1166 | cond_resched(); | ||
1167 | } | ||
1168 | rnp = rcu_get_root(rsp); | ||
1169 | raw_spin_lock_irq(&rnp->lock); | ||
1170 | } | ||
1171 | |||
1172 | rsp->completed = rsp->gpnum; /* Declare grace period done. */ | ||
1173 | trace_rcu_grace_period(rsp->name, rsp->completed, "end"); | ||
1174 | rsp->fqs_state = RCU_GP_IDLE; | ||
1175 | if (cpu_needs_another_gp(rsp, rdp)) | ||
1176 | rsp->gp_flags = 1; | ||
1177 | raw_spin_unlock_irq(&rnp->lock); | ||
1178 | } | 1198 | } |
1179 | } | 1199 | } |
1180 | 1200 | ||