Comment effectuer des opérations atomiques sur Linux qui fonctionnent sur des systèmes x86, arm, GCC et de la cpi?
Tous les OS Modernes offre aujourd'hui quelques opérations atomiques:
- Windows a
Interlocked*
API - FreeBSD a
<machine/atomic.h>
- Solaris a
<atomic.h>
- Mac OS X a
<libkern/OSAtomic.h>
Quelque chose comme ça pour Linux?
- J'en ai besoin pour travailler sur la plupart des Linux pris en charge les plates-formes, y compris: x86, x86_64 et bras.
- J'en ai besoin pour travailler sur au moins GCC et Intel Compilateur.
- Je n'ai pas besoin d'utiliser la 3ème par la bibliothèque comme glib ou qt.
- J'en ai besoin pour travailler en C++ (C pas obligatoire).
Questions:
- GCC atomique les builtins
__sync_*
ne sont pas pris en charge sur toutes les plateformes (BRAS) et ne sont pas pris en charge par le compilateur Intel. - Autant que je sache
<asm/atomic.h>
ne doit pas être utilisé dans l'espace utilisateur et je n'ai pas réussi du tout. Aussi, je ne sais pas si cela pourrait fonctionner avec les processeurs Intel compilateur.
Des suggestions?
Je sais qu'il y a de nombreuses questions, mais certains d'entre eux du point de __sync*
qui n'est pas possible pour moi (BRAS) et un point de asm/atomic.h
.
Peut-être il ya une ligne bibliothèque de l'assemblée qui fait cela pour GCC (ICC soutient gcc assemblée)?
Edit:
Il y a une solution très partielle pour les opérations d'ajout seulement (permet de mettre en œuvre atomique en vente libre, mais pas de blocage de libre-structures qui nécessitent des CAS):
Si vous utilisez libstc++
(Intel Compilateur utilise libstdc++
) alors vous pouvez utiliser __gnu_cxx::__exchange_and_add
que défini dans <ext/atomicity.h>
ou <bits/atomicity.h>
. Dépend de la version de compilateur.
Cependant, je voudrais encore voir quelque chose qui prend en charge le TAS.
- armv5, armv6 ou armv7?
- Les bonnes questions. Autant que je sache ll/sc sont uniquement disponibles sur arm6 et ci-dessus? Donc, il serait sans doute pertinent que pour les arm6 et au-dessus
- Donc, nous allons préciser qu' - GCC sont intrinsèques pas pris en charge sur les BRAS à cause de la GCC de la chaîne d'insuffisances ou en raison du BRAS de défauts? Pouvez-vous confirmer que vous ne pouvez pas les utiliser avec GCC pour les BRAS qui prend en charge les atomique ops?
- BRAS de lacunes. Certains connexes de soutien instructions: ARM v5: SWP(atomique swap de la taille de mot et la taille en octets) ARM v6: LDREX/STREX(32 bits enchaîné éventuellement atomique load/store)+SWP ARM v7: LDREX/STREX(de même que le v6, mais avec des options de taille pour les 8/16bits) V5 ne peut pas faire atomique incrément sans désactiver les interruptions, de l'espace utilisateur ne peut pas faire. Cependant, ce qu'il peut faire est d'appeler le système d'exploitation à dire, une interruption logicielle, et ont le handle de la place.
- Similaire pour le C, mais ne nécessitant pas autant de portabilité: stackoverflow.com/questions/2353371/atomic-increment-fetch
Vous devez vous connecter pour publier un commentaire.
Projets sont à l'aide de ceci:
http://packages.debian.org/source/sid/libatomic-ops
Si vous voulez des opérations simples comme CAS, ne pouvez-vous pas tout simplement utiliser l'arc des implémentations spécifiques hors du noyau, et de faire de l'arche de contrôles dans l'espace utilisateur avec les autotools/cmake? Aussi loin que l'octroi de licences va, même si le noyau est en GPL, je pense qu'il est possible de soutenir que la assembly en ligne de ces opérations est fourni par Intel/AMD, pas que le noyau a une licence sur eux. Ils ont juste arriver à être dans une forme aisément accessible dans le source du noyau.
Normes récentes (depuis 2011) de C & C++ maintenant spécifier les opérations atomiques:
stdatomic.h
std::atomique
Quel que soit, votre plate-forme ou le compilateur ne peut pas soutenir de nouveaux en-têtes & caractéristiques.
Darn. J'allais suggérer la GCC primitives, puis vous avez dit qu'ils étaient hors de portée. 🙂
Dans ce cas, je ferais une
#ifdef
pour chaque architecture/compilateur combinaison que vous aimez et le code de l'asm inline. Et peut-être vérifier pour__GNUC__
ou d'une même macro et d'utiliser GCC primitives s'ils sont disponibles, parce qu'il se sent tellement plus droit à l'utilisation de ceux-ci. 🙂Vous allez avoir beaucoup de duplication et il peut être difficile de vérifier l'exactitude, mais cela semble être la façon dont beaucoup de projets à faire, et j'ai eu de bons résultats avec elle.
Certains pièges qui ont peu de moi dans le passé: lorsque vous utilisez GCC, n'oubliez pas les "
asm volatile
" et clobbers pour"memory"
et"cc"
, etc.asm volatile
pas être instable, bien que je soupçonne que le phénomène ne se limite pas seulement à l'assembly en ligne.Coup de pouce, qui a non intrusive de licence, et d'autres cadres offrent déjà un portable atomique compteurs -- tant qu'ils sont pris en charge sur la plate-forme cible.
Bibliothèques tierces sont bonnes pour nous. Et si, pour d'étranges raisons pour lesquelles votre entreprise ne vous interdit de les utiliser, vous pouvez toujours avoir un oeil à la façon de procéder (tant que le permis et des licences pour votre usage) pour mettre en œuvre ce que vous cherchez.
atomic_counters
fournir uniquement inc/dec opérations qui sont bien pour le comptage de référence, mais ils sont trop faibles. Si vous besoin de quelque chose comme atomique liste liée, où vous avez besoin d'opérations comme les CAS.Que j'ai fait récemment une mise en œuvre d'une telle chose et j'ai été confronté aux mêmes difficultés que vous. Ma solution a été de essentiellement les suivantes:
la fonction macro
quelque chose comme
cmpxch
avec__asm__
pour les autres architectures (ARM est un peu plus compliqué que cela). Juste le faire pour une taille possible, l'e.gsizeof(int)
.le dessus de cela un ou deux primitives
avec
inline
fonctionsIl existe un patch pour GCC ici à l'appui de BRAS des opérations atomiques. Ne sera pas vous aider sur Intel, mais vous pouvez examiner le code, il n'y a noyau récent, un soutien pour les anciens BRAS architectures, et de nouveaux ont les instructions intégré, donc vous devriez être en mesure de construire quelque chose qui fonctionne.
http://gcc.gnu.org/ml/gcc-patches/2011-07/msg00050.html
__sync*
est certainement (et a été) pris en charge par le compilateur Intel, car GCC a adopté ces build-ins à partir de là. Lisez le premier paragraphe de sur cette page. Voir aussi "Intel® Compilateur C++ pour Linux* Intrinsèques de Référence", page 198. C'est à partir de 2006 et décrit exactement ceux built-ins.Concernant le soutien de BRAS, pour les anciens Processeurs ARM: il ne peut pas être entièrement effectuée dans l'espace utilisateur, mais il peut être fait dans kernelspace (par la désactivation des interruptions au cours de l'opération), et je pense que j'ai lu quelque part qu'il est pris en charge pour un certain temps maintenant.
Selon ce bogue de PHP, daté 2011-10-08,
__sync_*
échoue seulement surDonc avec GCC > en 4.3 et 4.7 est l'actuel), vous ne devriez pas avoir un problème avec ARMv6 et les plus récents. Vous ne devriez avoir aucun problème avec ARMv5 soit en tant que de compiler pour Linux.
Sur Debian/Ubuntu recommander...
sudo apt-get install libatomic-ops-dev
exemples: http://www.hpl.hp.com/research/linux/atomic_ops/example.php4
GCC & ICC compatible.
par rapport à Intel Fil de Blocs de Construction (TBB), à l'aide atomique< T >, libatomic-ops-dev est plus de deux fois plus vite! (Intel compilateur)
Test sur Ubuntu i7 producteur-consommateur filetages de tuyauterie de 10 millions ints vers le bas d'un tampon en anneau de connexion à 0,5 sec., par opposition à 1,2 secondes pour TBB
Et facile à utiliser, par exemple,
volatils AO_t tête;
AO_fetch_and_add1(&tête);
Voir: kernel_user_helpers.txt ou d'entrée de bras.c et de regarder pour
__kuser_cmpxchg
. Comme on le voit dans les commentaires de l'autre BRAS versions de Linux,kuser_cmpxchg
Notes:
C'est pour une utilisation avec Linux avec ARMv3 à l'aide de la
swp
primitive. Vous devez avoir une très ancien BRAS de ne pas soutenir cette. Seulement un données abandonner ou interrompre peut provoquer le fait de tourner à l'échec, de sorte que le noyau des moniteurs pour cette adresse ~0xffff0fc0 et effectue un de l'espace utilisateurPC
fix-up lorsqu'un données abandonner ou un interrompre se produit. Tout utilisateur de l'espace des bibliothèques qui prennent en charge ARMv5 et inférieurs utiliser cette facilité.Par exemple, QtConcurrent utilise cette.