Atomare (C99) "struktur"
-
Hallo Leute ich habe eine Strucktur, bspw:
typedef struct { int x, int y;} Point;
nun möchte ich lesen und schreiben des Struktur Object atomar machen. In C++
könnte ich jastd::atomic<Point>
atomicPoint nehmen
oder in C11c_Atomic(Point)tomicPoint;
...Aber in C99 ? habe bissel recherciert je nach platform könnte ich ja locks ein baunen,was mir nich so gefällt.. dann bin ich auf inline ASM gestoßen. ungefäahr so:
void atomic_assign(Point *dest, Point src) { #if defined(__x86_64__) || defined(_M_X64) // x86_64 architecture __asm__ __volatile__ ( "lock; cmpxchg16b %0" : "=m" (*dest) : "m" (*dest), "d" (src.b), "a" (src.a) : "memory" ); #elif defined(__aarch64__) // ARM64 architecture __asm__ __volatile__ ( "ldxr x0, [%0]\n" "stxr w1, %1, [%0]\n" : "=m" (*dest) : "r" (&src), "m" (*dest) : "x0", "w1", "memory" ); #else #error "Unsupported architecture" #endif }
nun die frage ist das straight-forward oder gebastelt? wie löse ich das schön .. ja ich würde natürlich die Funktion
c void atomic_assign(Point *dest, Point src)
extern machen und je nach Plattform die entsprechend bauen/linken .Danke schonmal:)
-
@SoIntMan
Hast du dir mal die Concurrency support library angeschaut?
-
@Quiche-Lorraine sagte in Atomare C "struktur":
@SoIntMan
Hast du dir mal die Concurrency support library angeschaut?
https://en.cppreference.com/w/c/thread.htmlAber ist das nich C11 ?? ich bin in C99 unterwegs... (noch)
-
@SoIntMan
Sorry, mein Fehler. Zu schnell gelesen.Ich mag keine selbst gebastelten Atomic und Co. Datenstrukturen, da diese schwer zu testen sind. Ja sie funktionierten am Anfang immer gut, aber unter Volllast gibt es da schon so manche Überraschung. Man muss ja bedenken dass der Algo an jeder Stelle unterbrochen werden kann.
-
@Quiche-Lorraine sagte in Atomare (C99) "struktur":
Man muss ja bedenken dass der Algo an jeder Stelle unterbrochen werden kann.
aber wird genau das nicht mit dem inline asm befehl vermieden..? weil so wie ich gelesen habe wird das ja genau so unter haube bswp. bei std::atomic gelöst?
-
@SoIntMan
Es könnte für x86_64 passen, aber für ARM64 sehe ich da zwei Befehle. Das müsste man mal durchspielen.
-
Von welcher Art Software sprechen wir denn, muss das für verschiedene OS funktionieren?
-
@DocShoe sagte in Atomare (C99) "struktur":
Von welcher Art Software sprechen wir denn, muss das für verschiedene OS funktionieren?
ja, das war die Idee.. also arm und rtos ....
-
Noch Analog dazu :
habe ich 2 threads,
static int i=0;
void thread1() { while(1) { if (i == 1) { /* do anything */ i =0; } /* yield*/ } } void thread2() { i=1; }
und thread 2 "sporadisch" ein request absettze den dann thread 1 ausführt.. dafür ist eine atomare int notwendig oder? bin bald etwa zu verkopft
-
@SoIntMan sagte in Atomare (C99) "struktur":
dafür ist eine atomare int notwendig oder?
Dein Beispiel könnte vermutlich funktionieren, auch wenn es mehr ein Hack wäre.
Das Problem ist folgendes: Nehmen wir mal eine 8-Bit CPU an. Unter der Annahme dass das Setzen von
i
mehrere Assembler-Befehle benötigt, kann auch während des Setzens voni
der Ablauf unterbrochen werden. Wenn nun die Abfrageif (i == 1)
losläuft steht ini
ein inkonsistener Wert, welche je nach Abfrage heftige Fehler auslösen kann.In meinem Fall hatte ich auf einen kleinen Controller einen Zähler implementiert, welche die Anzahl der Millisekunden seit Start zurückliefert. Und alle paar Minuten sprang der Zähler zurück.
-
@Quiche-Lorraine sagte in Atomare (C99) "struktur":
Dein Beispiel könnte vermutlich funktionieren, auch wenn es mehr ein Hack wäre.
Das Problem ist folgendes: Nehmen wir mal eine 8-Bit CPU an. Unter der Annahme dass das Setzen von i mehrere Assembler-Befehle benötigt, kann auch während des Setzens von i der Ablauf unterbrochen werden. Wenn nun die Abfrage if (i == 1) losläuft steht in i ein inkonsistener Wert, welche je nach Abfrage heftige Fehler auslösen kann.
In meinem Fall hatte ich auf einen kleinen Controller einen Zähler implementiert, welche die Anzahl der Millisekunden seit Start zurückliefert. Und alle paar Minuten sprang der Zähler zurück.ok das habe ich verstanden, nehmen wir an ich mach ein int32_t draus ,bedeutet dass den "genrell" das auf eine 32bit/64bit hw da setzen und vergleichen nur ein asm befehlt braucht, oder kann ich davon nicht ausgehen?
Da ich eben C99 verwende, kann ich je nach compiller (hier GGC) ja sowas machen für ne zuweisung:
int atomic_exchange(int *ptr, int new_value) { return atomic_exchange(ptr, new_value); }
wäre das übertrieben? im prinzip habe ich nur "flags" die ich prüfen und ggf. zurücksetzen möchte.