Autor Thema: SMP und die damit verbundenen Probleme  (Gelesen 26513 mal)

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #40 am: 21. October 2010, 20:54 »
Zitat von: erik
Du versuchst da Äpfel mit Birnen zu vergleichen.
Möglich.

Zitat von: erik
Aber wenn Du in einem Stück Software einen Fehler findest dann kannst Du den beheben und neu compilieren und gut is.
Ich vermute mal das es schon soetwas gibt, dass man um irgendwelche Fehler in irgendeiner Software drumrumprogrammiert.

Zitat von: erik
Wenn Du doch mehrere Locks benötigst dann musst Du 100%-tig darauf achten dass das wirklich immer in der selben Reihenfolge passiert (es wäre eigentlich schön wenn es für sowas ein Tool gäbe).
Logisch und nicht mein Problem.

Wenn man nur den BKL (wie ich übrigens vorhin lesen durfte, gibt es den ja immernoch) nutzt hat man natürlich ein leichtes Leben.

Ich habe aber halt viele Locks und da kommt dann durchaus mal die Situation auf das Thread A den Lock 1 hat und Lock 2 versucht zu bekommen. Thread B hat Lock 2 und will Lock 1 und solche Situationen sind ab einer gewissen Größe schlecht zu überschauen (jetzt komm mir ja nicht mit Dokumentation ;) ).
Das ist so "meine" Quelle für Deadlocks, vorallem welche die sich schlecht bis gar nicht finden lassen (da sie nie auftreten oder so selten das man sie nicht reproduzieren kann).

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #41 am: 21. October 2010, 21:53 »
Hallo,


Ich vermute mal das es schon soetwas gibt, dass man um irgendwelche Fehler in irgendeiner Software drumrumprogrammiert.
Sicher gibt es das, es gibt ne Menge schlechter Manager die einem zu knappe Zeitpläne aufdrücken und es gibt ja auch noch schlechte Programmierer.

Logisch und nicht mein Problem.
Na scheinbar ist das doch Dein Probem, wie Du ja selber schreibst.

da kommt dann durchaus mal die Situation auf das Thread A den Lock 1 hat und Lock 2 versucht zu bekommen. Thread B hat Lock 2 und will Lock 1
Genau das darf es nicht geben! Das ist fehlerhafter Code. Es darf absolut keinen Ausführungspfad geben der zu so einer Situation führen kann (genau dafür hätte ich gerne ein Toll das sowas automatisch prüft).

und solche Situationen sind ab einer gewissen Größe schlecht zu überschauen (jetzt komm mir ja nicht mit Dokumentation ;) ).
Doch, ich komme Dir jetzt mit Dokumentation und Planung. Wenn Du eben solche Probleme vermeiden willst dann musst Du Dir angewöhnen sauberer zu programmieren und dazu gehört immer auch ne anständige Dokumentation, vor allem bei etwas so komplexen wie einem SMP-OS-Kernel. Wenn Du Deine SW gut dokumentierst und planst wirst Du merken das sich solche Probleme relativ einfach entdecken lassen, noch bevor Du den Compiler anwirfst. Du bekommt dadurch einen viel besseren Überblick, probiere es doch mal aus.


Grüße
Erik
« Letzte Änderung: 21. October 2010, 21:57 von erik.vikinger »
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #42 am: 21. October 2010, 22:06 »
Zitat von: erik
Na scheinbar ist das doch Dein Probem, wie Du ja selber schreibst.
Wo? Ich meine es geht darum das man Lock 1 bekommt, dann Lock 2 und nicht erst Lock 1 sondern Lock 2 freigibt, oder? Man gibt die Locks nach dem LIFO-Prinzip wieder frei.

Daran halte ich mich!

Zitat von: erik
Du bekommt dadurch einen viel besseren Überblick, probiere es doch mal aus.
Dokumentation, ist für mich das selbe wie Zwischenergebnisse in der Schule ;) Die habe ich meistens auch nicht aufgeschrieben.

