OOStuBS/MPStuBS
Aufgabe 5: Zeitscheibenscheduling für OOStuBS/MPStuBS

Lernziele

  • Schutz kritischer Abschnitte im Betriebssystem mit Hilfe des Guard
  • Implementierung präemptiven Schedulings durch Timer-Interrupts

Aufgabenbeschreibung

Bislang haben wir das Prolog-Epilog Modell für die Interruptbehandlung implementiert und einen Threadwechsel-Mechanismus ohne Beachtung von Interrupts umgesetzt. Nun soll eine grobgranulare Locking-Strategie mithilfe des Pro-/Epilogmodells auch für das Threading-System eingebaut werden und ein Systemruf-Interface definiert werden. Threads sollen fortan im Round-Robin-Verfahren eingeplant werden und mithilfe eines Timer-Interrupts vom Nächsten verdrängt werden. Dafür betrachten wir den APIC-Timer genauer.

Die Klassen Guarded_Scheduler, Watch und Assassin (nur MPStuBS) müssen implementiert werden. Weiter muss die Klasse LAPIC um LAPIC::setTimer ergänzt werden.

Ab jetzt darf das globale Scheduler-Objekt nicht mehr länger von Nutzerprogrammen verwendet werden, sondern muss durch einen Guarded_Scheduler ersetzt werden. Dieser verwendet das gewöhnliche Scheduler-Objekt, was durch den Guard geschützt wird.

Die Aufgabe kann in drei Teile eingeteilt werden:

  • APIC-Timer einstellen und Interrupt fangen
  • das Scheduling-System auf präemptives Scheduling umstellen
  • Scheduler::kill(Thread*) als Inter-Prozessor-Interrupt (IPI)

(A) APIC-Timer einstellen

Um präemptives Umschalten zu implementieren, benötigen wir einen regelmäßigen Interrupt, der den laufenden Thread unterbricht und die Kontrolle an das Betriebssystem zurückgibt. Der APIC-Timer wird als Zeitgeber für den Timer-Interrupt benutzt. Der Timer-Interrupt erzwingt, dass der gerade laufende Thread durch das Betriebssystem verdrängt wird, welches nun den gerade laufenden Thread durch einen anderen austauschen kann.

Zunächst soll der Timer-Interrupt erzeugt werden. Dabei soll der Timer so genau wie möglich eingestellt werden und kontinuierlich mit Ablauf der Zeit einen Interrupt schicken. Die Teilaufgabe kann mit einer Testausgabe im Interrupt Handler des Timers getestet werden, sodass beobachtet werden kann, ob eine Unterbrechung vom Timer gesendet wurde.

(B) Präemptives Scheduling

Mithilfe des Timer-Interrupts kann nun das Scheduling-Verfahren auf ein Präemptives umgeschaltet werden. Es muss von jetzt an genau überlegt werden, wenn der Scheduler verwendet werden darf und ob er geschützt werden muss. Die expliziten Synchronisationsroutinen in MPStuBS um den Scheduler müssen nun entfernt werden, weil er nun durch den Guarded_Scheduler geschützt werden soll.

(C) Threads töten

Sollen Threads gestoppt werden, konnte auch früher schon Scheduler::kill(Thread*) verwendet werden. Allerdings war es in Aufgabe 4 nicht möglich, einen laufenden Thread zu unterbrechen und zu beenden. Er wurde lediglich nicht mehr in die Ready-List eingefügt. Mit aktivierten Interrupts aber können wir Inter-Prozessor-Interrupts versenden, mit denen ein Prozessor an einen anderen einen Interrupt schicken kann. Wird ein solcher empfangen, soll der Prozessor den zu beendenden Thread töten.

Zum Senden von IPIs steht die Methode APICSystem::sendCustomIPI() bereit, die mithilfe des LAPICs Interrupts an andere CPUs verschickt. Die Interruptbehandlung für einen IPI soll in der Klasse Assassin umgesetzt werden.

Klassenübersicht

dot_a5.png
Klassenübersicht für Aufgabe 5

Hilfen und Dokumentation