[LWN Logo]

Date:	Sat, 24 Jul 1999 20:05:55 +0200 (CEST)
From:	Rik van Riel <riel@nl.linux.org>
To:	Linux Kernel <linux-kernel@vger.rutgers.edu>
Subject: [PATCH] SCHED_IDLE

Hi,

I believe I have created a rather 'safe' SCHED_IDLE patch
now. I haven't run it yet (my machine is slow and busy with
something large at the moment), but I have verified that the
files in question compile and the patch looks trivial enough ;)

I hope you enjoy it -- and don't forget to grab the changed
rtnice utility: http://www.nl.linux.org/~riel/patches/rtnice.c

have fun,

Rik -- Open Source: you deserve to be in control of your data.
+-------------------------------------------------------------------+
| Le Reseau netwerksystemen BV:               http://www.reseau.nl/ |
| Linux Memory Management site:   http://www.linux.eu.org/Linux-MM/ |
| Nederlandse Linux documentatie:          http://www.nl.linux.org/ |
+-------------------------------------------------------------------+

--- linux/kernel/sched.c.12	Sat Jul 24 16:41:57 1999
+++ linux/kernel/sched.c	Sat Jul 24 19:56:32 1999
@@ -124,6 +124,13 @@
 	char __pad [SMP_CACHE_BYTES];
 } aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task,0}}};
 
+/*
+ * SCHED_IDLE defines.
+ */
+sched_idle_t sched_idle = {
+	0,	/* disabled, use sysctl to enable */
+};
+
 #define cpu_curr(cpu) aligned_data[(cpu)].schedule_data.curr
 
 struct kernel_stat kstat = { 0 };
@@ -166,8 +173,7 @@
 	 * into account).
 	 */
 	if (p->policy != SCHED_OTHER) {
-		weight = 1000 + p->rt_priority;
-		goto out;
+		goto rt_or_idle;
 	}
 
 	/*
@@ -181,6 +187,7 @@
 	if (!weight)
 		goto out;
 			
+calculate_bonus:
 #ifdef __SMP__
 	/* Give a largish advantage to the same processor...   */
 	/* (this is equivalent to penalizing other processors) */
@@ -195,6 +202,28 @@
 
 out:
 	return weight;
+
+rt_or_idle:
+	if (p->policy == SCHED_IDLE) {
+		weight = p->counter;
+		/* if it can deadlock the system, we'll avoid deadlock by
+		 * temporarily giving the task a higher priority.
+		 * We don't want SCHED_IDLE tasks to take advantage of this
+		 * situation however, so the task pays a heavy penalty.
+		 *   -- Rik
+		 */
+		if (p->lock_depth >= 0 || signal_pending(p)) {
+			p->counter >>= 1;
+		} else {
+			/* requirement: weight + bonus < 0 !!! */
+			weight -= HZ;
+		}
+		goto calculate_bonus;
+	} else {  /* SCHED_FIFO or SCHED_RR */
+		weight = 1000 + p->rt_priority;
+	}
+	goto out;
+
 }
 
 /*
@@ -1714,7 +1743,7 @@
 	else {
 		retval = -EINVAL;
 		if (policy != SCHED_FIFO && policy != SCHED_RR &&
-				policy != SCHED_OTHER)
+				policy != SCHED_OTHER && policy != SCHED_IDLE)
 			goto out_unlock;
 	}
 	
@@ -1725,12 +1754,19 @@
 	retval = -EINVAL;
 	if (lp.sched_priority < 0 || lp.sched_priority > 99)
 		goto out_unlock;
-	if ((policy == SCHED_OTHER) != (lp.sched_priority == 0))
+	if ((policy == SCHED_OTHER || policy == SCHED_IDLE) &&
+			(lp.sched_priority != 0))
 		goto out_unlock;
 
 	retval = -EPERM;
 	if ((policy == SCHED_FIFO || policy == SCHED_RR) && 
 	    !capable(CAP_SYS_NICE))
+		goto out_unlock;
+	if (policy == SCHED_IDLE && (!sched_idle.enabled || 
+			!capable(CAP_SYS_NICE)))
+		goto out_unlock;
+	if (p->policy == SCHED_IDLE && policy != SCHED_IDLE &&
+			!capable(CAP_SYS_NICE))
 		goto out_unlock;
 	if ((current->euid != p->euid) && (current->euid != p->uid) &&
 	    !capable(CAP_SYS_NICE))
--- linux/kernel/sysctl.c.12	Sat Jul 24 19:38:16 1999
+++ linux/kernel/sysctl.c	Sat Jul 24 19:33:41 1999
@@ -210,6 +210,8 @@
 #endif
 	{KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int),
 	 0644, NULL, &proc_dointvec},
+	{KERN_SCHED_IDLE_EN, "sched_idle_enable", &sched_idle.enabled, sizeof(int),
+	 0644, NULL, &proc_dointvec},
 	{0}
 };
 
--- linux/include/linux/sysctl.h.12	Sat Jul 24 18:55:26 1999
+++ linux/include/linux/sysctl.h	Sat Jul 24 19:13:38 1999
@@ -101,7 +101,8 @@
 	KERN_MSGMAX=35,         /* int: Maximum size of a messege */
 	KERN_MSGMNB=36,         /* int: Maximum message queue size */
 	KERN_MSGPOOL=37,        /* int: Maximum system message pool size */
-	KERN_MAX_THREADS=38     /* int: Maximum nr of threads in the system */
+	KERN_MAX_THREADS=38,    /* int: Maximum nr of threads in the system */
+	KERN_SCHED_IDLE_EN=39	/* int: SCHED_IDLE enabled for mortals? */
 };
 
 
--- linux/include/linux/sched.h.12	Sat Jul 24 16:40:55 1999
+++ linux/include/linux/sched.h	Sat Jul 24 19:54:14 1999
@@ -88,6 +88,7 @@
 #define SCHED_OTHER		0
 #define SCHED_FIFO		1
 #define SCHED_RR		2
+#define SCHED_IDLE		3
 
 /*
  * This is an additional bit set when we want to
@@ -98,6 +99,16 @@
 struct sched_param {
 	int sched_priority;
 };
+
+/*
+ * SCHED_IDLE control structure. For now it only controls
+ * whether SCHED_IDLE is enabled for mere mortals...
+ */
+typedef struct sched_idle_t
+{
+	int enabled;
+} sched_idle_t;
+extern sched_idle_t sched_idle;
 
 #ifndef NULL
 #define NULL ((void *) 0)


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/