Ich hatte mal mit ner Dokumentation angefangen, wo ich beschrieben habe was die Parameter machen/beinhalten, aber ich habe irgendwann festgestellt, das ich einfach nur aus nem alles sagenden Namen nen Satz gemacht habe, also zwecklos.
Was ich machen müsste, ist die Funktionalität einer Funktion zu beschreiben, aber auch das kann man bei mir aus dem Namen ableiten, bleibt nur noch das ich aufschreiben sollte, welche Locks benutzt werden.
Dann müsste ich mind. einmal (zu Dokumentationszwecken) alle meine Funktionen mit allen Funktionsaufrufen durchgehen um herauszufinden welche das sind.
Vielleicht mache ich das sogar, habe ich wenigstens was zu tun ;)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #43 am: 22. October 2010, 13:22 »
Hallo,


Ich meine es geht darum das man Lock 1 bekommt, dann Lock 2 und nicht erst Lock 1 sondern Lock 2 freigibt, oder? Man gibt die Locks nach dem LIFO-Prinzip wieder frei.
Das Du das LIFO-Prinzip beim locken -- entlocken einhältst habe ich nicht bezweifelt.
Dein Problem ist das es Code gibt der erst Lock 1 und dann Lock 2 will und das es ebenfalls Code gibt der erst Lock 2 und dann Lock 1 will. Genau das ist ein Bug! Sowas führt zu Deadlocks und muss 100%-tig vermieden werden!

Dokumentation, ist für mich das selbe wie Zwischenergebnisse in der Schule ;) Die habe ich meistens auch nicht aufgeschrieben.
Das mag in der Schule noch funktionieren (ich hab das auch nur selten gemacht und auch ein paar mal deswegen ne schlechtere Note bekommen obwohl das Ergebnis richtig war) aber bei großen Projekten, und ein OS ist ein großes Projekt, kann man sich solche Schlampigkeiten nicht leisten. Sonst endet man genau da wo Du jetzt bist und ärgert sich mit sporadischen Deadlocks rum.

....
Vielleicht mache ich das sogar, habe ich wenigstens was zu tun ;)
Mach das. Vielleicht lernst Du dabei sogar das gut strukturierte Arbeit viel effizienter geht. ;)


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #44 am: 22. October 2010, 13:36 »
Zitat von: erik
Dein Problem ist das es Code gibt der erst Lock 1 und dann Lock 2 will und das es ebenfalls Code gibt der erst Lock 2 und dann Lock 1 will. Genau das ist ein Bug! Sowas führt zu Deadlocks und muss 100%-tig vermieden werden!
Richtig.

Das Problem was ich mit meiner sporadischen Deadlock hatte, war ein wenig komplexer und ließ sich im Endeffekt nur dadurch lösen das ich jetzt IPI-Nachrichten per NMI schicke.

Da hatte eine CPU (A) den Lock 1 und wollte Lock 2 haben. Lock 2 hatte habe ne andere CPU (B) und diese hat ne IPI-Nachricht gesendet und darauf gewartet das CPU A die Nachricht abarbeitet, das konnte aber nie passieren, weil CPU A noch Lock 1 hatte und damit die Ints auswaren. Ich weiß nicht ob das nen klassischer Deadlock ist, weil die Locks ansich haben erstmal nichts mit einander zu tun, nur die Tatsache der ausgeschalteten Ints war ein Problem.

Zitat von: erik
(ich hab das auch nur selten gemacht und auch ein paar mal deswegen ne schlechtere Note bekommen obwohl das Ergebnis richtig war)
Wenn ich es nicht besser wüsste, würde ich sagen wir hatten die gleichen Lehrer ;)

Zitat von: erik
Mach das. Vielleicht lernst Du dabei sogar das gut strukturierte Arbeit viel effizienter geht.
Das kann ich dir ja dann erzählen.

Aber auch ne Dokumentation hilft nicht, wenn man Fehler an der falschen Stelle sucht ;) (War mein Problem, habe alles auf ne Deadlock geschoben, aber der Code hatte nen Fehler)

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #45 am: 22. October 2010, 14:18 »
Zitat von: svenska
Dir geht es darum, Locks ohne Schaden entziehen zu dürfen.
Auch, aber die ReadWrite-Sache könnte unter Umständen der Performance helfen.
Nein, dein Ausgangspunkt war das schadenfreie Entziehen von Locks!

Zitat von: svenska
Du darfst dir aber gerne sogenannte lock-free data-structures anschauen, sowas gibt es inzwischen auch.
Ich weiß, die eine Sache dazu die ich mir angesehen habe, war aber (meiner Meinung nach) Unfug bzw. auch nur nen Lock nur halt anders implementiert.
Ich habe mich damit nicht befasst, aber du kannst ein Problem, welches eine Zugriffssperre erfordert, nicht ohne Zugriffssperre umgehen. Das ist in der Natur der Sache.

