lkml.org 
[lkml]   [2000]   [Feb]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectsmall optimization for SMP scheduling
This patch uses a bitfield "idle_cpus" to keep track of idle cpus.
This can be used to
- speed up reschedule_idle when there is no idle cpu
- eliminate a call to reschedule_idle (and retaking the runqueue_lock)
in __schedule_tail, when there is no chance of replacing a running
process

The bitfield is changed only in cpu_idle, so on a busy system there
should be no problem with invalidating cache lines all the time.

On my 2 CPU system, the patch speeds up scheduling by a few percent and
decreases contention for the runqueue_lock.

The attached patch is for the i386 architecture only (it should be
trivial
to add the necessary code for other architectures that support SMP)--- linuxelf-2.3.orig/arch/i386/kernel/process.c Fri Feb 11 20:01:48 2000
+++ linuxelf-2.3/arch/i386/kernel/process.c Fri Feb 18 20:27:45 2000
@@ -86,6 +86,9 @@
*/
void cpu_idle(void)
{
+#ifdef __SMP__
+ int this_cpu=smp_processor_id();
+#endif
/* endless idle loop with no priority at all */
init_idle();
current->priority = 0;
@@ -93,10 +96,17 @@

while (1) {
void (*idle)(void) = pm_idle;
+#ifdef __SMP__
+ extern volatile unsigned long idle_cpus;
+ set_bit(this_cpu, &idle_cpus);
+#endif
if (!idle)
idle = default_idle;
while (!current->need_resched)
idle();
+#ifdef __SMP__
+ clear_bit(this_cpu, &idle_cpus);
+#endif
schedule();
check_pgt_cache();
}
--- linuxelf-2.3.orig/kernel/sched.c Fri Feb 11 20:02:12 2000
+++ linuxelf-2.3/kernel/sched.c Fri Feb 18 20:26:23 2000
@@ -81,6 +81,8 @@
struct kernel_stat kstat = { 0 };

#ifdef __SMP__
+unsigned long idle_cpus=0UL; /* assumes NR_CPUS = 32, just a hint for
+ reschedule_idle and __schedule_tail */

#define idle_task(cpu) (init_tasks[cpu_number_map(cpu)])
#define can_schedule(p) (!(p)->has_cpu)
@@ -189,34 +191,35 @@
struct task_struct *tsk;
int cpu, best_cpu, i;

- /*
- * shortcut if the woken up task's last CPU is
- * idle now.
- */
best_cpu = p->processor;
- tsk = idle_task(best_cpu);
- if (cpu_curr(best_cpu) == tsk)
- goto send_now;
-
- /*
- * We know that the preferred CPU has a cache-affine current
- * process, lets try to find a new idle CPU for the woken-up
- * process:
- */
- for (i = smp_num_cpus - 1; i >= 0; i--) {
- cpu = cpu_logical_map(i);
- if (cpu == best_cpu)
- continue;
- tsk = cpu_curr(cpu);
- /*
- * We use the last available idle CPU. This creates
- * a priority list between idle CPUs, but this is not
- * a problem.
- */
- if (tsk == idle_task(cpu))
- goto send_now;
- }

+ if (idle_cpus) { /* some cpus are idle */
+ /*
+ * shortcut if the woken up task's last CPU is
+ * idle now.
+ */
+ if (idle_cpus & (1<<best_cpu)) {
+ tsk=cpu_curr(best_cpu);
+ goto send_now;
+ }
+ /*
+ * We know that the preferred CPU has a cache-affine current
+ * process, lets try to find a new idle CPU for the woken-up
+ * process:
+ */
+ for (i = smp_num_cpus - 1; i >= 0; i--) {
+ cpu = cpu_logical_map(i);
+ if (idle_cpus & (1<<cpu)) {
+ /*
+ * We use the last available idle CPU. This creates
+ * a priority list between idle CPUs, but this is not
+ * a problem.
+ */
+ tsk=cpu_curr(cpu);
+ goto send_now;
+ }
+ }
+ }
/*
* No CPU is idle, but maybe this process has enough priority
* to preempt it's preferred CPU.
@@ -408,12 +411,18 @@
static inline void __schedule_tail(struct task_struct *prev)
{
#ifdef __SMP__
+ int this_cpu=smp_processor_id();
if ((prev->state == TASK_RUNNING) &&
- (prev != idle_task(smp_processor_id()))) {
- unsigned long flags;
-
- spin_lock_irqsave(&runqueue_lock, flags);
- reschedule_idle(prev, flags); // spin_unlocks runqueue
+ (prev != idle_task(this_cpu))) {
+ /* only try to reschedule if there is a chance of success */
+ if (idle_cpus || prev->policy != SCHED_OTHER ||
+ (prev->avg_slice < cacheflush_time &&
+ cpu_curr(this_cpu)->avg_slice > cacheflush_time))
+ {
+ unsigned long flags;
+ spin_lock_irqsave(&runqueue_lock, flags);
+ reschedule_idle(prev, flags); // spin_unlocks runqueue
+ }
}
wmb();
prev->has_cpu = 0;
\
 
 \ /
  Last update: 2005-03-22 13:56    [W:0.018 / U:0.924 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site