Hallo,
Soweit ich es verstanden habe, ist der edge-triggered IRQ mit der Annahme (dem ACK) am Lokalen-APIC abgeschlossen und es kann ein neuer IRQ verarbeitet (im IO-APIC) werden. Dieser neue IRQ kann ja wieder ein edge-triggered IRQ (vom selben Gerät) sein und ein andere Prozessor hat jetzt ne niedrigere Priorität als der der den letzten IRQ immernoch bearbeitet.
Hm, gibt es bei den APICs wirklich keinen Mechanismus mit dem man einen IRQ per Default erst mal maskieren kann? Du hattest doch was von einem "IRR-Bit" geschrieben, kann man damit nicht irgendwas drehen? Ich kenne die APICs nicht wirklich und hab auch nie die Spezifikation komplett durchgelesen, daher kann ich Dir da leider nicht wirklich helfen, sorry. Irgendwie fällt es mir aber schwer zu glauben dass das nicht funktioniert, auf der anderen Seite ist das auch nicht so schlimm wenn das nicht gehen sollte da anständige HW (und nur die würde ich auf die Benutzung von MSI(-X) konfigurieren, das muss man nämlich explizit machen) ja entsprechende Mechanismen selber hat um die IRQ-Rate auf einem angenehmen Niveau zu halten.
Kann das der PCI-Bustreiber ermitteln oder muss ich mich da auf den Treiber verlassen, der halt mehrere IRQs anfordert?
Wie viele IRQs ein PCI-Gerät maximal haben kann verraten die Capabilities für MSI bzw. MSI-X ganz genau, sämtliche Ressourcen (inkl. dem IRQ-Routing) lassen sich bei PCI komplett ohne die gerätespezifischen Treiber konfigurieren. Wen ein Treiber dann weniger IRQs haben möchte kann man das auch nachträglich noch reduzieren. Wenn ein PCI-Device MSI und MSI-X unterstützt dann solltest Du auf jeden Fall MSI-X bevorzugen und auch voll konfigurieren, wenn der Treiber das später nicht voll nutzt kannst Du bei MSI-X sehr flexibel downgraden wogegen bei MSI nur eine Zweierpotenz von 1 bis einschließlich 32 als IRQ-Anzahl möglich ist. Nebst dessen das bei MSI-X auch immer pro IRQ ein Mask-Bit verfügbar ist wogegen das bei MSI optional ist (ich kenne auch kein Device dass das bei MSI unterstützt).
Heißt im Endeffekt, wenn eine CPU schon den gleichen IRQ bearbeitet, wird auch der gerade eingetroffene IRQ (trotz anderer Prioritäten) wieder an diese CPU geleitet.
Aha, Danke. Das bedeutet also das man versucht die Cache-Effizienz möglichst hoch zu halten.
Wenn der IRQ-Controller die maximale IRQ-Frequenz relativ willkürlich begrenzt, dann ist das schlechtes Design, weil dann ja bewusst Interrupts fallengelassen werden, wenn eine Hardware sich anders verhält.
Wie kommst Du hier auf "willkürlich"? Ich hab doch extra "mit einem individuell konfigurierten Wert" geschrieben und so möchte ich das auf meiner Plattform auch realisieren. Mir schwebt vor das man die minimale IRQ-Delay-Zeit in einem Bereich von etwa 5 µs bis 1 ms (also etwa 1000 Hz bis 200 kHz) frei konfigurieren kann (bei einer Auflösung von 1 µs reicht dafür ein 10 Bit Counter aus). In dieser Zeit werden zwar weitere IRQ-Signale von dem zugehörigen HW-Gerät für den betreffenden IRQ angenommen (und auch ordnungsgemäß gezählt) aber eben nicht an eine CPU ausgeliefert. Es soll nur die maximale Auslieferfrequenz für jeden IRQ individuell konfigurierbar sein, weniger geht natürlich immer und wenn der letzte IRQ schon lange her ist dann kommt der nächste IRQ auch sofort (ohne zusätzliche Latenz) durch (so er denn nicht von einem anderen IRQ mit höherer Priorität verdrängt wird und auch eine CPU diesen IRQ akzeptiert). Der Delay-Counter wird auf jeden Fall immer nur bei einer tatsächlich erfolgreichen Auslieferung des betreffenden IRQ gestartet (genau zu dem Zeitpunkt wo auch der Zähler mit den vom HW-Gerät empfangenen IRQ-Signalen genullt wird). Das einzigste was hier
willkürlich ist sind die Grenzen für den Counter-Start-Wert, wobei ich 200 kHz als absolute Obergrenze und auch 1000 Hz als tiefste Grenze für angebracht halte. Mehr als 200 kHz für einen IRQ sind wohl nicht nötig (wenn ein einzelnes HW-Gerät mehr braucht dann muss es eben zwangsläufig mehrere IRQs benutzen) und 1000 Hz als tiefste Grenze lassen dem System auch bei komplexeren IRQ-Handlern noch genug Luft zum atmen (und zum eventuellen ziehen der Notbremse per Mask-Bit).
Du gehst den Weg, dass ein IRQ also nach einer gewissen Zeit automatisch demaskiert wird und begrenzt auf diese Weise die IRQ-Frequenz des Geräts. Solange du garantieren kannst, dass du den Interrupt in diesem Zeitslot auch wirklich verarbeitet hast und dass die Hardware niemals schneller feuert, dann ist das in Ordnung. Aber kannst du das immer garantieren?
Ich garantiere keines von beidem, wie sollte ich den auch? Wann der richtige IRQ-Handler, in meinem Fall ein asynchroner Event-Handler als extra PopUp-Thread im User-Mode-Treiber, fertig ist kann ich als OS-Entwickler nicht beeinflussen. Und die IRQ-Signal-Frequenz der Hardware hab ich auch nicht immer unter meiner Kontrolle. Schließlich müssten HW-Gerät und Treiber auch von Fremden erstellt werden können (sogar als Closed-Source).
Man muss in der Hardware die IRQ-Quelle behandeln.
Hä, wie soll das den bitte gehen? Wie soll die HW einen IRQ behandeln (z.B. ein empfangenes Ethernetframe)? Die abschließende Behandlung eines IRQ macht immer die Software (also der Treiber) und erst dann geht bei Level-Triggered-IRQs auch die IRQ-Leitung vom HW-Gerät zum IRQ-Controller wieder auf inaktiv zurück. Genau deswegen muss ja maskiert werden damit der IRQ-Controller in der Zeit weitere IRQs an eine (andere) CPU melden kann (bei Multi-Core und/oder Micro-Kernel ist das eine absolute Notwendigkeit).
Mir geht es um die Schnittstelle zwischen Interrupt Controller und CPUs
Halt! Stopp! Einen Moment mal, ich dachte wir reden hier von der Verbindung zwischen HW-Gerät und IRQ-Controller, jedenfalls hab ich bis jetzt nur darüber geschrieben (Bitte interpretiere meine Antworten auch entsprechend). Wie die Verbindung zwischen IRQ-Controller und CPU aussieht ist ein uninteressantes Implementierungsdetail das hier nicht beachtet wird. Bei meiner Plattform möchte ich das Level-Triggered machen, weil es nur einen IRQ-Controller aber dafür mehrere CPUs gibt ist das IMHO die bessere Lösung für diesen Teilabschnitt.
Level triggered IRQs bieten die Möglichkeit der gemeinsamen Nutzung. Wenn man diese nicht nutzt, hat man die gleichen Vorteile wie bei flankengesteuerten Interrupts, ist aber flexibler.
Jetzt bin ich aber mal neugierig. Welche
Möglichkeit bietet den IRQ-Sharing überhaupt? Von allerlei lustigen Problemen mit Treibern und Hardware mal abgesehen. Dadurch das so ein gesharter IRQ immer als ganzes maskiert wird bietet der auf jeden Fall die Möglichkeit für zusätzliche Latenzen wenn z.B. gerade der IRQ-Handler eines der beteiligten HW-Geräte noch läuft (also der IRQ noch maskiert ist) und ein anderes Gerät nun auch aktiv den Wunsch nach Aufmerksamkeit signalisiert muss dieses noch mindestens so lange warten bis der noch aktive IRQ-Handler eines anderen HW-Gerätes fertig ist (selbst wenn sich noch ein paar CPUs langweilen) und erst dann geht das Spiel mit dem Ausliefern dieses IRQ an eine CPU wieder von vorne los.
Der Treiber für meine 3c589 hat das mal gemacht. Wenn ich da die maximalen 10 MBit/s durchpumpe, ist ein Core mit 80%hi durchaus dicht.
Durch das Polling wird zwar eventuell die CPU-Last reduziert (wovon ich gar nicht mal wirklich überzeugt bin) aber auf jeden Fall auch der Durchsatz was das Problem eigentlich nur schlimmer macht oder länger hinaus zieht. Wenn eine gegebene HW-Kombination eine bestimmte Aufgabe (z.B. das Sättigen einer 10MBit/s-Verbindung) nicht anständig hinbekommt dann geht es eben nicht und da ist es auch egal wie die Software da versucht das Schlimmste zu vermeiden, die gewünschte Aufgabe wird einfach nicht erfüllt und damit ist die gegebene HW-Kombination schlicht und ergreifend nicht tauglich für diese Aufgabe.
Ich weiß ja nicht, wie du das siehst, aber da ist Polling durchaus akzeptabel...
Also ich sehe das so das Polling grundsätzlich nicht akzeptabel ist, das passt einfach nicht ins Konzept eines preemptiven Multitaskings, fertig.
Bei deiner Plattform hast du natürlich die vollkommene Freiheit, dir Hardware auszusuchen und zusammenzustellen, die freundlich ist. Bei x86 ist das eben nicht so, da zählt billig - und damit kämpfen sowohl Linux als auch Microsoft.
Ich sehe da keinen wesentlichen Unterschied zwischen dem x86-PC und meinem System, wenn z.B. eine Netzwerkkarte ein so langsames Interface zur Software hat das man selbst für eine 10MBit/s-Verbindung eine CPU nahezu komplett Auslasten muss dann ist das einfach nicht akzeptabel, egal was diese CPU für eine Befehlsarchitektur hat.
Grüße
Erik