Zitat von: svenska
Deadlocks geschehen entweder reproduzierbar aus Logikfehlern
Naja, einige Deadlocks die ich schon hatte, waren leider nicht so wirklich reproduzierbar, weil nämlich die Zeit (gerade auf SMP Systemen) auch nen Faktor spielt und das kann man immer so schlecht reproduzieren.
Den zweiten Teilsatz lesen können? ...oder schlecht reproduzierbar durch Race Conditions, also ungenügend/schlecht geschützte Strukturen...

Zitat von: svenska
Ersteres kann nur durch Nachdenken behoben werden
Das ist mir auch durch den Kopf gegangen, dass Deadlocks ja eigentlich ganz "einfach" zu lösen sind. Das beste gegen Deadlocks ist keine Locks zu benötigen, ansonsten sollte man versuchen das man immer nur einen Lock zur gleichen Zeit haben darf, dann können (eigentlich) auch keine Deadlocks auftreten.
Schlug ich bereits vor, nennt man GIANT_LOCK. Funktioniert und ist schneller als CPU-Festpinnen. Langsamer als gute Granularität.

Zitat von: svenska
Das ist Symptombehebung und damit Blödsinn.
Dem muss ich mal wiedersprechen. Ich bin mir jetzt nicht sicher ob man das als Symptom bezeichnen kann, aber z.B. CPU-Bugs die fixed du ja auch nicht (wie auch ;) ), sondern du versuchst das Problem zu umgehen (weiß nicht wie ich es anders sagen soll) und das ist auch kein Blödsinn, sondern einfach nötig.
Ich als Anwendungsprogrammierer muss damit leben, richtig. Ich als Systembesitzer ziehe mir (in der Theorie) ein BIOS-Update. Dieses BIOS-Update aktualisisiert mir bei jedem Systemstart den CPU-Mikrocode und fixt damit das Problem. Ich als Betriebssystementwickler stelle eine solche Schnittstelle dem Systembesitzer zur Verfügung, sodaß dieser die aktualisierten Mikrocodes auch ohne BIOS-Update einspielen kann.

Der Blödsinn liegt darin begründet, dass du grundlos Sympthombehebung durchführst. Ein CPU-Bug lässt dir keine andere Wahl, es sei denn du baust die CPU selbst.

Zitat von: erik
Aber wenn Du in einem Stück Software einen Fehler findest dann kannst Du den beheben und neu compilieren und gut is.
Ich vermute mal das es schon soetwas gibt, dass man um irgendwelche Fehler in irgendeiner Software drumrumprogrammiert.
Korrekt. Besonders in Produktionsumgebungen, wo man stabile und bekannte Softwareversionen benötigt, wird das so getan. Allerdings trifft das nur dann zu, wenn die zu benutzende Software nicht selbstgeschrieben ist. Kurz: Wenn möglich, wird gefixt. Erst wenn unmöglich oder nicht mehr sinnvoll, wird mit Workarounds gearbeitet.

Ich habe aber halt viele Locks und da kommt dann durchaus mal die Situation auf das Thread A den Lock 1 hat und Lock 2 versucht zu bekommen. Thread B hat Lock 2 und will Lock 1 und solche Situationen sind ab einer gewissen Größe schlecht zu überschauen (jetzt komm mir ja nicht mit Dokumentation ;) ).
Dann solltest du vielleicht dokumentieren, wie du dir gewisse Dinge vorstellst oder es einfach direkt richtig machen. Wenn (b) nicht geht, musst du halt doch (a) machen.

Wenn du weißt, dass dein Design kaputt ist, warum machst du dann keins, welches weniger kaputt ist?

Das ist so "meine" Quelle für Deadlocks, vorallem welche die sich schlecht bis gar nicht finden lassen (da sie nie auftreten oder so selten das man sie nicht reproduzieren kann).
Das nennt man Race-Condition.

Zitat von: erik
Na scheinbar ist das doch Dein Probem, wie Du ja selber schreibst.
Wo? Ich meine es geht darum das man Lock 1 bekommt, dann Lock 2 und nicht erst Lock 1 sondern Lock 2 freigibt, oder? Man gibt die Locks nach dem LIFO-Prinzip wieder frei.

