[CPU-Affinität] Eine gewisse, aber nicht das man sagt das ein Prozess nur noch auf dieser einen CPU läuft. Denn das läuft dann darauf hinaus, dass viele CPUs idlen und ein paar, auf denen die Threads gestartet wurden, machen die ganze arbeit. Von daher würde ich das als nicht so schlimm erachten.
Das ist mir schon klar. Einfacher ist es aber, wenn der Scheduler alle beim Start vorhandenen CPUs sieht und die Anwendungen direkt gleichmäßig verteilt, anstatt erstmal alle Anwendungen auf CPU2 zu legen und später von dort nochmal wegzunehmen.
Defekte CPUs (die nicht vom BIOS deaktiviert wurden, bei x86) würde ich komplett ignorieren. Weil wie stellst du fest ob sie defekt sind? Ich würde wenn mir der Idle-Prozess abstürzt das ganze System in einen Panic schicken, weil normal ist das nicht. Soll der Nutzer erstmal die CPU tauschen und dann wieder neu versuchen.
Ist ja auch in Ordnung. Zu der Zeit sollte aber noch kein Usercode gelaufen sein. Wenn du CPU-Hotplugging irgendwann unterstützt, dann kannst du die CPU auch einfach nicht in den aktiven Scheduler übernehmen.
Also gut ich starte für jede vorhandene Hardware einen Thread der die Hardware initialisiert. Viele Threads heißen für mich, es wäre gut wenn man die auch auf viele CPUs verteilen kann. Würde also schon was bringen.
Bringt nichts, weil dein Kernel erstmal für jeden Thread den Hardwaretreiber von sekundärem Speicher laden muss (sofern du nichts initrd-artiges benutzt). Das Problem sind nicht die paar Zyklen Ineffizienz, weil du noch während des CPU-Bootstraps schon sämtliche Hardware initialisieren möchtest, sondern die Wartezyklen, die durch I/O geschehen. Es geht hier ausschließlich um den Zeitraum, in dem du der Reihe nach alle vorhandenen CPUs erstmalig einschaltest.
Im hinblick auf die Zukunft, ich denke da an so Many-Core Projekte von Intel, wo man zwar 100 und mehr Cores hat, der einzelne Core aber wesentlich langsamer ist als heutige Cores, macht es wieder Sinn so schnell wie möglich alles parallel laufen zu lassen.
Ja, die sind aber weit von dem entfernt, was dein OS unterstützt und auch das, was eriks Plattform bietet. Bei euch geht es um 10
0..10
1 CPUs.
Das war ja meine erste Idee die aber bedeutet das es erst dann los geht wenn der Boot-Code alle APs aufgeweckt hat und das kostet IMHO unnötig Zeit. Nebst dessen das ich meinen Scheduler nicht aktivieren kann, er ist eine Art Exception-Handler der von der CPU automatisch aufgerufen wird wenn die Zeitscheibe abgelaufen ist. Also so bald ich eine CPU das erste mal in den User-Mode schicke muss der Scheduler bereits voll funktionsfähig sein und das ist er auch weil er vom Boot-Code passend vorbereitet wurde (noch vor der Lebendgeburt).
Okay. Das mit dem "unnötig Zeit" sehe ich unkritisch. Wieviel Zeit ließe sich denn einsparen? Wieviele Millisekunden dauert es denn, eine CPU hochzufahren? Solange du keine großen CPU-Mengen im System hast, lohnt es sich u.U. nicht.
Dein Aufbau klingt allerdings stark danach, dass es an sich total egal ist, ob du alle CPUs gleichzeitig aufweckst oder nacheinander. Von daher ist die Antwort ebenfalls egal (und eine Geschmackssache).
Erst init erstellt dann weitere Prozesse (mit Hilfe des exec-Service), init ist bei mir ne Art initrd mit etwas integriertem Code als eigenständiger User-Mode-Prozess realisiert.
Zu dem Zeitpunkt, wo du anfänst, Usercode auszuführen, sollte meiner Meinung nach das System schon einigermaßen stabil sein. Das heißt, RAM und CPU sind voll einsatzfähig.
Wenn ein System wegen einer defekten CPU abstürzt dann muss eben der User die CPUs tauschen, außerdem gibt es ja noch die Maschine-Check-Architekture die es vielleicht ermöglicht wenigstens eine einigermaßen brauchbare Fehlermeldung auszugeben damit der User zumindest eine wage Idee hat was wohl defekt sein könnte.
Das wäre übrigens ein Grund dafür, den BSP als allererstes ins aktive Scheduling zu übernehmen. Denn der hat den Boot-Code bereits ausgeführt und funktioniert garantiert; also kann er auch die Fehlermeldung ausgeben. Deine Herangehensweise ist ja, dass du den BSP als allerletztes aktivierst, da er bis zuletzt noch das System hochfährt.
Alles was das OS benötigt um an eine HDD (oder auch an eine LAN-Freigabe) zu kommen muss also in init enthalten sein und von diesem entpackt und gestartet werden bis dann endlich der richtige Boot-Vorgang anfangen kann.
Ja, und die Frage ist, ob zu diesem Zeitpunkt noch CPUs aktiviert werden sollen oder nicht. Ich bin der Meinung "nein", allerdings aus Prinzip. Wenn man sehr viele CPUs hat, mag es sich lohnen, ich sehe allerdings keinen Vorteil. Das System bootet nur äußerst selten (verglichen mit der Laufzeit). Wenn dein Kernel rein passiv ist, spielt es im Übrigen keine Rolle.
Wenn wir von einem schlanken Linux-Kernel mit fetter initrd (die alle möglichen Treiber als Module enthält) ausgehen dann muss der Linux-Kernel ja auch erst mal das Plug-&-Play über den PCI laufen lassen und alle nötigen Treiber aus der initrd holen bis er dann endlich das root-File-System mounten kann um dann von dort /sbin/init zu starten, dieser Abschnitt im Boot-Prozess dürfte wohl schon im wesentlichen CPU-limitiert sein.
Sicher ist das Zerpflücken der initrd im wesentlichen CPU-limitiert, aber es macht nur einen äußerst geringen Bruchteil der Bootzeit aus. Das Mounten des root-Dateisystems dauert wesentlich länger, weil du dazu auf die Festplatte warten musst usw. Aber das ist egal, weil du diesem Zeitpunkt definitiv alle CPUs aktiv sein sollten.
Bei einem Micro-Kernel ist nur der Unterschied das dieser bereits voll einsatzfähig ist weil ja Treiber usw. gar nicht zu seinen Aufgaben gehören. Mein Kernel weiß gar nicht das es überhaupt PCI gibt, der kennt nur CPUs und Speicher und so bald das beides da ist kann er glücklich leben und den Rest dem User-Mode überlassen.
Ja. Also ist er dafür zuständig, dass die CPUs auch funktionieren und aktiv sind.
Ich persönlich mag es, Initialisierung vom Rest danach zu trennen.
Das macht übrigens auch das Debugging einfacher. Wenn das System noch während der CPU-Initialisierung abstürzt, den Grund zu finden (ist es der BSP? irgendein AP? der AP, der gerade Init ausführt? Init selbst?), stell ich mir schwierig vor.
Machen musst du es am Ende eh selbst.
Gruß,
Svenska