idle task was __cliing the local CPU even if not needed

Andrea Arcangeli (andrea@e-mind.com)
Tue, 15 Dec 1998 20:29:09 +0100 (CET)


With this patch applyed the idle task run schedule() only if need_resched
is true. It seems that now under high IDE load my ppp link stopped to
drop/[not send] packes as it was used to do.

Index: linux/arch/i386/kernel/process.c
diff -u linux/arch/i386/kernel/process.c:1.1.3.1 linux/arch/i386/kernel/process.c:1.1.1.1.2.17
--- linux/arch/i386/kernel/process.c:1.1.3.1 Sat Dec 5 11:12:00 1998
+++ linux/arch/i386/kernel/process.c Tue Dec 15 20:07:08 1998
@@ -2,6 +2,10 @@
* linux/arch/i386/kernel/process.c
*
* Copyright (C) 1995 Linus Torvalds
+ *
+ * Optimized the idle task and other minor fixes. This will avoid a
+ * lot of local __cli() that make no sense when the CPU is idle.
+ * 15 Dec 1998, Andrea Arcangeli
*/

/*
@@ -73,11 +77,11 @@

#ifndef __SMP__

+#ifdef CONFIG_APM
static void hard_idle(void)
{
while (!current->need_resched) {
if (boot_cpu_data.hlt_works_ok && !hlt_counter) {
-#ifdef CONFIG_APM
/* If the APM BIOS is not enabled, or there
is an error calling the idle routine, we
should hlt if possible. We need to check
@@ -87,38 +91,49 @@
if (!apm_do_idle() && !current->need_resched)
__asm__("hlt");
end_bh_atomic();
-#else
- __asm__("hlt");
-#endif
}
if (current->need_resched)
break;
schedule();
}
-#ifdef CONFIG_APM
apm_do_busy();
-#endif
}
+#endif

/*
* The idle loop on a uniprocessor i386..
*/
static int cpu_idle(void *unused)
{
+#ifdef CONFIG_APM
unsigned long start_idle = jiffies;
+#endif
+ long *need_resched = &current->need_resched;

/* endless idle loop with no priority at all */
+ current->priority = 0;
+ /* before change this, see reschedule_idle() in kernel/sched.c */
+ current->counter = -4;
for (;;) {
- if (jiffies - start_idle > HARD_IDLE_TIMEOUT)
+#ifdef CONFIG_APM
+ if (jiffies - start_idle >= HARD_IDLE_TIMEOUT)
+ {
hard_idle();
+ start_idle = jiffies - HARD_IDLE_TIMEOUT;
+ }
else {
- if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
+#endif
+ if (boot_cpu_data.hlt_works_ok && !hlt_counter && !*need_resched)
__asm__("hlt");
+
}
- if (current->need_resched)
+ if (*need_resched)
+ {
+ schedule();
+#ifdef CONFIG_APM
start_idle = jiffies;
- current->policy = SCHED_YIELD;
- schedule();
+#endif
+ }
check_pgt_cache();
}
}
@@ -131,13 +146,17 @@

int cpu_idle(void *unused)
{
+ long *need_resched = &current->need_resched;

/* endless idle loop with no priority at all */
+ current->priority = 0;
+ /* before change this, see reschedule_idle() in kernel/sched.c */
+ current->counter = -4;
while(1) {
- if (current_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
+ if (current_cpu_data.hlt_works_ok && !hlt_counter && !*need_resched)
__asm__("hlt");
- current->policy = SCHED_YIELD;
- schedule();
+ if (*need_resched)
+ schedule();
check_pgt_cache();
}
}
Index: linux/init/main.c
diff -u linux/init/main.c:1.1.3.1 linux/init/main.c:1.1.1.1.2.4
--- linux/init/main.c:1.1.3.1 Sat Dec 5 11:17:26 1998
+++ linux/init/main.c Tue Dec 15 19:15:51 1998
@@ -1182,6 +1182,8 @@
*/
smp_init();
kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ /* tell the idle task to reschedule idle as first thing to do -arca */
+ current->need_resched = 1;
cpu_idle(NULL);
}

Index: linux/kernel/sched.c
diff -u linux/kernel/sched.c:1.1.3.1 linux/kernel/sched.c:1.1.1.1.2.27
--- linux/kernel/sched.c:1.1.3.1 Sat Dec 5 11:17:28 1998
+++ linux/kernel/sched.c Tue Dec 15 20:07:24 1998
@@ -7,6 +7,8 @@
* 1996-12-23 Modified by Dave Grothe to fix bugs in semaphores and
* make semaphores SMP safe
* 1997-01-28 Modified by Finn Arne Gangstad to make timers scale better.
+ * 1998-11-19 Implemented schedule_timeout() and related stuff
+ * by Andrea Arcangeli
*/

/*
@@ -93,7 +96,7 @@

static inline void reschedule_idle(struct task_struct * p)
{
-
+ struct task_struct * this = current;
/*
* For SMP, we try to see if the CPU the task used
* to run on is idle..
@@ -130,15 +133,8 @@
}
#endif
#endif
- /*
- * If the current process is the idle one, we must reschedule ASAP.
- * Checking for p->counter >= current->counter we have the idle task
- * check implicit.
- * -arca
- */
- if (/* implicit !current->pid || */ p->counter >= current->counter ||
- p->policy != SCHED_OTHER)
- current->need_resched = 1;
+ if (p->counter > this->counter + 3 || p->policy != SCHED_OTHER)
+ this->need_resched = 1;
}

/*
@@ -156,6 +152,7 @@
init_task.next_run = p;
p->next_run = next;
next->prev_run = p;
+ nr_running++;
}

static inline void del_from_runqueue(struct task_struct * p)
@@ -234,7 +231,6 @@
if (!p->next_run) {
add_to_runqueue(p);
reschedule_idle(p);
- nr_running++;
}
spin_unlock_irqrestore(&runqueue_lock, flags);
}
@@ -444,23 +444,6 @@
struct timer_list timer;
unsigned long expire;

- /*
- * PARANOID.
- */
- if (current->state == TASK_UNINTERRUPTIBLE)
- {
- printk(KERN_WARNING "schedule_timeout: task not interrutible "
- "from %p\n", __builtin_return_address(0));
- /*
- * We don' t want to interrupt a not interruptible task
- * risking to cause corruption. Better a a deadlock ;-).
- */
- timeout = MAX_SCHEDULE_TIMEOUT;
- }
-
- /*
- * Here we start for real.
- */
switch (timeout)
{
case MAX_SCHEDULE_TIMEOUT:
@@ -601,10 +584,12 @@

#ifdef __SMP__
next->has_cpu = 1;
- next->processor = this_cpu;
#endif

if (prev != next) {
+#ifdef __SMP__
+ next->processor = this_cpu;
+#endif
kstat.context_swtch++;
get_mmu_context(next);
switch_to(prev,next);

Andrea Arcangeli

Ps. the patch is extracted from arca-58.

-
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/