Daran halte ich mich!
Offensichtlich nicht immer oder nicht gut genug. Und wenn CPU1 erst Lock 1 und dann Lock 2 anfragt und CPU2 genau umgekehrt, dann hast du ein anderes wichtiges Prinzip verletzt.

Ich hatte mal mit ner Dokumentation angefangen, wo ich beschrieben habe was die Parameter machen/beinhalten, aber ich habe irgendwann festgestellt, das ich einfach nur aus nem alles sagenden Namen nen Satz gemacht habe, also zwecklos.
Was ich machen müsste, ist die Funktionalität einer Funktion zu beschreiben, aber auch das kann man bei mir aus dem Namen ableiten, bleibt nur noch das ich aufschreiben sollte, welche Locks benutzt werden.
Blödsinn. Was offensichtlich ist, muss man nicht unbedingt dokumentieren. Du erklärst Programme ja hoffentlich auch nicht mehr zeilenweise?

Wie wäre es mit einer Block-Übersicht, die die einzelnen Abhängigkeiten der Einzelteile untereinander dokumentiert? Genau diese Abhängigkeiten (=Schnittstellen) musst du definieren. Das machst du rekursiv von oben und soweit wie nötig. Also die einzelnen Blöcke wieder soweit einzeln dokumentieren, bis man den Überblick wieder hat. Zu den Schnittstellen gehören die zu schützenden Datenstrukturen (soweit vorhanden) und daraus ergibt sich innerhalb einer Ebene auf einen Blick, welche Locks wo verwendet werden.

Und sowas macht man parallel mit dem Projekt - geht einfach und schnell nebenher, wenn etwas funktioniert - , bei verteilten Großprojekten macht man das vorher in der Designphase.

Aber auch ne Dokumentation hilft nicht, wenn man Fehler an der falschen Stelle sucht ;) (War mein Problem, habe alles auf ne Deadlock geschoben, aber der Code hatte nen Fehler)
Darum dokumentiert man. Entweder, um gewisse Fehler von vornherein ausschließen zu können (oder stark eingrenzen zu können), oder um "mal schnell" in der Logik nachzuschauen, ob das überhaupt so geht. Die Logikprüfung muss immer aus der Vogelperspektive sehen, denn selbst wenn alle Einzelteile logisch fehlerfrei sind, muss es das Gesamtsystem noch lange nicht sein.

Gruß,
Svenska

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #46 am: 22. October 2010, 15:23 »
Zitat von: svenska
Schlug ich bereits vor, nennt man GIANT_LOCK.
Dann hast du mich nicht richtig verstanden, ich meinte nicht einen GIANT_LOCK, sondern viele kleine Locks, aber man darf immer nur eine dieser Locks zur gleichen Zeit haben!

Zitat von: svenska
Wenn du weißt, dass dein Design kaputt ist, warum machst du dann keins, welches weniger kaputt ist?
Weil mir kein besseres einfällt ;) (was mir gefällt/zusagt)

Ihr könnt mir aber gerne eins vorschlagen und ich sage dann was mir nicht gefällt ;)

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #47 am: 22. October 2010, 15:34 »
Damit schützt du dann die vielen kleinen Locks selbst durch ein gigantisches Locking-Lock. Ist also ein GIANT_LOCK.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #48 am: 22. October 2010, 17:44 »
Hallo,


Weil mir kein besseres einfällt ;) (was mir gefällt/zusagt)
Wenn Du jemals zum Ziel (SMP fähiges OS) kommen willst sollte Dir aber eines ohne Deadlocks gefallen/zusagen! ;)


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #49 am: 22. October 2010, 21:58 »
Zitat von: svenska
Damit schützt du dann die vielen kleinen Locks selbst durch ein gigantisches Locking-Lock. Ist also ein GIANT_LOCK.
Häh?! Ich will die Locks nicht durch einen großen Lock schützen (wäre auch totaler unfug), sondern ich müsste halt meine Datenstrukturen und Algorithmen so auslegen, das du immer nur einen Lock zur gleichen Zeit haben darfst/kannst. Es gibt trotzdem viele verschiedene Locks.

