Procedura scheduler (interrupts i spinlock)

Spójrzmy na troche zmodyfikowane ostatnie rozwiązanie. Przełączenie zostałe przeniosione poza blokadę.

void scheduler()
{
 disable_interrupts();
 spinlock_lock(&scheduler_lock);
 struct task *new = select_runnable_task(run_queue);
 current->state = RUNNABLE;
 new->state = RUNNING; /* zarezerwuj, aby inny procesor, nie wybral tego zadania */
 spinlock_unlock(&scheduler_lock);
 current = new;
 switch_to(new); 
 restore_interrupts();
}

W tym rozwiązaniu pojawia się inny problem: to samo zadanie, może być uruchomione na dwóch procesorach. Problemem nie jest zadanie new, ale zadanie current (które wykonuje funkcje scheduler). Zmiana stanu tego zadania na RUNNABLE, nie powoduje, że ono przestaje być wykonywane, dopiero procedura switch_to (specjalna instrukcja ljmp) to powoduje. Jeśli pomiędzy zwolnieniem blokady, a wykonaniem przełączenia, inny procesor wybierze to zadanie i wykona switch_to do tego zadania to ten procesor będzie próbował przełączyć się na zadanie, które aktualnie się wykonuje.