Autor Thema: Shared Memory  (Gelesen 36176 mal)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #100 am: 02. October 2010, 15:50 »
Hallo,


while(1) asm("hlt") interessiert sich für den Stack herzlich wenig. Du kannst denselben Code also mit demselben Stack auf mehreren CPUs ausführen und es passiert immer noch nichts böses.
Sicher?

Jetzt muss ich mal meine letzten x86-Kenntnisse zusammenkratzen:
Gehen wir davon aus (ich hab gleich mal den Compiler laufen lassen):label_loop:
    hlt
    jmp   label_loop
und das soll in Ring 0 laufen (wegen dem HLT). Wenn jetzt ein IRQ kommt dann muss doch der aktuelle EIP (und noch einiges mehr) auf den Stack geschrieben werden und da wir bereits im Ring 0 sind kann die CPU nicht einen anderen Stack aus dem TSS nehmen (in den Gates in der IDT sind doch nur CS:EIP enthalten). Oder irre ich da? Wenn also mehrere CPUs auf IRQs reagieren müssen (ich weiß gar nicht ob das bei x86 überhaupt geht aber gehen wir mal davon aus es ginge, zumindest mit allen APICs sollte es gehen) dann würden IMHO die EIPs usw. alle auf dem selben Stack landen. Der kleine Code selber interessiert sich wirklich nicht für den Stack aber der IRQ, der ja nötig ist um HLT zu beenden, interessiert sich schon für den Stack.
Ich hoffe mal ich hab mich jetzt nicht zu sehr blamiert. :roll:


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 #101 am: 02. October 2010, 15:56 »
Nope, alles soweit korrekt.

Und genau deswegen (weil man ja eh alles braucht was man auch für Kernel-Threads braucht), sollten doch Kernel-Threads auf x86 nicht so schwer sein.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #102 am: 02. October 2010, 17:11 »
und das soll in Ring 0 laufen (wegen dem HLT). Wenn jetzt ein IRQ kommt dann muss doch der aktuelle EIP (und noch einiges mehr) auf den Stack geschrieben werden und da wir bereits im Ring 0 sind kann die CPU nicht einen anderen Stack aus dem TSS nehmen (in den Gates in der IDT sind doch nur CS:EIP enthalten). Oder irre ich da? Wenn also mehrere CPUs auf IRQs reagieren müssen (ich weiß gar nicht ob das bei x86 überhaupt geht aber gehen wir mal davon aus es ginge, zumindest mit allen APICs sollte es gehen) dann würden IMHO die EIPs usw. alle auf dem selben Stack landen. Der kleine Code selber interessiert sich wirklich nicht für den Stack aber der IRQ, der ja nötig ist um HLT zu beenden, interessiert sich schon für den Stack.
Hm, ja, ich habe nicht berücksichtigt, dass wir in Ring 0 sein müssen und daher keinen Stackwechsel kriegen. Ich könnte jetzt versuchen, mich mit Task Gates rauszureden, aber das ist natürlich nicht praktikabel, auch wenn es theoretisch wohl ginge. Ich gebe mich hier geschlagen. ;)
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 #103 am: 02. October 2010, 19:35 »
Hallo,


Ich könnte jetzt versuchen, mich mit Task Gates rauszureden, aber das ist natürlich nicht praktikabel, auch wenn es theoretisch wohl ginge.
Das könnte schon funktionieren aber ich glaube nicht das sowas schon mal jemand ernsthaft gemacht hat.
Ich denke wir sind heute auf ein faires Unentschieden gekommen. ;)


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 #104 am: 02. October 2010, 20:02 »
Zitat von: erik
Das könnte schon funktionieren aber ich glaube nicht das sowas schon mal jemand ernsthaft gemacht hat.
So blöd es klingt, doch ;)

Es wird dir nämlich empfohlen für bestimmte Exceptions nen TaskGate zu nehmen, weil dann ein neuer Stack geladen wird.