Zitat von: erik
Wenn Du jemals zum Ziel (SMP fähiges OS) kommen willst sollte Dir aber eines ohne Deadlocks gefallen/zusagen!
Meine Deadlocks bin ich ja losgeworden (bis wieder eins auftritt ;) ). Ich finde mein Design gar nicht so schlecht, aber ihr könnt halt gerne andere Vorschlagen. Mein "Problem" ist im Endeffekt ja "nur" der VMM bzw. habe ich das ja jetzt im Griff.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #50 am: 23. October 2010, 11:11 »
Zitat von: svenska
Damit schützt du dann die vielen kleinen Locks selbst durch ein gigantisches Locking-Lock. Ist also ein GIANT_LOCK.
Häh?! Ich will die Locks nicht durch einen großen Lock schützen (wäre auch totaler unfug), sondern ich müsste halt meine Datenstrukturen und Algorithmen so auslegen, das du immer nur einen Lock zur gleichen Zeit haben darfst/kannst. Es gibt trotzdem viele verschiedene Locks.
Okay, also wenn du sagst "Du darfst nur ein Lock zur gleichen Zeit haben", dann ist das eine Policy, weil es nicht erzwungen wird. Ein böswilliger Angreifer könnte somit durch einen Treiber dein System in ein Deadlock bringen (oder wenn du es irgendwann vergisst und selbst Deadlocks produzierst).

Wenn du sagst "Du kannst nur ein Lock zur gleichen Zeit haben", fallen mir da nur zwei Möglichkeiten ein.. entweder es gibt nur ein Lock systemweit (giant lock) oder es gibt viele kleine Locks, wie von dir vorgeschlagen. Um durchzusetzen, dass du nur eins haben kannst, musst du also die Locks selbst schützen, was auf den ersten Ansatz hinausläuft.

Wenn du sagst "Du brauchst zu jedem Zeitpunkt nur ein Lock", dann ist das schön, aber ich glaube nicht immer machbar (das ist ebenfalls eine Art giant lock, nur ohne Performance-Verlust, weil alles darauf ausgelegt ist).

Oder ich versteh deinen Gedankengang nicht.

Gruß

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #51 am: 23. October 2010, 11:43 »
Ich hab zwar den Thread nicht gelesen, aber habe zu dem ganzen Thema zwei Anmerkungen:
* Es gibt lockfreie Algorithmen für mehrere Datenstrukturen, für einen Stack und eine Queue sind die m.E. nach ziemlich einfach. Es gibt auch eine für einen std::vector (ohne Iteratoren) und ich hab gelesen dass es welche für einen Baum, eine Hashmap und eine Deque gibt. Man muss dabei allerdings aupassen, da die meisten der Originalalgorithmen garbage collection voraussetzen und erst durch Anwendung von hazard pointern auch ohne garbage collection korrekt implementierbar sind. Ein damit zusammenhängendes, sehr subtiles Problem ist das ABA-Problem. (Alle vorkommenden unbekannten Sachen sollten googlebar sein, aber ich kann natürlich auch gerne mehr dazu sagen, falls Interesse besteht)
* Wenn man a priori weiß in welcher Reihenfolge Locks gehalten werden können, dann kann man jedem Lock eine Nummer geben und beim holen des Locks überprüfen, ob die max. Nummer aller momentan gehaltenen Locks kleiner als die des neuen Locks ist und falls nicht, eine Fehlermeldung ausgeben. Das könnte eventuell das Debuggen erleichtern.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #52 am: 23. October 2010, 22:24 »
Wenn du sagst "Du kannst nur ein Lock zur gleichen Zeit haben", fallen mir da nur zwei Möglichkeiten ein.. entweder es gibt nur ein Lock systemweit (giant lock) oder es gibt viele kleine Locks, wie von dir vorgeschlagen. Um durchzusetzen, dass du nur eins haben kannst, musst du also die Locks selbst schützen, was auf den ersten Ansatz hinausläuft.
Nicht wirklich. Der Unterschied ist, gegen wen du die Locks schützt. Wenn du einen Lock für die Locks hättest, würdest du anderen Threads verbieten, einen Lock zu holen, während du gerade einen hast. Wenn ich es richtig verstanden habe, will FlashBurn aber nur dem eigenen Thread verbieten, einen zweiten Lock zu nehmen - das läuft dann nicht mehr unter Locks locken, sondern ist irgendein anderer Mechanismus. Ein ziemlich trivialer sogar: lock() muss thread->current_lock setzen und wenn es schon gesetzt war, gibt es einen Panic.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #53 am: 23. October 2010, 22:37 »
Zitat von: taljeth
Wenn ich es richtig verstanden habe, will FlashBurn aber nur dem eigenen Thread verbieten, einen zweiten Lock zu nehmen
Wenigstens einer der mich verstanden hat ;)

