在中断程序内 变量的加加,这种情况是否会出现BUG!

2019-12-27 19:02发布

先说明一下   a=a+1这条程序语句的执行步骤:
javascript:;

我在想这种情况:
如果执行到第一步,将a的值读到寄存器R中

执行完这一条后,来了个中断就是 a=a-1 !
等执行完 a=a-1 ,这时候重点来了!

我的CPU会回到 a=a+1 的第二步!
R寄存器里面是不知道 a 已经被改变了,所以他还是按照原先的值 加1!
然后在写回到 a !
  
这时候就会出现bug了!
这种情况大伙们有考虑过吗?  要怎么避免?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
84条回答
zhchmi10000
1楼-- · 2019-12-31 11:05
单核心直接关中断再操作,多核心有互斥访问汇编指令。
lixin91985
2楼-- · 2019-12-31 11:17
 精彩回答 2  元偷偷看……
redroof
3楼-- · 2019-12-31 13:13
本帖最后由 redroof 于 2016-12-3 09:27 编辑
myxiaonia 发表于 2016-12-3 07:29
确实可以有互斥访问,cortex的ldrex和strex就是专为解决这个问题提供的指令


这种独占写也是原子操作的一种(ex后缀是exclusive独占)。保证一个会成功,另一个会失败请自己重试。供操作系统来构造原子加减函数。
而且这主要是对多cpu使用的。旧arm没有多cpu的就没有这些指令,因为只要关中断再做正常的加减就行了。

楼主写常规的程序,基本没办法在每个地方直接手写这种汇编指令。你如果写正常的“变量++”,就得不到这样的效果。
如果编译器有自带的原子操作,你需要调用“原子操作加”这样的库函数,如果没有那么你得自己封装一个这样的原子操作。
总之,在应用层上,这种东西始终是被叫做“原子操作”的,windows上叫InterlockedXX操作,不叫“互斥”

takashiki
4楼-- · 2019-12-31 13:30
15802770321 发表于 2016-12-2 22:13
_interrupt void isr(void)
{
    你的代码;

如果有这样的编译器,那一定是大bug
myxiaonia
5楼-- · 2019-12-31 18:21
redroof 发表于 2016-12-3 09:12
这种互斥写也是原子操作的一种。保证一个会成功,另一个会失败请自己重试。供操作系统来构造原子加减函数 ...

其实是这样 互斥的范围更大  互斥操作包括原子操作  但是互斥操作却不一定是原子操作  原子操作是指不可打断的操作  例如自增指令  没有自增指令的情况下自增操作就没有原子操作办法 所以才有关中断这样的互斥方法
redroof
6楼-- · 2019-12-31 22:57
myxiaonia 发表于 2016-12-3 09:30
其实是这样 互斥的范围更大  互斥操作包括原子操作  但是互斥操作却不一定是原子操作  原子操作是指不可 ...

被打断后只要能知道,主动重试也是可以的。从语义上,这也是原子操作。不管你怎么实现,是锁总线还是打断重试。
对应用程序来说,你能调用的就是这一个完整操作。它的名字一般就叫原子操作。
当然你理论上可以用arm的独占写来保护完整的一个大函数,但正常来说不该这么干。一是麻烦,这样的汇编不好写,二是这样就不能移植到锁总线做原子操做的系统了。

一周热门 更多>