2016-07-21 18 views
0

Ich habe zusammengestellt und analysiert, um den Montag Ausgang für:Atomspeicher. Strukturen

struct S{ 
public: 
    int a,b,c,d,e,f,g,h,i,j,k; 
}; 

int main() { 
    S s; 
    std::atomic<S> as; 
    as.store(s); 
    return 0; 
} 

ich sehen will, wie tut, ist es atomic store in der Tat umgesetzt. Es ist einfach, wenn es um ausgerichtete "kleine" Operanden geht. Aber jetzt haben wir einen breiteren Operanden, also ist es eine kompliziertere Situation.

In meiner anderen Frage (Atomicity on x86) sagte @ Peter Cordes:

Für breitere Operanden, wie atomar neue Daten in mehrere Einträge einer Struktur zu schreiben, können Sie es mit einem Schloss schützen müssen, die alle Zugriff darauf Respekt. (Unter Umständen können Sie x86 Sperre CMPXCHG16B mit einer Wiederholungsschleife verwenden, um ein Atom 16b Speicher zu tun. Beachten Sie, dass es keine Möglichkeit gibt es zu emulieren ohne Schloss.)

Ok, aber was bedeutet es genau ? Was bedeutet es zu sperren? Insbesondere, ich weiß, dass lock ist ein Präfix, das Atomizität von "vorfixierten" Anweisung gewährleistet. Insbesondere sagte @ Peter Cordes:

Unter Umständen können Sie auf x86-Sperre CMPXCHG16B mit einer Wiederholungsschleife zu tun, um eine Atom 16b speichern

Ich kann nicht verstehen, verwenden, wie es möglich ist, es zu halten Atom ? Ok, kann ich mir vorstellen, dass 16B Speicherbausteine ​​auf atomare Weise gespeichert werden können? Aber was ist mit den nächsten Iterationen?

Ich hoffe, dass meine Zweifel verständlich sind, weil ich ein Problem hatte, es auszudrücken.


Ich war das Debuggen über Programm und auf meinem Auge, ist die Magie hinter atomic_store. Ich nehme an, dass diese Funktion ausführt, was @Peter Cordes sagte. Wenn jemand will, kann ich einfügen hier zerlegt __atomic_store

+4

Sie haben gesagt, dass Sie den generierten Maschinencode analysiert haben. Nun, dann können Sie * uns * sagen, wie dies umgesetzt wird! –

+0

Ja, gehen Sie voran und fügen Sie die Demontage für __atomic_store ein. gcc erzeugt nur einen Aufruf mit den zu speichernden Daten, die als Referenz übergeben werden. –

+0

Fehle ich die Frage hier ?? –

Antwort

3

Sie können in der Lage sein zu verwenden x86-Sperre CMPXCHG16B mit einer Wiederholungsschleife zu tun, um einen atomaren 16B Speicher

Habe wirklich 16b sage ich statt 16B? Hoppla. Ich werde das als Teil einer größeren Bearbeitung beheben.

Damit können Sie einen 16B Atomspeicher tun, aber tun Sie es als ein Lesen-Modifizieren-Umschreiben, das wiederholt versucht, bis der Vergleichsteil erfolgreich ist. Sie können damit nicht mehr als 16B atomar speichern.


Was bedeutet es, zu sperren? Insbesondere weiß ich, dass die Sperre ein Präfix ist, das die Atomizität von "vorfixierten" Anweisungen sicherstellt.

Sperren wie in Spinlock/Mutex, nicht lock Präfix. Das Präfix lock funktioniert nur bei Lese-Modifizier-Schreib-Befehlen; Es gibt keine lock mov [mem], eax, um einen atomaren nicht ausgerichteten Speicher oder etwas zu tun. lock Ed-Buszyklen sind immer lesen-ändern-schreiben, wie von Intel in der Dokumentation für cmpxchg dokumentiert.Ein lock mov Speicher würde also auch einen Ladevorgang erzeugen, der eine andere Semantik hat, wenn Sie ihn für speicherprogrammierte E/A verwenden. (Ein Lesevorgang kann Nebenwirkungen auslösen).


Ich habe die Bestückungsleistung für ...

zusammengestellt und analysiert

Warum würden Sie diesen Code in main() setzen und speichern uninitialized Müll aus s in as? Abgesehen davon ist main in einigen Weisen besonders. Es ist immer besser, einfach eine Funktion zu schreiben, die ein arg übernimmt (oder nur ein globales betrifft). Und die atomic<s> muss global sein, keine lokale, die möglicherweise teilweise weg optimiert werden kann, wenn Sie sicher sein wollen, dass Sie sehen, was gcc "wirklich" macht.

#include <atomic> 
struct S{ int a,b,c,d,e,f,g,h,i,j,k; }; // or int a[11] 
std::atomic<S> as; 
void atomic_struct_store_zero() { 
    S s = { 0 };  // initializes all members to zero 
    as.store(s); 
} 

Diese compiles to ein Funktionsaufruf zu __atomic_store, src und dest Zeiger vorbei und eine Größe aus. Vermutlich verwendet es irgendwo eine Sperre, aber die Sperre ist nicht Teil von as. (sizeof(as) == sizeof(S) == 44).