Wird unter OS-X nicht was ähnliches gemacht, wimre habe ich mal was gelesen das dort der Kernel gar nicht in jedem Prozess eingeblendet ist, sondern das nur ein "Stub" existiert der dann das PageDir wechselt, in den Kernel rein.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #105 am: 14. October 2010, 20:18 »
Ich habe mal wieder ein wenig an meinem VMM gearbeitet und SharedMemory macht mir noch immer sorgen :(

Ich bin jetzt soweit das ich für jede physikalische Page die gemappt ist einen refCount führe und in welchen Prozess sie gemappt ist (kann sogar mehrmals der selbe sein).

Ich überlege halt gerade ob es überhaupt Sinn macht zu wissen ob eine Page als SharedRead oder SharedWrite gemappt ist? Denn die einzige Info die ich mal irgendwann bräuchte wäre ob eine Page COW ist, damit ich dann entsprechend reagieren kann.
Ich wüsste halt nicht wozu ich wissen müsste das eine Page irgendwie geshared wird (also mehrmals gemappt ist) wenn ich eh nen refCount habe. Oder fällt euch ein Grund ein? (Es geht darum, das ich nen Flag mit in den PTE packe, ob eine Page SharedRead oder -Write ist)

Noch eine Frage zu COW. Ansich ist das ja ne klare Sache, man markiert eine Page in allen Prozessen, bis auf dem ersten Prozess, als COW und wenn dann geschrieben werden soll, dann wird ne neue Page allokiert und der Inhalt wird kopiert. Soweit so klar. Was ist aber wenn der erste Prozess beendet wurde und die Page nur noch in einem anderen Prozess gemappt ist, das Flag für COW steht da ja weiterhin drin, dann würde die Page kopiert werden obwohl das gar nicht nötig ist!?

Meine Lösung wäre halt, dass jedes Mal bevor eine neue Page allokiert und kopiert wird, nachgeguckt wird ob dies auch wirklich noch nötig ist.

Wie habt ihr das gelöst?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #106 am: 14. October 2010, 20:36 »
Noch eine Frage zu COW. Ansich ist das ja ne klare Sache, man markiert eine Page in allen Prozessen, bis auf dem ersten Prozess, als COW und wenn dann geschrieben werden soll, dann wird ne neue Page allokiert und der Inhalt wird kopiert.
So hätte ich das nicht gemacht. Ich würde die Seite in allen Prozessen als COW markieren. Dann tritt dein Problem nicht auf. Keine Sonderbehandlung für den ersten Prozess.
Dieser Text wird unter jedem Beitrag angezeigt.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #107 am: 14. October 2010, 20:38 »
Hallo,


ein RefCount müsste IMHO reichen, wenn der >1 ist dann ist klar das die Page in mehreren Prozessen gemappt ist.

COW-Pages müssen in allen Prozessen als RO gemappt sein, wenn das bei einem davon nicht so wäre dann würden die anderen Prozesse dessen Änderungen sehen und das darf ja nicht sein. Für eine COW-Page braucht man auch einen RafCount und wenn der >1 ist dann muss eine Kopie (für den Prozess der gerade versucht zu schreiben) erstellt werden und anschließend wird der RefCount dekrementiert. Wenn der RefCount bei 1 angekommen ist kann die Page auch für den letzten verbleibenden Prozess als RW markiert werden (spart immerhin eine Exception). Wenn ein Prozess gekillt wird ohne das er die COW-Page beschrieben hat dann muss der RefCount natürlich auch dekrementiert werden und wenn einer der Prozesse forkt dann wird inkrementiert.


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 #108 am: 14. October 2010, 20:51 »
Zitat von: erik
So hätte ich das nicht gemacht. Ich würde die Seite in allen Prozessen als COW markieren. Dann tritt dein Problem nicht auf. Keine Sonderbehandlung für den ersten Prozess.
Hast recht, ich hatte mir sorgen gemacht, wenn ich das im ersten Prozess auch mache, dass ich dann wieder das Problem habe, das ich eine Page leake, aber das ist ja nicht der Fall, weil ja alle anderen Prozesse die ursprüngliche Page haben und die darf ja nicht verändert werden.

Jetzt bin ich gerade dabei meine Henne-Ei-Problem zu lösen, das ich ohne einen funktionierenden VMM keine Pages mappen kann, weil dann auch immer die Struktur allokiert werden muss, für den refCount und den Prozess in welche die Page gemappt ist.

Eine Frage hätte ich noch. Ich will die Prozesse in denen eine Page gemappt ist speicher, um später auch eine Page die in mehreren Prozessen gemappt ist, auslagern zu können. Macht man sowas überhaupt, weil ich es mir auch schwer vorstelle überhaupt rauszubekommen, das die Page eigentlich in allen Prozessen lange nicht genutzt wurde?

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #109 am: 14. October 2010, 21:13 »
Ich würde ja behaupten, dass heutzutage genug RAM in einem Rechner verbaut ist, dass man sich darum nicht besonders kümmern muss. Wenn der RAM vollläuft wird der Plattencache entsorgt (unter der Annahme, dass der über alle Grenzen wachsen darf), reicht das nicht, werden einfach gemappte Pages entsorgt, reicht das auch nicht, werden mehrfach gemappte Pages entsorgt, reicht das nicht, kommt der OOM-Killer.

Meine Vermutung ist, dass die Zahl der mehrfach gemappten Pages verschwindend klein ist gegenüber der Menge an Pages, die jedes Programm für sich hat. Sind letztere alle ausgelagert, hast du ohnehin andere Probleme als noch eine effiziente Auslagerung nachzulegen...

Oder du ignorierst den Fakt komplett und lagerst einfach "Pages" aus und speicherst pro Page, ob sie alt/ungenutzt ist oder nicht. Wobei ich nicht weiß, wie sich das in deinem Mikrokernel implementieren ließe.

Gruß

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #110 am: 14. October 2010, 21:41 »
Zitat von: svenska
Meine Vermutung ist, dass die Zahl der mehrfach gemappten Pages verschwindend klein ist gegenüber der Menge an Pages, die jedes Programm für sich hat.
Unter der Annahme das der Speicher den ein Programm erst zur Laufzeit allokiert größer ist als das Image der Executeable.
Denn bei mir ist jedes Executeable (wenn die physikalischen Sektionen 4KB aligned sind) gemappt (so ist es effizienter wenn man das gleiche Executeable mehrmals ausführt).

Zitat von: svenska
Oder du ignorierst den Fakt komplett und lagerst einfach "Pages" aus und speicherst pro Page, ob sie alt/ungenutzt ist oder nicht. Wobei ich nicht weiß, wie sich das in deinem Mikrokernel implementieren ließe.
Das verstehe ich jetzt nicht. Denn du kannst den Fakt das eine Page gemappt ist, nicht einfach ignorieren. Ich meine stell dir mal vor, du lagerst eine solche Page aus und dort kommen jetzt andere Daten rein, dann sind diese Daten jetzt in allen Prozessen die diese Page auch gemappt hatten und wenn das dann noch Code war, wird es interessant ;)

