Der Cortex M3 unterstützt ein nützliches Operationspaar (das auch bei vielen anderen Computern üblich ist), das als "Load-Exclusive" (LDREX) und "Store-Exclusive" (STREX) bezeichnet wird. Konzeptionell führt die LDREX-Operation ein Laden durch und stellt auch eine spezielle Hardware ein, um zu beobachten, ob der Speicherort, der geladen wurde, möglicherweise von etwas anderem geschrieben wurde. Wenn Sie einen STREX für die vom letzten LDREX verwendete Adresse ausführen, wird diese Adresse nur geschrieben , wenn sie zuerst von nichts anderem geschrieben wurde . Der STREX-Befehl lädt ein Register mit 0, wenn der Speicher stattgefunden hat, oder 1, wenn er abgebrochen wurde.
Beachten Sie, dass STREX oft pessimistisch ist. Es gibt eine Vielzahl von Situationen, in denen möglicherweise entschieden wird, das Geschäft nicht durchzuführen, selbst wenn der betreffende Ort tatsächlich nicht berührt wurde. Beispielsweise führt ein Interrupt zwischen einem LDREX und STREX dazu, dass der STREX davon ausgeht, dass der beobachtete Ort möglicherweise getroffen wurde. Aus diesem Grund ist es normalerweise eine gute Idee, die Codemenge zwischen LDREX und STREX zu minimieren. Betrachten Sie beispielsweise Folgendes:
inline void safe_increment (uint32_t * addr)
{
uint32_t new_value;
tun
{
new_value = __ldrex (addr) + 1;
} while (__ strex (new_value, addr));
}}
was zu etwas kompiliert wie:
;; Angenommen, R0 enthält die betreffende Adresse. r1 verwüstet
lp:
ldrex r1, [r0]
füge r1, r1, # 1 hinzu
strex r1, r1, [r0]
cmp r1, # 0; Testen Sie, ob nicht Null ist
bne lp
.. Code geht weiter
Die überwiegende Mehrheit der Zeit, in der der Code ausgeführt wird, passiert nichts zwischen LDREX und STREX, um sie zu "stören", so dass der STREX ohne weiteres erfolgreich sein wird. Wenn jedoch unmittelbar nach dem LDREX- oder ADD-Befehl ein Interrupt auftritt, führt der STREX den Speicher nicht aus, sondern der Code liest den (möglicherweise aktualisierten) Wert von [r0] zurück und berechnet einen neuen inkrementierten Wert basierend darauf.
Die Verwendung von LDREX / STREX zum Erstellen von Operationen wie safe_increment ermöglicht es, nicht nur kritische Abschnitte zu verwalten, sondern in vielen Fällen auch die Notwendigkeit dieser zu vermeiden.