説明するシナリオ(メモリからレジスタへの読み取り、レジスタの更新、メモリへの書き込み、およびこれらの操作のいずれかの間でコンテキストスイッチが発生する)で実行するリスクは、他のコンテキストで行われた更新を失う可能性があることです。
例えば:
main context:
read i (=10) from memory to register R1
add 5 to R1
<interrupt. Switch to interrupt context>
read i (=10) from memory to register R1
add 10 to R1
write R1 to i in memory (i = 20)
<end of interrupt. Back to main context>
write R1 to i in memory (i = 15)
ご覧のとおり、割り込みからの更新は失われています。
タイプがメモリに書き込むために複数の操作を必要とし、書き込み操作の途中で割り込みが発生した場合、さらに大きな問題が発生します。
例えば:
main context:
read first half of i (=10) from memory to register R1
read second half of i (=10) from memory to register R2
add 5 to R1/R2 pair
write R1 to first half of i in memory
<interrupt. Switch to interrupt context>
read first half of i (= ??) from memory to register R1
read second half of i (= ??) from memory to register R2
add 10 to R1/R2 pair
write R1 to first half of i in memory
write R2 to second half of i in memory
<end of interrupt. Back to main context>
write R2 to second half of i in memory
ここでは、私が最終的にどのような値になるかはわかりません。
sig_atomic_t
を使用すると、タイプがアトミックな読み取り/書き込み操作を使用することが保証されているため、この2番目の問題は発生しません。