diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2008-01-25 15:08:29 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-25 15:08:29 -0500 |
commit | fa85ae2418e6843953107cd6a06f645752829bc0 (patch) | |
tree | 004130ac471247a29d3f6adfbfe61c474e725779 /kernel/sched_rt.c | |
parent | 8f4d37ec073c17e2d4aa8851df5837d798606d6f (diff) |
sched: rt time limit
Very simple time limit on the realtime scheduling classes.
Allow the rq's realtime class to consume sched_rt_ratio of every
sched_rt_period slice. If the class exceeds this quota the fair class
will preempt the realtime class.
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 | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 83fbbcb8019e..fd10d965aa06 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c | |||
@@ -45,6 +45,50 @@ static void update_rt_migration(struct rq *rq) | |||
45 | } | 45 | } |
46 | #endif /* CONFIG_SMP */ | 46 | #endif /* CONFIG_SMP */ |
47 | 47 | ||
48 | static int sched_rt_ratio_exceeded(struct rq *rq, struct rt_rq *rt_rq) | ||
49 | { | ||
50 | u64 period, ratio; | ||
51 | |||
52 | if (sysctl_sched_rt_ratio == SCHED_RT_FRAC) | ||
53 | return 0; | ||
54 | |||
55 | if (rt_rq->rt_throttled) | ||
56 | return 1; | ||
57 | |||
58 | period = (u64)sysctl_sched_rt_period * NSEC_PER_MSEC; | ||
59 | ratio = (period * sysctl_sched_rt_ratio) >> SCHED_RT_FRAC_SHIFT; | ||
60 | |||
61 | if (rt_rq->rt_time > ratio) { | ||
62 | rt_rq->rt_throttled = rq->clock + period - rt_rq->rt_time; | ||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static void update_sched_rt_period(struct rq *rq) | ||
70 | { | ||
71 | while (rq->clock > rq->rt_period_expire) { | ||
72 | u64 period, ratio; | ||
73 | |||
74 | period = (u64)sysctl_sched_rt_period * NSEC_PER_MSEC; | ||
75 | ratio = (period * sysctl_sched_rt_ratio) >> SCHED_RT_FRAC_SHIFT; | ||
76 | |||
77 | rq->rt.rt_time -= min(rq->rt.rt_time, ratio); | ||
78 | rq->rt_period_expire += period; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * When the rt throttle is expired, let them rip. | ||
83 | * (XXX: use hrtick when available) | ||
84 | */ | ||
85 | if (rq->rt.rt_throttled && rq->clock > rq->rt.rt_throttled) { | ||
86 | rq->rt.rt_throttled = 0; | ||
87 | if (!sched_rt_ratio_exceeded(rq, &rq->rt)) | ||
88 | resched_task(rq->curr); | ||
89 | } | ||
90 | } | ||
91 | |||
48 | /* | 92 | /* |
49 | * Update the current task's runtime statistics. Skip current tasks that | 93 | * Update the current task's runtime statistics. Skip current tasks that |
50 | * are not in our scheduling class. | 94 | * are not in our scheduling class. |
@@ -66,6 +110,11 @@ static void update_curr_rt(struct rq *rq) | |||
66 | curr->se.sum_exec_runtime += delta_exec; | 110 | curr->se.sum_exec_runtime += delta_exec; |
67 | curr->se.exec_start = rq->clock; | 111 | curr->se.exec_start = rq->clock; |
68 | cpuacct_charge(curr, delta_exec); | 112 | cpuacct_charge(curr, delta_exec); |
113 | |||
114 | rq->rt.rt_time += delta_exec; | ||
115 | update_sched_rt_period(rq); | ||
116 | if (sched_rt_ratio_exceeded(rq, &rq->rt)) | ||
117 | resched_task(curr); | ||
69 | } | 118 | } |
70 | 119 | ||
71 | static inline void inc_rt_tasks(struct task_struct *p, struct rq *rq) | 120 | static inline void inc_rt_tasks(struct task_struct *p, struct rq *rq) |
@@ -208,8 +257,12 @@ static struct task_struct *pick_next_task_rt(struct rq *rq) | |||
208 | struct rt_prio_array *array = &rq->rt.active; | 257 | struct rt_prio_array *array = &rq->rt.active; |
209 | struct task_struct *next; | 258 | struct task_struct *next; |
210 | struct list_head *queue; | 259 | struct list_head *queue; |
260 | struct rt_rq *rt_rq = &rq->rt; | ||
211 | int idx; | 261 | int idx; |
212 | 262 | ||
263 | if (sched_rt_ratio_exceeded(rq, rt_rq)) | ||
264 | return NULL; | ||
265 | |||
213 | idx = sched_find_first_bit(array->bitmap); | 266 | idx = sched_find_first_bit(array->bitmap); |
214 | if (idx >= MAX_RT_PRIO) | 267 | if (idx >= MAX_RT_PRIO) |
215 | return NULL; | 268 | return NULL; |