“非原子操作”是相对于“原子操作”而言。
先来个例子(读-改-写 操作):
以下展现的是一段C代码和等效的ARM7汇编代码
C代码:
/* The C code being compiled. */
155: PORTA |= 0x01;
汇编代码:
/* The assembly code produced. */
0x00000264 481C LDR R0,[PC,#0x0070] ; Obtain the address of PORTA
0x00000266 6801 LDR R1,[R0,#0x00] ; Read the value of PORTA into R1
0x00000268 2201 MOV R2,#0x01 ; Move the absolute constant 1 into R2
0x0000026A 4311 ORR R1,R2 ; OR R1 (PORTA) with R2 (constant 1)
0x0000026C 6001 STR R1,[R0,#0x00] ; Store the new value back to PORTA
这是一个” 非原子” 操作,因为完成整个操作需要不止一条指令,所以操作过程可能
被中断。考虑如下情形,两个任务都试图更新一个名为PORTA 的内存映射寄存器:
1.任务A 把PORTA 的值加载到寄存器中——整个流程的读操作。
2.在任务A 完成整个流程的改和写操作之前,被任务B 抢占。
3.任务B 完整的执行了对PORTA 的更新流程,然后进入阻塞态。
4.任务A 从被抢占处继续执行。其修改了一个 PORTA 的拷贝,这其实只是寄存
器在任务A 回写到PORTA 之前曾经保存过的值。
任务A 更新并回写了一个过期的PORTA 寄存器值。在任务A 获得拷贝与更新回
写之间,任务B 又修改了PORTA 的值。而之后任务A 对PORTA 的回写操作,覆盖
了任务B 对PORTA 进行的修改结果,效果上等同于破坏了PORTA 寄存器的值。
虽然是以一个外围设备寄存器为例,但是整个情形同样适用于全局变量的读- 改-写
操作
变量的非原子访问
更新结构体的多个成员变量,或是更新的变量其长度超过了架构体系的自然长度
( 比如,更新一个 16位机上的32位变量) 均是非原子操作的例子。如果这样的操作被中
断,将可能导致数据损坏或丢失。
阅读(924) | 评论(0) | 转发(0) |