Hallo,
Weiß ich gerade auch nicht, aber braucht man die CPU-Nummer im UserSpace?
Ich bin mir da auch nicht ganz sicher ob es abseits eines SLAB-Allocators noch andere Dinge gibt die auch im User-Mode von der CPU-Nummer abhängen aber das alleine war für mich Grund genug dem User-Space eine lineare und eine physische CPU-Nummer per Befehl anzubieten (ich nutze dazu den normalen Befehl der die lokalen Controll-Register, mein MSR-Äquivalent, liest und erlaube dem User-Mode genau diese 2 Werte).
Als Index für ein Array kannst du es schonmal nicht benutzen, denn die CPU könnte ja, während du den Index benutzt, gewechselt werden. Von daher wird ja z.B. beim Slab-Allocator im UserSpace die Thread-ID für sowas genommen.
Dem kann ich ja glücklicherweise vorbeugen indem ich es erlaube das auch der User-Mode (ohne Kernel-Mitwirkung) für kurze und begrenzte Zeit die INTs komplett abschalten kann, was auch das Ablaufen der Zeitscheibe hinausschiebt. Somit kann ich selbst im User-Mode die aktuelle CPU-Nummer für den SLAB-Allocator nutzen, die Thread-ID ist da IMHO völlig ungeeignet da diese eher zufällig ist (auf jeden Fall nicht linear numeriert), bei jedem neuen Thread auch eine neue Thread-ID vergeben wird und es vor allem sehr viel mehr Threads in einem Prozess als CPUs geben kann.
Es gibt noch einen 3. Grund, nämlich wenn ein Thread "aufgeweckt" wird, vom Schlafen oder vom Warten (z.B. Semaphore).
Das Aufwecken ist so ähnlich wie das neu Erstellen und lässt sich auf jeden Fall in die 2 Kategorien einsortieren. Entweder wird durch einen IRQ geweckt (z.B. wenn der Timer ein Event triggert auf das bereits ein Thread wartet) oder es wird durch eine Software-Aktion ausgelößt (so wie auch Dein Beispiel mit dem Freigeben eines Semaphors und gerade hier kann ja im release() geprüft werden ob ein Thread mit höherer Priorität als der aktuelle wartet und wenn ja dann wird dieser sofort auf die aktuelle CPU geholt und der der gerade den Semaphor freigegeben hat kommt in die runnable-Liste).
Ich weiß nicht wie lange deine Zeitscheiben so sind, aber wir reden da schon von mehreren ms und wenn du dann Audio und Video machst, könnte das schon zu dem Problem führen was ich ja unter Windows habe (knacksen im Sound und Bildstocken, auf nem QuadCore).
Ja, meine Zeitscheiben sollen auch mehrere ms lang sein (ich dachte so an 10 ms bis etwa 20 ms) und, ja, das ist keine harte Echtzeit mehr. Normalerweise sollten die SW-Buffer bei Audio und Video deutlich mehr als 100 ms überbrücken können aber ich weiß auch das man im professionellen Umfeld auch Applikationen hat wo möglichst kurze Latenzen und damit auch kleine Buffer benutzt werden, wer sowas benötigt benötigt eben auch ein passendes OS oder das OS bietet die Möglichkeit spezielle Scheduler-Features anzuschalten (wie z.B. das bei neuen Threads immer eine Optimierung über alle CPUs gefahren wird) was dann zwar mehr CPU-Leistung kostet aber eben auch kürzere Latenzen für die wichtigen Dinge ermöglicht (die weniger wichtigen Dinge werden dafür noch stärker verdrängt).
Der Vorteil einer globalen runnable-Liste liegt für mich genau da, dass immer die Threads mit der höchsten Priorität laufen.
Das sehe ich ganz genauso, nur ist eben eine Frage wie schnell dieses automatische Gleichgewicht sein soll. Hier ist es eben so das wenn man kürzere Latenzen haben will (vor allem auch im Worst-Case der ja sonst bis zu einer kompletten Zeitscheibe dauern kann) das man dafür zusätzliche CPU-Leistung opfern muss.
Ich habe für sowas ne STOP-IPI. Damit kann man entweder alle, außer der sendenden, CPUs anhalten und kann halt z.B. nen kontrollierten Panic machen oder diese eine CPU den PC runterfahren lassen.
Also über die Kernel-Panic hab ich mir noch nicht allzu genau nen Kopf gemacht (steht jetzt aber auf meiner ToDo-Liste) aber das Runterfahren des PC (inklusive Ausschalten) soll bei mir eigentlich die User-Mode-Personality machen (also der init-Prozess).
Das halte ich ersten für Overhead (da ich durch eine Liste durchgehen muss) und zweitens, desto länger die Liste ist, desto schneller ist eine IPI-Nachricht.
Nö, ich würd einfach die nächsten X CPUs in den Scheduler zwingen, wobei X die Anzahl der neuen Threads ist welche eventuell noch einen kleinen Angstfaktor dazu bekommt. Das ist O(n), genauso wie das Verschicken von X IPIs.
dass es bei mir eher schwierig wird auf den APIC der anderen CPUs zu zugreifen (geht das überhaupt, dazu müsste man mindestens die physikalische Adresse der einzelnen APICs unterschiedlich setzen, aber ich glaube dass das trotzdem nicht geht).
Ich kenne mich bei x86 ja nicht mehr so gut aus aber wimre hat jeder APIC (auch die lokalen) eine individuelle physische Adresse, es gibt nur die zusätzliche Möglichkeit das von einer CPU aus der eigene local-APIC über eine zusätzliche physiche Alias-Adresse erreichbar ist. Diese zusätzliche Alias-Adresse ist auch nicht von außerhalb der CPU nutzbar, so das die nicht z.B. von einem PCI-Gerät benutzt werden kann.
Wenn ich mich nicht täusche, hat Homix letztens erzählt, dass er auf seinem System nur jeden zweiten Index genutzt hat, weil bei seiner CPU das Hyperthreading deaktiviert ist.
Das ist zwar doof aber auch kein Beinbruch wenn dadurch nur jeder zweite Eintrag in einem Array, das üblicherweise pro Element nur ein paar Controll-Variablen und Pointer enthält, ungenutzt bleibt. Es wäre aber auch sehr schön wenn sich in solchen Situationen das BIOS besser verhalten würde.
Wenn du einen Prozess auf eine CPU festpinnst und alle anderen Prozesse von dieser CPU entfernst, dann hast du plötzlich die Möglichkeit, weiche Echtzeitanforderungen zu erfüllen.
Das festpinnen mag sicher gut funktionieren aber ich bin mir nicht sicher ob es auch Möglichkeiten gibt
alle anderen Thread von dieser CPU zu verbannen. Dabei entstehen IMHO einige Probleme. Was ist wenn dieser eine Thread gerade blockiert? Bleibt die CPU dann unbenutzt? Geht die dann in einen Stromsparzustand (was eventuell längere Aufwachzeiten und damit Latenzen verursacht)? Wie viele CPUs in einem System kann man den ruhigen Gewissens frei räumen? Ich persönlich würde maximal die Hälfte zulassen und das auch nur wenn mindestens 4 CPUs verfügbar sind. Wenn dieser spezielle Thread z.B. einen synchronen IPC-Vorgang initiiert wäre es doch praktisch wenn der Thread der diesen IPC bearbeitet dafür so lange die CPU haben könnte, schon damit die zu bearbeitenden Daten auch im richtigen Cache bleiben. Ich bin zwar auch der Meinung das festpinnen eine interessante Option darstellt aber ich sehe noch einige Probleme die gelöst werden müssen damit das auch in der Praxis eine wirklich zufriedenstellende Angelegenheit wird.
Ich gebe Dir auf jeden Fall recht das zu häufiges wechseln der CPU eher kontraproduktiv ist, wegen dem Umladen der Caches obwohl das auch erst auf Mehr-Sockel-Systemen zum Problem wird (innerhalb einer CPU sind die Cache-to-Cache-Transfers ziemlich schnell und bei Intel auch gar nicht nötig weil der L3-Cache ja "inklusive" ist).
Außerdem kann man durch das Festpinnen den Scheduler entlasten.
Also das sehe ich noch nicht.
Ich mag es nicht, wenn ein OS alles besser weiß als ich und mir die Möglichkeiten nimmt, darauf einwirken zu können. Selbst dann, wenn ich es im Normalfall nie tun werde.
Auch hier kann ich Dir uneingeschränkt zustimmen (und betrachte sowas auch nicht als Over-Engineering) aber ob das Festpinnen wirklich eine gute Lösung darstellt wage ich zu bezweifeln. Aus meiner Sicht könnte es eine gute Lösung sein wenn man den Scheduler zwingt nach jeder Änderung der Anzahl aktiver Threads oder der Priorität eines aktiven Threads die optimale Verteilung über alle CPUs neu zu berechnen (also den großen Scheduler aufzurufen), das kostet zwar einiges an zusätzlicher CPU-Leistung kann aber bestimmt etwas helfen das die wichtigen Jobs auch immer eine CPU abbekommen. Wobei der große Scheduler natürlich auch aufpassen muss das er Thread nur möglichst selten von einer CPU auf eine andere Wechselt. Auf meiner Plattform habe ich vor die maximale Aufrufhäufigkeit des großen Schedulers mit HW-Hilfe zu begrenzen so das wenn z.B. ein Thread kurz erstellt wird aber recht schnell wieder verschwindet (z.B. ein IRQ-Handler-PopUp-Thread) das der große Scheduler eventuell gar nichts tut weil sich die große Gesamtsituation nicht geändert hat. Diese Maximal-Frequenz könnte man signifikant erhöhen wenn z.B. eine Applikation explizit ein besseres Echtzeit-Verhalten anfordert (das wäre aus meiner Sicht eine sinnvolle Stellschraube die sicher auch einiges bewirken kann und wenn die Applikation auch genau weiß welche Latenzen sie akzeptieren kann könnte man das OS auf genau diesen Wert trimmen so das eben nicht zu viel zusätzliche CPU-Leistung für sowas geopfert wird).
Grüße
Erik