Scheduler
Plánovač funguje na principu round-robin. Plánovaná vlákna jsou udržována
v obousměrném cyklickém spojovém seznamu vláken (viz dokumentace k
vláknům), která jsou ve stavu running.
Na "začátek" tohoto seznamu ukazuje proměnná running_threads, která mimo
plánování ukazuje vždy na aktuální (právě běžící) vlákno.
Buzená vlákna jsou přidávána vždy na "konec" tohoto seznamu. Možná by si
spící vlákna zasloužila být naplánována co nejdřív, pak by se ale na
ostatní nemuselo dostat.
Plánovač je spouštěn pravidelně při změně vnitřních hodin plánovače (hodiny
jsou aktualizovány při obsluze přerušení časovače - viz dokumentace k
výjimkám) a také při uspání aktuálního vlákna.
Plánuje se při zakázaných přerušeních (aby nedošlo k plánování během
plánování) a k jejich povolení uvnitř plánovače dochází pouze tehdy, když
nejsou žádná vlákna ve stavu running a čeká se na nějaké spící vlákno.
Povolení přerušení je nutné k tomu, aby se aktualizovala hodnota na
hodinách plánovače, a tím případně vzbudila sleeping vlákna, nebo aby došlo
k vyvolání přerušení klávesnice, a tím k vzbuzení vlákna, které je
zablokováno (suspended) v getc().
Na konci plánování dochází k přepnutí kontextu - k uložení stavu aktuálního
vlákna (do jeho zásobníku) a obnovení stavu plánovaného vlákna (opět z jeho
zásobníku). Tím se plánované vlákno stane aktuálním.
Pokud došlo k pravidelnému plánování a plánovač si myslí, že aktuální
vlákno běželo jen chvilku (vlákna před ním zabrala většinu času mezi
pravidelným plánováním a už by toho moc neudělalo), k přepnutí kontextu
nedojde - procesor dostane zpátky aktuální vlákno.
K přepínání kontextu nedochází ani tehdy, pokud je plánované vlákno totožné
s aktuálním - bylo by to zbytečné.