Listing 4. reschedule_idle

static void reschedule_idle(struct task_struct * p)

{

#ifdef __SMP__

	int this_cpu = smp_processor_id(), target_cpu;

	struct task_struct *tsk, *target_tsk;

	int cpu, best_cpu, i;

	unsigned long flags;

	spin_lock_irqsave(&runqueue_lock, flags);

	/*

	 * shortcut if the woken up task's last CPU is

	 * idle now.

	 */

	best_cpu = p->processor;

	target_tsk = idle_task(best_cpu);

	if (cpu_curr(best_cpu) == target_tsk)

		goto send_now;

	target_tsk = NULL;

	for (i = 0; i < smp_num_cpus; i++) {

		cpu = cpu_logical_map(i);

		tsk = cpu_curr(cpu);

		if (tsk == idle_task(cpu))

			target_tsk = tsk;

	}

	if (target_tsk && p->avg_slice > cacheflush_time)

		goto send_now;

	tsk = cpu_curr(best_cpu);

	if (preemption_goodness(tsk, p, best_cpu) > 0)

		target_tsk = tsk;

	/*

	 * found any suitable CPU?

	 */

	if (!target_tsk)

		goto out_no_target;

		

send_now:

	target_cpu = target_tsk->processor;

	target_tsk->need_resched = 1;

	spin_unlock_irqrestore(&runqueue_lock, flags);

	/*

	 * the APIC stuff can go outside of the lock because

	 * it uses no task information, only CPU#.

	 */

	if (target_cpu != this_cpu)

		smp_send_reschedule(target_cpu);

	return;

out_no_target:

	spin_unlock_irqrestore(&runqueue_lock, flags);

	return;

#else /* UP */

	int this_cpu = smp_processor_id();

	struct task_struct *tsk;

	tsk = cpu_curr(this_cpu);

	if (preemption_goodness(tsk, p, this_cpu) > 0)

		tsk->need_resched = 1;

#endif

}

------- cut and paste from linux/kernel/sched.c ---------