Ich meine wirklich das man halt in einer Funktion nur einen Lock haben darf und dann auch keine andere Funktion aufrufen darf (ohne den Lock freizugeben), die wieder nen Lock haben will.

Zitat von: svenska
Ein böswilliger Angreifer könnte somit durch einen Treiber dein System in ein Deadlock bringen (oder wenn du es irgendwann vergisst und selbst Deadlocks produzierst).
Zu monolithisch gedacht. Wenn mein Kernel sich an meine Regeln hält läuft das erstmal alles. Was dann in den Treibern passiert ist ne ganz andere Sache. Da kannst du im Prinzip Deadlocks nicht verhindern (wenn man davon ausgeht, das man den Treiber nicht selbst geschrieben hat). Zumal der Vorteil eines Mikrokernels dann genau das ist, das während einer Lock die Ints nicht deaktiviert werden können (ja, ich weiß könnte man auch im Kernel machen, aber wozu?).

Zitat von: svenska
Oder ich versteh deinen Gedankengang nicht.
Ich hoffe du verstehst es jetzt ;)

Ich will diesen Ansatz (nur ein Lock zur gleichen Zeit) ja auch nicht per Gewalt durchsetzen, sondern das sollte halt einfach ne Programmierregel sein, dass das schwer bis eventuell sogar gar nicht durchzusetzen ist, steht auf einem anderen Blatt.

Zitat von: bluecode
aber ich kann natürlich auch gerne mehr dazu sagen, falls Interesse besteht
Ich denke wir alle wären an mehr Informationen oder Hinweise in der Richtung Algos ohne Locks sehr interessiert.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #54 am: 25. October 2010, 21:46 »
Hmm, klingt nachvollziehbar. Ich mag Threading nicht, das ist mir alles zu verwurstet. :-p

Um das umzusetzen müsstest du aber zu jeder Funktion dokumentieren, ob sie ein Lock braucht (was nicht immer vorhersehbar ist) und das darf sich ja dann auch nicht nachträglich ändern. Unschön, aber machbar.

Was machst du aber, wenn du einen Anwendungsfall hast, für den du zwei Locks brauchst (z.B. einmal die PCI-Datenstrukturen und einmal die Puffer-/Speicherstrukturen zur Übergabe der Daten der Netzwerkkarte)?

Ich weiß nicht, ob sich das durch eine so simple Policy lösen lässt. (Besonders nicht, wenn die Policy als Workaround für ein schlechtes Design eingeführt wurde.)

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #55 am: 25. October 2010, 21:53 »
Zitat von: svenska
Ich weiß nicht, ob sich das durch eine so simple Policy lösen lässt. (Besonders nicht, wenn die Policy als Workaround für ein schlechtes Design eingeführt wurde.)
Also erstmal lässt sich diese Policy nicht wirklich umsetzen, da man immer irgendwo mind. 2 Locks zur gleichen Zeit hat/braucht.

Und mein "schlechtes" Design hatte halt "nur" das Problem das ich nicht wusste wie man IPI-Nachrichten an CPUs sendet die die Ints aus haben (was ja inzwischen gelöst ist).
Mich würde aber auch mal interessieren wie andere OSe das lösen.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #56 am: 26. October 2010, 10:30 »
Hallo,


aber ich kann natürlich auch gerne mehr dazu sagen, falls Interesse besteht)
Ein klein wenig mehr wäre schon nicht schlecht. Das Problem was ich bei vielen dieser lock-freien Datenstrukturen vermute ist das diese wohl nicht immer sehr effizient zu durchsuchen sind oder andere Nachteile haben. Eine doppelt verkettete Liste geht IMHO nicht lock-frei aber man kann recht effizient darin navigieren und sie bietet ein gewisses Maß an zusätzlicher Sicherheit wegen der Redundanz bei den Pointern. Die Frage ist natürlich wie schwerwiegend diese eventuellen Nachteile der lock-freien Datenstrukturen überhaupt sind.


