Opérations atomiques dans ARM
J'ai travaillé sur un système d'exploitation embarqué pour les BRAS, Cependant il y a quelques choses que je ne comprenais pas sur l'architecture même après se référant à ARMARM et source de linux.
Des opérations atomiques.
Bras BRAS dit de Charger et de Stocker des instructions atomiques et c'est l'exécution est garantie pour être complet avant de gestionnaire d'interruption s'exécute. Vérifié en regardant
arch/arm/include/asm/atomic.h :
#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
Cependant, le problème vient quand je veux manipuler cette valeur automatiquement à l'aide des instructions du processeur (atomic_inc, atomic_dec, atomic_cmpxchg etc..) dont l'utilisation LDREX et STREX pour ARMv7 (ma cible).
ARMARM ne dit rien sur les interruptions d'être bloqué dans cette section, donc je suppose une interruption peut se produire entre les LDREX et STREX. La chose qu'il ne mentionner sur le verrouillage de la mémoire de bus, qui je pense est uniquement utile pour les MP les systèmes où il peut y avoir plusieurs Processeurs en essayant d'accéder à un même endroit au même moment. Mais JUSQU' (et éventuellement en MP), Si une minuterie d'interruption (ou de l'IPI pour les SMP) feux dans cette petite fenêtre de LDREX et STREX, gestionnaire d'Exception exécute éventuellement des changements de contexte de processeur et retourne à la nouvelle tâche, mais le plus choquant vient maintenant, il exécute 'CLREX" et donc de supprimer toute verrou exclusif détenu par le thread précédent. Alors, comment mieux est d'utiliser LDREX et STREX de LDR et de STR pour l'atomicité sur un système ?
J'ai lu quelque chose à propos d'un verrou Exclusif moniteur, j'ai donc une possible théorie que lorsque le thread reprend et exécute le STREX, le système d'exploitation de surveiller les causes de cet appel à l'échec qui peut être détecté et la boucle peut être ré-exécuté à l'aide de la nouvelle valeur dans le processus (de la branche de retour à LDREX), Suis-je ici ?
source d'informationauteur sgupta
Vous devez vous connecter pour publier un commentaire.
Bon, j'ai la réponse à partir de leur site web.
Si un changement de contexte horaires un processus une fois le processus effectué une Charge Exclusive, mais avant qu'il effectue le Magasin Exclusif, le Magasin Exclusif retourne un résultat faussement négatif lorsque le processus reprend, et la mémoire n'est pas mis à jour. Cela n'affecte pas les fonctionnalités du programme, parce que le processus peut recommencer l'opération immédiatement.
L'idée derrière la charge liée/store-exclusif de paradigme, c'est que si si le magasin suit très bientôt après la charge, sans période d'opérations de mémoire, et si rien d'autre n'a touché l'emplacement, le magasin est probablement pour réussir, mais si quelque chose d'autre a touché l'emplacement du magasin est certains à l'échec. Il n'y a aucune garantie que les magasins ne seront pas parfois tomber en panne sans raison apparente; si le temps entre la charge et le magasin est maintenu à un minimum, cependant, et il n'y a pas d'accès mémoire entre eux, une boucle comme:
peuvent généralement être invoqué pour réussir dans un délai de quelques tentatives. Si le calcul de la nouvelle valeur basée sur l'ancienne valeur de certaines de calcul importante, il faut réécrire la boucle tant que:
Ce code va être relancé sa boucle principale en cas de modifications *dest, tandis que la nouvelle valeur est calculée, mais seulement la petite boucle devra être recommencée si l' __STREXW échoue pour une autre raison [qui, je l'espère pas trop probable, étant donné qu'il n'y aura qu'environ deux instructions entre l' __LDREXW et __ _ _ STREXW]
Addendum
Un exemple d'une situation où "calculer la nouvelle valeur basée sur l'ancien" pourrait être compliqué serait celui où les "valeurs" sont des références à une structure de données complexe. Le Code peut récupérer l'ancienne référence, et d'en tirer une nouvelle structure de données à partir de l'ancien, puis mise à jour de la référence. Ce modèle arrive beaucoup plus souvent au garbage collector de cadres que dans les "bare metal" de la programmation, mais il existe une variété de façons, il peut arriver, même lors de la programmation de métal nu. Normal malloc/calloc allocateurs ne sont généralement pas thread-safe/interruption sûr, mais allocateurs pour les structures de taille sont souvent. Si l'on a un "pool" d'une certaine puissance de deux nombre de structures de données (dites 255), on pourrait utiliser quelque chose comme:
Si il n'y va pas souvent être plusieurs threads/interruptions/quel que soit essayer de mettre à jour la même chose en même temps, cette approche devrait permettre des mises à jour à effectuer en toute sécurité. Si une priorité relations existent entre les choses qui peuvent vous essayez de mettre à jour l'élément de même, la plus grande priorité est la garantie de réussir sur sa première tentative, la priorité suivante la plus élevée on va réussir à toute tentative qui n'est pas préempté par la plus haute priorité, etc. Si l'on était en utilisant le verrouillage, la plus haute priorité de la tâche qui voulait effectuer la mise à jour devrait attendre la faible priorité de mise à jour à la fin; à l'aide de la CompareAndSwap paradigme, de la plus haute priorité de la tâche ne sera pas affectée par le taux le plus faible (mais fera en sorte que la partie inférieure avoir à faire le gaspillage de travail).