Annotation of /trunk/kernel26-alx/patches-2.6.20-r6/0007-2.6.20-sched-idleprio-1.1.patch
Parent Directory | Revision Log
Revision 1175 -
(hide annotations)
(download)
Thu Oct 14 12:15:46 2010 UTC (13 years, 11 months ago) by niro
File size: 7317 byte(s)
Thu Oct 14 12:15:46 2010 UTC (13 years, 11 months ago) by niro
File size: 7317 byte(s)
-2.6.20-alx-r6 new magellan 0.5.2 kernel
1 | niro | 1175 | 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 | Bugfixes by Sergio Cerlesi & Serge Belyshev. | ||
7 | |||
8 | Signed-off-by: Con Kolivas <kernel@kolivas.org> | ||
9 | |||
10 | include/linux/init_task.h | 6 ++-- | ||
11 | include/linux/sched.h | 9 ++++-- | ||
12 | kernel/sched.c | 68 +++++++++++++++++++++++++++++++++++++++++----- | ||
13 | 3 files changed, 70 insertions(+), 13 deletions(-) | ||
14 | |||
15 | Index: linux-2.6.20-ck1/include/linux/init_task.h | ||
16 | =================================================================== | ||
17 | --- linux-2.6.20-ck1.orig/include/linux/init_task.h 2007-02-16 19:01:31.000000000 +1100 | ||
18 | +++ linux-2.6.20-ck1/include/linux/init_task.h 2007-02-16 19:01:31.000000000 +1100 | ||
19 | @@ -99,9 +99,9 @@ extern struct group_info init_groups; | ||
20 | .usage = ATOMIC_INIT(2), \ | ||
21 | .flags = 0, \ | ||
22 | .lock_depth = -1, \ | ||
23 | - .prio = MAX_PRIO-20, \ | ||
24 | - .static_prio = MAX_PRIO-20, \ | ||
25 | - .normal_prio = MAX_PRIO-20, \ | ||
26 | + .prio = MAX_PRIO-21, \ | ||
27 | + .static_prio = MAX_PRIO-21, \ | ||
28 | + .normal_prio = MAX_PRIO-21, \ | ||
29 | .policy = SCHED_NORMAL, \ | ||
30 | .cpus_allowed = CPU_MASK_ALL, \ | ||
31 | .mm = NULL, \ | ||
32 | Index: linux-2.6.20-ck1/include/linux/sched.h | ||
33 | =================================================================== | ||
34 | --- linux-2.6.20-ck1.orig/include/linux/sched.h 2007-02-16 19:01:31.000000000 +1100 | ||
35 | +++ linux-2.6.20-ck1/include/linux/sched.h 2007-02-16 19:01:31.000000000 +1100 | ||
36 | @@ -35,10 +35,11 @@ | ||
37 | #define SCHED_RR 2 | ||
38 | #define SCHED_BATCH 3 | ||
39 | #define SCHED_ISO 4 | ||
40 | +#define SCHED_IDLEPRIO 5 | ||
41 | |||
42 | #ifdef __KERNEL__ | ||
43 | |||
44 | -#define SCHED_MAX SCHED_ISO | ||
45 | +#define SCHED_MAX SCHED_IDLEPRIO | ||
46 | #define SCHED_RANGE(policy) ((policy) <= SCHED_MAX) | ||
47 | |||
48 | struct sched_param { | ||
49 | @@ -529,8 +530,9 @@ struct signal_struct { | ||
50 | #define MAX_RT_PRIO MAX_USER_RT_PRIO | ||
51 | #define ISO_PRIO (MAX_RT_PRIO - 1) | ||
52 | |||
53 | -#define MAX_PRIO (MAX_RT_PRIO + 40) | ||
54 | -#define MIN_USER_PRIO (MAX_PRIO - 1) | ||
55 | +#define MAX_PRIO (MAX_RT_PRIO + 41) | ||
56 | +#define MIN_USER_PRIO (MAX_PRIO - 2) | ||
57 | +#define IDLEPRIO_PRIO (MAX_PRIO - 1) | ||
58 | |||
59 | #define rt_prio(prio) unlikely((prio) < ISO_PRIO) | ||
60 | #define rt_task(p) rt_prio((p)->prio) | ||
61 | @@ -539,6 +541,7 @@ struct signal_struct { | ||
62 | (policy) == SCHED_RR) | ||
63 | #define has_rt_policy(p) unlikely(is_rt_policy((p)->policy)) | ||
64 | #define iso_task(p) (unlikely((p)->policy == SCHED_ISO)) | ||
65 | +#define idleprio_task(p) (unlikely((p)->policy == SCHED_IDLEPRIO)) | ||
66 | |||
67 | /* | ||
68 | * Some day this will be a full-fledged user tracking system.. | ||
69 | Index: linux-2.6.20-ck1/kernel/sched.c | ||
70 | =================================================================== | ||
71 | --- linux-2.6.20-ck1.orig/kernel/sched.c 2007-02-16 19:01:31.000000000 +1100 | ||
72 | +++ linux-2.6.20-ck1/kernel/sched.c 2007-02-16 19:01:31.000000000 +1100 | ||
73 | @@ -696,6 +696,12 @@ static void set_load_weight(struct task_ | ||
74 | else | ||
75 | #endif | ||
76 | p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority); | ||
77 | + } else if (idleprio_task(p)) { | ||
78 | + /* | ||
79 | + * We want idleprio_tasks to have a presence on weighting but | ||
80 | + * as small as possible | ||
81 | + */ | ||
82 | + p->load_weight = 1; | ||
83 | } else | ||
84 | p->load_weight = TASK_LOAD_WEIGHT(p); | ||
85 | } | ||
86 | @@ -872,6 +878,17 @@ static inline void recalc_task_prio(stru | ||
87 | continue_slice(p); | ||
88 | } | ||
89 | |||
90 | +static inline int idleprio_suitable(struct task_struct *p) | ||
91 | +{ | ||
92 | + return (!p->mutexes_held && !freezing(p) && | ||
93 | + !(p->flags & (PF_NONSLEEP | PF_EXITING))); | ||
94 | +} | ||
95 | + | ||
96 | +static inline int idleprio(const struct task_struct *p) | ||
97 | +{ | ||
98 | + return (p->prio == IDLEPRIO_PRIO); | ||
99 | +} | ||
100 | + | ||
101 | /* | ||
102 | * __normal_prio - dynamic priority dependent on bonus. | ||
103 | * The priority normally decreases by one each RR_INTERVAL. | ||
104 | @@ -895,6 +912,18 @@ static inline int __normal_prio(struct t | ||
105 | return ISO_PRIO; | ||
106 | } | ||
107 | |||
108 | + if (idleprio_task(p)) { | ||
109 | + if (unlikely(!idleprio_suitable(p))) { | ||
110 | + /* | ||
111 | + * If idleprio tasks are holding a semaphore, mutex, | ||
112 | + * or being frozen, schedule at a normal priority. | ||
113 | + */ | ||
114 | + p->time_slice = p->slice % RR_INTERVAL ? : RR_INTERVAL; | ||
115 | + return MIN_USER_PRIO; | ||
116 | + } | ||
117 | + return IDLEPRIO_PRIO; | ||
118 | + } | ||
119 | + | ||
120 | full_slice = slice(p); | ||
121 | if (full_slice > p->slice) | ||
122 | used_slice = full_slice - p->slice; | ||
123 | @@ -1544,6 +1573,8 @@ out_activate: | ||
124 | out_running: | ||
125 | p->state = TASK_RUNNING; | ||
126 | out: | ||
127 | + if (idleprio_task(p) && freezing(p) && idleprio(p)) | ||
128 | + requeue_task(p, rq, effective_prio(p)); | ||
129 | task_rq_unlock(rq, &flags); | ||
130 | |||
131 | return success; | ||
132 | @@ -2941,7 +2972,7 @@ void account_user_time(struct task_struc | ||
133 | |||
134 | /* Add user time to cpustat. */ | ||
135 | tmp = cputime_to_cputime64(cputime); | ||
136 | - if (TASK_NICE(p) > 0) | ||
137 | + if (TASK_NICE(p) > 0 || idleprio_task(p)) | ||
138 | cpustat->nice = cputime64_add(cpustat->nice, tmp); | ||
139 | else | ||
140 | cpustat->user = cputime64_add(cpustat->user, tmp); | ||
141 | @@ -3051,9 +3082,12 @@ static void task_running_tick(struct rq | ||
142 | } else | ||
143 | p->flags &= ~PF_ISOREF; | ||
144 | } else { | ||
145 | - /* SCHED_FIFO tasks never run out of timeslice. */ | ||
146 | - if (unlikely(p->policy == SCHED_FIFO)) | ||
147 | - goto out_unlock; | ||
148 | + if (idleprio_task(p) && !idleprio(p) && idleprio_suitable(p)) | ||
149 | + set_tsk_need_resched(p); | ||
150 | + else | ||
151 | + /* SCHED_FIFO tasks never run out of timeslice. */ | ||
152 | + if (unlikely(p->policy == SCHED_FIFO)) | ||
153 | + goto out_unlock; | ||
154 | } | ||
155 | |||
156 | debit = ns_diff(rq->most_recent_timestamp, p->timestamp); | ||
157 | @@ -3219,11 +3253,23 @@ dependent_sleeper(int this_cpu, struct r | ||
158 | if ((jiffies % DEF_TIMESLICE) > | ||
159 | (sd->per_cpu_gain * DEF_TIMESLICE / 100)) | ||
160 | ret = 1; | ||
161 | + else if (idleprio(p)) | ||
162 | + ret = 1; | ||
163 | } else { | ||
164 | if (smt_curr->static_prio < p->static_prio && | ||
165 | !TASK_PREEMPTS_CURR(p, smt_rq) && | ||
166 | smt_slice(smt_curr, sd) > slice(p)) | ||
167 | ret = 1; | ||
168 | + else if (idleprio(p) && !idleprio_task(smt_curr) && | ||
169 | + smt_curr->slice * sd->per_cpu_gain > | ||
170 | + slice(smt_curr)) { | ||
171 | + /* | ||
172 | + * With idleprio tasks they run just the last | ||
173 | + * per_cpu_gain percent of the smt task's | ||
174 | + * slice. | ||
175 | + */ | ||
176 | + ret = 1; | ||
177 | + } | ||
178 | } | ||
179 | unlock: | ||
180 | spin_unlock(&smt_rq->lock); | ||
181 | @@ -3884,8 +3930,9 @@ void set_user_nice(struct task_struct *p | ||
182 | * If the task increased its priority or is running and | ||
183 | * lowered its priority, then reschedule its CPU: | ||
184 | */ | ||
185 | - if (delta < 0 || (delta > 0 && task_running(rq, p))) | ||
186 | - resched_task(rq->curr); | ||
187 | + if (delta < 0 || ((delta > 0 || idleprio_task(p)) && | ||
188 | + task_running(rq, p))) | ||
189 | + resched_task(rq->curr); | ||
190 | } | ||
191 | out_unlock: | ||
192 | task_rq_unlock(rq, &flags); | ||
193 | @@ -4086,6 +4133,11 @@ recheck: | ||
194 | return -EPERM; | ||
195 | } | ||
196 | |||
197 | + if (!(p->mm) && policy == SCHED_IDLEPRIO) { | ||
198 | + /* Don't allow kernel threads to be SCHED_IDLEPRIO. */ | ||
199 | + return -EINVAL; | ||
200 | + } | ||
201 | + | ||
202 | retval = security_task_setscheduler(p, policy, param); | ||
203 | if (retval) | ||
204 | return retval; | ||
205 | @@ -4407,7 +4459,7 @@ asmlinkage long sys_sched_yield(void) | ||
206 | schedstat_inc(rq, yld_cnt); | ||
207 | current->slice = slice(current); | ||
208 | current->time_slice = rr_interval(current); | ||
209 | - if (likely(!rt_task(current))) | ||
210 | + if (likely(!rt_task(current) && !idleprio(current))) | ||
211 | newprio = MIN_USER_PRIO; | ||
212 | |||
213 | requeue_task(current, rq, newprio); | ||
214 | @@ -4564,6 +4616,7 @@ asmlinkage long sys_sched_get_priority_m | ||
215 | case SCHED_NORMAL: | ||
216 | case SCHED_BATCH: | ||
217 | case SCHED_ISO: | ||
218 | + case SCHED_IDLEPRIO: | ||
219 | ret = 0; | ||
220 | break; | ||
221 | } | ||
222 | @@ -4589,6 +4642,7 @@ asmlinkage long sys_sched_get_priority_m | ||
223 | case SCHED_NORMAL: | ||
224 | case SCHED_BATCH: | ||
225 | case SCHED_ISO: | ||
226 | + case SCHED_IDLEPRIO: | ||
227 | ret = 0; | ||
228 | } | ||
229 | return ret; |