Ich mag Threading nicht, das ist mir alles zu verwurstet. :-p
Bist wohl Vegetarier wenn Du nichts verwurstetes magst? Also ich mag Threading sehr, da ist alles so schön parallel. :-D

Um das umzusetzen müsstest du aber zu jeder Funktion dokumentieren, ob sie ein Lock braucht (was nicht immer vorhersehbar ist) und das darf sich ja dann auch nicht nachträglich ändern. Unschön, aber machbar.
Das sollte man bei einem Projekt, wie einem OS-Kernel, aber immer sauber dokumentieren. Klar macht das Arbeit, aber es ist IMHO nicht "unschön".

Ich weiß nicht, ob sich das durch eine so simple Policy lösen lässt.
Mit an Sicherheit grenzender Wahrscheinlichkeit nicht, wenn man keinen GIANT-Lock will sondern viele kleine Locks dann wird man ganz sicher mal vor der Notwendigkeit stehen mehrere davon haben zu müssen.

(Besonders nicht, wenn die Policy als Workaround für ein schlechtes Design eingeführt wurde.)
lol, besser hätte ich das auch nicht formulieren können.


Und mein "schlechtes" Design hatte halt "nur" das Problem das ich nicht wusste wie man IPI-Nachrichten an CPUs sendet die die Ints aus haben (was ja inzwischen gelöst ist).
Ich würde schon sagen das Dein Design schlecht oder zumindest fehlerhaft ist/war.
Siehe:
Da hatte eine CPU (A) den Lock 1 und wollte Lock 2 haben. Lock 2 hatte habe ne andere CPU (B) und diese hat ne IPI-Nachricht gesendet und darauf gewartet das CPU A die Nachricht abarbeitet, das konnte aber nie passieren, weil CPU A noch Lock 1 hatte und damit die Ints auswaren. Ich weiß nicht ob das nen klassischer Deadlock ist, weil die Locks ansich haben erstmal nichts mit einander zu tun, nur die Tatsache der ausgeschalteten Ints war ein Problem.
Das Problem steckt in den ersten 20 Worten. Das jemand Lock 2 hat ohne Lock 1 zu haben obwohl an anderer Stelle Lock 2 nur innerhalb von Lock 1 benutzt wird und dann gegenseitige Abhängig auftritt ist ein Bug/Deadlock. Sowas darf es nicht geben! Diesmal hat das die Benutzung der IPIs blockiert (das konntest Du per NMI lösen) aber in einer anderen Situation, wo Du wieder vor einem derartigen Deadlock stehst, lässt sich das vielleicht nicht so einfach lösen. Das es überhaupt 2 verschieden Pfade gibt um an Lock 2 zu kommen, einmal mit Lock 1 und einmal ohne, das ist Dein Problem!


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #57 am: 26. October 2010, 10:46 »
Zitat von: erik
Ich würde schon sagen das Dein Design schlecht oder zumindest fehlerhaft ist/war.
Ich kann mit Kritik leben, dann aber bitte auch konstruktiv!

Ich denke dafür wäre aber mal wieder ein neuer Thread nötig, aber nur wenn interesse darin besteht mal ein VMM Design zu diskutieren!?

Zitat von: erik
Das es überhaupt 2 verschieden Pfade gibt um an Lock 2 zu kommen, einmal mit Lock 1 und einmal ohne, das ist Dein Problem!
Lässt sich wie du schon weiter oben mal geschrieben hattest, leider nicht (oder nicht so einfach??) vermeiden.

Ein ähnlicher Fall wäre, dass 2 Prozesse ne Page gemappt haben und dafür haben sie unterschiedliche Locks (weil 2 unterschiedliche Adressräume) und dann wollen beide den Lock um die IPI-Nachricht zu senden. Also ist es gar nicht so ungewöhnlich auf 2 Wegen an ein und die selbe Lock zu kommen (das ist woanders auch noch so)!
Ein weiteres Bsp. wäre, dass man nen Lock für irgendeine Datenstruktur hat und dann neuen Speicher braucht und ne Page mappt, dann hast du einmal den Lock für die jeweilige Datenstruktur und einmal willst du den gleichen Lock für den Adressraum haben.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #58 am: 26. October 2010, 11:40 »
Das es überhaupt 2 verschieden Pfade gibt um an Lock 2 zu kommen, einmal mit Lock 1 und einmal ohne, das ist Dein Problem!
Öhm, wenn ich mal eine ganz blöde Frage stellen darf: Wenn man Lock 2 nur nehmen dürfte, wenn man Lock 1 auf jeden Fall schon hat, wäre dann Lock 2 nicht überflüssig? Und wenn man es nur nehmen darf, wenn man keinen anderen Lock hat, ist man wieder bei FlashBurns Policy.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #59 am: 26. October 2010, 11:43 »
Hallo,


