[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <200703221304.58011.kernel@kolivas.org>
Date: Thu, 22 Mar 2007 13:04:57 +1100
From: Con Kolivas <kernel@...ivas.org>
To: Jeffrey Hundstad <jeffrey.hundstad@...u.edu>
Cc: Artur Skawina <art_k@...pl>,
linux list <linux-kernel@...r.kernel.org>,
ck list <ck@....kolivas.org>, Ingo Molnar <mingo@...e.hu>,
Andrew Morton <akpm@...ux-foundation.org>
Subject: [PATCH] sched: rsdl check for niced tasks lowering prio level
Here is the best fix for the bug pointed out. Thanks.
I'll try and find pc time to wrap these two patches together and make a v0.32
available.
---
Ensure niced tasks are not inappropriately limiting sleeping unniced tasks
by explicitly checking what the best static priority that has run this
major rotation was.
Reimplement SCHED_BATCH using this check.
Signed-off-by: Con Kolivas <kernel@...ivas.org>
---
kernel/sched.c | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
Index: linux-2.6.21-rc4-mm1/kernel/sched.c
===================================================================
--- linux-2.6.21-rc4-mm1.orig/kernel/sched.c 2007-03-22 12:44:05.000000000 +1100
+++ linux-2.6.21-rc4-mm1/kernel/sched.c 2007-03-22 12:58:26.000000000 +1100
@@ -201,8 +201,11 @@ struct rq {
struct prio_array *active, *expired, arrays[2];
unsigned long *dyn_bitmap, *exp_bitmap;
- int prio_level;
- /* The current dynamic priority level this runqueue is at */
+ int prio_level, best_static_prio;
+ /*
+ * The current dynamic priority level this runqueue is at, and the
+ * best static priority queued this major rotation.
+ */
unsigned long prio_rotation;
/* How many times we have rotated the priority queue */
@@ -704,16 +707,24 @@ static inline int entitled_slot(int stat
/*
* Find the first unused slot by this task that is also in its prio_matrix
- * level.
+ * level. Ensure that the prio_level is not unnecessarily low by checking
+ * that best_static_prio this major rotation was not a niced task.
+ * SCHED_BATCH tasks do not perform this check so they do not induce
+ * latencies in tasks of any nice level.
*/
static inline int next_entitled_slot(struct task_struct *p, struct rq *rq)
{
- DECLARE_BITMAP(tmp, PRIO_RANGE);
+ if (p->static_prio < rq->best_static_prio && p->policy != SCHED_BATCH)
+ return SCHED_PRIO(find_first_zero_bit(p->bitmap, PRIO_RANGE));
+ else {
+ DECLARE_BITMAP(tmp, PRIO_RANGE);
- bitmap_or(tmp, p->bitmap, prio_matrix[USER_PRIO(p->static_prio)],
- PRIO_RANGE);
- return SCHED_PRIO(find_next_zero_bit(tmp, PRIO_RANGE,
- USER_PRIO(rq->prio_level)));
+ bitmap_or(tmp, p->bitmap,
+ prio_matrix[USER_PRIO(p->static_prio)],
+ PRIO_RANGE);
+ return SCHED_PRIO(find_next_zero_bit(tmp, PRIO_RANGE,
+ USER_PRIO(rq->prio_level)));
+ }
}
static void queue_expired(struct task_struct *p, struct rq *rq)
@@ -3315,6 +3326,7 @@ static inline void major_prio_rotation(s
rq->active = new_array;
rq->exp_bitmap = rq->expired->prio_bitmap;
rq->dyn_bitmap = rq->active->prio_bitmap;
+ rq->best_static_prio = MAX_PRIO;
rq->prio_rotation++;
}
@@ -3640,10 +3652,12 @@ need_resched_nonpreemptible:
}
switch_tasks:
if (next == rq->idle) {
+ rq->best_static_prio = MAX_PRIO;
rq->prio_level = MAX_RT_PRIO;
rq->prio_rotation++;
schedstat_inc(rq, sched_goidle);
- }
+ } else if (next->static_prio < rq->best_static_prio)
+ rq->best_static_prio = next->static_prio;
prefetch(next);
prefetch_stack(next);
clear_tsk_need_resched(prev);
@@ -7093,6 +7107,7 @@ void __init sched_init(void)
lockdep_set_class(&rq->lock, &rq->rq_lock_key);
rq->nr_running = 0;
rq->prio_rotation = 0;
+ rq->best_static_prio = MAX_PRIO;
rq->prio_level = MAX_RT_PRIO;
rq->active = rq->arrays;
rq->expired = rq->arrays + 1;
--
-ck
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists