Magellan Linux

Contents of /trunk/kernel26-alx/patches-2.6.21-r15/0006-2.6.21-sched-idleprio-2.3.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 464 - (show annotations) (download)
Wed Feb 6 09:19:36 2008 UTC (16 years, 2 months ago) by niro
File size: 11511 byte(s)
-rev bump to 2.6.21-alx-r15; added i686 support

1 Add the SCHED_IDLEPRIO scheduling policy. Tasks set to this policy are only
2 given cpu time if no other tasks at all wish to have cpu time thus running
3 effectively at idle priority. If semaphores or mutexes are held, or the
4 system is going into suspend, schedule them as SCHED_NORMAL nice 19.
5
6 Signed-off-by: Con Kolivas <kernel@kolivas.org>
7 ---
8 include/linux/sched.h | 5 +
9 kernel/sched.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++----
10 2 files changed, 138 insertions(+), 12 deletions(-)
11
12 Index: linux-2.6.21-ck2/include/linux/sched.h
13 ===================================================================
14 --- linux-2.6.21-ck2.orig/include/linux/sched.h 2007-05-14 19:30:31.000000000 +1000
15 +++ linux-2.6.21-ck2/include/linux/sched.h 2007-05-14 19:30:31.000000000 +1000
16 @@ -35,10 +35,11 @@
17 #define SCHED_RR 2
18 #define SCHED_BATCH 3
19 #define SCHED_ISO 4
20 +#define SCHED_IDLEPRIO 5
21
22 #ifdef __KERNEL__
23
24 -#define SCHED_MAX SCHED_ISO
25 +#define SCHED_MAX SCHED_IDLEPRIO
26 #define SCHED_RANGE(policy) ((policy) <= SCHED_MAX)
27
28 struct sched_param {
29 @@ -537,6 +538,7 @@ struct signal_struct {
30 (policy) == SCHED_RR)
31 #define has_rt_policy(p) unlikely(is_rt_policy((p)->policy))
32 #define iso_task(p) unlikely((p)->policy == SCHED_ISO)
33 +#define idleprio_task(p) unlikely((p)->policy == SCHED_IDLEPRIO)
34
35 /*
36 * Some day this will be a full-fledged user tracking system..
37 @@ -1173,6 +1175,7 @@ static inline void put_task_struct(struc
38 #define PF_ISOREF 0x04000000 /* SCHED_ISO task has used up quota */
39 #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */
40 #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */
41 +#define PF_NONSLEEP 0x40000000 /* Waiting on in-kernel activity */
42
43 /*
44 * Only the _current_ task can read/write to tsk->flags, but other
45 Index: linux-2.6.21-ck2/kernel/sched.c
46 ===================================================================
47 --- linux-2.6.21-ck2.orig/kernel/sched.c 2007-05-14 19:30:31.000000000 +1000
48 +++ linux-2.6.21-ck2/kernel/sched.c 2007-05-14 19:30:31.000000000 +1000
49 @@ -144,7 +144,7 @@ struct rq;
50 */
51 struct prio_array {
52 /* Tasks queued at each priority */
53 - struct list_head queue[MAX_PRIO];
54 + struct list_head queue[MAX_PRIO + 1];
55
56 /*
57 * The bitmap of priorities queued for this array. While the expired
58 @@ -201,7 +201,7 @@ struct rq {
59 unsigned long next_balance;
60 struct mm_struct *prev_mm;
61
62 - struct prio_array *active, *expired, arrays[2];
63 + struct prio_array *active, *expired, *idleprio, arrays[2];
64 unsigned long *dyn_bitmap, *exp_bitmap;
65
66 /*
67 @@ -215,6 +215,8 @@ struct rq {
68 unsigned long iso_ticks;
69 unsigned short iso_refractory;
70
71 + /* Number of idleprio tasks running */
72 + unsigned long nr_idleprio;
73 atomic_t nr_iowait;
74
75 #ifdef CONFIG_SMP
76 @@ -652,6 +654,17 @@ sched_info_switch(struct task_struct *pr
77 #define sched_info_switch(t, next) do { } while (0)
78 #endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
79
80 +static int idleprio_suitable(struct task_struct *p)
81 +{
82 + return (!p->mutexes_held && !freezing(p) && !signal_pending(p) &&
83 + !(p->flags & (PF_NONSLEEP | PF_EXITING)));
84 +}
85 +
86 +static int idleprio(const struct task_struct *p)
87 +{
88 + return (p->prio == MAX_PRIO);
89 +}
90 +
91 static inline int task_queued(struct task_struct *task)
92 {
93 return !list_empty(&task->run_list);
94 @@ -668,7 +681,9 @@ static inline void set_dynamic_bit(struc
95 static void dequeue_task(struct task_struct *p, struct rq *rq)
96 {
97 list_del_init(&p->run_list);
98 - if (list_empty(p->array->queue + p->prio))
99 + if (idleprio_task(p) && idleprio(p))
100 + rq->nr_idleprio--;
101 + else if (list_empty(p->array->queue + p->prio))
102 __clear_bit(p->prio, p->array->prio_bitmap);
103 }
104
105 @@ -809,6 +824,8 @@ static inline int isoprio_suitable(struc
106 return !(p->flags & PF_ISOREF);
107 }
108
109 +static int task_timeslice(struct task_struct *p);
110 +
111 /*
112 * recalc_task_prio determines what priority a non rt_task will be
113 * queued at. If the task has already been running during this runqueue's
114 @@ -842,6 +859,30 @@ static void recalc_task_prio(struct task
115 /* Just about to be demoted to SCHED_NORMAL */
116 p->time_slice = 0;
117 }
118 + } else if (idleprio_task(p)) {
119 + if (idleprio_suitable(p)) {
120 + /*
121 + * If suitable idleprio_tasks are queued at MAX_PRIO
122 + * only on the idleprio array. Their time_slice is
123 + * their full task_timeslice as they cooperatively
124 + * multitask.
125 + */
126 + p->prio = p->normal_prio = MAX_PRIO;
127 + p->array = rq->idleprio;
128 + if (p->time_slice <= 0)
129 + p->time_slice = task_timeslice(p);
130 + return;
131 + }
132 + /*
133 + * If unsuitable idleprio_tasks are queued equivalent to
134 + * nice 19 tasks on the expired array.
135 + */
136 + p->flags &= ~PF_NONSLEEP;
137 + p->prio = p->normal_prio = MAX_PRIO - 1;
138 + p->array = rq->expired;
139 + if (p->time_slice <= 0 || p->time_slice > p->quota)
140 + p->time_slice = p->quota;
141 + return;
142 }
143
144 update_if_moved(p, rq);
145 @@ -878,6 +919,8 @@ static inline void __enqueue_task(struct
146 else
147 recalc_task_prio(p, rq);
148
149 + if (idleprio_task(p) && idleprio(p))
150 + rq->nr_idleprio++;
151 sched_info_queued(p);
152 set_dynamic_bit(p, rq);
153 }
154 @@ -942,6 +985,8 @@ static int task_timeslice(struct task_st
155
156 static void set_load_weight(struct task_struct *p)
157 {
158 + int load_weight;
159 +
160 if (has_rt_policy(p)) {
161 #ifdef CONFIG_SMP
162 if (p == task_rq(p)->migration_thread)
163 @@ -950,12 +995,19 @@ static void set_load_weight(struct task_
164 * Giving its load any weight will skew balancing
165 * adversely.
166 */
167 - p->load_weight = 0;
168 + load_weight = 0;
169 else
170 #endif
171 - p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
172 + load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
173 } else
174 - p->load_weight = task_timeslice(p);
175 + load_weight = task_timeslice(p);
176 + /*
177 + * idleprio tasks have much lower weight than SCHED_NORMAL tasks but
178 + * still need to be weighted to allow balancing to occur.
179 + */
180 + if (likely(!idleprio_task(p)))
181 + load_weight *= PRIO_RANGE;
182 + p->load_weight = load_weight;
183 }
184
185 static inline void
186 @@ -1653,6 +1705,14 @@ out_activate:
187 out_running:
188 p->state = TASK_RUNNING;
189 out:
190 + /*
191 + * Special case when freezing we need to reschedule idleprio tasks
192 + * as SCHED_NORMAL or else they'll never freeze
193 + */
194 + if (idleprio_task(p) && freezing(p) && idleprio(p)) {
195 + dequeue_task(p, rq);
196 + enqueue_task(p, rq);
197 + }
198 task_rq_unlock(rq, &flags);
199
200 return success;
201 @@ -2263,7 +2323,9 @@ skip_bitmap:
202 idx = sched_find_first_bit(array->prio_bitmap);
203 else
204 idx = find_next_bit(array->prio_bitmap, MAX_PRIO, idx);
205 - if (idx >= MAX_PRIO) {
206 + if (idx == MAX_PRIO) {
207 + if (array == busiest->idleprio && busiest->nr_idleprio)
208 + goto found_idleprio;
209 if (array == busiest->expired) {
210 array = busiest->active;
211 goto new_array;
212 @@ -2271,6 +2333,7 @@ skip_bitmap:
213 goto out;
214 }
215
216 +found_idleprio:
217 head = array->queue + idx;
218 curr = head->prev;
219 skip_queue:
220 @@ -2292,6 +2355,17 @@ skip_queue:
221 best_prio_seen |= idx == best_prio;
222 if (curr != head)
223 goto skip_queue;
224 + if (idx == MAX_PRIO) {
225 + /*
226 + * Occurs either when balancing idleprio tasks or
227 + * there really are no more tasks to find.
228 + */
229 + if (array == busiest->expired) {
230 + array = busiest->active;
231 + goto new_array;
232 + }
233 + goto out;
234 + }
235 idx++;
236 goto skip_bitmap;
237 }
238 @@ -2309,6 +2383,13 @@ skip_queue:
239 this_best_prio = idx;
240 if (curr != head)
241 goto skip_queue;
242 + if (idx == MAX_PRIO) {
243 + if (array == busiest->expired) {
244 + array = busiest->active;
245 + goto new_array;
246 + }
247 + goto out;
248 + }
249 idx++;
250 goto skip_bitmap;
251 }
252 @@ -3136,7 +3217,7 @@ void account_user_time(struct task_struc
253
254 /* Add user time to cpustat. */
255 tmp = cputime_to_cputime64(cputime);
256 - if (TASK_NICE(p) > 0)
257 + if (TASK_NICE(p) > 0 || idleprio_task(p))
258 cpustat->nice = cputime64_add(cpustat->nice, tmp);
259 else
260 cpustat->user = cputime64_add(cpustat->user, tmp);
261 @@ -3351,6 +3432,28 @@ static void reset_prio_levels(struct rq
262 }
263
264 /*
265 + * Only tasks running are SCHED_IDLEPRIO. Set the active array to the
266 + * idleprio array and if it isn't already active
267 + */
268 +static struct task_struct *next_idleprio_task(struct rq *rq)
269 +{
270 + struct prio_array *array = rq->active;
271 + struct list_head *queue;
272 +
273 + if (array != rq->idleprio) {
274 + rq->active = rq->idleprio;
275 + rq->expired = array;
276 + array = rq->active;
277 + rq->exp_bitmap = rq->expired->prio_bitmap;
278 + rq->dyn_bitmap = rq->active->prio_bitmap;
279 + }
280 + rq->prio_rotation++;
281 + reset_prio_levels(rq);
282 + queue = array->queue + MAX_PRIO;
283 + return list_entry(queue->next, struct task_struct, run_list);
284 +}
285 +
286 +/*
287 * next_dynamic_task finds the next suitable dynamic task.
288 */
289 static inline struct task_struct *next_dynamic_task(struct rq *rq, int idx)
290 @@ -3361,6 +3464,8 @@ static inline struct task_struct *next_d
291 int nstatic;
292
293 retry:
294 + if (unlikely(rq->nr_running == rq->nr_idleprio))
295 + return next_idleprio_task(rq);
296 if (idx >= MAX_PRIO) {
297 /* There are no more tasks in the active array. Swap arrays */
298 array = rq->expired;
299 @@ -3451,8 +3556,10 @@ need_resched_nonpreemptible:
300 unlikely(signal_pending(prev))))
301 prev->state = TASK_RUNNING;
302 else {
303 - if (prev->state == TASK_UNINTERRUPTIBLE)
304 + if (prev->state == TASK_UNINTERRUPTIBLE) {
305 + prev->flags |= PF_NONSLEEP;
306 rq->nr_uninterruptible++;
307 + }
308 deactivate_task(prev, rq);
309 }
310 }
311 @@ -3994,7 +4101,8 @@ void set_user_nice(struct task_struct *p
312 * If the task increased its priority or is running and
313 * lowered its priority, then reschedule its CPU:
314 */
315 - if (delta < 0 || (delta > 0 && task_running(rq, p)))
316 + if (delta < 0 || ((delta > 0 || idleprio_task(p)) &&
317 + task_running(rq, p)))
318 resched_task(rq->curr);
319 }
320 out_unlock:
321 @@ -4195,6 +4303,11 @@ recheck:
322 return -EPERM;
323 }
324
325 + if (!(p->mm) && policy == SCHED_IDLEPRIO) {
326 + /* Don't allow kernel threads to be SCHED_IDLEPRIO. */
327 + return -EINVAL;
328 + }
329 +
330 retval = security_task_setscheduler(p, policy, param);
331 if (retval)
332 return retval;
333 @@ -4520,12 +4633,18 @@ asmlinkage long sys_sched_yield(void)
334 struct prio_array *old_array = p->array;
335 int old_prio = p->prio;
336
337 + if (idleprio_task(p)) {
338 + dequeue_task(p, rq);
339 + enqueue_task(p, rq);
340 + goto out_release;
341 + }
342 /* p->prio will be updated in requeue_task via queue_expired */
343 if (!rt_task(p))
344 p->array = rq->expired;
345 requeue_task(p, rq, old_array, old_prio);
346 }
347
348 +out_release:
349 /*
350 * Since we are going to call schedule() anyway, there's
351 * no need to preempt or enable interrupts:
352 @@ -4678,6 +4797,7 @@ asmlinkage long sys_sched_get_priority_m
353 case SCHED_NORMAL:
354 case SCHED_BATCH:
355 case SCHED_ISO:
356 + case SCHED_IDLEPRIO:
357 ret = 0;
358 break;
359 }
360 @@ -4703,6 +4823,7 @@ asmlinkage long sys_sched_get_priority_m
361 case SCHED_NORMAL:
362 case SCHED_BATCH:
363 case SCHED_ISO:
364 + case SCHED_IDLEPRIO:
365 ret = 0;
366 }
367 return ret;
368 @@ -6812,8 +6933,10 @@ void __init sched_init(void)
369 lockdep_set_class(&rq->lock, &rq->rq_lock_key);
370 rq->iso_ticks = 0;
371 rq->nr_running = 0;
372 + rq->nr_idleprio = 0;
373 rq->prio_rotation = 0;
374 rq->active = rq->arrays;
375 + rq->idleprio = rq->active;
376 rq->expired = rq->arrays + 1;
377 reset_prio_levels(rq);
378 rq->dyn_bitmap = rq->active->prio_bitmap;
379 @@ -6836,7 +6959,7 @@ void __init sched_init(void)
380 for (j = 0; j < 2; j++) {
381
382 array = rq->arrays + j;
383 - for (k = 0; k < MAX_PRIO; k++)
384 + for (k = 0; k <= MAX_PRIO; k++)
385 INIT_LIST_HEAD(array->queue + k);
386 bitmap_zero(array->prio_bitmap, MAX_PRIO);
387 /* delimiter for bitsearch */