Ich kann mit Kritik leben, dann aber bitte auch konstruktiv!
Sorry, aber ich bin schon der Meinung das meine Kritik "konstruktiv" war, ich hab doch unmittelbar darunter präzise erläutert worin ich das Problem sehe. Wenn Du bezüglich des von mir erläuterten Problems anderer Meinung bist dann musst Du mir das erklären oder wir können das auch gerne (in einem anderen Thread) anhand von konkretem Code diskutieren. Ich wollte Dir einfach nur erläutern warum ich der Meinung bin das Du Locks falsch benutzt.

Zitat von: erik
Das es überhaupt 2 verschieden Pfade gibt um an Lock 2 zu kommen, einmal mit Lock 1 und einmal ohne, das ist Dein Problem!
Lässt sich wie du schon weiter oben mal geschrieben hattest, leider nicht (oder nicht so einfach??) vermeiden.
Wo hab ich auch nur angedeutet das es unmöglich (oder auch nur schwierig) wäre Locks immer in der selben Reihenfolge zu holen? Ich hab geschrieben das es bei vielen Locks sicher auch mal Notwendig ist mehrere zu haben aber ich hab nicht geschrieben das es unmöglich (oder schwierig) ist diese in geordneter Reihenfolge zu holen.

Ein ähnlicher Fall wäre, dass 2 Prozesse ne Page gemappt haben und dafür haben sie unterschiedliche Locks (weil 2 unterschiedliche Adressräume) und dann wollen beide den Lock um die IPI-Nachricht zu senden.
Das ist ein Problem weil der Lock für die IPI-Benutzung eben indirekt verlangt das keine anderen Locks (mit gesperrten INTs) in Benutzung sind. Ich muss zugeben das IPI da schon ein gewisser Sonderfall ist, sowas hab ich auf meiner Plattform nicht und daher hab ich mir darüber noch nicht den Kopf zerbrochen. Die IPIs als NMI zu realisieren erscheint mir als guter Ausweg aus diesem Dilemma (im Prinzip mache ich das ja auch so indem ich diese Dinge direkt in HW abarbeite und in Kauf nehme das die gerade laufende SW dadurch kurzzeitig eventuell blockiert/verlangsamt wird) aber es schränkt auch ganz klar die Möglichkeiten der IPI-Handler ein (was aber wohl kein Problem ist).

Also ist es gar nicht so ungewöhnlich auf 2 Wegen an ein und die selbe Lock zu kommen (das ist woanders auch noch so)!
Dann dürftest Du noch ne Menge anderer verborgener Deadlocks in Deinem Code haben. Sorry, aber das sehe ich als eine "Schwäche" Deines Designs.

Ein weiteres Bsp. wäre, dass man nen Lock für irgendeine Datenstruktur hat und dann neuen Speicher braucht und ne Page mappt, dann hast du einmal den Lock für die jeweilige Datenstruktur und einmal willst du den gleichen Lock für den Adressraum haben.
Solange die Wege zu den einzelnen Locks keine Deadlocks produzieren sehe ich da kein Problem.


Siehe mal nach http://de.wikipedia.org/wiki/Deadlock (auch die Links sind recht interessant), dort ist "Circular Wait ausschließen" das richtige Stichwort. In dem von Dir (am Freitag) geschildertem und von mir kritisiertem IPI-Szenario hast Du eben genau so ein "Circular Wait".


Öhm, wenn ich mal eine ganz blöde Frage stellen darf: Wenn man Lock 2 nur nehmen dürfte, wenn man Lock 1 auf jeden Fall schon hat, wäre dann Lock 2 nicht überflüssig?
Hm, das ist ein berechtigter Einwand (und keine blöde Frage). Muss ich (oder besser wir alle) mal in Ruhe drüber nachdenken.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

 

Einloggen