2013-01-17 4 views
7

Um Ihnen den vollständigen Kontext zu geben, begann meine Diskussion mit einer Beobachtung, dass ich einen SMP Linux (3.0.1-rt11) auf ARM Cortex laufen lasse A8-basiertes SoC, das ein Einprozessor ist. Ich war neugierig, ob es einen Leistungsvorteil geben wird, indem ich die SMP-Unterstützung deaktiviere. Und wenn ja, welche Auswirkungen wird es auf meine Fahrer und Interrupt-Handler haben.Die Verbindung zwischen CONFIG_SMP, Spinlocks und CONFIG_PREEMPT im neuesten (3.0.0 und höher) Linux Kernel

Ich habe etwas gelesen und stoße auf zwei verwandte Themen: Spinlocks und Kernel Preemption. Ich habe etwas mehr gegoogelt und gelesen, aber dieses Mal habe ich nur ein paar veraltete und widersprüchliche Antworten. Also dachte ich, lass mich Stackoverflow versuchen.

Herkunft meiner Zweifel/Fragen ist das para von Linux-Gerätetreiber 3. Auflage Kapitel 5:

Spinlocks sind von ihrer Natur sind für den Einsatz auf Multi-Prozessor Systeme, obwohl ein Einprozessor-Workstation ein Lauf preemptive Kernel verhält sich wie SMP, soweit Nebenläufigkeit betroffen ist. Wenn ein nicht präventives Einprozessorsystem jemals in eine Schleuse auf einer Schleuse ging, würde es für immer drehen; kein anderer Thread könnte jemals die CPU erhalten, um die Sperre aufzuheben. Aus diesem Grund sind Spinlock-Operationen auf Uniprozessor-Systemen ohne aktivierte Preemption optimiert, um nichts zu tun, mit Ausnahme derjenigen, die den Status der IRQ-Maskierung ändern. Aufgrund der Vorkaufsfrist, selbst wenn Sie nie erwarten, dass Ihr Code auf einem SMP-System ausgeführt wird, müssen Sie noch ordnungsgemäße Sperrung implementieren.

Meine Zweifel/Fragen sind:

a) Ist preemptive Linux-Kernel in den Kernel standardmäßig? Wenn ja, ist diese Vorkaufsfrist auf Prozesse beschränkt oder können Interrupt-Handler auch vorweggenommen werden?

b) Unterstützt Linux Kernel (auf ARM) verschachtelte Interrupts? Wenn ja, hat jeder Interrupt-Handler (obere Hälfte) seinen eigenen Stack oder teilen sie denselben 4k/8k-Kernel-Modus-Stack?

c) Wenn ich SMP (Config_SMP) deaktivieren und Preemption (Config_preempt) spin-locks in meinen Treibern und Interrupt-Handler Sinn machen?

d) Wie Kernel-Handle-Interrupts während der Ausführung der oberen Hälfte ausgelöst werden, d. H. Werden sie deaktiviert oder maskiert?

Nach einigen googeln fand ich dies:

Für Kerne ohne CONFIG_SMP kompiliert und ohne CONFIG_PREEMPT spinlocks gar nicht existieren. Dies ist eine ausgezeichnete Design-Entscheidung: wenn niemand sonst in der gleichen Zeit ausgeführt werden kann, gibt es keinen Grund eine Sperre zu haben.

Wenn der Kernel ohne CONFIG_SMP kompiliert wird, aber CONFIG_PREEMPT ist Satz, dann deaktivieren spinlocks einfach Vorkaufsrecht, die verhindern, dass Rennen ausreichend ist. Für die meisten Zwecke können wir uns Vorkaufsrecht als äquivalent zu SMP vorstellen, und kümmern uns nicht separat darum.

Aber es gibt keine Kernel-Version oder Datum auf dem source.Kann jemand bestätigen, ob es noch für die neuesten Linux-Kernel gültig ist?

+0

Das sind vier Fragen, also teile es auf, da sie nicht zusammen beantwortet werden können. –

Antwort

6

a) Ob Linux präventiv ist oder nicht, hängt davon ab, ob oder nicht, konfigurieren Sie es so
mit CONFIG_PREEMPT. Es gibt keinen Standard. Wenn Sie make config ausführen, müssen Sie wählen.

b) Interrupts verschachteln unter Linux; Während Interrupts verarbeitet werden, können andere Interrupts ausgehen. Das gilt für ARM und zahlreiche andere Architekturen. Es ist alles auf dem gleichen Stapel. Der User-Space-Stack wird natürlich nicht für Interrupts verwendet!

c) Wenn Sie SMP und Vorkaufsrecht zu deaktivieren, spinlocks im Code No-op zu reduzieren, wenn sie die regulären spinlocks sind, und IRQ spinlocks (spin_lock_irqsave/spin_lock_irqrestore) wird in Interrupt drehen aktivieren/deaktivieren. Letztere sind daher immer noch notwendig; Sie verhindern Rennen zwischen Aufgaben, die Ihren Code ausführen, und unterbrechen die Ausführung Ihres Codes.

d) Die "obere Hälfte" bezieht sich traditionell auf Interrupt-Service-Routinen. Der obere halbe Code eines Treibers wird von Interrupts ausgeführt. Die untere Hälfte wird von Tasks (zum Lesen oder Schreiben von Daten oder was auch immer) aufgerufen. Details der Interrupt-Behandlung sind architekturspezifisch.

Ich arbeitete zuletzt sehr eng mit Linux-Interrupts auf einer bestimmten MIPS-Architektur. Auf dieser speziellen Platine gab es 128 Interrupt-Leitungen, die über zwei 64-Bit-Wörter maskierbar waren. Der Kernel implementierte darüber hinaus ein Prioritätsschema, so dass vor der Ausführung eines Handlers für einen gegebenen Interrupt die unteren über Aktualisierungen dieser 2 × 64-Bit-Register maskiert wurden. Ich implementierte eine Modifikation, so dass die Unterbrechungsprioritäten willkürlich anstatt durch die Hardware-Position und dynamisch durch Schreiben von Werten in einen /proc Eintrag gesetzt werden konnten. Außerdem habe ich einen Hack eingefügt, bei dem sich ein Teil der numerischen IRQ-Priorität mit der Echtzeitpriorität von Aufgaben überlappt. So waren RT-Aufgaben (d. H. Benutzerraumthreads), die einem bestimmten Bereich von Prioritätsstufen zugeordnet waren, imstande, einen bestimmten Bereich von Unterbrechungen während des Laufens implizit zu unterdrücken. Dies war sehr nützlich, um zu verhindern, dass sich schlecht benehmende Interrupts bei kritischen Aufgaben störten (zum Beispiel eine Interrupt-Serviceroutine im IDE-Treibercode für den Compact Flash, die aufgrund einer schlecht gestalteten Hardware-Schnittstelle Busy-Schleifen ausführt und Flash-Schreibvorgänge verursacht die De-facto-Aktivität mit der höchsten Priorität im System werden.) Wie auch immer, das IRQ-Maskierungsverhalten ist nicht in Stein gemeißelt, wenn Sie die Kontrolle über den von den Kunden verwendeten Kernel haben.

Die zitierte Aussage in der Frage zu regulären spinlocks nur wahr ist (spin_lock Funktion/Makro) nicht IRQ spinlocks (spin_lock_irqsave). In einem präemptiven Kernel auf einem Uniprozessor muss spin_lock die Vorbelegung nur deaktivieren, was ausreicht, um alle anderen Aufgaben bis spin_unlock aus dem Kernel herauszuhalten. Aber spin_lock_irqsave muss Interrupts deaktivieren.

Verwandte Themen