aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched_rt.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2008-04-19 13:44:57 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-19 13:44:57 -0400
commitd0b27fa77854b149ad4af08b0fe47fe712a47ade (patch)
tree2f4487c108a5132e8d52456567b4a67e78fbb4a6 /kernel/sched_rt.c
parent57d3da2911787a101a384532f4519f9640bae883 (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.c104
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
131static inline cpumask_t sched_rt_period_mask(void)
132{
133 return cpu_rq(smp_processor_id())->rd->span;
134}
130#else 135#else
136static inline cpumask_t sched_rt_period_mask(void)
137{
138 return cpu_online_map;
139}
140#endif
131 141
132static inline u64 sched_rt_runtime(struct rt_rq *rt_rq) 142static inline
143struct 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
150static 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
192static inline cpumask_t sched_rt_period_mask(void)
193{
194 return cpu_online_map;
195}
196
197static inline
198struct 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
205static 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
178static inline int rt_se_prio(struct sched_rt_entity *rt_se) 240static 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
215static 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