UNIX Portable Atomic Operations

Lesezeit: 4 Minuten

Gibt es in C einen (POSIX-)portablen Weg für atomare Variablenoperationen ähnlich einem portablen Threading mit pthread?

Atomare Operationen sind Operationen wie “increment and get”, die atomar ausgeführt werden, was bedeutet, dass kein Kontextwechsel die Operation stören kann. Im Linux-Kernel-Raum müssen wir atomar_t Typ, in Java haben wir die java.util.concurrent.atomic Paket.

Unter Linux bietet die Datei atomic.h atomare Operationen, aber das Include ist plattformabhängig, z #include <asm-x86_64/atomic.h> und es ist auf ähnliche Weise unter Mac OS X nicht verfügbar.

Benutzer-Avatar
RubenLaguna

Ab C11 gibt es eine optionale Atombibliothek die atomare Operationen bereitstellt. Dies ist auf jede Plattform portierbar, die einen C11-Compiler (wie gcc-4.9) mit dieser optionalen Funktion hat.

Das Vorhandensein des Atoms kann mit überprüft werden __STDC_NO_ATOMICS__und das Vorhandensein von <stdatomic.h>

atomar.c

#include <stdio.h>
#include <stdlib.h>
#ifndef __STDC_NO_ATOMICS__
#include <stdatomic.h>
#endif

int main(int argc, char**argv) {
    _Atomic int a;
    atomic_init(&a, 42);
    atomic_store(&a, 5);
    int b = atomic_load(&a);
    printf("b = %i\n", b);

    return EXIT_SUCCESS;
}

Compiler-Aufrufe

clang -std=c11 atomic.c
gcc -std=c11 atomic.c

Für alle, die in Zukunft darauf stoßen, sind C11-Atomics der beste Weg, dies jetzt zu tun – ich glaube, sie werden in GCC 4.9 enthalten sein.

  • Können Sie das erweitern?

    – GraphicsMuncher

    25. November 2013 um 20:30 Uhr

  • Beispiel für minimal lauffähige C11-Atomics + -Threads: stackoverflow.com/questions/1130018/…

    – Ciro Santilli OurBigBook.com

    13. Februar 2019 um 22:08 Uhr

Da Sie nach OS X gefragt haben:

(und da Cross-Plattformity in diesem Thread angesprochen wurde.)

OS X hat Funktionen OSAtomicAdd32() und Freunde. Sie sind in “/usr/include/libkern/OSAtomic.h” deklariert. Sehen Der Threading-ProgrammierleitfadenAbschnitt “Verwendung atomarer Operationen”.

Und für Windows gibt es InterlockedIncrement() und Freunde (siehe MSDN).

Zusammen mit den gcc builtins __sync_fetch_and_add() and friends (wurde oben verlinkt), sollten Sie für jede Haupt-Desktop-Plattform etwas haben.

Bitte beachten Sie, dass ich sie selbst noch nicht verwendet habe, dies aber möglicherweise in den nächsten Tagen tun werde.

Nein, POSIX spezifiziert nicht irgendein portable lock-freie/atomare Operationen. Deshalb haben sie pthreads.

Sie müssen entweder nicht standardmäßige Methoden verwenden oder sich aus Gründen der Portabilität an ptrheads halten.

Benutzer-Avatar
Ciro Santilli OurBigBook.com

C11 Atomics minimal lauffähiges Beispiel

Mit der Hinzufügung von Threads in glibc 2.28 können wir sowohl Atomic als auch Threading in reinem C11 durchführen.

Beispiel aus: https://en.cppreference.com/w/c/language/atomic

Haupt c

#include <stdio.h>
#include <threads.h>
#include <stdatomic.h>

atomic_int acnt;
int cnt;

int f(void* thr_data)
{
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
        // for this example, relaxed memory order is sufficient, e.g.
        // atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed);
    }
    return 0;
}

int main(void)
{
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);

    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

Kompilieren und ausführen:

gcc -std=c11 main.c -pthread
./a.out

Mögliche Ausgabe:

The atomic counter is 10000
The non-atomic counter is 8644

Der nicht-atomare Zähler ist sehr wahrscheinlich kleiner als der atomare, da der Zugriff über Threads hinweg auf die nicht-atomare Variable sehr schnell erfolgt.

Ein pthreads-Beispiel finden Sie unter: How do I start threads in plain C?

Getestet in Ubuntu 18.04 (glibc 2.27) durch Kompilieren von glibc aus der Quelle: Mehrere glibc-Bibliotheken auf einem einzelnen Host Ubuntu 18.10 hat glibc 2.28, also sollten die Dinge dort einfach funktionieren.

  • Aber für den Fall, dass wir bei glibc 2.27 bleiben, würde stdatomic funktionieren pthreads?

    – Irgendein Name

    8. April 2019 um 18:52 Uhr

  • glibc 2.28 wird mit Ubuntu 18.10 oder 19.04 geliefert

    – junghm

    21. Mai 2019 um 14:56 Uhr

Benutzer-Avatar
Göz

AFAIK gibt es keine plattformübergreifenden Möglichkeiten, atomare Operationen durchzuführen. Vielleicht gibt es da draußen eine Bibliothek, aber ich weiß nichts davon. Es ist jedoch nicht besonders schwierig, Ihre eigenen zu rollen.

  • Aber für den Fall, dass wir bei glibc 2.27 bleiben, würde stdatomic funktionieren pthreads?

    – Irgendein Name

    8. April 2019 um 18:52 Uhr

  • glibc 2.28 wird mit Ubuntu 18.10 oder 19.04 geliefert

    – junghm

    21. Mai 2019 um 14:56 Uhr

Benutzer-Avatar
entspannen

Ich glaube nicht, dass es das gibt.

Eine Möglichkeit, dies zu lösen, sofern die Lizenzen dies natürlich zulassen, wäre, die relevanten Implementierungen pro Architektur beispielsweise aus dem Linux-Kernel-Space zu kopieren. Ich habe die Entwicklung dieser Primitiven nicht genau verfolgt, aber ich würde vermuten, dass sie tatsächlich Primitiven sind, dh nicht von anderen Diensten oder APIs im Kernel abhängen.

1382560cookie-checkUNIX Portable Atomic Operations

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy