diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2008-04-19 13:44:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-19 13:44:57 -0400 |
commit | d0b27fa77854b149ad4af08b0fe47fe712a47ade (patch) | |
tree | 2f4487c108a5132e8d52456567b4a67e78fbb4a6 /kernel/sched_rt.c | |
parent | 57d3da2911787a101a384532f4519f9640bae883 (diff) |
sched: rt-group: synchonised bandwidth period
Various SMP balancing algorithms require that the bandwidth period
run in sync.
Possible improvements are moving the rt_bandwidth thing into root_domain
and keeping a span per rt_bandwidth which marks throttled cpus.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched_rt.c')
-rw-r--r-- | kernel/sched_rt.c | 104 |
1 files changed, 72 insertions, 32 deletions
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 0a6d2e516420..8bc176136666 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c | |||
@@ -62,7 +62,7 @@ static inline u64 sched_rt_runtime(struct rt_rq *rt_rq) | |||
62 | if (!rt_rq->tg) | 62 | if (!rt_rq->tg) |
63 | return RUNTIME_INF; | 63 | return RUNTIME_INF; |
64 | 64 | ||
65 | return rt_rq->tg->rt_runtime; | 65 | return rt_rq->tg->rt_bandwidth.rt_runtime; |
66 | } | 66 | } |
67 | 67 | ||
68 | #define for_each_leaf_rt_rq(rt_rq, rq) \ | 68 | #define for_each_leaf_rt_rq(rt_rq, rq) \ |
@@ -127,14 +127,29 @@ static int rt_se_boosted(struct sched_rt_entity *rt_se) | |||
127 | return p->prio != p->normal_prio; | 127 | return p->prio != p->normal_prio; |
128 | } | 128 | } |
129 | 129 | ||
130 | #ifdef CONFIG_SMP | ||
131 | static inline cpumask_t sched_rt_period_mask(void) | ||
132 | { | ||
133 | return cpu_rq(smp_processor_id())->rd->span; | ||
134 | } | ||
130 | #else | 135 | #else |
136 | static inline cpumask_t sched_rt_period_mask(void) | ||
137 | { | ||
138 | return cpu_online_map; | ||
139 | } | ||
140 | #endif | ||
131 | 141 | ||
132 | static inline u64 sched_rt_runtime(struct rt_rq *rt_rq) | 142 | static inline |
143 | struct rt_rq *sched_rt_period_rt_rq(struct rt_bandwidth *rt_b, int cpu) | ||
133 | { | 144 | { |
134 | if (sysctl_sched_rt_runtime == -1) | 145 | return container_of(rt_b, struct task_group, rt_bandwidth)->rt_rq[cpu]; |
135 | return RUNTIME_INF; | 146 | } |
136 | 147 | ||
137 | return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC; | 148 | #else |
149 | |||
150 | static inline u64 sched_rt_runtime(struct rt_rq *rt_rq) | ||
151 | { | ||
152 | return def_rt_bandwidth.rt_runtime; | ||
138 | } | 153 | } |
139 | 154 | ||
140 | #define for_each_leaf_rt_rq(rt_rq, rq) \ | 155 | #define for_each_leaf_rt_rq(rt_rq, rq) \ |
@@ -173,8 +188,55 @@ static inline int rt_rq_throttled(struct rt_rq *rt_rq) | |||
173 | { | 188 | { |
174 | return rt_rq->rt_throttled; | 189 | return rt_rq->rt_throttled; |
175 | } | 190 | } |
191 | |||
192 | static inline cpumask_t sched_rt_period_mask(void) | ||
193 | { | ||
194 | return cpu_online_map; | ||
195 | } | ||
196 | |||
197 | static inline | ||
198 | struct rt_rq *sched_rt_period_rt_rq(struct rt_bandwidth *rt_b, int cpu) | ||
199 | { | ||
200 | return &cpu_rq(cpu)->rt; | ||
201 | } | ||
202 | |||
176 | #endif | 203 | #endif |
177 | 204 | ||
205 | static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun) | ||
206 | { | ||
207 | int i, idle = 1; | ||
208 | cpumask_t span; | ||
209 | |||
210 | if (rt_b->rt_runtime == RUNTIME_INF) | ||
211 | return 1; | ||
212 | |||
213 | span = sched_rt_period_mask(); | ||
214 | for_each_cpu_mask(i, span) { | ||
215 | int enqueue = 0; | ||
216 | struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i); | ||
217 | struct rq *rq = rq_of_rt_rq(rt_rq); | ||
218 | |||
219 | spin_lock(&rq->lock); | ||
220 | if (rt_rq->rt_time) { | ||
221 | u64 runtime = rt_b->rt_runtime; | ||
222 | |||
223 | rt_rq->rt_time -= min(rt_rq->rt_time, overrun*runtime); | ||
224 | if (rt_rq->rt_throttled && rt_rq->rt_time < runtime) { | ||
225 | rt_rq->rt_throttled = 0; | ||
226 | enqueue = 1; | ||
227 | } | ||
228 | if (rt_rq->rt_time || rt_rq->rt_nr_running) | ||
229 | idle = 0; | ||
230 | } | ||
231 | |||
232 | if (enqueue) | ||
233 | sched_rt_rq_enqueue(rt_rq); | ||
234 | spin_unlock(&rq->lock); | ||
235 | } | ||
236 | |||
237 | return idle; | ||
238 | } | ||
239 | |||
178 | static inline int rt_se_prio(struct sched_rt_entity *rt_se) | 240 | static inline int rt_se_prio(struct sched_rt_entity *rt_se) |
179 | { | 241 | { |
180 | #ifdef CONFIG_RT_GROUP_SCHED | 242 | #ifdef CONFIG_RT_GROUP_SCHED |
@@ -198,11 +260,7 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) | |||
198 | return rt_rq_throttled(rt_rq); | 260 | return rt_rq_throttled(rt_rq); |
199 | 261 | ||
200 | if (rt_rq->rt_time > runtime) { | 262 | if (rt_rq->rt_time > runtime) { |
201 | struct rq *rq = rq_of_rt_rq(rt_rq); | ||
202 | |||
203 | rq->rt_throttled = 1; | ||
204 | rt_rq->rt_throttled = 1; | 263 | rt_rq->rt_throttled = 1; |
205 | |||
206 | if (rt_rq_throttled(rt_rq)) { | 264 | if (rt_rq_throttled(rt_rq)) { |
207 | sched_rt_rq_dequeue(rt_rq); | 265 | sched_rt_rq_dequeue(rt_rq); |
208 | return 1; | 266 | return 1; |
@@ -212,29 +270,6 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) | |||
212 | return 0; | 270 | return 0; |
213 | } | 271 | } |
214 | 272 | ||
215 | static void update_sched_rt_period(struct rq *rq) | ||
216 | { | ||
217 | struct rt_rq *rt_rq; | ||
218 | u64 period; | ||
219 | |||
220 | while (rq->clock > rq->rt_period_expire) { | ||
221 | period = (u64)sysctl_sched_rt_period * NSEC_PER_USEC; | ||
222 | rq->rt_period_expire += period; | ||
223 | |||
224 | for_each_leaf_rt_rq(rt_rq, rq) { | ||
225 | u64 runtime = sched_rt_runtime(rt_rq); | ||
226 | |||
227 | rt_rq->rt_time -= min(rt_rq->rt_time, runtime); | ||
228 | if (rt_rq->rt_throttled && rt_rq->rt_time < runtime) { | ||
229 | rt_rq->rt_throttled = 0; | ||
230 | sched_rt_rq_enqueue(rt_rq); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | rq->rt_throttled = 0; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | /* | 273 | /* |
239 | * Update the current task's runtime statistics. Skip current tasks that | 274 | * Update the current task's runtime statistics. Skip current tasks that |
240 | * are not in our scheduling class. | 275 | * are not in our scheduling class. |
@@ -284,6 +319,11 @@ void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) | |||
284 | #ifdef CONFIG_RT_GROUP_SCHED | 319 | #ifdef CONFIG_RT_GROUP_SCHED |
285 | if (rt_se_boosted(rt_se)) | 320 | if (rt_se_boosted(rt_se)) |
286 | rt_rq->rt_nr_boosted++; | 321 | rt_rq->rt_nr_boosted++; |
322 | |||
323 | if (rt_rq->tg) | ||
324 | start_rt_bandwidth(&rt_rq->tg->rt_bandwidth); | ||
325 | #else | ||
326 | start_rt_bandwidth(&def_rt_bandwidth); | ||
287 | #endif | 327 | #endif |
288 | } | 328 | } |
289 | 329 | ||