Zum Thema wie man Paging in einem MikroKernel macht (der vorallem den VFS-Service nicht im Kernel hat) sollte es fast genauso funktionieren wie bei allen anderen auch (sag ich mal einfach so, da ich noch keine Ahnung davon habe ;) ). Nur das du halt den Inhalt der Pages erst an den VFS-Service schickst und dieser den dann in die Swap-Datei schreibt.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #111 am: 15. October 2010, 22:02 »
Das mit dem refCount für jede Page ist zwar ganz nett, aber zeigt leider, wieder einmal, große Design Probleme meines VMMs.

Ich überlege im Moment ob ich wirklich wissen muss in welchen Prozessen eine Page gemappt ist oder ob es nicht einfach reicht nen refCount zu haben?!

Problem ist mal wieder eine Henne-Ei-Geschichte. Jedes Mal wenn eine Page gemappt wird, wird halt eine Funktion aufgerufen, die den refCount erhöht und den laufenden Prozess in die Liste der Prozesse, die die Page gemappt haben, reinpackt. Soweit so gut, aber um den Prozess in die Liste zu packen oder um eine neue Page in meine Tabelle zu packen muss Speicher allokiert werden. Jetzt kann natürlich das Problem auftreten dass das in einer endlos Kette endet. Denn jedes mal wenn Speicher gebraucht wird, kann es ja sein, das eine neue Page gemappt werden muss damit ich neuen Speicher bekomme, aber wenn jetzt die neue Page gemappt werden soll, brauche ich ja wieder Speicher und da wird wieder festgestellt das ne neue Page benötigt wird und die muss wieder gemappt werden ... ne klassische Endlosschleife halt.

