Einzelnen Beitrag anzeigen

Benutzerbild von JamesTKirk
JamesTKirk

Registriert seit: 9. Sep 2004
Ort: München
604 Beiträge
 
FreePascal / Lazarus
 
#7

AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 13. Okt 2012, 11:56
Hallo,
Es geht mir darum folgendes zu wissen. (Im zugehörigen MSDN Artikel habe ich nichts gefunden.)

Wie ist die API Funktion EnterCriticalSection implementiert?
Für solche Fragen finde ich immer den Quellcode von ReactOS sehr hilfreich. Also stürzen wir uns doch mal mitten rein:

Die Funktion EnterCriticalSection wird von der kernel32.dll exportiert, also schauen wir doch im entsprechenden Verzeichnis mal nach. Ok, seitdem die Entwickler da drin aufgeräumt haben findet man da nichts mehr so leicht, aber versuchen wir es einfach mal damit mit grep sämtliche Dateien zu durchsuchen. Dabei finden wir dann heraus, dass EnterCriticalSection gar nicht selbst in der kernel32.dll implementiert ist, sondern kurzerhand nach RtlEnterCriticalSection in der ntdll.dll geforwarded ist (sieht man, wenn man in der kernel32.spec Datei nach der Funktion sucht).

Also gehen wir zur ntdll. Hier ist jetzt leider eine kleine Gemeinheit, da die Funktion in der statisch gelinkten RTL Bibilothek, statt der ntdll selbst zu finden ist. Diese befindet sich hier. Dort sieht man dann auch relativ schnell eine critical.c-Datei, welche den Code für die kritischen Abschnitte enthält.

Schauen wir uns den Code also mal an. Zuerst wird versucht den LockCount der nach außen hin nicht sichtbaren CriticalSection Struktur per InterlockedIncrement zu erhöhen. War der Count vorher 0, so hat kein Thread die Section bisher betreten und der aktuelle Thread kann sie in Besitz nehmen. Andernfalls wird überprüft, falls der aktuelle Thread sie bereits betreten hat, dann muss natürlich nicht gewartet werden, damit ein Thread nicht sich selbst blockieren kann. Ansonsten hat ein anderer Thread den Lock und es muss mit Hilfe der privaten Funktion RtlpWaitForCriticalSection darauf gewartet werden, dass der aktuelle Thread drankommt.

Gehen wir nun also zu dieser Wartefunktion weiter. Im Anfangscode bis zur for-Schleife halten wir mal fest, dass es anscheinend einen Timeout für's Warten gibt (dessen Konfigurierbarkeit in ReactOS noch nicht voll implementiert ist). Innerhalb der for-Schleife wird dann auf ein Ereignis gewartet, das Teil der Struktur der CriticalSection ist. Schlägt der Timeout einmal an, so gibt es noch eine zweite Chance das Lock zu bekommen ansonsten wird eine Possible deadlock Exception ausgelöst. Das Ereignis wird übrigens innerhalb von RtlpUnWaitCriticalSection gesetzt, welche von RtlLeaveCriticalSection aufgerufen wird.

Man sieht also, dass die CriticalSection mit Hilfe eines Events gelöst ist. Durch NtWaitForSingleObject wird dann (hoffentlich) auch dafür gesorgt, dass nur einer der wartenden Threads dann die Chance bekommt den kritischen Bereich zu betreten. Aber das behalten wir uns für einen anderen Ausflug in der Welt der NT API vor

Gruß,
Sven
Sven
[Free Pascal Compiler Entwickler]
this post is printed on 100% recycled electrons

Geändert von JamesTKirk (13. Okt 2012 um 11:58 Uhr) Grund: BBCode gefixt -.-
  Mit Zitat antworten Zitat