我想知道它是否能够确保line
被自动执行,因为它可以由ISR和主要方面都可以执行。我工作的一个ARM9(LPC313x),并使用的RealView 4器(armcc)。这可以原子执行吗?
foo() {
..
stack_var = ++volatile_var; // line
..
}
我正在寻找像_atomic_
为C166,直接汇编代码等任何程序,我宁愿不要有禁用中断。
非常感谢。
我想知道它是否能够确保line
被自动执行,因为它可以由ISR和主要方面都可以执行。我工作的一个ARM9(LPC313x),并使用的RealView 4器(armcc)。这可以原子执行吗?
foo() {
..
stack_var = ++volatile_var; // line
..
}
我正在寻找像_atomic_
为C166,直接汇编代码等任何程序,我宁愿不要有禁用中断。
非常感谢。
从快看,C166 _atomic_
宏似乎利用了有效地掩蔽中断的指令指定数量的持续时间的指令。 在ARM架构中没有直接对应的东西。
当然你可以使用SWP指令(或工具链的RealView内在__swp)将围绕临界区的锁。另一个答案中提到的ldrex/strex在ARM架构版本5中不存在,其中包含ARM9处理器。分别为 http://infocenter.arm.com/help/topic/com.arm.doc.dui0491c/CJAHDCHB.html和http://infocenter.arm.com/help/topic/com.arm.doc.dui0489c/Chdbbbai.html。
对此的一种简单的锁机制(使用RealView工具链)将是:
{
/* Loop until lock acquired */
while (__swp(LOCKED, &lockvar) == LOCKED);
..
/* Critical section */
..
lockvar = UNLOCKED;
}
然而,这将导致ISR背景下死锁时,主线程持有锁。
我认为屏蔽操作周围的中断可能是最毛茸茸的解决方案,但如果您的Main上下文在用户模式下执行,则需要系统调用来实现。
不,我不认为你永远可以期待++volatile_var
是原子的,即使你没有分配。为此使用适当的原子基元。如果你的编译器没有提供这样的扩展,你可以在网上找到一个简短的内联汇编器。我认为汇编程序的指令是调用ldrex
和strex
来进行原子交换。
编辑:似乎在问题中要求的特定处理器类型没有实现这些指令。
编辑:下应该用gcc工作,另外一个编译器可能具有对__asm__
部分适应。
inline
size_t arm_ldrex(size_t volatile*ptr) {
size_t ret;
__asm__ volatile ("ldrex %0,[%1]\[email protected] load exclusive\n"
: "=&r" (ret)
: "r" (ptr)
: "cc", "memory"
);
return ret;
}
inline
_Bool arm_strex(size_t volatile*ptr, size_t val) {
size_t error;
__asm__ volatile ("strex %0,%1,[%2]\[email protected] store exclusive\n"
: "=&r" (error)
: "r" (val), "r" (ptr)
: "cc", "memory"
);
return !error;
}
inline
size_t atomic_add_fetch(size_t volatile *object, size_t operand) {
for (;;) {
size_t oldval = arm_ldrex(object);
size_t newval = oldval + operand;
if (arm_strex(object, newval)) return newval;
}
}
它是有益的,如果有人能抛出一些光,但不会以下被认为是原子? ADD r0,r0,#1如何使用ldrex/strex来增加一个值?我肯定错过了一些东西。 – TheLoneJoker 2011-03-24 15:39:26
@Jens,我对此有点新。能否请你点我的一些资源/文件,提供有关代码的详细信息__asm__挥发性( “LDREX%0,[%1] \ t @负荷独家\ n” : “= R”(RET) :“R “(ptr) :”cc“,”memory“ ); 我不是很清楚里面的东西是什么意思。 – TheLoneJoker 2011-03-24 16:27:51
@TheLoneJoker这就是所谓的“内联汇编”,插入到位的汇编程序指令,搜索该术语应该会为您找到更多信息。我在这里使用的变体是gcc,其他人可能也支持这样的扩展,但在实现时可能看起来不同。 – 2011-03-24 17:18:04
谢谢unixsmurf。 – JoeSlav 2011-03-26 11:43:05
您可以在旧ARM上将'swpb'与'swp'混合使用以获得多个/单个模式。即,**多个标志制定者**和**单个标志清晰**。最多可以使用四个“字节”或“**状态”。 – 2013-02-19 22:44:09