Cortex M3は、 "Load-Exclusive"(LDREX)および "Store-Exclusive"(STREX)と呼ばれる便利な操作ペア(他の多くのマシンでも一般的)をサポートしています。概念的には、LDREX操作はロードを実行し、ロードされた場所が他の何かによって書き込まれた可能性があるかどうかを監視するためにいくつかの特別なハードウェアを設定します。最後のLDREXで使用されたアドレスに対してSTREXを実行すると、他に何も最初に書き込まなかった場合にのみ、そのアドレスが書き込まれます。STREX命令は、ストアが行われた場合は0、中止された場合は1でレジスタをロードします。
STREXはしばしば悲観的であることに注意してください。問題の場所に実際には触れていなかったとしても、ストアを実行しないと決定するさまざまな状況があります。たとえば、LDREXとSTREXの間の割り込みにより、STREXは監視されている場所がヒットしたと想定します。このため、LDREXとSTREXの間のコード量を最小限に抑えることをお勧めします。たとえば、次のようなものを考えます。
インラインvoid safe_increment(uint32_t * addr)
{
uint32_t new_value;
行う
{
new_value = __ldrex(addr)+ 1;
} while(__ strex(new_value、addr));
}
これは次のようにコンパイルされます:
; R0が問題のアドレスを保持していると想定します。r1を破棄しました
lp:
ldrex r1、[r0]
r1、r1、#1を追加
strex r1、r1、[r0]
cmp r1、#0; ゼロ以外かどうかをテスト
bne lp
..コードが続く
コードが実行される時間の大部分は、LDREXとSTREXの間でそれらを「妨害」することは何も起こらないため、STREXはこれ以上問題なく成功します。ただし、LDREXまたはADD命令の直後に割り込みが発生した場合、STREXはストアを実行せず、コードは[r0]の(更新された可能性のある)値を読み取り、新しい増分値を計算します。それに基づいて。
LDREX / STREXを使用してsafe_incrementのような操作を作成すると、クリティカルセクションを管理できるだけでなく、多くの場合、それらの必要性を回避できます。