Mir ist leider noch kein Weg eingefallen (außer halt keine Liste mit Prozessen, sondern nur nen RefCount zu haben) das Problem zu lösen (bisher tritt es nur auf mehreren CPUs auf, nicht aber auf einer).

Habt ihr auch solche Henne-Ei-Probleme in eurem VMM und wenn ja, wie habt ihr sie gelöst?

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #112 am: 17. October 2010, 23:15 »
Naja, den Fakt, dass eine Page "shared" ist, kannst du im Swapping komplett ignorieren.

Du speicherst halt pro Page irgendwelche Informationen zur Nutzung, um deinen welche-page-auslagern-Algorithmus betreiben zu können und ignorierst den Zustand des Sharings komplett. Wird eine solche, von mehreren Programmen genutzte, Page ausgelagert, bricht natürlich die Systemperformance ein - unter der Voraussetzung, dass du aber genug RAM hast, spielt das keine Rolle.

Den Rest deines Problems kann ich nicht so recht nachvollziehen, wahrscheinlich auch, da ich weder das Zusammenspiel deiner Verwaltung zueinander noch das Paging im x86-speziellen kenne, daher kann ich dazu nichts sagen. Ich bezog mich also nur auf identische, in mehreren Prozessen gemappte, Pages.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #113 am: 18. October 2010, 10:14 »
Zitat von: svenska
Naja, den Fakt, dass eine Page "shared" ist, kannst du im Swapping komplett ignorieren.

Du speicherst halt pro Page irgendwelche Informationen zur Nutzung, um deinen welche-page-auslagern-Algorithmus betreiben zu können und ignorierst den Zustand des Sharings komplett. Wird eine solche, von mehreren Programmen genutzte, Page ausgelagert, bricht natürlich die Systemperformance ein - unter der Voraussetzung, dass du aber genug RAM hast, spielt das keine Rolle.
Naja, ignorieren würde ich das nicht unbedingt. Ich würde sogar sagen, das wenn eine Page bei mehr als 2 Prozessen gemappt ist, dann lohnt sich das Auslagern schon gar nicht mehr.

Bei mir ist es halt so das du von einem Prozess nicht in den anderen reingucken kannst (auch nicht vom Kernel aus und erst recht nicht auf die PageTables) und von daher kannst du ja nicht wissen ob die Page die du gerade in dem Prozess ausgewählt hast, in dem anderen Prozess auch nicht benötigt wird. Da müsstest du also erst mal das PD von dem anderen Prozess mappen, dann die PageTable um dann nachzusehen ob die Page eventuell ausgelagert werden kann.
Das ganze temporäre mappen in den KernelSpace dauert wahrscheinlich auch ein wenig und ich denke mal da lohnt es sich dann nicht mehr die Page noch auszulagern. Bei mehr als zwei Prozessen wird das noch aufwendiger und wenn man dann noch SMP dazunimmt kann man sich solche SharedPages wahrscheinlich ganz sparen.

Zitat von: svenska
Den Rest deines Problems kann ich nicht so recht nachvollziehen, wahrscheinlich auch, da ich weder das Zusammenspiel deiner Verwaltung zueinander noch das Paging im x86-speziellen kenne, daher kann ich dazu nichts sagen. Ich bezog mich also nur auf identische, in mehreren Prozessen gemappte, Pages.
Naja, die Deadlock lässt sich leider aufgrund meines Designs nicht vermeiden und das eigentliche Problem habe ich inzwischen auch gefunden (habe ja nen neuen Thread aufgemacht).

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #114 am: 18. October 2010, 11:50 »
Hallo,


die Deadlock lässt sich leider aufgrund meines Designs nicht vermeiden
Dann ist Dein Design fehlerhaft!


