2010-07-28 4 views
5

Ich weiß, wie man einen Wert in x86 ASM atomar schreibt. Aber wie lese ich eins? Das Präfix LOCK kann nicht mit mov verwendet werden.Wie kann ich einen Wert in x86 ASM atomar lesen?

Wert zu erhöhen, ich tue:

lock inc dword ptr Counter 

Wie kann ich Zähler in einem Thread-sichere Art und Weise zu lesen?

Antwort

4

Ich bin kein Assembly-Experte, aber Word-Größe (auf x86, 32-Bit) Lese-/Schreibvorgänge sollten bereits atomar sein.

Der Grund, warum Sie das Inkrement sperren müssen, ist, weil das sowohl ein Lesen als auch ein Schreiben ist.

+0

Ich denke, du hast Recht. Das macht Sinn. Vielen Dank. – IamIC

+0

Vergiss nicht, eine Antwort zu akzeptieren, wenn es dir geholfen hat;) –

+4

Nicht immer! Wenn die Speicheradresse im Cache ist, die eine zweite CPU in einer Mehrprozessoreinheit verwendet, ist das Lesen nicht garantiert atomar. Verwenden Sie also "LOCK CMPXCHG EAX, [var]", die zuerst den Speichercache sperren. –

1

Für ein einfaches Lesen geht es hauptsächlich um die Ausrichtung. Der einfachste Weg zur Sicherstellung des atomaren Lesens besteht darin, immer eine "natürliche" Ausrichtung zu verwenden, d. H. Die Ausrichtung ist mindestens so groß wie die Größe des Objekts (z. B. 32-Bit-Element ist 32-Bit-ausgerichtet).

Fehlausrichtungen sind nicht unbedingt atomar. Für ein extremes Beispiel sollten Sie einen 32-Bit-Wert an einer ungeraden Adresse lesen, wo das erste Byte in einer Cache-Zeile ist und die anderen drei Byte in einer anderen Cache-Zeile sind. In einem solchen Fall ist ein atomares Lesen im Wesentlichen unmöglich.

Da (zumindest die meisten) Prozessoren einen 64-Bit breiten Speicherbus verwenden, ist das größte Element, das hoffentlich atomar gelesen werden kann, 64 Bit.

5

Wie ich Ihnen in this Post erklären:

Greift zu zwischenspeicherbar Speicher, der Spaltung zwischen Busbreiten, Cache-Zeilen sind, und Seitengrenzen nicht garantiert werden von der Intel Core 2 Atom sein Duo, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, P6-Familie, Pentium und Intel486-Prozessoren. Der Intel Core 2 Duo, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon und P6 Familie Prozessoren bieten Bussteuersignale die externen Speichersubsystemen erlauben Split greift Atom zu machen; jedoch nicht aligned Daten Zugriffe ernsthaft beeinträchtigen die Leistung von der Prozessor und sollte vermieden werden.

So verwenden:

LOCK  CMPXCHG EAX, [J] 

LOCK cmpxchg ersten Zaun Cache-Speicher und als die EAX mit Zielwert vergleichen, wenn nicht Zielwert das Ergebnis in EAX equ dann Zielwert ist.

EDIT: Links zu:

Intel® 64 and IA-32 Architectures Software Developer’s Manuals

In Volume 3A: System Programming Guide Prüfabschnitt 8.1.1

Prüfen Sie auch: Optimization Reference Manual section: CHAPTER 7 OPTIMIZING CACHE USAGE

+0

Das wird nicht kompiliert, da [J] ein Speicherzeiger ist. Es muss ein Registerwert sein. Das ist der Catch-22, ich komme nicht herum. – IamIC

+1

Ich sehe aus Ihrem anderen Beitrag, dass dies eigentlich kein Problem ist, solange der Wert ausgerichtet ist und mit der Busbreite der CPU. – IamIC

+0

@IamIC: Nicht die Busbreite, genau. Der kleinste gemeinsame Nenner bei den Garantien von Intel und AMD ist, dass 'mov' load/store atomar ist [wenn es keine 8-Byte-Grenze überschreitet (für zwischengespeicherte Zugriffe).] (Https://stackoverflow.com/a/36685056/224132) Oder für uncached, wenn es ausgerichtet ist oder ein 16-Bit-Zugriff, der keine dword-Grenze überschreitet. Auch ist '[J]' einfach ein absoluter oder (in x86-64) ein RIP-relativer Adressierungsmodus. Es ist keine doppelte Indirektion. Es fügt sich gut zusammen. In der MASM-Syntax wird häufig das '[]' weggelassen, sie sind jedoch in MASM optional und in NASM erforderlich. –

1

Es ist interessant, die anderen Antworten zu lesen. Ich denke @GJ ist wahrscheinlich auf das Geld.

Seit vielen Jahren war es immer wahr, dass 32-Bit lesen und schreiben atomar war. Erst in den letzten Jahren ist dies mit dem wirklich aggressiven Caching nicht mehr gewährleistet.

Ich denke, deshalb bevorzuge ich C++, Java oder so etwas zwischen mir und dem Maschinencode. Heutzutage ist der Maschinencode zu komplex, um zuverlässig zu schreiben (es sei denn, Sie tun es viel, um Ihre Fähigkeiten scharf zu halten). Glücklicherweise sind die heutigen optimierenden Compiler so gut, dass Sie selten die Leistung eines handoptimierten Assemblers benötigen.

+0

C++ garantiert nichts über die Speichersemantik oberhalb dessen, was die CPU tut, noch wird Java ohne volatile. –

+0

C++ kann atomare Zugriffe für atomare Typen (C++ 11 Zeug) garantieren, ebenso wie C (C11). –

Verwandte Themen