2008-10-03 10 views
17

In einem Programm, ich arbeite, habe ich eine Menge von Code wie folgt:Thema sicheres atomare Operationen in gcc

pthread_mutex_lock(&frame->mutex); 
frame->variable = variable; 
pthread_mutex_unlock(&frame->mutex); 

Dies ist eindeutig eine Verschwendung von CPU-Zyklen, wenn die mittlere Anweisung mit nur ersetzt werden ein Atomladen. Ich weiß, dass gcc dazu in der Lage ist, aber ich konnte nicht viel Dokumentation über solche einfachen Thread-sicheren atomaren Operationen finden. Wie würde ich diesen Code mit einer atomaren Operation ersetzen?

(Ich weiß, dass einfache Geschäfte theoretisch Atom sein sollten, aber ich will nicht zu haben, zu hoffen, dass der Optimierer nicht ihre Atom-ness an einem gewissen Punkt in dem Prozess zu vermasseln wird.)

Klärung : Ich brauche sie nicht streng atomar zu sein; Diese Variablen werden nur für die Thread-Synchronisierung verwendet. Das heißt, Thread B liest den Wert, überprüft, ob es korrekt ist, und wenn es nicht korrekt ist, schläft es. Auch wenn Thread A den Wert aktualisiert und Thread B nicht aktualisiert, ist dies kein Problem, da dies bedeutet, dass Thread B nur dann schläft, wenn es nicht wirklich benötigt wird, und wenn es aufwacht, wird der Wert angezeigt sei richtig.

+0

Seit Kernel 2.6 kostet ein Mutex fast nichts mehr, wenn der Mutex frei ist. Anyway, "__sync_lock_test_and_set" (seit gcc 4.1) sollte den Trick machen, das ist nicht die einzige Funktion, die in diesem Fall verwendet werden könnte. – claf

+0

__atomic_store oder __atomic_store_n scheint besser geeignet zu sein. – claf

Antwort

16

Sie könnten die GCC-Dokumentation überprüfen. Für die aktuelle GCC-Version (4.3.2) wäre es Kapitel 5.47 Built-in functions for atomic memory access - für andere GCC-Versionen bitte überprüfen Sie Ihre Dokumente. Es sollte in Kapitel 5- Erweiterungen der C-Sprachfamilie sein.

Übrigens macht der C-Compiler absolut keine Garantie, dass einfache Speicheroperationen atomar sind. Sie können sich nicht auf diese Annahme verlassen. Damit ein Maschinenopcode atomar ausgeführt werden kann, benötigt er das LOCK-Präfix.

+2

Darüber hinaus werden diese integrierten Funktionen für atomaren Speicherzugriff auch von ICC unterstützt (für den Fall, dass Sie Compiler tragbar sein wollen). Für GCC denke ich, dass atomische Funktionen seit 4.1 unterstützt werden, also stellen Sie sicher, dass Sie #ifdef haben, um die gcc- oder icc-Version zu gewährleisten! – claf

+0

Also im Falle des gleichzeitigen Zugriffs ist __sync_add_and_fetch nicht zuverlässig? und wir müssen lock addx direkt mit assembly inlining verwenden? – Bionix1441

1

AFAIK, MOV-Anweisungen können nicht mit LOCK vorangestellt werden; Dies ist nur für RMW-Vorgänge zulässig. Aber wenn er tut einen einfachen Speicher verwenden, könnte er auch eine Speicherbarriere, die implizit mit Mutex ist, sowie mit Anweisungen, die LOCK ermöglichen.

4

Auf x86 und den meisten anderen Architekturen sind ausgerichtete 4-Byte-Lese- und Schreibvorgänge immer atomar. Der Optimierer kann Lese- und Schreibvorgänge in einem einzelnen Thread jedoch überspringen/neu anordnen.

Sie möchten den Compiler informieren, dass andere Threads diesen Speicherort möglicherweise berührt haben. (Ein Nebeneffekt von pthread_mutex_lock teilt dem Compiler mit, dass andere Threads möglicherweise einen Teil des Speichers berührt haben.) Möglicherweise wird volatile empfohlen, aber dies nicht in der C-Spezifikation, und GCC interpretiert nicht auf diese Weise.

asm("" : "=m" (variable)); 
frame->variable = variable; 

ist ein GCC-spezifische Mechanismus zu sagen, dass „variable zu, es neu zu laden geschrieben wurde“.

+9

Darüber hinaus kann der Cache des Prozessors Lese- und Schreibvorgänge in Bezug auf andere Prozessoren verbergen oder neu anordnen ... daher wird ein Speicherzaun benötigt. pthread_mutex_lock bietet dies, aber es ist sehr architekturabhängig. – ephemient

15

Bis zu einem gewissen Punkt wurden atomare Operationen in C direkt aus den Kernel-Quellen über den atomic.h-Header bereitgestellt.

Allerdings, Kernel-Header direkt in User-Space-Code verwendet wird, ist eine sehr schlechte Praxis, so dass die atomic.h Header-Datei wurde vor einiger Zeit entfernt. Stattdessen können wir jetzt die "GCC Atomic Builtins" verwenden, die ein weitaus besserer und zuverlässigerer Ansatz sind.

Es gibt eine very good explanation provided by Tudor Golubenco on his blog. Er bietet sogar einen Drop-In-Ersatz für die ursprüngliche atomic.h-Datei, falls Sie über einen Code verfügen, der sie benötigt.

Leider bin ich neu zu stackoverflow, also kann ich nur einen Link in meinen Kommentaren verwenden, also überprüfe Tudors Post und erlebe.

0

Wie ich sehen kann, verwenden Sie gnu-Plattform für die Entwicklung, also ist es sicher zu sagen, dass glic einen Datentyp int mit atomaren Fähigkeiten bietet, 'sig_atomic_t'. Dieser Ansatz kann also atomare Operationen auf Kernel-Ebenen sicherstellen. nicht gcc Ebenen.

Verwandte Themen