AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Wie ist die Windows API Funktion EnterCriticalSection implementiert?
Thema durchsuchen
Ansicht
Themen-Optionen

Wie ist die Windows API Funktion EnterCriticalSection implementiert?

Ein Thema von QuickAndDirty · begonnen am 11. Okt 2012 · letzter Beitrag vom 15. Okt 2012
Antwort Antwort
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#1

Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 11. Okt 2012, 11:05
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?
Andreas
Monads? Wtf are Monads?

Geändert von QuickAndDirty (11. Okt 2012 um 12:09 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 11. Okt 2012, 12:51
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.
$2B or not $2B

Geändert von himitsu (11. Okt 2012 um 12:57 Uhr)
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#3

AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 11. Okt 2012, 13:02
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:
http://wuqingjun.wordpress.com/2010/...-in-user-mode/

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 http://www.codeproject.com/Articles/...-Kernel-Object )

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...
Andreas
Monads? Wtf are Monads?

Geändert von QuickAndDirty (11. Okt 2012 um 13:17 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 11. Okt 2012, 13:16
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:
while not Terminated do begin
  CS.Enter;
  try
    Sleep(100);
  finally
    CS.Leave;
  end;
end;
und starte ihn ein paar Mal.
$2B or not $2B
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#5

AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 11. Okt 2012, 13:18
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:
while not Terminated do begin
  CS.Enter;
  try
    Sleep(100);
  finally
    CS.Leave;
  end;
end;
und starte ihn ein paar Mal.
Ich benutze TCriticalSection...aber ich wollte wissen wie die das machen... jetzt bin ich aber überzeugt !!!
Andreas
Monads? Wtf are Monads?
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#6

AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 11. Okt 2012, 15:06
Arbeite an einer Anwendung mit möglicherweise hunderten von Threads, und die soll was beschleunigen, also sollte sie nicht die Prozessorzeit aufsaugen.
Je nachdem, worauf der Thread warten muss, ist neben der CriticalSection bei massiv parallelen Systemen auch immer mehr IOCP im Einsatz - hunderte oder tausende Threads sind damit "verlustlos" möglich. IOCP ist nicht nur auf Netzwerk / Socketprogrammierung beschränkt:

I/O completion port's advantages and disadvantages

Zitat:
I/O completion ports are awesome. There's no better word to describe them. If anything in Windows was done right, it's completion ports.

You can create some number of threads (does not really matter how many) and make them all block on one completion port until an event (either one you post manually, or an event from a timer or asynchronous I/O, or whatever) arrives. Then the completion port will wake one thread to handle the event, up to the limit that you specified. If you didn't specify anything, it will assume "up to number of CPU cores", which is really nice.
-> man kann eine praktisch unbegrenzte Anzahl Threads durch einen completion port blockieren lassen, bis ein Event eintrifft (entweder ein selbsterzeugtes oder ein Timer-Event oder ein asynchrones I/O Event). Dann wird der Completion Port einen Thread aufwecken, oder mehr (Vorgabe: so viele wie es CPU Kerne gibt).

(Es gibt IOCP API Implementierungen auch für Delphi als open source).

Is there a I/O completion port based component for Delphi?
Michael Justin
habarisoft.com
  Mit Zitat antworten Zitat
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
Benutzerbild von dummzeuch
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
1.623 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 13. Okt 2012, 17:15
Eventuell hilfreich:

http://delphitools.info/2011/11/30/f...iticalsection/

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.

https://svn.code.sf.net/p/dzlib/code...calSection.pas
Thomas Mueller
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.944 Beiträge
 
Delphi 12 Athens
 
#9

AW: Wie ist die Windows API Funktion EnterCriticalSection implementiert?

  Alt 15. Okt 2012, 15:53
Eventuell hilfreich:

http://delphitools.info/2011/11/30/f...iticalsection/

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.

https://svn.code.sf.net/p/dzlib/code...calSection.pas

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?
Andreas
Monads? Wtf are Monads?
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:03 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz