![]() |
Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Hallo,
Es geht mir darum folgendes zu wissen. (Im zugehörigen MSDN Artikel habe ich nichts gefunden.) Wie ist die API Funktion EnterCriticalSection implementiert? A) Aktives Warten: Abfragen einer LockVariable in einer While schleife bis diese anzeigt, dass die Section zugänglich ist. Alle Threads die Warten verbrauchen CPU Zeit. B) Semaphore: Ein mit 1 initialisierte Semaphore. Die Semaphore wird durch EnterCriticalSection decremtiert, wird die Semaphore dadurch negativ wird der Thread blockiert und in eine Warteschleife abgelegt, ist die Semaphore >=0 führt der Thread den Codeabschnitt aus . Die Semaphore wird durch LeaveCtricalSection incremtiert. Wird sie dadurch <=0 kommt der nächste Thread aus der Warteschlange dran und wird aus der Warteschlange entfernt und aufgeweckt um den Code auszuführen. (Das bedeutet das ein Wert von 1 dazu führt das nichts weiter getan wird. sprich dann ist alles getan , fürs Erste.) Nur die Vorgänge um das Prüfen und ändern der Semaphore werden über "Aktives Warten" geblockt die blockierten Threads in der Warteschlange selbst verbrauchen dann keine CPU Zeit. C) Irgendwie anders? |
AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Die arbeiten irgendwie mit Sperrvariablen, einem Event, Listen (wer grade per Enter anfragt), Speerzählern und sonstwas,
aber wozu muß man das unbedingt wissen? Es funktioniert und ist sogar recht flott. Hat mich auch gewundert, dachte das wäre langsamer und hab eine Zeit lang was Selbestgebasteltes verwendet. Über eine Schleife, 'nem winzigen Sleep (wegen der 100%-CPU) und das LOCK (Assembler), bzw. über die Interlocked-Funktionen. Es ist auf jeden Fall nicht nur ein billiger Semaphore, denn das Sperren ist threadabhängig. Der Thread, welcher das gesperrt hat, kann es recursiv beliebig oft "sperren". (Ich hatte mal die Debuginfos der CS versucht auszuwerten, aber irgendwie scheint das intern nun anders zu funktionieren, als es die Debuginfos verraten. PS: Es gibt hier irgendwo einen Thread von mir, wo ich mal versuchte ein Timeout für das ENTER zu implementieren, indem ich mich z.B. an das angeblich vorhandene Event hängen wollte. |
AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Warum?
Arbeite an einer Anwendung mit möglicherweise hunderten von Threads, und die soll was beschleunigen, also sollte sie nicht die Prozessorzeit aufsaugen. Das mit dem Event habe ich jetzt auch gelesen. Und zwar hier: ![]() Ich weiß zwar nicht was es in Windows bedeutet ein "Event" zu erzeugen aber das der Thread im "Kernelmode" keine CPU Zeit verbraucht ist schon mal gut. Also wird es wohl so etwas ähnliches sein wie Variante B nur eben über ein "event" statt über ein Semaphore. Und mit "Kernelmode" statt "blocked". (EDIT: hier noch was gefunden ![]() Also kann ich mit CritcalSection ganz gut weiter arbeiten. Es ist schrecklich, ich habe mir gerade ALLES MÖGLICHE über Prozesse, Scheduling, Threads und Synchronisierung aus meinen alten Skripten noch mal durchgelesen... Interessant was man so alles schon mal gewusst hat... |
AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Wir verwenden auch nicht unbedingt wenige CS, aber von einer erwähnenswerten CPU-Auslastung, durch die CS, haben wir noch nichts bemerkt.
PS: TCriticalSection ist auch was Nettes. (kapselt die WinAPI-CS, hat kaum Overhead und vorallen in Bezug auf Multiplatform oder OOP ist es irgendwie schöner) Mach dir doch einfach mal einen Thread
Delphi-Quellcode:
und starte ihn ein paar Mal.
while not Terminated do begin
CS.Enter; try Sleep(100); finally CS.Leave; end; end; |
AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Zitat:
|
AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Zitat:
![]() ![]() Zitat:
(Es gibt IOCP API Implementierungen auch für Delphi als open source). ![]() |
AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Zitat:
![]() Die Funktion EnterCriticalSection wird von der kernel32.dll exportiert, also schauen wir doch im entsprechenden ![]() ![]() 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 ![]() ![]() 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 |
AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Eventuell hilfreich:
![]() Ich weiss nicht, ob das in neueren Delphi-Versionen gefixt ist, aber in Delphi 2007 existiert das Problem. Deshalb habe ich mir eine eigene von TCtiticalSection abgeleitete Klasse geschrieben. ![]() |
AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Zitat:
Das ist nicht deren ernst? Ich setze Delphi2007 ein. also muss ich mir jetzt 'ne "größere" CS bauen oder in großen Objekten TRTLCriticalsection nutzen? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:24 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz