
Die Synchronisation der Aktivitäten innerhalb von OOStuBS/MPStuBS ist in Aufgabe 3 auf die Verwendung des Pro-/Epilogmodells umgestellt worden. Nun soll eine grobgranulare Locking-Strategie verwendet und eine Systemaufrufschnittstelle definiert werden. Der Scheduler soll - ausgelöst durch den Timer-Interrupt - Threads verdrängen können.
Hierzu müssen die Klassen Guarded_Scheduler, Watch und (in MPStuBS) Assassin implementiert sowie im Namespace LAPIC::Timer die Methoden LAPIC::Timer::set() und LAPIC::Timer::ticks() vervollständigt werden.
Um aus Benutzerprogrammen heraus die Methoden des Schedulers aufrufen zu können, darf die globale Variable scheduler nicht direkt benutzt werden. Stattdessen soll die Klasse Guarded_Scheduler mit Hilfe des guard die Zugriffe auf den globalen Scheduler schützen.
In MPStuBS gab es schon in Aufgabe 4 die Problematik, dass die Methoden des Schedulers von mehreren Prozessoren aus gleichzeitig aufgerufen werden konnten, und deswegen die Zugriffe auf die Bereitliste synchronisiert werden mussten. Da die Betriebssystemfunktionen nun in der Syscall-Schnittstelle mit dem Guard synchronisiert werden sollen, müssen die expliziten Synchronisationsaufrufe aus Aufgabe 4 entfernt werden.
Analog zum Scheduling soll nun auch die Implementierung von Scheduler::kill(Thread*) präemptiv erfolgen. Sollte der zu beendende Thread gerade auf einem anderen Prozessor laufen, dann muss dieser mit Hilfe eines Interprozessorinterrupts (IPIs) unterbrochen und zur Abgabe des Prozessors gezwungen werden. Dazu stellen wir im Namespace LAPIC::IPI die Methode LAPIC::IPI::send() bereit, die mit Hilfe des Local APICs Interrupts an andere CPUs schicken soll. Die Interruptbehandlung für den IPI soll in der Klasse Assassin implementiert werden.
Zusätzlich zum LAPIC-Timer kann auch der Zugriff auf den Timestamp Counter (TSC) implementiert werden. Der TSC erlaubt genaue Zeitmessungen sowie präzises zeitbasiertes aktives Warten. Zur Kalibrierung muss die Methode TSC::ticks - sowie eine Hilfsfunktion TSC::ticksByPIT
- implementiert werden, die analog zu LAPIC::Timer::ticks() die Anzahl der Zählerticks pro Millisekunde liefern soll. Darauf aufbauend können dann die Methoden TSC::delay zum aktiven Warten sowie TSC::nanoseconds zur Umrechnung eines in Ticks gegebenen Zeit-Deltas in Nanosekunden implementiert werden. Die notwendige Ansteuerung der TSC-Hardware selbst ist schon in machine/tsc.cc vorgegeben, es muss lediglich noch die Auswertung/Umrechnung implementiert werden.