diff -urpN -X /home/fletch/.diff.exclude 380-lockmeter/kernel/sched.c 420-sched_interactive/kernel/sched.c
--- 380-lockmeter/kernel/sched.c	Tue Sep  2 10:14:11 2003
+++ 420-sched_interactive/kernel/sched.c	Tue Sep  2 10:21:57 2003
@@ -88,6 +88,8 @@ int node_threshold = 125;
 #define STARVATION_LIMIT	(starvation_limit)
 #define NODE_THRESHOLD		(node_threshold)
 
+#define TIMESLICE_GRANULARITY (HZ/20 ?: 1)
+
 /*
  * If a task is 'interactive' then we reinsert it in the active
  * array after it has expired its current timeslice. (it will not
@@ -1283,6 +1285,27 @@ void scheduler_tick(int user_ticks, int 
 			enqueue_task(p, rq->expired);
 		} else
 			enqueue_task(p, rq->active);
+	} else {
+		/*
+		 * Prevent a too long timeslice allowing a task to monopolize
+		 * the CPU. We do this by splitting up the timeslice into
+		 * smaller pieces.
+		 *
+		 * Note: this does not mean the task's timeslices expire or
+		 * get lost in any way, they just might be preempted by
+		 * another task of equal priority. (one with higher
+		 * priority would have preempted this task already.) We
+		 * requeue this task to the end of the list on this priority
+		 * level, which is in essence a round-robin of tasks with
+		 * equal priority.
+		 */
+		if (!(p->time_slice % TIMESLICE_GRANULARITY) &&
+			       		(p->array == rq->active)) {
+			dequeue_task(p, rq->active);
+			set_tsk_need_resched(p);
+			p->prio = effective_prio(p);
+			enqueue_task(p, rq->active);
+		}
 	}
 out_unlock:
 	spin_unlock(&rq->lock);