SCNR
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #115 am: 18. October 2010, 12:11 »
Zitat von: erik
Dann ist Dein Design fehlerhaft!
Naja, so schlimm ist es auch nicht. Nur habe ich bei meinem Design halt viele Henne-Ei-Probleme und die zu lösen ist nicht immer schön.

Mein Lieblingsbeispiel ist das Allokieren von Speicher. Während des Vorgangs passiert es das der SlabAllocator aufgerufen wird damit du Speicher für eine Verwaltungsstruktur bekommst. Dieser wiederrum könnte den Allocator aufrufen, weil er mehr Speicher benötigt.

Dass das so nicht funktionieren kann ist klar, aber solche ähnlichen Probleme müssten eigentlich bei anderen auch auftreten, wenn man denn nicht alles statisch macht.

Das "lustige" an dem Bsp. ist, das ich also nicht mehr den SlabAllocator aufrufe, sondern nen speziellen Allocator, der nur Speicher aus nem vorher festgelegten Bereich holt (ansonsten funktioniert er genauso wie ein SlabAllocator) und genau dieser Allocator macht mir jetzt gerade die Probleme mit meiner vmmMap() ;)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #116 am: 18. October 2010, 15:28 »
Hallo,


Nur habe ich bei meinem Design halt viele Henne-Ei-Probleme
Oh ja, sehr viele. Irgendetwas scheinst Du anders zu machen.

Mein Lieblingsbeispiel ist das Allokieren von Speicher. Während des Vorgangs passiert es das der SlabAllocator aufgerufen wird damit du Speicher für eine Verwaltungsstruktur bekommst. Dieser wiederrum könnte den Allocator aufrufen, weil er mehr Speicher benötigt.
Dazu ist es erforderlich das die Verwaltungsstrukturen immer mit etwas Überschuss alloziert werden. Wenn Du welche brauchst dann musst Du dem Allocator mitteilen ob es momentan sicher ist das er selber die Speicherverwaltung bemüht oder eben nicht. Der Überschuss ermöglicht es diesem Allocator auch einige Aufrufe durchzustehen ohne das er selber externe Hilfe bekommen kann und wenn es sicher ist dann muss er eben den Überschuss wieder großzügig auffüllen.
Eine andere Lösung wäre die Verwaltungsstrukturen im voraus zu allozieren (schließlich weiß man ja das man welche benötigt) bevor der Heap in einen unsicheren Zustand gebracht wird und dann könnten sich die verschiedenen Allocatoren gegenseitig beliebig verschachtelt aufrufen.
Und es gibt sicher noch ne Menge anderer Wege dieses Problem zu lösen.


Grüße
Erik
« Letzte Änderung: 18. October 2010, 15:34 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 #117 am: 18. October 2010, 16:13 »
Zitat von: erik
Irgendetwas scheinst Du anders zu machen.
Ja definitiv  :-D

Zitat von: erik
Eine andere Lösung wäre die Verwaltungsstrukturen im voraus zu allozieren (schließlich weiß man ja das man welche benötigt) bevor der Heap in einen unsicheren Zustand gebracht wird und dann könnten sich die verschiedenen Allocatoren gegenseitig beliebig verschachtelt aufrufen.
Das war meine erste Lösung die leider die Anzahl der CPUs nicht in betracht gezogen hatte und daher ab einer bestimmten Anzahl auch nicht mehr funktioniert hat.

Ich versuche schon die ganze Zeit meine jetzige Lösung so zu gestalten, das ich den Lock irgendwie ändern könnte.
Allerdings bin ich so langsam an einem Punkt angekommen wo ich nicht mehr glaube dass das möglich ist :( Habe nämlich gerade festgestellt, das mein SlabAllocator Memory leakt und um das Leak zu schließen, müsste ich die Ints ausmachen und meine vmmAlloc() aufrufen welche ja die vmmMap() aufruft und das auch irgendwann zu einem Problem wird :(

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #118 am: 18. October 2010, 16:33 »
Hallo,


also hast Du doch ein Design-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 #119 am: 18. October 2010, 16:51 »
@erik

Siehe anderer Thread. Ich habe eventuell eine Möglichkeit gefunden mein Design, mal wieder, zu fixen ;)

 

Einloggen