Re: [PATCH] SCHED_IDLE (2.2.10 version)

Rik van Riel (riel@nl.linux.org)
Sun, 25 Jul 1999 18:51:10 +0200 (CEST)


On Sat, 24 Jul 1999, Jeff Lightfoot wrote:

[SCHED_IDLE patch]
> If you port it to 2.2.x, I won't be upset. :-) Rejects in
> sysctl.c and sysctl.h

OK, here it is (including a little bugfix that will
be included right now into the 2.3 version on my site).

The bugs in the last version:
- permission check somehow fails (in setscheduler())
--> extra braces should help ??
- if HZ==1024, the idle task may get higher priority than
your SCHED_IDLE patch --> fixed in goodness
- sys_sched_get_priority_{min,max}() didn't know about
SCHED_IDLE yet

Furthermore, I have very good news. The patch (the old and
'buggy one') runs wonderfully on my machine with 2.3.12-pre1.
No problems whatsoever... Phewww :)

cheers,

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-2.2.10/kernel/sched.c.orig Sun Jul 25 14:40:48 1999
+++ linux-2.2.10/kernel/sched.c Sun Jul 25 18:43:43 1999
@@ -108,6 +108,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 };
@@ -151,8 +158,7 @@
* into account).
*/
if (p->policy != SCHED_OTHER) {
- weight = 1000 + p->rt_priority;
- goto out;
+ goto rt_or_idle;
}

/*
@@ -166,6 +172,7 @@
if (!weight)
goto out;

+calculate_bonus:
#ifdef __SMP__
/* Give a largish advantage to the same processor... */
/* (this is equivalent to penalizing other processors) */
@@ -180,6 +187,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 -= 999;
+ }
+ goto calculate_bonus;
+ } else { /* SCHED_FIFO or SCHED_RR */
+ weight = 1000 + p->rt_priority;
+ }
+ goto out;
+
}

/*
@@ -1738,7 +1767,7 @@
else {
retval = -EINVAL;
if (policy != SCHED_FIFO && policy != SCHED_RR &&
- policy != SCHED_OTHER)
+ policy != SCHED_OTHER && policy != SCHED_IDLE)
goto out_unlock;
}

@@ -1749,13 +1778,20 @@
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))
goto out_unlock;
@@ -1864,6 +1900,7 @@
ret = 99;
break;
case SCHED_OTHER:
+ case SCHED_IDLE:
ret = 0;
break;
}
@@ -1880,6 +1917,7 @@
ret = 1;
break;
case SCHED_OTHER:
+ case SCHED_IDLE:
ret = 0;
}
return ret;
--- linux-2.2.10/include/linux/sched.h.orig Sun Jul 25 14:40:47 1999
+++ linux-2.2.10/include/linux/sched.h Sun Jul 25 18:39:51 1999
@@ -86,6 +86,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
@@ -96,6 +97,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/