2010-07-27 3 views
6

Ich weiß, wie LOCK verwenden, um Thread-sicher Wert erhöhen:Wie verwende ich das Präfix LOCK ASM, um einen Wert zu lesen?

lock inc  [J]; 

Aber wie lese ich [J] (oder einen beliebigen Wert) in einem Thread-sichere Art und Weise? Das Präfix LOCK kann nicht mit mov verwendet werden. Und wenn ich die folgenden:

xor eax, eax; 
    lock add eax, [J]; 
    mov [JC], eax; 

Es löst einen Fehler auf der Leitung 2.

+0

Was möchten Sie hier erreichen? – Iridium

+0

Alles, was ich tun möchte, ist [J] auf threadsichere Weise zu lesen. – IamIC

Antwort

9

Verwenden XADD oder MOV-Befehl statt Anweisung ADD! Siehe auch MFENCE, LFENCE und SFENCE Anweisungen!

EDIT: Sie können die LOCK-Anweisung nicht mit der Anweisung ADD verwenden, wenn der Quellenoperand ein Speicheroperand ist!

Von: „Intel® 64 und IA-32 ArchitecturesSoftware Anleitung für Entwickler“

Der LOCK-Präfix nur die folgenden Anweisungen vorangestellt werden kann und nur solche Formen der Befehle wo der Zieloperand ist ein Speicheroperand: ADD, ADC, AND, BTC, BTR, BTS, cmpxchg CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD und XCHG. Wenn das LOCK-Präfix mit einer dieser Anweisungen verwendet wird und der Quelloperand ein Speicheroperand ist, kann eine undefinierte Opcode-Ausnahme (#UD) generiert werden. Eine undefinierte Opcode-Ausnahme wird ebenfalls generiert, wenn das LOCK-Präfix mit einer beliebigen -Anweisung verwendet wird, die nicht in der obigen Liste enthalten ist. Die XCHG Anweisung immer behauptet das LOCK # Signal unabhängig von der Anwesenheit oder Abwesenheit des LOCK-Präfix

EDIT2: Form: "Intel® 64 und IA-32 ArchitecturesSoftware Anleitung für Entwickler, Volume3A"

8.1.1 Garantierte atomare Operationen. Der Intel486 Prozessor (und neuere Prozessoren da) garantiert, dass die folgenden grundlegenden Speicheroperationen wird immer atomar ausgeführt werden:

  • Lesen oder Schreiben eines Byte
  • Lesen oder Schreiben ein Wort auf einem ausgerichteten Schreib 16-Bit-Grenze
  • Lesen oder Schreiben eines Doppelwortes auf einem 32-Bit-Grenze

Der Pentium-Prozessor (a ausgerichtet Schreib nd neueren Prozessoren da) garantiert, dass das folgenden zusätzlichen Speicheroperationen immer atomar ausgeführt werden:

  • Lesen oder ein Quadwort auf einem 64-Bit-Grenze ausgerichtet Schreiben
  • 6-Bit-Zugriffe auf nicht gecachten Speicher Standorten, die den Prozessoren P6 Familie
    (und neueren Prozessoren seit)
    Garantie, dass die folgenden
    zusätzlichen Speicheroperationinnerhalb eines 32-Bit-
    Datenbus passen immer atomar ausgeführt werden:
  • Unaligned 16-, 32-, und 64-Bit-Zugriffe auf den gecachten Speicher, der

Greift auf cachefähigen Speicher
innerhalb einer Cache-Zeile passen, die sind über Split Busbreiten, Cache-Zeilen, und Seitengrenzen sind nicht garantiert durch das
Intel Core 2 Duo atomar sein, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, P6 Familie, Pentium und Intel486 Prozessoren. Die Intel Core 2 Duo, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon und P6 Familie Prozessoren bieten Bus-Steuersignale , die externe Speichersubsysteme ermöglichen Split-Zugriffe atomaren machen; jedoch nicht aligned Daten Zugriffe ernsthaft beeinträchtigen die Leistung von der Prozessor und sollte vermieden werden.

So zum Lesen prefare ich CMPXCHG Anweisung mit LOCK-Präfix zu verwenden, wie:

LOCK  CMPXCHG EAX, [J] 

Für Schriftfelter:

MOV [J], EAX 
SFENSE 

.

+0

Der Compiler weigert sich, Zeile 2 zu kompilieren. Ändern sogar zu: xadd dax, dword ptr J; funktioniert nicht. – IamIC

+0

Ja, der Quelloperand ist ein Speicheroperand! –

+0

Danke für die Klarstellung, warum es nicht kompilieren würde. So scheint es, dass ich entweder die Fencing-Anweisungen verwenden müsste, oder nur eine Momentaufnahme des Wertes machen, der, da es nur gelesen wird, kein Problem sein sollte - tool: mov eax, [ J]; mov [JSnapshot], eax; – IamIC

Verwandte Themen